merge mainline into net

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-12-15 20:51:35 +01:00
commit bd67ad0f70
335 changed files with 22289 additions and 5940 deletions

View file

@ -48,6 +48,7 @@ grub-kbdcomp
grub-macho2img grub-macho2img
grub-menulst2cfg grub-menulst2cfg
grub-mk* grub-mk*
grub-mount
grub-pe2elf grub-pe2elf
grub-probe grub-probe
grub_probe_init.c grub_probe_init.c

2408
ChangeLog

File diff suppressed because it is too large Load diff

View file

@ -33,6 +33,8 @@ library = {
library = { library = {
name = libgrubmods.a; name = libgrubmods.a;
cflags = '$(CFLAGS_POSIX) -Wno-undef';
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(top_srcdir)/grub-core/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
common_nodist = grub_script.tab.c; common_nodist = grub_script.tab.c;
common_nodist = grub_script.yy.c; common_nodist = grub_script.yy.c;
@ -41,6 +43,7 @@ library = {
common_nodist = grub_script.tab.h; common_nodist = grub_script.tab.h;
common = grub-core/commands/blocklist.c; common = grub-core/commands/blocklist.c;
common = grub-core/commands/xnu_uuid.c;
common = grub-core/commands/testload.c; common = grub-core/commands/testload.c;
common = grub-core/commands/ls.c; common = grub-core/commands/ls.c;
common = grub-core/disk/dmraid_nvidia.c; common = grub-core/disk/dmraid_nvidia.c;
@ -52,14 +55,13 @@ library = {
common = grub-core/disk/raid6_recover.c; common = grub-core/disk/raid6_recover.c;
common = grub-core/disk/raid.c; common = grub-core/disk/raid.c;
common = grub-core/fs/affs.c; common = grub-core/fs/affs.c;
common = grub-core/fs/afs_be.c;
common = grub-core/fs/afs.c; common = grub-core/fs/afs.c;
common = grub-core/fs/befs_be.c; common = grub-core/fs/bfs.c;
common = grub-core/fs/befs.c;
common = grub-core/fs/btrfs.c; common = grub-core/fs/btrfs.c;
common = grub-core/fs/cpio.c; common = grub-core/fs/cpio.c;
common = grub-core/fs/ext2.c; common = grub-core/fs/ext2.c;
common = grub-core/fs/fat.c; common = grub-core/fs/fat.c;
common = grub-core/fs/exfat.c;
common = grub-core/fs/fshelp.c; common = grub-core/fs/fshelp.c;
common = grub-core/fs/hfs.c; common = grub-core/fs/hfs.c;
common = grub-core/fs/hfsplus.c; common = grub-core/fs/hfsplus.c;
@ -80,7 +82,9 @@ library = {
common = grub-core/fs/ufs2.c; common = grub-core/fs/ufs2.c;
common = grub-core/fs/ufs.c; common = grub-core/fs/ufs.c;
common = grub-core/fs/xfs.c; common = grub-core/fs/xfs.c;
common = grub-core/fs/zfs/zfscrypt.c;
common = grub-core/fs/zfs/zfs.c; common = grub-core/fs/zfs/zfs.c;
common = grub-core/fs/zfs/zfsinfo.c;
common = grub-core/fs/zfs/zfs_lzjb.c; common = grub-core/fs/zfs/zfs_lzjb.c;
common = grub-core/fs/zfs/zfs_sha256.c; common = grub-core/fs/zfs/zfs_sha256.c;
common = grub-core/fs/zfs/zfs_fletcher.c; common = grub-core/fs/zfs/zfs_fletcher.c;
@ -89,6 +93,8 @@ library = {
common = grub-core/lib/LzFind.c; common = grub-core/lib/LzFind.c;
common = grub-core/lib/LzmaEnc.c; common = grub-core/lib/LzmaEnc.c;
common = grub-core/lib/crc.c; common = grub-core/lib/crc.c;
common = grub-core/lib/adler32.c;
common = grub-core/lib/crc64.c;
common = grub-core/normal/datetime.c; common = grub-core/normal/datetime.c;
common = grub-core/normal/misc.c; common = grub-core/normal/misc.c;
common = grub-core/partmap/acorn.c; common = grub-core/partmap/acorn.c;
@ -97,6 +103,7 @@ library = {
common = grub-core/partmap/gpt.c; common = grub-core/partmap/gpt.c;
common = grub-core/partmap/msdos.c; common = grub-core/partmap/msdos.c;
common = grub-core/partmap/sun.c; common = grub-core/partmap/sun.c;
common = grub-core/partmap/plan.c;
common = grub-core/partmap/dvh.c; common = grub-core/partmap/dvh.c;
common = grub-core/partmap/sunpc.c; common = grub-core/partmap/sunpc.c;
common = grub-core/partmap/bsdlabel.c; common = grub-core/partmap/bsdlabel.c;
@ -106,7 +113,9 @@ library = {
common = grub-core/script/script.c; common = grub-core/script/script.c;
common = grub-core/script/argv.c; common = grub-core/script/argv.c;
common = grub-core/io/gzio.c; common = grub-core/io/gzio.c;
common = grub-core/io/lzopio.c;
common = grub-core/kern/ia64/dl_helper.c; common = grub-core/kern/ia64/dl_helper.c;
common = grub-core/lib/minilzo/minilzo.c;
}; };
program = { program = {
@ -229,6 +238,22 @@ program = {
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
}; };
program = {
name = grub-mount;
mansection = 1;
common_nodist = grub_fstest_init.c;
common = util/grub-mount.c;
common = grub-core/kern/emu/hostfs.c;
common = grub-core/disk/host.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) -lfuse';
condition = COND_GRUB_MOUNT;
};
program = { program = {
name = grub-mkfont; name = grub-mkfont;
mansection = 1; mansection = 1;
@ -359,6 +384,13 @@ script = {
condition = COND_HOST_KFREEBSD; condition = COND_HOST_KFREEBSD;
}; };
script = {
name = '10_illumos';
common = util/grub.d/10_illumos.in;
installdir = grubconf;
condition = COND_HOST_ILLUMOS;
};
script = { script = {
name = '10_netbsd'; name = '10_netbsd';
common = util/grub.d/10_netbsd.in; common = util/grub.d/10_netbsd.in;
@ -645,6 +677,21 @@ program = {
ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
}; };
program = {
testcase;
name = printf_test;
common = tests/printf_unit_test.c;
common = tests/lib/unit_test.c;
common = grub-core/kern/list.c;
common = grub-core/kern/misc.c;
common = grub-core/tests/lib/test.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
program = { program = {
name = grub-menulst2cfg; name = grub-menulst2cfg;
mansection = 1; mansection = 1;

View file

@ -39,6 +39,8 @@
/* Define to 1 to enable disk cache statistics. */ /* Define to 1 to enable disk cache statistics. */
#define DISK_CACHE_STATS @DISK_CACHE_STATS@ #define DISK_CACHE_STATS @DISK_CACHE_STATS@
#define RE_ENABLE_I18N 1
#if defined(__i386__) #if defined(__i386__)
#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1))) #define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1)))
#else #else

View file

@ -154,6 +154,7 @@ case "$host_os" in
linux*) host_kernel=linux ;; linux*) host_kernel=linux ;;
freebsd* | kfreebsd*-gnu) host_kernel=kfreebsd ;; freebsd* | kfreebsd*-gnu) host_kernel=kfreebsd ;;
netbsd*) host_kernel=netbsd ;; netbsd*) host_kernel=netbsd ;;
solaris*) host_kernel=illumos ;;
cygwin) host_kernel=windows ;; cygwin) host_kernel=windows ;;
esac esac
@ -412,6 +413,23 @@ if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then
TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm"
fi fi
# By default, GCC 4.6 generates .eh_frame sections containing unwind
# information in some cases where it previously did not. GRUB doesn't need
# these and they just use up vital space. Restore the old compiler
# behaviour.
AC_CACHE_CHECK([whether -fno-asynchronous-unwind-tables works], [grub_cv_cc_fno_asynchronous_unwind_tables], [
SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fno-dwarf2-cfi-asm"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[grub_cv_cc_fno_asynchronous_unwind_tables=yes],
[grub_cv_cc_fno_asynchronous_unwind_tables=no])
CFLAGS="$SAVE_CFLAGS"
])
if test "x$grub_cv_cc_fno_asynchronous_unwind_tables" = xyes; then
TARGET_CFLAGS="$TARGET_CFLAGS -fno-asynchronous-unwind-tables"
fi
grub_apple_target_cc grub_apple_target_cc
if test x$grub_cv_apple_target_cc = xyes ; then if test x$grub_cv_apple_target_cc = xyes ; then
TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DAPPLE_CC=1" TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DAPPLE_CC=1"
@ -463,6 +481,7 @@ if test "x$target_m32" = x1; then
# Force 32-bit mode. # Force 32-bit mode.
TARGET_CFLAGS="$TARGET_CFLAGS -m32" TARGET_CFLAGS="$TARGET_CFLAGS -m32"
TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m32" TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m32"
TARGET_CPPFLAGS="$TARGET_CPPFLAGS -m32"
TARGET_LDFLAGS="$TARGET_LDFLAGS -m32" TARGET_LDFLAGS="$TARGET_LDFLAGS -m32"
TARGET_MODULE_FORMAT="elf32" TARGET_MODULE_FORMAT="elf32"
fi fi
@ -471,6 +490,7 @@ if test "x$target_m64" = x1; then
# Force 64-bit mode. # Force 64-bit mode.
TARGET_CFLAGS="$TARGET_CFLAGS -m64" TARGET_CFLAGS="$TARGET_CFLAGS -m64"
TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m64" TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m64"
TARGET_CPPFLAGS="$TARGET_CPPFLAGS -m64"
TARGET_LDFLAGS="$TARGET_LDFLAGS -m64" TARGET_LDFLAGS="$TARGET_LDFLAGS -m64"
TARGET_MODULE_FORMAT="elf64" TARGET_MODULE_FORMAT="elf64"
fi fi
@ -587,7 +607,7 @@ CFLAGS="$CFLAGS -Wl,--defsym,abort=main"
fi fi
# Check for libgcc symbols # Check for libgcc symbols
AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x __ia64_trampoline __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3 __moddi3 __divdi3) AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x __ia64_trampoline __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3 __moddi3 __divdi3 __ctzdi2 __ctzsi2)
if test "x$TARGET_APPLE_CC" = x1 ; then if test "x$TARGET_APPLE_CC" = x1 ; then
CFLAGS="$TARGET_CFLAGS -nostdlib" CFLAGS="$TARGET_CFLAGS -nostdlib"
@ -867,6 +887,37 @@ AC_SUBST([enable_grub_mkfont])
AC_SUBST([freetype_cflags]) AC_SUBST([freetype_cflags])
AC_SUBST([freetype_libs]) AC_SUBST([freetype_libs])
AC_ARG_ENABLE([grub-mount],
[AS_HELP_STRING([--enable-grub-mount],
[build and install the `grub-mount' utility (default=guessed)])])
if test x"$enable_grub_mount" = xno ; then
grub_mount_excuse="explicitly disabled"
fi
if test x"$grub_mount_excuse" = x ; then
AC_CHECK_LIB([fuse], [fuse_main_real], [],
[grub_mount_excuse="need FUSE library"])
fi
if test x"$grub_mount_excuse" = x ; then
# Check for fuse headers.
SAVED_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26"
AC_CHECK_HEADERS([fuse/fuse.h], [],
[grub_mount_excuse=["need FUSE headers"]])
CPPFLAGS="$SAVED_CPPFLAGS"
fi
if test x"$enable_grub_mount" = xyes && test x"$grub_mount_excuse" != x ; then
AC_MSG_ERROR([grub-mount was explicitly requested but can't be compiled])
fi
if test x"$grub_mount_excuse" = x ; then
enable_grub_mount=yes
else
enable_grub_mount=no
fi
AC_SUBST([enable_grub_mount])
AC_ARG_ENABLE([device-mapper], AC_ARG_ENABLE([device-mapper],
[AS_HELP_STRING([--enable-device-mapper], [AS_HELP_STRING([--enable-device-mapper],
[enable Linux device-mapper support (default=guessed)])]) [enable Linux device-mapper support (default=guessed)])])
@ -974,12 +1025,14 @@ AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux])
AM_CONDITIONAL([COND_HOST_NETBSD], [test x$host_kernel = xnetbsd]) AM_CONDITIONAL([COND_HOST_NETBSD], [test x$host_kernel = xnetbsd])
AM_CONDITIONAL([COND_HOST_WINDOWS], [test x$host_kernel = xwindows]) AM_CONDITIONAL([COND_HOST_WINDOWS], [test x$host_kernel = xwindows])
AM_CONDITIONAL([COND_HOST_KFREEBSD], [test x$host_kernel = xkfreebsd]) AM_CONDITIONAL([COND_HOST_KFREEBSD], [test x$host_kernel = xkfreebsd])
AM_CONDITIONAL([COND_HOST_ILLUMOS], [test x$host_kernel = xillumos])
AM_CONDITIONAL([COND_MAN_PAGES], [test x$cross_compiling = xno -a x$HELP2MAN != x]) AM_CONDITIONAL([COND_MAN_PAGES], [test x$cross_compiling = xno -a x$HELP2MAN != x])
AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes])
AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes])
AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes])
AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes]) AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes])
AM_CONDITIONAL([COND_GRUB_MOUNT], [test x$enable_grub_mount = xyes])
AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x])
AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x])
AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1]) AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1])
@ -1066,5 +1119,10 @@ echo grub-mkfont: Yes
else else
echo grub-mkfont: No "($grub_mkfont_excuse)" echo grub-mkfont: No "($grub_mkfont_excuse)"
fi fi
if [ x"$grub_mount_excuse" = x ]; then
echo grub-mount: Yes
else
echo grub-mount: No "($grub_mount_excuse)"
fi
echo "*******************************************************" echo "*******************************************************"
] ]

View file

@ -3943,6 +3943,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
@item @tab BIOS @tab Coreboot @item @tab BIOS @tab Coreboot
@item BIOS chainloading @tab yes @tab no (1) @item BIOS chainloading @tab yes @tab no (1)
@item NTLDR @tab yes @tab no (1) @item NTLDR @tab yes @tab no (1)
@item Plan9 @tab yes @tab no (1)
@item Freedos @tab yes @tab no (1) @item Freedos @tab yes @tab no (1)
@item FreeBSD bootloader @tab yes @tab crashes (1) @item FreeBSD bootloader @tab yes @tab crashes (1)
@item 32-bit kFreeBSD @tab yes @tab crashes (2,6) @item 32-bit kFreeBSD @tab yes @tab crashes (2,6)
@ -3968,6 +3969,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
@item @tab Multiboot @tab Qemu @item @tab Multiboot @tab Qemu
@item BIOS chainloading @tab no (1) @tab no (1) @item BIOS chainloading @tab no (1) @tab no (1)
@item NTLDR @tab no (1) @tab no (1) @item NTLDR @tab no (1) @tab no (1)
@item Plan9 @tab no (1) @tab no (1)
@item FreeDOS @tab no (1) @tab no (1) @item FreeDOS @tab no (1) @tab no (1)
@item FreeBSD bootloader @tab crashes (1) @tab crashes (1) @item FreeBSD bootloader @tab crashes (1) @tab crashes (1)
@item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6) @item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6)
@ -3993,6 +3995,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
@item @tab 32-bit EFI @tab 64-bit EFI @item @tab 32-bit EFI @tab 64-bit EFI
@item BIOS chainloading @tab no (1) @tab no (1) @item BIOS chainloading @tab no (1) @tab no (1)
@item NTLDR @tab no (1) @tab no (1) @item NTLDR @tab no (1) @tab no (1)
@item Plan9 @tab no (1) @tab no (1)
@item FreeDOS @tab no (1) @tab no (1) @item FreeDOS @tab no (1) @tab no (1)
@item FreeBSD bootloader @tab crashes (1) @tab crashes (1) @item FreeBSD bootloader @tab crashes (1) @tab crashes (1)
@item 32-bit kFreeBSD @tab headless @tab headless @item 32-bit kFreeBSD @tab headless @tab headless
@ -4018,6 +4021,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
@item @tab IEEE1275 @item @tab IEEE1275
@item BIOS chainloading @tab no (1) @item BIOS chainloading @tab no (1)
@item NTLDR @tab no (1) @item NTLDR @tab no (1)
@item Plan9 @tab no (1)
@item FreeDOS @tab no (1) @item FreeDOS @tab no (1)
@item FreeBSD bootloader @tab crashes (1) @item FreeBSD bootloader @tab crashes (1)
@item 32-bit kFreeBSD @tab crashes (6) @item 32-bit kFreeBSD @tab crashes (6)

2
docs/man/grub-mount.h2m Normal file
View file

@ -0,0 +1,2 @@
[NAME]
grub-mount \- export GRUB filesystem with FUSE

View file

@ -568,28 +568,28 @@ f = script_rules()
g = data_rules() g = data_rules()
z = global_variable_initializers() z = global_variable_initializers()
print "[+ AutoGen5 template +]\n" print ("[+ AutoGen5 template +]\n")
for p in GRUB_PLATFORMS: for p in GRUB_PLATFORMS:
print define_macro_for_platform_sources(p) print (define_macro_for_platform_sources(p))
print define_macro_for_platform_nodist_sources(p) print (define_macro_for_platform_nodist_sources(p))
# print define_macro_for_platform_dependencies(p) # print define_macro_for_platform_dependencies(p)
print define_macro_for_platform_startup(p) print (define_macro_for_platform_startup(p))
print define_macro_for_platform_cflags(p) print (define_macro_for_platform_cflags(p))
print define_macro_for_platform_ldadd(p) print (define_macro_for_platform_ldadd(p))
print define_macro_for_platform_ldflags(p) print (define_macro_for_platform_ldflags(p))
print define_macro_for_platform_cppflags(p) print (define_macro_for_platform_cppflags(p))
print define_macro_for_platform_ccasflags(p) print (define_macro_for_platform_ccasflags(p))
print define_macro_for_platform_stripflags(p) print (define_macro_for_platform_stripflags(p))
print define_macro_for_platform_objcopyflags(p) print (define_macro_for_platform_objcopyflags(p))
print define_macro_for_platform_conditionals_if_statement(p) print (define_macro_for_platform_conditionals_if_statement(p))
print define_macro_for_platform_conditionals_endif_statement(p) print (define_macro_for_platform_conditionals_endif_statement(p))
# print z # initializer for all vars # print z # initializer for all vars
print a print (a)
print b print (b)
print c print (c)
print d print (d)
print e print (e)
print f print (f)
print g print (g)

View file

@ -78,13 +78,11 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
if COND_i386_pc if COND_i386_pc
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loader.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h

View file

@ -18,6 +18,18 @@ script = {
common = modinfo.sh.in; common = modinfo.sh.in;
}; };
script = {
installdir = noinst;
name = gmodule.pl;
common = gmodule.pl.in;
};
script = {
installdir = noinst;
name = gdb_grub;
common = gdb_grub.in;
};
kernel = { kernel = {
name = kernel; name = kernel;
@ -34,7 +46,7 @@ kernel = {
ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment'; ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment';
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)'; i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
@ -356,6 +368,15 @@ image = {
enable = mips; enable = mips;
}; };
image = {
name = lzma_decompress;
i386_pc = boot/i386/pc/startup_raw.S;
objcopyflags = '-O binary';
ldflags = '-Wl,-Ttext,0x8200';
enable = i386_pc;
};
image = { image = {
name = fwstart; name = fwstart;
mips_loongson = boot/mips/loongson/fwstart.S; mips_loongson = boot/mips/loongson/fwstart.S;
@ -633,6 +654,20 @@ module = {
emu = lib/emu/halt.c; emu = lib/emu/halt.c;
}; };
module = {
name = reboot;
i386 = lib/i386/reboot.c;
i386 = lib/i386/reboot_trampoline.S;
ia64_efi = lib/efi/reboot.c;
x86_64_efi = lib/efi/reboot.c;
powerpc_ieee1275 = lib/ieee1275/reboot.c;
sparc64_ieee1275 = lib/ieee1275/reboot.c;
mips_arc = lib/mips/arc/reboot.c;
mips_loongson = lib/mips/loongson/reboot.c;
mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
common = commands/reboot.c;
};
module = { module = {
name = hashsum; name = hashsum;
common = commands/hashsum.c; common = commands/hashsum.c;
@ -733,11 +768,6 @@ module = {
common = commands/read.c; common = commands/read.c;
}; };
module = {
name = reboot;
common = commands/reboot.c;
};
module = { module = {
name = search; name = search;
common = commands/search_wrap.c; common = commands/search_wrap.c;
@ -967,24 +997,16 @@ module = {
}; };
module = { module = {
name = afs_be; name = bfs;
common = fs/afs_be.c; common = fs/bfs.c;
};
module = {
name = befs;
common = fs/befs.c;
};
module = {
name = befs_be;
common = fs/befs_be.c;
}; };
module = { module = {
name = btrfs; name = btrfs;
common = fs/btrfs.c; common = fs/btrfs.c;
common = lib/crc.c; common = lib/crc.c;
cflags = '$(CFLAGS_POSIX) -Wno-undef';
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
}; };
module = { module = {
@ -1002,6 +1024,11 @@ module = {
common = fs/fat.c; common = fs/fat.c;
}; };
module = {
name = exfat;
common = fs/exfat.c;
};
module = { module = {
name = fshelp; name = fshelp;
common = fs/fshelp.c; common = fs/fshelp.c;
@ -1110,6 +1137,11 @@ module = {
common = fs/zfs/zfs_fletcher.c; common = fs/zfs/zfs_fletcher.c;
}; };
module = {
name = zfscrypt;
common = fs/zfs/zfscrypt.c;
};
module = { module = {
name = zfsinfo; name = zfsinfo;
common = fs/zfs/zfsinfo.c; common = fs/zfs/zfsinfo.c;
@ -1245,6 +1277,13 @@ module = {
enable = x86; enable = x86;
}; };
module = {
name = plan9;
i386_pc = loader/i386/pc/plan9.c;
enable = i386_pc;
};
module = { module = {
name = linux16; name = linux16;
i386_pc = loader/i386/pc/linux.c; i386_pc = loader/i386/pc/linux.c;
@ -1379,7 +1418,7 @@ module = {
extra_dist = script/yylex.l; extra_dist = script/yylex.l;
extra_dist = script/parser.y; extra_dist = script/parser.y;
cflags = '$(CFLAGS_POSIX) -Wno-error'; cflags = '$(CFLAGS_POSIX)';
cppflags = '$(CPPFLAGS_POSIX)'; cppflags = '$(CPPFLAGS_POSIX)';
}; };
@ -1413,6 +1452,11 @@ module = {
common = partmap/sun.c; common = partmap/sun.c;
}; };
module = {
name = part_plan;
common = partmap/plan.c;
};
module = { module = {
name = part_dvh; name = part_dvh;
common = partmap/dvh.c; common = partmap/dvh.c;
@ -1661,6 +1705,14 @@ module = {
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed'; cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed';
}; };
module = {
name = lzopio;
common = io/lzopio.c;
common = lib/minilzo/minilzo.c;
cflags = '$(CFLAGS_POSIX) -Wno-undef';
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
};
module = { module = {
name = testload; name = testload;
common = commands/testload.c; common = commands/testload.c;
@ -1693,3 +1745,13 @@ module = {
common = commands/cacheinfo.c; common = commands/cacheinfo.c;
condition = COND_ENABLE_CACHE_STATS; condition = COND_ENABLE_CACHE_STATS;
}; };
module = {
name = adler32;
common = lib/adler32.c;
};
module = {
name = crc64;
common = lib/crc64.c;
};

View file

@ -18,7 +18,6 @@
*/ */
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/boot.h>
#include <grub/machine/boot.h> #include <grub/machine/boot.h>
/* /*

View file

@ -18,7 +18,6 @@
*/ */
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/boot.h>
#include <grub/machine/boot.h> #include <grub/machine/boot.h>
#include <grub/machine/kernel.h> #include <grub/machine/kernel.h>
#include <multiboot.h> #include <multiboot.h>

View file

@ -19,7 +19,6 @@
#include <config.h> #include <config.h>
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/boot.h>
#include <grub/machine/boot.h> #include <grub/machine/boot.h>
#include <grub/machine/kernel.h> #include <grub/machine/kernel.h>
#include <multiboot.h> #include <multiboot.h>
@ -200,21 +199,12 @@ real_code_2:
1: 1:
movl %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx
#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200 addl $((0x9000 - 0x8200) - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - 0x200), %ecx
#else
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx
#endif
2: 2:
call LOCAL(move_memory) call LOCAL(move_memory)
movsbl %dh, %eax
movl %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART)
movsbl (reg_edx + 2 - start), %eax
movl %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART)
movb $0xFF, %dh movb $0xFF, %dh
ljmp $(DATA_ADDR >> 4), $0 ljmp $(DATA_ADDR >> 4), $0

View file

@ -0,0 +1,348 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <grub/symbol.h>
#include <grub/offsets.h>
#include <grub/machine/boot.h>
#include <grub/machine/memory.h>
#include <grub/machine/kernel.h>
#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
.file "startup_raw.S"
.text
/* Tell GAS to generate 16-bit instructions so that this code works
in real mode. */
.code16
.globl start, _start
start:
_start:
LOCAL (base):
/*
* Guarantee that "main" is loaded at 0x0:0x8200.
*/
#ifdef __APPLE__
ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000)
#else
ljmp $0, $ABS(LOCAL (codestart))
#endif
/*
* This is a special data area.
*/
. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
LOCAL(compressed_size):
.long 0
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
LOCAL(uncompressed_size):
.long 0
. = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
reed_solomon_redundancy:
.long 0
/*
* This is the area for all of the special variables.
*/
LOCAL(boot_dev):
.byte 0xFF, 0xFF, 0xFF
LOCAL(boot_drive):
.byte 0x00
/* the real mode code continues... */
LOCAL (codestart):
cli /* we're not safe here! */
/* set up %ds, %ss, and %es */
xorw %ax, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
/* set up the real mode/BIOS stack */
movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp
movl %ebp, %esp
sti /* we're safe again */
/* save the boot drive */
ADDR32 movb %dl, LOCAL(boot_drive)
/* reset disk system (%ah = 0) */
int $0x13
/* transition to protected mode */
DATA32 call real_to_prot
/* The ".code32" directive takes GAS out of 16-bit mode. */
.code32
incl %eax
cld
call grub_gate_a20
movl LOCAL(compressed_size), %edx
addl $(LOCAL(decompressor_end) - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART - _start), %edx
movl reed_solomon_redundancy, %ecx
leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax
cld
call EXT_C (grub_reed_solomon_recover)
jmp post_reed_solomon
#include "../../../kern/i386/realmode.S"
#include <rs_decoder.S>
.text
. = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART
/*
* Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
* This uses the a.out kludge to load raw binary to the area starting at 1MB,
* and relocates itself after loaded.
*/
.p2align 2 /* force 4-byte alignment */
multiboot_header:
/* magic */
.long 0x1BADB002
/* flags */
.long (1 << 16)
/* checksum */
.long -0x1BADB002 - (1 << 16)
/* header addr */
.long multiboot_header - _start + 0x100000 + 0x200
/* load addr */
.long 0x100000
/* load end addr */
.long 0
/* bss end addr */
.long 0
/* entry addr */
.long multiboot_entry - _start + 0x100000 + 0x200
multiboot_entry:
.code32
/* obtain the boot device */
movl 12(%ebx), %edx
movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp
movl %ebp, %esp
/* relocate the code */
movl $(LOCAL(decompressor_end) + 0x200), %ecx
addl LOCAL(compressed_size) - _start + 0x100000 + 0x200, %ecx
movl $0x100000, %esi
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi
cld
rep
movsb
/* jump to the real address */
movl $multiboot_trampoline, %eax
jmp *%eax
multiboot_trampoline:
/* fill the boot information */
movl %edx, LOCAL(boot_dev)
shrl $24, %edx
/* enter the usual booting */
call prot_to_real
.code16
jmp LOCAL (codestart)
.code32
post_reed_solomon:
#ifdef ENABLE_LZMA
movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi
movl $LOCAL(decompressor_end), %esi
pushl %edi
movl LOCAL (uncompressed_size), %ecx
leal (%edi, %ecx), %ebx
call _LzmaDecodeA
/* _LzmaDecodeA clears DF, so no need to run cld */
popl %esi
#endif
movl LOCAL(boot_dev), %edx
movl $prot_to_real, %edi
movl $real_to_prot, %ecx
jmp *%esi
/*
* grub_gate_a20(int on)
*
* Gate address-line 20 for high memory.
*
* This routine is probably overconservative in what it does, but so what?
*
* It also eats any keystrokes in the keyboard buffer. :-(
*/
grub_gate_a20:
movl %eax, %edx
gate_a20_test_current_state:
/* first of all, test if already in a good state */
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_bios
ret
gate_a20_try_bios:
/* second, try a BIOS call */
pushl %ebp
call prot_to_real
.code16
movw $0x2400, %ax
testb %dl, %dl
jz 1f
incw %ax
1: int $0x15
DATA32 call real_to_prot
.code32
popl %ebp
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_system_control_port_a
ret
gate_a20_try_system_control_port_a:
/*
* In macbook, the keyboard test would hang the machine, so we move
* this forward.
*/
/* fourth, try the system control port A */
inb $0x92
andb $(~0x03), %al
testb %dl, %dl
jz 6f
orb $0x02, %al
6: outb $0x92
/* When turning off Gate A20, do not check the state strictly,
because a failure is not fatal usually, and Gate A20 is always
on some modern machines. */
testb %dl, %dl
jz 7f
call gate_a20_check_state
cmpb %al, %dl
jnz gate_a20_try_keyboard_controller
7: ret
gate_a20_flush_keyboard_buffer:
inb $0x64
andb $0x02, %al
jnz gate_a20_flush_keyboard_buffer
2:
inb $0x64
andb $0x01, %al
jz 3f
inb $0x60
jmp 2b
3:
ret
gate_a20_try_keyboard_controller:
/* third, try the keyboard controller */
call gate_a20_flush_keyboard_buffer
movb $0xd1, %al
outb $0x64
4:
inb $0x64
andb $0x02, %al
jnz 4b
movb $0xdd, %al
testb %dl, %dl
jz 5f
orb $0x02, %al
5: outb $0x60
call gate_a20_flush_keyboard_buffer
/* output a dummy command (USB keyboard hack) */
movb $0xff, %al
outb $0x64
call gate_a20_flush_keyboard_buffer
call gate_a20_check_state
cmpb %al, %dl
/* everything failed, so restart from the beginning */
jnz gate_a20_try_bios
ret
gate_a20_check_state:
/* iterate the checking for a while */
movl $100, %ecx
1:
call 3f
cmpb %al, %dl
jz 2f
loop 1b
2:
ret
3:
pushl %ebx
pushl %ecx
xorl %eax, %eax
/* compare the byte at 0x8000 with that at 0x108000 */
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx
pushl %ebx
/* save the original byte in CL */
movb (%ebx), %cl
/* store the value at 0x108000 in AL */
addl $0x100000, %ebx
movb (%ebx), %al
/* try to set one less value at 0x8000 */
popl %ebx
movb %al, %ch
decb %ch
movb %ch, (%ebx)
/* serialize */
outb %al, $0x80
outb %al, $0x80
/* obtain the value at 0x108000 in CH */
pushl %ebx
addl $0x100000, %ebx
movb (%ebx), %ch
/* this result is 1 if A20 is on or 0 if it is off */
subb %ch, %al
xorb $1, %al
/* restore the original */
popl %ebx
movb %cl, (%ebx)
popl %ecx
popl %ebx
ret
#ifdef ENABLE_LZMA
#include "lzma_decode.S"
#endif
.p2align 4
LOCAL(decompressor_end):

View file

@ -38,13 +38,13 @@ start:
bal codestart bal codestart
nop nop
base: base:
. = _start + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE . = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
compressed_size: compressed_size:
.long 0 .long 0
. = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
uncompressed_size: uncompressed_size:
.long 0 .long 0
. = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR
uncompressed_addr: uncompressed_addr:
.long 0 .long 0
codestart: codestart:
@ -240,9 +240,9 @@ cmdlinedone:
subu $a0, $a0, $t0 subu $a0, $a0, $t0
addu $a0, $a0, $s0 addu $a0, $a0, $s0
lw $a1, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0) lw $a1, (GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0)
lw $a2, (GRUB_KERNEL_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0) lw $a2, (GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0)
lw $a3, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0) lw $a3, (GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0)
move $s1, $a1 move $s1, $a1
/* $a0 contains source compressed address, $a1 is destination, /* $a0 contains source compressed address, $a1 is destination,

View file

@ -17,7 +17,6 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <grub/boot.h>
#include <grub/machine/boot.h> #include <grub/machine/boot.h>
.text .text
@ -29,9 +28,6 @@ pic_base:
call boot_continue call boot_continue
mov %o4, CIF_REG mov %o4, CIF_REG
. = _start + GRUB_BOOT_MACHINE_VER_MAJ
boot_version: .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
/* The offsets to these locations are defined by the /* The offsets to these locations are defined by the
* GRUB_BOOT_MACHINE_foo macros in include/grub/sparc/ieee1275/boot.h, * GRUB_BOOT_MACHINE_foo macros in include/grub/sparc/ieee1275/boot.h,
* and grub-setup uses this to patch these next three values as needed. * and grub-setup uses this to patch these next three values as needed.
@ -44,6 +40,7 @@ boot_version: .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
* After loading in that block we will execute it by jumping to the * After loading in that block we will execute it by jumping to the
* load address plus the size of the prepended A.OUT header (32 bytes). * load address plus the size of the prepended A.OUT header (32 bytes).
*/ */
. = _start + GRUB_BOOT_MACHINE_BOOT_DEVPATH
boot_path: boot_path:
. = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE . = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE
boot_path_end: boot_path_end:

View file

@ -17,7 +17,6 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <grub/boot.h>
#include <grub/machine/boot.h> #include <grub/machine/boot.h>
#include <grub/offsets.h> #include <grub/offsets.h>

View file

@ -97,8 +97,6 @@ grub_cs5536_smbus_wait (grub_port_t smbbase)
if (grub_get_time_ms () > start + 40) if (grub_get_time_ms () > start + 40)
return grub_error (GRUB_ERR_IO, "SM stalled"); return grub_error (GRUB_ERR_IO, "SM stalled");
} }
return GRUB_ERR_NONE;
} }
grub_err_t grub_err_t

View file

@ -1152,8 +1152,8 @@ grub_ohci_check_transfer (grub_usb_controller_t dev,
return parse_halt (dev, transfer, actual); return parse_halt (dev, transfer, actual);
/* Finished ED detection */ /* Finished ED detection */
if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf) == if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xfU) ==
(grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf) ) /* Empty ED */ (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xfU) ) /* Empty ED */
{ {
/* Check the HALT bit */ /* Check the HALT bit */
/* It looks like nonsense - it was tested previously... /* It looks like nonsense - it was tested previously...
@ -1426,7 +1426,7 @@ static struct grub_usb_controller_dev usb_controller =
.detect_dev = grub_ohci_detect_dev .detect_dev = grub_ohci_detect_dev
}; };
static void *fini_hnd; static struct grub_preboot *fini_hnd;
GRUB_MOD_INIT(ohci) GRUB_MOD_INIT(ohci)
{ {

View file

@ -544,8 +544,11 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev,
{ {
grub_size_t actual = 0; grub_size_t actual = 0;
/* Terminate and free. */ /* Terminate and free. */
td_prev->linkptr2 = 0; if (td_prev)
td_prev->linkptr = 1; {
td_prev->linkptr2 = 0;
td_prev->linkptr = 1;
}
if (cdata->td_first) if (cdata->td_first)
grub_free_queue (u, cdata->qh, cdata->td_first, NULL, &actual); grub_free_queue (u, cdata->qh, cdata->td_first, NULL, &actual);

View file

@ -138,6 +138,7 @@ iszero (grub_uint8_t *reg, int size)
return 1; return 1;
} }
#if defined (__i386__) || defined (__x86_64__)
grub_err_t grub_err_t
grub_acpi_create_ebda (void) grub_acpi_create_ebda (void)
{ {
@ -165,7 +166,7 @@ grub_acpi_create_ebda (void)
return 0; return 0;
} }
ebda = (grub_uint8_t *) UINT_TO_PTR ((*((grub_uint16_t *)0x40e)) << 4); ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4);
ebda_kb_len = *(grub_uint16_t *) ebda; ebda_kb_len = *(grub_uint16_t *) ebda;
if (! ebda || ebda_kb_len > 16) if (! ebda || ebda_kb_len > 16)
ebda_kb_len = 0; ebda_kb_len = 0;
@ -173,14 +174,14 @@ grub_acpi_create_ebda (void)
/* FIXME: use low-memory mm allocation once it's available. */ /* FIXME: use low-memory mm allocation once it's available. */
grub_mmap_iterate (find_hook); grub_mmap_iterate (find_hook);
targetebda = (grub_uint8_t *) UINT_TO_PTR (highestlow); targetebda = (grub_uint8_t *) (grub_addr_t) highestlow;
grub_dprintf ("acpi", "creating ebda @%llx\n", grub_dprintf ("acpi", "creating ebda @%llx\n",
(unsigned long long) highestlow); (unsigned long long) highestlow);
if (! highestlow) if (! highestlow)
return grub_error (GRUB_ERR_OUT_OF_MEMORY, return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"couldn't find space for the new EBDA"); "couldn't find space for the new EBDA");
mmapregion = grub_mmap_register (PTR_TO_UINT64 (targetebda), ebda_len, mmapregion = grub_mmap_register ((grub_addr_t) targetebda, ebda_len,
GRUB_MEMORY_RESERVED); GRUB_MEMORY_RESERVED);
if (! mmapregion) if (! mmapregion)
return grub_errno; return grub_errno;
@ -297,6 +298,7 @@ grub_acpi_create_ebda (void)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
#endif
/* Create tables common to ACPIv1 and ACPIv2+ */ /* Create tables common to ACPIv1 and ACPIv2+ */
static void static void
@ -328,13 +330,13 @@ setup_common_tables (void)
if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE, if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE,
sizeof (fadt->hdr.signature)) == 0) sizeof (fadt->hdr.signature)) == 0)
{ {
fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt); fadt->dsdt_addr = (grub_addr_t) table_dsdt;
fadt->facs_addr = facs_addr; fadt->facs_addr = facs_addr;
/* Does a revision 2 exist at all? */ /* Does a revision 2 exist at all? */
if (fadt->hdr.revision >= 3) if (fadt->hdr.revision >= 3)
{ {
fadt->dsdt_xaddr = PTR_TO_UINT64 (table_dsdt); fadt->dsdt_xaddr = (grub_addr_t) table_dsdt;
fadt->facs_xaddr = facs_addr; fadt->facs_xaddr = facs_addr;
} }
@ -365,7 +367,7 @@ setup_common_tables (void)
rsdt->creator_rev = root_creator_rev; rsdt->creator_rev = root_creator_rev;
for (cur = acpi_tables; cur; cur = cur->next) for (cur = acpi_tables; cur; cur = cur->next)
*(rsdt_entry++) = PTR_TO_UINT32 (cur->addr); *(rsdt_entry++) = (grub_addr_t) cur->addr;
/* Recompute checksum. */ /* Recompute checksum. */
rsdt->checksum = 0; rsdt->checksum = 0;
@ -383,7 +385,7 @@ setv1table (void)
sizeof (rsdpv1_new->signature)); sizeof (rsdpv1_new->signature));
grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid)); grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid));
rsdpv1_new->revision = 0; rsdpv1_new->revision = 0;
rsdpv1_new->rsdt_addr = PTR_TO_UINT32 (rsdt_addr); rsdpv1_new->rsdt_addr = (grub_addr_t) rsdt_addr;
rsdpv1_new->checksum = 0; rsdpv1_new->checksum = 0;
rsdpv1_new->checksum = 1 + ~grub_byte_checksum (rsdpv1_new, rsdpv1_new->checksum = 1 + ~grub_byte_checksum (rsdpv1_new,
sizeof (*rsdpv1_new)); sizeof (*rsdpv1_new));
@ -408,7 +410,7 @@ setv2table (void)
xsdt_entry = (grub_uint64_t *)(xsdt + 1); xsdt_entry = (grub_uint64_t *)(xsdt + 1);
for (cur = acpi_tables; cur; cur = cur->next) for (cur = acpi_tables; cur; cur = cur->next)
*(xsdt_entry++) = PTR_TO_UINT64 (cur->addr); *(xsdt_entry++) = (grub_addr_t) cur->addr;
grub_memcpy (&(xsdt->signature), "XSDT", 4); grub_memcpy (&(xsdt->signature), "XSDT", 4);
xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables; xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables;
xsdt->revision = 1; xsdt->revision = 1;
@ -428,12 +430,12 @@ setv2table (void)
grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid, grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid,
sizeof (rsdpv2_new->rsdpv1.oemid)); sizeof (rsdpv2_new->rsdpv1.oemid));
rsdpv2_new->rsdpv1.revision = rev2; rsdpv2_new->rsdpv1.revision = rev2;
rsdpv2_new->rsdpv1.rsdt_addr = PTR_TO_UINT32 (rsdt_addr); rsdpv2_new->rsdpv1.rsdt_addr = (grub_addr_t) rsdt_addr;
rsdpv2_new->rsdpv1.checksum = 0; rsdpv2_new->rsdpv1.checksum = 0;
rsdpv2_new->rsdpv1.checksum = 1 + ~grub_byte_checksum rsdpv2_new->rsdpv1.checksum = 1 + ~grub_byte_checksum
(&(rsdpv2_new->rsdpv1), sizeof (rsdpv2_new->rsdpv1)); (&(rsdpv2_new->rsdpv1), sizeof (rsdpv2_new->rsdpv1));
rsdpv2_new->length = sizeof (*rsdpv2_new); rsdpv2_new->length = sizeof (*rsdpv2_new);
rsdpv2_new->xsdt_addr = PTR_TO_UINT64 (xsdt); rsdpv2_new->xsdt_addr = (grub_addr_t) xsdt;
rsdpv2_new->checksum = 0; rsdpv2_new->checksum = 0;
rsdpv2_new->checksum = 1 + ~grub_byte_checksum (rsdpv2_new, rsdpv2_new->checksum = 1 + ~grub_byte_checksum (rsdpv2_new,
rsdpv2_new->length); rsdpv2_new->length);
@ -463,7 +465,6 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
struct grub_arg_list *state = ctxt->state; struct grub_arg_list *state = ctxt->state;
struct grub_acpi_rsdp_v10 *rsdp; struct grub_acpi_rsdp_v10 *rsdp;
struct efiemu_acpi_table *cur, *t; struct efiemu_acpi_table *cur, *t;
grub_err_t err;
int i, mmapregion; int i, mmapregion;
int numoftables; int numoftables;
@ -506,7 +507,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
/* Set revision variables to replicate the same version as host. */ /* Set revision variables to replicate the same version as host. */
rev1 = ! rsdp->revision; rev1 = ! rsdp->revision;
rev2 = rsdp->revision; rev2 = rsdp->revision;
rsdt = (struct grub_acpi_table_header *) UINT_TO_PTR (rsdp->rsdt_addr); rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr;
/* Load host tables. */ /* Load host tables. */
for (entry_ptr = (grub_uint32_t *) (rsdt + 1); for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt) entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
@ -516,7 +517,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
char signature[5]; char signature[5];
struct efiemu_acpi_table *table; struct efiemu_acpi_table *table;
struct grub_acpi_table_header *curtable struct grub_acpi_table_header *curtable
= (struct grub_acpi_table_header *) UINT_TO_PTR (*entry_ptr); = (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr;
signature[4] = 0; signature[4] = 0;
for (i = 0; i < 4;i++) for (i = 0; i < 4;i++)
signature[i] = grub_tolower (curtable->signature[i]); signature[i] = grub_tolower (curtable->signature[i]);
@ -540,7 +541,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
/* Load DSDT if not excluded. */ /* Load DSDT if not excluded. */
dsdt = (struct grub_acpi_table_header *) dsdt = (struct grub_acpi_table_header *)
UINT_TO_PTR (fadt->dsdt_addr); (grub_addr_t) fadt->dsdt_addr;
if (dsdt && (! exclude || ! grub_strword (exclude, "dsdt")) if (dsdt && (! exclude || ! grub_strword (exclude, "dsdt"))
&& (! load_only || grub_strword (load_only, "dsdt")) && (! load_only || grub_strword (load_only, "dsdt"))
&& dsdt->length >= sizeof (*dsdt)) && dsdt->length >= sizeof (*dsdt))
@ -732,13 +733,20 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
} }
acpi_tables = 0; acpi_tables = 0;
if (! state[9].set && (err = grub_acpi_create_ebda ())) #if defined (__i386__) || defined (__x86_64__)
if (! state[9].set)
{ {
rsdpv1_new = 0; grub_err_t err;
rsdpv2_new = 0; err = grub_acpi_create_ebda ();
grub_mmap_free_and_unregister (mmapregion); if (err)
return err; {
rsdpv1_new = 0;
rsdpv2_new = 0;
grub_mmap_free_and_unregister (mmapregion);
return err;
}
} }
#endif
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
{ {

View file

@ -33,6 +33,7 @@ typedef uint8_t grub_uint8_t;
#endif #endif
#include <grub/acpi.h> #include <grub/acpi.h>
#include <grub/i18n.h>
#ifndef GRUB_DSDT_TEST #ifndef GRUB_DSDT_TEST
#include <grub/misc.h> #include <grub/misc.h>
@ -327,6 +328,6 @@ grub_acpi_halt (void)
grub_millisleep (1500); grub_millisleep (1500);
grub_printf ("ACPI shutdown failed\n"); grub_puts_ (N_("ACPI shutdown failed"));
} }
#endif #endif

View file

@ -31,17 +31,17 @@ static grub_err_t (*grub_loader_boot_func) (void);
static grub_err_t (*grub_loader_unload_func) (void); static grub_err_t (*grub_loader_unload_func) (void);
static int grub_loader_noreturn; static int grub_loader_noreturn;
struct grub_preboot_t struct grub_preboot
{ {
grub_err_t (*preboot_func) (int); grub_err_t (*preboot_func) (int);
grub_err_t (*preboot_rest_func) (void); grub_err_t (*preboot_rest_func) (void);
grub_loader_preboot_hook_prio_t prio; grub_loader_preboot_hook_prio_t prio;
struct grub_preboot_t *next; struct grub_preboot *next;
struct grub_preboot_t *prev; struct grub_preboot *prev;
}; };
static int grub_loader_loaded; static int grub_loader_loaded;
static struct grub_preboot_t *preboots_head = 0, static struct grub_preboot *preboots_head = 0,
*preboots_tail = 0; *preboots_tail = 0;
int int
@ -51,18 +51,18 @@ grub_loader_is_loaded (void)
} }
/* Register a preboot hook. */ /* Register a preboot hook. */
void * struct grub_preboot *
grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn), grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
grub_err_t (*preboot_rest_func) (void), grub_err_t (*preboot_rest_func) (void),
grub_loader_preboot_hook_prio_t prio) grub_loader_preboot_hook_prio_t prio)
{ {
struct grub_preboot_t *cur, *new_preboot; struct grub_preboot *cur, *new_preboot;
if (! preboot_func && ! preboot_rest_func) if (! preboot_func && ! preboot_rest_func)
return 0; return 0;
new_preboot = (struct grub_preboot_t *) new_preboot = (struct grub_preboot *)
grub_malloc (sizeof (struct grub_preboot_t)); grub_malloc (sizeof (struct grub_preboot));
if (! new_preboot) if (! new_preboot)
{ {
grub_error (GRUB_ERR_OUT_OF_MEMORY, "hook not added"); grub_error (GRUB_ERR_OUT_OF_MEMORY, "hook not added");
@ -96,9 +96,9 @@ grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
} }
void void
grub_loader_unregister_preboot_hook (void *hnd) grub_loader_unregister_preboot_hook (struct grub_preboot *hnd)
{ {
struct grub_preboot_t *preb = hnd; struct grub_preboot *preb = hnd;
if (preb->next) if (preb->next)
preb->next->prev = preb->prev; preb->next->prev = preb->prev;
@ -143,7 +143,7 @@ grub_err_t
grub_loader_boot (void) grub_loader_boot (void)
{ {
grub_err_t err = GRUB_ERR_NONE; grub_err_t err = GRUB_ERR_NONE;
struct grub_preboot_t *cur; struct grub_preboot *cur;
if (! grub_loader_loaded) if (! grub_loader_loaded)
return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel"); return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel");

View file

@ -31,14 +31,14 @@ grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)),
unsigned long hits, misses; unsigned long hits, misses;
grub_disk_cache_get_performance (&hits, &misses); grub_disk_cache_get_performance (&hits, &misses);
grub_printf ("Disk cache: hits = %lu, misses = %lu ", hits, misses); grub_printf_ (N_("Disk cache: hits = %lu, misses = %lu "), hits, misses);
if (hits + misses) if (hits + misses)
{ {
unsigned long ratio = hits * 10000 / (hits + misses); unsigned long ratio = hits * 10000 / (hits + misses);
grub_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100); grub_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100);
} }
else else
grub_printf ("(N/A)\n"); grub_puts_ (N_("(N/A)"));
return 0; return 0;
} }

View file

@ -42,8 +42,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
if (argc != 2) if (argc != 2)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");
grub_printf ("Compare file `%s' with `%s':\n", args[0], grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0],
args[1]); args[1]);
file1 = grub_file_open (args[0]); file1 = grub_file_open (args[0]);
file2 = grub_file_open (args[1]); file2 = grub_file_open (args[1]);
@ -51,9 +51,9 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
goto cleanup; goto cleanup;
if (grub_file_size (file1) != grub_file_size (file2)) if (grub_file_size (file1) != grub_file_size (file2))
grub_printf ("Files differ in size: %llu [%s], %llu [%s]\n", grub_printf_ (N_("Files differ in size: %llu [%s], %llu [%s]\n"),
(unsigned long long) grub_file_size (file1), args[0], (unsigned long long) grub_file_size (file1), args[0],
(unsigned long long) grub_file_size (file2), args[1]); (unsigned long long) grub_file_size (file2), args[1]);
else else
{ {
pos = 0; pos = 0;
@ -78,9 +78,9 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
{ {
if (buf1[i] != buf2[i]) if (buf1[i] != buf2[i])
{ {
grub_printf ("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n", grub_printf_ (N_("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n"),
(unsigned long long) (i + pos), buf1[i], args[0], (unsigned long long) (i + pos), buf1[i],
buf2[i], args[1]); args[0], buf2[i], args[1]);
goto cleanup; goto cleanup;
} }
} }
@ -89,7 +89,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
} }
while (rd2); while (rd2);
grub_printf ("The files are identical.\n"); /* TRANSLATORS: it's always exactly 2 files. */
grub_printf_ (N_("The files are identical.\n"));
} }
cleanup: cleanup:

View file

@ -56,24 +56,24 @@ scan_card (grub_pci_device_t dev, grub_pci_id_t pciid)
{ {
grub_target_addr_t base; grub_target_addr_t base;
grub_printf ("Found graphic card: %s\n", p->name); grub_dprintf ("fixvideo", "Found graphic card: %s\n", p->name);
addr += 8 + p->mmio_bar * 4; addr += 8 + p->mmio_bar * 4;
base = grub_pci_read (addr); base = grub_pci_read (addr);
if ((! base) || (base & GRUB_PCI_ADDR_SPACE_IO) || if ((! base) || (base & GRUB_PCI_ADDR_SPACE_IO) ||
(base & GRUB_PCI_ADDR_MEM_PREFETCH)) (base & GRUB_PCI_ADDR_MEM_PREFETCH))
grub_printf ("Invalid MMIO bar %d\n", p->mmio_bar); grub_dprintf ("fixvideo", "Invalid MMIO bar %d\n", p->mmio_bar);
else else
{ {
base &= GRUB_PCI_ADDR_MEM_MASK; base &= GRUB_PCI_ADDR_MEM_MASK;
base += p->mmio_reg; base += p->mmio_reg;
if (*((volatile grub_uint32_t *) base) != p->mmio_old) if (*((volatile grub_uint32_t *) base) != p->mmio_old)
grub_printf ("Old value don't match\n"); grub_dprintf ("fixvideo", "Old value doesn't match\n");
else else
{ {
*((volatile grub_uint32_t *) base) = 0; *((volatile grub_uint32_t *) base) = 0;
if (*((volatile grub_uint32_t *) base)) if (*((volatile grub_uint32_t *) base))
grub_printf ("Set MMIO fails\n"); grub_dprintf ("fixvideo", "Setting MMIO fails\n");
} }
} }
@ -82,7 +82,7 @@ scan_card (grub_pci_device_t dev, grub_pci_id_t pciid)
p++; p++;
} }
grub_printf ("Unknown graphic card: %x\n", pciid); grub_dprintf ("fixvideo", "Unknown graphic card: %x\n", pciid);
} }
return 0; return 0;

View file

@ -49,7 +49,7 @@ enable_rom_area (void)
rom_ptr = (grub_uint32_t *) VBIOS_ADDR; rom_ptr = (grub_uint32_t *) VBIOS_ADDR;
if (*rom_ptr != BLANK_MEM) if (*rom_ptr != BLANK_MEM)
{ {
grub_printf ("ROM image is present.\n"); grub_puts_ (N_("ROM image is present."));
return 0; return 0;
} }
@ -67,7 +67,7 @@ enable_rom_area (void)
*rom_ptr = 0; *rom_ptr = 0;
if (*rom_ptr != 0) if (*rom_ptr != 0)
{ {
grub_printf ("Can\'t enable ROM area.\n"); grub_puts_ (N_("Can\'t enable ROM area."));
return 0; return 0;
} }
@ -209,7 +209,7 @@ GRUB_MOD_INIT(loadbios)
0, N_("Fake BIOS.")); 0, N_("Fake BIOS."));
cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios, cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
"BIOS_DUMP [INT10_DUMP]", N_("BIOS_DUMP [INT10_DUMP]"),
N_("Load BIOS dump.")); N_("Load BIOS dump."));
} }

View file

@ -231,7 +231,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
return grub_errno; return grub_errno;
} }
grub_printf ("New MBR is written to '%s'\n", args[0]); grub_printf_ (N_("New MBR is written to '%s'\n"), args[0]);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }

View file

@ -24,13 +24,12 @@
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
static grub_err_t static grub_err_t __attribute__ ((noreturn))
grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)), grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)), int argc __attribute__ ((unused)),
char **args __attribute__ ((unused))) char **args __attribute__ ((unused)))
{ {
grub_halt (); grub_halt ();
return 0;
} }
static grub_command_t cmd; static grub_command_t cmd;

View file

@ -141,7 +141,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
grub_file_close (file); grub_file_close (file);
if (err) if (err)
{ {
grub_printf ("%s: READ ERROR\n", p); grub_printf_ (N_("%s: READ ERROR\n"), p);
if (!keep) if (!keep)
{ {
grub_file_close (hashlist); grub_file_close (hashlist);
@ -155,7 +155,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
} }
if (grub_crypto_memcmp (expected, actual, hash->mdlen) != 0) if (grub_crypto_memcmp (expected, actual, hash->mdlen) != 0)
{ {
grub_printf ("%s: HASH MISMATCH\n", p); grub_printf_ (N_("%s: HASH MISMATCH\n"), p);
if (!keep) if (!keep)
{ {
grub_file_close (hashlist); grub_file_close (hashlist);
@ -166,7 +166,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
mismatch++; mismatch++;
continue; continue;
} }
grub_printf ("%s: OK\n", p); grub_printf_ (N_("%s: OK\n"), p);
} }
if (mismatch || unread) if (mismatch || unread)
return grub_error (GRUB_ERR_TEST_FAILURE, return grub_error (GRUB_ERR_TEST_FAILURE,
@ -257,8 +257,8 @@ static grub_extcmd_t cmd, cmd_md5, cmd_sha1, cmd_sha256, cmd_sha512, cmd_crc;
GRUB_MOD_INIT(hashsum) GRUB_MOD_INIT(hashsum)
{ {
cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0, cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0,
"hashsum -h HASH [-c FILE [-p PREFIX]] " N_("-h HASH [-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]", "[FILE1 [FILE2 ...]]"),
N_("Compute or check hash checksum."), N_("Compute or check hash checksum."),
options); options);
cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, 0, cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, 0,

View file

@ -165,22 +165,20 @@ grub_hdparm_set_val_cmd (const char * msg, int val,
} }
static const char * static const char *
le16_to_char (char *dest, const grub_uint16_t * src16, unsigned bytes) le16_to_char (grub_uint16_t *dest, const grub_uint16_t * src16, unsigned bytes)
{ {
grub_uint16_t * dest16 = (grub_uint16_t *) dest;
unsigned i; unsigned i;
for (i = 0; i < bytes / 2; i++) for (i = 0; i < bytes / 2; i++)
dest16[i] = grub_be_to_cpu16 (src16[i]); dest[i] = grub_be_to_cpu16 (src16[i]);
return dest; dest[i] = 0;
return (char *) dest;
} }
static void static void
grub_hdparm_print_identify (const char * idbuf) grub_hdparm_print_identify (const grub_uint16_t * idw)
{ {
const grub_uint16_t * idw = (const grub_uint16_t *) idbuf;
/* Print identity strings. */ /* Print identity strings. */
char tmp[40]; grub_uint16_t tmp[21];
grub_printf ("Model: \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40)); grub_printf ("Model: \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40));
grub_printf ("Firmware: \"%.8s\"\n", le16_to_char (tmp, &idw[23], 8)); grub_printf ("Firmware: \"%.8s\"\n", le16_to_char (tmp, &idw[23], 8));
grub_printf ("Serial: \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20)); grub_printf ("Serial: \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20));
@ -377,7 +375,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
/* Print/dump IDENTIFY. */ /* Print/dump IDENTIFY. */
if (ident || dumpid) if (ident || dumpid)
{ {
char buf[GRUB_DISK_SECTOR_SIZE]; grub_uint16_t buf[GRUB_DISK_SECTOR_SIZE / 2];
if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE, if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE,
0, 0, buf, sizeof (buf))) 0, 0, buf, sizeof (buf)))
grub_printf ("Cannot read ATA IDENTIFY data\n"); grub_printf ("Cannot read ATA IDENTIFY data\n");
@ -386,7 +384,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
if (ident) if (ident)
grub_hdparm_print_identify (buf); grub_hdparm_print_identify (buf);
if (dumpid) if (dumpid)
hexdump (0, buf, sizeof (buf)); hexdump (0, (char *) buf, sizeof (buf));
} }
} }

View file

@ -20,6 +20,7 @@
#include <grub/command.h> #include <grub/command.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/cmos.h> #include <grub/cmos.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -86,11 +87,11 @@ static grub_command_t cmd, cmd_clean;
GRUB_MOD_INIT(cmostest) GRUB_MOD_INIT(cmostest)
{ {
cmd = grub_register_command ("cmostest", grub_cmd_cmostest, cmd = grub_register_command ("cmostest", grub_cmd_cmostest,
"cmostest BYTE:BIT", N_("BYTE:BIT"),
"Test bit at BYTE:BIT in CMOS."); N_("Test bit at BYTE:BIT in CMOS."));
cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean, cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean,
"cmosclean BYTE:BIT", N_("BYTE:BIT"),
"Clean bit at BYTE:BIT in CMOS."); N_("Clean bit at BYTE:BIT in CMOS."));
} }
GRUB_MOD_FINI(cmostest) GRUB_MOD_FINI(cmostest)

View file

@ -178,11 +178,11 @@ list_mappings (void)
/* Show: list mappings. */ /* Show: list mappings. */
if (! map_head) if (! map_head)
{ {
grub_printf ("No drives have been remapped\n"); grub_puts_ (N_("No drives have been remapped"));
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
grub_printf ("OS disk #num ------> GRUB/BIOS device\n"); grub_puts_ (N_("OS disk #num ------> GRUB/BIOS device"));
drivemap_node_t *curnode = map_head; drivemap_node_t *curnode = map_head;
while (curnode) while (curnode)
{ {
@ -363,7 +363,7 @@ uninstall_int13_handler (void)
static int static int
grub_get_root_biosnumber_drivemap (void) grub_get_root_biosnumber_drivemap (void)
{ {
char *biosnum; const char *biosnum;
int ret = -1; int ret = -1;
grub_device_t dev; grub_device_t dev;

View file

@ -74,27 +74,27 @@ grub_cmd_lsapm (grub_command_t cmd __attribute__ ((unused)),
if (!grub_apm_get_info (&info)) if (!grub_apm_get_info (&info))
return grub_error (GRUB_ERR_IO, "no APM found"); return grub_error (GRUB_ERR_IO, "no APM found");
grub_printf ("Vesion %u.%u\n" grub_printf_ (N_("Vesion %u.%u\n"
"32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n" "32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n"
"16-bit CS = 0x%x, len = 0x%x\n" "16-bit CS = 0x%x, len = 0x%x\n"
"DS = 0x%x, len = 0x%x\n", "DS = 0x%x, len = 0x%x\n"),
info.version >> 8, info.version & 0xff, info.version >> 8, info.version & 0xff,
info.cseg, info.cseg_len, info.offset, info.cseg, info.cseg_len, info.offset,
info.cseg_16, info.cseg_16_len, info.cseg_16, info.cseg_16_len,
info.dseg, info.dseg_len); info.dseg, info.dseg_len);
grub_xputs (info.flags & GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED grub_xputs (info.flags & GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED
? "16-bit protected interface supported\n" ? _("16-bit protected interface supported\n")
: "16-bit protected interface unsupported\n"); : _("16-bit protected interface unsupported\n"));
grub_xputs (info.flags & GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED grub_xputs (info.flags & GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED
? "32-bit protected interface supported\n" ? _("32-bit protected interface supported\n")
: "32-bit protected interface unsupported\n"); : _("32-bit protected interface unsupported\n"));
grub_xputs (info.flags & GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN grub_xputs (info.flags & GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN
? "CPU Idle slows down processor\n" ? _("CPU Idle slows down processor\n")
: "CPU Idle doesn't slow down processor\n"); : _("CPU Idle doesn't slow down processor\n"));
grub_xputs (info.flags & GRUB_APM_FLAGS_DISABLED grub_xputs (info.flags & GRUB_APM_FLAGS_DISABLED
? "APM disabled\n" : "APM enabled\n"); ? _("APM disabled\n") : _("APM enabled\n"));
grub_xputs (info.flags & GRUB_APM_FLAGS_DISENGAGED grub_xputs (info.flags & GRUB_APM_FLAGS_DISENGAGED
? "APM disengaged\n" : "APM engaged\n"); ? _("APM disengaged\n") : _("APM engaged\n"));
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }

View file

@ -26,6 +26,7 @@
#include <grub/extcmd.h> #include <grub/extcmd.h>
#include <grub/cpu/io.h> #include <grub/cpu/io.h>
#include <grub/loader.h> #include <grub/loader.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv2+"); GRUB_MOD_LICENSE ("GPLv2+");
@ -35,23 +36,23 @@ static int keylen = 0;
static int noled = 0; static int noled = 0;
static const struct grub_arg_option options[] = static const struct grub_arg_option options[] =
{ {
{"num", 'n', 0, "set numlock mode", "[on|off]", ARG_TYPE_STRING}, {"num", 'n', 0, N_("set numlock mode"), "[on|off]", ARG_TYPE_STRING},
{"caps", 'c', 0, "set capslock mode", "[on|off]", ARG_TYPE_STRING}, {"caps", 'c', 0, N_("set capslock mode"), "[on|off]", ARG_TYPE_STRING},
{"scroll", 's', 0, "set scrolllock mode", "[on|off]", ARG_TYPE_STRING}, {"scroll", 's', 0, N_("set scrolllock mode"), "[on|off]", ARG_TYPE_STRING},
{"insert", 0, 0, "set insert mode", "[on|off]", ARG_TYPE_STRING}, {"insert", 0, 0, N_("set insert mode"), "[on|off]", ARG_TYPE_STRING},
{"pause", 0, 0, "set pause mode", "[on|off]", ARG_TYPE_STRING}, {"pause", 0, 0, N_("set pause mode"), "[on|off]", ARG_TYPE_STRING},
{"left-shift", 0, 0, "press left shift", "[on|off]", ARG_TYPE_STRING}, {"left-shift", 0, 0, N_("press left shift"), "[on|off]", ARG_TYPE_STRING},
{"right-shift", 0, 0, "press right shift", "[on|off]", ARG_TYPE_STRING}, {"right-shift", 0, 0, N_("press right shift"), "[on|off]", ARG_TYPE_STRING},
{"sysrq", 0, 0, "press SysRq", "[on|off]", ARG_TYPE_STRING}, {"sysrq", 0, 0, N_("press SysRq"), "[on|off]", ARG_TYPE_STRING},
{"numkey", 0, 0, "press NumLock key", "[on|off]", ARG_TYPE_STRING}, {"numkey", 0, 0, N_("press NumLock key"), "[on|off]", ARG_TYPE_STRING},
{"capskey", 0, 0, "press CapsLock key", "[on|off]", ARG_TYPE_STRING}, {"capskey", 0, 0, N_("press CapsLock key"), "[on|off]", ARG_TYPE_STRING},
{"scrollkey", 0, 0, "press ScrollLock key", "[on|off]", ARG_TYPE_STRING}, {"scrollkey", 0, 0, N_("press ScrollLock key"), "[on|off]", ARG_TYPE_STRING},
{"insertkey", 0, 0, "press Insert key", "[on|off]", ARG_TYPE_STRING}, {"insertkey", 0, 0, N_("press Insert key"), "[on|off]", ARG_TYPE_STRING},
{"left-alt", 0, 0, "press left alt", "[on|off]", ARG_TYPE_STRING}, {"left-alt", 0, 0, N_("press left alt"), "[on|off]", ARG_TYPE_STRING},
{"right-alt", 0, 0, "press right alt", "[on|off]", ARG_TYPE_STRING}, {"right-alt", 0, 0, N_("press right alt"), "[on|off]", ARG_TYPE_STRING},
{"left-ctrl", 0, 0, "press left ctrl", "[on|off]", ARG_TYPE_STRING}, {"left-ctrl", 0, 0, N_("press left ctrl"), "[on|off]", ARG_TYPE_STRING},
{"right-ctrl", 0, 0, "press right ctrl", "[on|off]", ARG_TYPE_STRING}, {"right-ctrl", 0, 0, N_("press right ctrl"), "[on|off]", ARG_TYPE_STRING},
{"no-led", 0, 0, "don't update LED state", 0, 0}, {"no-led", 0, 0, N_("don't update LED state"), 0, 0},
{0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0}
}; };
static int simple_flag_offsets[] static int simple_flag_offsets[]
@ -62,8 +63,8 @@ static grub_uint32_t andmask = 0xffffffff, ormask = 0;
struct struct
keysym keysym
{ {
char *unshifted_name; /* the name in unshifted state */ const char *unshifted_name; /* the name in unshifted state */
char *shifted_name; /* the name in shifted state */ const char *shifted_name; /* the name in shifted state */
unsigned char unshifted_ascii; /* the ascii code in unshifted state */ unsigned char unshifted_ascii; /* the ascii code in unshifted state */
unsigned char shifted_ascii; /* the ascii code in shifted state */ unsigned char shifted_ascii; /* the ascii code in shifted state */
unsigned char keycode; /* keyboard scancode */ unsigned char keycode; /* keyboard scancode */
@ -364,13 +365,13 @@ grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args)
} }
static grub_extcmd_t cmd; static grub_extcmd_t cmd;
static void *preboot_hook; static struct grub_preboot *preboot_hook;
GRUB_MOD_INIT (sendkey) GRUB_MOD_INIT (sendkey)
{ {
cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, 0, cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, 0,
"sendkey [KEYSTROKE1] [KEYSTROKE2] ...", N_("[KEYSTROKE1] [KEYSTROKE2] ..."),
"Emulate a keystroke", options); N_("Emulate a keystroke"), options);
preboot_hook preboot_hook
= grub_loader_register_preboot_hook (grub_sendkey_preboot, = grub_loader_register_preboot_hook (grub_sendkey_preboot,

View file

@ -31,7 +31,7 @@ grub_cmd_suspend (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)), int argc __attribute__ ((unused)),
char **args __attribute__ ((unused))) char **args __attribute__ ((unused)))
{ {
grub_printf ("Run 'go' to resume GRUB.\n"); grub_puts_ (N_("Run 'go' to resume GRUB."));
grub_ieee1275_enter (); grub_ieee1275_enter ();
grub_cls (); grub_cls ();
return 0; return 0;

View file

@ -344,7 +344,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
int bsd_part = -1; int bsd_part = -1;
{ {
grub_device_t dev; grub_device_t dev;
char *hdbiasstr; const char *hdbiasstr;
int hdbias = 0; int hdbias = 0;
hdbiasstr = grub_env_get ("legacy_hdbias"); hdbiasstr = grub_env_get ("legacy_hdbias");
if (hdbiasstr) if (hdbiasstr)
@ -723,7 +723,7 @@ grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unuse
if (argc == 0) if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected");
grub_printf ("Enter password:"); grub_puts_ (N_("Enter password: "));
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
return GRUB_ACCESS_DENIED; return GRUB_ACCESS_DENIED;

View file

@ -43,7 +43,7 @@ open_envblk_file (char *filename)
if (! filename) if (! filename)
{ {
char *prefix; const char *prefix;
prefix = grub_env_get ("prefix"); prefix = grub_env_get ("prefix");
if (prefix) if (prefix)
@ -346,7 +346,7 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
while (argc) while (argc)
{ {
char *value; const char *value;
value = grub_env_get (args[0]); value = grub_env_get (args[0]);
if (value) if (value)

View file

@ -26,13 +26,13 @@ GRUB_MOD_LICENSE ("GPLv3+");
static const char *names[] = static const char *names[] =
{ {
[GRUB_MEMORY_AVAILABLE] = "available", [GRUB_MEMORY_AVAILABLE] = N_("available"),
[GRUB_MEMORY_RESERVED] = "reserved", [GRUB_MEMORY_RESERVED] = N_("reserved"),
[GRUB_MEMORY_ACPI] = "ACPI reclamaible", [GRUB_MEMORY_ACPI] = N_("ACPI reclamaible"),
[GRUB_MEMORY_NVS] = "NVS", [GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage"),
[GRUB_MEMORY_BADRAM] = "BadRAM", [GRUB_MEMORY_BADRAM] = N_("BadRAM"),
[GRUB_MEMORY_CODE] = "firmware code", [GRUB_MEMORY_CODE] = N_("firmware code"),
[GRUB_MEMORY_HOLE] = "hole" [GRUB_MEMORY_HOLE] = N_("hole")
}; };
static grub_err_t static grub_err_t
@ -46,11 +46,11 @@ grub_cmd_lsmmap (grub_command_t cmd __attribute__ ((unused)),
grub_memory_type_t type) grub_memory_type_t type)
{ {
if (type < ARRAY_SIZE (names) && names[type]) if (type < ARRAY_SIZE (names) && names[type])
grub_printf ("base_addr = 0x%llx, length = 0x%llx, %s\n", grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, %s\n"),
(long long) addr, (long long) size, names[type]); (long long) addr, (long long) size, _(names[type]));
else else
grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n", grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n"),
(long long) addr, (long long) size, type); (long long) addr, (long long) size, type);
return 0; return 0;
} }
#ifndef GRUB_MACHINE_EMU #ifndef GRUB_MACHINE_EMU

View file

@ -29,7 +29,7 @@ struct grub_pci_classname
{ {
int class; int class;
int subclass; int subclass;
char *desc; const char *desc;
}; };
static const struct grub_pci_classname grub_pci_classes[] = static const struct grub_pci_classname grub_pci_classes[] =

View file

@ -31,7 +31,7 @@ static grub_command_t cmd_write_byte, cmd_write_word, cmd_write_dword;
static const struct grub_arg_option options[] = static const struct grub_arg_option options[] =
{ {
{0, 'v', 0, N_("Save read value into variable VARNAME."), {0, 'v', 0, N_("Save read value into variable VARNAME."),
"VARNAME", ARG_TYPE_STRING}, N_("VARNAME"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0}
}; };

View file

@ -28,19 +28,19 @@
static const struct grub_arg_option options[] = static const struct grub_arg_option options[] =
{ {
{"class", 1, GRUB_ARG_OPTION_REPEATABLE, {"class", 1, GRUB_ARG_OPTION_REPEATABLE,
N_("Menu entry type."), "STRING", ARG_TYPE_STRING}, N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING},
{"users", 2, 0, {"users", 2, 0,
N_("Users allowed to boot this entry."), "USERNAME", ARG_TYPE_STRING}, N_("Users allowed to boot this entry."), N_("USERNAME"), ARG_TYPE_STRING},
{"hotkey", 3, 0, {"hotkey", 3, 0,
N_("Keyboard key for this entry."), "KEY", ARG_TYPE_STRING}, N_("Keyboard key for this entry."), N_("KEY"), ARG_TYPE_STRING},
{"source", 4, 0, {"source", 4, 0,
N_("Menu entry definition as a string."), "STRING", ARG_TYPE_STRING}, N_("Menu entry definition as a string."), N_("STRING"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0}
}; };
static struct static struct
{ {
char *name; const char *name;
int key; int key;
} hotkey_aliases[] = } hotkey_aliases[] =
{ {

View file

@ -145,7 +145,7 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
{ {
grub_dl_t mod; grub_dl_t mod;
grub_printf ("Name\tRef Count\tDependencies\n"); grub_printf_ (N_("Name\tRef Count\tDependencies\n"));
FOR_DL_MODULES (mod) FOR_DL_MODULES (mod)
{ {
grub_dl_dep_t dep; grub_dl_dep_t dep;
@ -165,13 +165,13 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
} }
/* exit */ /* exit */
static grub_err_t static grub_err_t __attribute__ ((noreturn))
grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)), grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)), int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused))) char *argv[] __attribute__ ((unused)))
{ {
grub_exit (); grub_exit ();
return 0; /* Not reached. */
} }
static grub_command_t cmd_cat, cmd_help; static grub_command_t cmd_cat, cmd_help;

View file

@ -23,6 +23,7 @@
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/command.h> #include <grub/command.h>
#include <grub/cs5536.h> #include <grub/cs5536.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -38,43 +39,44 @@ grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)),
if (!grub_cs5536_find (&dev)) if (!grub_cs5536_find (&dev))
{ {
grub_printf ("No CS5536 found\n"); grub_puts_ (N_("No CS5536 found"));
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
grub_printf ("CS5536 at %d:%d.%d\n", grub_pci_get_bus (dev), grub_printf_ (N_("CS5536 at %d:%d.%d\n"), grub_pci_get_bus (dev),
grub_pci_get_device (dev), grub_pci_get_function (dev)); grub_pci_get_device (dev), grub_pci_get_function (dev));
err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase); err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase);
if (err) if (err)
return err; return err;
grub_printf ("SMB base = 0x%x\n", smbbase); grub_printf_ (N_("SMB base = 0x%x\n"), smbbase);
for (i = GRUB_SMB_RAM_START_ADDR; for (i = GRUB_SMB_RAM_START_ADDR;
i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++) i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++)
{ {
struct grub_smbus_spd spd; struct grub_smbus_spd spd;
grub_memset (&spd, 0, sizeof (spd)); grub_memset (&spd, 0, sizeof (spd));
grub_printf ("Device %d\n", i); grub_printf_ (N_("Device %d\n"), i);
err = grub_cs5536_read_spd (smbbase, i, &spd); err = grub_cs5536_read_spd (smbbase, i, &spd);
if (err) if (err)
{ {
grub_print_error (); grub_print_error ();
continue; continue;
} }
grub_printf ("Written SPD bytes: %d B.\n", spd.written_size); grub_printf_ (N_("Written SPD bytes: %d B.\n"), spd.written_size);
grub_printf ("Total flash size: %d B.\n", 1 << spd.log_total_flash_size); grub_printf_ (N_("Total flash size: %d B.\n"),
1 << spd.log_total_flash_size);
if (spd.memory_type == GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2) if (spd.memory_type == GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2)
{ {
char str[sizeof (spd.ddr2.part_number) + 1]; char str[sizeof (spd.ddr2.part_number) + 1];
grub_printf ("Memory type: DDR2.\n"); grub_puts_ (N_("Memory type: DDR2."));
grub_memcpy (str, spd.ddr2.part_number, grub_memcpy (str, spd.ddr2.part_number,
sizeof (spd.ddr2.part_number)); sizeof (spd.ddr2.part_number));
str[sizeof (spd.ddr2.part_number)] = 0; str[sizeof (spd.ddr2.part_number)] = 0;
grub_printf ("Part no: %s.\n", str); grub_printf_ (N_("Part no: %s.\n"), str);
} }
else else
grub_printf ("Memory type: Unknown.\n"); grub_puts_ (N_("Memory type: Unknown."));
} }
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
@ -85,7 +87,7 @@ static grub_command_t cmd;
GRUB_MOD_INIT(lsspd) GRUB_MOD_INIT(lsspd)
{ {
cmd = grub_register_command ("lsspd", grub_cmd_lsspd, 0, cmd = grub_register_command ("lsspd", grub_cmd_lsspd, 0,
"Print Memory information."); N_("Print Memory information."));
} }
GRUB_MOD_FINI(lsspd) GRUB_MOD_FINI(lsspd)

View file

@ -37,9 +37,9 @@ static struct grub_parttool *parts = 0;
static int curhandle = 0; static int curhandle = 0;
static grub_dl_t mymod; static grub_dl_t mymod;
static char helpmsg[] = static char helpmsg[] =
"Perform COMMANDS on partition.\n" N_("Perform COMMANDS on partition.\n"
"Use \"parttool PARTITION help\" for the list " "Use \"parttool PARTITION help\" for the list "
"of available commands."; "of available commands.");
int int
grub_parttool_register(const char *part_name, grub_parttool_register(const char *part_name,
@ -128,7 +128,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
break; break;
case GRUB_PARTTOOL_ARG_VAL: case GRUB_PARTTOOL_ARG_VAL:
grub_printf ("=VAL"); grub_xputs (_("=VAL"));
spacing -= 4; spacing -= 4;
break; break;
@ -137,18 +137,18 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
} }
while (spacing-- > 0) while (spacing-- > 0)
grub_printf (" "); grub_printf (" ");
grub_printf ("%s\n", curarg->desc); grub_puts_ (curarg->desc);
} }
} }
if (! found) if (! found)
grub_printf ("Sorry no parttool is available for %s\n", grub_printf_ (N_("Sorry no parttool is available for %s\n"),
dev->disk->partition->partmap->name); dev->disk->partition->partmap->name);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
if (argc < 1) if (argc < 1)
{ {
grub_printf ("%s\n", helpmsg); grub_puts_ (helpmsg);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments");
} }

View file

@ -136,7 +136,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
return err; return err;
if (! label) if (! label)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"uuid for this FS isn't supported yet"); "label for this FS isn't supported yet");
if (state[0].set) if (state[0].set)
grub_env_set (state[0].arg, label); grub_env_set (state[0].arg, label);

View file

@ -24,13 +24,12 @@
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
static grub_err_t static grub_err_t __attribute__ ((noreturn))
grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)), grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)), int argc __attribute__ ((unused)),
char **args __attribute__ ((unused))) char **args __attribute__ ((unused)))
{ {
grub_reboot (); grub_reboot ();
return 0;
} }
static grub_command_t cmd; static grub_command_t cmd;

View file

@ -66,12 +66,12 @@ static struct pci_register pci_registers[] =
static const struct grub_arg_option options[] = static const struct grub_arg_option options[] =
{ {
{0, 'd', 0, "Select device by vendor and device IDs.", {0, 'd', 0, N_("Select device by vendor and device IDs."),
"[vendor]:[device]", ARG_TYPE_STRING}, N_("[vendor]:[device]"), ARG_TYPE_STRING},
{0, 's', 0, "Select device by its position on the bus.", {0, 's', 0, N_("Select device by its position on the bus."),
"[bus]:[slot][.func]", ARG_TYPE_STRING}, N_("[bus]:[slot][.func]"), ARG_TYPE_STRING},
{0, 'v', 0, "Save read value into variable VARNAME.", {0, 'v', 0, N_("Save read value into variable VARNAME."),
"VARNAME", ARG_TYPE_STRING}, N_("VARNAME"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0}
}; };
@ -128,7 +128,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid)
if (!write_mask) if (!write_mask)
{ {
grub_printf ("Register %x of %d:%d.%d is %x\n", regaddr, grub_printf (N_("Register %x of %d:%d.%d is %x\n"), regaddr,
grub_pci_get_bus (dev), grub_pci_get_bus (dev),
grub_pci_get_device (dev), grub_pci_get_device (dev),
grub_pci_get_function (dev), grub_pci_get_function (dev),

View file

@ -47,8 +47,8 @@ grub_cmd_time (grub_command_t ctxt __attribute__ ((unused)),
(cmd->func) (cmd, argc - 1, &args[1]); (cmd->func) (cmd, argc - 1, &args[1]);
end = grub_get_time_ms (); end = grub_get_time_ms ();
grub_printf ("Elapsed time: %d.%03d seconds \n", (end - start) / 1000, grub_printf_ (N_("Elapsed time: %d.%03d seconds \n"), (end - start) / 1000,
(end - start) % 1000); (end - start) % 1000);
return grub_errno; return grub_errno;
} }

View file

@ -52,36 +52,36 @@ hook (const struct grub_video_mode_info *info)
grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp); grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp);
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT) if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
grub_printf ("Text-only "); grub_xputs (_("Text-only "));
/* Show mask and position details for direct color modes. */ /* Show mask and position details for direct color modes. */
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB) if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB)
grub_printf ("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d", grub_printf_ (N_("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d"),
info->red_mask_size, info->red_mask_size,
info->green_mask_size, info->green_mask_size,
info->blue_mask_size, info->blue_mask_size,
info->reserved_mask_size, info->reserved_mask_size,
info->red_field_pos, info->red_field_pos,
info->green_field_pos, info->green_field_pos,
info->blue_field_pos, info->blue_field_pos,
info->reserved_field_pos); info->reserved_field_pos);
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
grub_printf ("Packed "); grub_xputs (_("Packed "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV) if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV)
grub_printf ("YUV "); grub_xputs (_("YUV "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR) if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR)
grub_printf ("Planar "); grub_xputs (_("Planar "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES) if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES)
grub_printf ("Hercules "); grub_xputs (_("Hercules "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA) if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA)
grub_printf ("CGA "); grub_xputs (_("CGA "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_NONCHAIN4) if (info->mode_type & GRUB_VIDEO_MODE_TYPE_NONCHAIN4)
grub_printf ("Non-chain 4 "); grub_xputs (_("Non-chain 4 "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP)
grub_printf ("Monochrome "); grub_xputs (_("Monochrome "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN) if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN)
grub_printf ("Unknown "); grub_xputs (_("Unknown "));
grub_printf ("\n"); grub_xputs ("\n");
return 0; return 0;
} }
@ -93,19 +93,19 @@ print_edid (struct grub_video_edid_info *edid_info)
if (grub_video_edid_checksum (edid_info)) if (grub_video_edid_checksum (edid_info))
{ {
grub_printf (" EDID checksum invalid\n"); grub_puts_ (N_(" EDID checksum invalid"));
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
return; return;
} }
grub_printf (" EDID version: %u.%u\n", grub_printf_ (N_(" EDID version: %u.%u\n"),
edid_info->version, edid_info->revision); edid_info->version, edid_info->revision);
if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height) if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height)
== GRUB_ERR_NONE) == GRUB_ERR_NONE)
grub_printf (" Preferred mode: %ux%u\n", edid_width, edid_height); grub_printf_ (N_(" Preferred mode: %ux%u\n"), edid_width, edid_height);
else else
{ {
grub_printf (" No preferred mode available\n"); grub_printf_ (N_(" No preferred mode available\n"));
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
} }
} }
@ -147,20 +147,20 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
id = grub_video_get_driver_id (); id = grub_video_get_driver_id ();
grub_printf ("List of supported video modes:\n"); grub_puts_ (N_("List of supported video modes:"));
grub_printf ("Legend: P=Packed pixel, D=Direct color, " grub_puts_ (N_("Legend: P=Packed pixel, D=Direct color, "
"mask/pos=R/G/B/reserved\n"); "mask/pos=R/G/B/reserved"));
FOR_VIDEO_ADAPTERS (adapter) FOR_VIDEO_ADAPTERS (adapter)
{ {
struct grub_video_mode_info info; struct grub_video_mode_info info;
struct grub_video_edid_info edid_info; struct grub_video_edid_info edid_info;
grub_printf ("Adapter '%s':\n", adapter->name); grub_printf_ (N_("Adapter '%s':\n"), adapter->name);
if (!adapter->iterate) if (!adapter->iterate)
{ {
grub_printf (" No info available\n"); grub_puts_ (N_(" No info available"));
continue; continue;
} }
@ -178,7 +178,7 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
{ {
if (adapter->init ()) if (adapter->init ())
{ {
grub_printf (" Failed\n"); grub_puts_ (N_(" Failed"));
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
continue; continue;
} }
@ -215,12 +215,13 @@ static grub_command_t cmd_vbe;
GRUB_MOD_INIT(videoinfo) GRUB_MOD_INIT(videoinfo)
{ {
cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, "[WxH[xD]]", cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, N_("[WxH[xD]]"),
N_("List available video modes. If " N_("List available video modes. If "
"resolution is given show only modes" "resolution is given show only modes"
" matching it.")); " matching it."));
#ifdef GRUB_MACHINE_PCBIOS #ifdef GRUB_MACHINE_PCBIOS
cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo, "[WxH[xD]]", cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo,
N_("[WxH[xD]]"),
N_("List available video modes. If " N_("List available video modes. If "
"resolution is given show only modes" "resolution is given show only modes"
" matching it.")); " matching it."));

View file

@ -74,6 +74,8 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
grub_video_create_render_target (&text_layer, width, height, grub_video_create_render_target (&text_layer, width, height,
GRUB_VIDEO_MODE_TYPE_RGB GRUB_VIDEO_MODE_TYPE_RGB
| GRUB_VIDEO_MODE_TYPE_ALPHA); | GRUB_VIDEO_MODE_TYPE_ALPHA);
if (!text_layer)
goto fail;
grub_video_set_active_render_target (text_layer); grub_video_set_active_render_target (text_layer);
@ -191,6 +193,11 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
return grub_errno; return grub_errno;
fail:
grub_video_delete_render_target (text_layer);
grub_video_restore ();
return grub_errno;
} }
static grub_command_t cmd; static grub_command_t cmd;

View file

@ -436,7 +436,7 @@ wildcard_expand (const char *s, char ***strs)
else if (*start == '/') /* no device part */ else if (*start == '/') /* no device part */
{ {
char *root; const char *root;
char *prefix; char *prefix;
root = grub_env_get ("root"); root = grub_env_get ("root");

View file

@ -51,10 +51,18 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
char *ptr; char *ptr;
grub_uint8_t ctx[GRUB_MD_MD5->contextsize]; grub_uint8_t ctx[GRUB_MD_MD5->contextsize];
int low = 0;
if (argc < 1) if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required");
if (argc > 1 && grub_strcmp (args[0], "-l") == 0)
{
low = 1;
argc--;
args++;
}
serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16)); serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16));
GRUB_MD_MD5->init (&ctx); GRUB_MD_MD5->init (&ctx);
@ -75,10 +83,11 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
(unsigned int) xnu_uuid[10], (unsigned int) xnu_uuid[11], (unsigned int) xnu_uuid[10], (unsigned int) xnu_uuid[11],
(unsigned int) xnu_uuid[12], (unsigned int) xnu_uuid[13], (unsigned int) xnu_uuid[12], (unsigned int) xnu_uuid[13],
(unsigned int) xnu_uuid[14], (unsigned int) xnu_uuid[15]); (unsigned int) xnu_uuid[14], (unsigned int) xnu_uuid[15]);
for (ptr = uuid_string; *ptr; ptr++) if (!low)
*ptr = grub_toupper (*ptr); for (ptr = uuid_string; *ptr; ptr++)
*ptr = grub_toupper (*ptr);
if (argc == 1) if (argc == 1)
grub_printf ("%s", uuid_string); grub_printf ("%s\n", uuid_string);
if (argc > 1) if (argc > 1)
grub_env_set (args[1], uuid_string); grub_env_set (args[1], uuid_string);
@ -91,9 +100,10 @@ static grub_command_t cmd;
GRUB_MOD_INIT (xnu_uuid) GRUB_MOD_INIT (xnu_uuid)
{ {
cmd = grub_register_command ("xnu_uuid", grub_cmd_xnu_uuid, cmd = grub_register_command ("xnu_uuid", grub_cmd_xnu_uuid,
N_("GRUBUUID [VARNAME]"), N_("[-l] GRUBUUID [VARNAME]"),
N_("Transform 64-bit UUID to format " N_("Transform 64-bit UUID to format "
"suitable for XNU.")); "suitable for XNU. If -l is given keep "
"it lowercase as done by blkid."));
} }
GRUB_MOD_FINI (xnu_uuid) GRUB_MOD_FINI (xnu_uuid)

View file

@ -305,7 +305,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
else else
grub_dprintf ("ahci", "AHCI is already in OS mode\n"); grub_dprintf ("ahci", "AHCI is already in OS mode\n");
if (~(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)) if (!(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN))
grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n"); grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n");
else else
grub_dprintf ("ahci", "AHCI is in AHCI mode.\n"); grub_dprintf ("ahci", "AHCI is in AHCI mode.\n");
@ -706,7 +706,7 @@ static struct grub_ata_dev grub_ahci_dev =
static void *fini_hnd; static struct grub_preboot *fini_hnd;
GRUB_MOD_INIT(ahci) GRUB_MOD_INIT(ahci)
{ {

View file

@ -29,29 +29,27 @@ static grub_ata_dev_t grub_ata_dev_list;
/* Byteorder has to be changed before strings can be read. */ /* Byteorder has to be changed before strings can be read. */
static void static void
grub_ata_strncpy (char *dst, char *src, grub_size_t len) grub_ata_strncpy (grub_uint16_t *dst16, grub_uint16_t *src16, grub_size_t len)
{ {
grub_uint16_t *src16 = (grub_uint16_t *) src;
grub_uint16_t *dst16 = (grub_uint16_t *) dst;
unsigned int i; unsigned int i;
for (i = 0; i < len / 2; i++) for (i = 0; i < len / 2; i++)
*(dst16++) = grub_be_to_cpu16 (*(src16++)); *(dst16++) = grub_be_to_cpu16 (*(src16++));
dst[len] = '\0'; dst16[i] = 0;
} }
static void static void
grub_ata_dumpinfo (struct grub_ata *dev, char *info) grub_ata_dumpinfo (struct grub_ata *dev, grub_uint16_t *info)
{ {
char text[41]; grub_uint16_t text[21];
/* The device information was read, dump it for debugging. */ /* The device information was read, dump it for debugging. */
grub_ata_strncpy (text, info + 20, 20); grub_ata_strncpy (text, info + 10, 20);
grub_dprintf ("ata", "Serial: %s\n", text); grub_dprintf ("ata", "Serial: %s\n", (char *) text);
grub_ata_strncpy (text, info + 46, 8); grub_ata_strncpy (text, info + 23, 8);
grub_dprintf ("ata", "Firmware: %s\n", text); grub_dprintf ("ata", "Firmware: %s\n", (char *) text);
grub_ata_strncpy (text, info + 54, 40); grub_ata_strncpy (text, info + 27, 40);
grub_dprintf ("ata", "Model: %s\n", text); grub_dprintf ("ata", "Model: %s\n", (char *) text);
if (! dev->atapi) if (! dev->atapi)
{ {
@ -65,7 +63,7 @@ static grub_err_t
grub_atapi_identify (struct grub_ata *dev) grub_atapi_identify (struct grub_ata *dev)
{ {
struct grub_disk_ata_pass_through_parms parms; struct grub_disk_ata_pass_through_parms parms;
char *info; grub_uint16_t *info;
grub_err_t err; grub_err_t err;
info = grub_malloc (GRUB_DISK_SECTOR_SIZE); info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
@ -105,17 +103,19 @@ static grub_err_t
grub_ata_identify (struct grub_ata *dev) grub_ata_identify (struct grub_ata *dev)
{ {
struct grub_disk_ata_pass_through_parms parms; struct grub_disk_ata_pass_through_parms parms;
char *info; grub_uint64_t *info64;
grub_uint32_t *info32;
grub_uint16_t *info16; grub_uint16_t *info16;
grub_err_t err; grub_err_t err;
info = grub_malloc (GRUB_DISK_SECTOR_SIZE); info64 = grub_malloc (GRUB_DISK_SECTOR_SIZE);
if (! info) info32 = (grub_uint32_t *) info64;
info16 = (grub_uint16_t *) info64;
if (! info16)
return grub_errno; return grub_errno;
info16 = (grub_uint16_t *) info;
grub_memset (&parms, 0, sizeof (parms)); grub_memset (&parms, 0, sizeof (parms));
parms.buffer = info; parms.buffer = info16;
parms.size = GRUB_DISK_SECTOR_SIZE; parms.size = GRUB_DISK_SECTOR_SIZE;
parms.taskfile.disk = 0xE0; parms.taskfile.disk = 0xE0;
@ -126,7 +126,7 @@ grub_ata_identify (struct grub_ata *dev)
if (err || parms.size != GRUB_DISK_SECTOR_SIZE) if (err || parms.size != GRUB_DISK_SECTOR_SIZE)
{ {
grub_uint8_t sts = parms.taskfile.status; grub_uint8_t sts = parms.taskfile.status;
grub_free (info); grub_free (info16);
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ
| GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR
@ -167,14 +167,14 @@ grub_ata_identify (struct grub_ata *dev)
/* Determine the amount of sectors. */ /* Determine the amount of sectors. */
if (dev->addr != GRUB_ATA_LBA48) if (dev->addr != GRUB_ATA_LBA48)
dev->size = grub_le_to_cpu32(*((grub_uint32_t *) &info16[60])); dev->size = grub_le_to_cpu32 (info32[30]);
else else
dev->size = grub_le_to_cpu64(*((grub_uint64_t *) &info16[100])); dev->size = grub_le_to_cpu64 (info64[25]);
if (info16[106] & (1 << 12)) if (info16[106] & (1 << 12))
{ {
grub_uint32_t secsize; grub_uint32_t secsize;
secsize = grub_le_to_cpu32 (*((grub_uint32_t *) &info16[117])); secsize = grub_le_to_cpu32 (grub_get_unaligned32 (&info16[117]));
if (secsize & (secsize - 1) || !secsize if (secsize & (secsize - 1) || !secsize
|| secsize > 1048576) || secsize > 1048576)
secsize = 256; secsize = 256;
@ -191,9 +191,9 @@ grub_ata_identify (struct grub_ata *dev)
dev->heads = info16[3]; dev->heads = info16[3];
dev->sectors_per_track = info16[6]; dev->sectors_per_track = info16[6];
grub_ata_dumpinfo (dev, info); grub_ata_dumpinfo (dev, info16);
grub_free(info); grub_free (info16);
return 0; return 0;
} }

View file

@ -791,6 +791,4 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
grub_disk_close (parent); grub_disk_close (parent);
return device_name; return device_name;
} }
return 0;
} }

View file

@ -58,6 +58,38 @@
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
/* Dirty trick to solve circular dependency. */
#ifdef GRUB_UTIL
#include <grub/util/misc.h>
#undef GRUB_MD_SHA256
#undef GRUB_MD_SHA512
static const gcry_md_spec_t *
grub_md_sha256_real (void)
{
const gcry_md_spec_t *ret;
ret = grub_crypto_lookup_md_by_name ("sha256");
if (!ret)
grub_util_error ("Coulnd't load sha256");
return ret;
}
static const gcry_md_spec_t *
grub_md_sha512_real (void)
{
const gcry_md_spec_t *ret;
ret = grub_crypto_lookup_md_by_name ("sha512");
if (!ret)
grub_util_error ("Coulnd't load sha512");
return ret;
}
#define GRUB_MD_SHA256 grub_md_sha256_real()
#define GRUB_MD_SHA512 grub_md_sha512_real()
#endif
struct grub_geli_key struct grub_geli_key
{ {
grub_uint8_t iv_key[64]; grub_uint8_t iv_key[64];
@ -194,7 +226,7 @@ grub_util_get_geli_uuid (const char *dev)
uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1); uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1);
if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0) if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0)
grub_util_error ("couldn't read ELI metadata"); grub_util_error (_("couldn't read ELI metadata"));
COMPILE_TIME_ASSERT (sizeof (header) <= 512); COMPILE_TIME_ASSERT (sizeof (header) <= 512);
header = (void *) &hdr; header = (void *) &hdr;
@ -203,7 +235,7 @@ grub_util_get_geli_uuid (const char *dev)
if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC)) if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC))
|| grub_le_to_cpu32 (header->version) > 5 || grub_le_to_cpu32 (header->version) > 5
|| grub_le_to_cpu32 (header->version) < 1) || grub_le_to_cpu32 (header->version) < 1)
grub_util_error ("wrong ELI magic or version"); grub_util_error (_("wrong ELI magic or version"));
err = make_uuid ((void *) &hdr, uuid); err = make_uuid ((void *) &hdr, uuid);
if (err) if (err)
@ -386,15 +418,15 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
keysize = grub_le_to_cpu16 (header.keylen) / 8; keysize = grub_le_to_cpu16 (header.keylen) / 8;
grub_memset (zero, 0, sizeof (zero)); grub_memset (zero, 0, sizeof (zero));
grub_printf ("Attempting to decrypt master key...\n"); grub_puts_ (N_("Attempting to decrypt master key..."));
/* Get the passphrase from the user. */ /* Get the passphrase from the user. */
tmp = NULL; tmp = NULL;
if (source->partition) if (source->partition)
tmp = grub_partition_get_name (source->partition); tmp = grub_partition_get_name (source->partition);
grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name, grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
source->partition ? "," : "", tmp ? : "", source->partition ? "," : "", tmp ? : "",
dev->uuid); dev->uuid);
grub_free (tmp); grub_free (tmp);
if (!grub_password_get (passphrase, MAX_PASSPHRASE)) if (!grub_password_get (passphrase, MAX_PASSPHRASE))
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
@ -481,7 +513,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
if (grub_memcmp (candidate_key.hmac, key_hmac, dev->hash->mdlen) != 0) if (grub_memcmp (candidate_key.hmac, key_hmac, dev->hash->mdlen) != 0)
continue; continue;
grub_printf ("Slot %d opened\n", i); grub_printf_ (N_("Slot %d opened\n"), i);
/* Set the master key. */ /* Set the master key. */
if (!dev->rekey) if (!dev->rekey)

View file

@ -27,6 +27,7 @@
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/err.h> #include <grub/err.h>
#include <grub/term.h> #include <grub/term.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -621,11 +622,12 @@ grub_disk_biosdisk_fini (void)
GRUB_MOD_INIT(biosdisk) GRUB_MOD_INIT(biosdisk)
{ {
struct grub_biosdisk_cdrp *cdrp struct grub_biosdisk_cdrp *cdrp
= (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; = (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
grub_uint8_t boot_drive;
if (grub_disk_firmware_is_tainted) if (grub_disk_firmware_is_tainted)
{ {
grub_printf ("Firmware is marked as tainted, refusing to initialize.\n"); grub_puts_ (N_("Firmware is marked as tainted, refusing to initialize."));
return; return;
} }
grub_disk_firmware_fini = grub_disk_biosdisk_fini; grub_disk_firmware_fini = grub_disk_biosdisk_fini;
@ -633,15 +635,16 @@ GRUB_MOD_INIT(biosdisk)
grub_memset (cdrp, 0, sizeof (*cdrp)); grub_memset (cdrp, 0, sizeof (*cdrp));
cdrp->size = sizeof (*cdrp); cdrp->size = sizeof (*cdrp);
cdrp->media_type = 0xFF; cdrp->media_type = 0xFF;
if ((! grub_biosdisk_get_cdinfo_int13_extensions (grub_boot_drive, cdrp)) && boot_drive = (grub_boot_device >> 24);
((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK) if ((! grub_biosdisk_get_cdinfo_int13_extensions (boot_drive, cdrp))
== GRUB_BIOSDISK_CDTYPE_NO_EMUL)) && ((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK)
== GRUB_BIOSDISK_CDTYPE_NO_EMUL))
cd_drive = cdrp->drive_no; cd_drive = cdrp->drive_no;
/* Since diskboot.S rejects devices over 0x90 it must be a CD booted with /* Since diskboot.S rejects devices over 0x90 it must be a CD booted with
cdboot.S cdboot.S
*/ */
if (grub_boot_drive >= 0x90) if (boot_drive >= 0x90)
cd_drive = grub_boot_drive; cd_drive = boot_drive;
grub_disk_dev_register (&grub_biosdisk_dev); grub_disk_dev_register (&grub_biosdisk_dev);
} }

View file

@ -316,7 +316,7 @@ luks_recover_key (grub_disk_t source,
if (err) if (err)
return err; return err;
grub_printf ("Attempting to decrypt master key...\n"); grub_puts_ (N_("Attempting to decrypt master key..."));
keysize = grub_be_to_cpu32 (header.keyBytes); keysize = grub_be_to_cpu32 (header.keyBytes);
for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
@ -332,7 +332,7 @@ luks_recover_key (grub_disk_t source,
tmp = NULL; tmp = NULL;
if (source->partition) if (source->partition)
tmp = grub_partition_get_name (source->partition); tmp = grub_partition_get_name (source->partition);
grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name, grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
source->partition ? "," : "", tmp ? : "", source->partition ? "," : "", tmp ? : "",
dev->uuid); dev->uuid);
grub_free (tmp); grub_free (tmp);
@ -434,7 +434,7 @@ luks_recover_key (grub_disk_t source,
continue; continue;
} }
grub_printf ("Slot %d opened\n", i); grub_printf_ (N_("Slot %d opened\n"), i);
/* Set the master key. */ /* Set the master key. */
gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize); gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize);

View file

@ -1,7 +1,7 @@
/* lvm.c - module to read Logical Volumes. */ /* lvm.c - module to read Logical Volumes. */
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. * Copyright (C) 2006,2007,2008,2009,2011 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -23,6 +23,8 @@
#include <grub/err.h> #include <grub/err.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/lvm.h> #include <grub/lvm.h>
#include <grub/partition.h>
#include <grub/i18n.h>
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
#include <grub/emu/misc.h> #include <grub/emu/misc.h>
@ -42,7 +44,7 @@ static int is_lv_readable (struct grub_lvm_lv *lv);
at the number. In case STR is not found, *P will be NULL and the at the number. In case STR is not found, *P will be NULL and the
return value will be 0. */ return value will be 0. */
static int static int
grub_lvm_getvalue (char **p, char *str) grub_lvm_getvalue (char **p, const char *str)
{ {
*p = grub_strstr (*p, str); *p = grub_strstr (*p, str);
if (! *p) if (! *p)
@ -67,7 +69,7 @@ grub_lvm_checkvalue (char **p, char *str, char *tmpl)
#endif #endif
static int static int
grub_lvm_check_flag (char *p, char *str, char *flag) grub_lvm_check_flag (char *p, const char *str, const char *flag)
{ {
int len_str = grub_strlen (str), len_flag = grub_strlen (flag); int len_str = grub_strlen (str), len_flag = grub_strlen (flag);
while (1) while (1)
@ -153,7 +155,11 @@ do_lvm_scan (const char *scan_for)
for (vg = vg_list; vg; vg = vg->next) for (vg = vg_list; vg; vg = vg->next)
for (pv = vg->pvs; pv; pv = pv->next) for (pv = vg->pvs; pv; pv = pv->next)
if (pv->disk && pv->disk->id == disk->id if (pv->disk && pv->disk->id == disk->id
&& pv->disk->dev->id == disk->dev->id) && pv->disk->dev->id == disk->dev->id
&& grub_partition_get_start (pv->disk->partition)
== grub_partition_get_start (disk->partition)
&& grub_disk_get_size (pv->disk)
== grub_disk_get_size (disk))
{ {
grub_disk_close (disk); grub_disk_close (disk);
return 0; return 0;
@ -770,7 +776,7 @@ grub_lvm_memberlist (grub_disk_t disk)
for (pv = lv->vg->pvs; pv; pv = pv->next) for (pv = lv->vg->pvs; pv; pv = pv->next)
{ {
if (!pv->disk) if (!pv->disk)
grub_util_error ("Couldn't find PV %s. Check your device.map", grub_util_error (_("Couldn't find PV %s. Check your device.map"),
pv->name); pv->name);
tmp = grub_malloc (sizeof (*tmp)); tmp = grub_malloc (sizeof (*tmp));
tmp->disk = pv->disk; tmp->disk = pv->disk;

View file

@ -216,11 +216,11 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
array->chunk_size = grub_le_to_cpu32 (sb.chunk_size) >> 9; array->chunk_size = grub_le_to_cpu32 (sb.chunk_size) >> 9;
array->index = grub_le_to_cpu32 (sb.this_disk.number); array->index = grub_le_to_cpu32 (sb.this_disk.number);
array->uuid_len = 16; array->uuid_len = 16;
array->uuid = grub_malloc (16); uuid = grub_malloc (16);
array->uuid = (char *) uuid;
if (!array->uuid) if (!array->uuid)
return grub_errno; return grub_errno;
uuid = (grub_uint32_t *) array->uuid;
uuid[0] = grub_swap_bytes32 (sb.set_uuid0); uuid[0] = grub_swap_bytes32 (sb.set_uuid0);
uuid[1] = grub_swap_bytes32 (sb.set_uuid1); uuid[1] = grub_swap_bytes32 (sb.set_uuid1);
uuid[2] = grub_swap_bytes32 (sb.set_uuid2); uuid[2] = grub_swap_bytes32 (sb.set_uuid2);

View file

@ -86,30 +86,24 @@ static struct grub_disk_dev grub_memdisk_dev =
GRUB_MOD_INIT(memdisk) GRUB_MOD_INIT(memdisk)
{ {
auto int hook (struct grub_module_header *); struct grub_module_header *header;
int hook (struct grub_module_header *header) FOR_MODULES (header)
{ if (header->type == OBJ_TYPE_MEMDISK)
if (header->type == OBJ_TYPE_MEMDISK) {
{ char *memdisk_orig_addr;
char *memdisk_orig_addr; memdisk_orig_addr = (char *) header + sizeof (struct grub_module_header);
memdisk_orig_addr = (char *) header + sizeof (struct grub_module_header);
grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr); grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
memdisk_size = header->size - sizeof (struct grub_module_header); memdisk_size = header->size - sizeof (struct grub_module_header);
memdisk_addr = grub_malloc (memdisk_size); memdisk_addr = grub_malloc (memdisk_size);
grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n"); grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size); grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
grub_disk_dev_register (&grub_memdisk_dev); grub_disk_dev_register (&grub_memdisk_dev);
return 1; break;
} }
return 0;
}
grub_module_iterate (hook);
} }
GRUB_MOD_FINI(memdisk) GRUB_MOD_FINI(memdisk)

View file

@ -116,12 +116,13 @@ grub_pata_wait (void)
static void static void
grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size) grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size)
{ {
grub_uint16_t *buf16 = (grub_uint16_t *) buf;
unsigned int i; unsigned int i;
/* Read in the data, word by word. */ /* Read in the data, word by word. */
for (i = 0; i < size / 2; i++) for (i = 0; i < size / 2; i++)
buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA)); grub_set_unaligned16 (buf + 2 * i,
grub_le_to_cpu16 (grub_inw(dev->ioaddress
+ GRUB_ATA_REG_DATA)));
if (size & 1) if (size & 1)
buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress
+ GRUB_ATA_REG_DATA)); + GRUB_ATA_REG_DATA));
@ -130,12 +131,11 @@ grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size)
static void static void
grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size) grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size)
{ {
grub_uint16_t *buf16 = (grub_uint16_t *) buf;
unsigned int i; unsigned int i;
/* Write the data, word by word. */ /* Write the data, word by word. */
for (i = 0; i < size / 2; i++) for (i = 0; i < size / 2; i++)
grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA); grub_outw(grub_cpu_to_le16 (grub_get_unaligned16 (buf + 2 * i)), dev->ioaddress + GRUB_ATA_REG_DATA);
} }
/* ATA pass through support, used by hdparm.mod. */ /* ATA pass through support, used by hdparm.mod. */

View file

@ -23,6 +23,7 @@
#include <grub/err.h> #include <grub/err.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/raid.h> #include <grub/raid.h>
#include <grub/partition.h>
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
#include <grub/util/misc.h> #include <grub/util/misc.h>
#endif #endif
@ -119,7 +120,11 @@ scan_devices (const char *arname)
struct grub_raid_member *m; struct grub_raid_member *m;
for (m = arr->members; m < arr->members + arr->nr_devs; m++) for (m = arr->members; m < arr->members + arr->nr_devs; m++)
if (m->device && m->device->id == disk->id if (m->device && m->device->id == disk->id
&& m->device->dev->id == m->device->dev->id) && m->device->dev->id == disk->dev->id
&& grub_partition_get_start (m->device->partition)
== grub_partition_get_start (disk->partition)
&& grub_disk_get_size (m->device)
== grub_disk_get_size (disk))
{ {
grub_disk_close (disk); grub_disk_close (disk);
return 0; return 0;
@ -327,23 +332,6 @@ grub_raid_close (grub_disk_t disk __attribute ((unused)))
return; return;
} }
void
grub_raid_block_xor (char *buf1, const char *buf2, int size)
{
grub_size_t *p1;
const grub_size_t *p2;
p1 = (grub_size_t *) buf1;
p2 = (const grub_size_t *) buf2;
size /= GRUB_CPU_SIZEOF_VOID_P;
while (size)
{
*(p1++) ^= *(p2++);
size--;
}
}
static grub_err_t static grub_err_t
grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector, grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf) grub_size_t size, char *buf)

View file

@ -23,6 +23,7 @@
#include <grub/err.h> #include <grub/err.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/raid.h> #include <grub/raid.h>
#include <grub/crypto.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -57,7 +58,7 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr,
return err; return err;
} }
grub_raid_block_xor (buf, buf2, size); grub_crypto_xor (buf, buf2, buf2, size);
} }
grub_free (buf2); grub_free (buf2);

View file

@ -23,70 +23,44 @@
#include <grub/err.h> #include <grub/err.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/raid.h> #include <grub/raid.h>
#include <grub/crypto.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
static grub_uint8_t raid6_table1[256][256]; /* x**y. */
static grub_uint8_t raid6_table2[256][256]; static grub_uint8_t powx[255 * 2];
/* Such an s that x**s = y */
static int powx_inv[256];
static const grub_uint8_t poly = 0x1d;
static void static void
grub_raid_block_mul (grub_uint8_t mul, char *buf, int size) grub_raid_block_mulx (int mul, char *buf, int size)
{ {
int i; int i;
grub_uint8_t *p; grub_uint8_t *p;
p = (grub_uint8_t *) buf; p = (grub_uint8_t *) buf;
for (i = 0; i < size; i++, p++) for (i = 0; i < size; i++, p++)
*p = raid6_table1[mul][*p]; if (*p)
*p = powx[mul + powx_inv[*p]];
} }
static void static void
grub_raid6_init_table (void) grub_raid6_init_table (void)
{ {
int i, j; int i;
for (i = 0; i < 256; i++) grub_uint8_t cur = 1;
raid6_table1[i][1] = raid6_table1[1][i] = i; for (i = 0; i < 255; i++)
{
for (i = 2; i < 256; i++) powx[i] = cur;
for (j = i; j < 256; j++) powx[i + 255] = cur;
{ powx_inv[cur] = i;
int n; if (cur & 0x80)
grub_uint8_t c; cur = (cur << 1) ^ poly;
else
n = i >> 1; cur <<= 1;
}
c = raid6_table1[n][j];
c = (c << 1) ^ ((c & 0x80) ? 0x1d : 0);
if (i & 1)
c ^= j;
raid6_table1[j][i] = raid6_table1[i][j] = c;
}
raid6_table2[0][0] = 1;
for (i = 1; i < 256; i++)
raid6_table2[i][i] = raid6_table1[raid6_table2[i - 1][i - 1]][2];
for (i = 0; i < 254; i++)
for (j = 0; j < 254; j++)
{
grub_uint8_t c, n;
int k;
if (i == j)
continue;
k = i - j;
if (k < 0)
k += 255;
c = n = raid6_table2[k][k] ^ 1;
for (k = 0; k < 253; k++)
c = raid6_table1[c][n];
raid6_table2[i][j] = raid6_table1[raid6_table2[255 - j][255 - j]][c];
}
} }
static grub_err_t static grub_err_t
@ -122,12 +96,12 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
{ {
if ((array->members[pos].device) && if ((array->members[pos].device) &&
(! grub_disk_read (array->members[pos].device, (! grub_disk_read (array->members[pos].device,
array->members[i].start_sector + sector, array->members[pos].start_sector + sector,
0, size, buf))) 0, size, buf)))
{ {
grub_raid_block_xor (pbuf, buf, size); grub_crypto_xor (pbuf, pbuf, buf, size);
grub_raid_block_mul (raid6_table2[i][i], buf, size); grub_raid_block_mulx (i, buf, size);
grub_raid_block_xor (qbuf, buf, size); grub_crypto_xor (qbuf, qbuf, buf, size);
} }
else else
{ {
@ -154,10 +128,10 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
/* One bad device */ /* One bad device */
if ((array->members[p].device) && if ((array->members[p].device) &&
(! grub_disk_read (array->members[p].device, (! grub_disk_read (array->members[p].device,
array->members[i].start_sector + sector, array->members[p].start_sector + sector,
0, size, buf))) 0, size, buf)))
{ {
grub_raid_block_xor (buf, pbuf, size); grub_crypto_xor (buf, buf, pbuf, size);
goto quit; goto quit;
} }
@ -169,17 +143,17 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
if (grub_disk_read (array->members[q].device, if (grub_disk_read (array->members[q].device,
array->members[i].start_sector + sector, 0, size, buf)) array->members[q].start_sector + sector, 0, size, buf))
goto quit; goto quit;
grub_raid_block_xor (buf, qbuf, size); grub_crypto_xor (buf, buf, qbuf, size);
grub_raid_block_mul (raid6_table2[255 - bad1][255 - bad1], buf, grub_raid_block_mulx (255 - bad1, buf,
size); size);
} }
else else
{ {
/* Two bad devices */ /* Two bad devices */
grub_uint8_t c; int c;
if ((! array->members[p].device) || (! array->members[q].device)) if ((! array->members[p].device) || (! array->members[q].device))
{ {
@ -188,26 +162,26 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
} }
if (grub_disk_read (array->members[p].device, if (grub_disk_read (array->members[p].device,
array->members[i].start_sector + sector, array->members[p].start_sector + sector,
0, size, buf)) 0, size, buf))
goto quit; goto quit;
grub_raid_block_xor (pbuf, buf, size); grub_crypto_xor (pbuf, pbuf, buf, size);
if (grub_disk_read (array->members[q].device, if (grub_disk_read (array->members[q].device,
array->members[i].start_sector + sector, array->members[q].start_sector + sector,
0, size, buf)) 0, size, buf))
goto quit; goto quit;
grub_raid_block_xor (qbuf, buf, size); grub_crypto_xor (qbuf, qbuf, buf, size);
c = raid6_table2[bad2][bad1]; c = (255 - bad1 + (255 - powx_inv[(powx[bad2 - bad1 + 255] ^ 1)])) % 255;
grub_raid_block_mul (c, qbuf, size); grub_raid_block_mulx (c, qbuf, size);
c = raid6_table1[raid6_table2[bad2][bad2]][c]; c = (bad2 + c) % 255;
grub_raid_block_mul (c, pbuf, size); grub_raid_block_mulx (c, pbuf, size);
grub_raid_block_xor (pbuf, qbuf, size); grub_crypto_xor (pbuf, pbuf, qbuf, size);
grub_memcpy (buf, pbuf, size); grub_memcpy (buf, pbuf, size);
} }

View file

@ -26,7 +26,7 @@
#define bit_LM (1 << 29) #define bit_LM (1 << 29)
char * const char *
grub_efiemu_get_default_core_name (void) grub_efiemu_get_default_core_name (void)
{ {

View file

@ -149,7 +149,8 @@ grub_efiemu_register_configuration_table (grub_efi_guid_t guid,
if (! get_table && ! data) if (! get_table && ! data)
return grub_error (GRUB_ERR_BAD_ARGUMENT, return grub_error (GRUB_ERR_BAD_ARGUMENT,
"you must set at least get_table or data"); "you must set at least get_table or data");
if ((err = grub_efiemu_unregister_configuration_table (guid))) err = grub_efiemu_unregister_configuration_table (guid);
if (err)
return err; return err;
tbl = (struct grub_efiemu_configuration_table *) grub_malloc (sizeof (*tbl)); tbl = (struct grub_efiemu_configuration_table *) grub_malloc (sizeof (*tbl));
@ -226,7 +227,7 @@ grub_efiemu_autocore (void)
{ {
const char *prefix; const char *prefix;
char *filename; char *filename;
char *suffix; const char *suffix;
grub_err_t err; grub_err_t err;
if (grub_efiemu_sizeof_uintn_t () != 0) if (grub_efiemu_sizeof_uintn_t () != 0)

View file

@ -201,10 +201,10 @@ efiemu_alloc_requests (void)
- (requested_memory[reqorder[i]] % GRUB_EFIEMU_PAGESIZE); - (requested_memory[reqorder[i]] % GRUB_EFIEMU_PAGESIZE);
if (align_overhead == GRUB_EFIEMU_PAGESIZE) if (align_overhead == GRUB_EFIEMU_PAGESIZE)
align_overhead = 0; align_overhead = 0;
curptr = ((grub_uint8_t *)curptr) + align_overhead; curptr = ((grub_uint8_t *) curptr) + align_overhead;
/* Add the region to memory map */ /* Add the region to memory map */
grub_efiemu_add_to_mmap (PTR_TO_UINT64 (typestart), grub_efiemu_add_to_mmap ((grub_addr_t) typestart,
curptr - typestart, reqorder[i]); curptr - typestart, reqorder[i]);
} }
@ -404,7 +404,8 @@ grub_efiemu_mmap_fill (void)
GRUB_EFI_ACPI_MEMORY_NVS); GRUB_EFI_ACPI_MEMORY_NVS);
default: default:
grub_printf ("Unknown memory type %d. Assuming unusable\n", type); grub_dprintf ("efiemu",
"Unknown memory type %d. Assuming unusable\n", type);
case GRUB_MEMORY_RESERVED: case GRUB_MEMORY_RESERVED:
return grub_efiemu_add_to_mmap (addr, size, return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_UNUSABLE_MEMORY); GRUB_EFI_UNUSABLE_MEMORY);

View file

@ -97,10 +97,9 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks,
grub_memcpy (&(conftables[i].vendor_guid), &(cur->guid), grub_memcpy (&(conftables[i].vendor_guid), &(cur->guid),
sizeof (cur->guid)); sizeof (cur->guid));
if (cur->get_table) if (cur->get_table)
conftables[i].vendor_table conftables[i].vendor_table = (grub_addr_t) cur->get_table (cur->data);
= PTR_TO_UINT64 (cur->get_table (cur->data));
else else
conftables[i].vendor_table = PTR_TO_UINT64 (cur->data); conftables[i].vendor_table = (grub_addr_t) cur->data;
} }
err = SUFFIX (grub_efiemu_crc) (); err = SUFFIX (grub_efiemu_crc) ();

View file

@ -169,7 +169,7 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle,
else else
ptv_rels[ptv_written].plustype = 0; ptv_rels[ptv_written].plustype = 0;
ptv_rels[ptv_written].addr = PTR_TO_UINT64 (addr); ptv_rels[ptv_written].addr = (grub_addr_t) addr;
ptv_rels[ptv_written].size = size; ptv_rels[ptv_written].size = size;
ptv_written++; ptv_written++;
@ -179,10 +179,10 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle,
/* Compute the value */ /* Compute the value */
if (minus_handle) if (minus_handle)
value -= PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (minus_handle)); value -= (grub_addr_t) grub_efiemu_mm_obtain_request (minus_handle);
if (plus_handle) if (plus_handle)
value += PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (plus_handle)); value += (grub_addr_t) grub_efiemu_mm_obtain_request (plus_handle);
/* Write the value */ /* Write the value */
switch (size) switch (size)
@ -248,16 +248,16 @@ grub_efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
switch (cur_relloc->size) switch (cur_relloc->size)
{ {
case 8: case 8:
*((grub_uint64_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; *((grub_uint64_t *) (grub_addr_t) cur_relloc->addr) += corr;
break; break;
case 4: case 4:
*((grub_uint32_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; *((grub_uint32_t *) (grub_addr_t) cur_relloc->addr) += corr;
break; break;
case 2: case 2:
*((grub_uint16_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; *((grub_uint16_t *) (grub_addr_t) cur_relloc->addr) += corr;
break; break;
case 1: case 1:
*((grub_uint8_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; *((grub_uint8_t *) (grub_addr_t) cur_relloc->addr) += corr;
break; break;
} }
} }

View file

@ -608,7 +608,7 @@ grub_font_load (const char *filename)
if (!font->name) if (!font->name)
{ {
grub_printf ("Note: Font has no name.\n"); grub_dprintf ("font", "Font has no name.\n");
font->name = grub_strdup ("Unknown"); font->name = grub_strdup ("Unknown");
} }

View file

@ -49,7 +49,7 @@ lsfonts_command (grub_command_t cmd __attribute__ ((unused)),
{ {
struct grub_font_node *node; struct grub_font_node *node;
grub_printf ("Loaded fonts:\n"); grub_puts_ (N_("Loaded fonts:"));
for (node = grub_font_list; node; node = node->next) for (node = grub_font_list; node; node = node->next)
{ {
grub_font_t font = node->value; grub_font_t font = node->value;

View file

@ -25,6 +25,7 @@
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/types.h> #include <grub/types.h>
#include <grub/fshelp.h> #include <grub/fshelp.h>
#include <grub/charset.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -32,15 +33,11 @@ GRUB_MOD_LICENSE ("GPLv3+");
struct grub_affs_bblock struct grub_affs_bblock
{ {
grub_uint8_t type[3]; grub_uint8_t type[3];
grub_uint8_t flags; grub_uint8_t version;
grub_uint32_t checksum; grub_uint32_t checksum;
grub_uint32_t rootblock; grub_uint32_t rootblock;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* Set if the filesystem is a AFFS filesystem. Otherwise this is an
OFS filesystem. */
#define GRUB_AFFS_FLAG_FFS 1
/* The affs rootblock. */ /* The affs rootblock. */
struct grub_affs_rblock struct grub_affs_rblock
{ {
@ -85,19 +82,19 @@ struct grub_affs_file
#define GRUB_AFFS_BLOCKPTR_OFFSET 24 #define GRUB_AFFS_BLOCKPTR_OFFSET 24
#define GRUB_AFFS_SYMLINK_OFFSET 24 #define GRUB_AFFS_SYMLINK_OFFSET 24
#define GRUB_AFFS_SYMLINK_SIZE(blocksize) ((blocksize) - 225) #define GRUB_AFFS_FILETYPE_REG 0xfffffffd
#define GRUB_AFFS_FILETYPE_DIR 2
#define GRUB_AFFS_FILETYPE_DIR -3
#define GRUB_AFFS_FILETYPE_REG 2
#define GRUB_AFFS_FILETYPE_SYMLINK 3 #define GRUB_AFFS_FILETYPE_SYMLINK 3
struct grub_fshelp_node struct grub_fshelp_node
{ {
struct grub_affs_data *data; struct grub_affs_data *data;
grub_disk_addr_t block; grub_uint32_t block;
struct grub_fshelp_node *parent; struct grub_fshelp_node *parent;
struct grub_affs_file di; struct grub_affs_file di;
grub_uint32_t *block_cache;
grub_uint32_t last_block_cache;
}; };
/* Information about a "mounted" affs filesystem. */ /* Information about a "mounted" affs filesystem. */
@ -120,32 +117,46 @@ static grub_dl_t my_mod;
static grub_disk_addr_t static grub_disk_addr_t
grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{ {
int links; grub_uint32_t target, curblock;
grub_uint32_t pos; grub_uint32_t pos;
int block = node->block;
struct grub_affs_file file; struct grub_affs_file file;
struct grub_affs_data *data = node->data; struct grub_affs_data *data = node->data;
grub_uint64_t mod; grub_uint64_t mod;
if (!node->block_cache)
{
node->block_cache = grub_malloc ((((grub_be_to_cpu32 (node->di.size)
+ 511) >> 9) / data->htsize + 1)
* sizeof (node->block_cache[0]));
if (!node->block_cache)
return -1;
node->last_block_cache = 0;
node->block_cache[0] = node->block;
}
/* Files are at most 2G on AFFS, so no need for 64-bit division. */
target = (grub_uint32_t) fileblock / data->htsize;
mod = (grub_uint32_t) fileblock % data->htsize;
/* Find the block that points to the fileblock we are looking up by /* Find the block that points to the fileblock we are looking up by
following the chain until the right table is reached. */ following the chain until the right table is reached. */
for (links = grub_divmod64 (fileblock, data->htsize, &mod); links; links--) for (curblock = node->last_block_cache + 1; curblock <= target; curblock++)
{ {
grub_disk_read (data->disk, block + data->blocksize - 1, grub_disk_read (data->disk,
node->block_cache[curblock - 1] + data->blocksize - 1,
data->blocksize * (GRUB_DISK_SECTOR_SIZE data->blocksize * (GRUB_DISK_SECTOR_SIZE
- GRUB_AFFS_FILE_LOCATION), - GRUB_AFFS_FILE_LOCATION),
sizeof (file), &file); sizeof (file), &file);
if (grub_errno) if (grub_errno)
return 0; return 0;
block = grub_be_to_cpu32 (file.extension); node->block_cache[curblock] = grub_be_to_cpu32 (file.extension);
node->last_block_cache = curblock;
} }
/* Translate the fileblock to the block within the right table. */ /* Translate the fileblock to the block within the right table. */
fileblock = mod; grub_disk_read (data->disk, node->block_cache[target],
grub_disk_read (data->disk, block,
GRUB_AFFS_BLOCKPTR_OFFSET GRUB_AFFS_BLOCKPTR_OFFSET
+ (data->htsize - fileblock - 1) * sizeof (pos), + (data->htsize - mod - 1) * sizeof (pos),
sizeof (pos), &pos); sizeof (pos), &pos);
if (grub_errno) if (grub_errno)
return 0; return 0;
@ -153,21 +164,6 @@ grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
return grub_be_to_cpu32 (pos); return grub_be_to_cpu32 (pos);
} }
/* Read LEN bytes from the file described by DATA starting with byte
POS. Return the amount of read bytes in READ. */
static grub_ssize_t
grub_affs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_affs_read_block,
grub_be_to_cpu32 (node->di.size), 0);
}
static struct grub_affs_data * static struct grub_affs_data *
grub_affs_mount (grub_disk_t disk) grub_affs_mount (grub_disk_t disk)
{ {
@ -178,7 +174,7 @@ grub_affs_mount (grub_disk_t disk)
int checksum = 0; int checksum = 0;
int blocksize = 0; int blocksize = 0;
data = grub_malloc (sizeof (struct grub_affs_data)); data = grub_zalloc (sizeof (struct grub_affs_data));
if (!data) if (!data)
return 0; return 0;
@ -196,18 +192,12 @@ grub_affs_mount (grub_disk_t disk)
} }
/* Test if the filesystem is a OFS filesystem. */ /* Test if the filesystem is a OFS filesystem. */
if (! (data->bblock.flags & GRUB_AFFS_FLAG_FFS)) if (data->bblock.version < 1)
{ {
grub_error (GRUB_ERR_BAD_FS, "OFS not yet supported"); grub_error (GRUB_ERR_BAD_FS, "OFS not yet supported");
goto fail; goto fail;
} }
/* Read the bootblock. */
grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
&data->bblock);
if (grub_errno)
goto fail;
/* No sane person uses more than 8KB for a block. At least I hope /* No sane person uses more than 8KB for a block. At least I hope
for that person because in that case this won't work. */ for that person because in that case this won't work. */
rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE * 16); rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE * 16);
@ -270,18 +260,21 @@ grub_affs_read_symlink (grub_fshelp_node_t node)
{ {
struct grub_affs_data *data = node->data; struct grub_affs_data *data = node->data;
char *symlink; char *symlink;
const grub_size_t symlink_size = (data->blocksize * GRUB_DISK_SECTOR_SIZE
- 225);
symlink = grub_malloc (GRUB_AFFS_SYMLINK_SIZE (data->blocksize)); symlink = grub_malloc (symlink_size + 1);
if (!symlink) if (!symlink)
return 0; return 0;
grub_disk_read (data->disk, node->block, GRUB_AFFS_SYMLINK_OFFSET, grub_disk_read (data->disk, node->block, GRUB_AFFS_SYMLINK_OFFSET,
GRUB_AFFS_SYMLINK_SIZE (data->blocksize), symlink); symlink_size, symlink);
if (grub_errno) if (grub_errno)
{ {
grub_free (symlink); grub_free (symlink);
return 0; return 0;
} }
symlink[symlink_size] = 1;
grub_dprintf ("affs", "Symlink: `%s'\n", symlink); grub_dprintf ("affs", "Symlink: `%s'\n", symlink);
return symlink; return symlink;
} }
@ -300,25 +293,25 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
struct grub_affs_data *data = dir->data; struct grub_affs_data *data = dir->data;
grub_uint32_t *hashtable; grub_uint32_t *hashtable;
auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, auto int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block,
grub_disk_addr_t block,
const struct grub_affs_file *fil); const struct grub_affs_file *fil);
int NESTED_FUNC_ATTR grub_affs_create_node (const char *name, int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block,
grub_disk_addr_t block,
const struct grub_affs_file *fil) const struct grub_affs_file *fil)
{ {
int type; int type;
node = grub_malloc (sizeof (*node)); grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1];
node = grub_zalloc (sizeof (*node));
if (!node) if (!node)
{ {
grub_free (hashtable); grub_free (hashtable);
return 1; return 1;
} }
if ((int) grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR) if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG)
type = GRUB_FSHELP_REG; type = GRUB_FSHELP_REG;
else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG) else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR)
type = GRUB_FSHELP_DIR; type = GRUB_FSHELP_DIR;
else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_SYMLINK) else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_SYMLINK)
type = GRUB_FSHELP_SYMLINK; type = GRUB_FSHELP_SYMLINK;
@ -330,7 +323,10 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
node->di = *fil; node->di = *fil;
node->parent = dir; node->parent = dir;
if (hook (name, type, node)) *grub_latin1_to_utf8 (name_u8, fil->name,
grub_min (fil->namelen, sizeof (fil->name))) = '\0';
if (hook ((char *) name_u8, type, node))
{ {
grub_free (hashtable); grub_free (hashtable);
return 1; return 1;
@ -339,7 +335,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
} }
/* Create the directory entries for `.' and `..'. */ /* Create the directory entries for `.' and `..'. */
node = grub_malloc (sizeof (*node)); node = grub_zalloc (sizeof (*node));
if (!node) if (!node)
return 1; return 1;
@ -348,7 +344,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
return 1; return 1;
if (dir->parent) if (dir->parent)
{ {
node = grub_malloc (sizeof (*node)); node = grub_zalloc (sizeof (*node));
if (!node) if (!node)
return 1; return 1;
*node = *dir->parent; *node = *dir->parent;
@ -356,7 +352,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
return 1; return 1;
} }
hashtable = grub_malloc (data->htsize * sizeof (*hashtable)); hashtable = grub_zalloc (data->htsize * sizeof (*hashtable));
if (!hashtable) if (!hashtable)
return 1; return 1;
@ -367,7 +363,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
for (i = 0; i < data->htsize; i++) for (i = 0; i < data->htsize; i++)
{ {
grub_uint64_t next; grub_uint32_t next;
if (!hashtable[i]) if (!hashtable[i])
continue; continue;
@ -385,9 +381,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
if (grub_errno) if (grub_errno)
goto fail; goto fail;
file.name[file.namelen] = '\0'; if (grub_affs_create_node (next, &file))
if (grub_affs_create_node ((char *) (file.name), next, &file))
return 1; return 1;
next = grub_be_to_cpu32 (file.next); next = grub_be_to_cpu32 (file.next);
@ -441,10 +435,13 @@ grub_affs_open (struct grub_file *file, const char *name)
return grub_errno; return grub_errno;
} }
static grub_err_t static grub_err_t
grub_affs_close (grub_file_t file) grub_affs_close (grub_file_t file)
{ {
struct grub_affs_data *data =
(struct grub_affs_data *) file->data;
grub_free (data->diropen.block_cache);
grub_free (file->data); grub_free (file->data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -452,7 +449,6 @@ grub_affs_close (grub_file_t file)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
/* Read LEN bytes data from FILE into BUF. */ /* Read LEN bytes data from FILE into BUF. */
static grub_ssize_t static grub_ssize_t
grub_affs_read (grub_file_t file, char *buf, grub_size_t len) grub_affs_read (grub_file_t file, char *buf, grub_size_t len)
@ -460,13 +456,12 @@ grub_affs_read (grub_file_t file, char *buf, grub_size_t len)
struct grub_affs_data *data = struct grub_affs_data *data =
(struct grub_affs_data *) file->data; (struct grub_affs_data *) file->data;
int size = grub_affs_read_file (&data->diropen, file->read_hook, return grub_fshelp_read_file (data->diropen.data->disk, &data->diropen,
file->offset, len, buf); file->read_hook,
file->offset, len, buf, grub_affs_read_block,
return size; grub_be_to_cpu32 (data->diropen.di.size), 0);
} }
static grub_err_t static grub_err_t
grub_affs_dir (grub_device_t device, const char *path, grub_affs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename, int (*hook) (const char *filename,

View file

@ -1,720 +1,3 @@
/* afs.c - The native AtheOS file-system. */ #define MODE_AFS 1
/* #include "bfs.c"
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
GRUB_MOD_LICENSE ("GPLv3+");
#ifdef MODE_BIGENDIAN
#define GRUB_AFS_FSNAME_SUFFIX "_be"
#else
#define GRUB_AFS_FSNAME_SUFFIX ""
#endif
#ifdef MODE_BFS
#define GRUB_AFS_FSNAME "befs" GRUB_AFS_FSNAME_SUFFIX
#else
#define GRUB_AFS_FSNAME "afs" GRUB_AFS_FSNAME_SUFFIX
#endif
#define GRUB_AFS_DIRECT_BLOCK_COUNT 12
#define GRUB_AFS_BLOCKS_PER_DI_RUN 4
#ifdef MODE_BFS
#define GRUB_AFS_SBLOCK_SECTOR 1
#define GRUB_AFS_SBLOCK_MAGIC1 0x42465331 /* BFS1. */
#else
#define GRUB_AFS_SBLOCK_SECTOR 2
#define GRUB_AFS_SBLOCK_MAGIC1 0x41465331 /* AFS1. */
#endif
#define GRUB_AFS_SBLOCK_MAGIC2 0xdd121031
#define GRUB_AFS_SBLOCK_MAGIC3 0x15b6830e
#define GRUB_AFS_INODE_MAGIC 0x64358428
#ifdef MODE_BFS
#define GRUB_AFS_BTREE_MAGIC 0x69f6c2e8
#else
#define GRUB_AFS_BTREE_MAGIC 0x65768995
#endif
#define GRUB_AFS_BNODE_SIZE 1024
#define GRUB_AFS_S_IFMT 00170000
#define GRUB_AFS_S_IFLNK 0120000
#define GRUB_AFS_S_IFREG 0100000
#define GRUB_AFS_S_IFDIR 0040000
#define GRUB_AFS_S_IFIFO 0010000
#define GRUB_AFS_NULL_VAL ((grub_afs_bvalue_t)-1)
#ifdef MODE_BIGENDIAN
#define grub_afs_to_cpu16(x) grub_be_to_cpu16 (x)
#define grub_afs_to_cpu32(x) grub_be_to_cpu32 (x)
#define grub_afs_to_cpu64(x) grub_be_to_cpu64 (x)
#else
#define grub_afs_to_cpu16(x) grub_le_to_cpu16 (x)
#define grub_afs_to_cpu32(x) grub_le_to_cpu32 (x)
#define grub_afs_to_cpu64(x) grub_le_to_cpu64 (x)
#endif
#ifdef MODE_BFS
#define B_KEY_INDEX_ALIGN 8
#else
#define B_KEY_INDEX_ALIGN 4
#endif
#define B_KEY_INDEX_OFFSET(node) ((grub_uint16_t *) \
((char *) (node) \
+ ALIGN_UP (sizeof (struct grub_afs_bnode) \
+ node->key_size, \
B_KEY_INDEX_ALIGN)))
#define B_KEY_VALUE_OFFSET(node) ((grub_afs_bvalue_t *) \
((char *) B_KEY_INDEX_OFFSET (node) + \
node->key_count * 2))
typedef grub_uint64_t grub_afs_off_t;
typedef grub_uint64_t grub_afs_bigtime;
typedef grub_uint64_t grub_afs_bvalue_t;
struct grub_afs_blockrun
{
grub_uint32_t group;
grub_uint16_t start;
grub_uint16_t len;
} __attribute__ ((packed));
struct grub_afs_datastream
{
struct grub_afs_blockrun direct[GRUB_AFS_DIRECT_BLOCK_COUNT];
grub_afs_off_t max_direct_range;
struct grub_afs_blockrun indirect;
grub_afs_off_t max_indirect_range;
struct grub_afs_blockrun double_indirect;
grub_afs_off_t max_double_indirect_range;
grub_afs_off_t size;
} __attribute__ ((packed));
struct grub_afs_bnode
{
grub_afs_bvalue_t left;
grub_afs_bvalue_t right;
grub_afs_bvalue_t overflow;
#ifdef MODE_BFS
grub_uint16_t key_count;
grub_uint16_t key_size;
#else
grub_uint32_t key_count;
grub_uint32_t key_size;
#endif
char key_data[0];
} __attribute__ ((packed));
#ifdef MODE_BFS
struct grub_afs_btree
{
grub_uint32_t magic;
grub_uint32_t unused1;
grub_uint32_t tree_depth;
grub_uint32_t unused2;
grub_afs_bvalue_t root;
grub_uint32_t unused3[4];
} __attribute__ ((packed));
#else
struct grub_afs_btree
{
grub_uint32_t magic;
grub_afs_bvalue_t root;
grub_uint32_t tree_depth;
grub_afs_bvalue_t last_node;
grub_afs_bvalue_t first_free;
} __attribute__ ((packed));
#endif
/* Beware that following structure describes AtheFS and if you write code
which uses currently unused fields check it with both AtheFS and BeFS.
*/
struct grub_afs_sblock
{
char name[32];
grub_uint32_t magic1;
grub_uint32_t byte_order;
grub_uint32_t block_size;
grub_uint32_t block_shift;
grub_afs_off_t num_blocks;
grub_afs_off_t used_blocks;
grub_uint32_t inode_size;
grub_uint32_t magic2;
grub_uint32_t block_per_group; /* Number of blocks per allocation
group. (Max 65536) */
grub_uint32_t alloc_group_shift; /* Number of bits to shift a group
number to get a byte address. */
grub_uint32_t alloc_group_count;
grub_uint32_t flags;
struct grub_afs_blockrun log_block;
grub_afs_off_t log_start;
grub_uint32_t valid_log_blocks;
grub_uint32_t log_size;
grub_uint32_t magic3;
struct grub_afs_blockrun root_dir; /* Root dir inode. */
struct grub_afs_blockrun deleted_files; /* Directory containing files
scheduled for deletion. */
struct grub_afs_blockrun index_dir; /* Directory of index files. */
grub_uint32_t boot_loader_size;
grub_uint32_t pad[7];
} __attribute__ ((packed));
struct grub_afs_inode
{
grub_uint32_t magic1;
struct grub_afs_blockrun inode_num;
grub_uint32_t uid;
grub_uint32_t gid;
grub_uint32_t mode;
grub_uint32_t flags;
#ifndef MODE_BFS
grub_uint32_t link_count;
#endif
grub_afs_bigtime create_time;
grub_afs_bigtime modified_time;
struct grub_afs_blockrun parent;
struct grub_afs_blockrun attrib_dir;
grub_uint32_t index_type; /* Key data-key only used for index files. */
grub_uint32_t inode_size;
grub_uint32_t unused;
struct grub_afs_datastream stream;
grub_uint32_t pad[4];
grub_uint32_t small_data[1];
} __attribute__ ((packed));
struct grub_fshelp_node
{
struct grub_afs_data *data;
struct grub_afs_inode inode;
};
struct grub_afs_data
{
grub_disk_t disk;
struct grub_afs_sblock sblock;
struct grub_afs_inode *inode;
struct grub_fshelp_node diropen;
};
static grub_dl_t my_mod;
static grub_afs_off_t
grub_afs_run_to_num (struct grub_afs_sblock *sb,
struct grub_afs_blockrun *run)
{
return ((grub_afs_off_t) grub_afs_to_cpu32 (run->group)
* sb->block_per_group + grub_afs_to_cpu16 (run->start));
}
static grub_err_t
grub_afs_read_inode (struct grub_afs_data *data,
grub_uint32_t ino, struct grub_afs_inode *inode)
{
return grub_disk_read (data->disk,
ino *
(data->sblock.block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (struct grub_afs_inode),
inode);
}
static grub_disk_addr_t
grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{
struct grub_afs_sblock *sb = &node->data->sblock;
struct grub_afs_datastream *ds = &node->inode.stream;
if (fileblock < grub_afs_to_cpu64 (ds->max_direct_range))
{
int i;
for (i = 0; i < GRUB_AFS_DIRECT_BLOCK_COUNT; i++)
{
if (fileblock < grub_afs_to_cpu16 (ds->direct[i].len))
return grub_afs_run_to_num (sb, &ds->direct[i]) + fileblock;
fileblock -= grub_afs_to_cpu16 (ds->direct[i].len);
}
}
else if (fileblock < grub_afs_to_cpu64 (ds->max_indirect_range))
{
int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
struct grub_afs_blockrun indir[ptrs_per_blk];
grub_afs_off_t blk = grub_afs_run_to_num (sb, &ds->indirect);
int i;
fileblock -= grub_afs_to_cpu64 (ds->max_direct_range);
for (i = 0; i < ds->indirect.len; i++, blk++)
{
int j;
if (grub_disk_read (node->data->disk,
blk * (sb->block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (indir),
indir))
return 0;
for (j = 0; j < ptrs_per_blk; j++)
{
if (fileblock < grub_afs_to_cpu16 (indir[j].len))
return grub_afs_run_to_num (sb, &indir[j]) + fileblock;
fileblock -= grub_afs_to_cpu16 (indir[j].len);
}
}
}
else
{
int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
struct grub_afs_blockrun indir[ptrs_per_blk];
/* ([idblk][idptr]) ([dblk][dptr]) [blk] */
int cur_pos = fileblock - grub_afs_to_cpu64 (ds->max_indirect_range);
int dptr_size = GRUB_AFS_BLOCKS_PER_DI_RUN;
int dblk_size = dptr_size * ptrs_per_blk;
int idptr_size = dblk_size * GRUB_AFS_BLOCKS_PER_DI_RUN;
int idblk_size = idptr_size * ptrs_per_blk;
int off = cur_pos % GRUB_AFS_BLOCKS_PER_DI_RUN;
int dptr = (cur_pos / dptr_size) % ptrs_per_blk;
int dblk = (cur_pos / dblk_size) % GRUB_AFS_BLOCKS_PER_DI_RUN;
int idptr = (cur_pos / idptr_size) % ptrs_per_blk;
int idblk = (cur_pos / idblk_size);
if (grub_disk_read (node->data->disk,
(grub_afs_run_to_num (sb, &ds->double_indirect)
+ idblk) *
(sb->block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (indir),
indir))
return 0;
if (grub_disk_read (node->data->disk,
(grub_afs_run_to_num (sb, &indir[idptr]) + dblk) *
(sb->block_size >> GRUB_DISK_SECTOR_BITS),
0, sizeof (indir),
indir))
return 0;
return grub_afs_run_to_num (sb, &indir[dptr]) + off;
}
return 0;
}
static grub_ssize_t
grub_afs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf)
{
return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_afs_read_block,
grub_afs_to_cpu64 (node->inode.stream.size),
node->data->sblock.block_shift
- GRUB_DISK_SECTOR_BITS);
}
static char *
grub_afs_read_symlink (grub_fshelp_node_t node)
{
char *ret;
grub_afs_off_t size = grub_afs_to_cpu64 (node->inode.stream.size);
if (size == 0)
{
size = sizeof (node->inode.stream);
ret = grub_zalloc (size + 1);
if (! ret)
return 0;
grub_memcpy (ret, (char *) &(node->inode.stream),
sizeof (node->inode.stream));
return ret;
}
ret = grub_zalloc (size + 1);
if (! ret)
return 0;
grub_afs_read_file (node, 0, 0, size, ret);
return ret;
}
static int
grub_afs_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
struct grub_afs_btree head;
char node_data [GRUB_AFS_BNODE_SIZE];
struct grub_afs_bnode *node = (struct grub_afs_bnode *) node_data;
int i;
if ((dir->inode.stream.size == 0)
|| ((grub_afs_to_cpu32 (dir->inode.mode) & GRUB_AFS_S_IFMT)
!= GRUB_AFS_S_IFDIR))
return 0;
grub_afs_read_file (dir, 0, 0, sizeof (head), (char *) &head);
if (grub_errno)
return 0;
grub_afs_read_file (dir, 0, grub_afs_to_cpu64 (head.root),
GRUB_AFS_BNODE_SIZE, (char *) node);
if (grub_errno)
return 0;
for (i = 0; i < (int) grub_afs_to_cpu32 (head.tree_depth) - 1; i++)
{
grub_afs_bvalue_t blk;
blk = grub_afs_to_cpu64(B_KEY_VALUE_OFFSET (node) [0]);
grub_afs_read_file (dir, 0, blk, GRUB_AFS_BNODE_SIZE, (char *) node);
if (grub_errno)
return 0;
}
if (node->key_count)
{
grub_uint32_t cur_key = 0;
while (1)
{
int key_start, key_size;
grub_uint16_t *index;
index = B_KEY_INDEX_OFFSET (node);
key_start = (cur_key > 0)
? grub_afs_to_cpu16 (index[cur_key - 1]) : 0;
key_size = grub_afs_to_cpu16 (index[cur_key]) - key_start;
if (key_size > 0)
{
char filename [key_size + 1];
struct grub_fshelp_node *fdiro;
int mode, type;
fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
if (! fdiro)
return 0;
fdiro->data = dir->data;
if (grub_afs_read_inode (dir->data,
grub_afs_to_cpu64
(B_KEY_VALUE_OFFSET (node) [cur_key]),
&fdiro->inode))
return 0;
grub_memcpy (filename, &node->key_data[key_start], key_size);
filename [key_size] = 0;
mode = (grub_afs_to_cpu32 (fdiro->inode.mode) & GRUB_AFS_S_IFMT);
if (mode == GRUB_AFS_S_IFDIR)
type = GRUB_FSHELP_DIR;
else if (mode == GRUB_AFS_S_IFREG)
type = GRUB_FSHELP_REG;
else if (mode == GRUB_AFS_S_IFLNK)
type = GRUB_FSHELP_SYMLINK;
else
type = GRUB_FSHELP_UNKNOWN;
if (hook (filename, type, fdiro))
return 1;
}
cur_key++;
if (cur_key >= grub_afs_to_cpu32 (node->key_count))
{
if (node->right == GRUB_AFS_NULL_VAL)
break;
grub_afs_read_file (dir, 0, grub_afs_to_cpu64 (node->right),
GRUB_AFS_BNODE_SIZE, (char *) node);
if (grub_errno)
return 0;
cur_key = 0;
}
}
}
return 0;
}
static int
grub_afs_validate_sblock (struct grub_afs_sblock *sb)
{
if (grub_afs_to_cpu32 (sb->magic1) == GRUB_AFS_SBLOCK_MAGIC1)
{
sb->magic2 = grub_afs_to_cpu32 (sb->magic2);
sb->magic3 = grub_afs_to_cpu32 (sb->magic3);
sb->block_shift = grub_afs_to_cpu32 (sb->block_shift);
sb->block_size = grub_afs_to_cpu32 (sb->block_size);
sb->used_blocks = grub_afs_to_cpu64 (sb->used_blocks);
sb->num_blocks = grub_afs_to_cpu64 (sb->num_blocks);
sb->inode_size = grub_afs_to_cpu32 (sb->inode_size);
sb->alloc_group_count = grub_afs_to_cpu32 (sb->alloc_group_count);
sb->alloc_group_shift = grub_afs_to_cpu32 (sb->alloc_group_shift);
sb->block_per_group = grub_afs_to_cpu32 (sb->block_per_group);
sb->alloc_group_count = grub_afs_to_cpu32 (sb->alloc_group_count);
sb->log_size = grub_afs_to_cpu32 (sb->log_size);
}
else
return 0;
if ((sb->magic2 != GRUB_AFS_SBLOCK_MAGIC2) ||
(sb->magic3 != GRUB_AFS_SBLOCK_MAGIC3))
return 0;
#ifdef MODE_BFS
sb->block_per_group = 1 << (sb->alloc_group_shift);
#endif
if (((grub_uint32_t) (1 << sb->block_shift) != sb->block_size)
|| (sb->used_blocks > sb->num_blocks )
|| (sb->inode_size != sb->block_size)
|| (0 == sb->block_size)
#ifndef MODE_BFS
|| ((grub_uint32_t) (1 << sb->alloc_group_shift) !=
sb->block_per_group * sb->block_size)
|| (sb->alloc_group_count * sb->block_per_group < sb->num_blocks)
|| (grub_afs_to_cpu16 (sb->log_block.len) != sb->log_size)
|| (grub_afs_to_cpu32 (sb->valid_log_blocks) > sb->log_size)
#endif
)
return 0;
return 1;
}
static struct grub_afs_data *
grub_afs_mount (grub_disk_t disk)
{
struct grub_afs_data *data = 0;
data = grub_malloc (sizeof (struct grub_afs_data));
if (!data)
return 0;
/* Read the superblock. */
if (grub_disk_read (disk, GRUB_AFS_SBLOCK_SECTOR, 0,
sizeof (struct grub_afs_sblock), &data->sblock))
goto fail;
if (! grub_afs_validate_sblock (&data->sblock))
goto fail;
data->diropen.data = data;
data->inode = &data->diropen.inode;
data->disk = disk;
if (grub_afs_read_inode (data,
grub_afs_run_to_num (&data->sblock,
&data->sblock.root_dir),
data->inode))
goto fail;
return data;
fail:
grub_error (GRUB_ERR_BAD_FS, "not an " GRUB_AFS_FSNAME " filesystem");
grub_free (data);
return 0;
}
static grub_err_t
grub_afs_open (struct grub_file *file, const char *name)
{
struct grub_afs_data *data;
struct grub_fshelp_node *fdiro = 0;
grub_dl_ref (my_mod);
data = grub_afs_mount (file->device->disk);
if (! data)
goto fail;
grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_afs_iterate_dir,
grub_afs_read_symlink, GRUB_FSHELP_REG);
if (grub_errno)
goto fail;
grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_afs_inode));
grub_free (fdiro);
file->size = grub_afs_to_cpu64 (data->inode->stream.size);
file->data = data;
file->offset = 0;
return 0;
fail:
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_ssize_t
grub_afs_read (grub_file_t file, char *buf, grub_size_t len)
{
struct grub_afs_data *data = (struct grub_afs_data *) file->data;
return grub_afs_read_file (&data->diropen, file->read_hook,
file->offset, len, buf);
}
static grub_err_t
grub_afs_close (grub_file_t file)
{
grub_free (file->data);
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_afs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,
const struct grub_dirhook_info *info))
{
struct grub_afs_data *data = 0;
struct grub_fshelp_node *fdiro = 0;
auto int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node);
int NESTED_FUNC_ATTR iterate (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)
{
struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = 1;
#ifdef MODE_BFS
info.mtime = grub_afs_to_cpu64 (node->inode.modified_time) >> 16;
#else
info.mtime = grub_divmod64 (grub_afs_to_cpu64 (node->inode.modified_time),
1000000, 0);
#endif
grub_free (node);
return hook (filename, &info);
}
grub_dl_ref (my_mod);
data = grub_afs_mount (device->disk);
if (! data)
goto fail;
grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_afs_iterate_dir,
grub_afs_read_symlink, GRUB_FSHELP_DIR);
if (grub_errno)
goto fail;
grub_afs_iterate_dir (fdiro, iterate);
if (fdiro != &data->diropen)
grub_free (fdiro);
fail:
grub_free (data);
grub_dl_unref (my_mod);
return grub_errno;
}
static grub_err_t
grub_afs_label (grub_device_t device, char **label)
{
struct grub_afs_data *data;
grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_afs_mount (disk);
if (data)
*label = grub_strndup (data->sblock.name, sizeof (data->sblock.name));
else
*label = NULL;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno;
}
static struct grub_fs grub_afs_fs = {
.name = GRUB_AFS_FSNAME,
.dir = grub_afs_dir,
.open = grub_afs_open,
.read = grub_afs_read,
.close = grub_afs_close,
.label = grub_afs_label,
.next = 0
};
#if defined (MODE_BIGENDIAN) && defined (MODE_BFS)
GRUB_MOD_INIT (befs_be)
#elif defined (MODE_BFS)
GRUB_MOD_INIT (befs)
#elif defined (MODE_BIGENDIAN)
GRUB_MOD_INIT (afs_be)
#else
GRUB_MOD_INIT (afs)
#endif
{
grub_fs_register (&grub_afs_fs);
my_mod = mod;
}
#if defined (MODE_BIGENDIAN) && defined (MODE_BFS)
GRUB_MOD_FINI (befs_be)
#elif defined (MODE_BFS)
GRUB_MOD_FINI (befs)
#elif defined (MODE_BIGENDIAN)
GRUB_MOD_FINI (afs_be)
#else
GRUB_MOD_FINI (afs)
#endif
{
grub_fs_unregister (&grub_afs_fs);
}

View file

@ -1,2 +0,0 @@
#define MODE_BIGENDIAN 1
#include "afs.c"

View file

@ -1,3 +0,0 @@
/* befs.c - The native BeOS/Haiku file-system. */
#define MODE_BFS 1
#include "afs.c"

View file

@ -1,4 +0,0 @@
/* befs.c - The native BeOS/Haiku file-system. */
#define MODE_BFS 1
#define MODE_BIGENDIAN 1
#include "afs.c"

1050
grub-core/fs/bfs.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -26,11 +26,23 @@
#include <grub/types.h> #include <grub/types.h>
#include <grub/lib/crc.h> #include <grub/lib/crc.h>
#include <grub/deflate.h> #include <grub/deflate.h>
#include <minilzo.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_BTRFS_SIGNATURE "_BHRfS_M" #define GRUB_BTRFS_SIGNATURE "_BHRfS_M"
/* From http://www.oberhumer.com/opensource/lzo/lzofaq.php
* LZO will expand incompressible data by a little amount. I still haven't
* computed the exact values, but I suggest using these formulas for
* a worst-case expansion calculation:
*
* output_block_size = input_block_size + (input_block_size / 16) + 64 + 3
* */
#define GRUB_BTRFS_LZO_BLOCK_SIZE 4096
#define GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE (GRUB_BTRFS_LZO_BLOCK_SIZE + \
(GRUB_BTRFS_LZO_BLOCK_SIZE / 16) + 64 + 3)
typedef grub_uint8_t grub_btrfs_checksum_t[0x20]; typedef grub_uint8_t grub_btrfs_checksum_t[0x20];
typedef grub_uint16_t grub_btrfs_uuid_t[8]; typedef grub_uint16_t grub_btrfs_uuid_t[8];
@ -41,7 +53,7 @@ struct grub_btrfs_device
} __attribute__ ((packed)); } __attribute__ ((packed));
struct grub_btrfs_superblock struct grub_btrfs_superblock
{ {
grub_btrfs_checksum_t checksum; grub_btrfs_checksum_t checksum;
grub_btrfs_uuid_t uuid; grub_btrfs_uuid_t uuid;
grub_uint8_t dummy[0x10]; grub_uint8_t dummy[0x10];
@ -160,7 +172,8 @@ struct grub_btrfs_leaf_descriptor
{ {
unsigned depth; unsigned depth;
unsigned allocated; unsigned allocated;
struct { struct
{
grub_disk_addr_t addr; grub_disk_addr_t addr;
unsigned iter; unsigned iter;
unsigned maxiter; unsigned maxiter;
@ -179,7 +192,7 @@ struct grub_btrfs_time
{ {
grub_int64_t sec; grub_int64_t sec;
grub_uint32_t nanosec; grub_uint32_t nanosec;
} __attribute__ ((aligned(4))); } __attribute__ ((aligned (4)));
struct grub_btrfs_inode struct grub_btrfs_inode
{ {
@ -215,12 +228,13 @@ struct grub_btrfs_extent_data
#define GRUB_BTRFS_COMPRESSION_NONE 0 #define GRUB_BTRFS_COMPRESSION_NONE 0
#define GRUB_BTRFS_COMPRESSION_ZLIB 1 #define GRUB_BTRFS_COMPRESSION_ZLIB 1
#define GRUB_BTRFS_COMPRESSION_LZO 2
#define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100 #define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100
static grub_disk_addr_t superblock_sectors[] = { 64 * 2, 64 * 1024 * 2, static grub_disk_addr_t superblock_sectors[] = { 64 * 2, 64 * 1024 * 2,
256 * 1048576 * 2, 256 * 1048576 * 2, 1048576ULL * 1048576ULL * 2
1048576ULL * 1048576ULL * 2 }; };
static grub_err_t static grub_err_t
grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_btrfs_read_logical (struct grub_btrfs_data *data,
@ -283,7 +297,7 @@ free_iterator (struct grub_btrfs_leaf_descriptor *desc)
} }
static grub_err_t static grub_err_t
save_ref (struct grub_btrfs_leaf_descriptor *desc, save_ref (struct grub_btrfs_leaf_descriptor *desc,
grub_disk_addr_t addr, unsigned i, unsigned m, int l) grub_disk_addr_t addr, unsigned i, unsigned m, int l)
{ {
desc->depth++; desc->depth++;
@ -307,7 +321,7 @@ save_ref (struct grub_btrfs_leaf_descriptor *desc,
static int static int
next (struct grub_btrfs_data *data, next (struct grub_btrfs_data *data,
struct grub_btrfs_leaf_descriptor *desc, struct grub_btrfs_leaf_descriptor *desc,
grub_disk_addr_t *outaddr, grub_size_t *outsize, grub_disk_addr_t * outaddr, grub_size_t * outsize,
struct grub_btrfs_key *key_out) struct grub_btrfs_key *key_out)
{ {
grub_err_t err; grub_err_t err;
@ -330,17 +344,17 @@ next (struct grub_btrfs_data *data,
err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter
* sizeof (node) * sizeof (node)
+ sizeof (struct btrfs_header) + sizeof (struct btrfs_header)
+ desc->data[desc->depth - 1].addr, &node, + desc->data[desc->depth - 1].addr,
sizeof (node)); &node, sizeof (node));
if (err) if (err)
return -err; return -err;
err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr), &head, err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr),
sizeof (head)); &head, sizeof (head));
if (err) if (err)
return -err; return -err;
save_ref (desc, grub_le_to_cpu64 (node.addr), 0, save_ref (desc, grub_le_to_cpu64 (node.addr), 0,
grub_le_to_cpu32 (head.nitems), !head.level); grub_le_to_cpu32 (head.nitems), !head.level);
} }
err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter
@ -354,12 +368,12 @@ next (struct grub_btrfs_data *data,
*outaddr = desc->data[desc->depth - 1].addr + sizeof (struct btrfs_header) *outaddr = desc->data[desc->depth - 1].addr + sizeof (struct btrfs_header)
+ grub_le_to_cpu32 (leaf.offset); + grub_le_to_cpu32 (leaf.offset);
*key_out = leaf.key; *key_out = leaf.key;
return 1; return 1;
} }
static grub_err_t static grub_err_t
lower_bound (struct grub_btrfs_data *data, lower_bound (struct grub_btrfs_data *data,
const struct grub_btrfs_key *key_in, const struct grub_btrfs_key *key_in,
struct grub_btrfs_key *key_out, struct grub_btrfs_key *key_out,
grub_disk_addr_t root, grub_disk_addr_t root,
grub_disk_addr_t *outaddr, grub_size_t *outsize, grub_disk_addr_t *outaddr, grub_size_t *outsize,
@ -410,8 +424,9 @@ lower_bound (struct grub_btrfs_data *data,
grub_dprintf ("btrfs", grub_dprintf ("btrfs",
"internal node (depth %d) %" PRIxGRUB_UINT64_T "internal node (depth %d) %" PRIxGRUB_UINT64_T
" %x %" PRIxGRUB_UINT64_T "\n", depth, " %x %" PRIxGRUB_UINT64_T "\n", depth,
node.key.object_id, node.key.type, node.key.offset); node.key.object_id, node.key.type,
node.key.offset);
if (key_cmp (&node.key, key_in) == 0) if (key_cmp (&node.key, key_in) == 0)
{ {
err = GRUB_ERR_NONE; err = GRUB_ERR_NONE;
@ -433,7 +448,7 @@ lower_bound (struct grub_btrfs_data *data,
err = GRUB_ERR_NONE; err = GRUB_ERR_NONE;
if (desc) if (desc)
err = save_ref (desc, addr - sizeof (head), i - 1, err = save_ref (desc, addr - sizeof (head), i - 1,
grub_le_to_cpu32 (head.nitems), 0); grub_le_to_cpu32 (head.nitems), 0);
if (err) if (err)
return err; return err;
addr = grub_le_to_cpu64 (node_last.addr); addr = grub_le_to_cpu64 (node_last.addr);
@ -457,7 +472,7 @@ lower_bound (struct grub_btrfs_data *data,
&leaf, sizeof (leaf)); &leaf, sizeof (leaf));
if (err) if (err)
return err; return err;
grub_dprintf ("btrfs", grub_dprintf ("btrfs",
"leaf (depth %d) %" PRIxGRUB_UINT64_T "leaf (depth %d) %" PRIxGRUB_UINT64_T
" %x %" PRIxGRUB_UINT64_T "\n", depth, " %x %" PRIxGRUB_UINT64_T "\n", depth,
@ -465,31 +480,31 @@ lower_bound (struct grub_btrfs_data *data,
if (key_cmp (&leaf.key, key_in) == 0) if (key_cmp (&leaf.key, key_in) == 0)
{ {
grub_memcpy (key_out, &leaf.key, sizeof(*key_out)); grub_memcpy (key_out, &leaf.key, sizeof (*key_out));
*outsize = grub_le_to_cpu32 (leaf.size); *outsize = grub_le_to_cpu32 (leaf.size);
*outaddr = addr + grub_le_to_cpu32 (leaf.offset); *outaddr = addr + grub_le_to_cpu32 (leaf.offset);
if (desc) if (desc)
return save_ref (desc, addr - sizeof (head), i, return save_ref (desc, addr - sizeof (head), i,
grub_le_to_cpu32 (head.nitems), 1); grub_le_to_cpu32 (head.nitems), 1);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
if (key_cmp (&leaf.key, key_in) > 0) if (key_cmp (&leaf.key, key_in) > 0)
break; break;
have_last = 1; have_last = 1;
leaf_last = leaf; leaf_last = leaf;
} }
if (have_last) if (have_last)
{ {
grub_memcpy (key_out, &leaf_last.key, sizeof(*key_out)); grub_memcpy (key_out, &leaf_last.key, sizeof (*key_out));
*outsize = grub_le_to_cpu32 (leaf_last.size); *outsize = grub_le_to_cpu32 (leaf_last.size);
*outaddr = addr + grub_le_to_cpu32 (leaf_last.offset); *outaddr = addr + grub_le_to_cpu32 (leaf_last.offset);
if (desc) if (desc)
return save_ref (desc, addr - sizeof (head), i - 1, return save_ref (desc, addr - sizeof (head), i - 1,
grub_le_to_cpu32 (head.nitems), 1); grub_le_to_cpu32 (head.nitems), 1);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
*outsize = 0; *outsize = 0;
*outaddr = 0; *outaddr = 0;
@ -503,8 +518,7 @@ lower_bound (struct grub_btrfs_data *data,
} }
static grub_device_t static grub_device_t
find_device (struct grub_btrfs_data *data, grub_uint64_t id, find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan)
int do_rescan)
{ {
grub_device_t dev_found = NULL; grub_device_t dev_found = NULL;
auto int hook (const char *name); auto int hook (const char *name);
@ -540,7 +554,7 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id,
grub_device_close (dev); grub_device_close (dev);
return 0; return 0;
} }
dev_found = dev; dev_found = dev;
return 1; return 1;
} }
@ -579,17 +593,16 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id,
} }
static grub_err_t static grub_err_t
grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
grub_disk_addr_t addr,
void *buf, grub_size_t size) void *buf, grub_size_t size)
{ {
while (size > 0) while (size > 0)
{ {
grub_uint8_t *ptr; grub_uint8_t *ptr;
struct grub_btrfs_key *key; struct grub_btrfs_key *key;
struct grub_btrfs_chunk_item *chunk; struct grub_btrfs_chunk_item *chunk;
grub_uint64_t csize; grub_uint64_t csize;
grub_err_t err = 0; grub_err_t err = 0;
struct grub_btrfs_key key_out; struct grub_btrfs_key key_out;
int challoc = 0; int challoc = 0;
grub_device_t dev; grub_device_t dev;
@ -601,15 +614,15 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
addr); addr);
for (ptr = data->sblock.bootstrap_mapping; for (ptr = data->sblock.bootstrap_mapping;
ptr < data->sblock.bootstrap_mapping ptr < data->sblock.bootstrap_mapping
+ sizeof (data->sblock.bootstrap_mapping) + sizeof (data->sblock.bootstrap_mapping)
- sizeof (struct grub_btrfs_key); - sizeof (struct grub_btrfs_key);)
)
{ {
key = (struct grub_btrfs_key *) ptr; key = (struct grub_btrfs_key *) ptr;
if (key->type != GRUB_BTRFS_ITEM_TYPE_CHUNK) if (key->type != GRUB_BTRFS_ITEM_TYPE_CHUNK)
break; break;
chunk = (struct grub_btrfs_chunk_item *) (key + 1); chunk = (struct grub_btrfs_chunk_item *) (key + 1);
grub_dprintf ("btrfs", "%" PRIxGRUB_UINT64_T " %" PRIxGRUB_UINT64_T " \n", grub_dprintf ("btrfs",
"%" PRIxGRUB_UINT64_T " %" PRIxGRUB_UINT64_T " \n",
grub_le_to_cpu64 (key->offset), grub_le_to_cpu64 (key->offset),
grub_le_to_cpu64 (chunk->size)); grub_le_to_cpu64 (chunk->size));
if (grub_le_to_cpu64 (key->offset) <= addr if (grub_le_to_cpu64 (key->offset) <= addr
@ -704,11 +717,11 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
middle = grub_divmod64 (off, middle = grub_divmod64 (off,
grub_le_to_cpu64 (chunk->stripe_length), grub_le_to_cpu64 (chunk->stripe_length),
&low); &low);
high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes), high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes),
&stripen); &stripen);
stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length) stripe_offset =
* high; low + grub_le_to_cpu64 (chunk->stripe_length) * high;
csize = grub_le_to_cpu64 (chunk->stripe_length) - low; csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
break; break;
} }
@ -719,14 +732,13 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
middle = grub_divmod64 (off, middle = grub_divmod64 (off,
grub_le_to_cpu64 (chunk->stripe_length), grub_le_to_cpu64 (chunk->stripe_length),
&low); &low);
high = grub_divmod64 (middle, high = grub_divmod64 (middle,
grub_le_to_cpu16 (chunk->nsubstripes), grub_le_to_cpu16 (chunk->nstripes)
/ grub_le_to_cpu16 (chunk->nsubstripes),
&stripen); &stripen);
stripen *= grub_le_to_cpu16 (chunk->nstripes) stripen *= grub_le_to_cpu16 (chunk->nsubstripes);
/ grub_le_to_cpu16 (chunk->nsubstripes); redundancy = grub_le_to_cpu16 (chunk->nsubstripes);
redundancy = grub_le_to_cpu16 (chunk->nstripes)
/ grub_le_to_cpu16 (chunk->nsubstripes);
stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length) stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length)
* high; * high;
csize = grub_le_to_cpu64 (chunk->stripe_length) - low; csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
@ -759,7 +771,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
paddr = stripe->offset + stripe_offset; paddr = stripe->offset + stripe_offset;
grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
"+0x%" PRIxGRUB_UINT64_T " (%d stripes (%d substripes) of %" "+0x%" PRIxGRUB_UINT64_T
" (%d stripes (%d substripes) of %"
PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT64_T PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT64_T
" maps to 0x%" PRIxGRUB_UINT64_T "\n", " maps to 0x%" PRIxGRUB_UINT64_T "\n",
grub_le_to_cpu64 (key->offset), grub_le_to_cpu64 (key->offset),
@ -769,7 +782,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
grub_le_to_cpu64 (chunk->stripe_length), grub_le_to_cpu64 (chunk->stripe_length),
stripen, stripe->offset); stripen, stripe->offset);
grub_dprintf ("btrfs", "reading paddr 0x%" PRIxGRUB_UINT64_T grub_dprintf ("btrfs", "reading paddr 0x%" PRIxGRUB_UINT64_T
" for laddr 0x%" PRIxGRUB_UINT64_T"\n", paddr, " for laddr 0x%" PRIxGRUB_UINT64_T "\n", paddr,
addr); addr);
dev = find_device (data, stripe->device_id, j); dev = find_device (data, stripe->device_id, j);
@ -815,7 +828,7 @@ grub_btrfs_mount (grub_device_t dev)
} }
data = grub_zalloc (sizeof (*data)); data = grub_zalloc (sizeof (*data));
if (! data) if (!data)
return NULL; return NULL;
err = read_sblock (dev->disk, &data->sblock); err = read_sblock (dev->disk, &data->sblock);
@ -866,8 +879,7 @@ grub_btrfs_read_inode (struct grub_btrfs_data *data,
key_in.type = GRUB_BTRFS_ITEM_TYPE_INODE_ITEM; key_in.type = GRUB_BTRFS_ITEM_TYPE_INODE_ITEM;
key_in.offset = 0; key_in.offset = 0;
err = lower_bound (data, &key_in, &key_out, tree, err = lower_bound (data, &key_in, &key_out, tree, &elemaddr, &elemsize, NULL);
&elemaddr, &elemsize, NULL);
if (err) if (err)
return err; return err;
if (num != key_out.object_id if (num != key_out.object_id
@ -877,6 +889,76 @@ grub_btrfs_read_inode (struct grub_btrfs_data *data,
return grub_btrfs_read_logical (data, elemaddr, inode, sizeof (*inode)); return grub_btrfs_read_logical (data, elemaddr, inode, sizeof (*inode));
} }
static grub_ssize_t
grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off,
char *obuf, grub_size_t osize)
{
grub_uint32_t total_size, cblock_size, ret = 0;
unsigned char buf[GRUB_BTRFS_LZO_BLOCK_SIZE];
total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
ibuf += sizeof (total_size);
if (isize < total_size)
return -1;
/* Jump forward to first block with requested data. */
while (off >= GRUB_BTRFS_LZO_BLOCK_SIZE)
{
cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
ibuf += sizeof (cblock_size);
if (cblock_size > GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE)
return -1;
off -= GRUB_BTRFS_LZO_BLOCK_SIZE;
ibuf += cblock_size;
}
while (osize > 0)
{
lzo_uint usize = GRUB_BTRFS_LZO_BLOCK_SIZE;
cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
ibuf += sizeof (cblock_size);
if (cblock_size > GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE)
return -1;
/* Block partially filled with requested data. */
if (off > 0 || osize < GRUB_BTRFS_LZO_BLOCK_SIZE)
{
grub_size_t to_copy = grub_min(osize, GRUB_BTRFS_LZO_BLOCK_SIZE - off);
if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, buf, &usize,
NULL) != LZO_E_OK)
return -1;
to_copy = grub_min(to_copy, usize);
grub_memcpy(obuf, buf + off, to_copy);
osize -= to_copy;
ret += to_copy;
obuf += to_copy;
ibuf += cblock_size;
off = 0;
continue;
}
/* Decompress whole block directly to output buffer. */
if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, (lzo_bytep)obuf,
&usize, NULL) != LZO_E_OK)
return -1;
osize -= usize;
ret += usize;
obuf += usize;
ibuf += cblock_size;
}
return ret;
}
static grub_ssize_t static grub_ssize_t
grub_btrfs_extent_read (struct grub_btrfs_data *data, grub_btrfs_extent_read (struct grub_btrfs_data *data,
grub_uint64_t ino, grub_uint64_t tree, grub_uint64_t ino, grub_uint64_t tree,
@ -909,6 +991,12 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
grub_error (GRUB_ERR_BAD_FS, "extent not found"); grub_error (GRUB_ERR_BAD_FS, "extent not found");
return -1; return -1;
} }
if ((grub_ssize_t) elemsize < ((char *) &data->extent->inl
- (char *) data->extent))
{
grub_error (GRUB_ERR_BAD_FS, "extent descriptor is too short");
return -1;
}
data->extstart = grub_le_to_cpu64 (key_out.offset); data->extstart = grub_le_to_cpu64 (key_out.offset);
data->extsize = elemsize; data->extsize = elemsize;
data->extent = grub_malloc (elemsize); data->extent = grub_malloc (elemsize);
@ -917,26 +1005,22 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
if (!data->extent) if (!data->extent)
return grub_errno; return grub_errno;
err = grub_btrfs_read_logical (data, elemaddr, err = grub_btrfs_read_logical (data, elemaddr, data->extent,
data->extent, elemsize); elemsize);
if (err) if (err)
return err; return err;
data->extend = data->extstart data->extend = data->extstart + grub_le_to_cpu64 (data->extent->size);
+ grub_le_to_cpu64 (data->extent->size);
if (data->extent->type == GRUB_BTRFS_EXTENT_REGULAR if (data->extent->type == GRUB_BTRFS_EXTENT_REGULAR
&& (char *) &data->extent + elemsize && (char *) &data->extent + elemsize
>= (char *) &data->extent->filled >= (char *) &data->extent->filled + sizeof (data->extent->filled))
+ sizeof (data->extent->filled)) data->extend =
data->extend = data->extstart data->extstart + grub_le_to_cpu64 (data->extent->filled);
+ grub_le_to_cpu64 (data->extent->filled);
grub_dprintf ("btrfs", "extent 0x%" PRIxGRUB_UINT64_T "+0x%" grub_dprintf ("btrfs", "regular extent 0x%" PRIxGRUB_UINT64_T "+0x%"
PRIxGRUB_UINT64_T " (0x%" PRIxGRUB_UINT64_T "\n",
PRIxGRUB_UINT64_T ")\n",
grub_le_to_cpu64 (key_out.offset), grub_le_to_cpu64 (key_out.offset),
grub_le_to_cpu64 (data->extent->size), grub_le_to_cpu64 (data->extent->size));
grub_le_to_cpu64 (data->extent->filled));
if (data->extend <= pos) if (data->extend <= pos)
{ {
grub_error (GRUB_ERR_BAD_FS, "extent not found"); grub_error (GRUB_ERR_BAD_FS, "extent not found");
@ -956,7 +1040,8 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
} }
if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE
&& data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB) && data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB
&& data->extent->compression != GRUB_BTRFS_COMPRESSION_LZO)
{ {
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"compression type 0x%x not supported", "compression type 0x%x not supported",
@ -966,8 +1051,7 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
if (data->extent->encoding) if (data->extent->encoding)
{ {
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "encoding not supported");
"encoding not supported");
return -1; return -1;
} }
@ -983,6 +1067,15 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
!= (grub_ssize_t) csize) != (grub_ssize_t) csize)
return -1; return -1;
} }
else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO)
{
if (grub_btrfs_lzo_decompress(data->extent->inl, data->extsize -
((grub_uint8_t *) data->extent->inl
- (grub_uint8_t *) data->extent),
extoff, buf, csize)
!= (grub_ssize_t) csize)
return -1;
}
else else
grub_memcpy (buf, data->extent->inl + extoff, csize); grub_memcpy (buf, data->extent->inl + extoff, csize);
break; break;
@ -992,10 +1085,13 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
grub_memset (buf, 0, csize); grub_memset (buf, 0, csize);
break; break;
} }
if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB)
if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE)
{ {
char *tmp; char *tmp;
grub_uint64_t zsize; grub_uint64_t zsize;
grub_ssize_t ret;
zsize = grub_le_to_cpu64 (data->extent->compressed_size); zsize = grub_le_to_cpu64 (data->extent->compressed_size);
tmp = grub_malloc (zsize); tmp = grub_malloc (zsize);
if (!tmp) if (!tmp)
@ -1008,27 +1104,35 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
grub_free (tmp); grub_free (tmp);
return -1; return -1;
} }
if (grub_zlib_decompress (tmp, zsize, extoff
+ grub_le_to_cpu64 (data->extent->offset), if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB)
buf, csize) != (grub_ssize_t) csize) ret = grub_zlib_decompress (tmp, zsize, extoff
{ + grub_le_to_cpu64 (data->extent->offset),
grub_free (tmp); buf, csize);
return -1; else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO)
} ret = grub_btrfs_lzo_decompress (tmp, zsize, extoff
+ grub_le_to_cpu64 (data->extent->offset),
buf, csize);
else
ret = -1;
grub_free (tmp); grub_free (tmp);
if (ret != (grub_ssize_t) csize)
return -1;
break; break;
} }
err = grub_btrfs_read_logical (data, err = grub_btrfs_read_logical (data,
grub_le_to_cpu64 (data->extent->laddr) grub_le_to_cpu64 (data->extent->laddr)
+ grub_le_to_cpu64 (data->extent->offset) + grub_le_to_cpu64 (data->extent->offset)
+ extoff, + extoff, buf, csize);
buf, csize);
if (err) if (err)
return -1; return -1;
break; break;
default: default:
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported extent type 0x%x", data->extent->type); "unsupported extent type 0x%x", data->extent->type);
return -1; return -1;
} }
buf += csize; buf += csize;
@ -1096,9 +1200,9 @@ find_path (struct grub_btrfs_data *data,
key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
key->offset = grub_cpu_to_le64 (~grub_getcrc32c (1, ctoken, ctokenlen)); key->offset = grub_cpu_to_le64 (~grub_getcrc32c (1, ctoken, ctokenlen));
err = lower_bound (data, key, &key_out, *tree, err = lower_bound (data, key, &key_out, *tree, &elemaddr, &elemsize,
&elemaddr, &elemsize, NULL); NULL);
if (err) if (err)
{ {
grub_free (direl); grub_free (direl);
@ -1140,7 +1244,7 @@ find_path (struct grub_btrfs_data *data,
for (cdirel = direl; for (cdirel = direl;
(grub_uint8_t *) cdirel - (grub_uint8_t *) direl (grub_uint8_t *) cdirel - (grub_uint8_t *) direl
< (grub_ssize_t) elemsize; < (grub_ssize_t) elemsize;
cdirel = (void *) ((grub_uint8_t *) (direl + 1) cdirel = (void *) ((grub_uint8_t *) (direl + 1)
+ grub_le_to_cpu16 (cdirel->n) + grub_le_to_cpu16 (cdirel->n)
+ grub_le_to_cpu16 (cdirel->m))) + grub_le_to_cpu16 (cdirel->m)))
@ -1174,7 +1278,7 @@ find_path (struct grub_btrfs_data *data,
return grub_error (GRUB_ERR_SYMLINK_LOOP, return grub_error (GRUB_ERR_SYMLINK_LOOP,
"too deep nesting of symlinks"); "too deep nesting of symlinks");
} }
err = grub_btrfs_read_inode (data, &inode, err = grub_btrfs_read_inode (data, &inode,
cdirel->key.object_id, *tree); cdirel->key.object_id, *tree);
if (err) if (err)
@ -1205,10 +1309,9 @@ find_path (struct grub_btrfs_data *data,
grub_free (tmp); grub_free (tmp);
return grub_errno; return grub_errno;
} }
grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path, grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path,
grub_strlen (path) + 1); grub_strlen (path) + 1);
grub_free (path_alloc); grub_free (path_alloc);
grub_free (origpath);
path = path_alloc = tmp; path = path_alloc = tmp;
if (path[0] == '/') if (path[0] == '/')
{ {
@ -1247,8 +1350,7 @@ find_path (struct grub_btrfs_data *data,
grub_free (origpath); grub_free (origpath);
return err; return err;
} }
err = grub_btrfs_read_logical (data, elemaddr, err = grub_btrfs_read_logical (data, elemaddr, &ri, sizeof (ri));
&ri, sizeof (ri));
if (err) if (err)
{ {
grub_free (direl); grub_free (direl);
@ -1279,19 +1381,21 @@ find_path (struct grub_btrfs_data *data,
grub_free (path_alloc); grub_free (path_alloc);
grub_free (origpath); grub_free (origpath);
grub_free (direl); grub_free (direl);
return grub_error (GRUB_ERR_BAD_FS, "unrecognised object type 0x%x", return grub_error (GRUB_ERR_BAD_FS, "unrecognised object type 0x%x",
cdirel->key.type); cdirel->key.type);
} }
} }
grub_free (direl); grub_free (direl);
grub_free (origpath);
grub_free (path_alloc);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
static grub_err_t static grub_err_t
grub_btrfs_dir (grub_device_t device, const char *path, grub_btrfs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename, int (*hook) (const char *filename,
const struct grub_dirhook_info *info)) const struct grub_dirhook_info *info))
{ {
struct grub_btrfs_data *data = grub_btrfs_mount (device); struct grub_btrfs_data *data = grub_btrfs_mount (device);
struct grub_btrfs_key key_in, key_out; struct grub_btrfs_key key_in, key_out;
@ -1310,23 +1414,28 @@ grub_btrfs_dir (grub_device_t device, const char *path,
err = find_path (data, path, &key_in, &tree, &type); err = find_path (data, path, &key_in, &tree, &type);
if (err) if (err)
return err; {
grub_btrfs_unmount (data);
return err;
}
if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY)
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); {
grub_btrfs_unmount (data);
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
}
err = lower_bound (data, &key_in, &key_out, tree, err = lower_bound (data, &key_in, &key_out, tree, &elemaddr, &elemsize, &desc);
&elemaddr, &elemsize, &desc);
if (err) if (err)
return err; {
grub_btrfs_unmount (data);
return err;
}
if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM
|| key_out.object_id != key_in.object_id) || key_out.object_id != key_in.object_id)
{ {
r = next (data, &desc, &elemaddr, &elemsize, &key_out); r = next (data, &desc, &elemaddr, &elemsize, &key_out);
if (r <= 0) if (r <= 0)
{ goto out;
free_iterator (&desc);
return -r;
}
} }
do do
{ {
@ -1344,18 +1453,21 @@ grub_btrfs_dir (grub_device_t device, const char *path,
direl = grub_malloc (allocated + 1); direl = grub_malloc (allocated + 1);
if (!direl) if (!direl)
{ {
free_iterator (&desc); r = -grub_errno;
return grub_errno; break;
} }
} }
err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize); err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize);
if (err) if (err)
return err; {
r = -err;
break;
}
for (cdirel = direl; for (cdirel = direl;
(grub_uint8_t *) cdirel - (grub_uint8_t *) direl (grub_uint8_t *) cdirel - (grub_uint8_t *) direl
< (grub_ssize_t) elemsize; < (grub_ssize_t) elemsize;
cdirel = (void *) ((grub_uint8_t *) (direl + 1) cdirel = (void *) ((grub_uint8_t *) (direl + 1)
+ grub_le_to_cpu16 (cdirel->n) + grub_le_to_cpu16 (cdirel->n)
+ grub_le_to_cpu16 (cdirel->m))) + grub_le_to_cpu16 (cdirel->m)))
@ -1384,7 +1496,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
} }
while (r > 0); while (r > 0);
out: out:
grub_free (direl); grub_free (direl);
free_iterator (&desc); free_iterator (&desc);
@ -1456,7 +1568,7 @@ grub_btrfs_uuid (grub_device_t device, char **uuid)
*uuid = NULL; *uuid = NULL;
data = grub_btrfs_mount (device); data = grub_btrfs_mount (device);
if (! data) if (!data)
return grub_errno; return grub_errno;
*uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
@ -1482,7 +1594,7 @@ grub_btrfs_label (grub_device_t device, char **label)
*label = NULL; *label = NULL;
data = grub_btrfs_mount (device); data = grub_btrfs_mount (device);
if (! data) if (!data)
return grub_errno; return grub_errno;
*label = grub_strndup (data->sblock.label, sizeof (data->sblock.label)); *label = grub_strndup (data->sblock.label, sizeof (data->sblock.label));
@ -1492,26 +1604,55 @@ grub_btrfs_label (grub_device_t device, char **label)
return grub_errno; return grub_errno;
} }
static struct grub_fs grub_btrfs_fs =
{
.name = "btrfs",
.dir = grub_btrfs_dir,
.open = grub_btrfs_open,
.read = grub_btrfs_read,
.close = grub_btrfs_close,
.uuid = grub_btrfs_uuid,
.label = grub_btrfs_label,
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
.reserved_first_sector = 1, static grub_err_t
#endif grub_btrfs_embed (grub_device_t device __attribute__ ((unused)),
}; unsigned int *nsectors,
grub_embed_type_t embed_type,
grub_disk_addr_t **sectors)
{
unsigned i;
GRUB_MOD_INIT(btrfs) if (embed_type != GRUB_EMBED_PCBIOS)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"BtrFS currently supports only PC-BIOS embedding");
if (64 * 2 - 1 < *nsectors)
return grub_error (GRUB_ERR_OUT_OF_RANGE,
"Your core.img is unusually large. "
"It won't fit in the embedding area.");
*nsectors = 64 * 2 - 1;
*sectors = grub_malloc (*nsectors * sizeof (**sectors));
if (!*sectors)
return grub_errno;
for (i = 0; i < *nsectors; i++)
(*sectors)[i] = i + 1;
return GRUB_ERR_NONE;
}
#endif
static struct grub_fs grub_btrfs_fs = {
.name = "btrfs",
.dir = grub_btrfs_dir,
.open = grub_btrfs_open,
.read = grub_btrfs_read,
.close = grub_btrfs_close,
.uuid = grub_btrfs_uuid,
.label = grub_btrfs_label,
#ifdef GRUB_UTIL
.embed = grub_btrfs_embed,
.reserved_first_sector = 1,
#endif
};
GRUB_MOD_INIT (btrfs)
{ {
grub_fs_register (&grub_btrfs_fs); grub_fs_register (&grub_btrfs_fs);
} }
GRUB_MOD_FINI(btrfs) GRUB_MOD_FINI (btrfs)
{ {
grub_fs_unregister (&grub_btrfs_fs); grub_fs_unregister (&grub_btrfs_fs);
} }

View file

@ -25,6 +25,11 @@
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
#define ATTR_TYPE 0160000
#define ATTR_FILE 0100000
#define ATTR_DIR 0040000
#define ATTR_LNK 0120000
#ifndef MODE_USTAR #ifndef MODE_USTAR
/* cpio support */ /* cpio support */
#define MAGIC_BCPIO 070707 #define MAGIC_BCPIO 070707
@ -71,60 +76,94 @@ struct head
struct grub_cpio_data struct grub_cpio_data
{ {
grub_disk_t disk; grub_disk_t disk;
grub_uint32_t hofs; grub_off_t hofs;
grub_uint32_t dofs; grub_off_t dofs;
grub_uint32_t size; grub_off_t size;
#ifdef MODE_USTAR
char *linkname;
grub_size_t linkname_alloc;
#endif
}; };
static grub_dl_t my_mod; static grub_dl_t my_mod;
static inline void
canonicalize (char *name)
{
char *iptr, *optr;
for (iptr = name, optr = name; *iptr; )
{
while (*iptr == '/')
iptr++;
if (iptr[0] == '.' && (iptr[1] == '/' || iptr[1] == 0))
{
iptr += 2;
continue;
}
while (*iptr && *iptr != '/')
*optr++ = *iptr++;
if (*iptr)
*optr++ = *iptr++;
}
*optr = 0;
}
static grub_err_t static grub_err_t
grub_cpio_find_file (struct grub_cpio_data *data, char **name, grub_cpio_find_file (struct grub_cpio_data *data, char **name,
grub_int32_t *mtime, grub_uint32_t * ofs) grub_int32_t *mtime, grub_disk_addr_t *ofs,
grub_uint32_t *mode)
{ {
#ifndef MODE_USTAR #ifndef MODE_USTAR
struct head hd; struct head hd;
if (grub_disk_read if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd))
(data->disk, 0, data->hofs, sizeof (hd), &hd)) return grub_errno;
return grub_errno;
if (hd.magic != MAGIC_BCPIO) if (hd.magic != MAGIC_BCPIO)
return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive"); return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2; data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2;
if (mtime) if (mtime)
*mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2; *mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2;
if (mode)
*mode = hd.mode;
if (hd.namesize & 1) if (hd.namesize & 1)
hd.namesize++; hd.namesize++;
if ((*name = grub_malloc (hd.namesize)) == NULL) *name = grub_malloc (hd.namesize + 1);
return grub_errno; if (*name == NULL)
return grub_errno;
if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd),
hd.namesize, *name)) hd.namesize, *name))
{ {
grub_free (*name); grub_free (*name);
return grub_errno; return grub_errno;
} }
(*name)[hd.namesize] = 0;
if (data->size == 0 && hd.mode == 0 && hd.namesize == 11 + 1 if (data->size == 0 && hd.mode == 0 && hd.namesize == 11 + 1
&& ! grub_memcmp(*name, "TRAILER!!!", 11)) && grub_memcmp(*name, "TRAILER!!!", 11) == 0)
{ {
*ofs = 0; *ofs = 0;
return GRUB_ERR_NONE; grub_free (*name);
} return GRUB_ERR_NONE;
}
data->dofs = data->hofs + sizeof (hd) + hd.namesize; canonicalize (*name);
*ofs = data->dofs + data->size;
if (data->size & 1) data->dofs = data->hofs + sizeof (hd) + hd.namesize;
(*ofs)++; *ofs = data->dofs + data->size;
if (data->size & 1)
(*ofs)++;
#else #else
struct head hd; struct head hd;
int reread = 0, have_longname = 0, have_longlink = 0;
if (grub_disk_read for (reread = 0; reread < 3; reread++)
(data->disk, 0, data->hofs, sizeof (hd), &hd)) {
if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd))
return grub_errno; return grub_errno;
if (!hd.name[0]) if (!hd.name[0])
@ -136,15 +175,102 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name,
if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1)) if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1))
return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive"); return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive");
if ((*name = grub_strdup (hd.name)) == NULL) if (hd.typeflag == 'L')
return grub_errno; {
grub_err_t err;
grub_size_t namesize = grub_strtoull (hd.size, NULL, 8);
*name = grub_malloc (namesize + 1);
if (*name == NULL)
return grub_errno;
err = grub_disk_read (data->disk, 0,
data->hofs + GRUB_DISK_SECTOR_SIZE, namesize,
*name);
(*name)[namesize] = 0;
if (err)
return err;
data->hofs += GRUB_DISK_SECTOR_SIZE
+ ((namesize + GRUB_DISK_SECTOR_SIZE - 1) &
~(GRUB_DISK_SECTOR_SIZE - 1));
have_longname = 1;
continue;
}
data->size = grub_strtoul (hd.size, NULL, 8); if (hd.typeflag == 'K')
{
grub_err_t err;
grub_size_t linksize = grub_strtoull (hd.size, NULL, 8);
if (data->linkname_alloc < linksize + 1)
{
char *n;
n = grub_malloc (2 * (linksize + 1));
if (!n)
return grub_errno;
grub_free (data->linkname);
data->linkname = n;
data->linkname_alloc = 2 * (linksize + 1);
}
err = grub_disk_read (data->disk, 0,
data->hofs + GRUB_DISK_SECTOR_SIZE, linksize,
data->linkname);
if (err)
return err;
data->linkname[linksize] = 0;
data->hofs += GRUB_DISK_SECTOR_SIZE
+ ((linksize + GRUB_DISK_SECTOR_SIZE - 1) &
~(GRUB_DISK_SECTOR_SIZE - 1));
have_longlink = 1;
continue;
}
if (!have_longname)
{
*name = grub_strdup (hd.name);
if (*name == NULL)
return grub_errno;
}
data->size = grub_strtoull (hd.size, NULL, 8);
data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
*ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
~(GRUB_DISK_SECTOR_SIZE - 1)); ~(GRUB_DISK_SECTOR_SIZE - 1));
if (mtime) if (mtime)
*mtime = grub_strtoul (hd.mtime, NULL, 8); *mtime = grub_strtoul (hd.mtime, NULL, 8);
if (mode)
{
*mode = grub_strtoul (hd.mode, NULL, 8);
switch (hd.typeflag)
{
case '2':
*mode |= ATTR_LNK;
break;
case '0':
*mode |= ATTR_FILE;
break;
case '5':
*mode |= ATTR_DIR;
break;
}
}
if (!have_longlink)
{
if (data->linkname_alloc < 101)
{
char *n;
n = grub_malloc (101);
if (!n)
return grub_errno;
grub_free (data->linkname);
data->linkname = n;
data->linkname_alloc = 101;
}
grub_memcpy (data->linkname, hd.linkname, sizeof (hd.linkname));
data->linkname[100] = 0;
}
canonicalize (*name);
return GRUB_ERR_NONE;
}
#endif #endif
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -166,7 +292,7 @@ grub_cpio_mount (grub_disk_t disk)
#endif #endif
goto fail; goto fail;
data = (struct grub_cpio_data *) grub_malloc (sizeof (*data)); data = (struct grub_cpio_data *) grub_zalloc (sizeof (*data));
if (!data) if (!data)
goto fail; goto fail;
@ -186,15 +312,107 @@ fail:
} }
static grub_err_t static grub_err_t
grub_cpio_dir (grub_device_t device, const char *path, handle_symlink (struct grub_cpio_data *data,
const char *fn, char **name,
grub_uint32_t mode, int *restart)
{
grub_size_t flen;
char *target;
#ifndef MODE_USTAR
grub_err_t err;
#endif
char *ptr;
char *lastslash;
grub_size_t prefixlen;
char *rest;
grub_size_t size;
*restart = 0;
if ((mode & ATTR_TYPE) != ATTR_LNK)
return GRUB_ERR_NONE;
flen = grub_strlen (fn);
if (grub_memcmp (*name, fn, flen) != 0
|| ((*name)[flen] != 0 && (*name)[flen] != '/'))
return GRUB_ERR_NONE;
rest = *name + flen;
lastslash = rest;
if (*rest)
rest++;
while (lastslash >= *name && *lastslash != '/')
lastslash--;
if (lastslash >= *name)
prefixlen = lastslash - *name;
else
prefixlen = 0;
if (prefixlen)
prefixlen++;
#ifdef MODE_USTAR
size = grub_strlen (data->linkname);
#else
size = data->size;
#endif
if (size == 0)
return GRUB_ERR_NONE;
target = grub_malloc (size + grub_strlen (*name) + 2);
if (!target)
return grub_errno;
#ifdef MODE_USTAR
grub_memcpy (target + prefixlen, data->linkname, size);
#else
err = grub_disk_read (data->disk, 0, data->dofs, data->size,
target + prefixlen);
if (err)
return err;
#endif
if (target[prefixlen] == '/')
{
grub_memmove (target, target + prefixlen, data->size - 1);
ptr = target + data->size - 1;
ptr = grub_stpcpy (ptr, rest);
*ptr = 0;
grub_dprintf ("cpio", "symlink redirected %s to %s\n",
*name, target);
grub_free (*name);
*name = target;
*restart = 1;
return GRUB_ERR_NONE;
}
if (prefixlen)
{
grub_memcpy (target, *name, prefixlen);
target[prefixlen] = '/';
}
ptr = target + prefixlen + size;
ptr = grub_stpcpy (ptr, rest);
*ptr = 0;
grub_dprintf ("cpio", "symlink redirected %s to %s\n",
*name, target);
grub_free (*name);
*name = target;
*restart = 1;
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cpio_dir (grub_device_t device, const char *path_in,
int (*hook) (const char *filename, int (*hook) (const char *filename,
const struct grub_dirhook_info *info)) const struct grub_dirhook_info *info))
{ {
struct grub_cpio_data *data; struct grub_cpio_data *data;
grub_uint32_t ofs; grub_disk_addr_t ofs;
char *prev, *name; char *prev, *name, *path, *ptr;
const char *np; grub_size_t len;
int len; int symlinknest = 0;
path = grub_strdup (path_in + 1);
if (!path)
return grub_errno;
for (ptr = path + grub_strlen (path) - 1; ptr >= path && *ptr == '/'; ptr--)
*ptr = 0;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
@ -202,35 +420,39 @@ grub_cpio_dir (grub_device_t device, const char *path,
data = grub_cpio_mount (device->disk); data = grub_cpio_mount (device->disk);
if (!data) if (!data)
goto fail; {
grub_free (path);
np = path + 1; return grub_errno;
len = grub_strlen (path) - 1; }
len = grub_strlen (path);
data->hofs = 0; data->hofs = 0;
while (1) while (1)
{ {
grub_int32_t mtime; grub_int32_t mtime;
grub_uint32_t mode;
grub_err_t err;
if (grub_cpio_find_file (data, &name, &mtime, &ofs)) if (grub_cpio_find_file (data, &name, &mtime, &ofs, &mode))
goto fail; goto fail;
if (!ofs) if (!ofs)
break; break;
if (grub_memcmp (np, name, len) == 0) if (grub_memcmp (path, name, len) == 0
&& (name[len] == 0 || name[len] == '/' || len == 0))
{ {
char *p, *n; char *p, *n;
n = name + len; n = name + len;
if (*n == '/') while (*n == '/')
n++; n++;
p = grub_strchr (name + len, '/'); p = grub_strchr (n, '/');
if (p) if (p)
*p = 0; *p = 0;
if ((!prev) || (grub_strcmp (prev, name) != 0)) if (((!prev) || (grub_strcmp (prev, n) != 0)) && *n != 0)
{ {
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
@ -238,19 +460,42 @@ grub_cpio_dir (grub_device_t device, const char *path,
info.mtime = mtime; info.mtime = mtime;
info.mtimeset = 1; info.mtimeset = 1;
hook (name + len, &info); hook (n, &info);
grub_free (prev); grub_free (prev);
prev = name; prev = name;
} }
else else
grub_free (name); {
int restart;
err = handle_symlink (data, name, &path, mode, &restart);
grub_free (name);
if (err)
goto fail;
if (restart)
{
len = grub_strlen (path);
if (++symlinknest == 8)
{
grub_error (GRUB_ERR_SYMLINK_LOOP,
"too deep nesting of symlinks");
goto fail;
}
ofs = 0;
}
}
} }
else
grub_free (name);
data->hofs = ofs; data->hofs = ofs;
} }
fail: fail:
grub_free (path);
grub_free (prev); grub_free (prev);
#ifdef MODE_USTAR
grub_free (data->linkname);
#endif
grub_free (data); grub_free (data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -259,23 +504,33 @@ fail:
} }
static grub_err_t static grub_err_t
grub_cpio_open (grub_file_t file, const char *name) grub_cpio_open (grub_file_t file, const char *name_in)
{ {
struct grub_cpio_data *data; struct grub_cpio_data *data;
grub_uint32_t ofs; grub_disk_addr_t ofs;
char *fn; char *fn;
int i, j; char *name = grub_strdup (name_in + 1);
int symlinknest = 0;
if (!name)
return grub_errno;
grub_dl_ref (my_mod); grub_dl_ref (my_mod);
data = grub_cpio_mount (file->device->disk); data = grub_cpio_mount (file->device->disk);
if (!data) if (!data)
goto fail; {
grub_free (name);
return grub_errno;
}
data->hofs = 0; data->hofs = 0;
while (1) while (1)
{ {
if (grub_cpio_find_file (data, &fn, NULL, &ofs)) grub_uint32_t mode;
int restart;
if (grub_cpio_find_file (data, &fn, NULL, &ofs, &mode))
goto fail; goto fail;
if (!ofs) if (!ofs)
@ -284,33 +539,31 @@ grub_cpio_open (grub_file_t file, const char *name)
break; break;
} }
/* Compare NAME and FN by hand in order to cope with duplicate if (handle_symlink (data, fn, &name, mode, &restart))
slashes. */
i = 0;
j = 0;
while (name[i] == '/')
i++;
while (1)
{ {
if (name[i] != fn[j]) grub_free (fn);
goto no_match; goto fail;
if (name[i] == '\0')
break;
while (name[i] == '/' && name[i+1] == '/')
i++;
i++;
j++;
} }
if (name[i] != fn[j]) if (restart)
{
ofs = 0;
if (++symlinknest == 8)
{
grub_error (GRUB_ERR_SYMLINK_LOOP,
"too deep nesting of symlinks");
goto fail;
}
goto no_match;
}
if (grub_strcmp (name, fn) != 0)
goto no_match; goto no_match;
file->data = data; file->data = data;
file->size = data->size; file->size = data->size;
grub_free (fn); grub_free (fn);
grub_free (name);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
@ -321,8 +574,11 @@ grub_cpio_open (grub_file_t file, const char *name)
} }
fail: fail:
#ifdef MODE_USTAR
grub_free (data->linkname);
#endif
grub_free (data); grub_free (data);
grub_free (name);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -342,7 +598,13 @@ grub_cpio_read (grub_file_t file, char *buf, grub_size_t len)
static grub_err_t static grub_err_t
grub_cpio_close (grub_file_t file) grub_cpio_close (grub_file_t file)
{ {
grub_free (file->data); struct grub_cpio_data *data;
data = file->data;
#ifdef MODE_USTAR
grub_free (data->linkname);
#endif
grub_free (data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);

2
grub-core/fs/exfat.c Normal file
View file

@ -0,0 +1,2 @@
#define MODE_EXFAT 1
#include "fat.c"

View file

@ -337,7 +337,7 @@ grub_ext2_blockgroup (struct grub_ext2_data *data, int group,
} }
static struct grub_ext4_extent_header * static struct grub_ext4_extent_header *
grub_ext4_find_leaf (struct grub_ext2_data *data, char *buf, grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf,
struct grub_ext4_extent_header *ext_block, struct grub_ext4_extent_header *ext_block,
grub_uint32_t fileblock) grub_uint32_t fileblock)
{ {
@ -387,7 +387,7 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
if (grub_le_to_cpu32(inode->flags) & EXT4_EXTENTS_FLAG) if (grub_le_to_cpu32(inode->flags) & EXT4_EXTENTS_FLAG)
{ {
char buf[EXT2_BLOCK_SIZE(data)]; GRUB_PROPERLY_ALIGNED_ARRAY (buf, EXT2_BLOCK_SIZE(data));
struct grub_ext4_extent_header *leaf; struct grub_ext4_extent_header *leaf;
struct grub_ext4_extent *ext; struct grub_ext4_extent *ext;
int i; int i;

View file

@ -30,28 +30,117 @@
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_FAT_DIR_ENTRY_SIZE 32 enum
{
GRUB_FAT_ATTR_READ_ONLY = 0x01,
GRUB_FAT_ATTR_HIDDEN = 0x02,
GRUB_FAT_ATTR_SYSTEM = 0x04,
#ifndef MODE_EXFAT
GRUB_FAT_ATTR_VOLUME_ID = 0x08,
#endif
GRUB_FAT_ATTR_DIRECTORY = 0x10,
GRUB_FAT_ATTR_ARCHIVE = 0x20,
#define GRUB_FAT_ATTR_READ_ONLY 0x01 #ifndef MODE_EXFAT
#define GRUB_FAT_ATTR_HIDDEN 0x02 GRUB_FAT_ATTR_LONG_NAME = (GRUB_FAT_ATTR_READ_ONLY
#define GRUB_FAT_ATTR_SYSTEM 0x04 | GRUB_FAT_ATTR_HIDDEN
#define GRUB_FAT_ATTR_VOLUME_ID 0x08 | GRUB_FAT_ATTR_SYSTEM
#define GRUB_FAT_ATTR_DIRECTORY 0x10 | GRUB_FAT_ATTR_VOLUME_ID),
#define GRUB_FAT_ATTR_ARCHIVE 0x20 #endif
GRUB_FAT_ATTR_VALID = (GRUB_FAT_ATTR_READ_ONLY
| GRUB_FAT_ATTR_HIDDEN
| GRUB_FAT_ATTR_SYSTEM
| GRUB_FAT_ATTR_DIRECTORY
| GRUB_FAT_ATTR_ARCHIVE
#ifndef MODE_EXFAT
| GRUB_FAT_ATTR_VOLUME_ID
#endif
)
};
#define GRUB_FAT_MAXFILE 256 #ifdef MODE_EXFAT
struct grub_exfat_bpb
{
grub_uint8_t jmp_boot[3];
grub_uint8_t oem_name[8];
grub_uint8_t mbz[53];
grub_uint64_t num_hidden_sectors;
grub_uint64_t num_total_sectors;
grub_uint32_t num_reserved_sectors;
grub_uint32_t sectors_per_fat;
grub_uint32_t cluster_offset;
grub_uint32_t cluster_count;
grub_uint32_t root_cluster;
grub_uint32_t num_serial;
grub_uint16_t fs_revision;
grub_uint16_t volume_flags;
grub_uint8_t bytes_per_sector_shift;
grub_uint8_t sectors_per_cluster_shift;
grub_uint8_t num_fats;
grub_uint8_t num_ph_drive;
grub_uint8_t reserved[8];
} __attribute__ ((packed));
typedef struct grub_exfat_bpb grub_current_fat_bpb_t;
#else
typedef struct grub_fat_bpb grub_current_fat_bpb_t;
#endif
#define GRUB_FAT_ATTR_LONG_NAME (GRUB_FAT_ATTR_READ_ONLY \ #ifdef MODE_EXFAT
| GRUB_FAT_ATTR_HIDDEN \ struct grub_fat_dir_entry
| GRUB_FAT_ATTR_SYSTEM \ {
| GRUB_FAT_ATTR_VOLUME_ID) grub_uint8_t entry_type;
#define GRUB_FAT_ATTR_VALID (GRUB_FAT_ATTR_READ_ONLY \ union
| GRUB_FAT_ATTR_HIDDEN \ {
| GRUB_FAT_ATTR_SYSTEM \ grub_uint8_t placeholder[31];
| GRUB_FAT_ATTR_DIRECTORY \ struct {
| GRUB_FAT_ATTR_ARCHIVE \ grub_uint8_t secondary_count;
| GRUB_FAT_ATTR_VOLUME_ID) grub_uint16_t checksum;
grub_uint16_t attr;
grub_uint16_t reserved1;
grub_uint32_t c_time;
grub_uint32_t m_time;
grub_uint32_t a_time;
grub_uint8_t c_time_tenth;
grub_uint8_t m_time_tenth;
grub_uint8_t a_time_tenth;
grub_uint8_t reserved2[9];
} __attribute__ ((packed)) file;
struct {
grub_uint8_t flags;
grub_uint8_t reserved1;
grub_uint8_t name_length;
grub_uint16_t name_hash;
grub_uint16_t reserved2;
grub_uint64_t valid_size;
grub_uint32_t reserved3;
grub_uint32_t first_cluster;
grub_uint64_t file_size;
} __attribute__ ((packed)) stream_extension;
struct {
grub_uint8_t flags;
grub_uint16_t str[15];
} __attribute__ ((packed)) file_name;
struct {
grub_uint8_t character_count;
grub_uint16_t str[11];
grub_uint8_t reserved[8];
} __attribute__ ((packed)) volume_label;
} __attribute__ ((packed)) type_specific;
} __attribute__ ((packed));
struct grub_fat_dir_node
{
grub_uint32_t attr;
grub_uint32_t first_cluster;
grub_uint64_t file_size;
grub_uint64_t valid_size;
int have_stream;
int is_label;
};
typedef struct grub_fat_dir_node grub_fat_dir_node_t;
#else
struct grub_fat_dir_entry struct grub_fat_dir_entry
{ {
grub_uint8_t name[11]; grub_uint8_t name[11];
@ -80,6 +169,10 @@ struct grub_fat_long_name_entry
grub_uint16_t name3[2]; grub_uint16_t name3[2];
} __attribute__ ((packed)); } __attribute__ ((packed));
typedef struct grub_fat_dir_entry grub_fat_dir_node_t;
#endif
struct grub_fat_data struct grub_fat_data
{ {
int logical_sector_bits; int logical_sector_bits;
@ -90,8 +183,10 @@ struct grub_fat_data
int fat_size; int fat_size;
grub_uint32_t root_cluster; grub_uint32_t root_cluster;
#ifndef MODE_EXFAT
grub_uint32_t root_sector; grub_uint32_t root_sector;
grub_uint32_t num_root_sectors; grub_uint32_t num_root_sectors;
#endif
int cluster_bits; int cluster_bits;
grub_uint32_t cluster_eof_mark; grub_uint32_t cluster_eof_mark;
@ -109,6 +204,7 @@ struct grub_fat_data
static grub_dl_t my_mod; static grub_dl_t my_mod;
#ifndef MODE_EXFAT
static int static int
fat_log2 (unsigned x) fat_log2 (unsigned x)
{ {
@ -125,11 +221,12 @@ fat_log2 (unsigned x)
return i; return i;
} }
#endif
static struct grub_fat_data * static struct grub_fat_data *
grub_fat_mount (grub_disk_t disk) grub_fat_mount (grub_disk_t disk)
{ {
struct grub_fat_bpb bpb; grub_current_fat_bpb_t bpb;
struct grub_fat_data *data = 0; struct grub_fat_data *data = 0;
grub_uint32_t first_fat, magic; grub_uint32_t first_fat, magic;
@ -144,20 +241,35 @@ grub_fat_mount (grub_disk_t disk)
if (grub_disk_read (disk, 0, 0, sizeof (bpb), &bpb)) if (grub_disk_read (disk, 0, 0, sizeof (bpb), &bpb))
goto fail; goto fail;
#ifdef MODE_EXFAT
if (grub_memcmp ((const char *) bpb.oem_name, "EXFAT ",
sizeof (bpb.oem_name)) != 0)
goto fail;
#else
if (grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT12", 5) if (grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT12", 5)
&& grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT16", 5) && grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT16", 5)
&& grub_strncmp((const char *) bpb.version_specific.fat32.fstype, "FAT32", 5)) && grub_strncmp((const char *) bpb.version_specific.fat32.fstype, "FAT32", 5))
goto fail; goto fail;
#endif
/* Get the sizes of logical sectors and clusters. */ /* Get the sizes of logical sectors and clusters. */
#ifdef MODE_EXFAT
data->logical_sector_bits = bpb.bytes_per_sector_shift;
#else
data->logical_sector_bits = data->logical_sector_bits =
fat_log2 (grub_le_to_cpu16 (bpb.bytes_per_sector)); fat_log2 (grub_le_to_cpu16 (bpb.bytes_per_sector));
if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS) #endif
if (data->logical_sector_bits < GRUB_DISK_SECTOR_BITS
|| data->logical_sector_bits >= 16)
goto fail; goto fail;
data->logical_sector_bits -= GRUB_DISK_SECTOR_BITS; data->logical_sector_bits -= GRUB_DISK_SECTOR_BITS;
#ifdef MODE_EXFAT
data->cluster_bits = bpb.sectors_per_cluster_shift;
#else
data->cluster_bits = fat_log2 (bpb.sectors_per_cluster); data->cluster_bits = fat_log2 (bpb.sectors_per_cluster);
if (data->cluster_bits < 0) #endif
if (data->cluster_bits < 0 || data->cluster_bits > 25)
goto fail; goto fail;
data->cluster_bits += data->logical_sector_bits; data->cluster_bits += data->logical_sector_bits;
@ -167,18 +279,28 @@ grub_fat_mount (grub_disk_t disk)
if (data->fat_sector == 0) if (data->fat_sector == 0)
goto fail; goto fail;
#ifdef MODE_EXFAT
data->sectors_per_fat = (grub_le_to_cpu32 (bpb.sectors_per_fat)
<< data->logical_sector_bits);
#else
data->sectors_per_fat = ((bpb.sectors_per_fat_16 data->sectors_per_fat = ((bpb.sectors_per_fat_16
? grub_le_to_cpu16 (bpb.sectors_per_fat_16) ? grub_le_to_cpu16 (bpb.sectors_per_fat_16)
: grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32)) : grub_le_to_cpu32 (bpb.version_specific.fat32.sectors_per_fat_32))
<< data->logical_sector_bits); << data->logical_sector_bits);
#endif
if (data->sectors_per_fat == 0) if (data->sectors_per_fat == 0)
goto fail; goto fail;
/* Get the number of sectors in this volume. */ /* Get the number of sectors in this volume. */
#ifdef MODE_EXFAT
data->num_sectors = ((grub_le_to_cpu64 (bpb.num_total_sectors))
<< data->logical_sector_bits);
#else
data->num_sectors = ((bpb.num_total_sectors_16 data->num_sectors = ((bpb.num_total_sectors_16
? grub_le_to_cpu16 (bpb.num_total_sectors_16) ? grub_le_to_cpu16 (bpb.num_total_sectors_16)
: grub_le_to_cpu32 (bpb.num_total_sectors_32)) : grub_le_to_cpu32 (bpb.num_total_sectors_32))
<< data->logical_sector_bits); << data->logical_sector_bits);
#endif
if (data->num_sectors == 0) if (data->num_sectors == 0)
goto fail; goto fail;
@ -186,22 +308,44 @@ grub_fat_mount (grub_disk_t disk)
if (bpb.num_fats == 0) if (bpb.num_fats == 0)
goto fail; goto fail;
#ifndef MODE_EXFAT
data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat; data->root_sector = data->fat_sector + bpb.num_fats * data->sectors_per_fat;
data->num_root_sectors data->num_root_sectors
= ((((grub_uint32_t) grub_le_to_cpu16 (bpb.num_root_entries) = ((((grub_uint32_t) grub_le_to_cpu16 (bpb.num_root_entries)
* GRUB_FAT_DIR_ENTRY_SIZE * sizeof (struct grub_fat_dir_entry)
+ grub_le_to_cpu16 (bpb.bytes_per_sector) - 1) + grub_le_to_cpu16 (bpb.bytes_per_sector) - 1)
>> (data->logical_sector_bits + GRUB_DISK_SECTOR_BITS)) >> (data->logical_sector_bits + GRUB_DISK_SECTOR_BITS))
<< (data->logical_sector_bits)); << (data->logical_sector_bits));
#endif
#ifdef MODE_EXFAT
data->cluster_sector = (grub_le_to_cpu32 (bpb.cluster_offset)
<< data->logical_sector_bits);
data->num_clusters = (grub_le_to_cpu32 (bpb.cluster_count)
<< data->logical_sector_bits);
#else
data->cluster_sector = data->root_sector + data->num_root_sectors; data->cluster_sector = data->root_sector + data->num_root_sectors;
data->num_clusters = (((data->num_sectors - data->cluster_sector) data->num_clusters = (((data->num_sectors - data->cluster_sector)
>> (data->cluster_bits + data->logical_sector_bits)) >> (data->cluster_bits + data->logical_sector_bits))
+ 2); + 2);
#endif
if (data->num_clusters <= 2) if (data->num_clusters <= 2)
goto fail; goto fail;
#ifdef MODE_EXFAT
{
/* exFAT. */
grub_uint16_t flags = grub_le_to_cpu16 (bpb.volume_flags);
data->root_cluster = grub_le_to_cpu32 (bpb.root_cluster);
data->fat_size = 32;
data->cluster_eof_mark = 0xffffffff;
if ((flags & 0x1) && bpb.num_fats > 1)
data->fat_sector += data->sectors_per_fat;
}
#else
if (! bpb.sectors_per_fat_16) if (! bpb.sectors_per_fat_16)
{ {
/* FAT32. */ /* FAT32. */
@ -243,6 +387,7 @@ grub_fat_mount (grub_disk_t disk)
data->cluster_eof_mark = 0xfff8; data->cluster_eof_mark = 0xfff8;
} }
} }
#endif
/* More sanity checks. */ /* More sanity checks. */
if (data->num_sectors <= data->fat_sector) if (data->num_sectors <= data->fat_sector)
@ -274,17 +419,25 @@ grub_fat_mount (grub_disk_t disk)
} }
/* Serial number. */ /* Serial number. */
#ifdef MODE_EXFAT
data->uuid = grub_le_to_cpu32 (bpb.num_serial);
#else
if (bpb.sectors_per_fat_16) if (bpb.sectors_per_fat_16)
data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial); data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat12_or_fat16.num_serial);
else else
data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial); data->uuid = grub_le_to_cpu32 (bpb.version_specific.fat32.num_serial);
#endif
#ifndef MODE_EXFAT
/* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media /* Ignore the 3rd bit, because some BIOSes assigns 0xF0 to the media
descriptor, even if it is a so-called superfloppy (e.g. an USB key). descriptor, even if it is a so-called superfloppy (e.g. an USB key).
The check may be too strict for this kind of stupid BIOSes, as The check may be too strict for this kind of stupid BIOSes, as
they overwrite the media descriptor. */ they overwrite the media descriptor. */
if ((first_fat | 0x8) != (magic | bpb.media | 0x8)) if ((first_fat | 0x8) != (magic | bpb.media | 0x8))
goto fail; goto fail;
#else
(void) magic;
#endif
/* Start from the root directory. */ /* Start from the root directory. */
data->file_cluster = data->root_cluster; data->file_cluster = data->root_cluster;
@ -311,6 +464,7 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
grub_ssize_t ret = 0; grub_ssize_t ret = 0;
unsigned long sector; unsigned long sector;
#ifndef MODE_EXFAT
/* This is a special case. FAT12 and FAT16 doesn't have the root directory /* This is a special case. FAT12 and FAT16 doesn't have the root directory
in clusters. */ in clusters. */
if (data->file_cluster == ~0U) if (data->file_cluster == ~0U)
@ -324,13 +478,14 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
return size; return size;
} }
#endif
/* Calculate the logical cluster number and offset. */ /* Calculate the logical cluster number and offset. */
logical_cluster_bits = (data->cluster_bits logical_cluster_bits = (data->cluster_bits
+ data->logical_sector_bits + data->logical_sector_bits
+ GRUB_DISK_SECTOR_BITS); + GRUB_DISK_SECTOR_BITS);
logical_cluster = offset >> logical_cluster_bits; logical_cluster = offset >> logical_cluster_bits;
offset &= (1 << logical_cluster_bits) - 1; offset &= (1ULL << logical_cluster_bits) - 1;
if (logical_cluster < data->cur_cluster_num) if (logical_cluster < data->cur_cluster_num)
{ {
@ -422,13 +577,116 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data,
return ret; return ret;
} }
#ifdef MODE_EXFAT
static grub_err_t
grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
int (*hook) (const char *filename,
grub_fat_dir_node_t *node))
{
struct grub_fat_dir_entry dir;
grub_ssize_t offset = -sizeof(dir);
grub_uint16_t *unibuf;
char *filename;
unibuf = grub_malloc (15 * 256 * 2);
filename = grub_malloc (15 * 256 * GRUB_MAX_UTF8_PER_UTF16 + 1);
while (1)
{
offset += sizeof (dir);
if (grub_fat_read_data (disk, data, 0,
offset, sizeof (dir), (char *) &dir)
!= sizeof (dir))
break;
if (dir.entry_type == 0)
break;
if (!(dir.entry_type & 0x80))
continue;
if (dir.entry_type == 0x85)
{
unsigned i, nsec, slots = 0;
grub_fat_dir_node_t node;
nsec = dir.type_specific.file.secondary_count;
node.attr = grub_cpu_to_le32 (dir.type_specific.file.attr);
node.have_stream = 0;
for (i = 0; i < nsec; i++)
{
struct grub_fat_dir_entry sec;
offset += sizeof (sec);
if (grub_fat_read_data (disk, data, 0,
offset, sizeof (sec), (char *) &sec)
!= sizeof (sec))
break;
if (!(sec.entry_type & 0x80))
continue;
if (!(sec.entry_type & 0x40))
break;
switch (sec.entry_type)
{
case 0xc0:
node.first_cluster = grub_cpu_to_le32 (sec.type_specific.stream_extension.first_cluster);
node.valid_size
= grub_cpu_to_le64 (sec.type_specific.stream_extension.valid_size);
node.file_size
= grub_cpu_to_le64 (sec.type_specific.stream_extension.file_size);
node.have_stream = 1;
break;
case 0xc1:
grub_memcpy (unibuf + slots * 15,
sec.type_specific.file_name.str, 30);
slots++;
break;
default:
grub_dprintf ("exfat", "unknown secondary type 0x%02x\n",
sec.entry_type);
}
}
if (i != nsec)
{
offset -= sizeof (dir);
continue;
}
*grub_utf16_to_utf8 ((grub_uint8_t *) filename, unibuf,
slots * 15) = '\0';
if (hook (filename, &node))
break;
continue;
}
/* Allocation bitmap. */
if (dir.entry_type == 0x81)
continue;
/* Upcase table. */
if (dir.entry_type == 0x82)
continue;
/* Volume label. */
if (dir.entry_type == 0x83)
continue;
grub_dprintf ("exfat", "unknown primary type 0x%02x\n", dir.entry_type);
}
grub_free (filename);
grub_free (unibuf);
return grub_errno;
}
#else
static grub_err_t static grub_err_t
grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
int (*hook) (const char *filename, int (*hook) (const char *filename,
struct grub_fat_dir_entry *dir)) struct grub_fat_dir_entry *dir))
{ {
struct grub_fat_dir_entry dir; struct grub_fat_dir_entry dir;
char *filename, *filep = 0; char *filename;
char *filep = 0;
grub_uint16_t *unibuf; grub_uint16_t *unibuf;
int slot = -1, slots = -1; int slot = -1, slots = -1;
int checksum = -1; int checksum = -1;
@ -438,7 +696,7 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
/* Allocate space enough to hold a long name. */ /* Allocate space enough to hold a long name. */
filename = grub_malloc (0x40 * 13 * 4 + 1); filename = grub_malloc (0x40 * 13 * GRUB_MAX_UTF8_PER_UTF16 + 1);
unibuf = (grub_uint16_t *) grub_malloc (0x40 * 13 * 2); unibuf = (grub_uint16_t *) grub_malloc (0x40 * 13 * 2);
if (! filename || ! unibuf) if (! filename || ! unibuf)
{ {
@ -455,10 +713,11 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
offset += sizeof (dir); offset += sizeof (dir);
/* Read a directory entry. */ /* Read a directory entry. */
if ((grub_fat_read_data (disk, data, 0, if (grub_fat_read_data (disk, data, 0,
offset, sizeof (dir), (char *) &dir) offset, sizeof (dir), (char *) &dir)
!= sizeof (dir) || dir.name[0] == 0)) != sizeof (dir) || dir.name[0] == 0)
break; break;
/* Handle long name entries. */ /* Handle long name entries. */
if (dir.attr == GRUB_FAT_ATTR_LONG_NAME) if (dir.attr == GRUB_FAT_ATTR_LONG_NAME)
{ {
@ -543,7 +802,6 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
filep++; filep++;
} }
*filep = '\0'; *filep = '\0';
if (hook (filename, &dir)) if (hook (filename, &dir))
break; break;
} }
@ -553,7 +811,7 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data,
return grub_errno; return grub_errno;
} }
#endif
/* Find the underlying directory or file in PATH and return the /* Find the underlying directory or file in PATH and return the
next path. If there is no next path or an error occurs, return NULL. next path. If there is no next path or an error occurs, return NULL.
@ -569,8 +827,8 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
int call_hook; int call_hook;
int found = 0; int found = 0;
auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir); auto int iter_hook (const char *filename, grub_fat_dir_node_t *dir);
int iter_hook (const char *filename, struct grub_fat_dir_entry *dir) int iter_hook (const char *filename, grub_fat_dir_node_t *dir)
{ {
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
@ -578,8 +836,13 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
info.dir = !! (dir->attr & GRUB_FAT_ATTR_DIRECTORY); info.dir = !! (dir->attr & GRUB_FAT_ATTR_DIRECTORY);
info.case_insensitive = 1; info.case_insensitive = 1;
#ifdef MODE_EXFAT
if (!dir->have_stream)
return 0;
#else
if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID) if (dir->attr & GRUB_FAT_ATTR_VOLUME_ID)
return 0; return 0;
#endif
if (*dirname == '\0' && call_hook) if (*dirname == '\0' && call_hook)
return hook (filename, &info); return hook (filename, &info);
@ -587,9 +850,14 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data,
{ {
found = 1; found = 1;
data->attr = dir->attr; data->attr = dir->attr;
#ifdef MODE_EXFAT
data->file_size = dir->file_size;
data->file_cluster = dir->first_cluster;
#else
data->file_size = grub_le_to_cpu32 (dir->file_size); data->file_size = grub_le_to_cpu32 (dir->file_size);
data->file_cluster = ((grub_le_to_cpu16 (dir->first_cluster_high) << 16) data->file_cluster = ((grub_le_to_cpu16 (dir->first_cluster_high) << 16)
| grub_le_to_cpu16 (dir->first_cluster_low)); | grub_le_to_cpu16 (dir->first_cluster_low));
#endif
data->cur_cluster_num = ~0U; data->cur_cluster_num = ~0U;
if (call_hook) if (call_hook)
@ -745,14 +1013,67 @@ grub_fat_close (grub_file_t file)
return grub_errno; return grub_errno;
} }
#ifdef MODE_EXFAT
static grub_err_t
grub_fat_label (grub_device_t device, char **label)
{
struct grub_fat_dir_entry dir;
grub_ssize_t offset = -sizeof(dir);
struct grub_fat_data *data;
grub_disk_t disk = device->disk;
data = grub_fat_mount (disk);
if (! data)
return grub_errno;
*label = NULL;
while (1)
{
offset += sizeof (dir);
if (grub_fat_read_data (disk, data, 0,
offset, sizeof (dir), (char *) &dir)
!= sizeof (dir))
break;
if (dir.entry_type == 0)
break;
if (!(dir.entry_type & 0x80))
continue;
/* Volume label. */
if (dir.entry_type == 0x83)
{
grub_size_t chc;
*label = grub_malloc (11 * 4 + 1);
if (!*label)
{
grub_free (data);
return grub_errno;
}
chc = dir.type_specific.volume_label.character_count;
if (chc > ARRAY_SIZE (dir.type_specific.volume_label.str))
chc = ARRAY_SIZE (dir.type_specific.volume_label.str);
*grub_utf16_to_utf8 ((grub_uint8_t *) *label,
dir.type_specific.volume_label.str, chc) = '\0';
}
}
grub_free (data);
return grub_errno;
}
#else
static grub_err_t static grub_err_t
grub_fat_label (grub_device_t device, char **label) grub_fat_label (grub_device_t device, char **label)
{ {
struct grub_fat_data *data; struct grub_fat_data *data;
grub_disk_t disk = device->disk; grub_disk_t disk = device->disk;
auto int iter_hook (const char *filename, struct grub_fat_dir_entry *dir); auto int iter_hook (const char *filename, grub_fat_dir_node_t *dir);
int iter_hook (const char *filename, struct grub_fat_dir_entry *dir) int iter_hook (const char *filename, grub_fat_dir_node_t *dir)
{ {
if (dir->attr == GRUB_FAT_ATTR_VOLUME_ID) if (dir->attr == GRUB_FAT_ATTR_VOLUME_ID)
{ {
@ -787,6 +1108,8 @@ grub_fat_label (grub_device_t device, char **label)
return grub_errno; return grub_errno;
} }
#endif
static grub_err_t static grub_err_t
grub_fat_uuid (grub_device_t device, char **uuid) grub_fat_uuid (grub_device_t device, char **uuid)
{ {
@ -798,9 +1121,12 @@ grub_fat_uuid (grub_device_t device, char **uuid)
data = grub_fat_mount (disk); data = grub_fat_mount (disk);
if (data) if (data)
{ {
char *ptr;
*uuid = grub_xasprintf ("%04x-%04x", *uuid = grub_xasprintf ("%04x-%04x",
(grub_uint16_t) (data->uuid >> 16), (grub_uint16_t) (data->uuid >> 16),
(grub_uint16_t) data->uuid); (grub_uint16_t) data->uuid);
for (ptr = *uuid; ptr && *ptr; ptr++)
*ptr = grub_toupper (*ptr);
} }
else else
*uuid = NULL; *uuid = NULL;
@ -814,7 +1140,11 @@ grub_fat_uuid (grub_device_t device, char **uuid)
static struct grub_fs grub_fat_fs = static struct grub_fs grub_fat_fs =
{ {
#ifdef MODE_EXFAT
.name = "exfat",
#else
.name = "fat", .name = "fat",
#endif
.dir = grub_fat_dir, .dir = grub_fat_dir,
.open = grub_fat_open, .open = grub_fat_open,
.read = grub_fat_read, .read = grub_fat_read,
@ -822,18 +1152,31 @@ static struct grub_fs grub_fat_fs =
.label = grub_fat_label, .label = grub_fat_label,
.uuid = grub_fat_uuid, .uuid = grub_fat_uuid,
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
#ifdef MODE_EXFAT
/* ExFAT BPB is 30 larger than FAT32 one. */
.reserved_first_sector = 0,
#else
.reserved_first_sector = 1, .reserved_first_sector = 1,
#endif
#endif #endif
.next = 0 .next = 0
}; };
#ifdef MODE_EXFAT
GRUB_MOD_INIT(exfat)
#else
GRUB_MOD_INIT(fat) GRUB_MOD_INIT(fat)
#endif
{ {
COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry) == 32);
grub_fs_register (&grub_fat_fs); grub_fs_register (&grub_fat_fs);
my_mod = mod; my_mod = mod;
} }
#ifdef MODE_EXFAT
GRUB_MOD_FINI(exfat)
#else
GRUB_MOD_FINI(fat) GRUB_MOD_FINI(fat)
#endif
{ {
grub_fs_unregister (&grub_fat_fs); grub_fs_unregister (&grub_fat_fs);
} }

View file

@ -61,7 +61,6 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode,
char fpath[grub_strlen (currpath) + 1]; char fpath[grub_strlen (currpath) + 1];
char *name = fpath; char *name = fpath;
char *next; char *next;
// unsigned int pos = 0;
enum grub_fshelp_filetype type = GRUB_FSHELP_DIR; enum grub_fshelp_filetype type = GRUB_FSHELP_DIR;
grub_fshelp_node_t currnode = currroot; grub_fshelp_node_t currnode = currroot;
grub_fshelp_node_t oldnode = currroot; grub_fshelp_node_t oldnode = currroot;

View file

@ -244,22 +244,24 @@ static grub_ssize_t
grub_hfs_read_file (struct grub_hfs_data *data, grub_hfs_read_file (struct grub_hfs_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length), unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf) grub_off_t pos, grub_size_t len, char *buf)
{ {
int i; grub_off_t i;
int blockcnt; grub_off_t blockcnt;
blockcnt = ((len + pos) blockcnt = grub_divmod64 (((len + pos)
+ data->blksz - 1) / data->blksz; + data->blksz - 1), data->blksz, 0);
for (i = pos / data->blksz; i < blockcnt; i++) for (i = grub_divmod64 (pos, data->blksz, 0); i < blockcnt; i++)
{ {
int blknr; grub_disk_addr_t blknr;
int blockoff = pos % data->blksz; grub_off_t blockoff;
int blockend = data->blksz; grub_off_t blockend = data->blksz;
int skipfirst = 0; int skipfirst = 0;
grub_divmod64 (pos, data->blksz, &blockoff);
blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1); blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1);
if (grub_errno) if (grub_errno)
return -1; return -1;
@ -267,7 +269,7 @@ grub_hfs_read_file (struct grub_hfs_data *data,
/* Last block. */ /* Last block. */
if (i == blockcnt - 1) if (i == blockcnt - 1)
{ {
blockend = (len + pos) % data->blksz; grub_divmod64 ((len + pos), data->blksz, &blockend);
/* The last portion is exactly EXT2_BLOCK_SIZE (data). */ /* The last portion is exactly EXT2_BLOCK_SIZE (data). */
if (! blockend) if (! blockend)
@ -275,7 +277,7 @@ grub_hfs_read_file (struct grub_hfs_data *data,
} }
/* First block. */ /* First block. */
if (i == pos / data->blksz) if (i == grub_divmod64 (pos, data->blksz, 0))
{ {
skipfirst = blockoff; skipfirst = blockoff;
blockend -= skipfirst; blockend -= skipfirst;
@ -748,10 +750,7 @@ grub_hfs_find_node (struct grub_hfs_data *data, char *key,
entry. In case of a non-leaf mode it will be used to lookup entry. In case of a non-leaf mode it will be used to lookup
the rest of the tree. */ the rest of the tree. */
if (cmp <= 0) if (cmp <= 0)
{ found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data));
grub_uint32_t *node = (grub_uint32_t *) rec->data;
found = grub_be_to_cpu32 (*node);
}
else /* The key can not be found in the tree. */ else /* The key can not be found in the tree. */
return 1; return 1;
@ -815,7 +814,7 @@ grub_hfs_iterate_dir (struct grub_hfs_data *data, grub_uint32_t root_idx,
struct grub_hfs_catalog_key *ckey = rec->key; struct grub_hfs_catalog_key *ckey = rec->key;
if (grub_hfs_cmp_catkeys (rec->key, (void *) &key) <= 0) if (grub_hfs_cmp_catkeys (rec->key, (void *) &key) <= 0)
found = grub_be_to_cpu32 (*(grub_uint32_t *) rec->data); found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data));
if (hnd->type == 0xFF && ckey->strlen > 0) if (hnd->type == 0xFF && ckey->strlen > 0)
{ {

View file

@ -181,7 +181,8 @@ enum grub_hfsplus_filetype
struct grub_hfsplus_catkey_internal struct grub_hfsplus_catkey_internal
{ {
grub_uint32_t parent; grub_uint32_t parent;
char *name; const grub_uint16_t *name;
grub_size_t namelen;
}; };
/* Internal representation of an extent overflow key. */ /* Internal representation of an extent overflow key. */
@ -214,7 +215,7 @@ struct grub_fshelp_node
struct grub_hfsplus_btree struct grub_hfsplus_btree
{ {
grub_uint32_t root; grub_uint32_t root;
int nodesize; grub_size_t nodesize;
/* Catalog file node. */ /* Catalog file node. */
struct grub_fshelp_node file; struct grub_fshelp_node file;
@ -236,7 +237,7 @@ struct grub_hfsplus_data
/* This is the offset into the physical disk for an embedded HFS+ /* This is the offset into the physical disk for an embedded HFS+
filesystem (one inside a plain HFS wrapper). */ filesystem (one inside a plain HFS wrapper). */
int embedded_offset; grub_disk_addr_t embedded_offset;
int case_sensitive; int case_sensitive;
}; };
@ -245,15 +246,14 @@ static grub_dl_t my_mod;
/* Return the offset of the record with the index INDEX, in the node /* Return the offset of the record with the index INDEX, in the node
NODE which is part of the B+ tree BTREE. */ NODE which is part of the B+ tree BTREE. */
static inline unsigned int static inline grub_off_t
grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree, grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree,
struct grub_hfsplus_btnode *node, int index) struct grub_hfsplus_btnode *node, int index)
{ {
char *cnode = (char *) node; char *cnode = (char *) node;
grub_uint16_t *recptr; void *recptr;
recptr = (grub_uint16_t *) (&cnode[btree->nodesize recptr = (&cnode[btree->nodesize - index * sizeof (grub_uint16_t) - 2]);
- index * sizeof (grub_uint16_t) - 2]); return grub_be_to_cpu16 (grub_get_unaligned16 (recptr));
return grub_be_to_cpu16 (*recptr);
} }
/* Return a pointer to the record with the index INDEX, in the node /* Return a pointer to the record with the index INDEX, in the node
@ -263,7 +263,7 @@ grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree,
struct grub_hfsplus_btnode *node, int index) struct grub_hfsplus_btnode *node, int index)
{ {
char *cnode = (char *) node; char *cnode = (char *) node;
unsigned int offset; grub_off_t offset;
offset = grub_hfsplus_btree_recoffset (btree, node, index); offset = grub_hfsplus_btree_recoffset (btree, node, index);
return (struct grub_hfsplus_key *) &cnode[offset]; return (struct grub_hfsplus_key *) &cnode[offset];
} }
@ -272,12 +272,12 @@ grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree,
/* Find the extent that points to FILEBLOCK. If it is not in one of /* Find the extent that points to FILEBLOCK. If it is not in one of
the 8 extents described by EXTENT, return -1. In that case set the 8 extents described by EXTENT, return -1. In that case set
FILEBLOCK to the next block. */ FILEBLOCK to the next block. */
static int static grub_disk_addr_t
grub_hfsplus_find_block (struct grub_hfsplus_extent *extent, grub_hfsplus_find_block (struct grub_hfsplus_extent *extent,
int *fileblock) grub_disk_addr_t *fileblock)
{ {
int i; int i;
grub_size_t blksleft = *fileblock; grub_disk_addr_t blksleft = *fileblock;
/* First lookup the file in the given extents. */ /* First lookup the file in the given extents. */
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
@ -288,7 +288,7 @@ grub_hfsplus_find_block (struct grub_hfsplus_extent *extent,
} }
*fileblock = blksleft; *fileblock = blksleft;
return -1; return 0xffffffffffffffffULL;
} }
static grub_err_t static grub_err_t
@ -296,7 +296,8 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
struct grub_hfsplus_key_internal *key, struct grub_hfsplus_key_internal *key,
int (*compare_keys) (struct grub_hfsplus_key *keya, int (*compare_keys) (struct grub_hfsplus_key *keya,
struct grub_hfsplus_key_internal *keyb), struct grub_hfsplus_key_internal *keyb),
struct grub_hfsplus_btnode **matchnode, int *keyoffset); struct grub_hfsplus_btnode **matchnode,
grub_off_t *keyoffset);
static int grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya, static int grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya,
struct grub_hfsplus_key_internal *keyb); struct grub_hfsplus_key_internal *keyb);
@ -307,15 +308,15 @@ static grub_disk_addr_t
grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
{ {
struct grub_hfsplus_btnode *nnode = 0; struct grub_hfsplus_btnode *nnode = 0;
int blksleft = fileblock; grub_disk_addr_t blksleft = fileblock;
struct grub_hfsplus_extent *extents = &node->extents[0]; struct grub_hfsplus_extent *extents = &node->extents[0];
while (1) while (1)
{ {
struct grub_hfsplus_extkey *key; struct grub_hfsplus_extkey *key;
struct grub_hfsplus_extkey_internal extoverflow; struct grub_hfsplus_key_internal extoverflow;
int blk; grub_disk_addr_t blk;
int ptr; grub_off_t ptr;
/* Try to find this block in the current set of extents. */ /* Try to find this block in the current set of extents. */
blk = grub_hfsplus_find_block (extents, &blksleft); blk = grub_hfsplus_find_block (extents, &blksleft);
@ -325,7 +326,7 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
grub_free (nnode); grub_free (nnode);
nnode = 0; nnode = 0;
if (blk != -1) if (blk != 0xffffffffffffffffULL)
return (blk return (blk
+ (node->data->embedded_offset >> (node->data->log2blksize + (node->data->embedded_offset >> (node->data->log2blksize
- GRUB_DISK_SECTOR_BITS))); - GRUB_DISK_SECTOR_BITS)));
@ -341,11 +342,11 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
} }
/* Set up the key to look for in the extent overflow file. */ /* Set up the key to look for in the extent overflow file. */
extoverflow.fileid = node->fileid; extoverflow.extkey.fileid = node->fileid;
extoverflow.start = fileblock - blksleft; extoverflow.extkey.start = fileblock - blksleft;
if (grub_hfsplus_btree_search (&node->data->extoverflow_tree, if (grub_hfsplus_btree_search (&node->data->extoverflow_tree,
(struct grub_hfsplus_key_internal *) &extoverflow, &extoverflow,
grub_hfsplus_cmp_extkey, &nnode, &ptr)) grub_hfsplus_cmp_extkey, &nnode, &ptr))
{ {
grub_error (GRUB_ERR_READ_ERROR, grub_error (GRUB_ERR_READ_ERROR,
@ -376,7 +377,7 @@ static grub_ssize_t
grub_hfsplus_read_file (grub_fshelp_node_t node, grub_hfsplus_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length), unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf) grub_off_t pos, grub_size_t len, char *buf)
{ {
return grub_fshelp_read_file (node->data->disk, node, read_hook, return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_hfsplus_read_block, pos, len, buf, grub_hfsplus_read_block,
@ -411,9 +412,9 @@ grub_hfsplus_mount (grub_disk_t disk)
data->embedded_offset = 0; data->embedded_offset = 0;
if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC) if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC)
{ {
int extent_start; grub_disk_addr_t extent_start;
int ablk_size; grub_disk_addr_t ablk_size;
int ablk_start; grub_disk_addr_t ablk_start;
/* See if there's an embedded HFS+ filesystem. */ /* See if there's an embedded HFS+ filesystem. */
if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC) if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC)
@ -518,8 +519,6 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya,
{ {
struct grub_hfsplus_catkey *catkey_a = &keya->catkey; struct grub_hfsplus_catkey *catkey_a = &keya->catkey;
struct grub_hfsplus_catkey_internal *catkey_b = &keyb->catkey; struct grub_hfsplus_catkey_internal *catkey_b = &keyb->catkey;
char *filename;
int i;
int diff; int diff;
/* Safe unsigned comparison */ /* Safe unsigned comparison */
@ -529,29 +528,35 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya,
if (aparent < catkey_b->parent) if (aparent < catkey_b->parent)
return -1; return -1;
/* Change the filename in keya so the endianness is correct. */ diff = grub_memcmp (catkey_a->name, catkey_b->name,
for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++) grub_min (grub_be_to_cpu16 (catkey_a->namelen),
catkey_a->name[i] = grub_be_to_cpu16 (catkey_a->name[i]); catkey_b->namelen)
* sizeof (catkey_a->name[0]));
if (diff == 0)
diff = grub_be_to_cpu16 (catkey_a->namelen) - catkey_b->namelen;
filename = grub_malloc (grub_be_to_cpu16 (catkey_a->namelen) + 1);
if (! grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey_a->name,
grub_be_to_cpu16 (catkey_a->namelen)))
return -1; /* XXX: This error never occurs, but in case it happens
just skip this entry. */
diff = grub_strncmp (filename, catkey_b->name,
grub_be_to_cpu16 (catkey_a->namelen));
grub_free (filename);
/* The endianness was changed to host format, change it back to
whatever it was. */
for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++)
catkey_a->name[i] = grub_cpu_to_be16 (catkey_a->name[i]);
return diff; return diff;
} }
/* Compare the on disk catalog key KEYA with the catalog key we are
looking for (KEYB). */
static int
grub_hfsplus_cmp_catkey_id (struct grub_hfsplus_key *keya,
struct grub_hfsplus_key_internal *keyb)
{
struct grub_hfsplus_catkey *catkey_a = &keya->catkey;
struct grub_hfsplus_catkey_internal *catkey_b = &keyb->catkey;
/* Safe unsigned comparison */
grub_uint32_t aparent = grub_be_to_cpu32 (catkey_a->parent);
if (aparent > catkey_b->parent)
return 1;
if (aparent < catkey_b->parent)
return -1;
return 0;
}
/* Compare the on disk extent overflow key KEYA with the extent /* Compare the on disk extent overflow key KEYA with the extent
overflow key we are looking for (KEYB). */ overflow key we are looking for (KEYB). */
static int static int
@ -601,10 +606,10 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node)
static int static int
grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree, grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree,
struct grub_hfsplus_btnode *first_node, struct grub_hfsplus_btnode *first_node,
int first_rec, grub_disk_addr_t first_rec,
int (*hook) (void *record)) int (*hook) (void *record))
{ {
int rec; grub_disk_addr_t rec;
for (;;) for (;;)
{ {
@ -642,12 +647,13 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
struct grub_hfsplus_key_internal *key, struct grub_hfsplus_key_internal *key,
int (*compare_keys) (struct grub_hfsplus_key *keya, int (*compare_keys) (struct grub_hfsplus_key *keya,
struct grub_hfsplus_key_internal *keyb), struct grub_hfsplus_key_internal *keyb),
struct grub_hfsplus_btnode **matchnode, int *keyoffset) struct grub_hfsplus_btnode **matchnode,
grub_off_t *keyoffset)
{ {
grub_uint64_t currnode; grub_uint64_t currnode;
char *node; char *node;
struct grub_hfsplus_btnode *nodedesc; struct grub_hfsplus_btnode *nodedesc;
int rec; grub_disk_addr_t rec;
node = grub_malloc (btree->nodesize); node = grub_malloc (btree->nodesize);
if (! node) if (! node)
@ -660,7 +666,8 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
/* Read a node. */ /* Read a node. */
if (grub_hfsplus_read_file (&btree->file, 0, if (grub_hfsplus_read_file (&btree->file, 0,
(long)currnode * (long)btree->nodesize, (grub_disk_addr_t) currnode
* (grub_disk_addr_t) btree->nodesize,
btree->nodesize, (char *) node) <= 0) btree->nodesize, (char *) node) <= 0)
{ {
grub_free (node); grub_free (node);
@ -689,7 +696,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
} }
else if (nodedesc->type == GRUB_HFSPLUS_BTNODE_TYPE_INDEX) else if (nodedesc->type == GRUB_HFSPLUS_BTNODE_TYPE_INDEX)
{ {
grub_uint32_t *pointer; void *pointer;
/* The place where the key could have been found didn't /* The place where the key could have been found didn't
contain the key. This means that the previous match contain the key. This means that the previous match
@ -701,10 +708,10 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree,
that we are looking for. The last match that is that we are looking for. The last match that is
found will be used to locate the child which can found will be used to locate the child which can
contain the record. */ contain the record. */
pointer = (grub_uint32_t *) ((char *) currkey pointer = ((char *) currkey
+ grub_be_to_cpu16 (currkey->keylen) + grub_be_to_cpu16 (currkey->keylen)
+ 2); + 2);
currnode = grub_be_to_cpu32 (*pointer); currnode = grub_be_to_cpu32 (grub_get_unaligned32 (pointer));
match = 1; match = 1;
} }
} }
@ -770,6 +777,11 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
if (type == GRUB_FSHELP_UNKNOWN) if (type == GRUB_FSHELP_UNKNOWN)
return 0; return 0;
filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen)
* GRUB_MAX_UTF8_PER_UTF16 + 1);
if (! filename)
return 0;
/* Make sure the byte order of the UTF16 string is correct. */ /* Make sure the byte order of the UTF16 string is correct. */
for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++)
{ {
@ -780,18 +792,8 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
return 0; return 0;
} }
filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen) + 1); *grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name,
if (! filename) grub_be_to_cpu16 (catkey->namelen)) = '\0';
return 0;
if (! grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name,
grub_be_to_cpu16 (catkey->namelen)))
{
grub_free (filename);
return 0;
}
filename[grub_be_to_cpu16 (catkey->namelen)] = '\0';
/* Restore the byte order to what it was previously. */ /* Restore the byte order to what it was previously. */
for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++)
@ -801,22 +803,18 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
if (! dir->data->case_sensitive) if (! dir->data->case_sensitive)
type |= GRUB_FSHELP_CASE_INSENSITIVE; type |= GRUB_FSHELP_CASE_INSENSITIVE;
/* Only accept valid nodes. */ /* A valid node is found; setup the node and call the
if (grub_strlen (filename) == grub_be_to_cpu16 (catkey->namelen)) callback function. */
{ node = grub_malloc (sizeof (*node));
/* A valid node is found; setup the node and call the node->data = dir->data;
callback function. */
node = grub_malloc (sizeof (*node));
node->data = dir->data;
grub_memcpy (node->extents, fileinfo->data.extents, grub_memcpy (node->extents, fileinfo->data.extents,
sizeof (node->extents)); sizeof (node->extents));
node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800; node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800;
node->size = grub_be_to_cpu64 (fileinfo->data.size); node->size = grub_be_to_cpu64 (fileinfo->data.size);
node->fileid = grub_be_to_cpu32 (fileinfo->fileid); node->fileid = grub_be_to_cpu32 (fileinfo->fileid);
ret = hook (filename, type, node); ret = hook (filename, type, node);
}
grub_free (filename); grub_free (filename);
@ -825,11 +823,12 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir,
struct grub_hfsplus_key_internal intern; struct grub_hfsplus_key_internal intern;
struct grub_hfsplus_btnode *node; struct grub_hfsplus_btnode *node;
int ptr; grub_disk_addr_t ptr;
/* Create a key that points to the first entry in the directory. */ /* Create a key that points to the first entry in the directory. */
intern.catkey.parent = dir->fileid; intern.catkey.parent = dir->fileid;
intern.catkey.name = ""; intern.catkey.name = 0;
intern.catkey.namelen = 0;
/* First lookup the first entry. */ /* First lookup the first entry. */
if (grub_hfsplus_btree_search (&dir->data->catalog_tree, &intern, if (grub_hfsplus_btree_search (&dir->data->catalog_tree, &intern,
@ -894,7 +893,6 @@ grub_hfsplus_close (grub_file_t file)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
/* Read LEN bytes data from FILE into BUF. */ /* Read LEN bytes data from FILE into BUF. */
static grub_ssize_t static grub_ssize_t
grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len) grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
@ -902,13 +900,10 @@ grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len)
struct grub_hfsplus_data *data = struct grub_hfsplus_data *data =
(struct grub_hfsplus_data *) file->data; (struct grub_hfsplus_data *) file->data;
int size = grub_hfsplus_read_file (&data->opened_file, file->read_hook, return grub_hfsplus_read_file (&data->opened_file, file->read_hook,
file->offset, len, buf); file->offset, len, buf);
return size;
} }
static grub_err_t static grub_err_t
grub_hfsplus_dir (grub_device_t device, const char *path, grub_hfsplus_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename, int (*hook) (const char *filename,
@ -963,13 +958,59 @@ grub_hfsplus_dir (grub_device_t device, const char *path,
static grub_err_t static grub_err_t
grub_hfsplus_label (grub_device_t device __attribute__((unused)) grub_hfsplus_label (grub_device_t device, char **label)
, char **label __attribute__((unused)))
{ {
/* XXX: It's not documented how to read a label. */ struct grub_hfsplus_data *data;
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, grub_disk_t disk = device->disk;
"reading the label of a HFS+ " struct grub_hfsplus_catkey *catkey;
"partition is not implemented"); int i, label_len;
struct grub_hfsplus_key_internal intern;
struct grub_hfsplus_btnode *node;
grub_disk_addr_t ptr;
*label = 0;
data = grub_hfsplus_mount (disk);
if (!data)
return grub_errno;
/* Create a key that points to the label. */
intern.catkey.parent = 1;
intern.catkey.name = 0;
intern.catkey.namelen = 0;
/* First lookup the first entry. */
if (grub_hfsplus_btree_search (&data->catalog_tree, &intern,
grub_hfsplus_cmp_catkey_id, &node, &ptr))
{
grub_free (data);
return 0;
}
catkey = (struct grub_hfsplus_catkey *)
grub_hfsplus_btree_recptr (&data->catalog_tree, node, 0);
label_len = grub_be_to_cpu16 (catkey->namelen);
for (i = 0; i < label_len; i++)
{
catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]);
/* If the name is obviously invalid, skip this node. */
if (catkey->name[i] == 0)
return 0;
}
*label = grub_malloc (label_len * GRUB_MAX_UTF8_PER_UTF16 + 1);
if (! *label)
return grub_errno;
*grub_utf16_to_utf8 ((grub_uint8_t *) (*label), catkey->name,
label_len) = '\0';
grub_free (node);
grub_free (data);
return GRUB_ERR_NONE;
} }
/* Get mtime. */ /* Get mtime. */

View file

@ -149,22 +149,29 @@ struct grub_iso9660_data
{ {
struct grub_iso9660_primary_voldesc voldesc; struct grub_iso9660_primary_voldesc voldesc;
grub_disk_t disk; grub_disk_t disk;
unsigned int first_sector;
int rockridge; int rockridge;
int susp_skip; int susp_skip;
int joliet; int joliet;
struct grub_fshelp_node *node;
}; };
struct grub_fshelp_node struct grub_fshelp_node
{ {
struct grub_iso9660_data *data; struct grub_iso9660_data *data;
struct grub_iso9660_dir dirent; grub_size_t have_dirents, alloc_dirents;
unsigned int size; int have_symlink;
unsigned int blk; struct grub_iso9660_dir dirents[8];
unsigned int dir_blk; char symlink[0];
unsigned int dir_off;
}; };
enum
{
FLAG_TYPE_PLAIN = 0,
FLAG_TYPE_DIR = 2,
FLAG_TYPE = 3,
FLAG_MORE_EXTENTS = 0x80
};
static grub_dl_t my_mod; static grub_dl_t my_mod;
@ -214,35 +221,77 @@ iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix)
return 1; return 1;
} }
static grub_err_t
read_node (grub_fshelp_node_t node, grub_off_t off, grub_size_t len, char *buf)
{
grub_size_t i = 0;
while (len > 0)
{
grub_size_t toread;
grub_err_t err;
while (i < node->have_dirents
&& off >= grub_le_to_cpu32 (node->dirents[i].size))
{
off -= grub_le_to_cpu32 (node->dirents[i].size);
i++;
}
if (i == node->have_dirents)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "read out of range");
toread = grub_le_to_cpu32 (node->dirents[i].size);
if (toread > len)
toread = len;
err = grub_disk_read (node->data->disk,
((grub_disk_addr_t) grub_le_to_cpu32 (node->dirents[i].first_sector)) << GRUB_ISO9660_LOG2_BLKSZ,
off, toread, buf);
if (err)
return err;
len -= toread;
off += toread;
buf += toread;
}
return GRUB_ERR_NONE;
}
/* Iterate over the susp entries, starting with block SUA_BLOCK on the /* Iterate over the susp entries, starting with block SUA_BLOCK on the
offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for offset SUA_POS with a size of SUA_SIZE bytes. Hook is called for
every entry. */ every entry. */
static grub_err_t static grub_err_t
grub_iso9660_susp_iterate (struct grub_iso9660_data *data, grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off,
int sua_block, int sua_pos, int sua_size, grub_ssize_t sua_size,
grub_err_t (*hook) grub_err_t (*hook)
(struct grub_iso9660_susp_entry *entry)) (struct grub_iso9660_susp_entry *entry))
{ {
char *sua; char *sua;
struct grub_iso9660_susp_entry *entry; struct grub_iso9660_susp_entry *entry;
grub_disk_addr_t ce_block;
int is_ce = 0;
auto grub_err_t load_sua (void); auto grub_err_t load_sua (void);
/* Load a part of the System Usage Area. */ /* Load a part of the System Usage Area. */
grub_err_t load_sua (void) grub_err_t load_sua (void)
{ {
grub_err_t err;
sua = grub_malloc (sua_size); sua = grub_malloc (sua_size);
if (!sua) if (!sua)
return grub_errno; return grub_errno;
if (grub_disk_read (data->disk, sua_block, sua_pos, if (is_ce)
sua_size, sua)) err = grub_disk_read (node->data->disk, ce_block, off,
return grub_errno; sua_size, sua);
else
err = read_node (node, off, sua_size, sua);
if (err)
return err;
entry = (struct grub_iso9660_susp_entry *) sua; entry = (struct grub_iso9660_susp_entry *) sua;
return 0; return 0;
} }
if (sua_size <= 0)
return GRUB_ERR_NONE;
if (load_sua ()) if (load_sua ())
return grub_errno; return grub_errno;
@ -259,10 +308,11 @@ grub_iso9660_susp_iterate (struct grub_iso9660_data *data,
{ {
struct grub_iso9660_susp_ce *ce; struct grub_iso9660_susp_ce *ce;
is_ce = 1;
ce = (struct grub_iso9660_susp_ce *) entry; ce = (struct grub_iso9660_susp_ce *) entry;
sua_size = grub_le_to_cpu32 (ce->len); sua_size = grub_le_to_cpu32 (ce->len);
sua_pos = grub_le_to_cpu32 (ce->off); off = grub_le_to_cpu32 (ce->off);
sua_block = grub_le_to_cpu32 (ce->blk) << GRUB_ISO9660_LOG2_BLKSZ; ce_block = grub_le_to_cpu32 (ce->blk) << GRUB_ISO9660_LOG2_BLKSZ;
grub_free (sua); grub_free (sua);
if (load_sua ()) if (load_sua ())
@ -281,34 +331,32 @@ grub_iso9660_susp_iterate (struct grub_iso9660_data *data,
} }
static char * static char *
grub_iso9660_convert_string (grub_uint16_t *us, int len) grub_iso9660_convert_string (grub_uint8_t *us, int len)
{ {
char *p; char *p;
int i; int i;
grub_uint16_t t[len];
p = grub_malloc (len * 4 + 1); p = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1);
if (! p) if (! p)
return p; return p;
for (i=0; i<len; i++) for (i=0; i<len; i++)
us[i] = grub_be_to_cpu16 (us[i]); t[i] = grub_be_to_cpu16 (grub_get_unaligned16 (us + 2 * i));
*grub_utf16_to_utf8 ((grub_uint8_t *) p, us, len) = '\0'; *grub_utf16_to_utf8 ((grub_uint8_t *) p, t, len) = '\0';
return p; return p;
} }
static struct grub_iso9660_data * static grub_err_t
grub_iso9660_mount (grub_disk_t disk) set_rockridge (struct grub_iso9660_data *data)
{ {
struct grub_iso9660_data *data = 0;
struct grub_iso9660_dir rootdir;
int sua_pos; int sua_pos;
int sua_size; int sua_size;
char *sua; char *sua;
struct grub_iso9660_dir rootdir;
struct grub_iso9660_susp_entry *entry; struct grub_iso9660_susp_entry *entry;
struct grub_iso9660_primary_voldesc voldesc;
int block;
auto grub_err_t susp_iterate (struct grub_iso9660_susp_entry *); auto grub_err_t susp_iterate (struct grub_iso9660_susp_entry *);
@ -324,6 +372,74 @@ grub_iso9660_mount (grub_disk_t disk)
return 0; return 0;
} }
data->rockridge = 0;
/* Read the system use area and test it to see if SUSP is
supported. */
if (grub_disk_read (data->disk,
(grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ), 0,
sizeof (rootdir), (char *) &rootdir))
return grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
sua_pos = (sizeof (rootdir) + rootdir.namelen
+ (rootdir.namelen % 2) - 1);
sua_size = rootdir.len - sua_pos;
if (!sua_size)
return GRUB_ERR_NONE;
sua = grub_malloc (sua_size);
if (! sua)
return grub_errno;
if (grub_disk_read (data->disk,
(grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ), sua_pos,
sua_size, sua))
{
grub_free (sua);
return grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
}
entry = (struct grub_iso9660_susp_entry *) sua;
/* Test if the SUSP protocol is used on this filesystem. */
if (grub_strncmp ((char *) entry->sig, "SP", 2) == 0)
{
struct grub_fshelp_node rootnode;
rootnode.data = data;
rootnode.alloc_dirents = ARRAY_SIZE (rootnode.dirents);
rootnode.have_dirents = 1;
rootnode.have_symlink = 0;
rootnode.dirents[0] = data->voldesc.rootdir;
/* The 2nd data byte stored how many bytes are skipped every time
to get to the SUA (System Usage Area). */
data->susp_skip = entry->data[2];
entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len);
/* Iterate over the entries in the SUA area to detect
extensions. */
if (grub_iso9660_susp_iterate (&rootnode,
sua_pos, sua_size, susp_iterate))
{
grub_free (sua);
return grub_errno;
}
}
grub_free (sua);
return GRUB_ERR_NONE;
}
static struct grub_iso9660_data *
grub_iso9660_mount (grub_disk_t disk)
{
struct grub_iso9660_data *data = 0;
struct grub_iso9660_primary_voldesc voldesc;
int block;
data = grub_zalloc (sizeof (struct grub_iso9660_data)); data = grub_zalloc (sizeof (struct grub_iso9660_data));
if (! data) if (! data)
return 0; return 0;
@ -351,9 +467,11 @@ grub_iso9660_mount (grub_disk_t disk)
} }
if (voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_PRIMARY) if (voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_PRIMARY)
copy_voldesc = 1; copy_voldesc = 1;
else if ((voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_SUPP) && else if (!data->rockridge
(voldesc.escape[0] == 0x25) && (voldesc.escape[1] == 0x2f) && && (voldesc.voldesc.type == GRUB_ISO9660_VOLDESC_SUPP)
&& (voldesc.escape[0] == 0x25) && (voldesc.escape[1] == 0x2f)
&&
((voldesc.escape[2] == 0x40) || /* UCS-2 Level 1. */ ((voldesc.escape[2] == 0x40) || /* UCS-2 Level 1. */
(voldesc.escape[2] == 0x43) || /* UCS-2 Level 2. */ (voldesc.escape[2] == 0x43) || /* UCS-2 Level 2. */
(voldesc.escape[2] == 0x45))) /* UCS-2 Level 3. */ (voldesc.escape[2] == 0x45))) /* UCS-2 Level 3. */
@ -363,57 +481,16 @@ grub_iso9660_mount (grub_disk_t disk)
} }
if (copy_voldesc) if (copy_voldesc)
grub_memcpy((char *) &data->voldesc, (char *) &voldesc, {
sizeof (struct grub_iso9660_primary_voldesc)); grub_memcpy((char *) &data->voldesc, (char *) &voldesc,
sizeof (struct grub_iso9660_primary_voldesc));
if (set_rockridge (data))
goto fail;
}
block++; block++;
} while (voldesc.voldesc.type != GRUB_ISO9660_VOLDESC_END); } while (voldesc.voldesc.type != GRUB_ISO9660_VOLDESC_END);
/* Read the system use area and test it to see if SUSP is
supported. */
if (grub_disk_read (disk, (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ), 0,
sizeof (rootdir), (char *) &rootdir))
{
grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
goto fail;
}
sua_pos = (sizeof (rootdir) + rootdir.namelen
+ (rootdir.namelen % 2) - 1);
sua_size = rootdir.len - sua_pos;
sua = grub_malloc (sua_size);
if (! sua)
goto fail;
if (grub_disk_read (disk, (grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ), sua_pos,
sua_size, sua))
{
grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem");
goto fail;
}
entry = (struct grub_iso9660_susp_entry *) sua;
/* Test if the SUSP protocol is used on this filesystem. */
if (grub_strncmp ((char *) entry->sig, "SP", 2) == 0)
{
/* The 2nd data byte stored how many bytes are skipped every time
to get to the SUA (System Usage Area). */
data->susp_skip = entry->data[2];
entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len);
/* Iterate over the entries in the SUA area to detect
extensions. */
if (grub_iso9660_susp_iterate (data,
(grub_le_to_cpu32 (data->voldesc.rootdir.first_sector)
<< GRUB_ISO9660_LOG2_BLKSZ),
sua_pos, sua_size, susp_iterate))
goto fail;
}
return data; return data;
fail: fail:
@ -425,42 +502,125 @@ grub_iso9660_mount (grub_disk_t disk)
static char * static char *
grub_iso9660_read_symlink (grub_fshelp_node_t node) grub_iso9660_read_symlink (grub_fshelp_node_t node)
{ {
int sua_off; return node->have_symlink
int sua_size; ? grub_strdup (node->symlink
char *symlink = 0; + (node->have_dirents) * sizeof (node->dirents[0])
int addslash = 0; - sizeof (node->dirents)) : grub_strdup ("");
}
auto void add_part (const char *part, int len); static grub_off_t
auto grub_err_t susp_iterate_sl (struct grub_iso9660_susp_entry *); get_node_size (grub_fshelp_node_t node)
{
grub_off_t ret = 0;
grub_size_t i;
for (i = 0; i < node->have_dirents; i++)
ret += grub_le_to_cpu32 (node->dirents[i].size);
return ret;
}
static int
grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
struct grub_iso9660_dir dirent;
grub_off_t offset = 0;
char *filename = 0;
int filename_alloc = 0;
enum grub_fshelp_filetype type;
grub_off_t len;
char *symlink = 0;
/* Extend the symlink. */ /* Extend the symlink. */
void add_part (const char *part, int len) auto inline void __attribute__ ((always_inline)) add_part (const char *part,
{ int len2);
int size = grub_strlen (symlink);
symlink = grub_realloc (symlink, size + len + 1); auto inline void __attribute__ ((always_inline)) add_part (const char *part,
int len2)
{
int size = symlink ? grub_strlen (symlink) : 0;
symlink = grub_realloc (symlink, size + len2 + 1);
if (! symlink) if (! symlink)
return; return;
grub_strncat (symlink, part, len); symlink[size] = 0;
grub_strncat (symlink, part, len2);
} }
/* Read in a symlink. */ auto grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *);
grub_err_t susp_iterate_sl (struct grub_iso9660_susp_entry *entry)
grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *entry)
{ {
if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0) /* The filename in the rock ridge entry. */
if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0)
{
/* The flags are stored at the data position 0, here the
filename type is stored. */
if (entry->data[0] & GRUB_ISO9660_RR_DOT)
filename = ".";
else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT)
filename = "..";
else if (entry->len >= 5)
{
grub_size_t size = 1, csize = 1;
char *old;
csize = size = entry->len - 5;
old = filename;
if (filename_alloc)
{
size += grub_strlen (filename);
filename = grub_realloc (filename, size + 1);
}
else
{
filename_alloc = 1;
filename = grub_zalloc (size + 1);
filename[0] = 0;
}
if (!filename)
{
filename = old;
return grub_errno;
}
filename_alloc = 1;
grub_strncat (filename, (char *) &entry->data[1], csize);
filename[size] = '\0';
}
}
/* The mode information (st_mode). */
else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0)
{
/* At position 0 of the PX record the st_mode information is
stored (little-endian). */
grub_uint32_t mode = ((entry->data[0] + (entry->data[1] << 8))
& GRUB_ISO9660_FSTYPE_MASK);
switch (mode)
{
case GRUB_ISO9660_FSTYPE_DIR:
type = GRUB_FSHELP_DIR;
break;
case GRUB_ISO9660_FSTYPE_REG:
type = GRUB_FSHELP_REG;
break;
case GRUB_ISO9660_FSTYPE_SYMLINK:
type = GRUB_FSHELP_SYMLINK;
break;
default:
type = GRUB_FSHELP_UNKNOWN;
}
}
else if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0)
{ {
unsigned int pos = 1; unsigned int pos = 1;
/* The symlink is not stored as a POSIX symlink, translate it. */ /* The symlink is not stored as a POSIX symlink, translate it. */
while (pos < grub_le_to_cpu32 (entry->len)) while (pos + sizeof (*entry) < grub_le_to_cpu32 (entry->len))
{ {
if (addslash)
{
add_part ("/", 1);
addslash = 0;
}
/* The current position is the `Component Flag'. */ /* The current position is the `Component Flag'. */
switch (entry->data[pos] & 30) switch (entry->data[pos] & 30)
{ {
@ -469,10 +629,10 @@ grub_iso9660_read_symlink (grub_fshelp_node_t node)
/* The data on pos + 2 is the actual data, pos + 1 /* The data on pos + 2 is the actual data, pos + 1
is the length. Both are part of the `Component is the length. Both are part of the `Component
Record'. */ Record'. */
if (symlink && (entry->data[pos] & 1))
add_part ("/", 1);
add_part ((char *) &entry->data[pos + 2], add_part ((char *) &entry->data[pos + 2],
entry->data[pos + 1]); entry->data[pos + 1]);
if ((entry->data[pos] & 1))
addslash = 1;
break; break;
} }
@ -502,109 +662,13 @@ grub_iso9660_read_symlink (grub_fshelp_node_t node)
return 0; return 0;
} }
sua_off = (sizeof (node->dirent) + node->dirent.namelen + 1 len = get_node_size (dir);
- (node->dirent.namelen % 2)
+ node->data->susp_skip);
sua_size = node->dirent.len - sua_off;
symlink = grub_malloc (1); for (; offset < len; offset += dirent.len)
if (!symlink)
return 0;
*symlink = '\0';
if (grub_iso9660_susp_iterate (node->data, node->dir_blk,
node->dir_off + sua_off,
sua_size, susp_iterate_sl))
{ {
grub_free (symlink); symlink = 0;
return 0;
}
return symlink; if (read_node (dir, offset, sizeof (dirent), (char *) &dirent))
}
static int
grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR
(*hook) (const char *filename,
enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node))
{
struct grub_iso9660_dir dirent;
unsigned int offset = 0;
char *filename;
int filename_alloc = 0;
enum grub_fshelp_filetype type;
auto grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *);
grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *entry)
{
/* The filename in the rock ridge entry. */
if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0)
{
/* The flags are stored at the data position 0, here the
filename type is stored. */
if (entry->data[0] & GRUB_ISO9660_RR_DOT)
filename = ".";
else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT)
filename = "..";
else
{
int size = 1;
if (filename)
{
size += grub_strlen (filename);
grub_realloc (filename,
grub_strlen (filename)
+ entry->len);
}
else
{
size = entry->len - 5;
filename = grub_zalloc (size + 1);
}
filename_alloc = 1;
grub_strncpy (filename, (char *) &entry->data[1], size);
filename[size] = '\0';
}
}
/* The mode information (st_mode). */
else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0)
{
/* At position 0 of the PX record the st_mode information is
stored (little-endian). */
grub_uint32_t mode = ((entry->data[0] + (entry->data[1] << 8))
& GRUB_ISO9660_FSTYPE_MASK);
switch (mode)
{
case GRUB_ISO9660_FSTYPE_DIR:
type = GRUB_FSHELP_DIR;
break;
case GRUB_ISO9660_FSTYPE_REG:
type = GRUB_FSHELP_REG;
break;
case GRUB_ISO9660_FSTYPE_SYMLINK:
type = GRUB_FSHELP_SYMLINK;
break;
default:
type = GRUB_FSHELP_UNKNOWN;
}
}
return 0;
}
for (; offset < dir->size; offset += dirent.len)
{
if (grub_disk_read (dir->data->disk,
(dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+ offset / GRUB_DISK_SECTOR_SIZE,
offset % GRUB_DISK_SECTOR_SIZE,
sizeof (dirent), (char *) &dirent))
return 0; return 0;
/* The end of the block, skip to the next one. */ /* The end of the block, skip to the next one. */
@ -629,39 +693,30 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
type = GRUB_FSHELP_UNKNOWN; type = GRUB_FSHELP_UNKNOWN;
if (dir->data->rockridge if (dir->data->rockridge
&& grub_iso9660_susp_iterate (dir->data, && grub_iso9660_susp_iterate (dir, sua_off, sua_size,
(dir->blk << GRUB_ISO9660_LOG2_BLKSZ) susp_iterate_dir))
+ (sua_off
/ GRUB_DISK_SECTOR_SIZE),
sua_off % GRUB_DISK_SECTOR_SIZE,
sua_size, susp_iterate_dir))
return 0; return 0;
/* Read the name. */ /* Read the name. */
if (grub_disk_read (dir->data->disk, if (read_node (dir, nameoffset, dirent.namelen, (char *) name))
(dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+ nameoffset / GRUB_DISK_SECTOR_SIZE,
nameoffset % GRUB_DISK_SECTOR_SIZE,
dirent.namelen, (char *) name))
return 0; return 0;
node = grub_malloc (sizeof (struct grub_fshelp_node)); node = grub_malloc (sizeof (struct grub_fshelp_node));
if (!node) if (!node)
return 0; return 0;
node->alloc_dirents = ARRAY_SIZE (node->dirents);
node->have_dirents = 1;
/* Setup a new node. */ /* Setup a new node. */
node->data = dir->data; node->data = dir->data;
node->size = grub_le_to_cpu32 (dirent.size); node->have_symlink = 0;
node->blk = grub_le_to_cpu32 (dirent.first_sector);
node->dir_blk = ((dir->blk << GRUB_ISO9660_LOG2_BLKSZ)
+ offset / GRUB_DISK_SECTOR_SIZE);
node->dir_off = offset % GRUB_DISK_SECTOR_SIZE;
/* If the filetype was not stored using rockridge, use /* If the filetype was not stored using rockridge, use
whatever is stored in the iso9660 filesystem. */ whatever is stored in the iso9660 filesystem. */
if (type == GRUB_FSHELP_UNKNOWN) if (type == GRUB_FSHELP_UNKNOWN)
{ {
if ((dirent.flags & 3) == 2) if ((dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR)
type = GRUB_FSHELP_DIR; type = GRUB_FSHELP_DIR;
else else
type = GRUB_FSHELP_REG; type = GRUB_FSHELP_REG;
@ -678,7 +733,10 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
/* . and .. */ /* . and .. */
if (dirent.namelen == 1 && (name[0] == 0 || name[0] == 1)) if (dirent.namelen == 1 && (name[0] == 0 || name[0] == 1))
continue; {
grub_free (node);
continue;
}
else else
filename = name; filename = name;
} }
@ -689,7 +747,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
oldname = filename; oldname = filename;
filename = grub_iso9660_convert_string filename = grub_iso9660_convert_string
((grub_uint16_t *) oldname, dirent.namelen >> 1); ((grub_uint8_t *) oldname, dirent.namelen >> 1);
semicolon = grub_strrchr (filename, ';'); semicolon = grub_strrchr (filename, ';');
if (semicolon) if (semicolon)
@ -701,7 +759,64 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
filename_alloc = 1; filename_alloc = 1;
} }
node->dirent = dirent; node->dirents[0] = dirent;
while (dirent.flags & FLAG_MORE_EXTENTS)
{
offset += dirent.len;
if (read_node (dir, offset, sizeof (dirent), (char *) &dirent))
{
if (filename_alloc)
grub_free (filename);
grub_free (node);
return 0;
}
if (node->have_dirents >= node->alloc_dirents)
{
struct grub_fshelp_node *new_node;
node->alloc_dirents *= 2;
new_node = grub_realloc (node,
sizeof (struct grub_fshelp_node)
+ ((node->alloc_dirents
- ARRAY_SIZE (node->dirents))
* sizeof (node->dirents[0])));
if (!new_node)
{
if (filename_alloc)
grub_free (filename);
grub_free (node);
return 0;
}
node = new_node;
}
node->dirents[node->have_dirents++] = dirent;
}
if (symlink)
{
if ((node->alloc_dirents - node->have_dirents)
* sizeof (node->dirents[0]) < grub_strlen (symlink) + 1)
{
struct grub_fshelp_node *new_node;
new_node = grub_realloc (node,
sizeof (struct grub_fshelp_node)
+ ((node->alloc_dirents
- ARRAY_SIZE (node->dirents))
* sizeof (node->dirents[0]))
+ grub_strlen (symlink) + 1);
if (!new_node)
{
if (filename_alloc)
grub_free (filename);
grub_free (node);
return 0;
}
node = new_node;
}
node->have_symlink = 1;
grub_strcpy (node->symlink
+ node->have_dirents * sizeof (node->dirents[0])
- sizeof (node->dirents), symlink);
grub_free (symlink);
}
if (hook (filename, type, node)) if (hook (filename, type, node))
{ {
if (filename_alloc) if (filename_alloc)
@ -738,7 +853,7 @@ grub_iso9660_dir (grub_device_t device, const char *path,
struct grub_dirhook_info info; struct grub_dirhook_info info;
grub_memset (&info, 0, sizeof (info)); grub_memset (&info, 0, sizeof (info));
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = !!iso9660_to_unixtime2 (&node->dirent.mtime, &info.mtime); info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime);
grub_free (node); grub_free (node);
return hook (filename, &info); return hook (filename, &info);
@ -751,8 +866,10 @@ grub_iso9660_dir (grub_device_t device, const char *path,
goto fail; goto fail;
rootnode.data = data; rootnode.data = data;
rootnode.blk = grub_le_to_cpu32 (data->voldesc.rootdir.first_sector); rootnode.alloc_dirents = 0;
rootnode.size = grub_le_to_cpu32 (data->voldesc.rootdir.size); rootnode.have_dirents = 1;
rootnode.have_symlink = 0;
rootnode.dirents[0] = data->voldesc.rootdir;
/* Use the fshelp function to traverse the path. */ /* Use the fshelp function to traverse the path. */
if (grub_fshelp_find_file (path, &rootnode, if (grub_fshelp_find_file (path, &rootnode,
@ -792,8 +909,10 @@ grub_iso9660_open (struct grub_file *file, const char *name)
goto fail; goto fail;
rootnode.data = data; rootnode.data = data;
rootnode.blk = grub_le_to_cpu32 (data->voldesc.rootdir.first_sector); rootnode.alloc_dirents = 0;
rootnode.size = grub_le_to_cpu32 (data->voldesc.rootdir.size); rootnode.have_dirents = 1;
rootnode.have_symlink = 0;
rootnode.dirents[0] = data->voldesc.rootdir;
/* Use the fshelp function to traverse the path. */ /* Use the fshelp function to traverse the path. */
if (grub_fshelp_find_file (name, &rootnode, if (grub_fshelp_find_file (name, &rootnode,
@ -803,10 +922,9 @@ grub_iso9660_open (struct grub_file *file, const char *name)
GRUB_FSHELP_REG)) GRUB_FSHELP_REG))
goto fail; goto fail;
data->first_sector = foundnode->blk; data->node = foundnode;
file->data = data; file->data = data;
file->size = foundnode->size; file->size = get_node_size (foundnode);
file->offset = 0; file->offset = 0;
return 0; return 0;
@ -828,10 +946,7 @@ grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len)
/* XXX: The file is stored in as a single extent. */ /* XXX: The file is stored in as a single extent. */
data->disk->read_hook = file->read_hook; data->disk->read_hook = file->read_hook;
grub_disk_read (data->disk, read_node (data->node, file->offset, len, buf);
data->first_sector << GRUB_ISO9660_LOG2_BLKSZ,
file->offset,
len, buf);
data->disk->read_hook = NULL; data->disk->read_hook = NULL;
if (grub_errno) if (grub_errno)
@ -844,7 +959,10 @@ grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len)
static grub_err_t static grub_err_t
grub_iso9660_close (grub_file_t file) grub_iso9660_close (grub_file_t file)
{ {
grub_free (file->data); struct grub_iso9660_data *data =
(struct grub_iso9660_data *) file->data;
grub_free (data->node);
grub_free (data);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -861,8 +979,7 @@ grub_iso9660_label (grub_device_t device, char **label)
if (data) if (data)
{ {
if (data->joliet) if (data->joliet)
*label = grub_iso9660_convert_string *label = grub_iso9660_convert_string (data->voldesc.volname, 16);
((grub_uint16_t *) &data->voldesc.volname, 16);
else else
*label = grub_strndup ((char *) data->voldesc.volname, 32); *label = grub_strndup ((char *) data->voldesc.volname, 32);
if (*label) if (*label)

View file

@ -52,9 +52,9 @@ struct grub_jfs_sblock
grub_uint32_t blksz; grub_uint32_t blksz;
grub_uint16_t log2_blksz; grub_uint16_t log2_blksz;
grub_uint8_t unused[71]; grub_uint8_t unused[79];
grub_uint8_t volname[11]; grub_uint8_t volname[11];
grub_uint8_t unused2[32]; grub_uint8_t unused2[24];
grub_uint8_t uuid[16]; grub_uint8_t uuid[16];
}; };
@ -205,7 +205,7 @@ struct grub_jfs_inode
struct struct
{ {
grub_uint8_t unused[32]; grub_uint8_t unused[32];
grub_uint8_t path[128]; grub_uint8_t path[256];
} symlink; } symlink;
} __attribute__ ((packed)); } __attribute__ ((packed));
} __attribute__ ((packed)); } __attribute__ ((packed));
@ -238,7 +238,10 @@ struct grub_jfs_diropen
struct grub_jfs_leaf_next_dirent *next_leaf; struct grub_jfs_leaf_next_dirent *next_leaf;
/* The filename and inode of the last read dirent. */ /* The filename and inode of the last read dirent. */
char name[255]; /* On-disk name is at most 255 UTF-16 codepoints.
Every UTF-16 codepoint is at most 4 UTF-8 bytes.
*/
char name[256 * GRUB_MAX_UTF8_PER_UTF16 + 1];
grub_uint32_t ino; grub_uint32_t ino;
} __attribute__ ((packed)); } __attribute__ ((packed));
@ -253,11 +256,11 @@ static grub_int64_t
grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode, grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
grub_uint64_t blk) grub_uint64_t blk)
{ {
auto int getblk (struct grub_jfs_treehead *treehead, auto grub_int64_t getblk (struct grub_jfs_treehead *treehead,
struct grub_jfs_tree_extent *extents); struct grub_jfs_tree_extent *extents);
int getblk (struct grub_jfs_treehead *treehead, grub_int64_t getblk (struct grub_jfs_treehead *treehead,
struct grub_jfs_tree_extent *extents) struct grub_jfs_tree_extent *extents)
{ {
int found = -1; int found = -1;
int i; int i;
@ -269,7 +272,7 @@ grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
/* Read the leafnode. */ /* Read the leafnode. */
if (grub_le_to_cpu32 (extents[i].offset2) <= blk if (grub_le_to_cpu32 (extents[i].offset2) <= blk
&& ((grub_le_to_cpu16 (extents[i].extent.length)) && ((grub_le_to_cpu16 (extents[i].extent.length))
+ (extents[i].extent.length2 << 8) + (extents[i].extent.length2 << 16)
+ grub_le_to_cpu32 (extents[i].offset2)) > blk) + grub_le_to_cpu32 (extents[i].offset2)) > blk)
return (blk - grub_le_to_cpu32 (extents[i].offset2) return (blk - grub_le_to_cpu32 (extents[i].offset2)
+ grub_le_to_cpu32 (extents[i].extent.blk2)); + grub_le_to_cpu32 (extents[i].extent.blk2));
@ -288,7 +291,7 @@ grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
} tree; } tree;
if (grub_disk_read (data->disk, if (grub_disk_read (data->disk,
grub_le_to_cpu32 (extents[found].extent.blk2) ((grub_disk_addr_t) grub_le_to_cpu32 (extents[found].extent.blk2))
<< (grub_le_to_cpu16 (data->sblock.log2_blksz) << (grub_le_to_cpu16 (data->sblock.log2_blksz)
- GRUB_DISK_SECTOR_BITS), 0, - GRUB_DISK_SECTOR_BITS), 0,
sizeof (tree), (char *) &tree)) sizeof (tree), (char *) &tree))
@ -479,7 +482,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro)
struct grub_jfs_leaf_next_dirent *next_leaf; struct grub_jfs_leaf_next_dirent *next_leaf;
int len; int len;
int nextent; int nextent;
grub_uint16_t filename[255]; grub_uint16_t filename[256];
auto void addstr (grub_uint16_t *uname, int ulen); auto void addstr (grub_uint16_t *uname, int ulen);
@ -487,7 +490,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro)
void addstr (grub_uint16_t *name, int ulen) void addstr (grub_uint16_t *name, int ulen)
{ {
while (ulen--) while (ulen--)
filename[strpos++] = *(name++); filename[strpos++] = grub_le_to_cpu16 (*(name++));
} }
/* The last node, read in more. */ /* The last node, read in more. */
@ -558,10 +561,10 @@ static grub_ssize_t
grub_jfs_read_file (struct grub_jfs_data *data, grub_jfs_read_file (struct grub_jfs_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length), unsigned offset, unsigned length),
grub_uint64_t pos, grub_size_t len, char *buf) grub_off_t pos, grub_size_t len, char *buf)
{ {
grub_uint64_t i; grub_off_t i;
grub_uint64_t blockcnt; grub_off_t blockcnt;
blockcnt = (len + pos + grub_le_to_cpu32 (data->sblock.blksz) - 1) blockcnt = (len + pos + grub_le_to_cpu32 (data->sblock.blksz) - 1)
>> grub_le_to_cpu16 (data->sblock.log2_blksz); >> grub_le_to_cpu16 (data->sblock.log2_blksz);
@ -708,14 +711,14 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path,
static grub_err_t static grub_err_t
grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino) grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino)
{ {
grub_uint64_t size = grub_le_to_cpu64 (data->currinode.size); grub_size_t size = grub_le_to_cpu64 (data->currinode.size);
char symlink[size + 1]; char symlink[size + 1];
if (++data->linknest > GRUB_JFS_MAX_SYMLNK_CNT) if (++data->linknest > GRUB_JFS_MAX_SYMLNK_CNT)
return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks"); return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
if (size <= 128) if (size <= sizeof (data->currinode.symlink.path))
grub_strncpy (symlink, (char *) (data->currinode.symlink.path), 128); grub_strncpy (symlink, (char *) (data->currinode.symlink.path), size);
else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0) else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0)
return grub_errno; return grub_errno;
@ -888,6 +891,8 @@ grub_jfs_label (grub_device_t device, char **label)
else else
*label = 0; *label = 0;
grub_free (data);
return grub_errno; return grub_errno;
} }

View file

@ -63,7 +63,7 @@ typedef grub_uint16_t grub_minix_ino_t;
#define grub_minix_le_to_cpu_ino grub_le_to_cpu16 #define grub_minix_le_to_cpu_ino grub_le_to_cpu16
#endif #endif
#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size)) #define GRUB_MINIX_INODE_SIZE(data) (grub_le_to_cpu32 (data->inode.size))
#define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode)) #define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode))
#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) (grub_minix_le_to_cpu_n \ #define GRUB_MINIX_INODE_DIR_ZONES(data,blk) (grub_minix_le_to_cpu_n \
(data->inode.dir_zones[blk])) (data->inode.dir_zones[blk]))
@ -76,11 +76,11 @@ typedef grub_uint16_t grub_minix_ino_t;
#define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \ #define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \
+ grub_le_to_cpu16 (data->sblock.log2_zone_size)) + grub_le_to_cpu16 (data->sblock.log2_zone_size))
#endif #endif
#define GRUB_MINIX_ZONESZ (data->block_size \ #define GRUB_MINIX_ZONESZ (1 << (data->log_block_size \
<< grub_le_to_cpu16 (data->sblock.log2_zone_size)) + grub_le_to_cpu16 (data->sblock.log2_zone_size)))
#ifdef MODE_MINIX3 #ifdef MODE_MINIX3
#define GRUB_MINIX_ZONE2SECT(zone) ((zone) * (data->block_size / GRUB_DISK_SECTOR_SIZE)) #define GRUB_MINIX_ZONE2SECT(zone) ((zone) << (data->log_block_size - GRUB_DISK_SECTOR_BITS))
#else #else
#define GRUB_MINIX_ZONE2SECT(zone) ((zone) << GRUB_MINIX_LOG2_ZONESZ) #define GRUB_MINIX_ZONE2SECT(zone) ((zone) << GRUB_MINIX_LOG2_ZONESZ)
#endif #endif
@ -132,16 +132,15 @@ struct grub_minix_inode
grub_uint32_t dir_zones[7]; grub_uint32_t dir_zones[7];
grub_uint32_t indir_zone; grub_uint32_t indir_zone;
grub_uint32_t double_indir_zone; grub_uint32_t double_indir_zone;
grub_uint32_t unused; grub_uint32_t triple_indir_zone;
}; };
#else #else
struct grub_minix_inode struct grub_minix_inode
{ {
grub_uint16_t mode; grub_uint16_t mode;
grub_uint16_t uid; grub_uint16_t uid;
grub_uint16_t size; grub_uint32_t size;
grub_uint32_t ctime; grub_uint32_t mtime;
grub_uint8_t gid; grub_uint8_t gid;
grub_uint8_t nlinks; grub_uint8_t nlinks;
grub_uint16_t dir_zones[7]; grub_uint16_t dir_zones[7];
@ -160,7 +159,7 @@ struct grub_minix_data
int linknest; int linknest;
grub_disk_t disk; grub_disk_t disk;
int filename_size; int filename_size;
grub_size_t block_size; grub_size_t log_block_size;
}; };
static grub_dl_t my_mod; static grub_dl_t my_mod;
@ -168,15 +167,19 @@ static grub_dl_t my_mod;
static grub_err_t grub_minix_find_file (struct grub_minix_data *data, static grub_err_t grub_minix_find_file (struct grub_minix_data *data,
const char *path); const char *path);
static int static grub_minix_uintn_t
grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
{ {
int indir; grub_minix_uintn_t indir;
const grub_uint32_t block_per_zone = (GRUB_MINIX_ZONESZ
/ GRUB_MINIX_INODE_BLKSZ (data));
auto int grub_get_indir (int, int); auto grub_minix_uintn_t grub_get_indir (grub_minix_uintn_t,
grub_minix_uintn_t);
/* Read the block pointer in ZONE, on the offset NUM. */ /* Read the block pointer in ZONE, on the offset NUM. */
int grub_get_indir (int zone, int num) grub_minix_uintn_t grub_get_indir (grub_minix_uintn_t zone,
grub_minix_uintn_t num)
{ {
grub_minix_uintn_t indirn; grub_minix_uintn_t indirn;
grub_disk_read (data->disk, grub_disk_read (data->disk,
@ -192,25 +195,38 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
/* Indirect block. */ /* Indirect block. */
blk -= GRUB_MINIX_INODE_DIR_BLOCKS; blk -= GRUB_MINIX_INODE_DIR_BLOCKS;
if (blk < GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)) if (blk < block_per_zone)
{ {
indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk); indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk);
return indir; return indir;
} }
/* Double indirect block. */ /* Double indirect block. */
blk -= GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data); blk -= block_per_zone;
if (blk < (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)) if (blk < block_per_zone * block_per_zone)
* (GRUB_MINIX_ZONESZ / GRUB_MINIX_INODE_BLKSZ (data)))
{ {
indir = grub_get_indir (GRUB_MINIX_INODE_DINDIR_ZONE (data), indir = grub_get_indir (GRUB_MINIX_INODE_DINDIR_ZONE (data),
blk / GRUB_MINIX_ZONESZ); blk / block_per_zone);
indir = grub_get_indir (indir, blk % GRUB_MINIX_ZONESZ); indir = grub_get_indir (indir, blk % block_per_zone);
return indir; return indir;
} }
#if defined (MODE_MINIX3) || defined (MODE_MINIX2)
blk -= block_per_zone * block_per_zone;
if (blk < ((grub_uint64_t) block_per_zone * (grub_uint64_t) block_per_zone
* (grub_uint64_t) block_per_zone))
{
indir = grub_get_indir (grub_minix_le_to_cpu_n (data->inode.triple_indir_zone),
(blk / block_per_zone) / block_per_zone);
indir = grub_get_indir (indir, (blk / block_per_zone) % block_per_zone);
indir = grub_get_indir (indir, blk % block_per_zone);
return indir;
}
#endif
/* This should never happen. */ /* This should never happen. */
grub_error (GRUB_ERR_OUT_OF_RANGE, "file bigger than maximum size"); grub_error (GRUB_ERR_OUT_OF_RANGE, "file bigger than maximum size");
@ -235,14 +251,15 @@ grub_minix_read_file (struct grub_minix_data *data,
if (len + pos > GRUB_MINIX_INODE_SIZE (data)) if (len + pos > GRUB_MINIX_INODE_SIZE (data))
len = GRUB_MINIX_INODE_SIZE (data) - pos; len = GRUB_MINIX_INODE_SIZE (data) - pos;
blockcnt = grub_divmod64 ((len + pos + data->block_size - 1), blockcnt = ((len + pos + (1 << data->log_block_size) - 1)
data->block_size, 0); >> data->log_block_size);
posblock = grub_divmod64 (pos, data->block_size, &blockoff); posblock = pos >> data->log_block_size;
blockoff = pos & ((1 << data->log_block_size) - 1);
for (i = posblock; i < blockcnt; i++) for (i = posblock; i < blockcnt; i++)
{ {
grub_disk_addr_t blknr; grub_disk_addr_t blknr;
grub_uint64_t blockend = data->block_size; grub_uint64_t blockend = 1 << data->log_block_size;
grub_off_t skipfirst = 0; grub_off_t skipfirst = 0;
blknr = grub_minix_get_file_block (data, i); blknr = grub_minix_get_file_block (data, i);
@ -252,10 +269,10 @@ grub_minix_read_file (struct grub_minix_data *data,
/* Last block. */ /* Last block. */
if (i == blockcnt - 1) if (i == blockcnt - 1)
{ {
grub_divmod64 (len + pos, data->block_size, &blockend); blockend = (len + pos) & ((1 << data->log_block_size) - 1);
if (!blockend) if (!blockend)
blockend = data->block_size; blockend = 1 << data->log_block_size;
} }
/* First block. */ /* First block. */
@ -273,7 +290,7 @@ grub_minix_read_file (struct grub_minix_data *data,
if (grub_errno) if (grub_errno)
return -1; return -1;
buf += data->block_size - skipfirst; buf += (1 << data->log_block_size) - skipfirst;
} }
return len; return len;
@ -463,9 +480,14 @@ grub_minix_mount (grub_disk_t disk)
data->disk = disk; data->disk = disk;
data->linknest = 0; data->linknest = 0;
#ifdef MODE_MINIX3 #ifdef MODE_MINIX3
data->block_size = grub_le_to_cpu16 (data->sblock.block_size); if ((grub_le_to_cpu16 (data->sblock.block_size)
& (grub_le_to_cpu16 (data->sblock.block_size) - 1))
|| grub_le_to_cpu16 (data->sblock.block_size) == 0)
goto fail;
for (data->log_block_size = 0; (1 << data->log_block_size)
< grub_le_to_cpu16 (data->sblock.block_size); data->log_block_size++);
#else #else
data->block_size = 1024U; data->log_block_size = 10;
#endif #endif
return data; return data;
@ -536,11 +558,7 @@ grub_minix_dir (grub_device_t device, const char *path,
info.dir = ((GRUB_MINIX_INODE_MODE (data) info.dir = ((GRUB_MINIX_INODE_MODE (data)
& GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR); & GRUB_MINIX_IFDIR) == GRUB_MINIX_IFDIR);
info.mtimeset = 1; info.mtimeset = 1;
#ifndef MODE_MINIX2
info.mtime = grub_le_to_cpu32 (data->inode.ctime);
#else
info.mtime = grub_le_to_cpu32 (data->inode.mtime); info.mtime = grub_le_to_cpu32 (data->inode.mtime);
#endif
if (hook (filename, &info) ? 1 : 0) if (hook (filename, &info) ? 1 : 0)
break; break;

View file

@ -58,6 +58,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
in 512 block size */ in 512 block size */
#define NILFS_2ND_SUPER_BLOCK(devsize) (((devsize >> 3) - 1) << 3) #define NILFS_2ND_SUPER_BLOCK(devsize) (((devsize >> 3) - 1) << 3)
#define LOG_INODE_SIZE 7
struct grub_nilfs2_inode struct grub_nilfs2_inode
{ {
grub_uint64_t i_blocks; grub_uint64_t i_blocks;
@ -207,6 +208,7 @@ struct grub_nilfs2_btree_node
grub_uint8_t bn_level; grub_uint8_t bn_level;
grub_uint16_t bn_nchildren; grub_uint16_t bn_nchildren;
grub_uint32_t bn_pad; grub_uint32_t bn_pad;
grub_uint64_t keys[0];
}; };
struct grub_nilfs2_palloc_group_desc struct grub_nilfs2_palloc_group_desc
@ -214,6 +216,7 @@ struct grub_nilfs2_palloc_group_desc
grub_uint32_t pg_nfrees; grub_uint32_t pg_nfrees;
}; };
#define LOG_NILFS_DAT_ENTRY_SIZE 5
struct grub_nilfs2_dat_entry struct grub_nilfs2_dat_entry
{ {
grub_uint64_t de_blocknr; grub_uint64_t de_blocknr;
@ -296,17 +299,17 @@ static grub_dl_t my_mod;
static inline unsigned long static inline unsigned long
grub_nilfs2_palloc_entries_per_group (struct grub_nilfs2_data *data) grub_nilfs2_log_palloc_entries_per_group (struct grub_nilfs2_data *data)
{ {
return 1UL << (LOG2_BLOCK_SIZE (data) + 3); return LOG2_BLOCK_SIZE (data) + 3;
} }
static inline grub_uint64_t static inline grub_uint64_t
grub_nilfs2_palloc_group (struct grub_nilfs2_data *data, grub_nilfs2_palloc_group (struct grub_nilfs2_data *data,
grub_uint64_t nr, grub_uint64_t * offset) grub_uint64_t nr, grub_uint64_t * offset)
{ {
return grub_divmod64 (nr, grub_nilfs2_palloc_entries_per_group (data), *offset = nr & ((1 << grub_nilfs2_log_palloc_entries_per_group (data)) - 1);
offset); return nr >> grub_nilfs2_log_palloc_entries_per_group (data);
} }
static inline grub_uint32_t static inline grub_uint32_t
@ -317,55 +320,58 @@ grub_nilfs2_palloc_groups_per_desc_block (struct grub_nilfs2_data *data)
} }
static inline grub_uint32_t static inline grub_uint32_t
grub_nilfs2_entries_per_block (struct grub_nilfs2_data *data, grub_nilfs2_log_entries_per_block_log (struct grub_nilfs2_data *data,
unsigned long entry_size) unsigned long log_entry_size)
{ {
return NILFS2_BLOCK_SIZE (data) / entry_size; return LOG2_BLOCK_SIZE (data) - log_entry_size;
} }
static inline grub_uint32_t static inline grub_uint32_t
grub_nilfs2_blocks_per_group (struct grub_nilfs2_data *data, grub_nilfs2_blocks_per_group_log (struct grub_nilfs2_data *data,
unsigned long entry_size) unsigned long log_entry_size)
{ {
return grub_div_roundup (grub_nilfs2_palloc_entries_per_group (data), return (1 << (grub_nilfs2_log_palloc_entries_per_group (data)
grub_nilfs2_entries_per_block (data, - grub_nilfs2_log_entries_per_block_log (data,
entry_size)) + 1; log_entry_size))) + 1;
} }
static inline grub_uint32_t static inline grub_uint32_t
grub_nilfs2_blocks_per_desc_block (struct grub_nilfs2_data *data, grub_nilfs2_blocks_per_desc_block_log (struct grub_nilfs2_data *data,
unsigned long entry_size) unsigned long log_entry_size)
{ {
return grub_nilfs2_palloc_groups_per_desc_block (data) * return grub_nilfs2_palloc_groups_per_desc_block (data) *
grub_nilfs2_blocks_per_group (data, entry_size) + 1; grub_nilfs2_blocks_per_group_log (data, log_entry_size) + 1;
} }
static inline grub_uint32_t static inline grub_uint32_t
grub_nilfs2_palloc_desc_block_offset (struct grub_nilfs2_data *data, grub_nilfs2_palloc_desc_block_offset_log (struct grub_nilfs2_data *data,
unsigned long group, unsigned long group,
unsigned long entry_size) unsigned long log_entry_size)
{ {
grub_uint32_t desc_block = grub_uint32_t desc_block =
group / grub_nilfs2_palloc_groups_per_desc_block (data); group / grub_nilfs2_palloc_groups_per_desc_block (data);
return desc_block * grub_nilfs2_blocks_per_desc_block (data, entry_size); return desc_block * grub_nilfs2_blocks_per_desc_block_log (data,
log_entry_size);
} }
static inline grub_uint32_t static inline grub_uint32_t
grub_nilfs2_palloc_bitmap_block_offset (struct grub_nilfs2_data *data, grub_nilfs2_palloc_bitmap_block_offset (struct grub_nilfs2_data *data,
unsigned long group, unsigned long group,
unsigned long entry_size) unsigned long log_entry_size)
{ {
unsigned long desc_offset = group % unsigned long desc_offset = group %
grub_nilfs2_palloc_groups_per_desc_block (data); grub_nilfs2_palloc_groups_per_desc_block (data);
return grub_nilfs2_palloc_desc_block_offset (data, group, entry_size) + 1 + return grub_nilfs2_palloc_desc_block_offset_log (data, group, log_entry_size)
desc_offset * grub_nilfs2_blocks_per_group (data, entry_size); + 1
+ desc_offset * grub_nilfs2_blocks_per_group_log (data, log_entry_size);
} }
static inline grub_uint32_t static inline grub_uint32_t
grub_nilfs2_palloc_entry_offset (struct grub_nilfs2_data *data, grub_nilfs2_palloc_entry_offset_log (struct grub_nilfs2_data *data,
grub_uint64_t nr, unsigned long entry_size) grub_uint64_t nr,
unsigned long log_entry_size)
{ {
unsigned long group; unsigned long group;
grub_uint64_t group_offset; grub_uint64_t group_offset;
@ -373,10 +379,9 @@ grub_nilfs2_palloc_entry_offset (struct grub_nilfs2_data *data,
group = grub_nilfs2_palloc_group (data, nr, &group_offset); group = grub_nilfs2_palloc_group (data, nr, &group_offset);
return grub_nilfs2_palloc_bitmap_block_offset (data, group, return grub_nilfs2_palloc_bitmap_block_offset (data, group,
entry_size) + 1 + 1 << log_entry_size) + 1 +
grub_divmod64 (group_offset, grub_nilfs2_entries_per_block (data, (group_offset >> grub_nilfs2_log_entries_per_block_log (data,
entry_size), log_entry_size));
NULL);
} }
@ -395,9 +400,9 @@ grub_nilfs2_btree_get_level (struct grub_nilfs2_btree_node *node)
static inline grub_uint64_t * static inline grub_uint64_t *
grub_nilfs2_btree_node_dkeys (struct grub_nilfs2_btree_node *node) grub_nilfs2_btree_node_dkeys (struct grub_nilfs2_btree_node *node)
{ {
return (grub_uint64_t *) ((char *) (node + 1) + return (node->keys +
((node->bn_flags & NILFS_BTREE_NODE_ROOT) ? ((node->bn_flags & NILFS_BTREE_NODE_ROOT) ?
0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE)); 0 : (NILFS_BTREE_NODE_EXTRA_PAD_SIZE / sizeof (grub_uint64_t))));
} }
static inline grub_uint64_t static inline grub_uint64_t
@ -498,7 +503,7 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data,
grub_uint64_t key, int need_translate) grub_uint64_t key, int need_translate)
{ {
struct grub_nilfs2_btree_node *node; struct grub_nilfs2_btree_node *node;
unsigned char block[NILFS2_BLOCK_SIZE (data)]; GRUB_PROPERLY_ALIGNED_ARRAY (block, NILFS2_BLOCK_SIZE (data));
grub_uint64_t ptr; grub_uint64_t ptr;
int level, found, index; int level, found, index;
@ -582,12 +587,11 @@ grub_nilfs2_dat_translate (struct grub_nilfs2_data *data, grub_uint64_t key)
grub_uint64_t blockno, offset; grub_uint64_t blockno, offset;
unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data)); unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
blockno = grub_nilfs2_palloc_entry_offset (data, key, blockno = grub_nilfs2_palloc_entry_offset_log (data, key,
sizeof (struct LOG_NILFS_DAT_ENTRY_SIZE);
grub_nilfs2_dat_entry));
grub_divmod64 (key * sizeof (struct grub_nilfs2_dat_entry), offset = ((key * sizeof (struct grub_nilfs2_dat_entry))
NILFS2_BLOCK_SIZE (data), &offset); & ((1 << LOG2_BLOCK_SIZE (data)) - 1));
pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_dat, blockno, 0); pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_dat, blockno, 0);
if (pptr == (grub_uint64_t) - 1) if (pptr == (grub_uint64_t) - 1)
@ -628,7 +632,7 @@ grub_nilfs2_read_file (grub_fshelp_node_t node,
sector, sector,
unsigned offset, unsigned offset,
unsigned length), unsigned length),
int pos, grub_size_t len, char *buf) grub_off_t pos, grub_size_t len, char *buf)
{ {
return grub_fshelp_read_file (node->data->disk, node, read_hook, return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_nilfs2_read_block, pos, len, buf, grub_nilfs2_read_block,
@ -652,8 +656,8 @@ grub_nilfs2_read_checkpoint (struct grub_nilfs2_data *data,
sizeof(struct grub_nilfs2_checkpoint). sizeof(struct grub_nilfs2_checkpoint).
*/ */
blockno = grub_divmod64 (cpno, NILFS2_BLOCK_SIZE (data) / blockno = grub_divmod64 (cpno, NILFS2_BLOCK_SIZE (data) /
sizeof (struct grub_nilfs2_checkpoint), &offset); sizeof (struct grub_nilfs2_checkpoint), &offset);
pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_cpfile, blockno, 1); pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_cpfile, blockno, 1);
if (pptr == (grub_uint64_t) - 1) if (pptr == (grub_uint64_t) - 1)
{ {
@ -686,12 +690,11 @@ grub_nilfs2_read_inode (struct grub_nilfs2_data *data,
grub_disk_t disk = data->disk; grub_disk_t disk = data->disk;
unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data)); unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data));
blockno = grub_nilfs2_palloc_entry_offset (data, ino, blockno = grub_nilfs2_palloc_entry_offset_log (data, ino,
sizeof (struct LOG_INODE_SIZE);
grub_nilfs2_inode));
grub_divmod64 (sizeof (struct grub_nilfs2_inode) * ino, offset = ((sizeof (struct grub_nilfs2_inode) * ino)
NILFS2_BLOCK_SIZE (data), &offset); & ((1 << LOG2_BLOCK_SIZE (data)) - 1));
pptr = grub_nilfs2_bmap_lookup (data, &data->ifile, blockno, 1); pptr = grub_nilfs2_bmap_lookup (data, &data->ifile, blockno, 1);
if (pptr == (grub_uint64_t) - 1) if (pptr == (grub_uint64_t) - 1)
{ {
@ -866,7 +869,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir,
enum grub_fshelp_filetype filetype, enum grub_fshelp_filetype filetype,
grub_fshelp_node_t node)) grub_fshelp_node_t node))
{ {
unsigned int fpos = 0; grub_off_t fpos = 0;
struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir;
if (!diro->inode_read) if (!diro->inode_read)
@ -1117,7 +1120,7 @@ grub_nilfs2_uuid (grub_device_t device, char **uuid)
{ {
*uuid = *uuid =
grub_xasprintf grub_xasprintf
("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%0x-%02x%02x%02x%02x%02x%02x", ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
data->sblock.s_uuid[0], data->sblock.s_uuid[1], data->sblock.s_uuid[0], data->sblock.s_uuid[1],
data->sblock.s_uuid[2], data->sblock.s_uuid[3], data->sblock.s_uuid[2], data->sblock.s_uuid[3],
data->sblock.s_uuid[4], data->sblock.s_uuid[5], data->sblock.s_uuid[4], data->sblock.s_uuid[5],
@ -1150,7 +1153,7 @@ grub_nilfs2_mtime (grub_device_t device, grub_int32_t * tm)
if (!data) if (!data)
*tm = 0; *tm = 0;
else else
*tm = (grub_int32_t) grub_le_to_cpu64 (data->sblock.s_mtime); *tm = (grub_int32_t) grub_le_to_cpu64 (data->sblock.s_wtime);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -1178,6 +1181,11 @@ static struct grub_fs grub_nilfs2_fs = {
GRUB_MOD_INIT (nilfs2) GRUB_MOD_INIT (nilfs2)
{ {
COMPILE_TIME_ASSERT ((1 << LOG_NILFS_DAT_ENTRY_SIZE)
== sizeof (struct
grub_nilfs2_dat_entry));
COMPILE_TIME_ASSERT (1 << LOG_INODE_SIZE
== sizeof (struct grub_nilfs2_inode));
grub_fs_register (&grub_nilfs2_fs); grub_fs_register (&grub_nilfs2_fs);
my_mod = mod; my_mod = mod;
} }

View file

@ -17,6 +17,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define grub_fshelp_node grub_ntfs_file
#include <grub/file.h> #include <grub/file.h>
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/misc.h> #include <grub/misc.h>
@ -30,10 +32,30 @@ GRUB_MOD_LICENSE ("GPLv3+");
static grub_dl_t my_mod; static grub_dl_t my_mod;
ntfscomp_func_t grub_ntfscomp_func; #define grub_fshelp_node grub_ntfs_file
static inline grub_uint16_t
u16at (void *ptr, grub_size_t ofs)
{
return grub_le_to_cpu16 (grub_get_unaligned16 ((char *) ptr + ofs));
}
static inline grub_uint32_t
u32at (void *ptr, grub_size_t ofs)
{
return grub_le_to_cpu32 (grub_get_unaligned32 ((char *) ptr + ofs));
}
static inline grub_uint64_t
u64at (void *ptr, grub_size_t ofs)
{
return grub_le_to_cpu64 (grub_get_unaligned64 ((char *) ptr + ofs));
}
grub_ntfscomp_func_t grub_ntfscomp_func;
static grub_err_t static grub_err_t
fixup (struct grub_ntfs_data *data, char *buf, int len, char *magic) fixup (struct grub_ntfs_data *data, char *buf, int len, const char *magic)
{ {
int ss; int ss;
char *pu; char *pu;
@ -56,7 +78,8 @@ fixup (struct grub_ntfs_data *data, char *buf, int len, char *magic)
pu += 2; pu += 2;
if (u16at (buf, 0) != us) if (u16at (buf, 0) != us)
return grub_error (GRUB_ERR_BAD_FS, "fixup signature not match"); return grub_error (GRUB_ERR_BAD_FS, "fixup signature not match");
v16at (buf, 0) = v16at (pu, 0); buf[0] = pu[0];
buf[1] = pu[1];
ss--; ss--;
} }
@ -87,7 +110,7 @@ static void
init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft) init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft)
{ {
at->mft = mft; at->mft = mft;
at->flags = (mft == &mft->data->mmft) ? AF_MMFT : 0; at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0;
at->attr_nxt = mft->buf + u16at (mft->buf, 0x14); at->attr_nxt = mft->buf + u16at (mft->buf, 0x14);
at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL; at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL;
} }
@ -103,7 +126,7 @@ free_attr (struct grub_ntfs_attr *at)
static char * static char *
find_attr (struct grub_ntfs_attr *at, unsigned char attr) find_attr (struct grub_ntfs_attr *at, unsigned char attr)
{ {
if (at->flags & AF_ALST) if (at->flags & GRUB_NTFS_AF_ALST)
{ {
retry: retry:
while (at->attr_nxt < at->attr_end) while (at->attr_nxt < at->attr_end)
@ -114,14 +137,14 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr)
{ {
char *new_pos; char *new_pos;
if (at->flags & AF_MMFT) if (at->flags & GRUB_NTFS_AF_MMFT)
{ {
if ((grub_disk_read if ((grub_disk_read
(at->mft->data->disk, v32at (at->attr_cur, 0x10), 0, (at->mft->data->disk, u32at (at->attr_cur, 0x10), 0,
512, at->emft_buf)) 512, at->emft_buf))
|| ||
(grub_disk_read (grub_disk_read
(at->mft->data->disk, v32at (at->attr_cur, 0x14), 0, (at->mft->data->disk, u32at (at->attr_cur, 0x14), 0,
512, at->emft_buf + 512))) 512, at->emft_buf + 512)))
return NULL; return NULL;
@ -160,7 +183,7 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr)
while ((unsigned char) *at->attr_cur != 0xFF) while ((unsigned char) *at->attr_cur != 0xFF)
{ {
at->attr_nxt += u16at (at->attr_cur, 4); at->attr_nxt += u16at (at->attr_cur, 4);
if ((unsigned char) *at->attr_cur == AT_ATTRIBUTE_LIST) if ((unsigned char) *at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST)
at->attr_end = at->attr_cur; at->attr_end = at->attr_cur;
if (((unsigned char) *at->attr_cur == attr) || (attr == 0)) if (((unsigned char) *at->attr_cur == attr) || (attr == 0))
return at->attr_cur; return at->attr_cur;
@ -170,7 +193,7 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr)
{ {
char *pa; char *pa;
at->emft_buf = grub_malloc (at->mft->data->mft_size << BLK_SHR); at->emft_buf = grub_malloc (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR);
if (at->emft_buf == NULL) if (at->emft_buf == NULL)
return NULL; return NULL;
@ -199,7 +222,7 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr)
at->attr_nxt = at->attr_end + u16at (pa, 0x14); at->attr_nxt = at->attr_end + u16at (pa, 0x14);
at->attr_end = at->attr_end + u32at (pa, 4); at->attr_end = at->attr_end + u32at (pa, 4);
} }
at->flags |= AF_ALST; at->flags |= GRUB_NTFS_AF_ALST;
while (at->attr_nxt < at->attr_end) while (at->attr_nxt < at->attr_end)
{ {
if (((unsigned char) *at->attr_nxt == attr) || (attr == 0)) if (((unsigned char) *at->attr_nxt == attr) || (attr == 0))
@ -209,13 +232,16 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr)
if (at->attr_nxt >= at->attr_end) if (at->attr_nxt >= at->attr_end)
return NULL; return NULL;
if ((at->flags & AF_MMFT) && (attr == AT_DATA)) if ((at->flags & GRUB_NTFS_AF_MMFT) && (attr == GRUB_NTFS_AT_DATA))
{ {
at->flags |= AF_GPOS; at->flags |= GRUB_NTFS_AF_GPOS;
at->attr_cur = at->attr_nxt; at->attr_cur = at->attr_nxt;
pa = at->attr_cur; pa = at->attr_cur;
v32at (pa, 0x10) = at->mft->data->mft_start; grub_set_unaligned32 ((char *) pa + 0x10,
v32at (pa, 0x14) = at->mft->data->mft_start + 1; grub_cpu_to_le32 (at->mft->data->mft_start));
grub_set_unaligned32 ((char *) pa + 0x14,
grub_cpu_to_le32 (at->mft->data->mft_start
+ 1));
pa = at->attr_nxt + u16at (pa, 4); pa = at->attr_nxt + u16at (pa, 4);
while (pa < at->attr_end) while (pa < at->attr_end)
{ {
@ -223,13 +249,13 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr)
break; break;
if (read_attr if (read_attr
(at, pa + 0x10, (at, pa + 0x10,
u32at (pa, 0x10) * (at->mft->data->mft_size << BLK_SHR), u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR),
at->mft->data->mft_size << BLK_SHR, 0, 0)) at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0))
return NULL; return NULL;
pa += u16at (pa, 4); pa += u16at (pa, 4);
} }
at->attr_nxt = at->attr_cur; at->attr_nxt = at->attr_cur;
at->flags &= ~AF_GPOS; at->flags &= ~GRUB_NTFS_AF_GPOS;
} }
goto retry; goto retry;
} }
@ -245,13 +271,13 @@ locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft,
init_attr (at, mft); init_attr (at, mft);
if ((pa = find_attr (at, attr)) == NULL) if ((pa = find_attr (at, attr)) == NULL)
return NULL; return NULL;
if ((at->flags & AF_ALST) == 0) if ((at->flags & GRUB_NTFS_AF_ALST) == 0)
{ {
while (1) while (1)
{ {
if ((pa = find_attr (at, attr)) == NULL) if ((pa = find_attr (at, attr)) == NULL)
break; break;
if (at->flags & AF_ALST) if (at->flags & GRUB_NTFS_AF_ALST)
return pa; return pa;
} }
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
@ -296,7 +322,7 @@ retry:
c2 = ((unsigned char) (*run) >> 4); c2 = ((unsigned char) (*run) >> 4);
if (!c1) if (!c1)
{ {
if ((ctx->attr) && (ctx->attr->flags & AF_ALST)) if ((ctx->attr) && (ctx->attr->flags & GRUB_NTFS_AF_ALST))
{ {
void NESTED_FUNC_ATTR (*save_hook) (grub_disk_addr_t sector, void NESTED_FUNC_ATTR (*save_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned offset,
@ -325,9 +351,9 @@ retry:
run = read_run_data (run, c2, &val, 1); /* offset to previous LCN */ run = read_run_data (run, c2, &val, 1); /* offset to previous LCN */
ctx->curr_lcn += val; ctx->curr_lcn += val;
if (val == 0) if (val == 0)
ctx->flags |= RF_BLNK; ctx->flags |= GRUB_NTFS_RF_BLNK;
else else
ctx->flags &= ~RF_BLNK; ctx->flags &= ~GRUB_NTFS_RF_BLNK;
ctx->cur_run = run; ctx->cur_run = run;
return 0; return 0;
} }
@ -345,7 +371,7 @@ grub_ntfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t block)
return ctx->curr_lcn; return ctx->curr_lcn;
} }
else else
return (ctx->flags & RF_BLNK) ? 0 : (block - return (ctx->flags & GRUB_NTFS_RF_BLNK) ? 0 : (block -
ctx->curr_vcn + ctx->curr_lcn); ctx->curr_vcn + ctx->curr_lcn);
} }
@ -376,24 +402,24 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest,
return 0; return 0;
} }
if (u16at (pa, 0xC) & FLAG_COMPRESSED) if (u16at (pa, 0xC) & GRUB_NTFS_FLAG_COMPRESSED)
ctx->flags |= RF_COMP; ctx->flags |= GRUB_NTFS_RF_COMP;
else else
ctx->flags &= ~RF_COMP; ctx->flags &= ~GRUB_NTFS_RF_COMP;
ctx->cur_run = pa + u16at (pa, 0x20); ctx->cur_run = pa + u16at (pa, 0x20);
if (ctx->flags & RF_COMP) if (ctx->flags & GRUB_NTFS_RF_COMP)
{ {
if (!cached) if (!cached)
return grub_error (GRUB_ERR_BAD_FS, "attribute can\'t be compressed"); return grub_error (GRUB_ERR_BAD_FS, "attribute can\'t be compressed");
if (at->sbuf) if (at->sbuf)
{ {
if ((ofs & (~(COM_LEN - 1))) == at->save_pos) if ((ofs & (~(GRUB_NTFS_COM_LEN - 1))) == at->save_pos)
{ {
grub_disk_addr_t n; grub_disk_addr_t n;
n = COM_LEN - (ofs - at->save_pos); n = GRUB_NTFS_COM_LEN - (ofs - at->save_pos);
if (n > len) if (n > len)
n = len; n = len;
@ -408,17 +434,17 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest,
} }
else else
{ {
at->sbuf = grub_malloc (COM_LEN); at->sbuf = grub_malloc (GRUB_NTFS_COM_LEN);
if (at->sbuf == NULL) if (at->sbuf == NULL)
return grub_errno; return grub_errno;
at->save_pos = 1; at->save_pos = 1;
} }
vcn = ctx->target_vcn = (ofs >> COM_LOG_LEN) * (COM_SEC / ctx->comp.spc); vcn = ctx->target_vcn = (ofs >> GRUB_NTFS_COM_LOG_LEN) * (GRUB_NTFS_COM_SEC / ctx->comp.spc);
ctx->target_vcn &= ~0xF; ctx->target_vcn &= ~0xF;
} }
else else
vcn = ctx->target_vcn = grub_divmod64 (ofs >> BLK_SHR, ctx->comp.spc, 0); vcn = ctx->target_vcn = grub_divmod64 (ofs >> GRUB_NTFS_BLK_SHR, ctx->comp.spc, 0);
ctx->next_vcn = u32at (pa, 0x10); ctx->next_vcn = u32at (pa, 0x10);
ctx->curr_lcn = 0; ctx->curr_lcn = 0;
@ -428,12 +454,12 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest,
return grub_errno; return grub_errno;
} }
if (at->flags & AF_GPOS) if (at->flags & GRUB_NTFS_AF_GPOS)
{ {
grub_disk_addr_t st0, st1; grub_disk_addr_t st0, st1;
grub_uint64_t m; grub_uint64_t m;
grub_divmod64 (ofs >> BLK_SHR, ctx->comp.spc, &m); grub_divmod64 (ofs >> GRUB_NTFS_BLK_SHR, ctx->comp.spc, &m);
st0 = st0 =
(ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc + m; (ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc + m;
@ -445,12 +471,12 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest,
return grub_errno; return grub_errno;
st1 = ctx->curr_lcn * ctx->comp.spc; st1 = ctx->curr_lcn * ctx->comp.spc;
} }
v32at (dest, 0) = st0; grub_set_unaligned32 (dest, grub_cpu_to_le32 (st0));
v32at (dest, 4) = st1; grub_set_unaligned32 (dest + 4, grub_cpu_to_le32 (st1));
return 0; return 0;
} }
if (!(ctx->flags & RF_COMP)) if (!(ctx->flags & GRUB_NTFS_RF_COMP))
{ {
unsigned int pow; unsigned int pow;
@ -481,12 +507,12 @@ read_attr (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs,
save_cur = at->attr_cur; save_cur = at->attr_cur;
at->attr_nxt = at->attr_cur; at->attr_nxt = at->attr_cur;
attr = (unsigned char) *at->attr_nxt; attr = (unsigned char) *at->attr_nxt;
if (at->flags & AF_ALST) if (at->flags & GRUB_NTFS_AF_ALST)
{ {
char *pa; char *pa;
grub_disk_addr_t vcn; grub_disk_addr_t vcn;
vcn = grub_divmod64 (ofs, at->mft->data->spc << BLK_SHR, 0); vcn = grub_divmod64 (ofs, at->mft->data->spc << GRUB_NTFS_BLK_SHR, 0);
pa = at->attr_nxt + u16at (at->attr_nxt, 4); pa = at->attr_nxt + u16at (at->attr_nxt, 4);
while (pa < at->attr_end) while (pa < at->attr_end)
{ {
@ -513,8 +539,8 @@ static grub_err_t
read_mft (struct grub_ntfs_data *data, char *buf, grub_uint32_t mftno) read_mft (struct grub_ntfs_data *data, char *buf, grub_uint32_t mftno)
{ {
if (read_attr if (read_attr
(&data->mmft.attr, buf, mftno * ((grub_disk_addr_t) data->mft_size << BLK_SHR), (&data->mmft.attr, buf, mftno * ((grub_disk_addr_t) data->mft_size << GRUB_NTFS_BLK_SHR),
data->mft_size << BLK_SHR, 0, 0)) data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0))
return grub_error (GRUB_ERR_BAD_FS, "read MFT 0x%X fails", mftno); return grub_error (GRUB_ERR_BAD_FS, "read MFT 0x%X fails", mftno);
return fixup (data, buf, data->mft_size, "FILE"); return fixup (data, buf, data->mft_size, "FILE");
} }
@ -526,7 +552,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno)
mft->inode_read = 1; mft->inode_read = 1;
mft->buf = grub_malloc (mft->data->mft_size << BLK_SHR); mft->buf = grub_malloc (mft->data->mft_size << GRUB_NTFS_BLK_SHR);
if (mft->buf == NULL) if (mft->buf == NULL)
return grub_errno; return grub_errno;
@ -541,7 +567,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno)
{ {
char *pa; char *pa;
pa = locate_attr (&mft->attr, mft, AT_DATA); pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_DATA);
if (pa == NULL) if (pa == NULL)
return grub_error (GRUB_ERR_BAD_FS, "no $DATA in MFT 0x%X", mftno); return grub_error (GRUB_ERR_BAD_FS, "no $DATA in MFT 0x%X", mftno);
@ -550,7 +576,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno)
else else
mft->size = u64at (pa, 0x30); mft->size = u64at (pa, 0x30);
if ((mft->attr.flags & AF_ALST) == 0) if ((mft->attr.flags & GRUB_NTFS_AF_ALST) == 0)
mft->attr.attr_end = 0; /* Don't jump to attribute list */ mft->attr.attr_end = 0; /* Don't jump to attribute list */
} }
else else
@ -595,6 +621,7 @@ list_file (struct grub_ntfs_file *diro, char *pos,
{ {
enum grub_fshelp_filetype type; enum grub_fshelp_filetype type;
struct grub_ntfs_file *fdiro; struct grub_ntfs_file *fdiro;
grub_uint32_t attr;
if (u16at (pos, 4)) if (u16at (pos, 4))
{ {
@ -602,9 +629,13 @@ list_file (struct grub_ntfs_file *diro, char *pos,
return 0; return 0;
} }
type = attr = u32at (pos, 0x48);
(u32at (pos, 0x48) & ATTR_DIRECTORY) ? GRUB_FSHELP_DIR : if (attr & GRUB_NTFS_ATTR_REPARSE)
GRUB_FSHELP_REG; type = GRUB_FSHELP_SYMLINK;
else if (attr & GRUB_NTFS_ATTR_DIRECTORY)
type = GRUB_FSHELP_DIR;
else
type = GRUB_FSHELP_REG;
fdiro = grub_zalloc (sizeof (struct grub_ntfs_file)); fdiro = grub_zalloc (sizeof (struct grub_ntfs_file));
if (!fdiro) if (!fdiro)
@ -617,12 +648,18 @@ list_file (struct grub_ntfs_file *diro, char *pos,
else else
fdiro->mtime = u64at (pos, 0x28); fdiro->mtime = u64at (pos, 0x28);
ustr = grub_malloc (ns * 4 + 1); ustr = grub_malloc (ns * GRUB_MAX_UTF8_PER_UTF16 + 1);
if (ustr == NULL) if (ustr == NULL)
return 0; return 0;
*grub_utf16_to_utf8 ((grub_uint8_t *) ustr, (grub_uint16_t *) np, {
ns) = '\0'; grub_uint16_t tmp[ns];
int i;
for (i = 0; i < ns; i++)
tmp[i] = grub_le_to_cpu16 (grub_get_unaligned16 ((char *) np
+ 2 * i));
*grub_utf16_to_utf8 ((grub_uint8_t *) ustr, tmp, ns) = '\0';
}
if (namespace) if (namespace)
type |= GRUB_FSHELP_CASE_INSENSITIVE; type |= GRUB_FSHELP_CASE_INSENSITIVE;
@ -639,6 +676,102 @@ list_file (struct grub_ntfs_file *diro, char *pos,
return 0; return 0;
} }
struct symlink_descriptor
{
grub_uint32_t type;
grub_uint32_t total_len;
grub_uint16_t off1;
grub_uint16_t len1;
grub_uint16_t off2;
grub_uint16_t len2;
} __attribute__ ((packed));
static char *
grub_ntfs_read_symlink (grub_fshelp_node_t node)
{
struct grub_ntfs_file *mft;
struct symlink_descriptor symdesc;
grub_err_t err;
grub_uint16_t *buf16;
char *buf, *end;
grub_size_t len;
grub_size_t i;
char *pa;
grub_size_t off;
mft = (struct grub_ntfs_file *) node;
mft->buf = grub_malloc (mft->data->mft_size << GRUB_NTFS_BLK_SHR);
if (mft->buf == NULL)
return NULL;
if (read_mft (mft->data, mft->buf, mft->ino))
return NULL;
pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_SYMLINK);
if (pa == NULL)
{
grub_error (GRUB_ERR_BAD_FS, "no $SYMLINK in MFT 0x%X", mft->ino);
return NULL;
}
err = read_attr (&mft->attr, (char *) &symdesc, 0,
sizeof (struct symlink_descriptor), 1, 0);
if (err)
return NULL;
switch (grub_cpu_to_le32 (symdesc.type))
{
case 0xa000000c:
off = (sizeof (struct symlink_descriptor) + 4
+ grub_cpu_to_le32 (symdesc.off1));
len = grub_cpu_to_le32 (symdesc.len1);
break;
case 0xa0000003:
off = (sizeof (struct symlink_descriptor)
+ grub_cpu_to_le32 (symdesc.off1));
len = grub_cpu_to_le32 (symdesc.len1);
break;
default:
grub_error (GRUB_ERR_BAD_FS, "symlink type invalid (%x)",
grub_cpu_to_le32 (symdesc.type));
return NULL;
}
buf16 = grub_malloc (len);
if (!buf16)
return NULL;
err = read_attr (&mft->attr, (char *) buf16, off, len, 1, 0);
if (err)
return NULL;
buf = grub_malloc (len * 2 + 1);
if (!buf)
{
grub_free (buf16);
return NULL;
}
for (i = 0; i < len / 2; i++)
{
buf16[i] = grub_le_to_cpu16 (buf16[i]);
if (buf16[i] == '\\')
buf16[i] = '/';
}
end = (char *) grub_utf16_to_utf8 ((grub_uint8_t *) buf, buf16, len / 2);
*end = '\0';
/* Split the sequence to avoid GCC thinking that this is a trigraph. */
if (grub_memcmp (buf, "/?" "?/", 4) == 0 && buf[5] == ':' && buf[6] == '/'
&& grub_isalpha (buf[4]))
{
grub_memmove (buf, buf + 6, end - buf + 1 - 6);
end -= 6;
}
return buf;
}
static int static int
grub_ntfs_iterate_dir (grub_fshelp_node_t dir, grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
int NESTED_FUNC_ATTR int NESTED_FUNC_ATTR
@ -668,7 +801,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
init_attr (at, mft); init_attr (at, mft);
while (1) while (1)
{ {
if ((cur_pos = find_attr (at, AT_INDEX_ROOT)) == NULL) if ((cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ROOT)) == NULL)
{ {
grub_error (GRUB_ERR_BAD_FS, "no $INDEX_ROOT"); grub_error (GRUB_ERR_BAD_FS, "no $INDEX_ROOT");
goto done; goto done;
@ -694,7 +827,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
bitmap_len = 0; bitmap_len = 0;
free_attr (at); free_attr (at);
init_attr (at, mft); init_attr (at, mft);
while ((cur_pos = find_attr (at, AT_BITMAP)) != NULL) while ((cur_pos = find_attr (at, GRUB_NTFS_AT_BITMAP)) != NULL)
{ {
int ofs; int ofs;
@ -735,7 +868,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
} }
free_attr (at); free_attr (at);
cur_pos = locate_attr (at, mft, AT_INDEX_ALLOCATION); cur_pos = locate_attr (at, mft, GRUB_NTFS_AT_INDEX_ALLOCATION);
while (cur_pos != NULL) while (cur_pos != NULL)
{ {
/* Non-resident, Namelen=4, Offset=0x40, Flags=0, Name="$I30" */ /* Non-resident, Namelen=4, Offset=0x40, Flags=0, Name="$I30" */
@ -743,7 +876,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
(u32at (cur_pos, 0x40) == 0x490024) && (u32at (cur_pos, 0x40) == 0x490024) &&
(u32at (cur_pos, 0x44) == 0x300033)) (u32at (cur_pos, 0x44) == 0x300033))
break; break;
cur_pos = find_attr (at, AT_INDEX_ALLOCATION); cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ALLOCATION);
} }
if ((!cur_pos) && (bitmap)) if ((!cur_pos) && (bitmap))
@ -756,7 +889,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
{ {
grub_disk_addr_t v, i; grub_disk_addr_t v, i;
indx = grub_malloc (mft->data->idx_size << BLK_SHR); indx = grub_malloc (mft->data->idx_size << GRUB_NTFS_BLK_SHR);
if (indx == NULL) if (indx == NULL)
goto done; goto done;
@ -766,8 +899,8 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir,
if (*bitmap & v) if (*bitmap & v)
{ {
if ((read_attr if ((read_attr
(at, indx, i * (mft->data->idx_size << BLK_SHR), (at, indx, i * (mft->data->idx_size << GRUB_NTFS_BLK_SHR),
(mft->data->idx_size << BLK_SHR), 0, 0)) (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0))
|| (fixup (mft->data, indx, mft->data->idx_size, "INDX"))) || (fixup (mft->data, indx, mft->data->idx_size, "INDX")))
goto done; goto done;
ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], hook); ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], hook);
@ -814,32 +947,32 @@ grub_ntfs_mount (grub_disk_t disk)
goto fail; goto fail;
data->blocksize = grub_le_to_cpu16 (bpb.bytes_per_sector); data->blocksize = grub_le_to_cpu16 (bpb.bytes_per_sector);
data->spc = bpb.sectors_per_cluster * (data->blocksize >> BLK_SHR); data->spc = bpb.sectors_per_cluster * (data->blocksize >> GRUB_NTFS_BLK_SHR);
if (bpb.clusters_per_mft > 0) if (bpb.clusters_per_mft > 0)
data->mft_size = data->spc * bpb.clusters_per_mft; data->mft_size = data->spc * bpb.clusters_per_mft;
else else
data->mft_size = 1 << (-bpb.clusters_per_mft - BLK_SHR); data->mft_size = 1 << (-bpb.clusters_per_mft - GRUB_NTFS_BLK_SHR);
if (bpb.clusters_per_index > 0) if (bpb.clusters_per_index > 0)
data->idx_size = data->spc * bpb.clusters_per_index; data->idx_size = data->spc * bpb.clusters_per_index;
else else
data->idx_size = 1 << (-bpb.clusters_per_index - BLK_SHR); data->idx_size = 1 << (-bpb.clusters_per_index - GRUB_NTFS_BLK_SHR);
data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) * data->spc; data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) * data->spc;
if ((data->mft_size > MAX_MFT) || (data->idx_size > MAX_IDX)) if ((data->mft_size > GRUB_NTFS_MAX_MFT) || (data->idx_size > GRUB_NTFS_MAX_IDX))
goto fail; goto fail;
data->mmft.data = data; data->mmft.data = data;
data->cmft.data = data; data->cmft.data = data;
data->mmft.buf = grub_malloc (data->mft_size << BLK_SHR); data->mmft.buf = grub_malloc (data->mft_size << GRUB_NTFS_BLK_SHR);
if (!data->mmft.buf) if (!data->mmft.buf)
goto fail; goto fail;
if (grub_disk_read if (grub_disk_read
(disk, data->mft_start, 0, data->mft_size << BLK_SHR, data->mmft.buf)) (disk, data->mft_start, 0, data->mft_size << GRUB_NTFS_BLK_SHR, data->mmft.buf))
goto fail; goto fail;
data->uuid = grub_le_to_cpu64 (bpb.num_serial); data->uuid = grub_le_to_cpu64 (bpb.num_serial);
@ -847,10 +980,10 @@ grub_ntfs_mount (grub_disk_t disk)
if (fixup (data, data->mmft.buf, data->mft_size, "FILE")) if (fixup (data, data->mmft.buf, data->mft_size, "FILE"))
goto fail; goto fail;
if (!locate_attr (&data->mmft.attr, &data->mmft, AT_DATA)) if (!locate_attr (&data->mmft.attr, &data->mmft, GRUB_NTFS_AT_DATA))
goto fail; goto fail;
if (init_file (&data->cmft, FILE_ROOT)) if (init_file (&data->cmft, GRUB_NTFS_FILE_ROOT))
goto fail; goto fail;
return data; return data;
@ -901,7 +1034,7 @@ grub_ntfs_dir (grub_device_t device, const char *path,
goto fail; goto fail;
grub_fshelp_find_file (path, &data->cmft, &fdiro, grub_ntfs_iterate_dir, grub_fshelp_find_file (path, &data->cmft, &fdiro, grub_ntfs_iterate_dir,
0, GRUB_FSHELP_DIR); grub_ntfs_read_symlink, GRUB_FSHELP_DIR);
if (grub_errno) if (grub_errno)
goto fail; goto fail;
@ -939,7 +1072,7 @@ grub_ntfs_open (grub_file_t file, const char *name)
goto fail; goto fail;
grub_fshelp_find_file (name, &data->cmft, &mft, grub_ntfs_iterate_dir, grub_fshelp_find_file (name, &data->cmft, &mft, grub_ntfs_iterate_dir,
0, GRUB_FSHELP_REG); grub_ntfs_read_symlink, GRUB_FSHELP_REG);
if (grub_errno) if (grub_errno)
goto fail; goto fail;
@ -1030,7 +1163,7 @@ grub_ntfs_label (grub_device_t device, char **label)
if (!mft->inode_read) if (!mft->inode_read)
{ {
mft->buf = grub_malloc (mft->data->mft_size << BLK_SHR); mft->buf = grub_malloc (mft->data->mft_size << GRUB_NTFS_BLK_SHR);
if (mft->buf == NULL) if (mft->buf == NULL)
goto fail; goto fail;
@ -1039,7 +1172,7 @@ grub_ntfs_label (grub_device_t device, char **label)
} }
init_attr (&mft->attr, mft); init_attr (&mft->attr, mft);
pa = find_attr (&mft->attr, AT_VOLUME_NAME); pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME);
if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10))) if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10)))
{ {
char *buf; char *buf;
@ -1048,8 +1181,14 @@ grub_ntfs_label (grub_device_t device, char **label)
len = u32at (pa, 0x10) / 2; len = u32at (pa, 0x10) / 2;
buf = grub_malloc (len * 4 + 1); buf = grub_malloc (len * 4 + 1);
pa += u16at (pa, 0x14); pa += u16at (pa, 0x14);
*grub_utf16_to_utf8 ((grub_uint8_t *) buf, (grub_uint16_t *) pa, len) = {
'\0'; grub_uint16_t tmp[len];
int i;
for (i = 0; i < len; i++)
tmp[i] = grub_le_to_cpu16 (grub_get_unaligned16 (pa + 2 * i));
*grub_utf16_to_utf8 ((grub_uint8_t *) buf, tmp, len) =
'\0';
}
*label = buf; *label = buf;
} }
@ -1087,14 +1226,15 @@ grub_ntfs_uuid (grub_device_t device, char **uuid)
if (*uuid) if (*uuid)
for (ptr = *uuid; *ptr; ptr++) for (ptr = *uuid; *ptr; ptr++)
*ptr = grub_toupper (*ptr); *ptr = grub_toupper (*ptr);
free_file (&data->mmft);
free_file (&data->cmft);
grub_free (data);
} }
else else
*uuid = NULL; *uuid = NULL;
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
grub_free (data);
return grub_errno; return grub_errno;
} }

View file

@ -21,7 +21,6 @@
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/disk.h> #include <grub/disk.h>
#include <grub/dl.h> #include <grub/dl.h>
#include <grub/fshelp.h>
#include <grub/ntfs.h> #include <grub/ntfs.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -35,7 +34,7 @@ decomp_nextvcn (struct grub_ntfs_comp *cc)
(cc->disk, (cc->disk,
(cc->comp_table[cc->comp_head][1] - (cc->comp_table[cc->comp_head][1] -
(cc->comp_table[cc->comp_head][0] - cc->cbuf_vcn)) * cc->spc, 0, (cc->comp_table[cc->comp_head][0] - cc->cbuf_vcn)) * cc->spc, 0,
cc->spc << BLK_SHR, cc->cbuf)) cc->spc << GRUB_NTFS_BLK_SHR, cc->cbuf))
return grub_errno; return grub_errno;
cc->cbuf_vcn++; cc->cbuf_vcn++;
if ((cc->cbuf_vcn >= cc->comp_table[cc->comp_head][0])) if ((cc->cbuf_vcn >= cc->comp_table[cc->comp_head][0]))
@ -47,7 +46,7 @@ decomp_nextvcn (struct grub_ntfs_comp *cc)
static grub_err_t static grub_err_t
decomp_getch (struct grub_ntfs_comp *cc, unsigned char *res) decomp_getch (struct grub_ntfs_comp *cc, unsigned char *res)
{ {
if (cc->cbuf_ofs >= (cc->spc << BLK_SHR)) if (cc->cbuf_ofs >= (cc->spc << GRUB_NTFS_BLK_SHR))
{ {
if (decomp_nextvcn (cc)) if (decomp_nextvcn (cc))
return grub_errno; return grub_errno;
@ -87,7 +86,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest)
bits = copied = tag = 0; bits = copied = tag = 0;
while (cnt > 0) while (cnt > 0)
{ {
if (copied > COM_LEN) if (copied > GRUB_NTFS_COM_LEN)
return grub_error (GRUB_ERR_BAD_FS, return grub_error (GRUB_ERR_BAD_FS,
"compression block too large"); "compression block too large");
@ -150,7 +149,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest)
} }
else else
{ {
if (cnt != COM_LEN) if (cnt != GRUB_NTFS_COM_LEN)
return grub_error (GRUB_ERR_BAD_FS, return grub_error (GRUB_ERR_BAD_FS,
"invalid compression block size"); "invalid compression block size");
} }
@ -160,7 +159,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest)
{ {
int n; int n;
n = (cc->spc << BLK_SHR) - cc->cbuf_ofs; n = (cc->spc << GRUB_NTFS_BLK_SHR) - cc->cbuf_ofs;
if (n > cnt) if (n > cnt)
n = cnt; n = cnt;
if ((dest) && (n)) if ((dest) && (n))
@ -179,7 +178,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest)
static grub_err_t static grub_err_t
read_block (struct grub_ntfs_rlst *ctx, char *buf, int num) read_block (struct grub_ntfs_rlst *ctx, char *buf, int num)
{ {
int cpb = COM_SEC / ctx->comp.spc; int cpb = GRUB_NTFS_COM_SEC / ctx->comp.spc;
while (num) while (num)
{ {
@ -192,7 +191,7 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, int num)
return grub_error (GRUB_ERR_BAD_FS, "invalid compression block"); return grub_error (GRUB_ERR_BAD_FS, "invalid compression block");
ctx->comp.comp_head = ctx->comp.comp_tail = 0; ctx->comp.comp_head = ctx->comp.comp_tail = 0;
ctx->comp.cbuf_vcn = ctx->target_vcn; ctx->comp.cbuf_vcn = ctx->target_vcn;
ctx->comp.cbuf_ofs = (ctx->comp.spc << BLK_SHR); ctx->comp.cbuf_ofs = (ctx->comp.spc << GRUB_NTFS_BLK_SHR);
if (ctx->target_vcn >= ctx->next_vcn) if (ctx->target_vcn >= ctx->next_vcn)
{ {
if (grub_ntfs_read_run_list (ctx)) if (grub_ntfs_read_run_list (ctx))
@ -200,7 +199,7 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, int num)
} }
while (ctx->target_vcn + 16 > ctx->next_vcn) while (ctx->target_vcn + 16 > ctx->next_vcn)
{ {
if (ctx->flags & RF_BLNK) if (ctx->flags & GRUB_NTFS_RF_BLNK)
break; break;
ctx->comp.comp_table[ctx->comp.comp_tail][0] = ctx->next_vcn; ctx->comp.comp_table[ctx->comp.comp_tail][0] = ctx->next_vcn;
ctx->comp.comp_table[ctx->comp.comp_tail][1] = ctx->comp.comp_table[ctx->comp.comp_tail][1] =
@ -216,15 +215,15 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, int num)
nn = num; nn = num;
num -= nn; num -= nn;
if (ctx->flags & RF_BLNK) if (ctx->flags & GRUB_NTFS_RF_BLNK)
{ {
ctx->target_vcn += nn * cpb; ctx->target_vcn += nn * cpb;
if (ctx->comp.comp_tail == 0) if (ctx->comp.comp_tail == 0)
{ {
if (buf) if (buf)
{ {
grub_memset (buf, 0, nn * COM_LEN); grub_memset (buf, 0, nn * GRUB_NTFS_COM_LEN);
buf += nn * COM_LEN; buf += nn * GRUB_NTFS_COM_LEN;
} }
} }
else else
@ -234,7 +233,7 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, int num)
if (decomp_block (&ctx->comp, buf)) if (decomp_block (&ctx->comp, buf))
return grub_errno; return grub_errno;
if (buf) if (buf)
buf += COM_LEN; buf += GRUB_NTFS_COM_LEN;
nn--; nn--;
} }
} }
@ -259,9 +258,9 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, int num)
(ctx->comp.comp_table[ctx->comp.comp_head][1] - (ctx->comp.comp_table[ctx->comp.comp_head][1] -
(ctx->comp.comp_table[ctx->comp.comp_head][0] - (ctx->comp.comp_table[ctx->comp.comp_head][0] -
ctx->target_vcn)) * ctx->comp.spc, 0, ctx->target_vcn)) * ctx->comp.spc, 0,
tt * (ctx->comp.spc << BLK_SHR), buf)) tt * (ctx->comp.spc << GRUB_NTFS_BLK_SHR), buf))
return grub_errno; return grub_errno;
buf += tt * (ctx->comp.spc << BLK_SHR); buf += tt * (ctx->comp.spc << GRUB_NTFS_BLK_SHR);
} }
nn -= tt; nn -= tt;
if (ctx->target_vcn >= if (ctx->target_vcn >=
@ -276,9 +275,9 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, int num)
(ctx->comp.disk, (ctx->comp.disk,
(ctx->target_vcn - ctx->curr_vcn + (ctx->target_vcn - ctx->curr_vcn +
ctx->curr_lcn) * ctx->comp.spc, 0, ctx->curr_lcn) * ctx->comp.spc, 0,
nn * (ctx->comp.spc << BLK_SHR), buf)) nn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR), buf))
return grub_errno; return grub_errno;
buf += nn * (ctx->comp.spc << BLK_SHR); buf += nn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR);
} }
ctx->target_vcn += nn; ctx->target_vcn += nn;
} }
@ -294,7 +293,7 @@ ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_uint32_t ofs,
grub_err_t ret; grub_err_t ret;
ctx->comp.comp_head = ctx->comp.comp_tail = 0; ctx->comp.comp_head = ctx->comp.comp_tail = 0;
ctx->comp.cbuf = grub_malloc ((ctx->comp.spc) << BLK_SHR); ctx->comp.cbuf = grub_malloc ((ctx->comp.spc) << GRUB_NTFS_BLK_SHR);
if (!ctx->comp.cbuf) if (!ctx->comp.cbuf)
return 0; return 0;
@ -304,17 +303,17 @@ ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_uint32_t ofs,
if ((vcn > ctx->target_vcn) && if ((vcn > ctx->target_vcn) &&
(read_block (read_block
(ctx, NULL, ((vcn - ctx->target_vcn) * ctx->comp.spc) / COM_SEC))) (ctx, NULL, ((vcn - ctx->target_vcn) * ctx->comp.spc) / GRUB_NTFS_COM_SEC)))
{ {
ret = grub_errno; ret = grub_errno;
goto quit; goto quit;
} }
if (ofs % COM_LEN) if (ofs % GRUB_NTFS_COM_LEN)
{ {
grub_uint32_t t, n, o; grub_uint32_t t, n, o;
t = ctx->target_vcn * (ctx->comp.spc << BLK_SHR); t = ctx->target_vcn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR);
if (read_block (ctx, at->sbuf, 1)) if (read_block (ctx, at->sbuf, 1))
{ {
ret = grub_errno; ret = grub_errno;
@ -323,8 +322,8 @@ ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_uint32_t ofs,
at->save_pos = t; at->save_pos = t;
o = ofs % COM_LEN; o = ofs % GRUB_NTFS_COM_LEN;
n = COM_LEN - o; n = GRUB_NTFS_COM_LEN - o;
if (n > len) if (n > len)
n = len; n = len;
grub_memcpy (dest, &at->sbuf[o], n); grub_memcpy (dest, &at->sbuf[o], n);
@ -334,19 +333,19 @@ ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_uint32_t ofs,
len -= n; len -= n;
} }
if (read_block (ctx, dest, len / COM_LEN)) if (read_block (ctx, dest, len / GRUB_NTFS_COM_LEN))
{ {
ret = grub_errno; ret = grub_errno;
goto quit; goto quit;
} }
dest += (len / COM_LEN) * COM_LEN; dest += (len / GRUB_NTFS_COM_LEN) * GRUB_NTFS_COM_LEN;
len = len % COM_LEN; len = len % GRUB_NTFS_COM_LEN;
if (len) if (len)
{ {
grub_uint32_t t; grub_uint32_t t;
t = ctx->target_vcn * (ctx->comp.spc << BLK_SHR); t = ctx->target_vcn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR);
if (read_block (ctx, at->sbuf, 1)) if (read_block (ctx, at->sbuf, 1))
{ {
ret = grub_errno; ret = grub_errno;

View file

@ -57,8 +57,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
#define REISERFS_MAGIC_DESC_BLOCK "ReIsErLB" #define REISERFS_MAGIC_DESC_BLOCK "ReIsErLB"
/* If the 3rd bit of an item state is set, then it's visible. */ /* If the 3rd bit of an item state is set, then it's visible. */
#define GRUB_REISERFS_VISIBLE_MASK ((grub_uint16_t) 0x04) #define GRUB_REISERFS_VISIBLE_MASK ((grub_uint16_t) 0x04)
#define REISERFS_MAX_LABEL_LENGTH 16
#define REISERFS_LABEL_OFFSET 0x64
#define S_IFLNK 0xA000 #define S_IFLNK 0xA000
@ -109,6 +107,7 @@ struct grub_reiserfs_superblock
grub_uint32_t inode_generation; grub_uint32_t inode_generation;
grub_uint8_t unused[4]; grub_uint8_t unused[4];
grub_uint16_t uuid[8]; grub_uint16_t uuid[8];
char label[16];
} __attribute__ ((packed)); } __attribute__ ((packed));
struct grub_reiserfs_journal_header struct grub_reiserfs_journal_header
@ -1323,14 +1322,24 @@ grub_reiserfs_dir (grub_device_t device, const char *path,
static grub_err_t static grub_err_t
grub_reiserfs_label (grub_device_t device, char **label) grub_reiserfs_label (grub_device_t device, char **label)
{ {
*label = grub_malloc (REISERFS_MAX_LABEL_LENGTH); struct grub_reiserfs_data *data;
if (*label) grub_disk_t disk = device->disk;
grub_dl_ref (my_mod);
data = grub_reiserfs_mount (disk);
if (data)
{ {
grub_disk_read (device->disk, *label = grub_strndup (data->superblock.label,
REISERFS_SUPER_BLOCK_OFFSET / GRUB_DISK_SECTOR_SIZE, sizeof (data->superblock.label));
REISERFS_LABEL_OFFSET, REISERFS_MAX_LABEL_LENGTH,
*label);
} }
else
*label = NULL;
grub_dl_unref (my_mod);
grub_free (data);
return grub_errno; return grub_errno;
} }

View file

@ -112,7 +112,7 @@ grub_romfs_mount (grub_device_t dev)
if (err) if (err)
return NULL; return NULL;
for (ptr = sb.sb.label; (void *) ptr < (void *) (&sb + 1) for (ptr = sb.sb.label; (void *) ptr < (void *) (&sb + 1)
&& ptr < sb.d + grub_be_to_cpu32 (sb.sb.total_size); ptr++) && ptr - sb.d < (grub_ssize_t) grub_be_to_cpu32 (sb.sb.total_size); ptr++)
if (!*ptr) if (!*ptr)
break; break;
if ((void *) ptr == &sb + 1) if ((void *) ptr == &sb + 1)
@ -124,7 +124,7 @@ grub_romfs_mount (grub_device_t dev)
if (err) if (err)
return NULL; return NULL;
for (ptr = sb.d; (void *) ptr < (void *) (&sb + 1) for (ptr = sb.d; (void *) ptr < (void *) (&sb + 1)
&& ptr < sb.d + grub_be_to_cpu32 (sb.sb.total_size); ptr++) && ptr - sb.d < (grub_ssize_t) grub_be_to_cpu32 (sb.sb.total_size); ptr++)
if (!*ptr) if (!*ptr)
break; break;
} }
@ -166,17 +166,18 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir,
{ {
grub_disk_addr_t caddr; grub_disk_addr_t caddr;
struct grub_romfs_file_header hdr; struct grub_romfs_file_header hdr;
grub_size_t a = 0;
char *name = NULL;
unsigned nptr; unsigned nptr;
unsigned i, j; unsigned i, j;
grub_size_t a = 0;
grub_properly_aligned_t *name = NULL;
for (caddr = dir->data_addr; caddr; for (caddr = dir->data_addr; caddr;
caddr = grub_be_to_cpu32 (hdr.next_file) & ~(GRUB_ROMFS_ALIGN - 1)) caddr = grub_be_to_cpu32 (hdr.next_file) & ~(GRUB_ROMFS_ALIGN - 1))
{ {
grub_disk_addr_t naddr = caddr + sizeof (hdr); grub_disk_addr_t naddr = caddr + sizeof (hdr);
grub_uint32_t csum = 0; grub_uint32_t csum = 0;
enum grub_fshelp_filetype filetype = GRUB_FSHELP_UNKNOWN; enum grub_fshelp_filetype filetype = GRUB_FSHELP_UNKNOWN;
struct grub_fshelp_node *node; struct grub_fshelp_node *node = NULL;
grub_err_t err; grub_err_t err;
err = grub_disk_read (dir->data->disk, caddr >> GRUB_DISK_SECTOR_BITS, err = grub_disk_read (dir->data->disk, caddr >> GRUB_DISK_SECTOR_BITS,
@ -189,9 +190,9 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir,
} }
for (nptr = 0; ; nptr++, naddr += 16) for (nptr = 0; ; nptr++, naddr += 16)
{ {
if (a >= nptr) if (a <= nptr)
{ {
char *on; grub_properly_aligned_t *on;
a = 2 * (nptr + 1); a = 2 * (nptr + 1);
on = name; on = name;
name = grub_realloc (name, a * 16); name = grub_realloc (name, a * 16);
@ -201,13 +202,14 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir,
return 1; return 1;
} }
} }
COMPILE_TIME_ASSERT (16 % sizeof (name[0]) == 0);
err = grub_disk_read (dir->data->disk, naddr >> GRUB_DISK_SECTOR_BITS, err = grub_disk_read (dir->data->disk, naddr >> GRUB_DISK_SECTOR_BITS,
naddr & (GRUB_DISK_SECTOR_SIZE - 1), naddr & (GRUB_DISK_SECTOR_SIZE - 1),
16, name + 16 * nptr); 16, name + (16 / sizeof (name[0])) * nptr);
if (err) if (err)
return 1; return 1;
for (j = 0; j < 16; j++) for (j = 0; j < 16; j++)
if (!name[16 * nptr + j]) if (!((char *) name)[16 * nptr + j])
break; break;
if (j != 16) if (j != 16)
break; break;
@ -292,7 +294,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir,
} }
} }
if (hook (name, filetype, node)) if (hook ((char *) name, filetype, node))
{ {
grub_free (name); grub_free (name);
return 1; return 1;
@ -367,6 +369,7 @@ grub_romfs_open (struct grub_file *file, const char *name)
file->size = grub_be_to_cpu32 (fdiro->file.size); file->size = grub_be_to_cpu32 (fdiro->file.size);
file->data = fdiro; file->data = fdiro;
return GRUB_ERR_NONE;
fail: fail:
grub_free (data); grub_free (data);
@ -396,7 +399,10 @@ grub_romfs_read (grub_file_t file, char *buf, grub_size_t len)
static grub_err_t static grub_err_t
grub_romfs_close (grub_file_t file) grub_romfs_close (grub_file_t file)
{ {
grub_free (file->data); struct grub_fshelp_node *data = file->data;
grub_free (data->data);
grub_free (data);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -431,6 +437,7 @@ grub_romfs_label (grub_device_t device, char **label)
return err; return err;
} }
(*label)[data->first_file - sizeof (struct grub_romfs_superblock)] = 0; (*label)[data->first_file - sizeof (struct grub_romfs_superblock)] = 0;
grub_free (data);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }

View file

@ -250,7 +250,7 @@ static grub_ssize_t
grub_sfs_read_file (grub_fshelp_node_t node, grub_sfs_read_file (grub_fshelp_node_t node,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length), unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf) grub_off_t pos, grub_size_t len, char *buf)
{ {
return grub_fshelp_read_file (node->data->disk, node, read_hook, return grub_fshelp_read_file (node->data->disk, node, read_hook,
pos, len, buf, grub_sfs_read_block, pos, len, buf, grub_sfs_read_block,

View file

@ -42,7 +42,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
exttblptr RAW superblock exttblptr RAW superblock
UID/GID table is the array ot uint32_t UID/GID table is the array ot uint32_t
unk1 contains pointer to unk3 followed by some chunk. unk1 contains pointer to fragment table followed by some chunk.
unk2 containts one uint64_t unk2 containts one uint64_t
*/ */
@ -52,13 +52,9 @@ struct grub_squash_super
#define SQUASH_MAGIC 0x73717368 #define SQUASH_MAGIC 0x73717368
grub_uint32_t dummy1; grub_uint32_t dummy1;
grub_uint32_t creation_time; grub_uint32_t creation_time;
grub_uint32_t dummy2; grub_uint32_t block_size;
grub_uint64_t dummy3; grub_uint64_t dummy3;
grub_uint8_t flags; grub_uint64_t dummy4;
#define SQUASH_FLAG_UNCOMPRESSED_INODES 1
#define SQUASH_FLAG_UNCOMPRESSED_DATA 2
#define SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS 8
grub_uint8_t dummy4[7];
grub_uint16_t root_ino_offset; grub_uint16_t root_ino_offset;
grub_uint32_t root_ino_chunk; grub_uint32_t root_ino_chunk;
grub_uint16_t dummy5; grub_uint16_t dummy5;
@ -71,7 +67,6 @@ struct grub_squash_super
grub_uint64_t unk2offset; grub_uint64_t unk2offset;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* Chunk-based */ /* Chunk-based */
struct grub_squash_inode struct grub_squash_inode
{ {
@ -85,16 +80,30 @@ struct grub_squash_inode
grub_uint32_t dummy; grub_uint32_t dummy;
grub_uint32_t chunk; grub_uint32_t chunk;
grub_uint32_t fragment; grub_uint32_t fragment;
grub_uint32_t offset; grub_uint16_t offset;
grub_uint16_t dummy2;
grub_uint32_t size; grub_uint32_t size;
grub_uint32_t block_size[0];
} __attribute__ ((packed)) file; } __attribute__ ((packed)) file;
struct {
grub_uint32_t dummy;
grub_uint64_t chunk;
grub_uint64_t size;
grub_uint32_t dummy2[3];
grub_uint32_t fragment;
grub_uint16_t offset;
grub_uint16_t dummy3;
grub_uint32_t dummy4;
grub_uint32_t block_size[0];
} __attribute__ ((packed)) long_file;
struct { struct {
grub_uint32_t dummy1; grub_uint32_t dummy1;
grub_uint32_t chunk; grub_uint32_t chunk;
grub_uint32_t dummy2; grub_uint32_t dummy2;
grub_uint16_t size; grub_uint16_t size;
grub_uint32_t offset; grub_uint16_t offset;
grub_uint16_t dummy3; grub_uint16_t dummy3;
grub_uint16_t dummy4;
} __attribute__ ((packed)) dir; } __attribute__ ((packed)) dir;
struct { struct {
grub_uint64_t dummy; grub_uint64_t dummy;
@ -104,12 +113,22 @@ struct grub_squash_inode
} __attribute__ ((packed)); } __attribute__ ((packed));
} __attribute__ ((packed)); } __attribute__ ((packed));
struct grub_squash_cache_inode
{
struct grub_squash_inode ino;
grub_disk_addr_t ino_chunk;
grub_uint16_t ino_offset;
grub_uint32_t *block_sizes;
grub_disk_addr_t *cumulated_block_sizes;
};
/* Chunk-based. */ /* Chunk-based. */
struct grub_squash_dirent_header struct grub_squash_dirent_header
{ {
/* Actually the value is the number of elements - 1. */ /* Actually the value is the number of elements - 1. */
grub_uint32_t nelems; grub_uint32_t nelems;
grub_uint64_t ino_chunk; grub_uint32_t ino_chunk;
grub_uint32_t dummy;
} __attribute__ ((packed)); } __attribute__ ((packed));
struct grub_squash_dirent struct grub_squash_dirent
@ -117,46 +136,62 @@ struct grub_squash_dirent
grub_uint16_t ino_offset; grub_uint16_t ino_offset;
grub_uint16_t dummy; grub_uint16_t dummy;
grub_uint16_t type; grub_uint16_t type;
#define SQUASH_TYPE_DIR 1
#define SQUASH_TYPE_REGULAR 2
#define SQUASH_TYPE_SYMLINK 3
/* Actually the value is the length of name - 1. */ /* Actually the value is the length of name - 1. */
grub_uint16_t namelen; grub_uint16_t namelen;
char name[0]; char name[0];
} __attribute__ ((packed)); } __attribute__ ((packed));
enum
{
SQUASH_TYPE_DIR = 1,
SQUASH_TYPE_REGULAR = 2,
SQUASH_TYPE_SYMLINK = 3,
SQUASH_TYPE_LONG_REGULAR = 9,
};
struct grub_squash_frag_desc struct grub_squash_frag_desc
{ {
grub_uint64_t offset; grub_uint64_t offset;
grub_uint64_t dummy; grub_uint32_t size;
grub_uint32_t dummy;
} __attribute__ ((packed)); } __attribute__ ((packed));
enum
{
SQUASH_CHUNK_FLAGS = 0x8000,
SQUASH_CHUNK_UNCOMPRESSED = 0x8000
};
enum
{
SQUASH_BLOCK_FLAGS = 0x1000000,
SQUASH_BLOCK_UNCOMPRESSED = 0x1000000
};
#define SQUASH_CHUNK_SIZE 0x2000 #define SQUASH_CHUNK_SIZE 0x2000
#define SQUASH_CHUNK_FLAGS 0x8000
#define SQUASH_CHUNK_UNCOMPRESSED 0x8000
struct grub_squash_data struct grub_squash_data
{ {
grub_disk_t disk; grub_disk_t disk;
struct grub_squash_super sb; struct grub_squash_super sb;
struct grub_squash_inode ino; struct grub_squash_cache_inode ino;
grub_uint64_t fragments; grub_uint64_t fragments;
int log2_blksz;
}; };
struct grub_fshelp_node struct grub_fshelp_node
{ {
struct grub_squash_data *data; struct grub_squash_data *data;
struct grub_squash_inode ino; struct grub_squash_inode ino;
grub_uint32_t ino_chunk; grub_disk_addr_t ino_chunk;
grub_uint16_t ino_offset; grub_uint16_t ino_offset;
}; };
static grub_err_t static grub_err_t
read_chunk (grub_disk_t disk, void *buf, grub_size_t len, read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len,
grub_uint64_t chunk, grub_off_t offset) grub_uint64_t chunk_start, grub_off_t offset)
{ {
grub_uint64_t chunk_start;
chunk_start = grub_le_to_cpu64 (chunk);
while (len > 0) while (len > 0)
{ {
grub_uint64_t csize; grub_uint64_t csize;
@ -164,7 +199,8 @@ read_chunk (grub_disk_t disk, void *buf, grub_size_t len,
grub_err_t err; grub_err_t err;
while (1) while (1)
{ {
err = grub_disk_read (disk, chunk_start >> GRUB_DISK_SECTOR_BITS, err = grub_disk_read (data->disk,
chunk_start >> GRUB_DISK_SECTOR_BITS,
chunk_start & (GRUB_DISK_SECTOR_SIZE - 1), chunk_start & (GRUB_DISK_SECTOR_SIZE - 1),
sizeof (d), &d); sizeof (d), &d);
if (err) if (err)
@ -182,7 +218,7 @@ read_chunk (grub_disk_t disk, void *buf, grub_size_t len,
if (grub_le_to_cpu16 (d) & SQUASH_CHUNK_UNCOMPRESSED) if (grub_le_to_cpu16 (d) & SQUASH_CHUNK_UNCOMPRESSED)
{ {
grub_disk_addr_t a = chunk_start + 2 + offset; grub_disk_addr_t a = chunk_start + 2 + offset;
err = grub_disk_read (disk, (a >> GRUB_DISK_SECTOR_BITS), err = grub_disk_read (data->disk, (a >> GRUB_DISK_SECTOR_BITS),
a & (GRUB_DISK_SECTOR_SIZE - 1), a & (GRUB_DISK_SECTOR_SIZE - 1),
csize, buf); csize, buf);
if (err) if (err)
@ -197,7 +233,7 @@ read_chunk (grub_disk_t disk, void *buf, grub_size_t len,
if (!tmp) if (!tmp)
return grub_errno; return grub_errno;
/* FIXME: buffer uncompressed data. */ /* FIXME: buffer uncompressed data. */
err = grub_disk_read (disk, (a >> GRUB_DISK_SECTOR_BITS), err = grub_disk_read (data->disk, (a >> GRUB_DISK_SECTOR_BITS),
a & (GRUB_DISK_SECTOR_SIZE - 1), a & (GRUB_DISK_SECTOR_SIZE - 1),
bsize, tmp); bsize, tmp);
if (err) if (err)
@ -234,27 +270,35 @@ squash_mount (grub_disk_t disk)
grub_error (GRUB_ERR_BAD_FS, "not a squash4"); grub_error (GRUB_ERR_BAD_FS, "not a squash4");
if (err) if (err)
return NULL; return NULL;
if (grub_le_to_cpu32 (sb.magic) != SQUASH_MAGIC) if (grub_le_to_cpu32 (sb.magic) != SQUASH_MAGIC
|| grub_le_to_cpu32 (sb.block_size) == 0
|| ((grub_le_to_cpu32 (sb.block_size) - 1)
& grub_le_to_cpu32 (sb.block_size)))
{ {
grub_error (GRUB_ERR_BAD_FS, "not squash4"); grub_error (GRUB_ERR_BAD_FS, "not squash4");
return NULL; return NULL;
} }
err = grub_disk_read (disk, grub_le_to_cpu32 (sb.unk1offset) err = grub_disk_read (disk,
grub_le_to_cpu64 (sb.unk1offset)
>> GRUB_DISK_SECTOR_BITS, >> GRUB_DISK_SECTOR_BITS,
grub_le_to_cpu32 (sb.unk1offset) grub_le_to_cpu64 (sb.unk1offset)
& (GRUB_DISK_SECTOR_SIZE - 1), sizeof (frag), &frag); & (GRUB_DISK_SECTOR_SIZE - 1), sizeof (frag), &frag);
if (grub_errno == GRUB_ERR_OUT_OF_RANGE) if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
grub_error (GRUB_ERR_BAD_FS, "not a squash4"); grub_error (GRUB_ERR_BAD_FS, "not a squash4");
if (err) if (err)
return NULL; return NULL;
data = grub_malloc (sizeof (*data)); data = grub_zalloc (sizeof (*data));
if (!data) if (!data)
return NULL; return NULL;
data->sb = sb; data->sb = sb;
data->disk = disk; data->disk = disk;
data->fragments = frag; data->fragments = grub_le_to_cpu64 (frag);
for (data->log2_blksz = 0;
(1U << data->log2_blksz) < grub_le_to_cpu32 (data->sb.block_size);
data->log2_blksz++);
return data; return data;
} }
@ -266,7 +310,7 @@ grub_squash_read_symlink (grub_fshelp_node_t node)
grub_err_t err; grub_err_t err;
ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1); ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1);
err = read_chunk (node->data->disk, ret, err = read_chunk (node->data, ret,
grub_le_to_cpu32 (node->ino.symlink.namelen), grub_le_to_cpu32 (node->ino.symlink.namelen),
grub_le_to_cpu64 (node->data->sb.inodeoffset) grub_le_to_cpu64 (node->data->sb.inodeoffset)
+ node->ino_chunk, + node->ino_chunk,
@ -293,20 +337,20 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
unsigned i; unsigned i;
/* FIXME: why - 3 ? */ /* FIXME: why - 3 ? */
endoff = grub_le_to_cpu32 (dir->ino.dir.size) + off - 3; endoff = grub_le_to_cpu16 (dir->ino.dir.size) + off - 3;
while (off < endoff) while (off < endoff)
{ {
struct grub_squash_dirent_header dh; struct grub_squash_dirent_header dh;
grub_err_t err; grub_err_t err;
err = read_chunk (dir->data->disk, &dh, sizeof (dh), err = read_chunk (dir->data, &dh, sizeof (dh),
grub_le_to_cpu64 (dir->data->sb.diroffset) grub_le_to_cpu64 (dir->data->sb.diroffset)
+ grub_le_to_cpu32 (dir->ino.dir.chunk), off); + grub_le_to_cpu32 (dir->ino.dir.chunk), off);
if (err) if (err)
return 0; return 0;
off += sizeof (dh); off += sizeof (dh);
for (i = 0; i < (unsigned) grub_le_to_cpu16 (dh.nelems) + 1; i++) for (i = 0; i < (unsigned) grub_le_to_cpu32 (dh.nelems) + 1; i++)
{ {
char *buf; char *buf;
int r; int r;
@ -315,14 +359,14 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
struct grub_squash_dirent di; struct grub_squash_dirent di;
struct grub_squash_inode ino; struct grub_squash_inode ino;
err = read_chunk (dir->data->disk, &di, sizeof (di), err = read_chunk (dir->data, &di, sizeof (di),
grub_le_to_cpu64 (dir->data->sb.diroffset) grub_le_to_cpu64 (dir->data->sb.diroffset)
+ grub_le_to_cpu32 (dir->ino.dir.chunk), off); + grub_le_to_cpu32 (dir->ino.dir.chunk), off);
if (err) if (err)
return 0; return 0;
off += sizeof (di); off += sizeof (di);
err = read_chunk (dir->data->disk, &ino, sizeof (ino), err = read_chunk (dir->data, &ino, sizeof (ino),
grub_le_to_cpu64 (dir->data->sb.inodeoffset) grub_le_to_cpu64 (dir->data->sb.inodeoffset)
+ grub_le_to_cpu32 (dh.ino_chunk), + grub_le_to_cpu32 (dh.ino_chunk),
grub_cpu_to_le16 (di.ino_offset)); grub_cpu_to_le16 (di.ino_offset));
@ -332,7 +376,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir,
buf = grub_malloc (grub_le_to_cpu16 (di.namelen) + 2); buf = grub_malloc (grub_le_to_cpu16 (di.namelen) + 2);
if (!buf) if (!buf)
return 0; return 0;
err = read_chunk (dir->data->disk, buf, err = read_chunk (dir->data, buf,
grub_le_to_cpu16 (di.namelen) + 1, grub_le_to_cpu16 (di.namelen) + 1,
grub_le_to_cpu64 (dir->data->sb.diroffset) grub_le_to_cpu64 (dir->data->sb.diroffset)
+ grub_le_to_cpu32 (dir->ino.dir.chunk), off); + grub_le_to_cpu32 (dir->ino.dir.chunk), off);
@ -370,12 +414,21 @@ make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root)
grub_memset (root, 0, sizeof (*root)); grub_memset (root, 0, sizeof (*root));
root->data = data; root->data = data;
return read_chunk (data->disk, &root->ino, sizeof (root->ino), return read_chunk (data, &root->ino, sizeof (root->ino),
grub_le_to_cpu64 (data->sb.inodeoffset) grub_le_to_cpu64 (data->sb.inodeoffset)
+ grub_le_to_cpu16 (data->sb.root_ino_chunk), + grub_le_to_cpu16 (data->sb.root_ino_chunk),
grub_cpu_to_le16 (data->sb.root_ino_offset)); grub_cpu_to_le16 (data->sb.root_ino_offset));
} }
static void
squash_unmount (struct grub_squash_data *data)
{
grub_free (data->ino.cumulated_block_sizes);
grub_free (data->ino.block_sizes);
grub_free (data);
}
static grub_err_t static grub_err_t
grub_squash_dir (grub_device_t device, const char *path, grub_squash_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename, int (*hook) (const char *filename,
@ -394,6 +447,7 @@ grub_squash_dir (grub_device_t device, const char *path,
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
info.mtimeset = 1; info.mtimeset = 1;
info.mtime = grub_le_to_cpu32 (node->ino.mtime); info.mtime = grub_le_to_cpu32 (node->ino.mtime);
grub_free (node);
return hook (filename, &info); return hook (filename, &info);
} }
@ -415,7 +469,7 @@ grub_squash_dir (grub_device_t device, const char *path,
if (!grub_errno) if (!grub_errno)
grub_squash_iterate_dir (fdiro, iterate); grub_squash_iterate_dir (fdiro, iterate);
grub_free (data); squash_unmount (data);
return grub_errno; return grub_errno;
} }
@ -440,53 +494,173 @@ grub_squash_open (struct grub_file *file, const char *name)
grub_squash_read_symlink, GRUB_FSHELP_REG); grub_squash_read_symlink, GRUB_FSHELP_REG);
if (grub_errno) if (grub_errno)
{ {
grub_free (data); squash_unmount (data);
return grub_errno; return grub_errno;
} }
file->data = data; file->data = data;
data->ino = fdiro->ino; data->ino.ino = fdiro->ino;
file->size = grub_le_to_cpu32 (fdiro->ino.file.size); data->ino.block_sizes = NULL;
data->ino.cumulated_block_sizes = NULL;
data->ino.ino_chunk = fdiro->ino_chunk;
data->ino.ino_offset = fdiro->ino_offset;
if (fdiro->ino.type
== grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR))
file->size = grub_le_to_cpu64 (fdiro->ino.long_file.size);
else
file->size = grub_le_to_cpu32 (fdiro->ino.file.size);
grub_free (fdiro);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
static grub_ssize_t
direct_read (struct grub_squash_data *data,
struct grub_squash_cache_inode *ino,
grub_off_t off, char *buf, grub_size_t len)
{
grub_err_t err;
grub_off_t cumulated_uncompressed_size = 0;
grub_uint64_t a;
grub_size_t i;
grub_size_t origlen = len;
if (ino->ino.type == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR))
a = grub_le_to_cpu64 (ino->ino.long_file.chunk);
else
a = grub_le_to_cpu32 (ino->ino.file.chunk);
if (!ino->block_sizes)
{
grub_off_t total_size;
grub_size_t total_blocks;
grub_size_t block_offset;
if (ino->ino.type
== grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR))
{
total_size = grub_le_to_cpu64 (ino->ino.long_file.size);
block_offset = ((char *) &ino->ino.long_file.block_size
- (char *) &ino->ino);
}
else
{
total_size = grub_le_to_cpu32 (ino->ino.file.size);
block_offset = ((char *) &ino->ino.file.block_size
- (char *) &ino->ino);
}
total_blocks = ((total_size
+ grub_le_to_cpu32 (data->sb.block_size) - 1)
>> data->log2_blksz);
ino->block_sizes = grub_malloc (total_blocks
* sizeof (ino->block_sizes[0]));
ino->cumulated_block_sizes = grub_malloc (total_blocks
* sizeof (ino->cumulated_block_sizes[0]));
if (!ino->block_sizes || !ino->cumulated_block_sizes)
{
grub_free (ino->block_sizes);
grub_free (ino->cumulated_block_sizes);
ino->block_sizes = 0;
ino->cumulated_block_sizes = 0;
return -1;
}
err = read_chunk (data, ino->block_sizes,
total_blocks * sizeof (ino->block_sizes[0]),
grub_le_to_cpu64 (data->sb.inodeoffset)
+ ino->ino_chunk,
ino->ino_offset + block_offset);
if (err)
{
grub_free (ino->block_sizes);
grub_free (ino->cumulated_block_sizes);
ino->block_sizes = 0;
ino->cumulated_block_sizes = 0;
return -1;
}
ino->cumulated_block_sizes[0] = 0;
for (i = 1; i < total_blocks; i++)
ino->cumulated_block_sizes[i] = ino->cumulated_block_sizes[i - 1]
+ (grub_le_to_cpu32 (ino->block_sizes[i - 1]) & ~SQUASH_BLOCK_FLAGS);
}
if (a == 0)
a = sizeof (struct grub_squash_super);
i = off >> data->log2_blksz;
cumulated_uncompressed_size = grub_le_to_cpu32 (data->sb.block_size)
* (grub_disk_addr_t) i;
while (cumulated_uncompressed_size < off + len)
{
grub_size_t boff, read;
boff = off - cumulated_uncompressed_size;
read = grub_le_to_cpu32 (data->sb.block_size) - boff;
if (read > len)
read = len;
if (!(ino->block_sizes[i]
& grub_cpu_to_le32_compile_time (SQUASH_BLOCK_UNCOMPRESSED)))
err = grub_zlib_disk_read (data->disk,
ino->cumulated_block_sizes[i] + a,
boff, buf, read);
else
err = grub_disk_read (data->disk,
(ino->cumulated_block_sizes[i] + a + boff)
>> GRUB_DISK_SECTOR_BITS,
(ino->cumulated_block_sizes[i] + a + boff)
& (GRUB_DISK_SECTOR_SIZE - 1),
read, buf);
if (err)
return -1;
off += read;
len -= read;
buf += read;
cumulated_uncompressed_size += grub_le_to_cpu32 (data->sb.block_size);
i++;
}
return origlen;
}
static grub_ssize_t static grub_ssize_t
grub_squash_read_data (struct grub_squash_data *data, grub_squash_read_data (struct grub_squash_data *data,
grub_disk_t disk, const struct grub_squash_inode *ino, struct grub_squash_cache_inode *ino,
grub_off_t off, char *buf, grub_size_t len) grub_off_t off, char *buf, grub_size_t len)
{ {
grub_err_t err; grub_err_t err;
grub_uint64_t a, b; grub_uint64_t a, b;
grub_uint32_t fragment;
int compressed = 0; int compressed = 0;
struct grub_squash_frag_desc frag;
if (grub_le_to_cpu16 (ino->file.fragment) == 0xffff) if (ino->ino.type == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR))
{ {
if (grub_le_to_cpu32 (ino->file.chunk)) a = grub_le_to_cpu64 (ino->ino.long_file.chunk);
a = grub_le_to_cpu32 (ino->file.chunk); fragment = grub_le_to_cpu32 (ino->ino.long_file.fragment);
else
a = sizeof (struct grub_squash_super);
compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_DATA);
} }
else else
{ {
struct grub_squash_frag_desc frag; a = grub_le_to_cpu32 (ino->ino.file.chunk);
err = read_chunk (disk, &frag, sizeof (frag), fragment = grub_le_to_cpu32 (ino->ino.file.fragment);
data->fragments, sizeof (frag)
* grub_le_to_cpu16 (ino->file.fragment));
if (err)
return -1;
a = grub_le_to_cpu64 (frag.offset) + grub_le_to_cpu32 (ino->file.chunk);
compressed = !(data->sb.flags & SQUASH_FLAG_UNCOMPRESSED_FRAGMENTS);
} }
b = grub_le_to_cpu32 (data->ino.file.offset) + off; if (fragment == 0xffffffff)
return direct_read (data, ino, off, buf, len);
err = read_chunk (data, &frag, sizeof (frag),
data->fragments, sizeof (frag) * fragment);
if (err)
return -1;
a += grub_le_to_cpu64 (frag.offset);
compressed = !(frag.size & SQUASH_BLOCK_UNCOMPRESSED);
if (ino->ino.type == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR))
b = grub_le_to_cpu64 (ino->ino.long_file.offset) + off;
else
b = grub_le_to_cpu32 (ino->ino.file.offset) + off;
/* FIXME: cache uncompressed chunks. */ /* FIXME: cache uncompressed chunks. */
if (compressed) if (compressed)
err = grub_zlib_disk_read (disk, a, b, buf, len); err = grub_zlib_disk_read (data->disk, a, b, buf, len);
else else
err = grub_disk_read (disk, (a + b) >> GRUB_DISK_SECTOR_BITS, err = grub_disk_read (data->disk, (a + b) >> GRUB_DISK_SECTOR_BITS,
(a + b) & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); (a + b) & (GRUB_DISK_SECTOR_SIZE - 1), len, buf);
if (err) if (err)
return -1; return -1;
@ -498,14 +672,14 @@ grub_squash_read (grub_file_t file, char *buf, grub_size_t len)
{ {
struct grub_squash_data *data = file->data; struct grub_squash_data *data = file->data;
return grub_squash_read_data (data, file->device->disk, &data->ino, return grub_squash_read_data (data, &data->ino,
file->offset, buf, len); file->offset, buf, len);
} }
static grub_err_t static grub_err_t
grub_squash_close (grub_file_t file) grub_squash_close (grub_file_t file)
{ {
grub_free (file->data); squash_unmount (file->data);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -518,7 +692,7 @@ grub_squash_mtime (grub_device_t dev, grub_int32_t *tm)
if (! data) if (! data)
return grub_errno; return grub_errno;
*tm = grub_le_to_cpu32 (data->sb.creation_time); *tm = grub_le_to_cpu32 (data->sb.creation_time);
grub_free (data); squash_unmount (data);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }

View file

@ -317,7 +317,7 @@ struct grub_udf_partmap
grub_uint8_t ident[62]; grub_uint8_t ident[62];
} type2; } type2;
}; };
}; } __attribute__ ((packed));
struct grub_udf_lvd struct grub_udf_lvd
{ {
@ -820,7 +820,7 @@ read_string (grub_uint8_t *raw, grub_size_t sz)
for (i = 0; i < utf16len; i++) for (i = 0; i < utf16len; i++)
utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2];
} }
ret = grub_malloc (utf16len * 3 + 1); ret = grub_malloc (utf16len * GRUB_MAX_UTF8_PER_UTF16 + 1);
if (ret) if (ret)
*grub_utf16_to_utf8 ((grub_uint8_t *) ret, utf16, utf16len) = '\0'; *grub_utf16_to_utf8 ((grub_uint8_t *) ret, utf16, utf16len) = '\0';
grub_free (utf16); grub_free (utf16);

View file

@ -50,6 +50,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
/* Calculate in which group the inode can be found. */ /* Calculate in which group the inode can be found. */
#define UFS_BLKSZ(sblock) (grub_le_to_cpu32 (sblock->bsize)) #define UFS_BLKSZ(sblock) (grub_le_to_cpu32 (sblock->bsize))
#define UFS_LOG_BLKSZ(sblock) (data->log2_blksz)
#define INODE(data,field) data->inode. field #define INODE(data,field) data->inode. field
#ifdef MODE_UFS2 #ifdef MODE_UFS2
@ -214,6 +215,7 @@ struct grub_ufs_data
struct grub_ufs_inode inode; struct grub_ufs_inode inode;
int ino; int ino;
int linknest; int linknest;
int log2_blksz;
}; };
static grub_dl_t my_mod; static grub_dl_t my_mod;
@ -285,26 +287,28 @@ static grub_ssize_t
grub_ufs_read_file (struct grub_ufs_data *data, grub_ufs_read_file (struct grub_ufs_data *data,
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
unsigned offset, unsigned length), unsigned offset, unsigned length),
int pos, grub_size_t len, char *buf) grub_off_t pos, grub_size_t len, char *buf)
{ {
struct grub_ufs_sblock *sblock = &data->sblock; struct grub_ufs_sblock *sblock = &data->sblock;
int i; grub_off_t i;
int blockcnt; grub_off_t blockcnt;
/* Adjust len so it we can't read past the end of the file. */ /* Adjust len so it we can't read past the end of the file. */
if (len + pos > INODE_SIZE (data)) if (len + pos > INODE_SIZE (data))
len = INODE_SIZE (data) - pos; len = INODE_SIZE (data) - pos;
blockcnt = (len + pos + UFS_BLKSZ (sblock) - 1) / UFS_BLKSZ (sblock); blockcnt = (len + pos + UFS_BLKSZ (sblock) - 1) >> UFS_LOG_BLKSZ (sblock);
for (i = pos / UFS_BLKSZ (sblock); i < blockcnt; i++) for (i = pos >> UFS_LOG_BLKSZ (sblock); i < blockcnt; i++)
{ {
int blknr; grub_disk_addr_t blknr;
int blockoff = pos % UFS_BLKSZ (sblock); grub_off_t blockoff;
int blockend = UFS_BLKSZ (sblock); grub_off_t blockend = UFS_BLKSZ (sblock);
int skipfirst = 0; int skipfirst = 0;
blockoff = pos & (UFS_BLKSZ (sblock) - 1);
blknr = grub_ufs_get_file_block (data, i); blknr = grub_ufs_get_file_block (data, i);
if (grub_errno) if (grub_errno)
return -1; return -1;
@ -312,14 +316,14 @@ grub_ufs_read_file (struct grub_ufs_data *data,
/* Last block. */ /* Last block. */
if (i == blockcnt - 1) if (i == blockcnt - 1)
{ {
blockend = (len + pos) % UFS_BLKSZ (sblock); blockend = (len + pos) & (UFS_BLKSZ (sblock) - 1);
if (!blockend) if (!blockend)
blockend = UFS_BLKSZ (sblock); blockend = UFS_BLKSZ (sblock);
} }
/* First block. */ /* First block. */
if (i == (pos / (int) UFS_BLKSZ (sblock))) if (i == (pos >> UFS_LOG_BLKSZ (sblock)))
{ {
skipfirst = blockoff; skipfirst = blockoff;
blockend -= skipfirst; blockend -= skipfirst;
@ -391,21 +395,16 @@ grub_ufs_read_inode (struct grub_ufs_data *data, int ino, char *inode)
static grub_err_t static grub_err_t
grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino)
{ {
char symlink[INODE_SIZE (data)]; char symlink[INODE_SIZE (data) + 1];
if (++data->linknest > GRUB_UFS_MAX_SYMLNK_CNT) if (++data->linknest > GRUB_UFS_MAX_SYMLNK_CNT)
return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks"); return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
if (INODE_NBLOCKS (data) == 0) if (INODE_SIZE (data) <= sizeof (data->inode.symlink))
grub_strcpy (symlink, (char *) INODE (data, symlink)); grub_strcpy (symlink, (char *) INODE (data, symlink));
else else
{ grub_ufs_read_file (data, 0, 0, INODE_SIZE (data), symlink);
grub_disk_read (data->disk, symlink[INODE_SIZE (data)] = '\0';
(INODE_DIRBLOCKS (data, 0)
<< grub_le_to_cpu32 (data->sblock.log2_blksz)),
0, INODE_SIZE (data), symlink);
symlink[INODE_SIZE (data)] = '\0';
}
/* The symlink is an absolute path, go back to the root inode. */ /* The symlink is an absolute path, go back to the root inode. */
if (symlink[0] == '/') if (symlink[0] == '/')
@ -538,8 +537,16 @@ grub_ufs_mount (grub_disk_t disk)
if (grub_errno) if (grub_errno)
goto fail; goto fail;
if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS_MAGIC) /* No need to byteswap bsize in this check. It works the same on both
endiannesses. */
if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS_MAGIC
&& data->sblock.bsize != 0
&& ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0))
{ {
for (data->log2_blksz = 0;
(1U << data->log2_blksz) < grub_le_to_cpu32 (data->sblock.bsize);
data->log2_blksz++);
data->disk = disk; data->disk = disk;
data->linknest = 0; data->linknest = 0;
return data; return data;
@ -698,8 +705,6 @@ grub_ufs_close (grub_file_t file)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
#ifdef MODE_UFS2
static grub_err_t static grub_err_t
grub_ufs_label (grub_device_t device, char **label) grub_ufs_label (grub_device_t device, char **label)
{ {
@ -719,7 +724,6 @@ grub_ufs_label (grub_device_t device, char **label)
return grub_errno; return grub_errno;
} }
#endif
static grub_err_t static grub_err_t
grub_ufs_uuid (grub_device_t device, char **uuid) grub_ufs_uuid (grub_device_t device, char **uuid)
@ -757,11 +761,13 @@ grub_ufs_mtime (grub_device_t device, grub_int32_t *tm)
if (!data) if (!data)
*tm = 0; *tm = 0;
else else
{
*tm = grub_le_to_cpu32 (data->sblock.mtime);
#ifdef MODE_UFS2 #ifdef MODE_UFS2
*tm = grub_le_to_cpu64 (data->sblock.mtime2); if (*tm < (grub_int64_t) grub_le_to_cpu64 (data->sblock.mtime2))
#else *tm = grub_le_to_cpu64 (data->sblock.mtime2);
*tm = grub_le_to_cpu32 (data->sblock.mtime);
#endif #endif
}
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
@ -783,9 +789,7 @@ static struct grub_fs grub_ufs_fs =
.open = grub_ufs_open, .open = grub_ufs_open,
.read = grub_ufs_read, .read = grub_ufs_read,
.close = grub_ufs_close, .close = grub_ufs_close,
#ifdef MODE_UFS2
.label = grub_ufs_label, .label = grub_ufs_label,
#endif
.uuid = grub_ufs_uuid, .uuid = grub_ufs_uuid,
.mtime = grub_ufs_mtime, .mtime = grub_ufs_mtime,
.next = 0 .next = 0

Some files were not shown because too many files have changed in this diff Show more