[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,
¤t_partition, ¤t_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