[grub] Update to kernel.org fedora-16 branch Add findiso command Add support for providing legacy graphics

Peter Jones pjones at fedoraproject.org
Wed Sep 28 23:32:23 UTC 2011


commit 61e5bc89cf7d58bd568b80eb4ebda0db99c598ec
Author: Peter Jones <pjones at redhat.com>
Date:   Thu Aug 25 10:13:50 2011 -0400

    Update to kernel.org fedora-16 branch
    Add findiso command
    Add support for providing legacy graphics rom support
    Fix locate_device_path
    Add support for finding the parent device in a device path
    Add mechanism for getting runtime pages
    Add support for the PCI and PCI root bridge IO protocols
    Merge -76 changes upstream.

 grub-0.97-128-drives-support.patch                 |   73 -
 grub-fedora-15.patch                               |46660 --------------------
 grub-fedora-16.patch                               | 5307 +--
 ...-stack.patch => grub-use-gnu-efi-callwrap.patch |    5 -
 grub.spec                                          |   17 +-
 5 files changed, 1193 insertions(+), 50869 deletions(-)
---
diff --git a/grub-fedora-16.patch b/grub-fedora-16.patch
index 0994ba4..03d2086 100644
--- a/grub-fedora-16.patch
+++ b/grub-fedora-16.patch
@@ -11,150 +11,147 @@ Using the command:
 
 git diff grub-0.97 fedora-16
 
- b/.gitignore                     |    8 
- b/AUTHORS                        |    2 
- b/ChangeLog                      |   48 
- b/INSTALL                        |    3 
- b/Makefile.am                    |    3 
- b/Makefile.in                    |  175 
- b/acinclude.m4                   |    4 
- b/aclocal.m4                     |  555 --
- b/config.h.in                    |    5 
- b/configure.in                   |  120 
- b/docs/.gitignore                |    3 
- b/docs/Makefile.am               |    9 
- b/docs/Makefile.in               |  260 -
- b/docs/grub-crypt.8              |   39 
- b/docs/grub-install.8            |    2 
- b/docs/grub.8                    |    2 
- b/docs/grub.info                 |  370 -
- b/docs/grub.texi                 |   82 
- b/docs/stamp-vti                 |    4 
- b/docs/version.texi              |    4 
- b/efi/.gitignore                 |    7 
- b/efi/Makefile.am                |   76 
- b/efi/byteswap.h                 |   37 
- b/efi/dhcp.h                     |  133 
- b/efi/efichainloader.c           |  265 +
- b/efi/eficon.c                   |  306 +
- b/efi/eficore.c                  |  231 +
- b/efi/efidisk.c                  |  785 ++++
- b/efi/efidp.c                    |  984 +++++
- b/efi/efigraph.c                 | 1467 +++++++
- b/efi/efimain.c                  |  129 
- b/efi/efimisc.c                  |  665 +++
- b/efi/efimm.c                    |  512 ++
- b/efi/efiserial.c                |  265 +
- b/efi/efitftp.c                  |  228 +
- b/efi/efiuga.c                   |  946 ++++
- b/efi/font_8x16.c                | 4638 +++++++++++++++++++++++
- b/efi/graphics.c                 |  568 ++
- b/efi/graphics.h                 |   79 
- b/efi/grub/.gitignore            |    1 
- b/efi/grub/efi/api.h             | 1471 +++++++
- b/efi/grub/efi/console_control.h |   59 
- b/efi/grub/efi/efi.h             |   79 
- b/efi/grub/efi/eficall.h         |  162 
- b/efi/grub/efi/misc.h            |   58 
- b/efi/grub/efi/time.h            |   31 
- b/efi/grub/i386/linux.h          |  226 +
- b/efi/grub/i386/types.h          |   32 
- b/efi/grub/misc.h                |   71 
- b/efi/grub/symbol.h              |   34 
- b/efi/grub/types.h               |  158 
- b/efi/grub/x86_64/linux.h        |  228 +
- b/efi/grub/x86_64/types.h        |   32 
- b/efi/ia32/callwrap.c            |  131 
- b/efi/ia32/loader/bin_to_h.c     |   29 
- b/efi/ia32/loader/linux.c        |  648 +++
- b/efi/ia32/loader/switch.S       |  118 
- b/efi/ia32/loader/switch.h       |   19 
- b/efi/ia32/reloc.c               |   79 
- b/efi/ia32/setjmp.S              |   86 
- b/efi/pxe.c                      |  444 ++
- b/efi/pxe.h                      |  237 +
- b/efi/ugadebug.h                 |  201 +
- b/efi/x86_64/callwrap.c          |  395 ++
- b/efi/x86_64/crt0-efi.S          |   63 
- b/efi/x86_64/elf_efi.lds         |   58 
- b/efi/x86_64/loader/Makefile     |   20 
- b/efi/x86_64/loader/bin_to_h.c   |   29 
- b/efi/x86_64/loader/linux.c      |  588 +++
- b/efi/x86_64/loader/switch.S     |   92 
- b/efi/x86_64/loader/switch.h     |   25 
- b/efi/x86_64/reloc.c             |   79 
- b/efi/x86_64/setjmp.S            |   56 
- b/efi/xpm.c                      |  231 +
- b/efi/xpm.h                      |   36 
- b/grub.spec                      |  438 ++
- b/grub/.gitignore                |    2 
- b/grub/Makefile.am               |    4 
- b/grub/Makefile.in               |  117 
- b/grub/asmstub.c                 |  194 
- b/grub/efitftp.c                 |   34 
- b/grub/main.c                    |    2 
- b/lib/.gitignore                 |    2 
- b/lib/Makefile.in                |  111 
- b/lib/device.c                   |  360 +
- b/netboot/.gitignore             |    2 
- b/netboot/Makefile.in            |  359 -
- b/netboot/etherboot.h            |   34 
- b/netboot/main.c                 |    6 
- b/netboot/misc.c                 |   58 
- b/netboot/osdep.h                |   24 
- b/stage1/.gitignore              |    2 
- b/stage1/Makefile.am             |   15 
- b/stage1/Makefile.in             |  169 
- b/stage1/stage1.S                |    4 
- b/stage2/.gitignore              |    5 
- b/stage2/Makefile.am             |  100 
- b/stage2/Makefile.in             | 1729 +++++---
- b/stage2/asm.S                   |  284 +
- b/stage2/boot.c                  |  114 
- b/stage2/btrfs.h                 | 1414 +++++++
- b/stage2/builtins.c              | 1325 ++++--
- b/stage2/char_io.c               |  609 ++-
- b/stage2/cmdline.c               |   19 
- b/stage2/common.c                |   16 
- b/stage2/disk_io.c               |  201 -
- b/stage2/efistubs.c              |    7 
- b/stage2/efistubs.h              |    8 
- b/stage2/fat.h                   |    2 
- b/stage2/filesys.h               |   30 
- b/stage2/fsys_btrfs.c            | 1815 +++++++++
- b/stage2/fsys_ext2fs.c           |  394 +-
- b/stage2/fsys_fat.c              |   41 
- b/stage2/fsys_iso9660.c          |    6 
- b/stage2/fsys_jfs.c              |   12 
- b/stage2/fsys_minix.c            |   10 
- b/stage2/fsys_reiserfs.c         |   44 
- b/stage2/fsys_vstafs.c           |   28 
- b/stage2/fsys_xfs.c              |   22 
- b/stage2/gpt.h                   |   69 
- b/stage2/graphics.c              |  573 ++
- b/stage2/graphics.h              |   42 
- b/stage2/gunzip.c                |   15 
- b/stage2/iso9660.h               |    4 
- b/stage2/mb_info.h               |    4 
- b/stage2/pc_slice.h              |   51 
- b/stage2/serial.c                |    4 
- b/stage2/sha256crypt.c           |  723 +++
- b/stage2/sha512crypt.c           |  795 ++++
- b/stage2/shared.h                |  125 
- b/stage2/smp-imps.h              |    1 
- b/stage2/stage1_5.c              |    3 
- b/stage2/stage2.c                |  203 -
- b/stage2/start.S                 |   13 
- b/stage2/term.h                  |   35 
- b/stage2/tparm.c                 |   14 
- b/test                           |    1 
- b/util/.gitignore                |    7 
- b/util/Makefile.am               |   11 
- b/util/Makefile.in               |  131 
- b/util/grub-crypt.in             |   80 
- b/util/grub-install.in           |  334 +
- configure                        | 7639 ---------------------------------------
- 143 files changed, 30722 insertions(+), 10652 deletions(-)
+ .gitignore                     |    8 
+ ChangeLog                      |   48 
+ Makefile.am                    |    3 
+ Makefile.in                    |  175 
+ acinclude.m4                   |    4 
+ aclocal.m4                     |  555 +-
+ config.h.in                    |    5 
+ configure                      | 7639 -----------------------------------------
+ configure.in                   |  113 
+ docs/.gitignore                |    3 
+ docs/Makefile.am               |    9 
+ docs/Makefile.in               |  260 -
+ docs/grub-crypt.8              |   39 
+ docs/grub-install.8            |    2 
+ docs/grub.8                    |    2 
+ docs/grub.info                 |  370 +
+ docs/grub.texi                 |   79 
+ docs/stamp-vti                 |    4 
+ docs/version.texi              |    4 
+ efi/.gitignore                 |    7 
+ efi/Makefile.am                |   76 
+ efi/byteswap.h                 |   37 
+ efi/dhcp.h                     |  133 
+ efi/efichainloader.c           |  265 +
+ efi/eficon.c                   |  306 +
+ efi/eficore.c                  |  241 +
+ efi/efidisk.c                  |  785 ++++
+ efi/efidp.c                    |  999 +++++
+ efi/efigraph.c                 | 1498 ++++++++
+ efi/efimain.c                  |  129 
+ efi/efimisc.c                  |  665 +++
+ efi/efimm.c                    |  539 ++
+ efi/efiserial.c                |  265 +
+ efi/efitftp.c                  |  228 +
+ efi/efiuga.c                   |  979 +++++
+ efi/font_8x16.c                | 4638 ++++++++++++++++++++++++
+ efi/graphics.c                 |  659 +++
+ efi/graphics.h                 |   81 
+ efi/grub/.gitignore            |    1 
+ efi/grub/efi/api.h             | 1716 +++++++++
+ efi/grub/efi/console_control.h |   59 
+ efi/grub/efi/efi.h             |   85 
+ efi/grub/efi/eficall.h         |  162 
+ efi/grub/efi/misc.h            |   60 
+ efi/grub/efi/time.h            |   31 
+ efi/grub/i386/linux.h          |  226 +
+ efi/grub/i386/types.h          |   32 
+ efi/grub/misc.h                |   71 
+ efi/grub/symbol.h              |   34 
+ efi/grub/types.h               |  158 
+ efi/grub/x86_64/linux.h        |  228 +
+ efi/grub/x86_64/types.h        |   32 
+ efi/ia32/callwrap.S            |    1 
+ efi/ia32/callwrap.c            |  131 
+ efi/ia32/loader/bin_to_h.c     |   29 
+ efi/ia32/loader/linux.c        |  648 +++
+ efi/ia32/loader/switch.S       |  118 
+ efi/ia32/loader/switch.h       |   19 
+ efi/ia32/reloc.c               |   79 
+ efi/ia32/setjmp.S              |   86 
+ efi/pxe.c                      |  444 ++
+ efi/pxe.h                      |  237 +
+ efi/ugadebug.h                 |  201 +
+ efi/x86_64/callwrap.S          |  274 +
+ efi/x86_64/crt0-efi.S          |   63 
+ efi/x86_64/elf_efi.lds         |   58 
+ efi/x86_64/loader/Makefile     |   20 
+ efi/x86_64/loader/bin_to_h.c   |   29 
+ efi/x86_64/loader/linux.c      |  588 +++
+ efi/x86_64/loader/switch.S     |   92 
+ efi/x86_64/loader/switch.h     |   25 
+ efi/x86_64/reloc.c             |   79 
+ efi/x86_64/setjmp.S            |   56 
+ efi/xpm.c                      |  231 +
+ efi/xpm.h                      |   36 
+ grub.spec                      |  438 ++
+ grub/.gitignore                |    2 
+ grub/Makefile.am               |    2 
+ grub/Makefile.in               |  117 
+ grub/asmstub.c                 |  194 -
+ grub/efitftp.c                 |   34 
+ grub/main.c                    |    2 
+ lib/.gitignore                 |    2 
+ lib/Makefile.in                |  111 
+ lib/device.c                   |  360 +
+ netboot/.gitignore             |    2 
+ netboot/Makefile.in            |  359 -
+ netboot/etherboot.h            |   34 
+ netboot/main.c                 |    6 
+ netboot/misc.c                 |   58 
+ netboot/osdep.h                |   24 
+ stage1/.gitignore              |    2 
+ stage1/Makefile.am             |   15 
+ stage1/Makefile.in             |  169 
+ stage1/stage1.S                |    4 
+ stage2/.gitignore              |    5 
+ stage2/Makefile.am             |   73 
+ stage2/Makefile.in             | 1729 +++++----
+ stage2/asm.S                   |  284 +
+ stage2/boot.c                  |  114 
+ stage2/builtins.c              | 1368 +++++--
+ stage2/char_io.c               |  609 ++-
+ stage2/cmdline.c               |   19 
+ stage2/common.c                |   16 
+ stage2/disk_io.c               |  208 -
+ stage2/efistubs.c              |    7 
+ stage2/efistubs.h              |    8 
+ stage2/fat.h                   |    2 
+ stage2/filesys.h               |   17 
+ stage2/fsys_ext2fs.c           |  394 +-
+ stage2/fsys_fat.c              |   41 
+ stage2/fsys_iso9660.c          |    6 
+ stage2/fsys_jfs.c              |   12 
+ stage2/fsys_minix.c            |   10 
+ stage2/fsys_reiserfs.c         |   44 
+ stage2/fsys_vstafs.c           |   28 
+ stage2/fsys_xfs.c              |   22 
+ stage2/gpt.h                   |   69 
+ stage2/graphics.c              |  573 +++
+ stage2/graphics.h              |   42 
+ stage2/gunzip.c                |   15 
+ stage2/iso9660.h               |    4 
+ stage2/mb_info.h               |    4 
+ stage2/pc_slice.h              |   51 
+ stage2/serial.c                |    4 
+ stage2/sha256crypt.c           |  723 +++
+ stage2/sha512crypt.c           |  795 ++++
+ stage2/shared.h                |  124 
+ stage2/smp-imps.h              |    1 
+ stage2/stage1_5.c              |    3 
+ stage2/stage2.c                |  203 -
+ stage2/start.S                 |   13 
+ stage2/term.h                  |   35 
+ stage2/tparm.c                 |   14 
+ test                           |    1 
+ util/.gitignore                |    7 
+ util/Makefile.am               |   11 
+ util/Makefile.in               |  131 
+ util/grub-crypt.in             |   80 
+ util/grub-install.in           |  334 +
+ 140 files changed, 27836 insertions(+), 10643 deletions(-)
 
 diff --git a/.gitignore b/.gitignore
 new file mode 100644
@@ -170,19 +167,6 @@ index 0000000..4e19579
 +config.log
 +config.status
 +stamp-h1
-diff --git a/AUTHORS b/AUTHORS
-index ea8cb4a..236e423 100644
---- a/AUTHORS
-+++ b/AUTHORS
-@@ -41,6 +41,8 @@ Kristoffer Branemyr added VSTa filesystem support.
- 
- Serguei Tzukanov added JFS and XFS support.
- 
-+Edward Shishkin added Btrfs support.
-+
- Jason Thomas added Linux DAC960 support and support for hiding/unhiding
- logical partitions, and did a significant bugfix for the terminal stuff.
- 
 diff --git a/ChangeLog b/ChangeLog
 index 0f93033..9602fb9 100644
 --- a/ChangeLog
@@ -249,20 +233,6 @@ index 0f93033..9602fb9 100644
  2003-01-25  Yoshinori K. Okuji  <okuji at enbug.org>
  
  	From Steven Dick <ssd.gnu at mmae.ucf.edu>:
-diff --git a/INSTALL b/INSTALL
-index 1ba68a6..a8bce4b 100644
---- a/INSTALL
-+++ b/INSTALL
-@@ -216,6 +216,9 @@ operates.
- `--disable-xfs'
-      Omit the XFS support in Stage 2.
- 
-+`--disable-btrfs'
-+     Omit the BtrFS support in Stage 2.
-+
- `--disable-ufs2'
-      Omit the UFS2 support in Stage 2.
- 
 diff --git a/Makefile.am b/Makefile.am
 index 63a9a4f..a27da9c 100644
 --- a/Makefile.am
@@ -9143,10 +9113,10 @@ index 537ab89..0000000
 -fi
 -
 diff --git a/configure.ac b/configure.in
-similarity index 85%
+similarity index 86%
 rename from configure.ac
 rename to configure.in
-index bb9e1d9..1580801 100644
+index bb9e1d9..e9745e6 100644
 --- a/configure.ac
 +++ b/configure.in
 @@ -29,6 +29,65 @@ esac
@@ -9282,21 +9252,7 @@ index bb9e1d9..1580801 100644
         AC_DEFINE(HAVE_LIBCURSES, 1, [Define if you have a curses library])])])
  fi
  
-@@ -284,6 +362,13 @@ if test x"$enable_xfs" != xno; then
-   FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_XFS=1"
- fi
- 
-+AC_ARG_ENABLE(btrfs,
-+  [  --disable-btrfs         disable BtrFS support in Stage 2])
-+
-+if test x"$enable_btrfs" != xno; then
-+  FSYS_CFLAGS="$FSYS_CFLAGS -DFSYS_BTRFS=1"
-+fi
-+
- AC_ARG_ENABLE(iso9660,
-   [  --disable-iso9660       disable ISO9660 support in Stage 2])
- 
-@@ -595,9 +680,18 @@ AC_ARG_ENABLE(diskless,
+@@ -595,9 +673,18 @@ AC_ARG_ENABLE(diskless,
    [  --enable-diskless       enable diskless support])
  AM_CONDITIONAL(DISKLESS_SUPPORT, test "x$enable_diskless" = xyes)
  
@@ -9317,7 +9273,7 @@ index bb9e1d9..1580801 100644
  AM_CONDITIONAL(HERCULES_SUPPORT, test "x$enable_hercules" != xno)
  
  dnl Serial terminal
-@@ -662,9 +756,13 @@ AC_SUBST(CCASFLAGS)
+@@ -662,9 +749,13 @@ AC_SUBST(CCASFLAGS)
  
  
  dnl Output.
@@ -10434,7 +10390,7 @@ index f48783c..7692f31 100644
  
  End Tag Table
 diff --git a/docs/grub.texi b/docs/grub.texi
-index 51d330a..ca10751 100644
+index 51d330a..5fd324d 100644
 --- a/docs/grub.texi
 +++ b/docs/grub.texi
 @@ -21,6 +21,7 @@
@@ -10456,15 +10412,6 @@ index 51d330a..ca10751 100644
  * Invoking grub-terminfo::      How to generate a terminfo command
  * Invoking grub-set-default::   How to set a default boot entry
  * Invoking mbchk::              How to use the Multiboot checker
-@@ -283,7 +285,7 @@ devices, partitions, and files in a directory depending on context.
- Support multiple filesystem types transparently, plus a useful explicit
- blocklist notation. The currently supported filesystem types are
- @dfn{BSD FFS}, @dfn{DOS FAT16 and FAT32}, @dfn{Minix fs}, @dfn{Linux
--ext2fs}, @dfn{ReiserFS}, @dfn{JFS}, @dfn{XFS}, and @dfn{VSTa
-+ext2fs}, @dfn{ReiserFS}, @dfn{JFS}, @dfn{XFS}, @dfn{BtrFS}, and @dfn{VSTa
- fs}. @xref{Filesystem}, for more information.
- 
- @item Support automatic decompression
 @@ -1265,7 +1267,7 @@ OS. There's a solution to that - GRUB provides a menu interface
  keys) that will do everything to boot an OS.
  
@@ -10507,15 +10454,7 @@ index 51d330a..ca10751 100644
  
  Also, you can specify an optional argument to @command{password}. See
  this example:
-@@ -1778,6 +1770,7 @@ itself. Usually, this is put in a filesystem, but that is not required.
- @itemx reiserfs_stage1_5
- @itemx vstafs_stage1_5
- @itemx xfs_stage1_5
-+ at itemx btrfs_stage1_5
- 
- These are called @dfn{Stage 1.5}, because they serve as a bridge
- between @file{stage1} and @file{stage2}, that is to say, Stage 1.5 is
-@@ -1882,8 +1875,8 @@ There are two ways to specify files, by @dfn{absolute file name} and by
+@@ -1882,8 +1874,8 @@ There are two ways to specify files, by @dfn{absolute file name} and by
  
  An absolute file name resembles a Unix absolute file name, using
  @samp{/} for the directory separator (not @samp{\} as in DOS). One
@@ -10526,7 +10465,7 @@ index 51d330a..ca10751 100644
  disk. If you omit the device name in an absolute file name, GRUB uses
  GRUB's @dfn{root device} implicitly. So if you set the root device to,
  say, @samp{(hd1,0)} by the command @command{root} (@pxref{root}), then
-@@ -2199,6 +2192,7 @@ Commands usable anywhere in the menu and in the command-line.
+@@ -2199,6 +2191,7 @@ Commands usable anywhere in the menu and in the command-line.
  * rarp::                        Initialize a network device via RARP
  * serial::                      Set up a serial device
  * setkey::                      Configure the key map
@@ -10534,7 +10473,7 @@ index 51d330a..ca10751 100644
  * terminal::                    Choose a terminal
  * terminfo::                    Define escape sequences for a terminal
  * tftpserver::                  Specify a TFTP server
-@@ -2398,7 +2392,7 @@ is the new partition type and must be a number in the range 0-0xff.
+@@ -2398,7 +2391,7 @@ is the new partition type and must be a number in the range 0-0xff.
  @node password
  @subsection password
  
@@ -10543,7 +10482,7 @@ index 51d330a..ca10751 100644
  If used in the first section of a menu file, disable all interactive
  editing control (menu entry editor and command-line) and entries
  protected by the command @command{lock}. If the password @var{passwd} is
-@@ -2408,7 +2402,9 @@ specified. Otherwise, GRUB will just unlock the privileged instructions.
+@@ -2408,7 +2401,9 @@ specified. Otherwise, GRUB will just unlock the privileged instructions.
  You can also use this command in the script section, in which case it
  will ask for the password, before continuing.  The option
  @option{--md5} tells GRUB that @var{passwd} is encrypted with
@@ -10554,7 +10493,7 @@ index 51d330a..ca10751 100644
  @end deffn
  
  
-@@ -2578,6 +2574,16 @@ character each of the symbols corresponds:
+@@ -2578,6 +2573,16 @@ character each of the symbols corresponds:
  @end deffn
  
  
@@ -10571,7 +10510,7 @@ index 51d330a..ca10751 100644
  @node terminal
  @subsection terminal
  
-@@ -3542,7 +3548,7 @@ ignores this option.
+@@ -3542,7 +3547,7 @@ ignores this option.
  
  @item --config-file=@var{file}
  Read the configuration file @var{file} instead of
@@ -10580,7 +10519,7 @@ index 51d330a..ca10751 100644
  syntax. See @ref{Filesystem}, for more information.
  
  @item --boot-drive=@var{drive}
-@@ -3653,6 +3659,31 @@ comments in the file if needed, as the grub shell assumes that a line is
+@@ -3653,6 +3658,31 @@ comments in the file if needed, as the grub shell assumes that a line is
  just a comment if the first character is @samp{#}.
  
  
@@ -10612,7 +10551,7 @@ index 51d330a..ca10751 100644
  @node Invoking grub-install
  @chapter Invoking grub-install
  
-@@ -3702,8 +3733,9 @@ Use @var{file} as the grub shell. You can append arbitrary options to
+@@ -3702,8 +3732,9 @@ Use @var{file} as the grub shell. You can append arbitrary options to
  
  @item --recheck
  Recheck the device map, even if @file{/boot/grub/device.map} already
@@ -10661,7 +10600,7 @@ index 0000000..a0e4294
 +*.efi
 diff --git a/efi/Makefile.am b/efi/Makefile.am
 new file mode 100644
-index 0000000..4cffe7d
+index 0000000..1d5bd15
 --- /dev/null
 +++ b/efi/Makefile.am
 @@ -0,0 +1,76 @@
@@ -10734,7 +10673,7 @@ index 0000000..4cffe7d
 +	$(HERCULES_FLAGS) $(GRAPHICS_FLAGS)
 +
 +noinst_LIBRARIES = libgrubefi.a
-+libgrubefi_a_SOURCES = $(EFI_ARCH)/callwrap.c eficore.c efimm.c efimisc.c \
++libgrubefi_a_SOURCES = $(EFI_ARCH)/callwrap.S eficore.c efimm.c efimisc.c \
 +	eficon.c efidisk.c graphics.c efigraph.c efiuga.c efidp.c \
 +	font_8x16.c efiserial.c $(EFI_ARCH)/loader/linux.c efichainloader.c \
 +	xpm.c pxe.c efitftp.c
@@ -11508,10 +11447,10 @@ index 0000000..037f050
 +}
 diff --git a/efi/eficore.c b/efi/eficore.c
 new file mode 100644
-index 0000000..259c5dc
+index 0000000..8abea7d
 --- /dev/null
 +++ b/efi/eficore.c
-@@ -0,0 +1,231 @@
+@@ -0,0 +1,241 @@
 +/* eficore.c - generic EFI support */
 +/*
 + *  GRUB  --  GRand Unified Bootloader
@@ -11566,6 +11505,16 @@ index 0000000..259c5dc
 +}
 +
 +grub_efi_status_t
++grub_efi_locate_device_path (grub_efi_guid_t *protocol,
++			     grub_efi_device_path_t **dp,
++			     grub_efi_handle_t *handle)
++{
++	return Call_Service_3(
++		grub_efi_system_table->boot_services->locate_device_path,
++		protocol, dp, handle);
++}
++
++grub_efi_status_t
 +grub_efi_locate_handle_buffer (grub_efi_locate_search_type_t search_type,
 +				grub_efi_guid_t *protocol,
 +				void *search_key,
@@ -12536,10 +12485,10 @@ index 0000000..2192021
 +}
 diff --git a/efi/efidp.c b/efi/efidp.c
 new file mode 100644
-index 0000000..3e0019d
+index 0000000..d8ca03d
 --- /dev/null
 +++ b/efi/efidp.c
-@@ -0,0 +1,984 @@
+@@ -0,0 +1,999 @@
 +/*
 + * GRUB  --  GRand Unified Bootloader
 + * Copyright (C) 2010 Free Software Foundation, Inc.
@@ -12608,6 +12557,21 @@ index 0000000..3e0019d
 +  return p;
 +}
 +
++/* Return the parent device path node. Must be freed */
++grub_efi_device_path_t *
++find_parent_device_path (const grub_efi_device_path_t *dp)
++{
++  grub_efi_device_path_t *final, *dup;
++
++  dup = duplicate_device_path(dp);
++  final = find_last_device_path(dup);
++
++  final->type = GRUB_EFI_END_DEVICE_PATH_TYPE;
++  final->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE;
++
++  return dup;
++}
++
 +/* Compare device paths.  */
 +int
 +compare_device_paths (const grub_efi_device_path_t *dp1,
@@ -13526,10 +13490,10 @@ index 0000000..3e0019d
 +}
 diff --git a/efi/efigraph.c b/efi/efigraph.c
 new file mode 100644
-index 0000000..db112dd
+index 0000000..c285d39
 --- /dev/null
 +++ b/efi/efigraph.c
-@@ -0,0 +1,1467 @@
+@@ -0,0 +1,1498 @@
 +/* efigraph.c - EFI "graphics output" support for GRUB/EFI */
 +/*
 + *  GRUB  --  GRand Unified Bootloader
@@ -13560,7 +13524,7 @@ index 0000000..db112dd
 +#include <grub/cpu/linux.h>
 +#include <grub/efi/api.h>
 +#include <grub/efi/efi.h>
-+#include <grub/misc.h>
++#include <grub/efi/misc.h>
 +
 +#include <term.h>
 +#include <shared.h>
@@ -13605,6 +13569,7 @@ index 0000000..db112dd
 +
 +
 +static grub_efi_guid_t graphics_output_guid = GRUB_EFI_GRAPHICS_OUTPUT_GUID;
++static grub_efi_guid_t pci_io_guid = GRUB_EFI_PCI_IO_GUID;
 +
 +#ifndef MIN
 +#define MIN(x,y) ( ((x) < (y)) ? (x) : (y))
@@ -14809,7 +14774,7 @@ index 0000000..db112dd
 +try_enable(struct graphics_backend *backend)
 +{
 +    struct eg *eg = backend->priv;
-+    grub_efi_status_t efi_status;
++    grub_efi_status_t efi_status = GRUB_EFI_UNSUPPORTED;
 +    int i;
 +
 +    if (eg->text_mode == 0xffffffff) {
@@ -14905,6 +14870,9 @@ index 0000000..db112dd
 +        }
 +    } else {
 +        grub_efi_status_t efi_status;
++	grub_efi_handle_t *handle, *handles;
++	grub_efi_uintn_t num_handles;
++	grub_efi_pci_io_t *pci_proto;
 +
 +        if (!(eg = grub_malloc(sizeof (*eg))))
 +            return 0;
@@ -14913,7 +14881,34 @@ index 0000000..db112dd
 +
 +        eg->backend = backend;
 +        eg->current_mode = TEXT;
-+        eg->output_intf = grub_efi_locate_protocol(&graphics_output_guid, NULL);
++
++	handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL,
++					  &graphics_output_guid,
++					  NULL, &num_handles);
++
++	if (!num_handles || !handles)
++	  goto fail;
++
++	for (handle = handles; num_handles--; handle++)
++	  {
++	    pci_proto = grub_efi_open_protocol (*handle, &pci_io_guid,
++					 GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++	    if (!pci_proto)
++	      continue;
++
++	    eg->output_intf = grub_efi_open_protocol (*handle,
++		   &graphics_output_guid, GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++	    if (eg->output_intf)
++	      {
++		grub_efi_setup_gfx_pci(*handle);
++		break;
++	      }
++	  }
++
++	grub_free(handles);
++
 +        if (!eg->output_intf)
 +            goto fail;
 +
@@ -15805,10 +15800,10 @@ index 0000000..480ba25
 +}
 diff --git a/efi/efimm.c b/efi/efimm.c
 new file mode 100644
-index 0000000..c3cbfc4
+index 0000000..836188d
 --- /dev/null
 +++ b/efi/efimm.c
-@@ -0,0 +1,512 @@
+@@ -0,0 +1,539 @@
 +/*
 + *  GRUB  --  GRand Unified Bootloader
 + *  Copyright (C) 2006  Free Software Foundation, Inc.
@@ -15931,9 +15926,10 @@ index 0000000..c3cbfc4
 +}
 +
 +/* Allocate pages. Return the pointer to the first of allocated pages.  */
-+void *
-+grub_efi_allocate_pages (grub_efi_physical_address_t address,
-+			 grub_efi_uintn_t pages)
++static void *
++grub_efi_allocate_pages_real (grub_efi_physical_address_t address,
++			      grub_efi_uintn_t pages,
++			      grub_efi_memory_type_t memtype)
 +{
 +  grub_efi_allocate_type_t type;
 +  grub_efi_status_t status;
@@ -15954,9 +15950,18 @@ index 0000000..c3cbfc4
 +
 +  b = grub_efi_system_table->boot_services;
 +  status = Call_Service_4 (b->allocate_pages, type,
-+			   GRUB_EFI_LOADER_DATA, pages, &address);
++			   memtype, pages, &address);
++
 +  if (status != GRUB_EFI_SUCCESS)
-+    return 0;
++    {
++      /* EFI_NOT_FOUND means the region was unavailable, which means we can
++	 probably just use it. This is only for hacks to start with */
++      if (memtype == GRUB_EFI_RUNTIME_SERVICES_DATA &&
++	  status == GRUB_EFI_NOT_FOUND)
++	return (void *) ((grub_addr_t) address);
++      else
++	return 0;
++    }
 +
 +  if (address == 0)
 +    {
@@ -15970,7 +15975,8 @@ index 0000000..c3cbfc4
 +	return 0;
 +    }
 +
-+  if (allocated_pages)
++  /* We don't want to free anything we've allocated for runtime */
++  if (allocated_pages && memtype != GRUB_EFI_RUNTIME_SERVICES_DATA)
 +    {
 +      unsigned i;
 +
@@ -15992,6 +15998,22 @@ index 0000000..c3cbfc4
 +  return (void *) ((grub_addr_t) address);
 +}
 +
++void *
++grub_efi_allocate_pages (grub_efi_physical_address_t address,
++			 grub_efi_uintn_t pages)
++
++{
++  return grub_efi_allocate_pages_real(address, pages, GRUB_EFI_LOADER_DATA);
++}
++
++void *
++grub_efi_allocate_runtime_pages (grub_efi_physical_address_t address,
++				 grub_efi_uintn_t pages)
++
++{
++  return grub_efi_allocate_pages_real(address, pages,
++				      GRUB_EFI_RUNTIME_SERVICES_DATA);
++}
 +/* Free pages starting from ADDRESS.  */
 +void
 +grub_efi_free_pages (grub_efi_physical_address_t address,
@@ -16831,10 +16853,10 @@ index 0000000..ba6918f
 +}
 diff --git a/efi/efiuga.c b/efi/efiuga.c
 new file mode 100644
-index 0000000..b762eb8
+index 0000000..e035c55
 --- /dev/null
 +++ b/efi/efiuga.c
-@@ -0,0 +1,946 @@
+@@ -0,0 +1,979 @@
 +/* efiuga.c - "univeral graphics adapter" support for GRUB/EFI */
 +/*
 + *  GRUB  --  GRand Unified Bootloader
@@ -16875,6 +16897,7 @@ index 0000000..b762eb8
 +#include "xpm.h"
 +
 +static grub_efi_guid_t draw_guid = GRUB_EFI_UGA_DRAW_GUID;
++static grub_efi_guid_t pci_io_guid = GRUB_EFI_PCI_IO_GUID;
 +
 +#if 0
 +#define UGA
@@ -17702,6 +17725,9 @@ index 0000000..b762eb8
 +enable(struct graphics_backend *backend)
 +{
 +    struct uga *uga = backend->priv;
++    grub_efi_handle_t *handle, *handles;
++    grub_efi_uintn_t num_handles;
++    grub_efi_pci_io_t *pci_proto;
 +    int i;
 +
 +    if (uga) {
@@ -17715,7 +17741,36 @@ index 0000000..b762eb8
 +	grub_memset(uga, '\0', sizeof (*uga));
 +
 +        uga->current_mode = TEXT;
-+	uga->draw_intf = grub_efi_locate_protocol(&draw_guid, NULL);
++
++        handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL,
++                                          &draw_guid, NULL, &num_handles);
++
++        if (!num_handles || !handles)
++	  {
++            grub_free(uga);
++	    return 0;
++	  }
++
++	for (handle = handles; num_handles--; handle++)
++          {
++            pci_proto = grub_efi_open_protocol (*handle, &pci_io_guid,
++				          GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++            if (!pci_proto)
++              continue;
++
++            uga->draw_intf = grub_efi_open_protocol (*handle, &draw_guid,
++					  GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++            if (uga->draw_intf)
++              {
++                grub_efi_setup_gfx_pci(*handle);
++                break;
++              }
++          }
++
++	grub_free(handles);
++
 +        if (!uga->draw_intf) {
 +            grub_free(uga);
 +            return 0;
@@ -22427,10 +22482,10 @@ index 0000000..94829ec
 +#endif
 diff --git a/efi/graphics.c b/efi/graphics.c
 new file mode 100644
-index 0000000..5e91810
+index 0000000..2302590
 --- /dev/null
 +++ b/efi/graphics.c
-@@ -0,0 +1,568 @@
+@@ -0,0 +1,659 @@
 +#ifdef SUPPORT_GRAPHICS
 +
 +#include <grub/misc.h>
@@ -22438,7 +22493,7 @@ index 0000000..5e91810
 +#include <grub/cpu/linux.h>
 +#include <grub/efi/api.h>
 +#include <grub/efi/efi.h>
-+#include <grub/misc.h>
++#include <grub/efi/misc.h>
 +
 +#include <term.h>
 +#include <shared.h>
@@ -22509,6 +22564,97 @@ index 0000000..5e91810
 +    unsigned short *text;
 +};
 +
++static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
++static grub_efi_guid_t pci_io_guid = GRUB_EFI_PCI_IO_GUID;
++static grub_efi_guid_t pci_root_io_guid = GRUB_EFI_PCI_ROOT_IO_GUID;
++
++static void
++grub_efi_configure_pci(grub_efi_handle_t handle)
++{
++  grub_efi_device_path_t *path, *parent;
++  grub_efi_handle_t parent_handle;
++  grub_efi_pci_io_t *pci_proto;
++  grub_efi_pci_root_io_t *pci_root_proto;
++  grub_efi_status_t status;
++
++  path = grub_efi_get_device_path(handle);
++  parent = find_parent_device_path(path);
++
++  if (!parent)
++    return;
++
++  status = grub_efi_locate_device_path (&device_path_guid, &parent,
++					&parent_handle);
++  if (status != GRUB_EFI_SUCCESS)
++    return;
++
++  pci_proto = grub_efi_open_protocol (parent_handle, &pci_io_guid,
++				      GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++  pci_root_proto = grub_efi_open_protocol (parent_handle, &pci_root_io_guid,
++					   GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++
++  if (pci_proto || pci_root_proto)
++    {
++      if (pci_proto)
++	{
++	  Call_Service_4 (pci_proto->attributes, pci_proto,
++			  grub_efi_pci_io_attribute_operation_enable,
++			  GRUB_EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |
++			  GRUB_EFI_PCI_IO_ATTRIBUTE_VGA_IO |
++			  GRUB_EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO, NULL);
++
++	  grub_efi_configure_pci (parent_handle);
++	}
++      else
++	{
++	  grub_uint8_t value = 0x33;
++
++	  Call_Service_5 (pci_root_proto->pci.write, pci_root_proto,
++			  grub_efi_pci_io_width_uint8, 0x91, 1, &value);
++	  Call_Service_5 (pci_root_proto->pci.write, pci_root_proto,
++			  grub_efi_pci_io_width_uint8, 0x92, 1, &value);
++	}
++    }
++  grub_free(parent);
++}
++
++void
++grub_efi_setup_gfx_pci(grub_efi_handle_t handle)
++{
++  grub_efi_uint64_t romsize;
++  grub_efi_uint16_t *header;
++  void *vrom;
++  grub_efi_pci_io_t *pci_proto;
++
++  pci_proto = grub_efi_open_protocol (handle, &pci_io_guid,
++				      GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
++
++  if (!pci_proto)
++    return;
++
++  romsize = pci_proto->rom_size;
++
++  if (!romsize || romsize > 65536 || !pci_proto->rom_image)
++    return;
++
++  /* Copy the ROM */
++  vrom = grub_efi_allocate_runtime_pages(0xc0000, 16);
++
++  if (!vrom)
++    return;
++
++  header = vrom;
++
++  if (*header == 0xaa55)
++    return;
++
++  grub_efi_configure_pci(handle);
++
++  grub_memcpy(vrom, pci_proto->rom_image, romsize);
++}
++
 +void
 +graphics_set_kernel_params(struct linux_kernel_params *params)
 +{
@@ -23001,10 +23147,10 @@ index 0000000..5e91810
 +#endif /* SUPPORT_GRAPHICS */
 diff --git a/efi/graphics.h b/efi/graphics.h
 new file mode 100644
-index 0000000..7bdd647
+index 0000000..ecf9e0e
 --- /dev/null
 +++ b/efi/graphics.h
-@@ -0,0 +1,79 @@
+@@ -0,0 +1,81 @@
 +#ifndef GRUB_EFI_GRAPHICS_H
 +#define GRUB_EFI_GRAPHICS_H
 +
@@ -23024,6 +23170,8 @@ index 0000000..7bdd647
 +};
 +typedef struct position position_t;
 +
++extern void grub_efi_setup_gfx_pci (grub_efi_handle_t handle);
++
 +extern grub_uint16_t grub_console_getwh (void);
 +extern void graphics_set_kernel_params(struct linux_kernel_params *params);
 +extern void graphics_set_font_position(position_t *pos);
@@ -23093,10 +23241,10 @@ index 0000000..40a991e
 +cpu
 diff --git a/efi/grub/efi/api.h b/efi/grub/efi/api.h
 new file mode 100644
-index 0000000..8f75a68
+index 0000000..f7f8a3d
 --- /dev/null
 +++ b/efi/grub/efi/api.h
-@@ -0,0 +1,1471 @@
+@@ -0,0 +1,1716 @@
 +/* efi.h - declare EFI types and functions */
 +/*
 + *  GRUB  --  GRand Unified Bootloader
@@ -23169,6 +23317,16 @@ index 0000000..8f75a68
 +
 +#define GRUB_EFI_OPTIONAL_PTR	0x00000001
 +
++#define GRUB_EFI_PCI_IO_GUID	\
++  { 0x4cf5b200, 0x68b8, 0x4ca5, \
++    { 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x02, 0x9a } \
++  }
++
++#define GRUB_EFI_PCI_ROOT_IO_GUID \
++  { 0x2F707EBB, 0x4A1A, 0x11d4, \
++      { 0x9A, 0x38, 0x00, 0x90,	0x27, 0x3F, 0xC1, 0x4D } \
++  }
++
 +#define GRUB_EFI_LOADED_IMAGE_GUID	\
 +  { 0x5b1b31a1, 0x9562, 0x11d2, \
 +    { 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
@@ -24338,6 +24496,241 @@ index 0000000..8f75a68
 +  EfiUgaBltMax
 +} grub_efi_uga_blt_operation_t;
 +
++typedef enum {
++  grub_efi_pci_io_width_uint8,
++  grub_efi_pci_io_width_uint16,
++  grub_efi_pci_io_width_uint32,
++  grub_efi_pci_io_width_uint64,
++  grub_efi_pci_io_width_fifo_uint8,
++  grub_efi_pci_io_width_fifo_uint16,
++  grub_efi_pci_io_width_fifo_uint32,
++  grub_efi_pci_io_width_fifo_uint64,
++  grub_efi_pci_io_width_fill_uint8,
++  grub_efi_pci_io_width_fill_uint16,
++  grub_efi_pci_io_width_fill_uint32,
++  grub_efi_pci_io_width_fill_uint64,
++  grub_efi_pci_io_width_maximum
++} grub_efi_pci_io_width;
++
++struct grub_efi_pci_io;
++
++typedef struct
++{
++  grub_efi_status_t(*read) (struct grub_efi_pci_io *this,
++			    grub_efi_pci_io_width width,
++			    grub_efi_uint8_t bar_index,
++			    grub_efi_uint64_t offset,
++			    grub_efi_uintn_t count,
++			    void *buffer);
++  grub_efi_status_t(*write) (struct grub_efi_pci_io *this,
++			    grub_efi_pci_io_width width,
++			    grub_efi_uint8_t bar_index,
++			    grub_efi_uint64_t offset,
++			    grub_efi_uintn_t count,
++			    void *buffer);
++} grub_efi_pci_io_access_t;
++
++typedef struct
++{
++  grub_efi_status_t( *read) (struct grub_efi_pci_io *this,
++			     grub_efi_pci_io_width width,
++			     grub_efi_uint32_t offset,
++			     grub_efi_uintn_t count,
++			     void *buffer);
++  grub_efi_status_t( *write) (struct grub_efi_pci_io *this,
++			     grub_efi_pci_io_width width,
++			     grub_efi_uint32_t offset,
++			     grub_efi_uintn_t count,
++			     void *buffer);
++} grub_efi_pci_io_config_access_t;
++
++typedef enum {
++  grub_efi_pci_io_operation_bus_masterread,
++  grub_efi_pci_io_operation_bus_masterwrite,
++  grub_efi_pci_io_operation_bus_master_common_buffer,
++  grub_efi_pci_io_operation_maximum
++} grub_efi_pci_io_operation_t;
++
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_ISA_IO               0x0002
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO       0x0004
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY           0x0008
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_VGA_IO               0x0010
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO       0x0020
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO     0x0040
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_IO                   0x0100
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_MEMORY               0x0200
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_BUS_MASTER           0x0400
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED        0x0800
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE       0x1000
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE      0x2000
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM         0x4000
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE   0x8000
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_ISA_IO_16            0x10000
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16    0x20000
++#define GRUB_EFI_PCI_IO_ATTRIBUTE_VGA_IO_16            0x40000
++
++typedef enum {
++  grub_efi_pci_io_attribute_operation_get,
++  grub_efi_pci_io_attribute_operation_set,
++  grub_efi_pci_io_attribute_operation_enable,
++  grub_efi_pci_io_attribute_operation_disable,
++  grub_efi_pci_io_attribute_operation_supported,
++  grub_efi_pci_io_attribute_operation_maximum
++} grub_efi_pci_io_attribute_operation_t;
++
++struct grub_efi_pci_io {
++  grub_efi_status_t (*poll_mem) (struct grub_efi_pci_io *this,
++				 grub_efi_pci_io_width  width,
++				 grub_efi_uint8_t bar_ndex,
++				 grub_efi_uint64_t offset,
++				 grub_efi_uint64_t mask,
++				 grub_efi_uint64_t value,
++				 grub_efi_uint64_t delay,
++				 grub_efi_uint64_t *result);
++  grub_efi_status_t (*poll_io) (struct grub_efi_pci_io *this,
++				grub_efi_pci_io_width  Width,
++				grub_efi_uint8_t bar_index,
++				grub_efi_uint64_t offset,
++				grub_efi_uint64_t mask,
++				grub_efi_uint64_t value,
++				grub_efi_uint64_t delay,
++				grub_efi_uint64_t *result);
++  grub_efi_pci_io_access_t mem;
++  grub_efi_pci_io_access_t io;
++  grub_efi_pci_io_config_access_t pci;
++  grub_efi_status_t (*copy_mem) (struct grub_efi_pci_io *this,
++				 grub_efi_pci_io_width width,
++				 grub_efi_uint8_t dest_bar_index,
++				 grub_efi_uint64_t dest_offset,
++				 grub_efi_uint8_t src_bar_index,
++				 grub_efi_uint64_t src_offset,
++				 grub_efi_uintn_t count);
++  grub_efi_status_t (*map) ( struct grub_efi_pci_io *this,
++			     grub_efi_pci_io_operation_t operation,
++			     void *host_address,
++			     grub_efi_uintn_t *number_of_bytes,
++			     grub_efi_uint64_t *device_address,
++			     void **mapping);
++  grub_efi_status_t (*unmap) (struct grub_efi_pci_io *this,
++			      void *mapping);
++  grub_efi_status_t (*allocate_buffer) (struct grub_efi_pci_io *this,
++					grub_efi_allocate_type_t type,
++					grub_efi_memory_type_t memory_type,
++					grub_efi_uintn_t pages,
++					void **host_address,
++					grub_efi_uint64_t attributes);
++  grub_efi_status_t (*free_buffer) (struct grub_efi_pci_io *this,
++					grub_efi_allocate_type_t type,
++					grub_efi_memory_type_t memory_type,
++					grub_efi_uintn_t pages,
++					void **host_address,
++					grub_efi_uint64_t attributes);
++  grub_efi_status_t (*flush) (struct grub_efi_pci_io *this);
++  grub_efi_status_t (*get_location) (struct grub_efi_pci_io *this,
++				     grub_efi_uintn_t *segment_number,
++				     grub_efi_uintn_t *bus_number,
++				     grub_efi_uintn_t *device_number,
++				     grub_efi_uintn_t *function_number);
++  grub_efi_status_t (*attributes) (struct grub_efi_pci_io *this,
++				   grub_efi_pci_io_attribute_operation_t operation,
++				   grub_efi_uint64_t attributes,
++				   grub_efi_uint64_t *result);
++  grub_efi_status_t (*get_bar_attributes) (struct grub_efi_pci_io *this,
++					   grub_efi_uint8_t bar_index,
++					   grub_efi_uint64_t *supports,
++					   void **resources);
++  grub_efi_status_t (*set_bar_attributes) (struct grub_efi_pci_io *this,
++					   grub_efi_uint64_t attributes,
++					   grub_efi_uint8_t bar_index,
++					   grub_efi_uint64_t *offset,
++					   grub_efi_uint64_t *length);
++  grub_efi_uint64_t rom_size;
++  void *rom_image;
++};
++typedef struct grub_efi_pci_io grub_efi_pci_io_t;
++
++struct grub_efi_pci_root_io;
++
++typedef struct
++{
++  grub_efi_status_t(*read) (struct grub_efi_pci_root_io *this,
++			    grub_efi_pci_io_width width,
++			    grub_efi_uint64_t address,
++			    grub_efi_uintn_t count,
++			    void *buffer);
++  grub_efi_status_t(*write) (struct grub_efi_pci_root_io *this,
++			    grub_efi_pci_io_width width,
++			    grub_efi_uint64_t address,
++			    grub_efi_uintn_t count,
++			    void *buffer);
++} grub_efi_pci_root_io_access_t;
++
++typedef enum {
++  grub_efi_pci_root_io_operation_bus_master_read,
++  grub_efi_pci_root_io_operation_bus_master_write,
++  grub_efi_pci_root_io_operation_bus_master_common_buffer,
++  grub_efi_pci_root_io_operation_bus_master_read_64,
++  grub_efi_pci_root_io_operation_bus_master_write_64,
++  grub_efi_pci_root_io_operation_bus_master_common_buffer_64,
++  grub_efi_pci_root_io_operation_maximum
++} grub_efi_pci_root_io_operation_t;
++
++struct grub_efi_pci_root_io {
++  grub_efi_handle_t parent;
++  grub_efi_status_t (*poll_mem) (struct grub_efi_pci_root_io *this,
++				 grub_efi_pci_io_width  width,
++				 grub_efi_uint64_t address,
++				 grub_efi_uint64_t mask,
++				 grub_efi_uint64_t value,
++				 grub_efi_uint64_t delay,
++				 grub_efi_uint64_t *result);
++  grub_efi_status_t (*poll_io) (struct grub_efi_pci_root_io *this,
++				grub_efi_pci_io_width  Width,
++				grub_efi_uint64_t address,
++				grub_efi_uint64_t mask,
++				grub_efi_uint64_t value,
++				grub_efi_uint64_t delay,
++				grub_efi_uint64_t *result);
++  grub_efi_pci_root_io_access_t mem;
++  grub_efi_pci_root_io_access_t io;
++  grub_efi_pci_root_io_access_t pci;
++  grub_efi_status_t (*copy_mem) (struct grub_efi_pci_root_io *this,
++				 grub_efi_pci_io_width width,
++				 grub_efi_uint64_t dest_offset,
++				 grub_efi_uint64_t src_offset,
++				 grub_efi_uintn_t count);
++  grub_efi_status_t (*map) ( struct grub_efi_pci_root_io *this,
++			     grub_efi_pci_root_io_operation_t operation,
++			     void *host_address,
++			     grub_efi_uintn_t *number_of_bytes,
++			     grub_efi_uint64_t *device_address,
++			     void **mapping);
++  grub_efi_status_t (*unmap) (struct grub_efi_pci_root_io *this,
++			      void *mapping);
++  grub_efi_status_t (*allocate_buffer) (struct grub_efi_pci_root_io *this,
++					grub_efi_allocate_type_t type,
++					grub_efi_memory_type_t memory_type,
++					grub_efi_uintn_t pages,
++					void **host_address,
++					grub_efi_uint64_t attributes);
++  grub_efi_status_t (*free_buffer) (struct grub_efi_pci_root_io *this,
++				    grub_efi_uintn_t pages,
++				    void **host_address);
++  grub_efi_status_t (*flush) (struct grub_efi_pci_root_io *this);
++  grub_efi_status_t (*get_attributes) (struct grub_efi_pci_root_io *this,
++				       grub_efi_uint64_t *supports,
++				       void **resources);
++  grub_efi_status_t (*set_attributes) (struct grub_efi_pci_root_io *this,
++				       grub_efi_uint64_t attributes,
++				       grub_efi_uint64_t *offset,
++				       grub_efi_uint64_t *length);
++  grub_efi_status_t (*configuration) (struct grub_efi_pci_root_io *this,
++				      void **resources);
++};
++
++typedef struct grub_efi_pci_root_io grub_efi_pci_root_io_t;
++
 +struct grub_efi_uga_draw
 +{
 +  grub_efi_status_t (*get_mode) (struct grub_efi_uga_draw * this,
@@ -24635,10 +25028,10 @@ index 0000000..ffc4305
 +#endif /* ! GRUB_EFI_CONSOLE_CONTROL_HEADER */
 diff --git a/efi/grub/efi/efi.h b/efi/grub/efi/efi.h
 new file mode 100644
-index 0000000..936759b
+index 0000000..301f9d9
 --- /dev/null
 +++ b/efi/grub/efi/efi.h
-@@ -0,0 +1,79 @@
+@@ -0,0 +1,85 @@
 +/* efi.h - declare variables and functions for EFI support */
 +/*
 + *  GRUB  --  GRand Unified Bootloader
@@ -24667,6 +25060,10 @@ index 0000000..936759b
 +
 +/* Functions.  */
 +grub_efi_status_t
++grub_efi_locate_device_path (grub_efi_guid_t *protocol,
++                             grub_efi_device_path_t **dp,
++                             grub_efi_handle_t *handle);
++grub_efi_status_t
 +grub_efi_locate_handle_buffer (grub_efi_locate_search_type_t search_type,
 +				grub_efi_guid_t *protocol,
 +				void *search_key,
@@ -24689,6 +25086,8 @@ index 0000000..936759b
 +void *grub_efi_allocate_anypages (grub_efi_uintn_t pages);
 +void *grub_efi_allocate_pages (grub_efi_physical_address_t address,
 +			       grub_efi_uintn_t pages);
++void *grub_efi_allocate_runtime_pages (grub_efi_physical_address_t address,
++				       grub_efi_uintn_t pages);
 +void
 +grub_efi_free_pages (grub_efi_physical_address_t address,
 +		     grub_efi_uintn_t pages);
@@ -24888,10 +25287,10 @@ index 0000000..2e79e04
 +#endif
 diff --git a/efi/grub/efi/misc.h b/efi/grub/efi/misc.h
 new file mode 100644
-index 0000000..7dc34e7
+index 0000000..e06a2fb
 --- /dev/null
 +++ b/efi/grub/efi/misc.h
-@@ -0,0 +1,58 @@
+@@ -0,0 +1,60 @@
 +/* misc.h - prototypes for misc EFI functions */
 +/*
 + *  GRUB  --  GRand Unified Bootloader
@@ -24940,6 +25339,8 @@ index 0000000..7dc34e7
 +grub_efi_device_path_t *
 +find_last_device_path (const grub_efi_device_path_t *dp);
 +grub_efi_device_path_t *
++find_parent_device_path (const grub_efi_device_path_t *dp);
++grub_efi_device_path_t *
 +duplicate_device_path (const grub_efi_device_path_t *dp);
 +int
 +compare_device_paths (const grub_efi_device_path_t *dp1,
@@ -25815,7 +26216,11 @@ index 0000000..0c077f6
 +#endif /* ! GRUB_TYPES_CPU_HEADER */
 diff --git a/efi/ia32/callwrap.S b/efi/ia32/callwrap.S
 new file mode 100644
-index 0000000..e69de29
+index 0000000..50d737f
+--- /dev/null
++++ b/efi/ia32/callwrap.S
+@@ -0,0 +1 @@
++/* This file is a stub for ia32 building */
 diff --git a/efi/ia32/callwrap.c b/efi/ia32/callwrap.c
 new file mode 100644
 index 0000000..56df899
@@ -27870,408 +28275,284 @@ index 0000000..f461c8b
 +#endif /* UGA_DEBUG_H */
 diff --git a/efi/x86_64/callwrap.S b/efi/x86_64/callwrap.S
 new file mode 100644
-index 0000000..e69de29
-diff --git a/efi/x86_64/callwrap.c b/efi/x86_64/callwrap.c
-new file mode 100644
-index 0000000..eb8fd25
+index 0000000..f574ad0
 --- /dev/null
-+++ b/efi/x86_64/callwrap.c
-@@ -0,0 +1,395 @@
++++ b/efi/x86_64/callwrap.S
+@@ -0,0 +1,274 @@
 +/*
-+ *  Copyright (C) 2006 Giridhar Pemmasani
-+ *  Copyright (C) 2007-2010 Intel Corp
-+ *  	Contributed by Chandramouli Narayanan<mouli at linux.intel.com>
-+ *	Adapted wrapper macros for Linux to windows calls from
-+ *	NDIS wrapper project (http:/ndiswrapper.sourceforge.net)
-+ *	
++ * Function calling ABI conversion from Linux to EFI for x86_64
 + *
-+ *  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.
++ * Copyright (C) 2007 Intel Corp
++ *	Bibo Mao <bibo.mao at intel.com>
++ *	Huang Ying <ying.huang at intel.com>
++ */
++
++/*
++ * EFI calling conventions are documented at:
++ *   http://msdn.microsoft.com/en-us/library/ms235286%28v=vs.80%29.aspx
++ * ELF calling conventions are documented at:
++ *   http://www.x86-64.org/documentation/abi.pdf
 + *
++ * Basically here are the conversion rules:
++ * a) our function pointer is in %rdi
++ * b) ELF gives us 8-byte aligned %rsp, so we need to pad out to 16-byte
++ *    alignment.
++ * c) inside each call thunker, we can only adjust the stack by
++ *    multiples of 16 bytes. "offset" below refers to however much
++ *    we allocate inside a thunker.
++ * d) rsi through r8 (elf) aka rcx through r9 (ms) require stack space
++ *    on the MS side even though it's not getting used at all.
++ * e) arguments are as follows: (elf -> ms)
++ *   1) rdi -> rcx (32 saved)
++ *   2) rsi -> rdx (32 saved)
++ *   3) rdx -> r8 ( 32 saved)
++ *   4) rcx -> r9 (32 saved)
++ *   5) r8 -> 32(%rsp) (48 saved)
++ *   6) r9 -> 40(%rsp) (48 saved)
++ *   7) pad+offset+0(%rsp) -> 48(%rsp) (64 saved)
++ *   8) pad+offset+8(%rsp) -> 56(%rsp) (64 saved)
++ *   9) pad+offset+16(%rsp) -> 64(%rsp) (80 saved)
++ *  10) pad+offset+24(%rsp) -> 72(%rsp) (80 saved)
++ *  11) pad+offset+32(%rsp) -> 80(%rsp) (96 saved)
++ *  12) pad+offset+40(%rsp) -> 88(%rsp) (96 saved)
++ * f) because the first argument we recieve in a thunker is actually the
++ *    function to be called, arguments are offset as such:
++ *   0) rdi -> caller
++ *   1) rsi -> rcx (32 saved)
++ *   2) rdx -> rdx (32 saved)
++ *   3) rcx -> r8 (32 saved)
++ *   4) r8 -> r9 (32 saved)
++ *   5) r9 -> 32(%rsp) (48 saved)
++ *   6) pad+offset+0(%rsp) -> 40(%rsp) (48 saved)
++ *   7) pad+offset+8(%rsp) -> 48(%rsp) (64 saved)
++ *   8) pad+offset+16(%rsp) -> 56(%rsp) (64 saved)
++ *   9) pad+offset+24(%rsp) -> 64(%rsp) (80 saved)
++ *  10) pad+offset+32(%rsp) -> 72(%rsp) (80 saved)
++ *  11) pad+offset+40(%rsp) -> 80(%rsp) (96 saved)
++ *  12) pad+offset+48(%rsp) -> 88(%rsp) (96 saved)
++ * e) arguments need to be moved in opposite order to avoid clobbering
++ * f) pad_stack leaves the amount of padding it added in %r11 for functions
++ *    to use
++ * g) efi -> elf calls don't need to pad the stack, because the 16-byte
++ *    alignment is also always 8-byte aligned.
 + */
 +
-+#define alloc_win_stack_frame(argc)		\
-+	"subq $" #argc "*8, %%rsp\n\t"
-+#define free_win_stack_frame(argc)		\
-+	"addq $" #argc "*8, %%rsp\n\t"
-+
-+/* m is index of Windows arg required, n is total number of args to
-+ * function Windows arg 1 should be at 0(%rsp), arg 2 at 8(%rsp) and
-+ * so on, after stack frame is allocated, which starts at -n*8(%rsp)
-+ * when stack frame is allocated. 4 > m >= n.
-+*/
-+
-+#define lin2win_win_arg(m,n) "(" #m "-1-" #n ")*8(%%rsp)"
-+
-+/* volatile args for Windows function must be in clobber / output list */
-+extern unsigned long long x64_call0(void *func);
-+extern unsigned long long x64_call1(void *func, unsigned long long arg1);
-+extern unsigned long long x64_call2(void *func, unsigned long long arg1, unsigned long long arg2);
-+extern unsigned long long x64_call3(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3);
-+extern unsigned long long x64_call4(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4);
-+extern unsigned long long x64_call5(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4,
-+	unsigned long long arg5);
-+extern unsigned long long x64_call6(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4,
-+	unsigned long long arg5,
-+	unsigned long long arg6);
-+extern unsigned long long x64_call7(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4,
-+	unsigned long long arg5,
-+	unsigned long long arg6,
-+	unsigned long long arg7);
-+extern unsigned long long x64_call8(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4,
-+	unsigned long long arg5,
-+	unsigned long long arg6,
-+	unsigned long long arg7,
-+	unsigned long long arg8);
-+extern unsigned long long x64_call9(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4,
-+	unsigned long long arg5,
-+	unsigned long long arg6,
-+	unsigned long long arg7,
-+	unsigned long long arg8,
-+	unsigned long long arg9);
-+extern unsigned long long x64_call10(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4,
-+	unsigned long long arg5,
-+	unsigned long long arg6,
-+	unsigned long long arg7,
-+	unsigned long long arg8,
-+	unsigned long long arg9,
-+	unsigned long long arg10);
-+
-+
-+unsigned long long x64_call0(void *func)
-+{									
-+	unsigned long long ret, dummy;
-+	register unsigned long long r8 __asm__("r8");
-+	register unsigned long long r9 __asm__("r9");
-+	register unsigned long long r10 __asm__("r10");
-+	register unsigned long long r11 __asm__("r11");
-+	__asm__ __volatile__(					
-+		alloc_win_stack_frame(4)				
-+		"call *%[fptr]\n\t"					
-+		free_win_stack_frame(4)					
-+		: "=a" (ret), "=c" (dummy), "=d" (dummy),		
-+		  "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11)		
-+		: [fptr] "r" (func));					
-+	return ret;								
-+}
-+
-+unsigned long long x64_call1(void *func, unsigned long long arg1)
-+{
-+	unsigned long long ret, dummy;
-+	register unsigned long long r8 __asm__("r8");
-+	register unsigned long long r9 __asm__("r9");
-+	register unsigned long long r10 __asm__("r10");
-+	register unsigned long long r11 __asm__("r11");
-+	__asm__ __volatile__(
-+		alloc_win_stack_frame(4)
-+		"call *%[fptr]\n\t"
-+		free_win_stack_frame(4)	
-+		: "=a" (ret), "=c" (dummy), "=d" (dummy),
-+		  "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11)
-+		: "c" (arg1),
-+		  [fptr] "r" (func));
-+	return ret;
-+}
++#define ENTRY(name)	\
++	.globl name;	\
++	name:
++
++#define out(val)		\
++	push %rax ;		\
++	mov val, %rax ;		\
++	out %al, $128 ;		\
++	pop %rax
++
++#define pad_stack							\
++	subq $8, %rsp ; /* must be a multiple of 16 - sizeof(%rip) */	\
++	/* stash some handy integers */					\
++	mov $0x8, %rax ;						\
++	mov $0x10, %r10 ;						\
++	/* see if we need padding */					\
++	and %rsp, %rax ;						\
++	/* store the pad amount in %r11 */				\
++	cmovnz %rax, %r11 ;						\
++	cmovz %r10, %r11 ;						\
++	/* insert the padding */					\
++	subq %r11, %rsp ;						\
++	/* add the $8 we saved above in %r11 */				\
++	addq $8, %r11 ;							\
++	/* store the pad amount */					\
++	mov %r11, (%rsp) ;						\
++	/* compensate for %rip being stored on the stack by call */	\
++	addq $8, %r11
++
++#define unpad_stack							\
++	/* fetch the pad amount	we saved (%r11 has been clobbered) */	\
++	mov (%rsp), %r11 ;						\
++	/* remove the padding */					\
++	addq %r11, %rsp
++
++ENTRY(x64_call0)
++	pad_stack
++	subq $32, %rsp
++	call *%rdi
++	addq $32, %rsp
++	unpad_stack
++	ret
 +
-+unsigned long long x64_call2(void *func, unsigned long long arg1, unsigned long long arg2)
-+{
-+	unsigned long long ret, dummy;
-+	register unsigned long long r8 __asm__("r8");
-+	register unsigned long long r9 __asm__("r9");
-+	register unsigned long long r10 __asm__("r10");
-+	register unsigned long long r11 __asm__("r11");
-+	__asm__ __volatile__(
-+		alloc_win_stack_frame(4)
-+		"call *%[fptr]\n\t"
-+		free_win_stack_frame(4)
-+		: "=a" (ret), "=c" (dummy), "=d" (dummy),
-+		  "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11)
-+		: "c" (arg1), "d" (arg2),
-+		  [fptr] "r" (func));
-+	return ret;
-+}
++ENTRY(x64_call1)
++	pad_stack
++	subq $32, %rsp
++	mov  %rsi, %rcx
++	call *%rdi
++	addq $32, %rsp
++	unpad_stack
++	ret
 +
-+unsigned long long x64_call3(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3)
-+{
-+	unsigned long long ret, dummy;
-+	register unsigned long long r8 __asm__("r8") = (unsigned long long)arg3;
-+	register unsigned long long r9 __asm__("r9");
-+	register unsigned long long r10 __asm__("r10");
-+	register unsigned long long r11 __asm__("r11");
-+	__asm__ __volatile__(
-+		alloc_win_stack_frame(4)
-+		"call *%[fptr]\n\t"
-+		free_win_stack_frame(4)
-+		: "=a" (ret), "=c" (dummy), "=d" (dummy),
-+		  "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11)
-+		: "c" (arg1), "d" (arg2), "r" (r8),
-+		  [fptr] "r" (func));
-+	return ret;
-+}
++ENTRY(x64_call2)
++	pad_stack
++	subq $32, %rsp
++	/* mov %rdx, %rdx */
++	mov  %rsi, %rcx
++	call *%rdi
++	addq $32, %rsp
++	unpad_stack
++	ret
 +
-+unsigned long long x64_call4(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4)
-+{
-+	unsigned long long ret, dummy;
-+	register unsigned long long r8 __asm__("r8") = (unsigned long long)arg3;
-+	register unsigned long long r9 __asm__("r9") = (unsigned long long)arg4;
-+	register unsigned long long r10 __asm__("r10");
-+	register unsigned long long r11 __asm__("r11");
-+	__asm__ __volatile__(
-+		alloc_win_stack_frame(4)
-+		"call *%[fptr]\n\t"
-+		free_win_stack_frame(4)
-+		: "=a" (ret), "=c" (dummy), "=d" (dummy),
-+		  "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11)
-+		: "c" (arg1), "d" (arg2), "r" (r8), "r" (r9),
-+		  [fptr] "r" (func));
-+	return ret;
-+}
++ENTRY(x64_call3)
++	pad_stack
++	subq $32, %rsp
++	mov  %rcx, %r8
++	/* mov %rdx, %rdx */
++	mov  %rsi, %rcx
++	call *%rdi
++	addq $32, %rsp
++	unpad_stack
++	ret
 +
-+unsigned long long x64_call5(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4,
-+	unsigned long long arg5)
-+{
-+	unsigned long long ret, dummy;
-+	register unsigned long long r8 __asm__("r8") = (unsigned long long)arg3;
-+	register unsigned long long r9 __asm__("r9") = (unsigned long long)arg4;
-+	register unsigned long long r10 __asm__("r10");
-+	register unsigned long long r11 __asm__("r11");
-+	__asm__ __volatile__(
-+		"mov %[rarg5], " lin2win_win_arg(5,6) "\n\t"
-+		alloc_win_stack_frame(6)
-+		"call *%[fptr]\n\t"
-+		free_win_stack_frame(6)
-+		: "=a" (ret), "=c" (dummy), "=d" (dummy),
-+		  "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11)
-+		: "c" (arg1), "d" (arg2), "r" (r8), "r" (r9),
-+		  [rarg5] "r" ((unsigned long long)arg5),
-+		  [fptr] "r" (func));
-+	return ret;
-+}
++ENTRY(x64_call4)
++	pad_stack
++	subq $32, %rsp
++	mov %r8, %r9
++	mov %rcx, %r8
++	/* mov %rdx, %rdx */
++	mov %rsi, %rcx
++	call *%rdi
++	addq $32, %rsp
++	unpad_stack
++	ret
 +
-+unsigned long long x64_call6(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4,
-+	unsigned long long arg5,
-+	unsigned long long arg6)
-+{
-+	unsigned long long ret, dummy;
-+	register unsigned long long r8 __asm__("r8") = (unsigned long long)arg3;
-+	register unsigned long long r9 __asm__("r9") = (unsigned long long)arg4;
-+	register unsigned long long r10 __asm__("r10");
-+	register unsigned long long r11 __asm__("r11");
-+	__asm__ __volatile__(
-+		"movq %[rarg5], " lin2win_win_arg(5,6) "\n\t"
-+		"movq %[rarg6], " lin2win_win_arg(6,6) "\n\t"
-+		alloc_win_stack_frame(6)
-+		"call *%[fptr]\n\t"
-+		free_win_stack_frame(6)
-+		: "=a" (ret), "=c" (dummy), "=d" (dummy),
-+		  "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11)
-+		: "c" (arg1), "d" (arg2), "r" (r8), "r" (r9),
-+		  [rarg5] "r" ((unsigned long long)arg5), [rarg6] "r" ((unsigned long long)arg6),
-+		  [fptr] "r" (func));
-+	return ret;
-+}
++ENTRY(x64_call5)
++	pad_stack
++	subq $48, %rsp
++	mov %r9, 32(%rsp)
++	mov %r8, %r9
++	mov %rcx, %r8
++	/* mov %rdx, %rdx */
++	mov %rsi, %rcx
++	call *%rdi
++	addq $48, %rsp
++	unpad_stack
++	ret
 +
-+unsigned long long x64_call7(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4,
-+	unsigned long long arg5,
-+	unsigned long long arg6,
-+	unsigned long long arg7)
-+{
-+	unsigned long long ret, dummy;
-+	register unsigned long long r8 __asm__("r8") = (unsigned long long)arg3;
-+	register unsigned long long r9 __asm__("r9") = (unsigned long long)arg4;
-+	register unsigned long long r10 __asm__("r10");
-+	register unsigned long long r11 __asm__("r11");
-+	__asm__ __volatile__(
-+		"movq %[rarg5], " lin2win_win_arg(5,7) "\n\t"
-+		"movq %[rarg6], " lin2win_win_arg(6,7) "\n\t"
-+		"movq %[rarg7], " lin2win_win_arg(7,7) "\n\t"
-+		alloc_win_stack_frame(7)
-+		"call *%[fptr]\n\t"
-+		free_win_stack_frame(7)
-+		: "=a" (ret), "=c" (dummy), "=d" (dummy),
-+		  "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11)
-+		: "c" (arg1), "d" (arg2), "r" (r8), "r" (r9),
-+		  [rarg5] "r" ((unsigned long long)arg5), [rarg6] "r" ((unsigned long long)arg6),
-+		  [rarg7] "r" ((unsigned long long)arg7), [fptr] "r" (func));
-+	return ret;
-+}
++ENTRY(x64_call6)
++	pad_stack
++	subq $48, %rsp
++	addq $48, %r11
++	addq %rsp, %r11
++	mov (%r11), %rax
++	mov %rax, 40(%rsp)
++	mov %r9, 32(%rsp)
++	mov %r8, %r9
++	mov %rcx, %r8
++	/* mov %rdx, %rdx */
++	mov %rsi, %rcx
++	call *%rdi
++	addq $48, %rsp
++	unpad_stack
++	ret
 +
-+unsigned long long x64_call8(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4,
-+	unsigned long long arg5,
-+	unsigned long long arg6,
-+	unsigned long long arg7,
-+	unsigned long long arg8)
-+{
-+	unsigned long long ret, dummy;
-+	register unsigned long long r8 __asm__("r8") = (unsigned long long)arg3;
-+	register unsigned long long r9 __asm__("r9") = (unsigned long long)arg4;
-+	register unsigned long long r10 __asm__("r10");
-+	register unsigned long long r11 __asm__("r11");
-+	__asm__ __volatile__(
-+		"movq %[rarg5], " lin2win_win_arg(5,8) "\n\t"
-+		"movq %[rarg6], " lin2win_win_arg(6,8) "\n\t"
-+		"movq %[rarg7], " lin2win_win_arg(7,8) "\n\t"
-+		"movq %[rarg8], " lin2win_win_arg(8,8) "\n\t"
-+		alloc_win_stack_frame(8)
-+		"call *%[fptr]\n\t"
-+		free_win_stack_frame(8)
-+		: "=a" (ret), "=c" (dummy), "=d" (dummy),
-+		  "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11)
-+		: "c" (arg1), "d" (arg2), "r" (r8), "r" (r9),
-+		  [rarg5] "r" ((unsigned long long)arg5), [rarg6] "r" ((unsigned long long)arg6),
-+		  [rarg7] "r" ((unsigned long long)arg7), [rarg8] "r" ((unsigned long long)arg8),
-+		  [fptr] "r" (func));
-+	return ret;
-+}
++ENTRY(x64_call7)
++	pad_stack
++	subq $64, %rsp
++	addq $64, %r11
++	addq $8, %r11
++	addq %rsp, %r11
++	mov (%r11), %rax
++	mov %rax, 48(%rsp)
++	subq $8, %r11
++	mov (%r11), %rax
++	mov %rax, 40(%rsp)
++	mov %r9, 32(%rsp)
++	mov %r8, %r9
++	mov %rcx, %r8
++	/* mov %rdx, %rdx */
++	mov %rsi, %rcx
++	call *%rdi
++	addq $64, %rsp
++	unpad_stack
++	ret
 +
-+unsigned long long x64_call9(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4,
-+	unsigned long long arg5,
-+	unsigned long long arg6,
-+	unsigned long long arg7,
-+	unsigned long long arg8,
-+	unsigned long long arg9)
-+{
-+	unsigned long long ret, dummy;
-+	register unsigned long long r8 __asm__("r8") = (unsigned long long)arg3;
-+	register unsigned long long r9 __asm__("r9") = (unsigned long long)arg4;
-+	register unsigned long long r10 __asm__("r10");
-+	register unsigned long long r11 __asm__("r11");
-+	__asm__ __volatile__(
-+		"movq %[rarg5], " lin2win_win_arg(5,9) "\n\t"
-+		"movq %[rarg6], " lin2win_win_arg(6,9) "\n\t"
-+		"movq %[rarg7], " lin2win_win_arg(7,9) "\n\t"
-+		"movq %[rarg8], " lin2win_win_arg(8,9) "\n\t"
-+		"movq %[rarg9], " lin2win_win_arg(9,9) "\n\t"
-+		alloc_win_stack_frame(9)
-+		"call *%[fptr]\n\t"
-+		free_win_stack_frame(9)
-+		: "=a" (ret), "=c" (dummy), "=d" (dummy),
-+		  "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11)
-+		: "c" (arg1), "d" (arg2), "r" (r8), "r" (r9),
-+		  [rarg5] "r" ((unsigned long long)arg5), [rarg6] "r" ((unsigned long long)arg6),
-+		  [rarg7] "r" ((unsigned long long)arg7), [rarg8] "r" ((unsigned long long)arg8),
-+		  [rarg9] "r" ((unsigned long long)arg9), [fptr] "r" (func));
-+	return ret;
-+}
++ENTRY(x64_call8)
++	pad_stack
++	subq $64, %rsp
++	addq $64, %r11
++	addq $16, %r11
++	addq %rsp, %r11
++	mov (%r11), %rax
++	mov %rax, 56(%rsp)
++	subq $8, %r11
++	mov (%r11), %rax
++	mov %rax, 48(%rsp)
++	subq $8, %r11
++	mov (%r11), %rax
++	mov %rax, 40(%rsp)
++	mov %r9, 32(%rsp)
++	mov %r8, %r9
++	mov %rcx, %r8
++	/* mov %rdx, %rdx */
++	mov %rsi, %rcx
++	call *%rdi
++	addq $64, %rsp
++	unpad_stack
++	ret
 +
-+unsigned long long x64_call10(
-+	void *func,
-+	unsigned long long arg1,
-+	unsigned long long arg2,
-+	unsigned long long arg3,
-+	unsigned long long arg4,
-+	unsigned long long arg5,
-+	unsigned long long arg6,
-+	unsigned long long arg7,
-+	unsigned long long arg8,
-+	unsigned long long arg9,
-+	unsigned long long arg10)
-+{
-+	unsigned long long ret, dummy;
-+	register unsigned long long r8 __asm__("r8") = (unsigned long long)arg3;
-+	register unsigned long long r9 __asm__("r9") = (unsigned long long)arg4;
-+	register unsigned long long r10 __asm__("r10");
-+	register unsigned long long r11 __asm__("r11");
-+	__asm__ __volatile__(
-+		"movq %[rarg5], " lin2win_win_arg(5,10) "\n\t"
-+		"movq %[rarg6], " lin2win_win_arg(6,10) "\n\t"
-+		"movq %[rarg7], " lin2win_win_arg(7,10) "\n\t"
-+		"movq %[rarg8], " lin2win_win_arg(8,10) "\n\t"
-+		"movq %[rarg9], " lin2win_win_arg(9,10) "\n\t"
-+		"movq %[rarg10], " lin2win_win_arg(10,10) "\n\t"
-+		alloc_win_stack_frame(10)
-+		"call *%[fptr]\n\t"
-+		free_win_stack_frame(10)
-+		: "=a" (ret), "=c" (dummy), "=d" (dummy),
-+		  "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11)
-+		: "c" (arg1), "d" (arg2), "r" (r8), "r" (r9),
-+		  [rarg5] "r" ((unsigned long long)arg5), [rarg6] "r" ((unsigned long long)arg6),
-+		  [rarg7] "r" ((unsigned long long)arg7), [rarg8] "r" ((unsigned long long)arg8),
-+		  [rarg9] "r" ((unsigned long long)arg9), [rarg10] "r" ((unsigned long long)arg10),
-+		  [fptr] "r" (func));
-+	return ret;
-+}
++ENTRY(x64_call9)
++	pad_stack
++	subq $80, %rsp
++	addq $80, %r11
++	addq $24, %r11
++	addq %rsp, %r11
++	mov (%r11), %rax
++	mov %rax, 64(%rsp)
++	subq $8, %r11
++	mov (%r11), %rax
++	mov %rax, 56(%rsp)
++	subq $8, %r11
++	mov (%r11), %rax
++	mov %rax, 48(%rsp)
++	subq $8, %r11
++	mov (%r11), %rax
++	mov %rax, 40(%rsp)
++	mov %r9, 32(%rsp)
++	mov %r8, %r9
++	mov %rcx, %r8
++	/* mov %rdx, %rdx */
++	mov %rsi, %rcx
++	call *%rdi
++	addq $80, %rsp
++	unpad_stack
++	ret
 +
++ENTRY(x64_call10)
++	pad_stack
++	subq $80, %rsp
++	addq $80, %r11
++	addq $32, %r11
++	addq %rsp, %r11
++	mov (%r11), %rax
++	mov %rax, 72(%rsp)
++	subq $8, %r11
++	mov (%r11), %rax
++	mov %rax, 64(%rsp)
++	subq $8, %r11
++	mov (%r11), %rax
++	mov %rax, 56(%rsp)
++	subq $8, %r11
++	mov (%r11), %rax
++	mov %rax, 48(%rsp)
++	subq $8, %r11
++	mov (%r11), %rax
++	mov %rax, 40(%rsp)
++	mov %r9, 32(%rsp)
++	mov %r8, %r9
++	mov %rcx, %r8
++	/* mov %rdx, %rdx */
++	mov %rsi, %rcx
++	call *%rdi
++	addq $80, %rsp
++	unpad_stack
++	ret
 diff --git a/efi/x86_64/crt0-efi.S b/efi/x86_64/crt0-efi.S
 new file mode 100644
 index 0000000..8667694
@@ -30068,18 +30349,10 @@ index 0000000..5d89f6d
 +Makefile.in
 +.deps
 diff --git a/grub/Makefile.am b/grub/Makefile.am
-index 7eb2eaa..c569174 100644
+index 7eb2eaa..d4353f7 100644
 --- a/grub/Makefile.am
 +++ b/grub/Makefile.am
-@@ -8,12 +8,12 @@ endif
- 
- AM_CPPFLAGS = -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
- 	-DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
--	-DFSYS_UFS2=1 -DFSYS_VSTAFS=1 -DFSYS_XFS=1 \
-+	-DFSYS_UFS2=1 -DFSYS_VSTAFS=1 -DFSYS_XFS=1 -DFSYS_BTRFS=1 \
- 	-DUSE_MD5_PASSWORDS=1 -DSUPPORT_HERCULES=1 \
- 	$(SERIAL_FLAGS) -I$(top_srcdir)/stage2 \
- 	-I$(top_srcdir)/stage1 -I$(top_srcdir)/lib
+@@ -15,5 +15,5 @@ AM_CPPFLAGS = -DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
  
  AM_CFLAGS = $(GRUB_CFLAGS)
  
@@ -33227,10 +33500,10 @@ index 0000000..e0480a0
 +*.a
 +*.o
 diff --git a/stage2/Makefile.am b/stage2/Makefile.am
-index f8e6d42..9dabffb 100644
+index f8e6d42..477d129 100644
 --- a/stage2/Makefile.am
 +++ b/stage2/Makefile.am
-@@ -7,59 +7,70 @@ noinst_HEADERS = apic.h defs.h dir.h disk_inode.h disk_inode_ffs.h \
+@@ -7,19 +7,23 @@ noinst_HEADERS = apic.h defs.h dir.h disk_inode.h disk_inode_ffs.h \
          fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \
  	imgact_aout.h iso9660.h jfs.h mb_header.h mb_info.h md5.h \
  	nbi.h pc_slice.h serial.h shared.h smp-imps.h term.h \
@@ -33252,14 +33525,12 @@ index f8e6d42..9dabffb 100644
  	fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \
 -	fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \
 -	terminfo.c tparm.c
-+	fsys_vstafs.c fsys_xfs.c fsys_btrfs.c  gunzip.c md5.c serial.c \
-+	sha256crypt.c sha512crypt.c stage2.c terminfo.c tparm.c graphics.c \
-+	efistubs.c
++	fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c sha256crypt.c \
++	sha512crypt.c stage2.c terminfo.c tparm.c graphics.c efistubs.c
  libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
  	-DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
  	-DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
--	-DFSYS_UFS2=1 -DFSYS_VSTAFS=1 -DFSYS_XFS=1 \
-+	-DFSYS_UFS2=1 -DFSYS_VSTAFS=1 -DFSYS_XFS=1 -DFSYS_BTRFS=1 \
+@@ -27,12 +31,14 @@ libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
  	-DUSE_MD5_PASSWORDS=1 -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1
  
  # Stage 2 and Stage 1.5's.
@@ -33274,32 +33545,18 @@ index f8e6d42..9dabffb 100644
 -pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
 +pkgdata_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
  	ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
--	reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 \
--	nbgrub pxegrub
-+	reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 \
-+	xfs_stage1_5 btrfs_stage1_5 nbgrub pxegrub
- noinst_DATA = pre_stage2 start start_eltorito nbloader pxeloader diskless
- noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \
- 	e2fs_stage1_5.exec fat_stage1_5.exec ffs_stage1_5.exec \
- 	iso9660_stage1_5.exec jfs_stage1_5.exec minix_stage1_5.exec \
+ 	reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 \
+ 	nbgrub pxegrub
+@@ -43,7 +49,7 @@ noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \
  	reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
--	xfs_stage1_5.exec nbloader.exec pxeloader.exec diskless.exec
-+	xfs_stage1_5.exec btrfs_stage1_5.exec nbloader.exec \
-+	pxeloader.exec diskless.exec
+ 	xfs_stage1_5.exec nbloader.exec pxeloader.exec diskless.exec
  else
 -pkglib_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
 +pkgdata_DATA = stage2 stage2_eltorito e2fs_stage1_5 fat_stage1_5 \
  	ffs_stage1_5 iso9660_stage1_5 jfs_stage1_5 minix_stage1_5 \
--	reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5
-+	reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5 \
-+        btrfs_stage1_5
+ 	reiserfs_stage1_5 ufs2_stage1_5 vstafs_stage1_5 xfs_stage1_5
  noinst_DATA = pre_stage2 start start_eltorito
- noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \
- 	e2fs_stage1_5.exec fat_stage1_5.exec ffs_stage1_5.exec \
- 	iso9660_stage1_5.exec jfs_stage1_5.exec minix_stage1_5.exec \
- 	reiserfs_stage1_5.exec ufs2_stage1_5.exec vstafs_stage1_5.exec \
--	xfs_stage1_5.exec
-+        xfs_stage1_5.exec btrfs_stage1_5.exec
+@@ -55,11 +61,13 @@ noinst_PROGRAMS = pre_stage2.exec start.exec start_eltorito.exec \
  endif
  MOSTLYCLEANFILES = $(noinst_PROGRAMS)
  
@@ -33318,7 +33575,7 @@ index f8e6d42..9dabffb 100644
  
  if NETBOOT_SUPPORT
  NETBOOT_FLAGS = -I$(top_srcdir)/netboot -DSUPPORT_NETBOOT=1
-@@ -79,24 +90,41 @@ else
+@@ -79,10 +87,25 @@ else
  HERCULES_FLAGS =
  endif
  
@@ -33334,8 +33591,8 @@ index f8e6d42..9dabffb 100644
 +
 +libstage2_a_SOURCES = boot.c builtins.c char_io.c cmdline.c common.c \
 +	disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \
-+	fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c \
-+	fsys_xfs.c fsys_btrfs.c gunzip.c md5.c serial.c sha256crypt.c \
++	fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \
++	fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c sha256crypt.c \
 +	sha512crypt.c stage2.c terminfo.c tparm.c efistubs.c
 +libstage2_a_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
  
@@ -33346,14 +33603,13 @@ index f8e6d42..9dabffb 100644
  STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
  
  # For stage2 target.
- pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c char_io.c \
+@@ -90,13 +113,15 @@ pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c char_io.c \
  	cmdline.c common.c console.c disk_io.c fsys_ext2fs.c \
  	fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \
--	fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \
+ 	fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \
 -	hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c
-+	fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c fsys_btrfs.c \
-+	gunzip.c hercules.c md5.c serial.c smp-imps.c sha256crypt.c \
-+	sha512crypt.c stage2.c terminfo.c tparm.c graphics.c
++	hercules.c md5.c serial.c smp-imps.c sha256crypt.c sha512crypt.c \
++	stage2.c terminfo.c tparm.c graphics.c
  pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
  pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
  pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
@@ -33365,7 +33621,7 @@ index f8e6d42..9dabffb 100644
  endif
  
  if DISKLESS_SUPPORT
-@@ -105,7 +133,7 @@ else
+@@ -105,7 +130,7 @@ else
  BUILT_SOURCES = stage2_size.h
  endif
  
@@ -33374,7 +33630,7 @@ index f8e6d42..9dabffb 100644
  
  stage2_size.h: pre_stage2
  	-rm -f stage2_size.h
-@@ -115,6 +143,7 @@ stage2_size.h: pre_stage2
+@@ -115,6 +140,7 @@ stage2_size.h: pre_stage2
  start_exec_SOURCES = start.S
  start_exec_CCASFLAGS = $(STAGE2_COMPILE)
  start_exec_LDFLAGS = $(START_LINK)
@@ -33382,7 +33638,7 @@ index f8e6d42..9dabffb 100644
  
  # XXX: automake doesn't provide a way to specify dependencies for object
  # files explicitly, so we must write this by a general Makefile scheme.
-@@ -129,6 +158,7 @@ stage2: pre_stage2 start
+@@ -129,6 +155,7 @@ stage2: pre_stage2 start
  start_eltorito_exec_SOURCES = start_eltorito.S
  start_eltorito_exec_CCASFLAGS = $(STAGE2_COMPILE)
  start_eltorito_exec_LDFLAGS = $(START_ELTORITO_LINK)
@@ -33390,7 +33646,7 @@ index f8e6d42..9dabffb 100644
  
  start_eltorito_exec-start.$(OBJEXT): stage2_size.h
  
-@@ -144,6 +174,7 @@ e2fs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_EXT2FS=1 \
+@@ -144,6 +171,7 @@ e2fs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_EXT2FS=1 \
  e2fs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_EXT2FS=1 \
  	-DNO_BLOCK_FILES=1
  e2fs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
@@ -33398,7 +33654,7 @@ index f8e6d42..9dabffb 100644
  
  # For fat_stage1_5 target.
  fat_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
-@@ -153,6 +184,7 @@ fat_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FAT=1 \
+@@ -153,6 +181,7 @@ fat_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FAT=1 \
  fat_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FAT=1 \
  	-DNO_BLOCK_FILES=1
  fat_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
@@ -33406,7 +33662,7 @@ index f8e6d42..9dabffb 100644
  
  # For ffs_stage1_5 target.
  ffs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
-@@ -162,6 +194,7 @@ ffs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FFS=1 \
+@@ -162,6 +191,7 @@ ffs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FFS=1 \
  ffs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_FFS=1 \
  	-DNO_BLOCK_FILES=1
  ffs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
@@ -33414,7 +33670,7 @@ index f8e6d42..9dabffb 100644
  
  # For ufs2_stage1_5 target.
  ufs2_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
-@@ -171,6 +204,7 @@ ufs2_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_UFS2=1 \
+@@ -171,6 +201,7 @@ ufs2_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_UFS2=1 \
  ufs2_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_UFS2=1 \
  	-DNO_BLOCK_FILES=1
  ufs2_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
@@ -33422,7 +33678,7 @@ index f8e6d42..9dabffb 100644
  
  # For minix_stage1_5 target.
  minix_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c disk_io.c \
-@@ -180,6 +214,7 @@ minix_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_MINIX=1 \
+@@ -180,6 +211,7 @@ minix_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_MINIX=1 \
  minix_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_MINIX=1 \
  	-DNO_BLOCK_FILES=1
  minix_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
@@ -33430,7 +33686,7 @@ index f8e6d42..9dabffb 100644
  
  # For reiserfs_stage1_5 target.
  reiserfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
-@@ -189,6 +224,7 @@ reiserfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_REISERFS=1 \
+@@ -189,6 +221,7 @@ reiserfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_REISERFS=1 \
  reiserfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_REISERFS=1 \
  	-DNO_BLOCK_FILES=1
  reiserfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
@@ -33438,7 +33694,7 @@ index f8e6d42..9dabffb 100644
  
  # For vstafs_stage1_5 target.
  vstafs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
-@@ -198,6 +234,7 @@ vstafs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_VSTAFS=1 \
+@@ -198,6 +231,7 @@ vstafs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_VSTAFS=1 \
  vstafs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_VSTAFS=1 \
  	-DNO_BLOCK_FILES=1
  vstafs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
@@ -33446,7 +33702,7 @@ index f8e6d42..9dabffb 100644
  
  # For jfs_stage1_5 target.
  jfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
-@@ -207,6 +244,7 @@ jfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_JFS=1 \
+@@ -207,6 +241,7 @@ jfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_JFS=1 \
  jfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_JFS=1 \
  	-DNO_BLOCK_FILES=1
  jfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
@@ -33454,25 +33710,15 @@ index f8e6d42..9dabffb 100644
  
  # For xfs_stage1_5 target.
  xfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
-@@ -216,6 +254,17 @@ xfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_XFS=1 \
+@@ -216,6 +251,7 @@ xfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_XFS=1 \
  xfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_XFS=1 \
  	-DNO_BLOCK_FILES=1
  xfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
 +xfs_stage1_5_exec_LDADD = @LIBGCC@
-+
-+# For btrfs_stage1_5 target.
-+btrfs_stage1_5_exec_SOURCES = start.S asm.S common.c char_io.c \
-+	disk_io.c stage1_5.c fsys_btrfs.c bios.c
-+btrfs_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_BTRFS=1 \
-+	-DNO_BLOCK_FILES=1
-+btrfs_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_BTRFS=1 \
-+	-DNO_BLOCK_FILES=1
-+btrfs_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
-+btrfs_stage1_5_exec_LDADD = @LIBGCC@
  
  # For iso9660_stage1_5 target.
  iso9660_stage1_5_exec_SOURCES = start_eltorito.S asm.S common.c char_io.c \
-@@ -225,6 +274,7 @@ iso9660_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_ISO9660=1 \
+@@ -225,6 +261,7 @@ iso9660_stage1_5_exec_CFLAGS = $(STAGE1_5_COMPILE) -DFSYS_ISO9660=1 \
  iso9660_stage1_5_exec_CCASFLAGS = $(STAGE1_5_COMPILE) -DFSYS_ISO9660=1 \
  	-DNO_BLOCK_FILES=1
  iso9660_stage1_5_exec_LDFLAGS = $(STAGE1_5_LINK)
@@ -33480,7 +33726,7 @@ index f8e6d42..9dabffb 100644
  
  # For diskless target.
  diskless_exec_SOURCES = $(pre_stage2_exec_SOURCES)
-@@ -233,7 +283,7 @@ diskless_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) \
+@@ -233,7 +270,7 @@ diskless_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) \
  diskless_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) \
  	-DSUPPORT_DISKLESS=1
  diskless_exec_LDFLAGS = $(PRE_STAGE2_LINK)
@@ -33489,7 +33735,7 @@ index f8e6d42..9dabffb 100644
  
  diskless_size.h: diskless
  	-rm -f $@
-@@ -270,3 +320,5 @@ pxegrub: pxeloader diskless
+@@ -270,3 +307,5 @@ pxegrub: pxeloader diskless
  SUFFIXES = .exec
  .exec:
  	$(OBJCOPY) -O binary $< $@
@@ -37888,1428 +38134,8 @@ index 4185d23..e30daf8 100644
  }
 +#endif
 +
-diff --git a/stage2/btrfs.h b/stage2/btrfs.h
-new file mode 100644
-index 0000000..79d879e
---- /dev/null
-+++ b/stage2/btrfs.h
-@@ -0,0 +1,1414 @@
-+/* btrfs.h - an extraction from btrfs-progs-0.18/ctree.h into one file
-+ *
-+ * Copyright (C) 2007 Oracle.  All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU General Public
-+ * License v2 as published by the Free Software Foundation.
-+ *
-+ * 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., 59 Temple Place - Suite 330,
-+ * Boston, MA 021110-1307, USA.
-+ */
-+
-+/* include/asm-i386/types.h */
-+
-+typedef __signed__ char __s8;
-+typedef unsigned char __u8;
-+typedef __signed__ short __s16;
-+typedef unsigned short __u16;
-+typedef __signed__ int __s32;
-+typedef unsigned int __u32;
-+typedef unsigned long long __u64;
-+typedef __signed__ long long __s64;
-+
-+typedef __s8 s8;
-+typedef __u8 u8;
-+typedef __u16 u16;
-+typedef __u32 u32;
-+typedef __u64 u64;
-+typedef __s64 s64;
-+
-+#define __bitwise
-+
-+typedef u16 __bitwise __le16;
-+typedef u32 __bitwise __le32;
-+typedef u64 __bitwise __le64;
-+
-+/* linux/posix_type.h */
-+typedef long linux_off_t;
-+
-+/* linux/little_endian.h */
-+#define cpu_to_le64(x) ((__u64) (x))
-+#define le64_to_cpu(x) ((__u64) (x))
-+#define cpu_to_le32(x) ((__u32) (x))
-+#define le32_to_cpu(x) ((__u32) (x))
-+#define cpu_to_le16(x) ((__u16) (x))
-+#define le16_to_cpu(x) ((__u16) (x))
-+#define le8_to_cpu(x) ((__u8) (x))
-+#define cpu_to_le8(x) ((__u8) (x))
-+
-+/* linux/stat.h */
-+#define S_IFMT  00170000
-+#define S_IFLNK  0120000
-+#define S_IFREG  0100000
-+#define S_IFDIR  0040000
-+#define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)
-+#define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
-+#define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
-+
-+struct btrfs_root;
-+#define BTRFS_MAGIC "_BHRfS_M"
-+
-+#define BTRFS_SUPER_INFO_OFFSET (64 * 1024)
-+#define BTRFS_SUPER_INFO_SIZE 4096
-+
-+#define BTRFS_SUPER_MIRROR_MAX	 3
-+#define BTRFS_SUPER_MIRROR_SHIFT 12
-+
-+#define PATH_MAX                1024	/* include/linux/limits.h */
-+#define MAX_LINK_COUNT             5	/* number of symbolic links
-+					   to follow */
-+#define BTRFS_MAX_LEVEL 8
-+#define BTRFS_ROOT_TREE_OBJECTID 1ULL
-+#define BTRFS_EXTENT_TREE_OBJECTID 2ULL
-+#define BTRFS_CHUNK_TREE_OBJECTID 3ULL
-+#define BTRFS_DEV_TREE_OBJECTID 4ULL
-+#define BTRFS_FS_TREE_OBJECTID 5ULL
-+#define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL
-+#define BTRFS_CSUM_TREE_OBJECTID 7ULL
-+
-+#define BTRFS_ORPHAN_OBJECTID -5ULL
-+#define BTRFS_TREE_LOG_OBJECTID -6ULL
-+#define BTRFS_TREE_LOG_FIXUP_OBJECTID -7ULL
-+#define BTRFS_TREE_RELOC_OBJECTID -8ULL
-+#define BTRFS_DATA_RELOC_TREE_OBJECTID -9ULL
-+#define BTRFS_EXTENT_CSUM_OBJECTID -10ULL
-+
-+#define BTRFS_MULTIPLE_OBJECTIDS -255ULL
-+#define BTRFS_FIRST_FREE_OBJECTID 256ULL
-+#define BTRFS_LAST_FREE_OBJECTID -256ULL
-+#define BTRFS_FIRST_CHUNK_TREE_OBJECTID 256ULL
-+#define BTRFS_DEV_ITEMS_OBJECTID 1ULL
-+
-+
-+#define BTRFS_NAME_LEN 255
-+#define BTRFS_CSUM_SIZE 32
-+#define BTRFS_CSUM_TYPE_CRC32	0
-+
-+static int btrfs_csum_sizes[] = { 4, 0 };
-+
-+/* four bytes for CRC32 */
-+#define BTRFS_CRC32_SIZE 4
-+#define BTRFS_EMPTY_DIR_SIZE 0
-+
-+#define BTRFS_FT_UNKNOWN	0
-+#define BTRFS_FT_REG_FILE	1
-+#define BTRFS_FT_DIR		2
-+#define BTRFS_FT_CHRDEV		3
-+#define BTRFS_FT_BLKDEV		4
-+#define BTRFS_FT_FIFO		5
-+#define BTRFS_FT_SOCK		6
-+#define BTRFS_FT_SYMLINK	7
-+#define BTRFS_FT_XATTR		8
-+#define BTRFS_FT_MAX		9
-+
-+#define BTRFS_UUID_SIZE 16
-+
-+#define BTRFS_DEFAULT_NUM_DEVICES     1
-+#define BTRFS_DEFAULT_NODE_SIZE       4096
-+#define BTRFS_DEFAULT_LEAF_SIZE       4096
-+#define BTRFS_NUM_CACHED_DEVICES      128
-+
-+#define WARN_ON(c)
-+#define cassert(cond) ({ switch (-1) { case (cond): case 0: break; } })
-+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-+
-+#define offsetof(type, memb) \
-+	((unsigned long)(&((type *)0)->memb))
-+
-+struct btrfs_disk_key {
-+	__le64 objectid;
-+	u8 type;
-+	__le64 offset;
-+} __attribute__ ((__packed__));
-+
-+/* cpu key */
-+struct btrfs_key {
-+	u64 objectid;
-+	u8 type;
-+	u64 offset;
-+} __attribute__ ((__packed__));
-+
-+/* this represents a divice in a chunk tree */
-+struct btrfs_dev_item {
-+	__le64 devid; /* internal device id */
-+	__le64 total_bytes; /* size of the device */
-+	__le64 bytes_used;
-+	__le32 io_align; /* optimal io alignment */
-+	__le32 io_width; /* optimal io width */
-+	__le32 sector_size; /* minimal io size */
-+	__le64 type; /* type and info about this device */
-+	__le64 generation; /* expected generation */
-+        __le64 start_offset; /* of the partition on a device */
-+
-+	/* info for allocation decisions */
-+	__le32 dev_group;
-+
-+        u8 seek_speed; /* 0-100 (100 is fastest) */
-+	u8 bandwidth;  /* 0-100 (100 is fastest) */
-+
-+        u8 uuid[BTRFS_UUID_SIZE]; /* dev uuid generated by btrfs */
-+	u8 fsid[BTRFS_UUID_SIZE]; /* uuid of the host FS */
-+} __attribute__ ((__packed__));
-+
-+struct btrfs_stripe {
-+	__le64 devid;
-+	__le64 offset;
-+	u8 dev_uuid[BTRFS_UUID_SIZE];
-+} __attribute__ ((__packed__));
-+
-+struct btrfs_chunk {
-+	/* size of this chunk in bytes */
-+	__le64 length;
-+	__le64 owner; /* objectid of the root referincing this chunk */
-+	__le64 stripe_len;
-+	__le64 type;
-+	__le32 io_align; /* optimal io alignment for this chunk */
-+	__le32 io_width; /* optimal io width for this chunk */
-+	__le32 sector_size; /* minimal io size for this chunk */
-+	__le16 num_stripes;
-+	__le16 sub_stripes; /* sub stripes (for raid10) */
-+	struct btrfs_stripe stripe;
-+} __attribute__ ((__packed__));
-+
-+static inline unsigned long btrfs_chunk_item_size(int num_stripes)
-+{
-+	return sizeof(struct btrfs_chunk) +
-+		sizeof(struct btrfs_stripe) * (num_stripes - 1);
-+}
-+
-+#define BTRFS_FSID_SIZE 16
-+#define BTRFS_HEADER_FLAG_WRITTEN (1 << 0)
-+
-+struct btrfs_header {
-+	/* these first four must match the super block */
-+	u8 csum[BTRFS_CSUM_SIZE];
-+	u8 fsid[BTRFS_FSID_SIZE]; /* uuid of the host fs */
-+	__le64 bytenr; /* which block this node is supposed to live in */
-+	__le64 flags;
-+
-+	/* allowed to be different from the super from here on down */
-+	u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
-+	__le64 generation;
-+	__le64 owner;
-+	__le32 nritems;
-+	u8 level;
-+} __attribute__ ((__packed__));
-+
-+#define BTRFS_NODEPTRS_PER_BLOCK(r) (((r)->nodesize - \
-+			        sizeof(struct btrfs_header)) / \
-+			        sizeof(struct btrfs_key_ptr))
-+#define __BTRFS_LEAF_DATA_SIZE(bs) ((bs) - sizeof(struct btrfs_header))
-+#define BTRFS_LEAF_DATA_SIZE(r) (__BTRFS_LEAF_DATA_SIZE(r->leafsize))
-+#define BTRFS_MAX_INLINE_DATA_SIZE(r) (BTRFS_LEAF_DATA_SIZE(r) - \
-+					sizeof(struct btrfs_item) - \
-+					sizeof(struct btrfs_file_extent_item))
-+
-+#define BTRFS_SUPER_FLAG_SEEDING	(1ULL << 32)
-+#define BTRFS_SUPER_FLAG_METADUMP	(1ULL << 33)
-+
-+/*
-+ * a portion of superblock which is used
-+ * for chunk translation (up to 14 chunks
-+ * with 3 stripes each.
-+ */
-+#define BTRFS_SYSTEM_CHUNK_ARRAY_SIZE 2048
-+#define BTRFS_LABEL_SIZE 256
-+
-+/*
-+ * the super block basically lists the main trees of the FS
-+ * it currently lacks any block count etc etc
-+ */
-+struct btrfs_super_block {
-+	u8 csum[BTRFS_CSUM_SIZE];
-+	/* the first 3 fields must match struct btrfs_header */
-+	u8 fsid[BTRFS_FSID_SIZE];    /* FS specific uuid */
-+	__le64 bytenr; /* this block number */
-+	__le64 flags;
-+
-+	/* allowed to be different from the btrfs_header from here own down */
-+	__le64 magic;
-+	__le64 generation;
-+	__le64 root;        /* tree root */
-+	__le64 chunk_root;
-+	__le64 log_root;
-+
-+	/* this will help find the new super based on the log root */
-+	__le64 log_root_transid;
-+	__le64 total_bytes;
-+	__le64 bytes_used;
-+	__le64 root_dir_objectid;
-+	__le64 num_devices;
-+	__le32 sectorsize;
-+	__le32 nodesize;
-+	__le32 leafsize;
-+	__le32 stripesize;
-+	__le32 sys_chunk_array_size;
-+	__le64 chunk_root_generation;
-+	__le64 compat_flags;
-+	__le64 compat_ro_flags;
-+	__le64 incompat_flags;
-+	__le16 csum_type;
-+	u8 root_level;
-+	u8 chunk_root_level;
-+	u8 log_root_level;
-+	struct btrfs_dev_item dev_item;
-+
-+	char label[BTRFS_LABEL_SIZE];
-+
-+	/* future expansion */
-+	__le64 reserved[32];
-+	u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
-+} __attribute__ ((__packed__));
-+
-+/*
-+ * Compat flags that we support.  If any incompat flags are set other than the
-+ * ones specified below then we will fail to mount
-+ */
-+#define BTRFS_FEATURE_COMPAT_SUPP	0x0
-+#define BTRFS_FEATURE_COMPAT_RO_SUPP	0x0
-+#define BTRFS_FEATURE_INCOMPAT_SUPP	0x0
-+
-+/* Item header for per-leaf lookup */
-+struct btrfs_item {
-+	struct btrfs_disk_key key;
-+	__le32 offset;
-+	__le32 size;
-+} __attribute__ ((__packed__));
-+
-+/*
-+ * Format of the leaves:
-+ * [item0, item1....itemN] [free space] [dataN...data1, data0]
-+ */
-+struct btrfs_leaf {
-+	struct btrfs_header header;
-+	struct btrfs_item items[];
-+} __attribute__ ((__packed__));
-+
-+/*
-+ * keys-pointers pairs for per-node (non-leaf) lookup
-+ */
-+struct btrfs_key_ptr {
-+	struct btrfs_disk_key key;
-+	__le64 blockptr;
-+	__le64 generation;
-+} __attribute__ ((__packed__));
-+
-+struct btrfs_node {
-+	struct btrfs_header header;
-+	struct btrfs_key_ptr ptrs[];
-+} __attribute__ ((__packed__));
-+
-+struct btrfs_device {
-+	/* the internal btrfs device id */
-+	u64 devid;
-+	/* the internal grub device representation */
-+	unsigned long drive;
-+	unsigned long part;
-+	unsigned long length;
-+};
-+
-+struct extent_buffer {
-+	/* metadata */
-+	struct btrfs_device dev;
-+	u64 start;
-+	u64 dev_bytenr;
-+	u32 len;
-+	/* data */
-+	char *data;
-+};
-+
-+static inline void read_extent_buffer(struct extent_buffer *eb,
-+				      void *dst, unsigned long start,
-+				      unsigned long len)
-+{
-+	memcpy(dst, eb->data + start, len);
-+}
-+
-+static inline void write_extent_buffer(struct extent_buffer *eb,
-+				       const void *src, unsigned long start,
-+				       unsigned long len)
-+{
-+	memcpy(eb->data + start, src, len);
-+}
-+
-+/*
-+ * NOTE:
-+ * don't increase a number of levels for grub-0.97!
-+ */
-+typedef enum {
-+	FIRST_EXTERNAL_LOOKUP_POOL,
-+	SECOND_EXTERNAL_LOOKUP_POOL,
-+	INTERNAL_LOOKUP_POOL,
-+	LAST_LOOKUP_POOL
-+} lookup_pool_id;
-+
-+/*             Relationship between lookup pools:
-+ *  depth
-+ *
-+ *    ^             +----> INTERNAL <----+
-+ *    |             |                    |
-+ *    |             |                    |
-+ *    -        FIRST_EXTERNAL     SECOND_EXTERNAL
-+ */
-+
-+struct btrfs_path {
-+	lookup_pool_id lpid;
-+	struct extent_buffer nodes[BTRFS_MAX_LEVEL];
-+	int slots[BTRFS_MAX_LEVEL];
-+};
-+
-+/*
-+ * items in the extent btree are used to record the objectid of the
-+ * owner of the block and the number of references
-+ */
-+struct btrfs_extent_item {
-+	__le32 refs;
-+} __attribute__ ((__packed__));
-+
-+struct btrfs_extent_ref {
-+	__le64 root;
-+	__le64 generation;
-+	__le64 objectid;
-+	__le32 num_refs;
-+} __attribute__ ((__packed__));
-+
-+/* dev extents record free space on individual devices.  The owner
-+ * field points back to the chunk allocation mapping tree that allocated
-+ * the extent.  The chunk tree uuid field is a way to double check the owner
-+ */
-+struct btrfs_dev_extent {
-+	__le64 chunk_tree;
-+	__le64 chunk_objectid;
-+	__le64 chunk_offset;
-+	__le64 length;
-+	u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
-+} __attribute__ ((__packed__));
-+
-+struct btrfs_inode_ref {
-+	__le64 index;
-+	__le16 name_len;
-+	/* name goes here */
-+} __attribute__ ((__packed__));
-+
-+struct btrfs_timespec {
-+	__le64 sec;
-+	__le32 nsec;
-+} __attribute__ ((__packed__));
-+
-+typedef enum {
-+	BTRFS_COMPRESS_NONE = 0,
-+	BTRFS_COMPRESS_ZLIB = 1,
-+	BTRFS_COMPRESS_LAST = 2,
-+} btrfs_compression_type;
-+
-+/* we don't understand any encryption methods right now */
-+typedef enum {
-+	BTRFS_ENCRYPTION_NONE = 0,
-+	BTRFS_ENCRYPTION_LAST = 1,
-+} btrfs_encryption_type;
-+
-+struct btrfs_inode_item {
-+	/* nfs style generation number */
-+	__le64 generation;
-+	/* transid that last touched this inode */
-+	__le64 transid;
-+	__le64 size;
-+	__le64 nbytes;
-+	__le64 block_group;
-+	__le32 nlink;
-+	__le32 uid;
-+	__le32 gid;
-+	__le32 mode;
-+	__le64 rdev;
-+	__le64 flags;
-+
-+	/* modification sequence number for NFS */
-+	__le64 sequence;
-+
-+	/*
-+	 * a little future expansion, for more than this we can
-+	 * just grow the inode item and version it
-+	 */
-+	__le64 reserved[4];
-+	struct btrfs_timespec atime;
-+	struct btrfs_timespec ctime;
-+	struct btrfs_timespec mtime;
-+	struct btrfs_timespec otime;
-+} __attribute__ ((__packed__));
-+
-+struct btrfs_dir_item {
-+	struct btrfs_disk_key location;
-+	__le64 transid;
-+	__le16 data_len;
-+	__le16 name_len;
-+	u8 type;
-+} __attribute__ ((__packed__));
-+
-+struct btrfs_root_item {
-+	struct btrfs_inode_item inode;
-+	__le64 generation;
-+	__le64 root_dirid;
-+	__le64 bytenr;
-+	__le64 byte_limit;
-+	__le64 bytes_used;
-+	__le64 last_snapshot;
-+	__le64 flags;
-+	__le32 refs;
-+	struct btrfs_disk_key drop_progress;
-+	u8 drop_level;
-+	u8 level;
-+} __attribute__ ((__packed__));
-+
-+/*
-+ * this is used for both forward and backward root refs
-+ */
-+struct btrfs_root_ref {
-+	__le64 dirid;
-+	__le64 sequence;
-+	__le16 name_len;
-+} __attribute__ ((__packed__));
-+
-+#define BTRFS_FILE_EXTENT_INLINE 0
-+#define BTRFS_FILE_EXTENT_REG 1
-+#define BTRFS_FILE_EXTENT_PREALLOC 2
-+
-+struct btrfs_file_extent_item {
-+	/*
-+	 * transaction id that created this extent
-+	 */
-+	__le64 generation;
-+	/*
-+	 * max number of bytes to hold this extent in ram
-+	 * when we split a compressed extent we can't know how big
-+	 * each of the resulting pieces will be.  So, this is
-+	 * an upper limit on the size of the extent in ram instead of
-+	 * an exact limit.
-+	 */
-+	__le64 ram_bytes;
-+
-+	/*
-+	 * 32 bits for the various ways we might encode the data,
-+	 * including compression and encryption.  If any of these
-+	 * are set to something a given disk format doesn't understand
-+	 * it is treated like an incompat flag for reading and writing,
-+	 * but not for stat.
-+	 */
-+	u8 compression;
-+	u8 encryption;
-+	__le16 other_encoding; /* spare for later use */
-+
-+	/* are we inline data or a real extent? */
-+	u8 type;
-+
-+	/*
-+	 * disk space consumed by the extent, checksum blocks are included
-+	 * in these numbers
-+	 */
-+	__le64 disk_bytenr;
-+	__le64 disk_num_bytes;
-+	/*
-+	 * the logical offset in file blocks (no csums)
-+	 * this extent record is for.  This allows a file extent to point
-+	 * into the middle of an existing extent on disk, sharing it
-+	 * between two snapshots (useful if some bytes in the middle of the
-+	 * extent have changed
-+	 */
-+	__le64 offset;
-+	/*
-+	 * the logical number of file blocks (no csums included)
-+	 */
-+	__le64 num_bytes;
-+
-+} __attribute__ ((__packed__));
-+
-+struct btrfs_csum_item {
-+	u8 csum;
-+} __attribute__ ((__packed__));
-+
-+/* tag for the radix tree of block groups in ram */
-+#define BTRFS_BLOCK_GROUP_DATA     (1 << 0)
-+#define BTRFS_BLOCK_GROUP_SYSTEM   (1 << 1)
-+#define BTRFS_BLOCK_GROUP_METADATA (1 << 2)
-+#define BTRFS_BLOCK_GROUP_RAID0    (1 << 3)
-+#define BTRFS_BLOCK_GROUP_RAID1    (1 << 4)
-+#define BTRFS_BLOCK_GROUP_DUP	   (1 << 5)
-+#define BTRFS_BLOCK_GROUP_RAID10   (1 << 6)
-+
-+struct btrfs_block_group_item {
-+	__le64 used;
-+	__le64 chunk_objectid;
-+	__le64 flags;
-+} __attribute__ ((__packed__));
-+
-+/*
-+ * in ram representation of the tree.  extent_root is used for all allocations
-+ * and for the extent tree extent_root root.
-+ */
-+struct btrfs_root {
-+	struct extent_buffer   node;
-+	char                   data[4096];
-+	struct btrfs_root_item root_item;
-+	u64 objectid;
-+
-+	/* data allocations are done in sectorsize units */
-+	u32 sectorsize;
-+
-+	/* node allocations are done in nodesize units */
-+	u32 nodesize;
-+
-+	/* leaf allocations are done in leafsize units */
-+	u32 leafsize;
-+
-+	/* leaf allocations are done in leafsize units */
-+	u32 stripesize;
-+};
-+
-+struct btrfs_file_info {
-+	struct btrfs_key key;
-+};
-+
-+struct btrfs_root;
-+struct btrfs_fs_devices;
-+struct btrfs_fs_info {
-+	u8 fsid[BTRFS_FSID_SIZE];
-+	struct btrfs_root fs_root;
-+	struct btrfs_root tree_root;
-+	struct btrfs_root chunk_root;
-+
-+	struct btrfs_file_info file_info; /* currently opened file */
-+	struct btrfs_path paths [LAST_LOOKUP_POOL];
-+
-+	char mbr[SECTOR_SIZE];
-+
-+	int sb_mirror;
-+	u64 sb_transid;
-+	struct btrfs_device sb_dev;
-+   	struct btrfs_super_block sb_copy;
-+
-+	struct btrfs_device devices[BTRFS_NUM_CACHED_DEVICES + 1];
-+};
-+
-+/*
-+ * inode items have the data typically returned from stat and store other
-+ * info about object characteristics.  There is one for every file and dir in
-+ * the FS
-+ */
-+#define BTRFS_INODE_ITEM_KEY		1
-+#define BTRFS_INODE_REF_KEY		12
-+#define BTRFS_XATTR_ITEM_KEY		24
-+#define BTRFS_ORPHAN_ITEM_KEY		48
-+
-+#define BTRFS_DIR_LOG_ITEM_KEY  60
-+#define BTRFS_DIR_LOG_INDEX_KEY 72
-+/*
-+ * dir items are the name -> inode pointers in a directory.  There is one
-+ * for every name in a directory.
-+ */
-+#define BTRFS_DIR_ITEM_KEY	84
-+#define BTRFS_DIR_INDEX_KEY	96
-+
-+/*
-+ * extent data is for file data
-+ */
-+#define BTRFS_EXTENT_DATA_KEY	108
-+
-+/*
-+ * csum items have the checksums for data in the extents
-+ */
-+#define BTRFS_CSUM_ITEM_KEY	120
-+/*
-+ * extent csums are stored in a separate tree and hold csums for
-+ * an entire extent on disk.
-+ */
-+#define BTRFS_EXTENT_CSUM_KEY	128
-+
-+/*
-+ * root items point to tree roots.  There are typically in the root
-+ * tree used by the super block to find all the other trees
-+ */
-+#define BTRFS_ROOT_ITEM_KEY	132
-+
-+/*
-+ * root backrefs tie subvols and snapshots to the directory entries that
-+ * reference them
-+ */
-+#define BTRFS_ROOT_BACKREF_KEY	144
-+
-+/*
-+ * root refs make a fast index for listing all of the snapshots and
-+ * subvolumes referenced by a given root.  They point directly to the
-+ * directory item in the root that references the subvol
-+ */
-+#define BTRFS_ROOT_REF_KEY	156
-+
-+/*
-+ * extent items are in the extent map tree.  These record which blocks
-+ * are used, and how many references there are to each block
-+ */
-+#define BTRFS_EXTENT_ITEM_KEY	168
-+#define BTRFS_EXTENT_REF_KEY	180
-+
-+/*
-+ * block groups give us hints into the extent allocation trees.  Which
-+ * blocks are free etc etc
-+ */
-+#define BTRFS_BLOCK_GROUP_ITEM_KEY 192
-+
-+#define BTRFS_DEV_EXTENT_KEY	204
-+#define BTRFS_DEV_ITEM_KEY	216
-+#define BTRFS_CHUNK_ITEM_KEY	228
-+
-+/*
-+ * string items are for debugging.  They just store a short string of
-+ * data in the FS
-+ */
-+#define BTRFS_STRING_ITEM_KEY	253
-+/*
-+ * Inode flags
-+ */
-+#define BTRFS_INODE_NODATASUM		(1 << 0)
-+#define BTRFS_INODE_NODATACOW		(1 << 1)
-+#define BTRFS_INODE_READONLY		(1 << 2)
-+
-+#define read_eb_member(eb, ptr, type, member, result) (			\
-+	read_extent_buffer(eb, (char *)(result),			\
-+			   ((unsigned long)(ptr)) +			\
-+			    offsetof(type, member),			\
-+			   sizeof(((type *)0)->member)))
-+
-+#define BTRFS_SETGET_HEADER_FUNCS(name, type, member, bits)		\
-+static inline u##bits btrfs_##name(struct extent_buffer *eb)		\
-+{									\
-+	struct btrfs_header *h = (struct btrfs_header *)eb->data;	\
-+	return le##bits##_to_cpu(h->member);				\
-+}									\
-+static inline void btrfs_set_##name(struct extent_buffer *eb,		\
-+				    u##bits val)			\
-+{									\
-+	struct btrfs_header *h = (struct btrfs_header *)eb->data;	\
-+	h->member = cpu_to_le##bits(val);				\
-+}
-+
-+#define BTRFS_SETGET_FUNCS(name, type, member, bits)			\
-+static inline u##bits btrfs_##name(struct extent_buffer *eb,		\
-+				   type *s)				\
-+{									\
-+	unsigned long offset = (unsigned long)s;			\
-+	type *p = (type *) (eb->data + offset);				\
-+	return le##bits##_to_cpu(p->member);				\
-+}									\
-+static inline void btrfs_set_##name(struct extent_buffer *eb,		\
-+				    type *s, u##bits val)		\
-+{									\
-+	unsigned long offset = (unsigned long)s;			\
-+	type *p = (type *) (eb->data + offset);				\
-+	p->member = cpu_to_le##bits(val);				\
-+}
-+
-+#define BTRFS_SETGET_STACK_FUNCS(name, type, member, bits)		\
-+static inline u##bits btrfs_##name(type *s)				\
-+{									\
-+	return le##bits##_to_cpu(s->member);				\
-+}									\
-+static inline void btrfs_set_##name(type *s, u##bits val)		\
-+{									\
-+	s->member = cpu_to_le##bits(val);				\
-+}
-+
-+BTRFS_SETGET_FUNCS(device_type, struct btrfs_dev_item, type, 64);
-+BTRFS_SETGET_FUNCS(device_total_bytes, struct btrfs_dev_item, total_bytes, 64);
-+BTRFS_SETGET_FUNCS(device_bytes_used, struct btrfs_dev_item, bytes_used, 64);
-+BTRFS_SETGET_FUNCS(device_io_align, struct btrfs_dev_item, io_align, 32);
-+BTRFS_SETGET_FUNCS(device_io_width, struct btrfs_dev_item, io_width, 32);
-+BTRFS_SETGET_FUNCS(device_start_offset, struct btrfs_dev_item,
-+		   start_offset, 64);
-+BTRFS_SETGET_FUNCS(device_sector_size, struct btrfs_dev_item, sector_size, 32);
-+BTRFS_SETGET_FUNCS(device_id, struct btrfs_dev_item, devid, 64);
-+BTRFS_SETGET_FUNCS(device_group, struct btrfs_dev_item, dev_group, 32);
-+BTRFS_SETGET_FUNCS(device_seek_speed, struct btrfs_dev_item, seek_speed, 8);
-+BTRFS_SETGET_FUNCS(device_bandwidth, struct btrfs_dev_item, bandwidth, 8);
-+BTRFS_SETGET_FUNCS(device_generation, struct btrfs_dev_item, generation, 64);
-+
-+BTRFS_SETGET_STACK_FUNCS(stack_device_type, struct btrfs_dev_item, type, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_device_total_bytes, struct btrfs_dev_item,
-+			 total_bytes, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_device_bytes_used, struct btrfs_dev_item,
-+			 bytes_used, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_device_io_align, struct btrfs_dev_item,
-+			 io_align, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_device_io_width, struct btrfs_dev_item,
-+			 io_width, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_device_sector_size, struct btrfs_dev_item,
-+			 sector_size, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_device_id, struct btrfs_dev_item, devid, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_device_group, struct btrfs_dev_item,
-+			 dev_group, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_device_seek_speed, struct btrfs_dev_item,
-+			 seek_speed, 8);
-+BTRFS_SETGET_STACK_FUNCS(stack_device_bandwidth, struct btrfs_dev_item,
-+			 bandwidth, 8);
-+BTRFS_SETGET_STACK_FUNCS(stack_device_generation, struct btrfs_dev_item,
-+			 generation, 64);
-+
-+static inline char *btrfs_device_uuid(struct btrfs_dev_item *d)
-+{
-+	return (char *)d + offsetof(struct btrfs_dev_item, uuid);
-+}
-+
-+static inline char *btrfs_device_fsid(struct btrfs_dev_item *d)
-+{
-+	return (char *)d + offsetof(struct btrfs_dev_item, fsid);
-+}
-+
-+BTRFS_SETGET_FUNCS(chunk_length, struct btrfs_chunk, length, 64);
-+BTRFS_SETGET_FUNCS(chunk_owner, struct btrfs_chunk, owner, 64);
-+BTRFS_SETGET_FUNCS(chunk_stripe_len, struct btrfs_chunk, stripe_len, 64);
-+BTRFS_SETGET_FUNCS(chunk_io_align, struct btrfs_chunk, io_align, 32);
-+BTRFS_SETGET_FUNCS(chunk_io_width, struct btrfs_chunk, io_width, 32);
-+BTRFS_SETGET_FUNCS(chunk_sector_size, struct btrfs_chunk, sector_size, 32);
-+BTRFS_SETGET_FUNCS(chunk_type, struct btrfs_chunk, type, 64);
-+BTRFS_SETGET_FUNCS(chunk_num_stripes, struct btrfs_chunk, num_stripes, 16);
-+BTRFS_SETGET_FUNCS(chunk_sub_stripes, struct btrfs_chunk, sub_stripes, 16);
-+BTRFS_SETGET_FUNCS(stripe_devid, struct btrfs_stripe, devid, 64);
-+BTRFS_SETGET_FUNCS(stripe_offset, struct btrfs_stripe, offset, 64);
-+
-+static inline char *btrfs_stripe_dev_uuid(struct btrfs_stripe *s)
-+{
-+	return (char *)s + offsetof(struct btrfs_stripe, dev_uuid);
-+}
-+
-+BTRFS_SETGET_STACK_FUNCS(stack_chunk_length, struct btrfs_chunk, length, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_chunk_owner, struct btrfs_chunk, owner, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_chunk_stripe_len, struct btrfs_chunk,
-+			 stripe_len, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_chunk_io_align, struct btrfs_chunk,
-+			 io_align, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_chunk_io_width, struct btrfs_chunk,
-+			 io_width, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_chunk_sector_size, struct btrfs_chunk,
-+			 sector_size, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_chunk_type, struct btrfs_chunk, type, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_chunk_num_stripes, struct btrfs_chunk,
-+			 num_stripes, 16);
-+BTRFS_SETGET_STACK_FUNCS(stack_chunk_sub_stripes, struct btrfs_chunk,
-+			 sub_stripes, 16);
-+BTRFS_SETGET_STACK_FUNCS(stack_stripe_devid, struct btrfs_stripe, devid, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_stripe_offset, struct btrfs_stripe, offset, 64);
-+
-+static inline struct btrfs_stripe *btrfs_stripe_nr(struct btrfs_chunk *c,
-+						   int nr)
-+{
-+	unsigned long offset = (unsigned long)c;
-+	offset += offsetof(struct btrfs_chunk, stripe);
-+	offset += nr * sizeof(struct btrfs_stripe);
-+	return (struct btrfs_stripe *)offset;
-+}
-+
-+static inline char *btrfs_stripe_dev_uuid_nr(struct btrfs_chunk *c, int nr)
-+{
-+	return btrfs_stripe_dev_uuid(btrfs_stripe_nr(c, nr));
-+}
-+
-+static inline u64 btrfs_stripe_offset_nr(struct extent_buffer *eb,
-+					 struct btrfs_chunk *c, int nr)
-+{
-+	return btrfs_stripe_offset(eb, btrfs_stripe_nr(c, nr));
-+}
-+
-+static inline void btrfs_set_stripe_offset_nr(struct extent_buffer *eb,
-+					     struct btrfs_chunk *c, int nr,
-+					     u64 val)
-+{
-+	btrfs_set_stripe_offset(eb, btrfs_stripe_nr(c, nr), val);
-+}
-+
-+static inline u64 btrfs_stripe_devid_nr(struct extent_buffer *eb,
-+					 struct btrfs_chunk *c, int nr)
-+{
-+	return btrfs_stripe_devid(eb, btrfs_stripe_nr(c, nr));
-+}
-+
-+static inline void btrfs_set_stripe_devid_nr(struct extent_buffer *eb,
-+					     struct btrfs_chunk *c, int nr,
-+					     u64 val)
-+{
-+	btrfs_set_stripe_devid(eb, btrfs_stripe_nr(c, nr), val);
-+}
-+
-+/* struct btrfs_block_group_item */
-+BTRFS_SETGET_STACK_FUNCS(block_group_used, struct btrfs_block_group_item,
-+			 used, 64);
-+BTRFS_SETGET_FUNCS(disk_block_group_used, struct btrfs_block_group_item,
-+			 used, 64);
-+BTRFS_SETGET_STACK_FUNCS(block_group_chunk_objectid,
-+			struct btrfs_block_group_item, chunk_objectid, 64);
-+
-+BTRFS_SETGET_FUNCS(disk_block_group_chunk_objectid,
-+		   struct btrfs_block_group_item, chunk_objectid, 64);
-+BTRFS_SETGET_FUNCS(disk_block_group_flags,
-+		   struct btrfs_block_group_item, flags, 64);
-+BTRFS_SETGET_STACK_FUNCS(block_group_flags,
-+			struct btrfs_block_group_item, flags, 64);
-+
-+/* struct btrfs_inode_ref */
-+BTRFS_SETGET_FUNCS(inode_ref_name_len, struct btrfs_inode_ref, name_len, 16);
-+BTRFS_SETGET_FUNCS(inode_ref_index, struct btrfs_inode_ref, index, 64);
-+
-+/* struct btrfs_inode_item */
-+BTRFS_SETGET_FUNCS(inode_generation, struct btrfs_inode_item, generation, 64);
-+BTRFS_SETGET_FUNCS(inode_sequence, struct btrfs_inode_item, sequence, 64);
-+BTRFS_SETGET_FUNCS(inode_transid, struct btrfs_inode_item, transid, 64);
-+BTRFS_SETGET_FUNCS(inode_size, struct btrfs_inode_item, size, 64);
-+BTRFS_SETGET_FUNCS(inode_nbytes, struct btrfs_inode_item, nbytes, 64);
-+BTRFS_SETGET_FUNCS(inode_block_group, struct btrfs_inode_item, block_group, 64);
-+BTRFS_SETGET_FUNCS(inode_nlink, struct btrfs_inode_item, nlink, 32);
-+BTRFS_SETGET_FUNCS(inode_uid, struct btrfs_inode_item, uid, 32);
-+BTRFS_SETGET_FUNCS(inode_gid, struct btrfs_inode_item, gid, 32);
-+BTRFS_SETGET_FUNCS(inode_mode, struct btrfs_inode_item, mode, 32);
-+BTRFS_SETGET_FUNCS(inode_rdev, struct btrfs_inode_item, rdev, 64);
-+BTRFS_SETGET_FUNCS(inode_flags, struct btrfs_inode_item, flags, 64);
-+
-+BTRFS_SETGET_STACK_FUNCS(stack_inode_generation,
-+			 struct btrfs_inode_item, generation, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_inode_sequence,
-+			 struct btrfs_inode_item, generation, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_inode_size,
-+			 struct btrfs_inode_item, size, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_inode_nbytes,
-+			 struct btrfs_inode_item, nbytes, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_inode_block_group,
-+			 struct btrfs_inode_item, block_group, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_inode_nlink,
-+			 struct btrfs_inode_item, nlink, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_inode_uid,
-+			 struct btrfs_inode_item, uid, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_inode_gid,
-+			 struct btrfs_inode_item, gid, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_inode_mode,
-+			 struct btrfs_inode_item, mode, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_inode_rdev,
-+			 struct btrfs_inode_item, rdev, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_inode_flags,
-+			 struct btrfs_inode_item, flags, 64);
-+
-+BTRFS_SETGET_FUNCS(timespec_sec, struct btrfs_timespec, sec, 64);
-+BTRFS_SETGET_FUNCS(timespec_nsec, struct btrfs_timespec, nsec, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_timespec_sec, struct btrfs_timespec,
-+			 sec, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_timespec_nsec, struct btrfs_timespec,
-+			 nsec, 32);
-+
-+/* struct btrfs_dev_extent */
-+BTRFS_SETGET_FUNCS(dev_extent_chunk_tree, struct btrfs_dev_extent,
-+		   chunk_tree, 64);
-+BTRFS_SETGET_FUNCS(dev_extent_chunk_objectid, struct btrfs_dev_extent,
-+		   chunk_objectid, 64);
-+BTRFS_SETGET_FUNCS(dev_extent_chunk_offset, struct btrfs_dev_extent,
-+		   chunk_offset, 64);
-+BTRFS_SETGET_FUNCS(dev_extent_length, struct btrfs_dev_extent, length, 64);
-+
-+static inline u8 *btrfs_dev_extent_chunk_tree_uuid(struct btrfs_dev_extent *dev)
-+{
-+	unsigned long ptr = offsetof(struct btrfs_dev_extent, chunk_tree_uuid);
-+	return (u8 *)((unsigned long)dev + ptr);
-+}
-+
-+/* struct btrfs_extent_ref */
-+BTRFS_SETGET_FUNCS(ref_root, struct btrfs_extent_ref, root, 64);
-+BTRFS_SETGET_FUNCS(ref_generation, struct btrfs_extent_ref, generation, 64);
-+BTRFS_SETGET_FUNCS(ref_objectid, struct btrfs_extent_ref, objectid, 64);
-+BTRFS_SETGET_FUNCS(ref_num_refs, struct btrfs_extent_ref, num_refs, 32);
-+
-+BTRFS_SETGET_STACK_FUNCS(stack_ref_root, struct btrfs_extent_ref, root, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_ref_generation, struct btrfs_extent_ref,
-+			 generation, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_ref_objectid, struct btrfs_extent_ref,
-+			 objectid, 64);
-+BTRFS_SETGET_STACK_FUNCS(stack_ref_num_refs, struct btrfs_extent_ref,
-+			 num_refs, 32);
-+
-+/* struct btrfs_extent_item */
-+BTRFS_SETGET_FUNCS(extent_refs, struct btrfs_extent_item, refs, 32);
-+BTRFS_SETGET_STACK_FUNCS(stack_extent_refs, struct btrfs_extent_item,
-+			 refs, 32);
-+
-+/* struct btrfs_node */
-+BTRFS_SETGET_FUNCS(key_blockptr, struct btrfs_key_ptr, blockptr, 64);
-+BTRFS_SETGET_FUNCS(key_generation, struct btrfs_key_ptr, generation, 64);
-+
-+static inline u64 btrfs_node_blockptr(struct extent_buffer *eb, int nr)
-+{
-+	unsigned long ptr;
-+	ptr = offsetof(struct btrfs_node, ptrs) +
-+		sizeof(struct btrfs_key_ptr) * nr;
-+	return btrfs_key_blockptr(eb, (struct btrfs_key_ptr *)ptr);
-+}
-+
-+static inline void btrfs_set_node_blockptr(struct extent_buffer *eb,
-+					   int nr, u64 val)
-+{
-+	unsigned long ptr;
-+	ptr = offsetof(struct btrfs_node, ptrs) +
-+		sizeof(struct btrfs_key_ptr) * nr;
-+	btrfs_set_key_blockptr(eb, (struct btrfs_key_ptr *)ptr, val);
-+}
-+
-+static inline u64 btrfs_node_ptr_generation(struct extent_buffer *eb, int nr)
-+{
-+	unsigned long ptr;
-+	ptr = offsetof(struct btrfs_node, ptrs) +
-+		sizeof(struct btrfs_key_ptr) * nr;
-+	return btrfs_key_generation(eb, (struct btrfs_key_ptr *)ptr);
-+}
-+
-+static inline void btrfs_set_node_ptr_generation(struct extent_buffer *eb,
-+						 int nr, u64 val)
-+{
-+	unsigned long ptr;
-+	ptr = offsetof(struct btrfs_node, ptrs) +
-+		sizeof(struct btrfs_key_ptr) * nr;
-+	btrfs_set_key_generation(eb, (struct btrfs_key_ptr *)ptr, val);
-+}
-+
-+static inline unsigned long btrfs_node_key_ptr_offset(int nr)
-+{
-+	return offsetof(struct btrfs_node, ptrs) +
-+		sizeof(struct btrfs_key_ptr) * nr;
-+}
-+
-+static inline void btrfs_node_key(struct extent_buffer *eb,
-+				  struct btrfs_disk_key *disk_key, int nr)
-+{
-+	unsigned long ptr;
-+	ptr = btrfs_node_key_ptr_offset(nr);
-+	read_eb_member(eb, (struct btrfs_key_ptr *)ptr,
-+		       struct btrfs_key_ptr, key, disk_key);
-+}
-+
-+/* struct btrfs_item */
-+BTRFS_SETGET_FUNCS(item_offset, struct btrfs_item, offset, 32);
-+BTRFS_SETGET_FUNCS(item_size, struct btrfs_item, size, 32);
-+
-+static inline unsigned long btrfs_item_nr_offset(int nr)
-+{
-+	return offsetof(struct btrfs_leaf, items) +
-+		sizeof(struct btrfs_item) * nr;
-+}
-+
-+static inline struct btrfs_item *btrfs_item_nr(struct extent_buffer *eb,
-+					       int nr)
-+{
-+	return (struct btrfs_item *)btrfs_item_nr_offset(nr);
-+}
-+
-+static inline u32 btrfs_item_end(struct extent_buffer *eb,
-+				 struct btrfs_item *item)
-+{
-+	return btrfs_item_offset(eb, item) + btrfs_item_size(eb, item);
-+}
-+
-+static inline u32 btrfs_item_end_nr(struct extent_buffer *eb, int nr)
-+{
-+	return btrfs_item_end(eb, btrfs_item_nr(eb, nr));
-+}
-+
-+static inline u32 btrfs_item_offset_nr(struct extent_buffer *eb, int nr)
-+{
-+	return btrfs_item_offset(eb, btrfs_item_nr(eb, nr));
-+}
-+
-+static inline u32 btrfs_item_size_nr(struct extent_buffer *eb, int nr)
-+{
-+	return btrfs_item_size(eb, btrfs_item_nr(eb, nr));
-+}
-+
-+static inline void btrfs_item_key(struct extent_buffer *eb,
-+			   struct btrfs_disk_key *disk_key, int nr)
-+{
-+	struct btrfs_item *item = btrfs_item_nr(eb, nr);
-+	read_eb_member(eb, item, struct btrfs_item, key, disk_key);
-+}
-+
-+/*
-+ * struct btrfs_root_ref
-+ */
-+BTRFS_SETGET_FUNCS(root_ref_dirid, struct btrfs_root_ref, dirid, 64);
-+BTRFS_SETGET_FUNCS(root_ref_sequence, struct btrfs_root_ref, sequence, 64);
-+BTRFS_SETGET_FUNCS(root_ref_name_len, struct btrfs_root_ref, name_len, 16);
-+
-+/* struct btrfs_dir_item */
-+BTRFS_SETGET_FUNCS(dir_data_len, struct btrfs_dir_item, data_len, 16);
-+BTRFS_SETGET_FUNCS(dir_type, struct btrfs_dir_item, type, 8);
-+BTRFS_SETGET_FUNCS(dir_name_len, struct btrfs_dir_item, name_len, 16);
-+BTRFS_SETGET_FUNCS(dir_transid, struct btrfs_dir_item, transid, 64);
-+
-+static inline void btrfs_dir_item_key(struct extent_buffer *eb,
-+				      struct btrfs_dir_item *item,
-+				      struct btrfs_disk_key *key)
-+{
-+	read_eb_member(eb, item, struct btrfs_dir_item, location, key);
-+}
-+
-+/* struct btrfs_disk_key */
-+BTRFS_SETGET_STACK_FUNCS(disk_key_objectid, struct btrfs_disk_key,
-+			 objectid, 64);
-+BTRFS_SETGET_STACK_FUNCS(disk_key_offset, struct btrfs_disk_key, offset, 64);
-+BTRFS_SETGET_STACK_FUNCS(disk_key_type, struct btrfs_disk_key, type, 8);
-+
-+static inline void btrfs_disk_key_to_cpu(struct btrfs_key *cpu,
-+					 struct btrfs_disk_key *disk)
-+{
-+	cpu->offset = le64_to_cpu(disk->offset);
-+	cpu->type = disk->type;
-+	cpu->objectid = le64_to_cpu(disk->objectid);
-+}
-+
-+static inline void btrfs_cpu_key_to_disk(struct btrfs_disk_key *disk,
-+					 struct btrfs_key *cpu)
-+{
-+	disk->offset = cpu_to_le64(cpu->offset);
-+	disk->type = cpu->type;
-+	disk->objectid = cpu_to_le64(cpu->objectid);
-+}
-+
-+static inline void btrfs_node_key_to_cpu(struct extent_buffer *eb,
-+				  struct btrfs_key *key, int nr)
-+{
-+	struct btrfs_disk_key disk_key;
-+	btrfs_node_key(eb, &disk_key, nr);
-+	btrfs_disk_key_to_cpu(key, &disk_key);
-+}
-+
-+static inline void btrfs_item_key_to_cpu(struct extent_buffer *eb,
-+				  struct btrfs_key *key, int nr)
-+{
-+	struct btrfs_disk_key disk_key;
-+	btrfs_item_key(eb, &disk_key, nr);
-+	btrfs_disk_key_to_cpu(key, &disk_key);
-+}
-+
-+static inline void btrfs_dir_item_key_to_cpu(struct extent_buffer *eb,
-+				      struct btrfs_dir_item *item,
-+				      struct btrfs_key *key)
-+{
-+	struct btrfs_disk_key disk_key;
-+	btrfs_dir_item_key(eb, item, &disk_key);
-+	btrfs_disk_key_to_cpu(key, &disk_key);
-+}
-+
-+static inline u8 btrfs_key_type(struct btrfs_key *key)
-+{
-+	return key->type;
-+}
-+
-+static inline void btrfs_set_key_type(struct btrfs_key *key, u8 val)
-+{
-+	key->type = val;
-+}
-+
-+static inline u64 btrfs_super_devid(struct btrfs_super_block *disk_super)
-+{
-+	return le64_to_cpu(disk_super->dev_item.devid);
-+}
-+
-+/* struct btrfs_header */
-+BTRFS_SETGET_HEADER_FUNCS(header_bytenr, struct btrfs_header, bytenr, 64);
-+BTRFS_SETGET_HEADER_FUNCS(header_generation, struct btrfs_header,
-+			  generation, 64);
-+BTRFS_SETGET_HEADER_FUNCS(header_owner, struct btrfs_header, owner, 64);
-+BTRFS_SETGET_HEADER_FUNCS(header_nritems, struct btrfs_header, nritems, 32);
-+BTRFS_SETGET_HEADER_FUNCS(header_flags, struct btrfs_header, flags, 64);
-+BTRFS_SETGET_HEADER_FUNCS(header_level, struct btrfs_header, level, 8);
-+
-+/* struct btrfs_root_item */
-+BTRFS_SETGET_FUNCS(disk_root_generation, struct btrfs_root_item,
-+		   generation, 64);
-+BTRFS_SETGET_FUNCS(disk_root_refs, struct btrfs_root_item, refs, 32);
-+BTRFS_SETGET_FUNCS(disk_root_bytenr, struct btrfs_root_item, bytenr, 64);
-+BTRFS_SETGET_FUNCS(disk_root_level, struct btrfs_root_item, level, 8);
-+
-+BTRFS_SETGET_STACK_FUNCS(root_generation, struct btrfs_root_item,
-+			 generation, 64);
-+BTRFS_SETGET_STACK_FUNCS(root_bytenr, struct btrfs_root_item, bytenr, 64);
-+BTRFS_SETGET_STACK_FUNCS(root_level, struct btrfs_root_item, level, 8);
-+BTRFS_SETGET_STACK_FUNCS(root_dirid, struct btrfs_root_item, root_dirid, 64);
-+BTRFS_SETGET_STACK_FUNCS(root_refs, struct btrfs_root_item, refs, 32);
-+BTRFS_SETGET_STACK_FUNCS(root_flags, struct btrfs_root_item, flags, 64);
-+BTRFS_SETGET_STACK_FUNCS(root_used, struct btrfs_root_item, bytes_used, 64);
-+BTRFS_SETGET_STACK_FUNCS(root_limit, struct btrfs_root_item, byte_limit, 64);
-+BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item,
-+			 last_snapshot, 64);
-+
-+/* struct btrfs_super_block */
-+
-+BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_flags, struct btrfs_super_block, flags, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block,
-+			 generation, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_root, struct btrfs_super_block, root, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_sys_array_size,
-+			 struct btrfs_super_block, sys_chunk_array_size, 32);
-+BTRFS_SETGET_STACK_FUNCS(super_chunk_root_generation,
-+			 struct btrfs_super_block, chunk_root_generation, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_root_level, struct btrfs_super_block,
-+			 root_level, 8);
-+BTRFS_SETGET_STACK_FUNCS(super_chunk_root, struct btrfs_super_block,
-+			 chunk_root, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_chunk_root_level, struct btrfs_super_block,
-+			 chunk_root_level, 8);
-+BTRFS_SETGET_STACK_FUNCS(super_log_root, struct btrfs_super_block,
-+			 log_root, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_log_root_transid, struct btrfs_super_block,
-+			 log_root_transid, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_log_root_level, struct btrfs_super_block,
-+			 log_root_level, 8);
-+BTRFS_SETGET_STACK_FUNCS(super_total_bytes, struct btrfs_super_block,
-+			 total_bytes, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_bytes_used, struct btrfs_super_block,
-+			 bytes_used, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_sectorsize, struct btrfs_super_block,
-+			 sectorsize, 32);
-+BTRFS_SETGET_STACK_FUNCS(super_nodesize, struct btrfs_super_block,
-+			 nodesize, 32);
-+BTRFS_SETGET_STACK_FUNCS(super_leafsize, struct btrfs_super_block,
-+			 leafsize, 32);
-+BTRFS_SETGET_STACK_FUNCS(super_stripesize, struct btrfs_super_block,
-+			 stripesize, 32);
-+BTRFS_SETGET_STACK_FUNCS(super_root_dir, struct btrfs_super_block,
-+			 root_dir_objectid, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_num_devices, struct btrfs_super_block,
-+			 num_devices, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_compat_flags, struct btrfs_super_block,
-+			 compat_flags, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_compat_ro_flags, struct btrfs_super_block,
-+			 compat_flags, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_incompat_flags, struct btrfs_super_block,
-+			 incompat_flags, 64);
-+BTRFS_SETGET_STACK_FUNCS(super_csum_type, struct btrfs_super_block,
-+			 csum_type, 16);
-+
-+static inline int btrfs_super_csum_size(struct btrfs_super_block *s)
-+{
-+	int t = btrfs_super_csum_type(s);
-+	//BUG_ON(t >= ARRAY_SIZE(btrfs_csum_sizes));
-+	return btrfs_csum_sizes[t];
-+}
-+
-+static inline unsigned long btrfs_leaf_data(struct extent_buffer *l)
-+{
-+	return offsetof(struct btrfs_leaf, items);
-+}
-+
-+/* struct btrfs_file_extent_item */
-+BTRFS_SETGET_FUNCS(file_extent_type, struct btrfs_file_extent_item, type, 8);
-+
-+static inline unsigned long btrfs_file_extent_inline_start(struct
-+						   btrfs_file_extent_item *e)
-+{
-+	unsigned long offset = (unsigned long)e;
-+	offset += offsetof(struct btrfs_file_extent_item, disk_bytenr);
-+	return offset;
-+}
-+
-+static inline u32 btrfs_file_extent_calc_inline_size(u32 datasize)
-+{
-+	return offsetof(struct btrfs_file_extent_item, disk_bytenr) + datasize;
-+}
-+
-+BTRFS_SETGET_FUNCS(file_extent_disk_bytenr, struct btrfs_file_extent_item,
-+		   disk_bytenr, 64);
-+BTRFS_SETGET_FUNCS(file_extent_generation, struct btrfs_file_extent_item,
-+		   generation, 64);
-+BTRFS_SETGET_FUNCS(file_extent_disk_num_bytes, struct btrfs_file_extent_item,
-+		   disk_num_bytes, 64);
-+BTRFS_SETGET_FUNCS(file_extent_offset, struct btrfs_file_extent_item,
-+		  offset, 64);
-+BTRFS_SETGET_FUNCS(file_extent_num_bytes, struct btrfs_file_extent_item,
-+		   num_bytes, 64);
-+BTRFS_SETGET_FUNCS(file_extent_ram_bytes, struct btrfs_file_extent_item,
-+		   ram_bytes, 64);
-+BTRFS_SETGET_FUNCS(file_extent_compression, struct btrfs_file_extent_item,
-+		   compression, 8);
-+BTRFS_SETGET_FUNCS(file_extent_encryption, struct btrfs_file_extent_item,
-+		   encryption, 8);
-+BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item,
-+		   other_encoding, 16);
-+
-+/* this returns the number of file bytes represented by the inline item.
-+ * If an item is compressed, this is the uncompressed size
-+ */
-+static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
-+					struct btrfs_file_extent_item *e)
-+{
-+       return btrfs_file_extent_ram_bytes(eb, e);
-+}
-+
-+/*
-+ * this returns the number of bytes used by the item on disk, minus the
-+ * size of any extent headers.  If a file is compressed on disk, this is
-+ * the compressed size
-+ */
-+static inline u32 btrfs_file_extent_inline_item_len(struct extent_buffer *eb,
-+						    struct btrfs_item *e)
-+{
-+       unsigned long offset;
-+       offset = offsetof(struct btrfs_file_extent_item, disk_bytenr);
-+       return btrfs_item_size(eb, e) - offset;
-+}
-+
-+static inline u32 btrfs_level_size(struct btrfs_root *root, int level) {
-+	if (level == 0)
-+		return root->leafsize;
-+	return root->nodesize;
-+}
-+
-+static inline u32 btrfs_root_level_size(struct btrfs_super_block *sb) {
-+	return btrfs_super_root_level(sb) == 0 ?
-+		btrfs_super_leafsize(sb) :
-+		btrfs_super_nodesize(sb);
-+}
-+
-+static inline u32 btrfs_chunk_root_level_size(struct btrfs_super_block *sb) {
-+	return btrfs_super_chunk_root_level(sb) == 0 ?
-+		btrfs_super_leafsize(sb) :
-+		btrfs_super_nodesize(sb);
-+}
-+
-+/* helper function to cast into the data area of the leaf. */
-+#define btrfs_item_ptr(leaf, slot, type) \
-+	((type *)(btrfs_leaf_data(leaf) + \
-+	btrfs_item_offset_nr(leaf, slot)))
-+
-+#define btrfs_item_ptr_offset(leaf, slot) \
-+	((unsigned long)(btrfs_leaf_data(leaf) + \
-+	btrfs_item_offset_nr(leaf, slot)))
-+
-+/*volumes.h */
-+
-+struct btrfs_fs_devices {
-+	u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
-+
-+	/* the device with this id has the most recent coyp of the super */
-+	u64 latest_devid;
-+	u64 latest_trans;
-+	u64 lowest_devid;
-+	int latest_bdev;
-+	int lowest_bdev;
-+	int seeding;
-+	struct btrfs_fs_devices *seed;
-+};
-+
-+struct btrfs_bio_stripe {
-+	struct btrfs_device dev;
-+	u64 physical;
-+};
-+
-+#define MAX_NRSTRIPES 8
-+struct btrfs_multi_bio {
-+	int error;
-+	int num_stripes;
-+	struct btrfs_bio_stripe stripes[MAX_NRSTRIPES];
-+};
-+
-+#define btrfs_multi_bio_size(n) (sizeof(struct btrfs_multi_bio) + \
-+			    (sizeof(struct btrfs_bio_stripe) * (n)))
-+
-+static int aux_tree_lookup(struct btrfs_root *root,
-+			   struct btrfs_key *key,
-+			   struct btrfs_path *path);
-+
-+struct cache_extent {
-+	u64 start;
-+	u64 size;
-+};
-+
-+struct map_lookup {
-+	struct cache_extent ce;
-+	u64 type;
-+	int io_align;
-+	int io_width;
-+	int stripe_len;
-+	int sector_size;
-+	int num_stripes;
-+	int sub_stripes;
-+        struct btrfs_bio_stripe stripes[MAX_NRSTRIPES];
-+};
-+
-+/* "VFS" things */
-+
-+/* file types recognized by grub */
-+typedef enum {
-+	BTRFS_REGULAR_FILE,
-+	BTRFS_DIRECTORY_FILE,
-+	BTRFS_SYMLINK_FILE,
-+	BTRFS_UNKNOWN_FILE
-+} btrfs_file_type;
-+
-+static inline int coord_is_root(struct btrfs_root *root,
-+				struct btrfs_path *path)
-+{
-+	return btrfs_header_bytenr(&path->nodes[0]) ==
-+		btrfs_header_bytenr(&root->node);
-+}
-+
-+static inline btrfs_file_type btrfs_get_file_type (int mode)
-+{
-+	if (S_ISLNK(mode))
-+		return BTRFS_SYMLINK_FILE;
-+	if (S_ISREG(mode))
-+		return BTRFS_REGULAR_FILE;
-+	if (S_ISDIR(mode))
-+		return BTRFS_DIRECTORY_FILE;
-+	return BTRFS_UNKNOWN_FILE;
-+}
-+
-+#define min_t(type,x,y)							\
-+	({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
-+#define max_t(type,x,y)							\
-+	({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
-+
-+
-+int sys_array_lookup(struct map_lookup *map, u64 logical);
-+int tree_chunk_lookup(struct map_lookup *map,
-+		      u64 logical);
-+int __btrfs_map_block(u64 logical, u64 *length,
-+		      struct btrfs_multi_bio *multi_ret, int mirror_num);
-+int read_tree_block(struct btrfs_root *root,
-+		    struct extent_buffer *eb,
-+		    u64 bytenr, /* logical */
-+		    u32 blocksize,
-+		    u64 parent_transid,
-+		    lookup_pool_id lpid);
-+int check_read_chunk(struct btrfs_key *key,
-+		     struct extent_buffer *leaf,
-+		     struct btrfs_chunk *chunk,
-+		     struct map_lookup *map,
-+		     u64 logical);
-+/*
-+  Local variables:
-+  c-indentation-style: "K&R"
-+  mode-name: "LC"
-+  c-basic-offset: 8
-+  tab-width: 8
-+  fill-column: 80
-+  scroll-step: 1
-+  End:
-+*/
 diff --git a/stage2/builtins.c b/stage2/builtins.c
-index 3e08a86..6c6e3fa 100644
+index 3e08a86..fe6a622 100644
 --- a/stage2/builtins.c
 +++ b/stage2/builtins.c
 @@ -56,6 +56,9 @@ static int bootdev;
@@ -39446,7 +38272,7 @@ index 3e08a86..6c6e3fa 100644
 -  int num_sectors = 0;
 -  int num_entries = 0;
 -  int last_length = 0;
--
+ 
 -  auto void disk_read_blocklist_func (int sector, int offset, int length);
 -  
 -  /* Collect contiguous blocks into one entry as many as possible,
@@ -39479,7 +38305,7 @@ index 3e08a86..6c6e3fa 100644
 -	      num_sectors = 0;
 -	    }
 -	}
- 
+-
 -      if (offset > 0)
 -	{
 -	  grub_printf("%s%d[%d-%d]", num_entries ? "," : "",
@@ -40121,8 +38947,12 @@ index 3e08a86..6c6e3fa 100644
  
  
  /* fallback */
-@@ -1233,14 +1511,16 @@ find_func (char *arg, int flags)
-   for (drive = 0x80; drive < 0x88; drive++)
+@@ -1230,17 +1508,19 @@ find_func (char *arg, int flags)
+     }
+ 
+   /* Hard disks.  */
+-  for (drive = 0x80; drive < 0x88; drive++)
++  for (drive = 0x80; drive < (0x80 + MAX_HD_NUM); drive++)
      {
        unsigned long part = 0xFFFFFF;
 -      unsigned long start, len, offset, ext_offset;
@@ -40142,7 +38972,67 @@ index 3e08a86..6c6e3fa 100644
  	{
  	  if (type != PC_SLICE_TYPE_NONE
  	      && ! IS_PC_SLICE_TYPE_BSD (type)
-@@ -1679,6 +1959,7 @@ static struct builtin builtin_ifconfig =
+@@ -1301,6 +1581,59 @@ static struct builtin builtin_find =
+   "Search for the filename FILENAME in all of partitions and print the list of"
+   " the devices which contain the file."
+ };
++
++/* findiso */
++
++/* Search for an ISO 9660 partition.  */
++static int
++findiso_func (char *arg, int flags)
++{
++  unsigned long drive;
++  unsigned long tmp_drive = saved_drive;
++  unsigned long tmp_partition = saved_partition;
++
++  /* Hard disks.  */
++  for (drive = 0x79; drive < 0x88; drive++)
++    {
++      unsigned long part = 0xFFFFFF;
++
++      if (drive == 0x79)
++	  drive = 0x100;
++
++      current_drive = drive;
++      current_partition = part;
++
++      if (open_device ())
++      {
++	  char *type = get_fsys_type();
++	  if (!grub_strcmp(type, "iso9660"))
++	  {
++	      saved_drive = current_drive;
++	      saved_partition = current_partition;
++	      errnum = ERR_NONE;
++	      return 0;
++	  }
++      }
++
++      /* We want to ignore any error here.  */
++      errnum = ERR_NONE;
++    }
++
++  saved_drive = tmp_drive;
++  saved_partition = tmp_partition;
++
++  errnum = ERR_FILE_NOT_FOUND;
++  return 1;
++}
++
++static struct builtin builtin_findiso =
++{
++  "findiso",
++  findiso_func,
++  BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
++  "findiso FILENAME",
++  "Set root to the first device with a valid ISO 9660 filesystem."
++};
+ 
+ 
+ /* fstest */
+@@ -1679,6 +2012,7 @@ static struct builtin builtin_ifconfig =
  };
  #endif /* SUPPORT_NETBOOT */
  
@@ -40150,7 +39040,7 @@ index 3e08a86..6c6e3fa 100644
  
  /* impsprobe */
  static int
-@@ -1706,6 +1987,7 @@ static struct builtin builtin_impsprobe =
+@@ -1706,6 +2040,7 @@ static struct builtin builtin_impsprobe =
    " configuration table and boot the various CPUs which are found into"
    " a tight loop."
  };
@@ -40158,7 +39048,7 @@ index 3e08a86..6c6e3fa 100644
  
  
  /* initrd */
-@@ -1738,8 +2020,82 @@ static struct builtin builtin_initrd =
+@@ -1738,8 +2073,82 @@ static struct builtin builtin_initrd =
    " appropriate parameters in the Linux setup area in memory."
  };
  
@@ -40241,7 +39131,7 @@ index 3e08a86..6c6e3fa 100644
  static int
  install_func (char *arg, int flags)
  {
-@@ -1747,8 +2103,12 @@ install_func (char *arg, int flags)
+@@ -1747,8 +2156,12 @@ install_func (char *arg, int flags)
    char *stage1_buffer = (char *) RAW_ADDR (0x100000);
    char *stage2_buffer = stage1_buffer + SECTOR_SIZE;
    char *old_sect = stage2_buffer + SECTOR_SIZE;
@@ -40256,7 +39146,7 @@ index 3e08a86..6c6e3fa 100644
    /* XXX: Probably SECTOR_SIZE is reasonable.  */
    char *config_filename = stage2_second_buffer + SECTOR_SIZE;
    char *dummy = config_filename + SECTOR_SIZE;
-@@ -1757,10 +2117,11 @@ install_func (char *arg, int flags)
+@@ -1757,10 +2170,11 @@ install_func (char *arg, int flags)
    int src_drive, src_partition, src_part_start;
    int i;
    struct geometry dest_geom, src_geom;
@@ -40270,7 +39160,7 @@ index 3e08a86..6c6e3fa 100644
    /* Point to the location of the name of a configuration file in Stage 2.  */
    char *config_file_location;
    /* If FILE is a Stage 1.5?  */
-@@ -1769,68 +2130,18 @@ install_func (char *arg, int flags)
+@@ -1769,68 +2183,18 @@ install_func (char *arg, int flags)
    int is_open = 0;
    /* If LBA is forced?  */
    int is_force_lba = 0;
@@ -40344,7 +39234,7 @@ index 3e08a86..6c6e3fa 100644
    /* First, check the GNU-style long option.  */
    while (1)
      {
-@@ -1862,10 +2173,10 @@ install_func (char *arg, int flags)
+@@ -1862,10 +2226,10 @@ install_func (char *arg, int flags)
    addr = skip_to (0, file);
  
    /* Get the installation address.  */
@@ -40357,7 +39247,7 @@ index 3e08a86..6c6e3fa 100644
        ptr = addr;
        errnum = 0;
      }
-@@ -1961,17 +2272,17 @@ install_func (char *arg, int flags)
+@@ -1961,17 +2325,17 @@ install_func (char *arg, int flags)
        = 0x9090;
    
    /* Read the first sector of Stage 2.  */
@@ -40379,7 +39269,7 @@ index 3e08a86..6c6e3fa 100644
    
    /* Check for the version of Stage 2.  */
    if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS))
-@@ -1987,27 +2298,27 @@ install_func (char *arg, int flags)
+@@ -1987,27 +2351,27 @@ install_func (char *arg, int flags)
  
    /* If INSTALLADDR is not specified explicitly in the command-line,
       determine it by the Stage 2 id.  */
@@ -40414,7 +39304,7 @@ index 3e08a86..6c6e3fa 100644
  	  || (*((int *) (i - 4)) & 0x80000000)
  	  || *((unsigned short *) i) >= 0xA00
  	  || *((short *) (i + 2)) == 0)
-@@ -2021,13 +2332,13 @@ install_func (char *arg, int flags)
+@@ -2021,13 +2385,13 @@ install_func (char *arg, int flags)
        i -= 8;
      }
  
@@ -40431,7 +39321,7 @@ index 3e08a86..6c6e3fa 100644
    if (! grub_read (dummy, -1))
      goto fail;
    
-@@ -2110,7 +2421,7 @@ install_func (char *arg, int flags)
+@@ -2110,7 +2474,7 @@ install_func (char *arg, int flags)
  	  /* Skip the first sector.  */
  	  grub_seek (SECTOR_SIZE);
  	  
@@ -40440,26 +39330,16 @@ index 3e08a86..6c6e3fa 100644
  	  if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE)
  	    goto fail;
  	  
-@@ -2180,7 +2491,17 @@ install_func (char *arg, int flags)
+@@ -2180,7 +2544,7 @@ install_func (char *arg, int flags)
  	  else
  #endif /* GRUB_UTIL */
  	    {
 -	      if (! devwrite (saved_sector - part_start, 1, stage2_buffer))
-+	      /*
-+	       * FIXME: Ugly hack.
-+	       * Do not write to btrfs partition
-+	       * without a help of the file system!
-+	       */
-+	      if (!strcmp(fsys_table[fsys_type].name, "btrfs"))
-+		{
-+		  errnum = ERR_BAD_ARGUMENT;
-+		  goto fail;
-+		}
 +	      if (! devwrite (*saved_sector - part_start, 1, stage2_buffer))
  		goto fail;
  	    }
  	}
-@@ -2202,7 +2523,7 @@ install_func (char *arg, int flags)
+@@ -2202,7 +2566,7 @@ install_func (char *arg, int flags)
  	  goto fail;
  	}
  
@@ -40468,7 +39348,7 @@ index 3e08a86..6c6e3fa 100644
  	{
  	  fclose (fp);
  	  errnum = ERR_WRITE;
-@@ -2229,7 +2550,7 @@ install_func (char *arg, int flags)
+@@ -2229,7 +2593,7 @@ install_func (char *arg, int flags)
  	goto fail;
  
        if (! devwrite (stage2_first_sector - src_part_start, 1,
@@ -40477,7 +39357,7 @@ index 3e08a86..6c6e3fa 100644
  	goto fail;
  
        if (! devwrite (stage2_second_sector - src_part_start, 1,
-@@ -2322,6 +2643,7 @@ static struct builtin builtin_ioprobe =
+@@ -2322,6 +2686,7 @@ static struct builtin builtin_ioprobe =
    "ioprobe DRIVE",
    "Probe I/O ports used for the drive DRIVE."
  };
@@ -40485,7 +39365,7 @@ index 3e08a86..6c6e3fa 100644
  
  
  /* kernel */
-@@ -2456,6 +2778,7 @@ static struct builtin builtin_makeactive =
+@@ -2456,6 +2821,7 @@ static struct builtin builtin_makeactive =
    " This command is limited to _primary_ PC partitions on a hard disk."
  };
  
@@ -40493,7 +39373,7 @@ index 3e08a86..6c6e3fa 100644
  
  /* map */
  /* Map FROM_DRIVE to TO_DRIVE.  */
-@@ -2519,6 +2842,7 @@ static struct builtin builtin_map =
+@@ -2519,6 +2885,7 @@ static struct builtin builtin_map =
    " when you chain-load some operating systems, such as DOS, if such an"
    " OS resides at a non-first drive."
  };
@@ -40501,7 +39381,7 @@ index 3e08a86..6c6e3fa 100644
  
  
  #ifdef USE_MD5_PASSWORDS
-@@ -2579,6 +2903,7 @@ static struct builtin builtin_md5crypt =
+@@ -2579,6 +2946,7 @@ static struct builtin builtin_md5crypt =
  };
  #endif /* USE_MD5_PASSWORDS */
  
@@ -40509,7 +39389,7 @@ index 3e08a86..6c6e3fa 100644
  
  /* module */
  static int
-@@ -2656,6 +2981,7 @@ static struct builtin builtin_modulenounzip =
+@@ -2656,6 +3024,7 @@ static struct builtin builtin_modulenounzip =
    "The same as `module', except that automatic decompression is"
    " disabled."
  };
@@ -40517,7 +39397,7 @@ index 3e08a86..6c6e3fa 100644
  
  
  /* pager [on|off] */
-@@ -2698,7 +3024,6 @@ partnew_func (char *arg, int flags)
+@@ -2698,7 +3067,6 @@ partnew_func (char *arg, int flags)
    int start_cl, start_ch, start_dh;
    int end_cl, end_ch, end_dh;
    int entry;
@@ -40525,7 +39405,7 @@ index 3e08a86..6c6e3fa 100644
  
    /* Convert a LBA address to a CHS address in the INT 13 format.  */
    auto void lba_to_chs (int lba, int *cl, int *ch, int *dh);
-@@ -2729,6 +3054,9 @@ partnew_func (char *arg, int flags)
+@@ -2729,6 +3097,9 @@ partnew_func (char *arg, int flags)
        return 1;
      }
  
@@ -40535,7 +39415,7 @@ index 3e08a86..6c6e3fa 100644
    /* The partition must a primary partition.  */
    if ((current_partition >> 16) > 3
        || (current_partition & 0xFFFF) != 0xFFFF)
-@@ -2762,7 +3090,7 @@ partnew_func (char *arg, int flags)
+@@ -2762,7 +3133,7 @@ partnew_func (char *arg, int flags)
      return 1;
  
    /* Read the MBR.  */
@@ -40544,7 +39424,7 @@ index 3e08a86..6c6e3fa 100644
      return 1;
  
    /* Check if the new partition will fit in the disk.  */
-@@ -2815,9 +3143,8 @@ parttype_func (char *arg, int flags)
+@@ -2815,9 +3186,8 @@ parttype_func (char *arg, int flags)
  {
    int new_type;
    unsigned long part = 0xFFFFFF;
@@ -40556,7 +39436,7 @@ index 3e08a86..6c6e3fa 100644
  
    /* Get the drive and the partition.  */
    if (! set_device (arg))
-@@ -2829,6 +3156,9 @@ parttype_func (char *arg, int flags)
+@@ -2829,6 +3199,9 @@ parttype_func (char *arg, int flags)
        errnum = ERR_BAD_ARGUMENT;
        return 1;
      }
@@ -40566,7 +39446,7 @@ index 3e08a86..6c6e3fa 100644
    
    /* The partition must be a PC slice.  */
    if ((current_partition >> 16) == 0xFF
-@@ -2853,8 +3183,15 @@ parttype_func (char *arg, int flags)
+@@ -2853,8 +3226,15 @@ parttype_func (char *arg, int flags)
    /* Look for the partition.  */
    while (next_partition (current_drive, 0xFFFFFF, &part, &type,
  			 &start, &len, &offset, &entry,
@@ -40583,7 +39463,7 @@ index 3e08a86..6c6e3fa 100644
        if (part == current_partition)
  	{
  	  /* Found.  */
-@@ -2900,6 +3237,11 @@ password_func (char *arg, int flags)
+@@ -2900,6 +3280,11 @@ password_func (char *arg, int flags)
        arg = skip_to (0, arg);
      }
  #endif
@@ -40595,7 +39475,7 @@ index 3e08a86..6c6e3fa 100644
    if (grub_memcmp (arg, "--", 2) == 0)
      {
        type = PASSWORD_UNSUPPORTED;
-@@ -2947,7 +3289,7 @@ static struct builtin builtin_password =
+@@ -2947,7 +3332,7 @@ static struct builtin builtin_password =
    "password",
    password_func,
    BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_NO_ECHO,
@@ -40604,7 +39484,7 @@ index 3e08a86..6c6e3fa 100644
    "If used in the first section of a menu file, disable all"
    " interactive editing control (menu entry editor and"
    " command line). If the password PASSWD is entered, it loads the"
-@@ -2956,7 +3298,8 @@ static struct builtin builtin_password =
+@@ -2956,7 +3341,8 @@ static struct builtin builtin_password =
    " instructions.  You can also use it in the script section, in"
    " which case it will ask for the password, before continueing."
    " The option --md5 tells GRUB that PASSWD is encrypted with"
@@ -40614,7 +39494,7 @@ index 3e08a86..6c6e3fa 100644
  };
  
  
-@@ -2982,8 +3325,8 @@ static struct builtin builtin_pause =
+@@ -2982,8 +3368,8 @@ static struct builtin builtin_pause =
    "Print MESSAGE, then wait until a key is pressed."
  };
  
@@ -40624,7 +39504,7 @@ index 3e08a86..6c6e3fa 100644
  /* quit */
  static int
  quit_func (char *arg, int flags)
-@@ -3002,7 +3345,7 @@ static struct builtin builtin_quit =
+@@ -3002,7 +3388,7 @@ static struct builtin builtin_quit =
    "quit",
    "Exit from the GRUB shell."
  };
@@ -40633,7 +39513,7 @@ index 3e08a86..6c6e3fa 100644
  
  
  #ifdef SUPPORT_NETBOOT
-@@ -3165,7 +3508,8 @@ real_root_func (char *arg, int attempt_mount)
+@@ -3165,7 +3551,8 @@ real_root_func (char *arg, int attempt_mount)
  	return 1;
        
        /* Print the type of the filesystem.  */
@@ -40643,7 +39523,7 @@ index 3e08a86..6c6e3fa 100644
      }
    
    return 0;
-@@ -3217,146 +3561,181 @@ static struct builtin builtin_rootnoverify =
+@@ -3217,146 +3604,181 @@ static struct builtin builtin_rootnoverify =
  };
  
  
@@ -40946,7 +39826,7 @@ index 3e08a86..6c6e3fa 100644
  #else /* ! SUPPORT_DISKLESS && ! GRUB_UTIL */
    errnum = ERR_UNRECOGNIZED;
    return 1;
-@@ -3368,10 +3747,14 @@ static struct builtin builtin_savedefault =
+@@ -3368,10 +3790,14 @@ static struct builtin builtin_savedefault =
    "savedefault",
    savedefault_func,
    BUILTIN_CMDLINE,
@@ -40965,7 +39845,7 @@ index 3e08a86..6c6e3fa 100644
  };
  
  
-@@ -3527,6 +3910,7 @@ static struct builtin builtin_serial =
+@@ -3527,6 +3953,7 @@ static struct builtin builtin_serial =
  };
  #endif /* SUPPORT_SERIAL */
  
@@ -40973,7 +39853,7 @@ index 3e08a86..6c6e3fa 100644
  
  /* setkey */
  struct keysym
-@@ -3612,50 +3996,47 @@ static struct keysym keysym_table[] =
+@@ -3612,50 +4039,47 @@ static struct keysym keysym_table[] =
    {"delete",		0,		0x7f,	0,	0x53}
  };
  
@@ -41058,7 +39938,7 @@ index 3e08a86..6c6e3fa 100644
    to_key = arg;
    from_key = skip_to (0, to_key);
  
-@@ -3830,15 +4211,15 @@ setup_func (char *arg, int flags)
+@@ -3830,15 +4254,15 @@ setup_func (char *arg, int flags)
  	{
  	  char tmp[16];
  	  grub_sprintf (tmp, ",%d", (partition >> 16) & 0xFF);
@@ -41077,17 +39957,7 @@ index 3e08a86..6c6e3fa 100644
      }
    
    int embed_stage1_5 (char *stage1_5, int drive, int partition)
-@@ -3881,7 +4262,8 @@ setup_func (char *arg, int flags)
-     {"minix",    "/minix_stage1_5"},
-     {"reiserfs", "/reiserfs_stage1_5"},
-     {"vstafs",   "/vstafs_stage1_5"},
--    {"xfs",      "/xfs_stage1_5"}
-+    {"xfs",      "/xfs_stage1_5"},
-+    {"btrfs",    "/btrfs_stage1_5"}
-   };
- 
-   tmp_drive = saved_drive;
-@@ -3973,7 +4355,7 @@ setup_func (char *arg, int flags)
+@@ -3973,7 +4397,7 @@ setup_func (char *arg, int flags)
  
    /* The prefix was determined.  */
    grub_sprintf (stage2, "%s%s", prefix, "/stage2");
@@ -41096,14 +39966,13 @@ index 3e08a86..6c6e3fa 100644
    *real_config_filename = 0;
  
    /* Check if stage2 exists.  */
-@@ -4083,9 +4465,26 @@ static struct builtin builtin_setup =
+@@ -4083,9 +4507,26 @@ static struct builtin builtin_setup =
    " partition where GRUB images reside, specify the option `--stage2'"
    " to tell GRUB the file name under your OS."
  };
 +#endif /* ! PLATFORM_EFI */
- 
- 
--#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
++
++
 +static int
 +silent_func (char *arg, int flags)
 +{
@@ -41118,13 +39987,14 @@ index 3e08a86..6c6e3fa 100644
 +  BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
 +  "grub will attempt to avoid printing anything to the screen"
 +};
-+
-+
+ 
+ 
+-#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
 +#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES) || defined(SUPPORT_GRAPHICS)
  /* terminal */
  static int
  terminal_func (char *arg, int flags)
-@@ -4244,17 +4643,21 @@ terminal_func (char *arg, int flags)
+@@ -4244,17 +4685,21 @@ terminal_func (char *arg, int flags)
   end:
    current_term = term_table + default_term;
    current_term->flags = term_flags;
@@ -41151,7 +40021,7 @@ index 3e08a86..6c6e3fa 100644
    
    return 0;
  }
-@@ -4264,7 +4667,7 @@ static struct builtin builtin_terminal =
+@@ -4264,7 +4709,7 @@ static struct builtin builtin_terminal =
    "terminal",
    terminal_func,
    BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
@@ -41160,7 +40030,7 @@ index 3e08a86..6c6e3fa 100644
    "Select a terminal. When multiple terminals are specified, wait until"
    " you push any key to continue. If both console and serial are specified,"
    " the terminal to which you input a key first will be selected. If no"
-@@ -4276,7 +4679,7 @@ static struct builtin builtin_terminal =
+@@ -4276,7 +4721,7 @@ static struct builtin builtin_terminal =
    " seconds. The option --lines specifies the maximum number of lines."
    " The option --silent is used to suppress messages."
  };
@@ -41169,7 +40039,7 @@ index 3e08a86..6c6e3fa 100644
  
  
  #ifdef SUPPORT_SERIAL
-@@ -4462,6 +4865,7 @@ static struct builtin builtin_testload =
+@@ -4462,6 +4907,7 @@ static struct builtin builtin_testload =
    " step is to try loading a kernel."
  };
  
@@ -41177,7 +40047,7 @@ index 3e08a86..6c6e3fa 100644
  
  /* testvbe MODE */
  static int
-@@ -4566,6 +4970,7 @@ static struct builtin builtin_testvbe =
+@@ -4566,6 +5012,7 @@ static struct builtin builtin_testvbe =
    "testvbe MODE",
    "Test the VBE mode MODE. Hit any key to return."
  };
@@ -41185,7 +40055,7 @@ index 3e08a86..6c6e3fa 100644
  
  
  #ifdef SUPPORT_NETBOOT
-@@ -4598,6 +5003,15 @@ static struct builtin builtin_tftpserver =
+@@ -4598,6 +5045,15 @@ static struct builtin builtin_tftpserver =
  static int
  timeout_func (char *arg, int flags)
  {
@@ -41201,7 +40071,7 @@ index 3e08a86..6c6e3fa 100644
    if (! safe_parse_maxint (&arg, &grub_timeout))
      return 1;
  
-@@ -4661,6 +5075,7 @@ static struct builtin builtin_unhide =
+@@ -4661,6 +5117,7 @@ static struct builtin builtin_unhide =
    " partition type code."
  };
  
@@ -41209,7 +40079,7 @@ index 3e08a86..6c6e3fa 100644
  
  /* uppermem */
  static int
-@@ -4790,11 +5205,34 @@ static struct builtin builtin_vbeprobe =
+@@ -4790,11 +5247,34 @@ static struct builtin builtin_vbeprobe =
    "Probe VBE information. If the mode number MODE is specified, show only"
    " the information about only the mode."
  };
@@ -41245,7 +40115,7 @@ index 3e08a86..6c6e3fa 100644
    &builtin_blocklist,
    &builtin_boot,
  #ifdef SUPPORT_NETBOOT
-@@ -4802,25 +5240,36 @@ struct builtin *builtin_table[] =
+@@ -4802,25 +5282,37 @@ struct builtin *builtin_table[] =
  #endif /* SUPPORT_NETBOOT */
    &builtin_cat,
    &builtin_chainloader,
@@ -41278,13 +40148,14 @@ index 3e08a86..6c6e3fa 100644
 +#endif
    &builtin_fallback,
    &builtin_find,
++  &builtin_findiso,
 +#ifdef SUPPORT_GRAPHICS
 +  &builtin_foreground,
 +#endif
    &builtin_fstest,
    &builtin_geometry,
    &builtin_halt,
-@@ -4830,27 +5279,35 @@ struct builtin *builtin_table[] =
+@@ -4830,27 +5322,35 @@ struct builtin *builtin_table[] =
  #ifdef SUPPORT_NETBOOT
    &builtin_ifconfig,
  #endif /* SUPPORT_NETBOOT */
@@ -41322,7 +40193,7 @@ index 3e08a86..6c6e3fa 100644
  #ifdef SUPPORT_NETBOOT
    &builtin_rarp,
  #endif /* SUPPORT_NETBOOT */
-@@ -4862,23 +5319,35 @@ struct builtin *builtin_table[] =
+@@ -4862,23 +5362,35 @@ struct builtin *builtin_table[] =
  #ifdef SUPPORT_SERIAL
    &builtin_serial,
  #endif /* SUPPORT_SERIAL */
@@ -42271,7 +41142,7 @@ index 09f9e31..e96bec2 100644
    
    /* Start main routine here.  */
 diff --git a/stage2/disk_io.c b/stage2/disk_io.c
-index b9bc526..e07ca77 100644
+index b9bc526..ee7300d 100644
 --- a/stage2/disk_io.c
 +++ b/stage2/disk_io.c
 @@ -21,12 +21,17 @@
@@ -42302,17 +41173,7 @@ index b9bc526..e07ca77 100644
  # ifdef FSYS_TFTP
    {"tftp", tftp_mount, tftp_read, tftp_dir, tftp_close, 0},
  # endif
-@@ -72,6 +80,9 @@ struct fsys_entry fsys_table[NUM_FSYS + 1] =
- # ifdef FSYS_XFS
-   {"xfs", xfs_mount, xfs_read, xfs_dir, 0, 0},
- # endif
-+# ifdef FSYS_BTRFS
-+  {"btrfs", btrfs_mount, btrfs_read, btrfs_dir, 0, btrfs_embed},
-+# endif
- # ifdef FSYS_UFS2
-   {"ufs2", ufs2_mount, ufs2_read, ufs2_dir, 0, ufs2_embed},
- # endif
-@@ -127,8 +138,8 @@ struct geometry buf_geom;
+@@ -127,8 +135,8 @@ struct geometry buf_geom;
  int filepos;
  int filemax;
  
@@ -42323,7 +41184,7 @@ index b9bc526..e07ca77 100644
  {
    asm volatile ("bsfl %1,%0"
  		: "=r" (word)
-@@ -140,7 +151,7 @@ int
+@@ -140,7 +148,7 @@ int
  rawread (int drive, int sector, int byte_offset, int byte_len, char *buf)
  {
    int slen, sectors_per_vtrack;
@@ -42332,7 +41193,7 @@ index b9bc526..e07ca77 100644
  
    if (byte_len <= 0)
      return 1;
-@@ -163,7 +174,7 @@ rawread (int drive, int sector, int byte_offset, int byte_len, char *buf)
+@@ -163,7 +171,7 @@ rawread (int drive, int sector, int byte_offset, int byte_len, char *buf)
  	    }
  	  buf_drive = drive;
  	  buf_track = -1;
@@ -42341,7 +41202,7 @@ index b9bc526..e07ca77 100644
  	}
  
        /* Make sure that SECTOR is valid.  */
-@@ -297,7 +308,7 @@ devread (int sector, int byte_offset, int byte_len, char *buf)
+@@ -297,7 +305,7 @@ devread (int sector, int byte_offset, int byte_len, char *buf)
     *  Check partition boundaries
     */
    if (sector < 0
@@ -42350,7 +41211,7 @@ index b9bc526..e07ca77 100644
  	  >= part_length))
      {
        errnum = ERR_OUTSIDE_PART;
-@@ -307,8 +318,8 @@ devread (int sector, int byte_offset, int byte_len, char *buf)
+@@ -307,8 +315,8 @@ devread (int sector, int byte_offset, int byte_len, char *buf)
    /*
     *  Get the read to the beginning of a partition.
     */
@@ -42361,7 +41222,7 @@ index b9bc526..e07ca77 100644
  
  #if !defined(STAGE1_5)
    if (disk_read_hook && debug)
-@@ -347,7 +358,7 @@ rawwrite (int drive, int sector, char *buf)
+@@ -347,7 +355,7 @@ rawwrite (int drive, int sector, char *buf)
  	sector = 1;
      }
    
@@ -42370,7 +41231,7 @@ index b9bc526..e07ca77 100644
    if (biosdisk (BIOSDISK_WRITE, drive, &buf_geom,
  		sector, 1, SCRATCHSEG))
      {
-@@ -373,23 +384,23 @@ devwrite (int sector, int sector_count, char *buf)
+@@ -373,23 +381,23 @@ devwrite (int sector, int sector_count, char *buf)
  	 embed a Stage 1.5 into a partition instead of a MBR, use system
  	 calls directly instead of biosdisk, because of the bug in
  	 Linux. *sigh*  */
@@ -42408,7 +41269,16 @@ index b9bc526..e07ca77 100644
  }
  
  static int
-@@ -458,7 +469,7 @@ make_saved_active (void)
+@@ -400,7 +408,7 @@ sane_partition (void)
+     return 1;
+   
+   if (!(current_partition & 0xFF000000uL)
+-      && ((current_drive & 0xFFFFFF7F) < 8
++      && ((current_drive & 0xFFFFFF7F) < MAX_HD_NUM
+ 	  || current_drive == cdrom_drive)
+       && (current_partition & 0xFF) == 0xFF
+       && ((current_partition & 0xFF00) == 0xFF00
+@@ -458,7 +466,7 @@ make_saved_active (void)
  	}
  
        /* Read the MBR in the scratch space.  */
@@ -42417,7 +41287,7 @@ index b9bc526..e07ca77 100644
  	return 0;
  
        /* If the partition is an extended partition, setting the active
-@@ -502,8 +513,8 @@ int
+@@ -502,8 +510,8 @@ int
  set_partition_hidden_flag (int hidden)
  {
    unsigned long part = 0xFFFFFF;
@@ -42428,7 +41298,7 @@ index b9bc526..e07ca77 100644
    char mbr[512];
    
    /* The drive must be a hard disk.  */
-@@ -524,8 +535,15 @@ set_partition_hidden_flag (int hidden)
+@@ -524,8 +532,15 @@ set_partition_hidden_flag (int hidden)
    /* Look for the partition.  */
    while (next_partition (current_drive, 0xFFFFFF, &part, &type,           
  			 &start, &len, &offset, &entry,
@@ -42446,7 +41316,7 @@ index b9bc526..e07ca77 100644
        if (part == current_partition)
  	{
  	  /* Found.  */
-@@ -577,11 +595,14 @@ next_partition (unsigned long drive, unsigned long dest,
+@@ -577,11 +592,14 @@ next_partition (unsigned long drive, unsigned long dest,
  		unsigned long *partition, int *type,
  		unsigned long *start, unsigned long *len,
  		unsigned long *offset, int *entry,
@@ -42462,7 +41332,7 @@ index b9bc526..e07ca77 100644
  
    /* Get next BSD partition in current PC slice.  */
    int next_bsd_partition (void)
-@@ -601,7 +622,7 @@ next_partition (unsigned long drive, unsigned long dest,
+@@ -601,7 +619,7 @@ next_partition (unsigned long drive, unsigned long dest,
  
  	  /* Read the BSD label.  */
  	  if (! rawread (drive, *start + BSD_LABEL_SECTOR,
@@ -42471,7 +41341,7 @@ index b9bc526..e07ca77 100644
  	    return 0;
  
  	  /* Check if it is valid.  */
-@@ -656,7 +677,7 @@ next_partition (unsigned long drive, unsigned long dest,
+@@ -656,7 +674,7 @@ next_partition (unsigned long drive, unsigned long dest,
  	}
  
        /* Read the MBR or the boot sector of the extended partition.  */
@@ -42480,7 +41350,7 @@ index b9bc526..e07ca77 100644
  	return 0;
  
        /* Check if it is valid.  */
-@@ -666,6 +687,40 @@ next_partition (unsigned long drive, unsigned long dest,
+@@ -666,6 +684,40 @@ next_partition (unsigned long drive, unsigned long dest,
  	  return 0;
  	}
  
@@ -42521,7 +41391,7 @@ index b9bc526..e07ca77 100644
        /* Increase the entry number.  */
        (*entry)++;
  
-@@ -710,6 +765,43 @@ next_partition (unsigned long drive, unsigned long dest,
+@@ -710,6 +762,43 @@ next_partition (unsigned long drive, unsigned long dest,
        return 1;
      }
  
@@ -42565,7 +41435,7 @@ index b9bc526..e07ca77 100644
    /* Start the body of this function.  */
    
  #ifndef STAGE1_5
-@@ -717,6 +809,9 @@ next_partition (unsigned long drive, unsigned long dest,
+@@ -717,6 +806,9 @@ next_partition (unsigned long drive, unsigned long dest,
      return 0;
  #endif
  
@@ -42575,7 +41445,7 @@ index b9bc526..e07ca77 100644
    /* If previous partition is a BSD partition or a PC slice which
       contains BSD partitions...  */
    if ((*partition != 0xFFFFFF && IS_PC_SLICE_TYPE_BSD (*type & 0xff))
-@@ -755,8 +850,11 @@ real_open_partition (int flags)
+@@ -755,8 +847,11 @@ real_open_partition (int flags)
    unsigned long dest_partition = current_partition;
    unsigned long part_offset;
    unsigned long ext_offset;
@@ -42588,7 +41458,7 @@ index b9bc526..e07ca77 100644
    int bsd_part, pc_slice;
  
    /* For simplicity.  */
-@@ -766,7 +864,8 @@ real_open_partition (int flags)
+@@ -766,7 +861,8 @@ real_open_partition (int flags)
        int ret = next_partition (current_drive, dest_partition,
  				&current_partition, &current_slice,
  				&part_start, &part_length,
@@ -42598,7 +41468,7 @@ index b9bc526..e07ca77 100644
        bsd_part = (current_partition >> 8) & 0xFF;
        pc_slice = current_partition >> 16;
        return ret;
-@@ -926,6 +1025,17 @@ open_partition (void)
+@@ -926,6 +1022,17 @@ open_partition (void)
    return real_open_partition (0);
  }
  
@@ -42616,7 +41486,7 @@ index b9bc526..e07ca77 100644
  
  #ifndef STAGE1_5
  /* XX used for device completion in 'set_device' and 'print_completions' */
-@@ -978,7 +1088,7 @@ set_device (char *device)
+@@ -978,7 +1085,7 @@ set_device (char *device)
        if (*device != ',' && *device != ')')
  	{
  	  char ch = *device;
@@ -42625,7 +41495,7 @@ index b9bc526..e07ca77 100644
  	  if (*device == 'f' || *device == 'h'
  	      || (*device == 'n' && network_ready)
  	      || (*device == 'c' && cdrom_drive != GRUB_INVALID_DRIVE))
-@@ -1002,14 +1112,14 @@ set_device (char *device)
+@@ -1002,14 +1109,14 @@ set_device (char *device)
  
  	  if ((*device == 'f'
  	       || *device == 'h'
@@ -42643,7 +41513,7 @@ index b9bc526..e07ca77 100644
  	  if (ch == 'n' && network_ready)
  	    current_drive = NETWORK_DRIVE;
  	  else
-@@ -1131,7 +1241,7 @@ set_bootdev (int hdbias)
+@@ -1131,7 +1238,7 @@ set_bootdev (int hdbias)
    if ((saved_drive & 0x80) && cur_part_addr)
      {
        if (rawread (saved_drive, cur_part_offset,
@@ -42652,7 +41522,20 @@ index b9bc526..e07ca77 100644
  	{
  	  char *dst, *src;
        
-@@ -1376,7 +1486,7 @@ print_completions (int is_filename, int is_completion)
+@@ -1243,6 +1350,12 @@ setup_part (char *filename)
+ 
+ 
+ #ifndef STAGE1_5
++char *
++get_fsys_type (void)
++{
++    return fsys_table[fsys_type].name;
++}
++
+ /*
+  *  This prints the filesystem type or gives relevant information.
+  */
+@@ -1376,7 +1489,7 @@ print_completions (int is_filename, int is_completion)
  
  	      if (!ptr
  		  || *(ptr-1) != 'd'
@@ -42661,7 +41544,16 @@ index b9bc526..e07ca77 100644
  		  || *(ptr-2) != 'n'
  #endif /* SUPPORT_NETBOOT */
  		  || *(ptr-2) != 'c')
-@@ -1407,7 +1517,7 @@ print_completions (int is_filename, int is_completion)
+@@ -1385,7 +1498,7 @@ print_completions (int is_filename, int is_completion)
+ 		       i < (ptr && (*(ptr-1) == 'd' && *(ptr-2) == 'f') ? 1:2);
+ 		       i++)
+ 		    {
+-		      for (j = 0; j < 8; j++)
++		      for (j = 0; j < MAX_HD_NUM; j++)
+ 			{
+ 			  disk_no = (i * 0x80) + j;
+ 			  if ((disk_choice || disk_no == current_drive)
+@@ -1407,7 +1520,7 @@ print_completions (int is_filename, int is_completion)
  		      || (*(ptr-1) == 'd' && *(ptr-2) == 'c')))
  		print_a_completion ("cd");
  
@@ -42670,7 +41562,7 @@ index b9bc526..e07ca77 100644
  	      if (network_ready
  		  && (disk_choice || NETWORK_DRIVE == current_drive)
  		  && (!ptr
-@@ -1596,7 +1706,7 @@ grub_open (char *filename)
+@@ -1596,7 +1709,7 @@ grub_open (char *filename)
  
  	  BLK_BLKLENGTH (list_addr) = tmp;
  
@@ -42679,7 +41571,7 @@ index b9bc526..e07ca77 100644
  	  list_addr += BLK_BLKLIST_INC_VAL;
  
  	  if (*ptr != ',')
-@@ -1673,6 +1783,7 @@ grub_read (char *buf, int len)
+@@ -1673,6 +1786,7 @@ grub_read (char *buf, int len)
    if (block_file)
      {
        int size, off, ret = 0;
@@ -42687,7 +41579,7 @@ index b9bc526..e07ca77 100644
  
        while (len && !errnum)
  	{
-@@ -1687,10 +1798,10 @@ grub_read (char *buf, int len)
+@@ -1687,10 +1801,10 @@ grub_read (char *buf, int len)
  	  /* run BLK_CUR_FILEPOS up to filepos */
  	  while (filepos > BLK_CUR_FILEPOS)
  	    {
@@ -42701,7 +41593,7 @@ index b9bc526..e07ca77 100644
  		  BLK_CUR_BLKNUM++;
  
  		  if (BLK_CUR_BLKNUM >= BLK_BLKLENGTH (BLK_CUR_BLKLIST))
-@@ -1703,9 +1814,9 @@ grub_read (char *buf, int len)
+@@ -1703,9 +1817,9 @@ grub_read (char *buf, int len)
  		BLK_CUR_FILEPOS = filepos;
  	    }
  
@@ -42754,27 +41646,10 @@ index 7fed6ba..f154eed 100644
  #define FAT_LONGDIR_ID(entry) \
    (*((unsigned char *) (entry)))
 diff --git a/stage2/filesys.h b/stage2/filesys.h
-index bbad8b9..9d159a8 100644
+index bbad8b9..4295e45 100644
 --- a/stage2/filesys.h
 +++ b/stage2/filesys.h
-@@ -105,6 +105,16 @@ int xfs_dir (char *dirname);
- #define FSYS_XFS_NUM 0
- #endif
- 
-+#ifdef FSYS_BTRFS
-+#define FSYS_BTRFS_NUM 1
-+int btrfs_mount (void);
-+int btrfs_read (char *buf, int len);
-+int btrfs_dir (char *dirname);
-+int btrfs_embed (int *start_sector, int needed_sectors);
-+#else
-+#define FSYS_BTRFS_NUM 0
-+#endif
-+
- #ifdef FSYS_TFTP
- #define FSYS_TFTP_NUM 1
- int tftp_mount (void);
-@@ -115,6 +125,17 @@ void tftp_close (void);
+@@ -115,6 +115,17 @@ void tftp_close (void);
  #define FSYS_TFTP_NUM 0
  #endif
  
@@ -42792,19 +41667,16 @@ index bbad8b9..9d159a8 100644
  #ifdef FSYS_ISO9660
  #define FSYS_ISO9660_NUM 1
  int iso9660_mount (void);
-@@ -127,8 +148,9 @@ int iso9660_dir (char *dirname);
- #ifndef NUM_FSYS
+@@ -128,7 +139,7 @@ int iso9660_dir (char *dirname);
  #define NUM_FSYS	\
    (FSYS_FFS_NUM + FSYS_FAT_NUM + FSYS_EXT2FS_NUM + FSYS_MINIX_NUM	\
--   + FSYS_REISERFS_NUM + FSYS_VSTAFS_NUM + FSYS_JFS_NUM + FSYS_XFS_NUM	\
+    + FSYS_REISERFS_NUM + FSYS_VSTAFS_NUM + FSYS_JFS_NUM + FSYS_XFS_NUM	\
 -   + FSYS_TFTP_NUM + FSYS_ISO9660_NUM + FSYS_UFS2_NUM)
-+   + FSYS_REISERFS_NUM + FSYS_BTRFS_NUM + FSYS_VSTAFS_NUM + FSYS_JFS_NUM \
-+   + FSYS_XFS_NUM + FSYS_TFTP_NUM + FSYS_EFI_TFTP_NUM + FSYS_ISO9660_NUM \
-+   + FSYS_UFS2_NUM)
++   + FSYS_TFTP_NUM + FSYS_EFI_TFTP_NUM + FSYS_ISO9660_NUM + FSYS_UFS2_NUM)
  #endif
  
  /* defines for the block filesystem info area */
-@@ -137,8 +159,8 @@ int iso9660_dir (char *dirname);
+@@ -137,8 +148,8 @@ int iso9660_dir (char *dirname);
  #define BLK_CUR_BLKLIST      (*((int*)(FSYS_BUF+4)))
  #define BLK_CUR_BLKNUM       (*((int*)(FSYS_BUF+8)))
  #define BLK_MAX_ADDR         (FSYS_BUF+0x7FF9)
@@ -42815,1827 +41687,6 @@ index bbad8b9..9d159a8 100644
  #define BLK_BLKLIST_START    (FSYS_BUF+12)
  #define BLK_BLKLIST_INC_VAL  8
  #endif /* NO_BLOCK_FILES */
-diff --git a/stage2/fsys_btrfs.c b/stage2/fsys_btrfs.c
-new file mode 100644
-index 0000000..f47f317
---- /dev/null
-+++ b/stage2/fsys_btrfs.c
-@@ -0,0 +1,1815 @@
-+/* fsys_btrfs.c - an implementation for the Btrfs filesystem
-+ *
-+ * Copyright 2009 Red Hat, Inc.  All rights reserved.
-+ *
-+ * 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, see <http://www.gnu.org/licenses/>.
-+ */
-+
-+#ifdef FSYS_BTRFS
-+
-+#include "shared.h"
-+#include "filesys.h"
-+#include "btrfs.h"
-+
-+#define BTRFS_VERBOSE 0
-+
-+/* Cache layouts */
-+
-+#define LOOKUP_CACHE_BUF_SIZE   (4096)
-+#define LOOKUP_CACHE_SIZE       (LOOKUP_CACHE_BUF_SIZE * LAST_LOOKUP_POOL)
-+#define BTRFS_FS_INFO							\
-+	((struct btrfs_fs_info *)((unsigned long)FSYS_BUF +		\
-+				  LOOKUP_CACHE_SIZE))
-+#define BTRFS_CACHE_SIZE         (sizeof(struct btrfs_fs_info) +	\
-+				  LOOKUP_CACHE_SIZE)
-+#define BTRFS_TREE_ROOT          (&BTRFS_FS_INFO->tree_root)
-+#define BTRFS_CHUNK_ROOT         (&BTRFS_FS_INFO->chunk_root)
-+#define BTRFS_FS_ROOT            (&BTRFS_FS_INFO->fs_root)
-+#define BTRFS_SUPER              (&BTRFS_FS_INFO->sb_copy)
-+#define BTRFS_DEVICES            (&BTRFS_FS_INFO->devices[0])
-+#define BTRFS_FILE_INFO          (&BTRFS_FS_INFO->file_info)
-+#define BTRFS_FILE_INFO_KEY      (&BTRFS_FILE_INFO->key)
-+
-+#define BTRFS_VOLATILE_DEV_CACHE				        \
-+	(&BTRFS_FS_INFO->devices[BTRFS_NUM_CACHED_DEVICES])
-+
-+#define LOOKUP_CACHE_BUF(id) ((char *)((unsigned long)FSYS_BUF +	\
-+				       id * LOOKUP_CACHE_BUF_SIZE))
-+
-+#define noop   do {; } while (0)
-+
-+#if BTRFS_VERBOSE
-+#define btrfs_msg(format, ...) printf(format , ## __VA_ARGS__)
-+#else
-+#define btrfs_msg(format, args...) noop
-+#endif
-+
-+/* compile-time check to make sure we don't overlap
-+   filesystem buffer */
-+static inline void check_btrfs_cache_size(void)
-+{
-+	cassert(BTRFS_CACHE_SIZE <= FSYS_BUFLEN);
-+}
-+
-+static inline u64 btrfs_sb_offset(int mirror)
-+{
-+	u64 start = 16 * 1024;
-+	if (mirror)
-+		return start << (BTRFS_SUPER_MIRROR_SHIFT * mirror);
-+	return BTRFS_SUPER_INFO_OFFSET;
-+}
-+
-+static inline char *grab_lookup_cache(lookup_pool_id lpid)
-+{
-+	char *buf = LOOKUP_CACHE_BUF(lpid);
-+	memset(buf, 0, LOOKUP_CACHE_BUF_SIZE);
-+	return buf;
-+}
-+
-+static inline struct btrfs_path *btrfs_grab_path(lookup_pool_id lpid)
-+{
-+	return &BTRFS_FS_INFO->paths[lpid];
-+}
-+
-+static inline void btrfs_set_path_key(struct btrfs_path *path,
-+				      struct btrfs_key *key)
-+{
-+	btrfs_item_key_to_cpu(&path->nodes[0],
-+			      key,
-+			      path->slots[0]);
-+}
-+
-+static inline void btrfs_update_file_info(struct btrfs_path *path)
-+{
-+	btrfs_set_path_key(path, BTRFS_FILE_INFO_KEY);
-+}
-+
-+static inline void btrfs_set_root_dir_key(struct btrfs_key *key)
-+{
-+	key->objectid = BTRFS_FIRST_FREE_OBJECTID;
-+	btrfs_set_key_type(key, BTRFS_INODE_ITEM_KEY);
-+	key->offset = 0;
-+}
-+
-+static inline void copy_extent_buffer(struct extent_buffer *dst,
-+				      struct extent_buffer *src)
-+{
-+	char *data = dst->data;
-+	memcpy(dst, src, sizeof(*dst));
-+	memcpy(data, src->data, 4096);
-+	dst->data = data;
-+}
-+
-+static inline void move_extent_buffer(struct extent_buffer *dst,
-+				      struct extent_buffer *src)
-+{
-+	memcpy(dst, src, sizeof(*dst));
-+}
-+
-+static inline void init_btrfs_root (struct btrfs_root *root)
-+{
-+	root->node.data = root->data;
-+}
-+
-+static inline void init_btrfs_path(lookup_pool_id lpid)
-+{
-+	struct btrfs_path *path;
-+	path = btrfs_grab_path(lpid);
-+	path->lpid = lpid;
-+}
-+
-+static inline void init_btrfs_info(void)
-+{
-+	int i;
-+
-+	memset(BTRFS_FS_INFO, 0, sizeof(struct btrfs_fs_info));
-+	for(i = 0; i < LAST_LOOKUP_POOL; i++)
-+		init_btrfs_path(i);
-+	init_btrfs_root(BTRFS_TREE_ROOT);
-+	init_btrfs_root(BTRFS_CHUNK_ROOT);
-+	init_btrfs_root(BTRFS_FS_ROOT);
-+}
-+
-+static void setup_root(struct btrfs_root *root,
-+		       u32 nodesize,
-+		       u32 leafsize,
-+		       u32 sectorsize,
-+		       u32 stripesize,
-+		       u64 objectid)
-+{
-+	root->nodesize = nodesize;
-+	root->leafsize = leafsize;
-+	root->sectorsize = sectorsize;
-+	root->stripesize = stripesize;
-+	root->objectid = objectid;
-+}
-+
-+/*
-+ * Pick up the latest root of a
-+ * tree with specified @objectid
-+ */
-+static int btrfs_find_last_root(struct btrfs_root *tree_root,
-+				u64 objectid,
-+				struct btrfs_root_item *item,
-+				lookup_pool_id lpid)
-+{
-+	int ret;
-+	int slot;
-+	struct btrfs_key search_key;
-+	struct btrfs_key found_key;
-+	struct btrfs_path *path;
-+
-+	search_key.objectid = objectid;
-+	search_key.type = BTRFS_ROOT_ITEM_KEY;
-+	search_key.offset = (u64)-1;
-+	path = btrfs_grab_path(lpid);
-+
-+	ret = aux_tree_lookup(tree_root, &search_key, path);
-+	if (ret < 0)
-+		return 1;
-+	slot = path->slots[0];
-+	WARN_ON(slot == 0);
-+	slot -= 1;
-+	btrfs_item_key_to_cpu(&path->nodes[0], &found_key, slot);
-+	if (found_key.objectid != objectid)
-+		return 1;
-+
-+	read_extent_buffer(&path->nodes[0], item,
-+			   btrfs_item_ptr_offset(&path->nodes[0], slot),
-+			   sizeof(*item));
-+	return 0;
-+}
-+
-+static int find_setup_root(struct btrfs_root *tree_root,
-+			   u32 nodesize,
-+			   u32 leafsize,
-+			   u32 sectorsize,
-+			   u32 stripesize,
-+			   u64 objectid,
-+			   struct btrfs_root *dest_root,
-+			   u64 bytenr,
-+			   u32 blocksize,
-+			   u64 generation,
-+			   lookup_pool_id lpid)
-+{
-+	int ret;
-+	struct extent_buffer eb;
-+
-+	setup_root(dest_root,
-+		   nodesize,
-+		   leafsize,
-+		   sectorsize,
-+		   stripesize,
-+		   objectid);
-+	if (tree_root) {
-+		/*
-+		 * pick up the latest version
-+		 * of the root we want to set up
-+		 */
-+		ret = btrfs_find_last_root(tree_root, objectid,
-+					   &dest_root->root_item,
-+					   lpid);
-+		if (ret)
-+			return ret;
-+		bytenr = btrfs_root_bytenr(&dest_root->root_item);
-+		blocksize = btrfs_level_size(dest_root,
-+				       btrfs_root_level(&dest_root->root_item));
-+		generation = btrfs_root_generation(&dest_root->root_item);
-+	}
-+	ret = read_tree_block(dest_root,
-+			      &eb,
-+			      bytenr,
-+			      blocksize,
-+			      generation,
-+			      lpid);
-+	if (!ret)
-+		return 1;
-+	copy_extent_buffer(&dest_root->node, &eb);
-+	return 0;
-+}
-+
-+static inline int btrfs_strncmp(const char *cs, const char *ct, int count)
-+{
-+	signed char __res = 0;
-+
-+	while (count) {
-+		if ((__res = *cs - *ct++) != 0 || !*cs++)
-+			break;
-+		count--;
-+	}
-+	return __res;
-+}
-+
-+/*
-+ * the same as devread, but accepts
-+ * device number, start and length.
-+ */
-+static int btrfs_devread(unsigned long drive, unsigned long part,
-+			 unsigned long dev_len, int sector,
-+			 int byte_offset, int byte_len, char *buf)
-+{
-+	if (sector < 0
-+	    || ((sector + ((byte_offset + byte_len - 1) >> SECTOR_BITS))
-+		>= dev_len)) {
-+		errnum = ERR_OUTSIDE_PART;
-+		return 0;
-+	}
-+	sector += byte_offset >> SECTOR_BITS;
-+	byte_offset &= SECTOR_SIZE - 1;
-+#if !defined(STAGE1_5)
-+	if (disk_read_hook && debug)
-+		printf ("<%d, %d, %d>", sector, byte_offset, byte_len);
-+#endif /* !STAGE1_5 */
-+	return rawread(drive, part + sector, byte_offset,
-+		       byte_len, buf);
-+}
-+
-+static int btrfs_check_super(void)
-+{
-+	struct btrfs_super_block *sb = BTRFS_SUPER;
-+
-+	if (sb->nodesize != BTRFS_DEFAULT_NODE_SIZE) {
-+		btrfs_msg("Btrfs node size (%d) != %d unsupported\n",
-+			  sb->nodesize, BTRFS_DEFAULT_NODE_SIZE);
-+		goto error;
-+	}
-+	if (sb->leafsize != BTRFS_DEFAULT_LEAF_SIZE) {
-+ 	        btrfs_msg("Btrfs leaf size (%d) != %d unsupported\n",
-+			  sb->leafsize, BTRFS_DEFAULT_LEAF_SIZE);
-+		goto error;
-+	}
-+	return 0;
-+ error:
-+	return 1;
-+}
-+
-+/* lift the super block */
-+static int btrfs_uptodate_super_copy(struct btrfs_fs_info *fs)
-+{
-+	errnum = ERR_NONE;
-+	btrfs_devread(BTRFS_FS_INFO->sb_dev.drive,
-+		      BTRFS_FS_INFO->sb_dev.part,
-+		      BTRFS_FS_INFO->sb_dev.length,
-+		      btrfs_sb_offset(BTRFS_FS_INFO->sb_mirror) >> SECTOR_BITS,
-+		      0,
-+		      sizeof(struct btrfs_super_block),
-+		      (char *)BTRFS_SUPER);
-+	return btrfs_check_super();
-+}
-+
-+/*
-+ * Looking for a btrfs super block by magic, @fsid and @devid
-+ * (the last two ones are optional). Update latest transid (if
-+ * any). Return 0, if such super block was found. Otherwise,
-+ * return 1.
-+ *
-+ * NOTE:
-+ * After calling this function the sb_copy of global btrfs_fs_info
-+ * can contain garbage, so the caller is responsible for this to be
-+ * uptodate (see the function btrfs_uptodate_super_copy()).
-+ */
-+static int btrfs_find_super(struct btrfs_device *dev, char *fsid, u64 *devid)
-+{
-+	int i, ret;
-+	int found = 0;
-+
-+	for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
-+		ret = btrfs_devread(dev->drive,
-+				    dev->part,
-+				    dev->length,
-+				    btrfs_sb_offset(i) >> SECTOR_BITS,
-+				    0,
-+				    sizeof(struct btrfs_super_block),
-+				    (char *)BTRFS_SUPER);
-+		if (!ret) {
-+			if (errnum == ERR_OUTSIDE_PART) {
-+				errnum = ERR_NONE;
-+				break;
-+			} else {
-+				errnum = ERR_NONE;
-+				continue;
-+			}
-+		}
-+		if (btrfs_super_bytenr(BTRFS_SUPER) != btrfs_sb_offset(i) ||
-+		    btrfs_strncmp((char *)(&BTRFS_SUPER->magic),
-+				  BTRFS_MAGIC,
-+				  sizeof(BTRFS_SUPER->magic)))
-+			continue;
-+		if (fsid &&
-+		    btrfs_strncmp(fsid,
-+				  (char *)BTRFS_SUPER->fsid,
-+				  BTRFS_FSID_SIZE))
-+			return 1;
-+		if (devid &&
-+		    *devid != btrfs_super_devid(BTRFS_SUPER))
-+			return 1;
-+		found = 1;
-+		dev->devid = btrfs_super_devid(BTRFS_SUPER);
-+
-+		if (btrfs_super_generation(BTRFS_SUPER) >
-+		    BTRFS_FS_INFO->sb_transid) {
-+			BTRFS_FS_INFO->sb_transid =
-+				btrfs_super_generation(BTRFS_SUPER);
-+			BTRFS_FS_INFO->sb_mirror = i;
-+			BTRFS_FS_INFO->sb_dev.devid =
-+				btrfs_super_devid(BTRFS_SUPER);
-+			BTRFS_FS_INFO->sb_dev.drive = dev->drive;
-+			BTRFS_FS_INFO->sb_dev.part = dev->part;
-+			BTRFS_FS_INFO->sb_dev.length = dev->length;
-+		}
-+	}
-+	return !found;
-+}
-+
-+/*
-+ * "Discern" a btrfs device by fsid and
-+ * optionaly by devid (if lookup is set).
-+ * Populate persistent device cache (if
-+ * there are free slots).
-+ */
-+static int btrfs_discerner(struct btrfs_device **dev, int lookup)
-+{
-+	if (btrfs_find_super(*dev,
-+			     (char *)BTRFS_FS_INFO->fsid,
-+			     (lookup ? &(*dev)->devid : 0)))
-+		/* not found */
-+		return 0;
-+	if (*dev < BTRFS_VOLATILE_DEV_CACHE) {
-+		/* populate persistent device cache */
-+		memcpy(*dev + 1, *dev, sizeof(struct btrfs_device));
-+		(*dev)++;
-+	}
-+	return 1;
-+}
-+
-+/*
-+ * Scan available grub devices and call discerner
-+ * for them. Return a number of discerned devices
-+ * The scanner was stolen from print_completions().
-+ *
-+ * Preconditions:
-+ * The global structure btrfs_fs_info contains
-+ * the latest valid version of btrfs superblock
-+ * (the field @sb_copy)
-+ */
-+static u64 scan_grub_devices(struct btrfs_device *dev,
-+			     int (*discerner)(struct btrfs_device **, int),
-+			     int lookup)
-+{
-+	int i, j;
-+	u64 count = 0;
-+	struct geometry geom;
-+
-+	for (i = 0; i < 2; i++)
-+		for (j = 0; j < 8; j++) {
-+			unsigned long part = 0xFFFFFF;
-+			int type, entry, gpt_count, gpt_size;
-+			unsigned long offset, ext_offset, gpt_offset;
-+
-+			dev->drive = (i * 0x80) + j;
-+			if (get_diskinfo(dev->drive, &geom))
-+				continue;
-+			while (1) {
-+				int ret;
-+				buf_drive = -1;
-+				errnum = ERR_NONE;
-+				ret = next_partition(dev->drive, 0xFFFFFF,
-+						     &part, &type, &dev->part,
-+						     &dev->length, &offset,
-+						     &entry, &ext_offset,
-+						     &gpt_offset, &gpt_count,
-+						     &gpt_size,
-+						     BTRFS_FS_INFO->mbr);
-+				if (!ret)
-+					break;
-+				if (discerner(&dev, lookup)) {
-+					count++;
-+					if (lookup)
-+						goto exit;
-+				}
-+			}
-+		}
-+	errnum = ERR_NONE;
-+	if (cdrom_drive != GRUB_INVALID_DRIVE &&
-+	    !get_diskinfo(cdrom_drive, &geom)) {
-+		dev->drive = cdrom_drive;
-+		dev->part = 0;
-+		dev->length = geom.total_sectors;
-+		if (discerner(&dev, lookup)) {
-+			count++;
-+			if (lookup)
-+				goto exit;
-+		}
-+	}
-+#if 0
-+	errnum = ERR_NONE;
-+	if (network_ready &&
-+	    !get_diskinfo(NETWORK_DRIVE, &geom)) {
-+		dev->drive = NETWORK_DRIVE;
-+		dev->part = 0;
-+		dev->length = geom.total_sectors;
-+		if (discerner(&dev, lookup)) {
-+			count++;
-+			if (lookup)
-+				goto exit;
-+		}
-+	}
-+#endif /* 0 */
-+ exit:
-+	return count;
-+}
-+
-+#if 0
-+static int btrfs_next_item(struct btrfs_root *root,
-+			   struct btrfs_path *path);
-+
-+/*
-+ * Scan the chunk tree for dev items
-+ * and call a seeker for all of them.
-+ * Preconditions: chunk root is installed
-+ * to the global btrfs_fs_info.
-+ */
-+static int scan_dev_tree(struct btrfs_device* (*seeker)(u64))
-+{
-+	int ret;
-+	u64 num_devices = 0;
-+	struct btrfs_key key;
-+	struct btrfs_key found_key;
-+	struct btrfs_path *path;
-+	struct btrfs_root *root;
-+
-+	root = BTRFS_CHUNK_ROOT;
-+	path = btrfs_grab_path(FIRST_EXTERNAL_LOOKUP_POOL);
-+	key.objectid = BTRFS_DEV_ITEMS_OBJECTID;
-+	key.type = 0;
-+	key.offset = 0;
-+
-+	ret = aux_tree_lookup(root, &key, path);
-+	if (ret == -1)
-+		goto corrupted;
-+	while (1) {
-+		struct btrfs_device *result;
-+		struct btrfs_dev_item *dev_item;
-+
-+		btrfs_item_key_to_cpu(&path->nodes[0],
-+				      &found_key,
-+				      path->slots[0]);
-+		if (found_key.objectid != BTRFS_DEV_ITEMS_OBJECTID)
-+			break;
-+		dev_item = btrfs_item_ptr(&path->nodes[0],
-+					  path->slots[0],
-+					  struct btrfs_dev_item);
-+		result = seeker(btrfs_device_id(&path->nodes[0], dev_item));
-+		if (result == NULL) {
-+			btrfs_msg("Btrfs device %llu is not available\n",
-+				  btrfs_device_id(&path->nodes[0], dev_item));
-+			goto missed_dev;
-+		}
-+		num_devices++;
-+		ret = btrfs_next_item(root, path);
-+		if (ret)
-+			break;
-+	}
-+	if (num_devices == btrfs_super_num_devices(BTRFS_SUPER))
-+		return 0;
-+ corrupted:
-+	errnum = ERR_FSYS_CORRUPT;
-+	return 1;
-+ missed_dev:
-+	errnum = ERR_FSYS_MOUNT;
-+	return 1;
-+}
-+#endif /* 0 */
-+
-+/*
-+ * Find a grub btrfs device by devid.
-+ * Preconditions: global btrfs_fs_info
-+ * contains a copy of btrfs super block.
-+ *
-+ * Return pointer to the cached device on success.
-+ * Otherwise return NULL.
-+ */
-+static struct btrfs_device *btrfs_lookup_device(u64 devid)
-+{
-+	int i, result;
-+	struct btrfs_device *cdev;
-+
-+	for (i = 0; i < BTRFS_NUM_CACHED_DEVICES; i++) {
-+		cdev = &BTRFS_DEVICES[i];
-+		if (cdev->devid == devid)
-+			goto found_in_cache;
-+		if (cdev->devid == 0)
-+			goto not_found_in_cache;
-+	}
-+ not_found_in_cache:
-+	cdev = BTRFS_VOLATILE_DEV_CACHE;
-+	cdev->devid = devid;
-+	result = scan_grub_devices(cdev,
-+				   btrfs_discerner,
-+				   1);
-+	if (result == 0)
-+		/*
-+		 * At mount time we have figured out that
-+		 * number of available devices is not less
-+		 * then number of devices recorded in the
-+		 * super block. Hence we treat this case as
-+		 * file system corruption.
-+		 */
-+		goto corrupt;
-+	result = btrfs_uptodate_super_copy(BTRFS_FS_INFO);
-+	if (result)
-+		goto corrupt;
-+ found_in_cache:
-+	return cdev;
-+ corrupt:
-+	errnum = ERR_FSYS_CORRUPT;
-+	return NULL;
-+}
-+
-+static int btrfs_find_device(struct btrfs_device *dev)
-+{
-+	struct btrfs_device *cdev;
-+
-+	if (btrfs_super_num_devices(BTRFS_SUPER) == 1) {
-+		dev->drive = current_drive;
-+		dev->part = part_start;
-+		dev->length = part_length;
-+		return 0;
-+	}
-+	cdev = btrfs_lookup_device(dev->devid);
-+	if (cdev == NULL)
-+		return 1;
-+	dev->drive  = cdev->drive;
-+	dev->part   = cdev->part;
-+	dev->length = cdev->length;
-+	return 0;
-+}
-+
-+static inline void init_btrfs_volatile_dev_cache(void)
-+{
-+	BTRFS_VOLATILE_DEV_CACHE->devid = 0;
-+	BTRFS_VOLATILE_DEV_CACHE->drive = current_drive;
-+	BTRFS_VOLATILE_DEV_CACHE->part = part_start;
-+	BTRFS_VOLATILE_DEV_CACHE->length = part_length;
-+}
-+
-+/*
-+ * check availability of btrfs devices
-+ * and populate the persistent device cache
-+ */
-+static int btrfs_check_devices(void)
-+{
-+	u64 num_dev;
-+
-+	if (btrfs_super_num_devices(BTRFS_SUPER) == 1)
-+		return 0;
-+	num_dev = scan_grub_devices(BTRFS_DEVICES,
-+				    btrfs_discerner, 0);
-+	if (btrfs_uptodate_super_copy(BTRFS_FS_INFO))
-+		return 1;
-+	if (num_dev < btrfs_super_num_devices(BTRFS_SUPER)) {
-+		btrfs_msg("Some (%llu) Btrfs devices is not available\n",
-+			  btrfs_super_num_devices(BTRFS_SUPER) - num_dev);
-+	        return 1;
-+	}
-+	return 0;
-+}
-+
-+int btrfs_mount(void)
-+{
-+	int ret;
-+
-+	check_btrfs_cache_size();
-+	init_btrfs_info();
-+	init_btrfs_volatile_dev_cache();
-+
-+	ret = btrfs_find_super(BTRFS_VOLATILE_DEV_CACHE, NULL, NULL);
-+	if (ret) {
-+		btrfs_msg("Drive %lu, partition %lu: no Btrfs metadata\n",
-+			  current_drive, part_start);
-+		return 0;
-+	}
-+	ret = btrfs_uptodate_super_copy(BTRFS_FS_INFO);
-+	if (ret)
-+		goto error;
-+	BTRFS_FS_INFO->sb_transid =
-+		btrfs_super_generation(BTRFS_SUPER);
-+	memcpy(BTRFS_FS_INFO->fsid,
-+	       BTRFS_SUPER->fsid,
-+	       BTRFS_FSID_SIZE);
-+	ret = btrfs_check_devices();
-+	if (ret)
-+		goto error;
-+	/* setup chunk root */
-+	ret = find_setup_root(NULL,
-+			      btrfs_super_nodesize(BTRFS_SUPER),
-+			      btrfs_super_leafsize(BTRFS_SUPER),
-+			      btrfs_super_sectorsize(BTRFS_SUPER),
-+			      btrfs_super_stripesize(BTRFS_SUPER),
-+			      BTRFS_CHUNK_TREE_OBJECTID,
-+			      BTRFS_CHUNK_ROOT,
-+			      btrfs_super_chunk_root(BTRFS_SUPER),
-+			      btrfs_chunk_root_level_size(BTRFS_SUPER),
-+			      btrfs_super_chunk_root_generation(BTRFS_SUPER),
-+			      FIRST_EXTERNAL_LOOKUP_POOL);
-+	if (ret)
-+		return 0;
-+	/* setup tree root */
-+	ret = find_setup_root(NULL,
-+			      btrfs_super_nodesize(BTRFS_SUPER),
-+			      btrfs_super_leafsize(BTRFS_SUPER),
-+			      btrfs_super_sectorsize(BTRFS_SUPER),
-+			      btrfs_super_stripesize(BTRFS_SUPER),
-+			      BTRFS_ROOT_TREE_OBJECTID,
-+			      BTRFS_TREE_ROOT,
-+			      btrfs_super_root(BTRFS_SUPER),
-+			      btrfs_root_level_size(BTRFS_SUPER),
-+			      btrfs_super_generation(BTRFS_SUPER),
-+			      FIRST_EXTERNAL_LOOKUP_POOL);
-+	if (ret)
-+		return 0;
-+	/* setup fs_root */
-+	ret = find_setup_root(BTRFS_TREE_ROOT,
-+			      btrfs_super_nodesize(BTRFS_SUPER),
-+			      btrfs_super_leafsize(BTRFS_SUPER),
-+			      btrfs_super_sectorsize(BTRFS_SUPER),
-+			      btrfs_super_stripesize(BTRFS_SUPER),
-+			      BTRFS_FS_TREE_OBJECTID,
-+			      BTRFS_FS_ROOT,
-+			      0,
-+			      0,
-+			      0,
-+			      FIRST_EXTERNAL_LOOKUP_POOL);
-+	return !ret;
-+ error:
-+	errnum = ERR_FSYS_MOUNT;
-+	return 0;
-+}
-+
-+/*
-+ * Check, whether @chunk is the map for a
-+ * block with @logical block number.
-+ * If yes, then fill the @map.
-+ * Return 1 on affirmative result,
-+ * otherwise return 0.
-+ */
-+int check_read_chunk(struct btrfs_key *key,
-+			    struct extent_buffer *leaf,
-+			    struct btrfs_chunk *chunk,
-+			    struct map_lookup *map,
-+			    u64 logical)
-+{
-+	int i, ret;
-+	u64 chunk_start;
-+	u64 chunk_size;
-+	int num_stripes;
-+
-+	chunk_start = key->offset;
-+	chunk_size = btrfs_chunk_length(leaf, chunk);
-+
-+	if (logical + 1 > chunk_start + chunk_size ||
-+	    logical < chunk_start)
-+		/* not a fit */
-+		return 0;
-+	num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
-+	map->ce.start = chunk_start;
-+	map->ce.size = chunk_size;
-+	map->num_stripes = num_stripes;
-+	map->io_width = btrfs_chunk_io_width(leaf, chunk);
-+	map->io_align = btrfs_chunk_io_align(leaf, chunk);
-+	map->sector_size = btrfs_chunk_sector_size(leaf, chunk);
-+	map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
-+	map->type = btrfs_chunk_type(leaf, chunk);
-+	map->sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
-+
-+	for (i = 0; i < num_stripes; i++) {
-+		map->stripes[i].physical =
-+			btrfs_stripe_offset_nr(leaf, chunk, i);
-+		map->stripes[i].dev.devid =
-+			btrfs_stripe_devid_nr(leaf, chunk, i);
-+		ret = btrfs_find_device(&map->stripes[i].dev);
-+		if (ret)
-+			return 0;
-+	}
-+	return 1;
-+}
-+
-+static void init_extent_buffer(struct extent_buffer *eb,
-+			       struct btrfs_device *dev,
-+			       u64 logical,
-+			       u32 blocksize,
-+			       u64 physical,
-+			       lookup_pool_id lpid)
-+{
-+	if (dev)
-+		memcpy(&eb->dev, dev, sizeof(*dev));
-+	eb->start = logical;
-+	eb->len = blocksize;
-+	eb->dev_bytenr = physical;
-+	eb->data = grab_lookup_cache(lpid);
-+}
-+
-+/*
-+ * Search for a map by logical offset in sys array.
-+ * Return -1 on errors;
-+ * Return 1 if the map is found,
-+ * Return 0 if the map is not found.
-+ */
-+int sys_array_lookup(struct map_lookup *map, u64 logical)
-+{
-+	struct extent_buffer sb;
-+	struct btrfs_disk_key *disk_key;
-+	struct btrfs_chunk *chunk;
-+	struct btrfs_key key;
-+	u32 num_stripes;
-+	u32 array_size;
-+	u32 len = 0;
-+	u8 *ptr;
-+	unsigned long sb_ptr;
-+	u32 cur;
-+	int ret;
-+	int i = 0;
-+
-+	sb.data = (char *)BTRFS_SUPER;
-+	array_size = btrfs_super_sys_array_size(BTRFS_SUPER);
-+
-+	ptr = BTRFS_SUPER->sys_chunk_array;
-+	sb_ptr = offsetof(struct btrfs_super_block, sys_chunk_array);
-+	cur = 0;
-+
-+	while (cur < array_size) {
-+		disk_key = (struct btrfs_disk_key *)ptr;
-+		btrfs_disk_key_to_cpu(&key, disk_key);
-+
-+		len = sizeof(*disk_key);
-+		ptr += len;
-+		sb_ptr += len;
-+		cur += len;
-+
-+		if (key.type == BTRFS_CHUNK_ITEM_KEY) {
-+			chunk = (struct btrfs_chunk *)sb_ptr;
-+			ret = check_read_chunk(&key, &sb,
-+					       chunk, map, logical);
-+			if (ret)
-+				/* map is found */
-+				return ret;
-+			num_stripes = btrfs_chunk_num_stripes(&sb, chunk);
-+			len = btrfs_chunk_item_size(num_stripes);
-+		} else {
-+			errnum = ERR_FSYS_CORRUPT;
-+			return -1;
-+		}
-+		ptr += len;
-+		sb_ptr += len;
-+		cur += len;
-+		i++;
-+	}
-+	return 0;
-+}
-+
-+/*
-+ * Search for a map by logical offset in the chunk tree.
-+ * Return 1 if map is found, otherwise return 0.
-+ */
-+static int chunk_tree_lookup(struct map_lookup *map,
-+			     u64 logical)
-+{
-+	int ret;
-+	int slot;
-+	struct extent_buffer *leaf;
-+	struct btrfs_key key;
-+	struct btrfs_key found_key;
-+	struct btrfs_chunk *chunk;
-+	struct btrfs_path *path;
-+
-+	path = btrfs_grab_path(INTERNAL_LOOKUP_POOL);
-+
-+	key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
-+	key.offset = logical;
-+	key.type = BTRFS_CHUNK_ITEM_KEY;
-+
-+	ret = aux_tree_lookup(BTRFS_CHUNK_ROOT, &key, path);
-+	if (ret < 0)
-+		return 0;
-+	leaf = &path->nodes[0];
-+	slot = path->slots[0];
-+	if (ret == 1) {
-+		WARN_ON(slot == 0);
-+		slot -= 1;
-+	}
-+	btrfs_item_key_to_cpu(leaf, &found_key, slot);
-+	if (found_key.type != BTRFS_CHUNK_ITEM_KEY)
-+		return 0;
-+	chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
-+	return check_read_chunk(&found_key, leaf,
-+				chunk, map, logical);
-+}
-+
-+/*
-+ * Btrfs logical/physical block mapper.
-+ * Look for an appropriate map-extent and
-+ * perform a translation. Return 1 on errors.
-+ */
-+static int btrfs_map_block(u64 logical, u64 *length,
-+			   struct btrfs_multi_bio *multi,
-+			   int mirror_num)
-+{
-+	struct map_lookup map;
-+	u64 offset;
-+	u64 stripe_offset;
-+	u64 stripe_nr;
-+	struct cache_extent *ce;
-+	int stripe_index;
-+	int i;
-+	int ret;
-+
-+	memset(&map, 0, sizeof(map));
-+	ret = sys_array_lookup(&map, logical);
-+	if (ret == -1) {
-+		errnum = ERR_FSYS_CORRUPT;
-+		return 1;
-+	}
-+	if (ret == 0) {
-+		ret = chunk_tree_lookup(&map, logical);
-+		if (!ret) {
-+			/* something should be found! */
-+			errnum = ERR_FSYS_CORRUPT;
-+			return 1;
-+		}
-+	}
-+	/* do translation */
-+	ce = &map.ce;
-+
-+	offset = logical - ce->start;
-+	stripe_nr = offset / map.stripe_len;
-+	stripe_offset = stripe_nr * map.stripe_len;
-+	WARN_ON(offset < stripe_offset);
-+
-+	stripe_offset = offset - stripe_offset;
-+
-+	if (map.type & (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 |
-+			 BTRFS_BLOCK_GROUP_RAID10 |
-+			 BTRFS_BLOCK_GROUP_DUP)) {
-+		*length = min_t(u64, ce->size - offset,
-+			      map.stripe_len - stripe_offset);
-+	} else {
-+		*length = ce->size - offset;
-+	}
-+	multi->num_stripes = 1;
-+	stripe_index = 0;
-+	if (map.type & BTRFS_BLOCK_GROUP_RAID1) {
-+		if (mirror_num)
-+			stripe_index = mirror_num - 1;
-+		else
-+			stripe_index = stripe_nr % map.num_stripes;
-+	} else if (map.type & BTRFS_BLOCK_GROUP_RAID10) {
-+		int factor = map.num_stripes / map.sub_stripes;
-+
-+		stripe_index = stripe_nr % factor;
-+		stripe_index *= map.sub_stripes;
-+
-+		if (mirror_num)
-+			stripe_index += mirror_num - 1;
-+		else
-+			stripe_index = stripe_nr % map.sub_stripes;
-+
-+		stripe_nr = stripe_nr / factor;
-+	} else if (map.type & BTRFS_BLOCK_GROUP_DUP) {
-+		if (mirror_num)
-+			stripe_index = mirror_num - 1;
-+	} else {
-+		stripe_index = stripe_nr % map.num_stripes;
-+		stripe_nr = stripe_nr / map.num_stripes;
-+	}
-+	WARN_ON(stripe_index >= map.num_stripes);
-+
-+	for (i = 0; i < multi->num_stripes; i++) {
-+		multi->stripes[i].physical =
-+			map.stripes[stripe_index].physical + stripe_offset +
-+			stripe_nr * map.stripe_len;
-+		memcpy(&multi->stripes[i].dev,
-+		       &map.stripes[stripe_index].dev,
-+		       sizeof(struct btrfs_device));
-+		stripe_index++;
-+	}
-+	return 0;
-+}
-+
-+static u64 read_data_extent(u64 logical_start, u64 to_read, char *pos)
-+{
-+	int ret;
-+	u64 length;
-+	struct btrfs_multi_bio multi;
-+
-+	while (to_read) {
-+		ret = btrfs_map_block(logical_start, &length, &multi, 0);
-+		if (ret) {
-+			errnum = ERR_FSYS_CORRUPT;
-+			return ret;
-+		}
-+		if (length > to_read)
-+			length = to_read;
-+		disk_read_func = disk_read_hook;
-+		ret = btrfs_devread(multi.stripes[0].dev.drive,
-+				    multi.stripes[0].dev.part,
-+				    multi.stripes[0].dev.length,
-+				    multi.stripes[0].physical >> SECTOR_BITS,
-+				    logical_start & ((u64)SECTOR_SIZE - 1),
-+				    length,
-+				    pos);
-+		disk_read_func = NULL;
-+		if (!ret)
-+			return 1;
-+		btrfs_msg("BTRFS data extent: read %llu bytes\n", length);
-+		to_read -= length;
-+		pos += length;
-+		logical_start += length;
-+	}
-+	return 0;
-+}
-+
-+static int read_extent_from_disk(struct extent_buffer *eb)
-+{
-+	WARN_ON(eb->dev_bytenr % SECTOR_BITS);
-+	return btrfs_devread(eb->dev.drive,
-+			     eb->dev.part,
-+			     eb->dev.length,
-+			     eb->dev_bytenr >> SECTOR_BITS,
-+			     0,
-+			     eb->len,
-+			     eb->data);
-+}
-+
-+static int verify_parent_transid(struct extent_buffer *eb, u64 parent_transid)
-+{
-+	return parent_transid && (btrfs_header_generation(eb) != parent_transid);
-+}
-+
-+static int btrfs_num_copies(u64 logical, u64 len)
-+{
-+	return 1;
-+}
-+
-+static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
-+{
-+	return 0;
-+}
-+
-+static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
-+		    int verify)
-+{
-+	return 0;
-+}
-+
-+/*
-+ * Read a block of logical number @bytenr
-+ * from disk to buffer @eb.
-+ * Return 1 on success.
-+ */
-+int read_tree_block(struct btrfs_root *root,
-+		    struct extent_buffer *eb,
-+		    u64 bytenr, /* logical */
-+		    u32 blocksize,
-+		    u64 parent_transid,
-+		    lookup_pool_id lpid)
-+{
-+	int ret;
-+	int dev_nr;
-+	u64 length;
-+	struct btrfs_multi_bio multi;
-+	int mirror_num = 0;
-+	int num_copies;
-+
-+	dev_nr = 0;
-+	length = blocksize;
-+	while (1) {
-+		ret = btrfs_map_block(bytenr,
-+				      &length, &multi, mirror_num);
-+		if (ret) {
-+			errnum = ERR_FSYS_CORRUPT;
-+			return 0;
-+		}
-+		init_extent_buffer(eb,
-+				   &multi.stripes[0].dev,
-+				   bytenr,
-+				   blocksize,
-+				   multi.stripes[0].physical,
-+				   lpid);
-+
-+		ret = read_extent_from_disk(eb);
-+		if (ret &&
-+		    check_tree_block(root, eb) == 0 &&
-+		    csum_tree_block(root, eb, 1) == 0 &&
-+		    verify_parent_transid(eb, parent_transid) == 0)
-+			return 1;
-+
-+		num_copies = btrfs_num_copies(eb->start, eb->len);
-+		if (num_copies == 1)
-+			break;
-+		mirror_num++;
-+		if (mirror_num > num_copies)
-+			break;
-+	}
-+	return 0;
-+}
-+
-+/*
-+ * Read a child pointed by @slot node pointer
-+ * of @parent. Put the result to @parent.
-+ * Return 1 on success.
-+ */
-+static int parent2child(struct btrfs_root *root,
-+			struct extent_buffer *parent,
-+			int slot,
-+			lookup_pool_id lpid)
-+{
-+	int level;
-+
-+	WARN_ON(slot < 0);
-+	WARN_ON(slot >= btrfs_header_nritems(parent));
-+
-+	level = btrfs_header_level(parent);
-+	WARN_ON(level <= 0);
-+
-+	return read_tree_block(root,
-+			       parent,
-+			       btrfs_node_blockptr(parent, slot),
-+			       btrfs_level_size(root, level - 1),
-+			       btrfs_node_ptr_generation(parent, slot),
-+			       lpid);
-+}
-+
-+static int btrfs_comp_keys(struct btrfs_disk_key *disk, struct btrfs_key *k2)
-+{
-+	struct btrfs_key k1;
-+
-+	btrfs_disk_key_to_cpu(&k1, disk);
-+
-+	if (k1.objectid > k2->objectid)
-+		return 1;
-+	if (k1.objectid < k2->objectid)
-+		return -1;
-+	if (k1.type > k2->type)
-+		return 1;
-+	if (k1.type < k2->type)
-+		return -1;
-+	if (k1.offset > k2->offset)
-+		return 1;
-+	if (k1.offset < k2->offset)
-+		return -1;
-+	return 0;
-+}
-+
-+static int bin_search(struct extent_buffer *eb, unsigned long p,
-+		      int item_size, struct btrfs_key *key,
-+		      int max, int *slot)
-+{
-+	int low = 0;
-+	int high = max;
-+	int mid;
-+	int ret;
-+	unsigned long offset;
-+	struct btrfs_disk_key *tmp;
-+
-+	while(low < high) {
-+		mid = (low + high) / 2;
-+		offset = p + mid * item_size;
-+
-+		tmp = (struct btrfs_disk_key *)(eb->data + offset);
-+		ret = btrfs_comp_keys(tmp, key);
-+
-+		if (ret < 0)
-+			low = mid + 1;
-+		else if (ret > 0)
-+			high = mid;
-+		else {
-+			*slot = mid;
-+			return 0;
-+		}
-+	}
-+	*slot = low;
-+	return 1;
-+}
-+
-+/* look for a key in a node */
-+static int node_lookup(struct extent_buffer *eb,
-+		       struct btrfs_key *key,
-+		       int *slot)
-+{
-+	if (btrfs_header_level(eb) == 0) {
-+		return bin_search(eb,
-+				  offsetof(struct btrfs_leaf, items),
-+				  sizeof(struct btrfs_item),
-+				  key, btrfs_header_nritems(eb),
-+				  slot);
-+	} else {
-+		return bin_search(eb,
-+				  offsetof(struct btrfs_node, ptrs),
-+				  sizeof(struct btrfs_key_ptr),
-+				  key, btrfs_header_nritems(eb),
-+				  slot);
-+	}
-+	return -1;
-+}
-+
-+static inline int check_node(struct extent_buffer *buf, int slot)
-+{
-+	return 0;
-+}
-+
-+/*
-+ * Look for an item by key in read-only tree.
-+ * Return 0, if key was found. Return -1 on io errors.
-+ *
-+ * Preconditions: btrfs_mount already executed.
-+ * Postconditions: if returned value is non-negative,
-+ * then path[0] represents the found position in the
-+ * tree. All components of the @path from leaf to root
-+ * are valid except their data buffers (only path[0]
-+ * has valid attached data buffer).
-+ */
-+
-+int aux_tree_lookup(struct btrfs_root *root,
-+		    struct btrfs_key *key,
-+		    struct btrfs_path *path)
-+{
-+	int ret;
-+	int slot = 0;
-+	int level;
-+	struct extent_buffer node;
-+	init_extent_buffer(&node,
-+			   NULL,
-+			   0,
-+			   0,
-+			   0,
-+			   path->lpid);
-+	copy_extent_buffer(&node, &root->node);
-+	do {
-+		level = btrfs_header_level(&node);
-+		ret = check_node(&node, slot);
-+		if (ret)
-+			return -1;
-+		move_extent_buffer(&path->nodes[level],
-+				   &node);
-+		ret = node_lookup(&node, key, &slot);
-+		if (ret < 0)
-+			return ret;
-+		if (level) {
-+		        /*
-+			 * non-leaf,
-+			 * jump to the next level
-+			 */
-+			if (ret && slot > 0)
-+			        slot -= 1;
-+			ret = parent2child(root, &node, slot, path->lpid);
-+			if (ret == 0)
-+				return -1;
-+		}
-+		path->slots[level] = slot;
-+	} while (level);
-+	return ret;
-+}
-+
-+static int readup_buffer(struct extent_buffer *buf, lookup_pool_id lpid)
-+{
-+	buf->data = grab_lookup_cache(lpid);
-+	return read_extent_from_disk(buf);
-+}
-+
-+/*
-+ * Find the next leaf in accordance with tree order;
-+ * walk up the tree as far as required to find it.
-+ * Returns 0 if something was found, or 1 if there
-+ * are no greater leaves. Returns < 0 on io errors.
-+ *
-+ * Preconditions: all @path components from leaf to
-+ * root have valid meta-data fields. path[0] has a
-+ * valid attached data buffer with initial leaf.
-+ * Postcondition: the same as above, but path[0] has
-+ * an attached data buffer with the next leaf.
-+ */
-+static int btrfs_next_leaf(struct btrfs_root *root,
-+			   struct btrfs_path *path)
-+{
-+	int res;
-+	int slot;
-+	int level = 1;
-+	struct extent_buffer *buf;
-+
-+	while(level < BTRFS_MAX_LEVEL) {
-+		buf = &path->nodes[level];
-+		slot = path->slots[level] + 1;
-+		/*
-+		 * lift data on this level
-+		 */
-+		res = readup_buffer(buf, path->lpid);
-+		if (!res)
-+			break;
-+		if (slot >= btrfs_header_nritems(buf)) {
-+			/* alas, go to parent (if any) */
-+			level++;
-+			res = 1;
-+			continue;
-+		}
-+		break;
-+	}
-+	if (!res)
-+		return 1;
-+	/*
-+	 * At this level slot points to
-+	 * the subtree we are interested in.
-+	 */
-+	path->slots[level] = slot;
-+	while(level) {
-+		struct extent_buffer tmp;
-+		move_extent_buffer(&tmp, &path->nodes[level]);
-+		res = parent2child(root, &tmp, slot, path->lpid);
-+		if (res == 0)
-+			return -1;
-+		level --;
-+		slot = 0;
-+		move_extent_buffer(&path->nodes[level], &tmp);
-+		path->slots[level] = slot;
-+	}
-+	return 0;
-+}
-+
-+/* Preconditions: path is valid, data buffer
-+ * is attached to leaf node.
-+ * Postcondition: path is updated to point to
-+ * the next position with respect to the tree
-+ * order.
-+ *
-+ * Return -1 on io errors.
-+ * Return 0, if next item was found.
-+ * Return 1, if next item wasn't found (no more items).
-+ */
-+static int btrfs_next_item(struct btrfs_root *root,
-+			   struct btrfs_path *path)
-+{
-+	WARN_ON(path->slots[0] >= btrfs_header_nritems(&path->nodes[0]));
-+
-+	path->slots[0] += 1;
-+
-+	if (path->slots[0] < btrfs_header_nritems(&path->nodes[0]))
-+		return 0;
-+	if (coord_is_root(root, path))
-+		/* no more items */
-+		return 1;
-+	return btrfs_next_leaf(root, path);
-+}
-+
-+/*
-+ * check if we can reuse results of previous
-+ * search for read operation
-+ */
-+static int path_is_valid(struct btrfs_path *path,
-+			 struct btrfs_key *key, u64 offset)
-+{
-+	btrfs_item_key_to_cpu(&path->nodes[0],
-+			      key,
-+			      path->slots[0]);
-+	if (BTRFS_FILE_INFO_KEY->objectid != key->objectid)
-+		return 0;
-+	if (btrfs_key_type(key) == BTRFS_INODE_ITEM_KEY)
-+		return 1;
-+	if (btrfs_key_type(key) != BTRFS_EXTENT_DATA_KEY)
-+		return 0;
-+	return BTRFS_FILE_INFO_KEY->offset <= offset;
-+}
-+
-+/* ->read_func() */
-+int btrfs_read(char *buf, int len)
-+{
-+	int ret;
-+	struct btrfs_root *fs_root;
-+	struct btrfs_path *path;
-+	struct btrfs_key  path_key;
-+	u64 ioff;
-+	u64 bytes;
-+	int to_read;
-+	char *pos = buf;
-+
-+	fs_root = BTRFS_FS_ROOT;
-+	path = btrfs_grab_path(FIRST_EXTERNAL_LOOKUP_POOL);
-+
-+	if (!path_is_valid(path, &path_key, filepos)) {
-+		ret = aux_tree_lookup(fs_root, BTRFS_FILE_INFO_KEY, path);
-+		if (ret < 0)
-+			errnum = ERR_FSYS_CORRUPT;
-+	}
-+	while (!errnum) {
-+		struct btrfs_item *item;
-+		struct btrfs_file_extent_item *fi;
-+		u64 from;
-+
-+		btrfs_item_key_to_cpu(&path->nodes[0],
-+				      &path_key,
-+				      path->slots[0]);
-+		if (BTRFS_FILE_INFO_KEY->objectid != path_key.objectid)
-+			break;
-+		if (btrfs_key_type(&path_key) != BTRFS_EXTENT_DATA_KEY)
-+			goto next;
-+		/*
-+		 * current position is extent item
-+		 */
-+		item = btrfs_item_nr(&path->nodes[0], path->slots[0]);
-+		fi = btrfs_item_ptr(&path->nodes[0],
-+				    path->slots[0],
-+				    struct btrfs_file_extent_item);
-+		if (btrfs_file_extent_compression(&path->nodes[0], fi)) {
-+		       btrfs_msg("Btrfs transparent compression unsupported\n");
-+		       errnum = ERR_BAD_FILETYPE;
-+		       goto exit;
-+		}
-+		ioff = filepos - path_key.offset;
-+
-+		switch (btrfs_file_extent_type(&path->nodes[0], fi)) {
-+		case BTRFS_FILE_EXTENT_INLINE:
-+			bytes = btrfs_file_extent_inline_item_len(&path->
-+								  nodes[0],
-+								  item);
-+			if (path_key.offset + bytes < filepos)
-+				goto next;
-+			to_read = bytes - ioff;
-+			if (to_read > len)
-+				to_read = len;
-+			from = ioff + btrfs_file_extent_inline_start(fi);
-+			if (disk_read_hook != NULL) {
-+				disk_read_func = disk_read_hook;
-+				ret = btrfs_devread(path->nodes[0].dev.drive,
-+						    path->nodes[0].dev.part,
-+						    path->nodes[0].dev.length,
-+						    path->nodes[0].dev_bytenr >>
-+						    SECTOR_BITS,
-+						    from,
-+						    to_read,
-+						    pos);
-+				disk_read_func = NULL;
-+				if (ret)
-+					goto exit;
-+			} else
-+				memcpy(pos,
-+				       path->nodes[0].data + from,
-+				       to_read);
-+			btrfs_msg("BTRFS inline extent: read %d bytes pos %d\n",
-+				  to_read, filepos);
-+			break;
-+		case BTRFS_FILE_EXTENT_REG:
-+			bytes = btrfs_file_extent_num_bytes(&path->nodes[0],
-+							    fi);
-+			if (path_key.offset + bytes < filepos)
-+				goto next;
-+			to_read = bytes - ioff;
-+			if (to_read > len)
-+				to_read = len;
-+			from = ioff +
-+				btrfs_file_extent_disk_bytenr(&path->nodes[0],
-+							      fi) +
-+				btrfs_file_extent_offset(&path->nodes[0],
-+							 fi);
-+			ret = read_data_extent(from, to_read, pos);
-+			if (ret)
-+				goto exit;
-+			break;
-+		case BTRFS_FILE_EXTENT_PREALLOC:
-+			btrfs_msg("Btrfs preallocated extents unsupported\n");
-+			errnum = ERR_BAD_FILETYPE;
-+			goto exit;
-+		default:
-+			errnum = ERR_FSYS_CORRUPT;
-+			goto exit;
-+		}
-+		len -= to_read;
-+		pos += to_read;
-+		filepos += to_read;
-+		if (len == 0)
-+			break;
-+		/* not everything was read */
-+	next:
-+		ret = btrfs_next_item(fs_root, path);
-+		if (ret < 0) {
-+			errnum = ERR_FSYS_CORRUPT;
-+			break;
-+		}
-+		btrfs_update_file_info(path);
-+		continue;
-+	}
-+ exit:
-+	return errnum ? 0 : pos - buf;
-+}
-+
-+static int btrfs_follow_link(struct btrfs_root *root,
-+			     struct btrfs_path *path,
-+			     char **dirname, char *linkbuf,
-+			     int *link_count,
-+			     struct btrfs_inode_item *sd)
-+{
-+	int ret;
-+	int len;
-+	char *name = *dirname;
-+
-+	if (++(*link_count) > MAX_LINK_COUNT) {
-+		errnum = ERR_SYMLINK_LOOP;
-+		return 0;
-+	}
-+	/* calculate remaining name size */
-+	filemax = btrfs_inode_size(&path->nodes[0], sd);
-+	for (len = 0;
-+	     name[len] && isspace(name[len]);
-+	     len ++);
-+
-+	if (filemax + len > PATH_MAX - 1) {
-+		errnum = ERR_FILELENGTH;
-+		return 0;
-+	}
-+	grub_memmove(linkbuf + filemax, name, len + 1);
-+	btrfs_update_file_info(path);
-+	filepos = 0;
-+	/* extract symlink content */
-+	while (1) {
-+		u64 oid = BTRFS_FILE_INFO_KEY->objectid;
-+		ret = btrfs_next_item(root, path);
-+		if (ret)
-+			break;
-+		btrfs_update_file_info(path);
-+		if (oid != BTRFS_FILE_INFO_KEY->objectid)
-+			break;
-+		if (btrfs_key_type(BTRFS_FILE_INFO_KEY) ==
-+		    BTRFS_EXTENT_DATA_KEY)
-+			goto found;
-+	}
-+	/* no target was found */
-+	errnum = ERR_FSYS_CORRUPT;
-+	return 0;
-+ found:
-+	/* fill the rest of linkbuf with the content */
-+	ret = btrfs_read(linkbuf, filemax);
-+	if (ret != filemax) {
-+		errnum = ERR_FSYS_CORRUPT;
-+		return 0;
-+	}
-+	return 1;
-+}
-+
-+static int update_fs_root(struct btrfs_root *fs_root,
-+			  struct btrfs_key *location)
-+{
-+	int ret;
-+	struct btrfs_root *tree_root;
-+
-+	if (location->offset != (u64)-1)
-+		return 0;
-+	tree_root = &BTRFS_FS_INFO->tree_root;
-+	ret = find_setup_root(tree_root,
-+			      tree_root->nodesize,
-+			      tree_root->leafsize,
-+			      tree_root->sectorsize,
-+			      tree_root->stripesize,
-+			      location->objectid,
-+			      fs_root,
-+			      0,
-+			      0,
-+			      0,
-+			      SECOND_EXTERNAL_LOOKUP_POOL);
-+	if (ret)
-+		return ret;
-+	location->objectid = btrfs_root_dirid(&fs_root->root_item);
-+	btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY);
-+	location->offset = 0;
-+	return 0;
-+}
-+
-+#ifndef STAGE1_5
-+static inline void update_possibilities(void)
-+{
-+	if (print_possibilities > 0)
-+		print_possibilities =
-+			-print_possibilities;
-+}
-+#endif
-+
-+/*
-+ * Look for a directory item by name.
-+ * Print possibilities, if needed.
-+ * Postconditions: on success @sd_key points
-+ * to the key contained in the directory entry.
-+ */
-+static int btrfs_de_index_by_name(struct btrfs_root *root,
-+				  struct btrfs_path *path,
-+				  char **dirname,
-+				  struct btrfs_key *sd_key)
-+{
-+	char ch;
-+	int ret;
-+	char *rest;
-+	struct btrfs_dir_item *di;
-+#ifndef STAGE1_5
-+	int do_possibilities = 0;
-+#endif
-+	for (; **dirname == '/'; (*dirname)++);
-+	for (rest = *dirname;
-+	     (ch = *rest) && !isspace(ch) && ch != '/';
-+	     rest++);
-+	*rest = 0; /* for substrung() */
-+#ifndef STAGE1_5
-+	if (print_possibilities && ch != '/')
-+		do_possibilities = 1;
-+#endif
-+	/* scan a directory */
-+	while (1) {
-+		u32 total;
-+		u32 cur = 0;
-+		u32 len;
-+		struct btrfs_key di_key;
-+		struct btrfs_disk_key location;
-+		struct btrfs_item *item;
-+
-+		/* extract next dir entry */
-+		ret = btrfs_next_item(root, path);
-+		if (ret)
-+			break;
-+		item = btrfs_item_nr(&path->nodes[0],
-+				     path->slots[0]);
-+		btrfs_item_key_to_cpu(&path->nodes[0],
-+				      &di_key,
-+				      path->slots[0]);
-+		if (di_key.objectid != sd_key->objectid)
-+			/* no more entries */
-+			break;
-+		di = btrfs_item_ptr(&path->nodes[0],
-+				    path->slots[0],
-+				    struct btrfs_dir_item);
-+		/*
-+		 * working around special cases:
-+		 * btrfs doesn't maintain directory entries
-+		 * which contain names "." and ".."
-+		 */
-+		if (!substring(".", *dirname)) {
-+#ifndef STAGE1_5
-+			if (do_possibilities) {
-+				update_possibilities();
-+				return 1;
-+			}
-+#endif
-+			goto found;
-+		}
-+		if (!substring("..", *dirname)) {
-+			if (di_key.type != BTRFS_INODE_REF_KEY)
-+				continue;
-+			sd_key->objectid = di_key.offset;
-+			btrfs_set_key_type(sd_key, BTRFS_INODE_ITEM_KEY);
-+			sd_key->offset = 0;
-+#ifndef STAGE1_5
-+			if (do_possibilities) {
-+				update_possibilities();
-+				return 1;
-+			}
-+#endif
-+			goto found;
-+		}
-+		if (di_key.type != BTRFS_DIR_ITEM_KEY)
-+			continue;
-+		total = btrfs_item_size(&path->nodes[0], item);
-+		/* scan a directory item */
-+		while (cur < total) {
-+			char tmp;
-+			int result;
-+			char *filename;
-+			char *end_of_name;
-+			int name_len;
-+			int data_len;
-+
-+			btrfs_dir_item_key(&path->nodes[0], di, &location);
-+
-+			name_len = btrfs_dir_name_len(&path->nodes[0], di);
-+			data_len = btrfs_dir_data_len(&path->nodes[0], di);
-+
-+			WARN_ON(name_len > BTRFS_NAME_LEN);
-+
-+			filename = (char *)(path->nodes[0].data +
-+					    (unsigned long)(di + 1));
-+			end_of_name = filename + name_len;
-+			/*
-+			 * working around not null-terminated
-+			 * directory names in btrfs: just
-+			 * a short-term overwrite of the
-+			 * cache with the following rollback
-+			 * of the change.
-+			 */
-+			tmp = *end_of_name;
-+			*end_of_name = 0;
-+			result = substring(*dirname, filename);
-+			*end_of_name = tmp;
-+#ifndef STAGE1_5
-+			if (do_possibilities) {
-+				if (result <= 0) {
-+					update_possibilities();
-+					*end_of_name = 0;
-+					print_a_completion(filename);
-+					*end_of_name = tmp;
-+				}
-+			}
-+			else
-+#endif
-+				if (result == 0) {
-+				      btrfs_dir_item_key_to_cpu(&path->nodes[0],
-+								di, sd_key);
-+				      goto found;
-+				}
-+			len = sizeof(*di) + name_len + data_len;
-+			di = (struct btrfs_dir_item *)((char *)di + len);
-+			cur += len;
-+		}
-+	}
-+#ifndef STAGE1_5
-+	if (print_possibilities < 0)
-+		return 1;
-+#endif
-+	errnum = ERR_FILE_NOT_FOUND;
-+	*rest = ch;
-+	return 0;
-+ found:
-+	*rest = ch;
-+	*dirname = rest;
-+	return 1;
-+}
-+
-+/*
-+ * ->dir_func().
-+ * Postcondition: on a non-zero return BTRFS_FS_INFO
-+ * contains the latest fs_root of file's subvolume.
-+ * BTRFS_FS_INFO points to a subvolume of a file we
-+ * were trying to look up.
-+ * BTRFS_FILE_INFO contains info of the file we were
-+ * trying to look up.
-+ */
-+
-+int btrfs_dir(char *dirname)
-+{
-+	int ret;
-+	int mode;
-+	u64 size;
-+	int linkcount = 0;
-+	char linkbuf[PATH_MAX];
-+
-+	struct btrfs_path *path;
-+	struct btrfs_root *root;
-+
-+	struct btrfs_key sd_key;
-+	struct btrfs_inode_item *sd;
-+	struct btrfs_key parent_sd_key;
-+
-+	root = BTRFS_FS_ROOT;
-+	path = btrfs_grab_path(FIRST_EXTERNAL_LOOKUP_POOL);
-+
-+	btrfs_set_root_dir_key(&sd_key);
-+	while (1) {
-+		struct extent_buffer *leaf;
-+		ret = aux_tree_lookup(root, &sd_key, path);
-+		if (ret)
-+			return 0;
-+		leaf = &path->nodes[0];
-+		sd = btrfs_item_ptr(leaf,
-+				    path->slots[0],
-+				    struct btrfs_inode_item);
-+		mode = btrfs_inode_mode(leaf, sd);
-+		size = btrfs_inode_size(leaf, sd);
-+		switch (btrfs_get_file_type(mode)) {
-+		case BTRFS_SYMLINK_FILE:
-+			ret = btrfs_follow_link(root,
-+						path,
-+						&dirname,
-+						linkbuf,
-+						&linkcount,
-+						sd);
-+			if (!ret)
-+				return 0;
-+			dirname = linkbuf;
-+			if (*dirname == '/')
-+				/* absolute name */
-+				btrfs_set_root_dir_key(&sd_key);
-+			else
-+				memcpy(&sd_key, &parent_sd_key,
-+				       sizeof(sd_key));
-+			continue;
-+		case BTRFS_REGULAR_FILE:
-+			/*
-+			 * normally we want to exit here
-+			 */
-+			if (*dirname && !isspace (*dirname)) {
-+				errnum = ERR_BAD_FILETYPE;
-+				return 0;
-+			}
-+			filepos = 0;
-+			filemax = btrfs_inode_size(leaf, sd);
-+			btrfs_update_file_info(path);
-+			return 1;
-+		case BTRFS_DIRECTORY_FILE:
-+			memcpy(&parent_sd_key, &sd_key, sizeof(sd_key));
-+			ret = btrfs_de_index_by_name(root,
-+						     path,
-+						     &dirname,
-+						     &sd_key);
-+			if (!ret)
-+				return 0;
-+#ifndef STAGE1_5
-+			if (print_possibilities < 0)
-+				return 1;
-+#endif
-+			/*
-+			 * update fs_tree:
-+			 * subvolume stuff goes here
-+			 */
-+			ret = update_fs_root(root, &sd_key);
-+			if (ret)
-+				return 0;
-+			continue;
-+		case BTRFS_UNKNOWN_FILE:
-+		default:
-+			btrfs_msg("Btrfs: bad file type\n");
-+			errnum = ERR_BAD_FILETYPE;
-+			return 0;
-+		}
-+	}
-+}
-+
-+int btrfs_embed(int *start_sector, int needed_sectors)
-+{
-+	int ret;
-+	init_btrfs_info();
-+	init_btrfs_volatile_dev_cache();
-+
-+	ret = btrfs_find_super(BTRFS_VOLATILE_DEV_CACHE, NULL, NULL);
-+	if (ret)
-+		return 0;
-+	ret = btrfs_uptodate_super_copy(BTRFS_FS_INFO);
-+	if (ret)
-+		return 0;
-+	*start_sector = 1; /* reserve first sector for stage1 */
-+	return needed_sectors <=
-+		((BTRFS_SUPER_INFO_OFFSET >> SECTOR_BITS) - 1);
-+}
-+#endif /* FSYS_BTRFS */
-+
-+/*
-+  Local variables:
-+  c-indentation-style: "K&R"
-+  mode-name: "LC"
-+  c-basic-offset: 8
-+  tab-width: 8
-+  fill-column: 80
-+  scroll-step: 1
-+  End:
-+*/
 diff --git a/stage2/fsys_ext2fs.c b/stage2/fsys_ext2fs.c
 index 560048f..01386d1 100644
 --- a/stage2/fsys_ext2fs.c
@@ -48257,7 +45308,7 @@ index 0000000..ff6cd26
 +}
 +#endif
 diff --git a/stage2/shared.h b/stage2/shared.h
-index 77eef11..587f9a1 100644
+index 77eef11..a82067b 100644
 --- a/stage2/shared.h
 +++ b/stage2/shared.h
 @@ -35,9 +35,10 @@
@@ -48294,7 +45345,25 @@ index 77eef11..587f9a1 100644
  #define BUFFERADDR  RAW_ADDR (0x70000)
  #define BUFFERSEG   RAW_SEG (0x7000)
  
-@@ -160,16 +161,18 @@ extern char *grub_scratch_mem;
+@@ -79,6 +80,8 @@ extern char *grub_scratch_mem;
+ #define BIOSDISK_FLAG_LBA_EXTENSION	0x1
+ #define BIOSDISK_FLAG_CDROM		0x2
+ 
++#define MAX_HD_NUM	128
++
+ /*
+  *  This is the filesystem (not raw device) buffer.
+  *  It is 32K in size, do not overrun!
+@@ -127,7 +130,7 @@ extern char *grub_scratch_mem;
+ #define MENU_BUFLEN		(0x8000 + PASSWORD_BUF - MENU_BUF)
+ 
+ /* The size of the drive map.  */
+-#define DRIVE_MAP_SIZE		8
++#define DRIVE_MAP_SIZE		128
+ 
+ /* The size of the key map.  */
+ #define KEY_MAP_SIZE		128
+@@ -160,16 +163,18 @@ extern char *grub_scratch_mem;
  #define LINUX_VID_MODE_ASK		0xFFFD
  
  #define LINUX_CL_OFFSET			0x9000
@@ -48315,7 +45384,7 @@ index 77eef11..587f9a1 100644
  #define BIOS_FLAG_FIXED_DISK	0x80
  
  #define BOOTSEC_LOCATION		RAW_ADDR (0x7C00)
-@@ -200,6 +203,8 @@ extern char *grub_scratch_mem;
+@@ -200,6 +205,8 @@ extern char *grub_scratch_mem;
  #define STAGE2_FORCE_LBA	0x11
  #define STAGE2_VER_STR_OFFS	0x12
  
@@ -48324,28 +45393,7 @@ index 77eef11..587f9a1 100644
  /* Stage 2 identifiers */
  #define STAGE2_ID_STAGE2		0
  #define STAGE2_ID_FFS_STAGE1_5		1
-@@ -210,8 +215,9 @@ extern char *grub_scratch_mem;
- #define STAGE2_ID_VSTAFS_STAGE1_5	6
- #define STAGE2_ID_JFS_STAGE1_5		7
- #define STAGE2_ID_XFS_STAGE1_5		8
--#define STAGE2_ID_ISO9660_STAGE1_5	9
--#define STAGE2_ID_UFS2_STAGE1_5		10
-+#define STAGE2_ID_BTRFS_STAGE1_5	9
-+#define STAGE2_ID_ISO9660_STAGE1_5	10
-+#define STAGE2_ID_UFS2_STAGE1_5		11
- 
- #ifndef STAGE1_5
- # define STAGE2_ID	STAGE2_ID_STAGE2
-@@ -232,6 +238,8 @@ extern char *grub_scratch_mem;
- #  define STAGE2_ID	STAGE2_ID_JFS_STAGE1_5
- # elif defined(FSYS_XFS)
- #  define STAGE2_ID	STAGE2_ID_XFS_STAGE1_5
-+# elif defined(FSYS_BTRFS)
-+#  define STAGE2_ID	STAGE2_ID_BTRFS_STAGE1_5
- # elif defined(FSYS_ISO9660)
- #  define STAGE2_ID	STAGE2_ID_ISO9660_STAGE1_5
- # elif defined(FSYS_UFS2)
-@@ -371,14 +379,24 @@ extern char *grub_scratch_mem;
+@@ -371,14 +378,24 @@ extern char *grub_scratch_mem;
  #define tolower grub_tolower
  #define strlen grub_strlen
  #define strcpy grub_strcpy
@@ -48371,7 +45419,7 @@ index 77eef11..587f9a1 100644
  /* multiboot stuff */
  
  #include "mb_header.h"
-@@ -400,30 +418,33 @@ struct linux_kernel_header
+@@ -400,30 +417,33 @@ struct linux_kernel_header
    unsigned short root_dev;		/* Default root device number */
    unsigned short boot_flag;		/* 0xAA55 magic number */
    unsigned short jump;			/* Jump instruction */
@@ -48415,7 +45463,7 @@ index 77eef11..587f9a1 100644
  } __attribute__ ((packed));
  
  /* VBE controller information.  */
-@@ -600,6 +621,7 @@ typedef enum
+@@ -600,6 +620,7 @@ typedef enum
  {
    PASSWORD_PLAIN,
    PASSWORD_MD5,
@@ -48423,7 +45471,7 @@ index 77eef11..587f9a1 100644
    PASSWORD_UNSUPPORTED
  }
  password_t;
-@@ -627,8 +649,16 @@ extern void (*disk_read_func) (int, int, int);
+@@ -627,8 +648,16 @@ extern void (*disk_read_func) (int, int, int);
  #ifndef STAGE1_5
  /* The flag for debug mode.  */
  extern int debug;
@@ -48440,7 +45488,7 @@ index 77eef11..587f9a1 100644
  extern unsigned long current_drive;
  extern unsigned long current_partition;
  
-@@ -666,6 +696,8 @@ extern struct geometry buf_geom;
+@@ -666,6 +695,8 @@ extern struct geometry buf_geom;
  extern int filepos;
  extern int filemax;
  
@@ -48449,7 +45497,7 @@ index 77eef11..587f9a1 100644
  /*
   *  Common BIOS/boot data.
   */
-@@ -804,11 +836,17 @@ int getkey (void);
+@@ -804,11 +835,17 @@ int getkey (void);
     available. */
  int checkkey (void);
  
@@ -48467,7 +45515,7 @@ index 77eef11..587f9a1 100644
  
  /* Command-line interface functions. */
  #ifndef STAGE1_5
-@@ -860,17 +898,25 @@ void init_builtins (void);
+@@ -860,17 +897,25 @@ void init_builtins (void);
  void init_config (void);
  char *skip_to (int after_equal, char *cmdline);
  struct builtin *find_command (char *command);
@@ -48495,7 +45543,7 @@ index 77eef11..587f9a1 100644
  void *grub_memmove (void *to, const void *from, int len);
  void *grub_memset (void *start, int c, int len);
  int grub_strncat (char *s1, const char *s2, int n);
-@@ -879,9 +925,19 @@ int grub_memcmp (const char *s1, const char *s2, int n);
+@@ -879,9 +924,19 @@ int grub_memcmp (const char *s1, const char *s2, int n);
  int grub_strcmp (const char *s1, const char *s2);
  int grub_strlen (const char *str);
  char *grub_strcpy (char *dest, const char *src);
@@ -48516,7 +45564,7 @@ index 77eef11..587f9a1 100644
  #else
  /* In the grub shell, use the libc jmp_buf instead.  */
  # include <setjmp.h>
-@@ -904,10 +960,11 @@ extern grub_jmp_buf restart_cmdline_env;
+@@ -904,10 +959,11 @@ extern grub_jmp_buf restart_cmdline_env;
  /* misc */
  void init_page (void);
  void print_error (void);
@@ -48529,7 +45577,7 @@ index 77eef11..587f9a1 100644
  int nul_terminate (char *str);
  int get_based_digit (int c, int base);
  int safe_parse_maxint (char **str_ptr, int *myint_ptr);
-@@ -934,7 +991,9 @@ int next_partition (unsigned long drive, unsigned long dest,
+@@ -934,7 +990,9 @@ int next_partition (unsigned long drive, unsigned long dest,
  		    unsigned long *partition, int *type,
  		    unsigned long *start, unsigned long *len,
  		    unsigned long *offset, int *entry,
@@ -48540,7 +45588,16 @@ index 77eef11..587f9a1 100644
  
  /* Sets device to the one represented by the SAVED_* parameters. */
  int make_saved_active (void);
-@@ -987,10 +1046,22 @@ int load_module (char *module, char *arg);
+@@ -962,6 +1020,8 @@ int dir (char *dirname);
+ 
+ int set_bootdev (int hdbias);
+ 
++char *get_fsys_type (void);
++
+ /* Display statistics on the current active device. */
+ void print_fsys_type (void);
+ 
+@@ -987,10 +1047,22 @@ int load_module (char *module, char *arg);
  int load_initrd (char *initrd);
  
  int check_password(char *entered, char* expected, password_t type);
diff --git a/grub-0.97-bz677468-properly-align-stack.patch b/grub-use-gnu-efi-callwrap.patch
similarity index 99%
rename from grub-0.97-bz677468-properly-align-stack.patch
rename to grub-use-gnu-efi-callwrap.patch
index 8ea0f98..d01840c 100644
--- a/grub-0.97-bz677468-properly-align-stack.patch
+++ b/grub-use-gnu-efi-callwrap.patch
@@ -706,11 +706,6 @@ index eb8fd25..0000000
 -	return ret;
 -}
 -
-diff --git a/efi/ia32/callwrap.S b/efi/ia32/callwrap.S
---- a/efi/ia32/callwrap.S
-+++ b/efi/ia32/callwrap.S
-@@ -0,0 +1,1 @@
-+/* This file is a stub for ia32 building */
 -- 
 1.7.6
 
diff --git a/grub.spec b/grub.spec
index 17548b8..94672e8 100644
--- a/grub.spec
+++ b/grub.spec
@@ -1,6 +1,6 @@
 Name: grub
 Version: 0.97
-Release: 76%{?dist}
+Release: 77%{?dist}
 Epoch: 1
 Summary: Grand Unified Boot Loader.
 Group: System Environment/Base
@@ -25,10 +25,6 @@ Source0: ftp://alpha.gnu.org/gnu/%{name}/%{name}-%{version}.tar.gz
 # This is from
 # http://git.kernel.org/?p=boot/grub-fedora/grub-fedora.git;a=summary
 Patch0: grub-fedora-16.patch
-Patch1: 0001-Revert-Added-support-for-btrfs-file-system.patch
-Patch2: 0002-Revert-Make-changes-in-the-following-files-for-btrfs.patch
-Patch3: grub-0.97-128-drives-support.patch
-Patch4: grub-0.97-bz677468-properly-align-stack.patch
 
 %description
 GRUB (Grand Unified Boot Loader) is an experimental boot loader
@@ -109,13 +105,22 @@ fi
 %{_datadir}/grub
 
 %changelog
+* Thu Aug 25 2011 Peter Jones <pjones at redhat.com> - 0.97-77
+- Update to kernel.org fedora-16 branch
+  - Add findiso command
+  - Add support for providing legacy graphics rom support
+  - Fix locate_device_path
+  - Add support for finding the parent device in a device path
+  - Add mechanism for getting runtime pages
+  - Add support for the PCI and PCI root bridge IO protocols
+  - Merge -76 changes upstream.
+
 * Wed Aug 17 2011 Peter Jones <pjones at redhat.com> - 0.97-76
 - Fix stack alignment on UEFI machines (replaces patch in -74)
   Resolves: rhbz#677468
 - Allow booting from higher drive numbers
   Resolves: rhbz#671355
 - Conflict with grub2
-  Resolves: rhbz#731226
 
 * Mon Jun 06 2011 Peter Jones <pjones at redhat.com> - 0.97-75
 - Update to Fedora-16 branch.


More information about the scm-commits mailing list