merge mainline into hints

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-12-23 18:49:00 +01:00
commit 17785932df
448 changed files with 43023 additions and 10176 deletions

View file

@ -48,6 +48,7 @@ grub-kbdcomp
grub-macho2img
grub-menulst2cfg
grub-mk*
grub-mount
grub-pe2elf
grub-probe
grub_probe_init.c
@ -160,3 +161,4 @@ widthspec.bin
widthspec.h
docs/stamp-1
docs/version-dev.texi
Makefile.utilgcry.def

3959
ChangeLog

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
AUTOMAKE_OPTIONS = subdir-objects
AUTOMAKE_OPTIONS = subdir-objects -Wno-portability
DEPDIR = .deps-util
SUBDIRS = grub-core/gnulib . grub-core po docs util/bash-completion.d

View file

@ -9,7 +9,8 @@ library = {
common = grub-core/kern/command.c;
common = grub-core/kern/device.c;
common = grub-core/kern/disk.c;
common = grub-core/kern/emu/getroot.c;
common = util/getroot.c;
common = util/raid.c;
common = grub-core/kern/emu/hostdisk.c;
common = grub-core/kern/emu/misc.c;
common = grub-core/kern/emu/mm.c;
@ -20,12 +21,20 @@ library = {
common = grub-core/kern/list.c;
common = grub-core/kern/misc.c;
common = grub-core/kern/partition.c;
common = grub-core/lib/crypto.c;
common = grub-core/disk/luks.c;
common = grub-core/disk/geli.c;
common = grub-core/disk/cryptodisk.c;
common = grub-core/disk/AFSplitter.c;
common = grub-core/lib/pbkdf2.c;
common = grub-core/commands/extcmd.c;
common = grub-core/lib/arg.c;
};
library = {
name = libgrubmods.a;
cflags = '$(CFLAGS_GCRY)';
cppflags = '$(CPPFLAGS_GCRY)';
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.yy.c;
@ -34,7 +43,8 @@ library = {
common_nodist = grub_script.tab.h;
common = grub-core/commands/blocklist.c;
common = grub-core/commands/extcmd.c;
common = grub-core/commands/xnu_uuid.c;
common = grub-core/commands/testload.c;
common = grub-core/commands/ls.c;
common = grub-core/disk/dmraid_nvidia.c;
common = grub-core/disk/loopback.c;
@ -45,14 +55,16 @@ library = {
common = grub-core/disk/raid6_recover.c;
common = grub-core/disk/raid.c;
common = grub-core/fs/affs.c;
common = grub-core/fs/afs_be.c;
common = grub-core/fs/afs.c;
common = grub-core/fs/befs_be.c;
common = grub-core/fs/befs.c;
common = grub-core/fs/bfs.c;
common = grub-core/fs/btrfs.c;
common = grub-core/fs/cpio.c;
common = grub-core/fs/cpio_be.c;
common = grub-core/fs/odc.c;
common = grub-core/fs/newc.c;
common = grub-core/fs/ext2.c;
common = grub-core/fs/fat.c;
common = grub-core/fs/exfat.c;
common = grub-core/fs/fshelp.c;
common = grub-core/fs/hfs.c;
common = grub-core/fs/hfsplus.c;
@ -73,20 +85,19 @@ library = {
common = grub-core/fs/ufs2.c;
common = grub-core/fs/ufs.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/zfsinfo.c;
common = grub-core/fs/zfs/zfs_lzjb.c;
common = grub-core/fs/zfs/zfs_sha256.c;
common = grub-core/fs/zfs/zfs_fletcher.c;
common = grub-core/lib/arg.c;
common = grub-core/lib/crypto.c;
common = grub-core/lib/envblk.c;
common = grub-core/lib/hexdump.c;
common = grub-core/lib/libgcrypt-grub/cipher/sha512.c;
common = grub-core/lib/libgcrypt-grub/cipher/crc.c;
common = grub-core/lib/LzFind.c;
common = grub-core/lib/LzmaEnc.c;
common = grub-core/lib/pbkdf2.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/misc.c;
common = grub-core/partmap/acorn.c;
@ -95,6 +106,7 @@ library = {
common = grub-core/partmap/gpt.c;
common = grub-core/partmap/msdos.c;
common = grub-core/partmap/sun.c;
common = grub-core/partmap/plan.c;
common = grub-core/partmap/dvh.c;
common = grub-core/partmap/sunpc.c;
common = grub-core/partmap/bsdlabel.c;
@ -104,13 +116,16 @@ library = {
common = grub-core/script/script.c;
common = grub-core/script/argv.c;
common = grub-core/io/gzio.c;
common = grub-core/io/lzopio.c;
common = grub-core/kern/ia64/dl_helper.c;
common = grub-core/lib/minilzo/minilzo.c;
};
program = {
name = grub-bin2h;
common = util/bin2h.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER)';
@ -126,6 +141,7 @@ program = {
extra_dist = util/grub-mkimagexx.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBLZMA)';
@ -140,9 +156,10 @@ program = {
common = util/grub-mkrelpath.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
};
program = {
@ -152,6 +169,7 @@ program = {
common = util/grub-script-check.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
@ -164,6 +182,7 @@ program = {
common = util/grub-editenv.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
@ -176,6 +195,7 @@ program = {
common = util/grub-mkpasswd-pbkdf2.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
@ -196,6 +216,7 @@ program = {
common = util/grub-pe2elf.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL)';
@ -214,9 +235,26 @@ program = {
cppflags = '$(CPPFLAGS_GCRY)';
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(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 = {
@ -228,6 +266,7 @@ program = {
cflags = '$(freetype_cflags)';
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(freetype_libs)';
@ -245,6 +284,7 @@ program = {
common = util/devicemap.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
@ -258,6 +298,7 @@ program = {
common = util/ieee1275/ofpath.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
@ -268,7 +309,6 @@ program = {
installdir = sbin;
mansection = 8;
common = util/grub-setup.c;
common = util/raid.c;
common = util/lvm.c;
common = grub-core/lib/reed_solomon.c;
@ -276,6 +316,7 @@ program = {
ldadd = libgrubmods.a;
ldadd = libgrubkern.a;
ldadd = libgrubgcry.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
@ -291,6 +332,7 @@ program = {
ieee1275 = util/ieee1275/ofpath.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBGEOM)';
@ -305,6 +347,7 @@ program = {
common = util/grub-mklayout.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
@ -342,6 +385,13 @@ script = {
condition = COND_HOST_KFREEBSD;
};
script = {
name = '10_illumos';
common = util/grub.d/10_illumos.in;
installdir = grubconf;
condition = COND_HOST_ILLUMOS;
};
script = {
name = '10_netbsd';
common = util/grub.d/10_netbsd.in;
@ -395,6 +445,12 @@ script = {
enable = powerpc_ieee1275;
};
script = {
mansection = 1;
name = grub-mkstandalone;
common = util/grub-mkstandalone.in;
};
script = {
mansection = 8;
installdir = sbin;
@ -616,6 +672,22 @@ program = {
common = grub-core/tests/lib/test.c;
cflags = -Wno-format;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
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)';
@ -629,6 +701,7 @@ program = {
common = grub-core/lib/i386/pc/vesa_modes_table.c;
ldadd = libgrubmods.a;
ldadd = libgrubgcry.a;
ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';

View file

@ -316,14 +316,14 @@ fi
dnl Check if the C compiler generates calls to `__enable_execute_stack()'.
AC_DEFUN([grub_CHECK_ENABLE_EXECUTE_STACK],[
AC_MSG_CHECKING([whether `$CC' generates calls to `__enable_execute_stack()'])
AC_LANG_CONFTEST([[
AC_LANG_CONFTEST([AC_LANG_SOURCE([[
void f (int (*p) (void));
void g (int i)
{
int nestedfunc (void) { return i; }
f (nestedfunc);
}
]])
]])])
if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -S conftest.c]) && test -s conftest.s; then
true
else
@ -346,7 +346,9 @@ AC_DEFUN([grub_CHECK_STACK_PROTECTOR],[
ssp_possible=yes]
AC_MSG_CHECKING([whether `$CC' accepts `-fstack-protector'])
# Is this a reliable test case?
AC_LANG_CONFTEST([[void foo (void) { volatile char a[8]; a[3]; }]])
AC_LANG_CONFTEST([AC_LANG_SOURCE([[
void foo (void) { volatile char a[8]; a[3]; }
]])])
[# `$CC -c -o ...' might not be portable. But, oh, well... Is calling
# `ac_compile' like this correct, after all?
if eval "$ac_compile -S -fstack-protector -o conftest.s" 2> /dev/null; then]
@ -364,7 +366,9 @@ AC_DEFUN([grub_CHECK_STACK_ARG_PROBE],[
[# Smashing stack arg probe.
sap_possible=yes]
AC_MSG_CHECKING([whether `$CC' accepts `-mstack-arg-probe'])
AC_LANG_CONFTEST([[void foo (void) { volatile char a[8]; a[3]; }]])
AC_LANG_CONFTEST([AC_LANG_SOURCE([[
void foo (void) { volatile char a[8]; a[3]; }
]])])
[if eval "$ac_compile -S -mstack-arg-probe -o conftest.s" 2> /dev/null; then]
AC_MSG_RESULT([yes])
[# Should we clear up other files as well, having called `AC_LANG_CONFTEST'?
@ -399,7 +403,7 @@ AC_DEFUN([grub_CHECK_PIE],[
pie_possible=yes]
AC_MSG_CHECKING([whether `$CC' has `-fPIE' as default])
# Is this a reliable test case?
AC_LANG_CONFTEST([[
AC_LANG_CONFTEST([AC_LANG_SOURCE([[
#ifdef __PIE__
int main() {
return 0;
@ -407,7 +411,7 @@ int main() {
#else
#error NO __PIE__ DEFINED
#endif
]])
]])])
[# `$CC -c -o ...' might not be portable. But, oh, well... Is calling
# `ac_compile' like this correct, after all?

View file

@ -26,7 +26,7 @@ if [ "x${GRUB_CONTRIB}" != x ]; then
[ "${GRUB_CONTRIB}" = grub-core/contrib ] || ln -s ../contrib grub-core/contrib
fi
UTIL_DEFS=Makefile.util.def
UTIL_DEFS='Makefile.util.def Makefile.utilgcry.def'
CORE_DEFS='grub-core/Makefile.core.def grub-core/Makefile.gcry.def'
for extra in contrib/*/Makefile.util.def; do

View file

@ -36,6 +36,10 @@
#define NEED_ENABLE_EXECUTE_STACK @NEED_ENABLE_EXECUTE_STACK@
/* Define to 1 if GCC generates calls to __register_frame_info(). */
#define NEED_REGISTER_FRAME_INFO @NEED_REGISTER_FRAME_INFO@
/* Define to 1 to enable disk cache statistics. */
#define DISK_CACHE_STATS @DISK_CACHE_STATS@
#define RE_ENABLE_I18N 1
#if defined(__i386__)
#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1)))

View file

@ -154,6 +154,7 @@ case "$host_os" in
linux*) host_kernel=linux ;;
freebsd* | kfreebsd*-gnu) host_kernel=kfreebsd ;;
netbsd*) host_kernel=netbsd ;;
solaris*) host_kernel=illumos ;;
cygwin) host_kernel=windows ;;
esac
@ -412,21 +413,21 @@ if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then
TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm"
fi
if test "${target_cpu}-${platform}" = mipsel-loongson; then
AC_CACHE_CHECK([whether -march=loongson2f works], [grub_cv_cc_march_loongson2f], [
# 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 -march=loongson2f"
CFLAGS="$CFLAGS -fno-dwarf2-cfi-asm"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[grub_cv_cc_march_loongson2f=yes],
[grub_cv_cc_march_loongson2f=no])
[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_march_loongson2f" = xyes; then
TARGET_CFLAGS="$TARGET_CFLAGS -march=loongson2f"
else
TARGET_CFLAGS="$TARGET_CFLAGS -march=mips3"
fi
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
@ -480,6 +481,7 @@ if test "x$target_m32" = x1; then
# Force 32-bit mode.
TARGET_CFLAGS="$TARGET_CFLAGS -m32"
TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m32"
TARGET_CPPFLAGS="$TARGET_CPPFLAGS -m32"
TARGET_LDFLAGS="$TARGET_LDFLAGS -m32"
TARGET_MODULE_FORMAT="elf32"
fi
@ -488,6 +490,7 @@ if test "x$target_m64" = x1; then
# Force 64-bit mode.
TARGET_CFLAGS="$TARGET_CFLAGS -m64"
TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m64"
TARGET_CPPFLAGS="$TARGET_CPPFLAGS -m64"
TARGET_LDFLAGS="$TARGET_LDFLAGS -m64"
TARGET_MODULE_FORMAT="elf64"
fi
@ -604,7 +607,7 @@ CFLAGS="$CFLAGS -Wl,--defsym,abort=main"
fi
# 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
CFLAGS="$TARGET_CFLAGS -nostdlib"
@ -717,6 +720,17 @@ AC_ARG_ENABLE([mm-debug],
[AC_DEFINE([MM_DEBUG], [1],
[Define to 1 if you enable memory manager debugging.])])
AC_ARG_ENABLE([cache-stats],
AS_HELP_STRING([--enable-cache-stats],
[enable disk cache statistics collection]))
if test x$enable_cache_stats = xyes; then
DISK_CACHE_STATS=1
else
DISK_CACHE_STATS=0
fi
AC_SUBST([DISK_CACHE_STATS])
AC_ARG_ENABLE([grub-emu-usb],
[AS_HELP_STRING([--enable-grub-emu-usb],
[build and install the `grub-emu' debugging utility with USB support (default=guessed)])])
@ -866,10 +880,44 @@ enable_grub_mkfont=yes
else
enable_grub_mkfont=no
fi
if test x"$enable_grub_mkfont" = xno && test "x$platform" = xloongson; then
AC_MSG_ERROR([loongson port needs grub-mkfont])
fi
AC_SUBST([enable_grub_mkfont])
AC_SUBST([freetype_cflags])
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],
[AS_HELP_STRING([--enable-device-mapper],
[enable Linux device-mapper support (default=guessed)])])
@ -977,16 +1025,19 @@ AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux])
AM_CONDITIONAL([COND_HOST_NETBSD], [test x$host_kernel = xnetbsd])
AM_CONDITIONAL([COND_HOST_WINDOWS], [test x$host_kernel = xwindows])
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_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_PCI], [test x$enable_grub_emu_pci = 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_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x])
AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1])
AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes])
AM_CONDITIONAL([COND_ENABLE_CACHE_STATS], [test x$DISK_CACHE_STATS = x1])
AM_CONDITIONAL([COND_HAVE_ASM_USCORE], [test x$HAVE_ASM_USCORE = x1])
AM_CONDITIONAL([COND_CYGWIN], [test x$host_os = xcygwin])
@ -1053,6 +1104,11 @@ echo With memory debugging: Yes
else
echo With memory debugging: No
fi
if [ x"$enable_cache_stats" = xyes ]; then
echo With disk cache statistics: Yes
else
echo With disk cache statistics: No
fi
if [ x"$efiemu_excuse" = x ]; then
echo efiemu runtime: Yes
else
@ -1063,5 +1119,10 @@ echo grub-mkfont: Yes
else
echo grub-mkfont: No "($grub_mkfont_excuse)"
fi
if [ x"$grub_mount_excuse" = x ]; then
echo grub-mount: Yes
else
echo grub-mount: No "($grub_mount_excuse)"
fi
echo "*******************************************************"
]

View file

@ -89,6 +89,7 @@ This edition documents version @value{VERSION}.
* Interface:: The menu and the command-line
* Environment:: GRUB environment variables
* Commands:: The list of available builtin commands
* Internationalisation:: Topics relating to language support
* Security:: Authentication and authorisation
* Supported kernels:: The list of supported kernels
* Troubleshooting:: Error messages produced by GRUB
@ -340,11 +341,17 @@ devices, partitions, and files in a directory depending on context.
@item Support multiple filesystem types
Support multiple filesystem types transparently, plus a useful explicit
blocklist notation. The currently supported filesystem types are @dfn{Amiga
Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS}, @dfn{cpio}, @dfn{Linux
ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{HFS}, @dfn{HFS+},
@dfn{ISO9660}, @dfn{JFS}, @dfn{Minix fs}, @dfn{nilfs2}, @dfn{NTFS},
@dfn{ReiserFS}, @dfn{Amiga Smart FileSystem (SFS)}, @dfn{tar}, @dfn{UDF},
@dfn{BSD UFS/UFS2}, and @dfn{XFS}. @xref{Filesystem}, for more information.
Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS},
@dfn{BtrFS} (including raid0, raid1, raid10, gzip and lzo),
@dfn{cpio} (little- and big-endian bin, odc and newc variants),
@dfn{Linux ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{exFAT}, @dfn{HFS},
@dfn{HFS+}, @dfn{ISO9660} (including Joliet, Rock-ridge and multi-chunk files),
@dfn{JFS}, @dfn{Minix fs} (versions 1, 2 and 3), @dfn{nilfs2},
@dfn{NTFS} (including compression), @dfn{ReiserFS}, @dfn{ROMFS},
@dfn{Amiga Smart FileSystem (SFS)}, @dfn{Squash4}, @dfn{tar}, @dfn{UDF},
@dfn{BSD UFS/UFS2}, @dfn{XFS}, and @dfn{ZFS} (including lzjb, gzip,
zle, mirror, stripe, raidz1/2/3 and encryption in AES-CCM and AES-GCM).
@xref{Filesystem}, for more information.
@item Support automatic decompression
Can decompress files which were compressed by @command{gzip} or
@ -784,6 +791,7 @@ magic.
@menu
* General boot methods:: How to boot OSes with GRUB generally
* Loopback booting:: Notes on booting from loopbacks
* OS-specific notes:: Notes on some operating systems
@end menu
@ -855,6 +863,31 @@ required. @xref{DOS/Windows}.
Chain-loading is only supported on PC BIOS and EFI platforms.
@node Loopback booting
@section Loopback booting
GRUB is able to read from an image (be it one of CD or HDD) stored on
any of its accessible storages (refer to @pxref{loopback} command).
However the OS itself should be able to find its root. This usually
involves running a userspace program running before the real root
is discovered. This is achieved by GRUB loading a specially made
small image and passing it as ramdisk to the kernel. This is achieved
by commands @command{kfreebsd_module}, @command{knetbsd_module_elf},
@command{kopenbsd_ramdisk}, @command{initrd} (@pxref{initrd}),
@command{initrd16} (@pxref{initrd}), @command{multiboot_module},
@command{multiboot2_module} or @command{xnu_ramdisk}
depending on the loader. Note that for knetbsd the image must be put
inside miniroot.kmod and the whole miniroot.kmod has to be loaded. In
kopenbsd payload this is disabled by default. Aditionally behaviour of
initial ramdisk depends on command line options. Several distributors provide
the image for this purpose or it's integrated in their standard ramdisk and
activated by special option. Consult your kernel and distribution manual for
more details. Other loaders like appleloader, chainloader (BIOS, EFI, coreboot),
freedos, ntldr and plan9 provide no possibility of loading initial ramdisk and
as far as author is aware the payloads in question don't support either initial
ramdisk or discovering loopback boot in other way and as such not bootable this
way. Please consider alternative boot methods like copying all files
from the image to actual partition. Consult your OS documentation for
more details
@node OS-specific notes
@section Some caveats on OS-specific issues
@ -1203,7 +1236,8 @@ listed in @file{/boot/grub/video.lst}.
Set the resolution used on the @samp{gfxterm} graphical terminal. Note that
you can only use modes which your graphics card supports via VESA BIOS
Extensions (VBE), so for example native LCD panel resolutions may not be
available. The default is @samp{640x480}. @xref{gfxmode}.
available. The default is @samp{auto}, which tries to select a preferred
resolution. @xref{gfxmode}.
@item GRUB_BACKGROUND
Set a background image for use with the @samp{gfxterm} graphical terminal.
@ -2202,42 +2236,64 @@ you see the files in a device or use the command @command{search}
The device syntax is like this:
@example
@code{(@var{device}[,@var{part-num}][,@var{bsd-subpart-letter}])}
@code{(@var{device}[,@var{partmap-name1}@var{part-num1}[,@var{partmap-name2}@var{part-num2}[,...]]])}
@end example
@samp{[]} means the parameter is optional. @var{device} should be
either @samp{fd} or @samp{hd} followed by a digit, like @samp{fd0}.
But you can also set @var{device} to a hexadecimal or a decimal number
which is a BIOS drive number, so the following are equivalent:
@samp{[]} means the parameter is optional. @var{device} depends on the disk
driver in use. BIOS and EFI disks use either @samp{fd} or @samp{hd} followed
by a digit, like @samp{fd0}, or @samp{cd}.
AHCI, PATA (ata), crypto, USB use the name of driver followed by a number.
Memdisk and host are limited to one disk and so it's refered just by driver
name.
RAID (md), ofdisk (ieee1275), LVM (lv) and arcdisk (arc) use intrinsic name
of disk prefixed by driver name. Conflicts are solved by suffixing a number
if necessarry. Commas need to be escaped.
Loopback uses whatever name specified to @command{loopback} command.
For crypto and RAID (md) additionally you can use the syntax
<driver name>uuid/<uuid>
@example
(fd0)
(hd0)
(0x80)
(128)
(cd)
(ahci0)
(ata0)
(crypto0)
(usb0)
(cryptouuid/123456789abcdef0123456789abcdef0)
(mduuid/123456789abcdef0123456789abcdef0)
(lv/system-root)
(md/myraid)
(md/0)
(ieee1275/disk)
(memdisk)
(host)
(myloop)
@end example
@var{part-num} represents the partition number of @var{device}, starting
from one for primary partitions and from five for extended partitions,
and @var{bsd-subpart-letter} represents the BSD disklabel subpartition,
such as @samp{a} or @samp{e}.
A shortcut for specifying BSD subpartitions is
@code{(@var{device},@var{bsd-subpart-letter})}, in this case, GRUB
searches for the first PC partition containing a BSD disklabel, then
finds the subpartition @var{bsd-subpart-letter}. Here is an example:
@example
(hd0,a)
@end example
from one. @var{partname} is optional but is recommended since disk may have
several top-level partmaps. Specifying third and later component you can access
to subpartitions.
The syntax @samp{(hd0)} represents using the entire disk (or the
MBR when installing GRUB), while the syntax @samp{(hd0,1)}
represents using the first partition of the disk (or the boot sector
of the partition when installing GRUB).
If you enabled the network support, the special drive @samp{(pxe)} is
also available. Before using the network drive, you must initialize the
network. @xref{Network}, for more information.
@example
(hd0,msdos1)
(hd0,msdos1,msdos5)
(hd0,msdos1,bsd3)
(hd0,netbsd1)
(hd0,gpt1)
(hd0,1,3)
@end example
If you enabled the network support, the special drives @samp{(tftp)},
@samp{(http)} and so on ars also available.
Before using the network drive, you must initialize the network.
@xref{Network}, for more information.
If you boot GRUB from a CD-ROM, @samp{(cd)} is available. @xref{Making
a GRUB bootable CD-ROM}, for details.
@ -3866,6 +3922,65 @@ Unset the environment variable @var{envvar}.
This command is not yet implemented for GRUB 2, although it is planned.
@node Internationalisation
@chapter Charset
GRUB uses UTF-8 internally other than in rendering where some GRUB-specific
appropriate representation is used. All text files (including config) are
assumed to be encoded in UTF-8.
@chapter Filesystems
NTFS, JFS, UDF, HFS+, exFAT, long filesnames in FAT, Joliet part of
ISO9660 are treated as UTF-16 as per specification. BFS is read as UTF-8,
again according to specification. BtrFS, cpio, tar, squash4, minix, minix2,
minix3, ROMFS, ReiserFS, XFS, ext2, ext3, ext4, FAT (short names),
ISO9660 (plain and RockRidge), nilfs2, UFS1, UFS2 and ZFS are assumed
to be UTF-8. This might be false on systems configured with legacy charset
but as long as the charset used is superset of ASCII you should be able to
access ASCII-named files. And it's recommended to configure your system to use
UTF-8 to access the filesystem, convmv may help with migration. AFFS and HFS
never use unicode and GRUB assumes them to be in Latin1 and MacRoman
respectively. NTFS, HFS+, FAT and exFAT are case-insensitive however no
attempt is performed at case conversion of international characters so e.g.
a file named lowercase greek alpha is treated as different from the one named
as uppercase alpha. Also similar to POSIX systems GRUB make no attempt at check
of canonical equivalence so a file name u-diaresis is treated as distinct from
u+combining diaresis. This however means that in order to access file on
HFS+ its name must be specified in normalisation form D. On ZFS subvolumes
marked as case insensitive files containing lowercase international characters
are inaccessible.
@chapter Output terminal
Firmware output console ``console'' on ARC and IEEE1275 are limited to ASCII.
BIOS firmware console and VGA text are limited to ASCII and some pseudographics.
None of above mentioned is appropriate for displaying international and any
unsupported character is replaced with question mark except pseudographics
which we attempt to approximate with ASCII. EFI console on the other hand
nominally supports UTF-16 but actual language coverage depends on firmware and
may be very limited. The encoding used on serial can be chosen with
@command{terminfo} as either ASCII, UTF-8 or ``visual UTF-8''. Last one is
against the specification but results in correct rendering of right-to-left
on some readers which don't have own bidi implementation. When using gfxterm
or gfxmenu GRUB itself is responsible for rendering the text. In this case
GRUB is limited by loaded fonts. If fonts contain all required characters
then bidirectional text, cursive variants and combining marks other than
enclosing ones. Ligatures aren't supported though. This should cover
European, Middle Eastern (if you don't mind lack of la-alef ligature in
Arabic) and East Asian scripts. Notable unsupported scripts are Brahmic family
and derived as well as Mongolian and Tifinagh. If you can complete either of
two lists or, better, propose a patch to improve rendering, please contact
developper team.
@chapter Input terminal
Firmware console on BIOS, IEEE1275 and ARC doesn't allow you to enter non-ASCII
characters. EFI specification allows for such but author is unaware of any
actual implementations. Serial input is currently limited for latin1 (unlikely
to change). Own keyboard implementations (at_keyboard and usb_keyboard) can
support any characters but work on one-char-per-keystroke. So no dead keys or
advanced input method. Also there is no keymap change hotkey. In practice it
makes difficult to enter any text using non-Latin alphabet.
@chapter Gettext
GRUB supports being translated. For this you need to have language *.mo files in $prefix/locale, load gettext module and set ``lang'' variable.
@node Security
@chapter Authentication and authorisation
@ -3942,6 +4057,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
@item @tab BIOS @tab Coreboot
@item BIOS chainloading @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 FreeBSD bootloader @tab yes @tab crashes (1)
@item 32-bit kFreeBSD @tab yes @tab crashes (2,6)
@ -3967,6 +4083,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
@item @tab Multiboot @tab Qemu
@item BIOS chainloading @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 FreeBSD bootloader @tab crashes (1) @tab crashes (1)
@item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6)
@ -3992,6 +4109,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
@item @tab 32-bit EFI @tab 64-bit EFI
@item BIOS chainloading @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 FreeBSD bootloader @tab crashes (1) @tab crashes (1)
@item 32-bit kFreeBSD @tab headless @tab headless
@ -4017,6 +4135,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
@item @tab IEEE1275
@item BIOS chainloading @tab no (1)
@item NTLDR @tab no (1)
@item Plan9 @tab no (1)
@item FreeDOS @tab no (1)
@item FreeBSD bootloader @tab crashes (1)
@item 32-bit kFreeBSD @tab crashes (6)
@ -4330,11 +4449,11 @@ how to get the latest version.
@end quotation
GRUB is available from the GNU alpha archive site
@uref{ftp://alpha.gnu.org/gnu/grub} or any of its mirrors. The file
@uref{ftp://ftp.gnu.org/gnu/grub} or any of its mirrors. The file
will be named grub-version.tar.gz. The current version is
@value{VERSION}, so the file you should grab is:
@uref{ftp://alpha.gnu.org/gnu/grub/grub-@value{VERSION}.tar.gz}
@uref{ftp://ftp.gnu.org/gnu/grub/grub-@value{VERSION}.tar.gz}
To unbundle GRUB use the instruction:

View file

@ -1,4 +1,10 @@
[NAME]
grub-mklayout \- generate a GRUB keyboard layout file
[DESCRIPTION]
grub-mklayout processes a keyboard layout description in
.BR keymaps (5)
format into a format that can be used by GRUB's
.B keymap
command.
[SEE ALSO]
.BR grub-mkconfig (8)

View file

@ -0,0 +1,4 @@
[NAME]
grub-mkstandalone \- make a memdisk-based GRUB image
[SEE ALSO]
.BR grub-mkimage (1)

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

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

134
gentpl.py
View file

@ -30,12 +30,14 @@ GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275"
GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu")
# Groups based on hardware features
GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips"]; GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi")
GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips",
"sparc64_ieee1275", "powerpc_ieee1275"]
GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi")
GROUPS["pci"] = GROUPS["x86"] + ["mips_loongson"]
GROUPS["usb"] = GROUPS["pci"]
# If gfxterm is main output console integrate it into kernel
GROUPS["videoinkernel"] = ["mips_loongson"]
GROUPS["videoinkernel"] = ["mips_loongson", "mips_qemu_mips"]
GROUPS["videomodules"] = GRUB_PLATFORMS[:];
for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i)
@ -181,6 +183,17 @@ def foreach_platform_specific_value(platform, suffix, nonetag, closure):
r += "[+ ELSE +][+ FOR " + nonetag + " +]" + closure("[+ ." + nonetag + " +]") + "[+ ENDFOR +][+ ENDIF +]"
return r
#
# Returns autogen code that defines an autogen macro using the
# definition given in the 'snippet'.
#
def define_autogen_macro(name, snippet):
r = ""
r += "[+ DEFINE " + name + " +]"
r += snippet
r += "[+ ENDDEF +]\n"
return r
#
# Template for handling values from sum of all groups for a platform,
# for example:
@ -243,10 +256,18 @@ def foreach_enabled_platform(closure):
# emu_condition = COND_GRUB_EMU_USB;
# };
#
def define_macro_for_platform_conditionals_if_statement(p):
return define_autogen_macro(
"if_" + p + "_conditionals",
foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "if " + cond + "\n"))
def define_macro_for_platform_conditionals_endif_statement(p):
return define_autogen_macro(
"endif_" + p + "_conditionals",
foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "endif " + cond + "\n"))
def under_platform_specific_conditionals(platform, snippet):
r = foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "if " + cond + "\n")
r = "[+ if_" + platform + "_conditionals +]"
r += snippet
r += foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "endif " + cond + "\n")
r += "[+ endif_" + platform + "_conditionals +]"
return r
def platform_specific_values(platform, suffix, nonetag):
@ -259,18 +280,69 @@ def platform_values(platform, suffix):
def extra_dist():
return foreach_value("extra_dist", lambda value: value + " ")
def platform_sources(p): return platform_values(p, "")
def platform_nodist_sources(p): return platform_values(p, "_nodist")
def platform_dependencies(p): return platform_values(p, "dependencies", "_dependencies")
def define_macro_for_platform_sources(p):
return define_autogen_macro(
"get_" + p + "_sources",
platform_values(p, ""))
def define_macro_for_platform_nodist_sources(p):
return define_autogen_macro(
"get_" + p + "_nodist_sources",
platform_values(p, "_nodist"))
def define_macro_for_platform_dependencies(p):
return define_autogen_macro(
"get_" + p + "_dependencies",
platform_values(p, "dependencies", "_dependencies"))
def platform_sources(p): return "[+ get_" + p + "_sources +]"
def platform_nodist_sources(p): return "[+ get_" + p + "_nodist_sources +]"
def platform_dependencies(p): return "[+ get_" + p + "_dependencies +]"
def platform_startup(p): return platform_specific_values(p, "_startup", "startup")
def platform_ldadd(p): return platform_specific_values(p, "_ldadd", "ldadd")
def platform_cflags(p): return platform_specific_values(p, "_cflags", "cflags")
def platform_ldflags(p): return platform_specific_values(p, "_ldflags", "ldflags")
def platform_cppflags(p): return platform_specific_values(p, "_cppflags", "cppflags")
def platform_ccasflags(p): return platform_specific_values(p, "_ccasflags", "ccasflags")
def platform_stripflags(p): return platform_specific_values(p, "_stripflags", "stripflags")
def platform_objcopyflags(p): return platform_specific_values(p, "_objcopyflags", "objcopyflags")
#
# Returns Autogen code which defines the autogen macros that collect
# platform specific values for cflags, ldflags, etc. tags.
#
def define_macro_for_platform_startup(p):
return define_autogen_macro(
"get_" + p + "_startup",
platform_specific_values(p, "_startup", "startup"))
def define_macro_for_platform_cflags(p):
return define_autogen_macro(
"get_" + p + "_cflags",
platform_specific_values(p, "_cflags", "cflags"))
def define_macro_for_platform_ldadd(p):
return define_autogen_macro(
"get_" + p + "_ldadd",
platform_specific_values(p, "_ldadd", "ldadd"))
def define_macro_for_platform_ldflags(p):
return define_autogen_macro(
"get_" + p + "_ldflags",
platform_specific_values(p, "_ldflags", "ldflags"))
def define_macro_for_platform_cppflags(p):
return define_autogen_macro(
"get_" + p + "_cppflags",
platform_specific_values(p, "_cppflags", "cppflags"))
def define_macro_for_platform_ccasflags(p):
return define_autogen_macro(
"get_" + p + "_ccasflags",
platform_specific_values(p, "_ccasflags", "ccasflags"))
def define_macro_for_platform_stripflags(p):
return define_autogen_macro(
"get_" + p + "_stripflags",
platform_specific_values(p, "_stripflags", "stripflags"))
def define_macro_for_platform_objcopyflags(p):
return define_autogen_macro(
"get_" + p + "_objcopyflags",
platform_specific_values(p, "_objcopyflags", "objcopyflags"))
#
# Autogen calls to invoke the above macros.
#
def platform_startup(p): return "[+ get_" + p + "_startup +]"
def platform_ldadd(p): return "[+ get_" + p + "_ldadd +]"
def platform_cflags(p): return "[+ get_" + p + "_cflags +]"
def platform_ldflags(p): return "[+ get_" + p + "_ldflags +]"
def platform_cppflags(p): return "[+ get_" + p + "_cppflags +]"
def platform_ccasflags(p): return "[+ get_" + p + "_ccasflags +]"
def platform_stripflags(p): return "[+ get_" + p + "_stripflags +]"
def platform_objcopyflags(p): return "[+ get_" + p + "_objcopyflags +]"
#
# Emit snippet only the first time through for the current name.
@ -487,7 +559,6 @@ def script_rules():
def data_rules():
return rules("data", data)
print "[+ AutoGen5 template +]\n"
a = module_rules()
b = kernel_rules()
c = image_rules()
@ -497,11 +568,28 @@ f = script_rules()
g = data_rules()
z = global_variable_initializers()
print ("[+ AutoGen5 template +]\n")
for p in GRUB_PLATFORMS:
print (define_macro_for_platform_sources(p))
print (define_macro_for_platform_nodist_sources(p))
# print define_macro_for_platform_dependencies(p)
print (define_macro_for_platform_startup(p))
print (define_macro_for_platform_cflags(p))
print (define_macro_for_platform_ldadd(p))
print (define_macro_for_platform_ldflags(p))
print (define_macro_for_platform_cppflags(p))
print (define_macro_for_platform_ccasflags(p))
print (define_macro_for_platform_stripflags(p))
print (define_macro_for_platform_objcopyflags(p))
print (define_macro_for_platform_conditionals_if_statement(p))
print (define_macro_for_platform_conditionals_endif_statement(p))
# print z # initializer for all vars
print a
print b
print c
print d
print e
print f
print g
print (a)
print (b)
print (c)
print (d)
print (e)
print (f)
print (g)

View file

@ -1,4 +1,4 @@
AUTOMAKE_OPTIONS = subdir-objects
AUTOMAKE_OPTIONS = subdir-objects -Wno-portability
DEPDIR=.deps-core
@ -78,12 +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/time.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/libgcc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
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/pxe.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h
@ -99,10 +98,12 @@ endif
if COND_i386_coreboot
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h
endif
if COND_i386_multiboot
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h
endif
if COND_i386_qemu
@ -141,7 +142,20 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arc/arc.h
endif
if COND_mips_qemu_mips
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
endif
if COND_mips_loongson
@ -187,6 +201,7 @@ endif
if COND_emu
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/export.h
if COND_GRUB_EMU_SDL
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
endif

View file

@ -18,6 +18,18 @@ script = {
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 = {
name = kernel;
@ -34,7 +46,7 @@ kernel = {
ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment';
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_BASE_LDOPT),0x8200';
@ -102,6 +114,7 @@ kernel = {
ieee1275 = kern/ieee1275/mmap.c;
ieee1275 = kern/ieee1275/openfw.c;
ieee1275 = term/ieee1275/ofconsole.c;
ieee1275 = kern/ieee1275/init.c;
terminfoinkernel = term/terminfo.c;
terminfoinkernel = term/tparm.c;
@ -143,7 +156,7 @@ kernel = {
i386_pc = term/i386/pc/console.c;
i386_qemu = bus/pci.c;
i386_qemu = kern/i386/qemu/init.c;
i386_qemu = kern/vga_init.c;
i386_qemu = kern/i386/qemu/mmap.c;
i386_qemu = kern/i386/tsc.c;
@ -153,8 +166,6 @@ kernel = {
i386_multiboot = kern/i386/multiboot_mmap.c;
i386_multiboot = kern/i386/tsc.c;
i386_ieee1275 = kern/ieee1275/init.c;
mips = kern/mips/cache.S;
mips = kern/mips/dl.c;
mips = kern/mips/init.c;
@ -162,6 +173,11 @@ kernel = {
mips_qemu_mips = kern/mips/qemu_mips/init.c;
mips_qemu_mips = term/ns8250.c;
mips_qemu_mips = term/serial.c;
mips_qemu_mips = term/at_keyboard.c;
mips_qemu_mips = commands/keylayouts.c;
mips_qemu_mips = term/i386/pc/vga_text.c;
mips_qemu_mips = term/i386/vga_common.c;
mips_qemu_mips = kern/vga_init.c;
mips_arc = kern/mips/arc/init.c;
mips_arc = term/arc/console.c;
@ -176,24 +192,22 @@ kernel = {
mips_loongson = term/serial.c;
mips_loongson = video/sm712.c;
mips_loongson = video/sis315pro.c;
mips_loongson = video/radeon_fuloong2e.c;
extra_dist = video/sm712_init.c;
mips_loongson = commands/keylayouts.c;
powerpc_ieee1275 = kern/ieee1275/init.c;
powerpc_ieee1275 = kern/powerpc/cache.S;
powerpc_ieee1275 = kern/powerpc/dl.c;
sparc64_ieee1275 = kern/sparc64/cache.S;
sparc64_ieee1275 = kern/sparc64/dl.c;
sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c;
sparc64_ieee1275 = kern/sparc64/ieee1275/init.c;
emu = disk/host.c;
emu = gnulib/progname.c;
emu = gnulib/error.c;
emu = kern/emu/cache_s.S;
emu = kern/emu/console.c;
emu = kern/emu/getroot.c;
emu = kern/emu/hostdisk.c;
emu = kern/emu/hostfs.c;
emu = kern/emu/main.c;
@ -217,6 +231,7 @@ kernel = {
videoinkernel = commands/boot.c;
extra_dist = kern/i386/int.S;
extra_dist = kern/i386/realmode.S;
extra_dist = kern/i386/pc/lzma_decode.S;
extra_dist = kern/mips/cache_flush.S;
@ -353,6 +368,15 @@ image = {
enable = mips;
};
image = {
name = lzma_decompress;
i386_pc = boot/i386/pc/startup_raw.S;
objcopyflags = '-O binary';
ldflags = '$(TARGET_IMG_LDFLAGS) -Wl,-Ttext,0x8200';
enable = i386_pc;
};
image = {
name = fwstart;
mips_loongson = boot/mips/loongson/fwstart.S;
@ -362,8 +386,8 @@ image = {
};
image = {
name = fwstart_fuloong;
mips_loongson = boot/mips/loongson/fuloong.S;
name = fwstart_fuloong2f;
mips_loongson = boot/mips/loongson/fuloong2f.S;
objcopyflags = '-O binary';
ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic';
enable = mips_loongson;
@ -397,11 +421,15 @@ module = {
module = {
name = usb;
common = bus/usb/usb.c;
noemu = bus/usb/usbtrans.c;
noemu = bus/usb/usbhub.c;
enable = emu;
common = bus/usb/usbtrans.c;
common = bus/usb/usbhub.c;
enable = usb;
emu_condition = COND_GRUB_EMU_USB;
};
module = {
name = emuusb;
common = bus/usb/usb.c;
condition = COND_GRUB_EMU_USB;
};
module = {
@ -436,18 +464,22 @@ module = {
module = {
name = pci;
noemu = bus/pci.c;
emu = bus/emu/pci.c;
emu = commands/lspci.c;
common = bus/pci.c;
enable = emu;
enable = i386_pc;
enable = i386_efi;
enable = x86_64_efi;
enable = i386_ieee1275;
enable = i386_coreboot;
enable = i386_multiboot;
emu_condition = COND_GRUB_EMU_PCI;
};
module = {
name = emupci;
common = bus/emu/pci.c;
common = commands/lspci.c;
condition = COND_GRUB_EMU_PCI;
};
module = {
@ -622,6 +654,20 @@ module = {
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 = {
name = hashsum;
common = commands/hashsum.c;
@ -717,22 +763,11 @@ module = {
common = commands/probe.c;
};
module = {
name = pxecmd;
i386_pc = commands/i386/pc/pxecmd.c;
enable = i386_pc;
};
module = {
name = read;
common = commands/read.c;
};
module = {
name = reboot;
common = commands/reboot.c;
};
module = {
name = search;
common = commands/search_wrap.c;
@ -791,8 +826,6 @@ module = {
name = usbtest;
common = commands/usbtest.c;
enable = usb;
enable = emu;
emu_condition = COND_GRUB_EMU_USB;
};
module = {
@ -820,6 +853,22 @@ module = {
common = disk/loopback.c;
};
module = {
name = cryptodisk;
common = disk/cryptodisk.c;
};
module = {
name = luks;
common = disk/luks.c;
common = disk/AFSplitter.c;
};
module = {
name = geli;
common = disk/geli.c;
};
module = {
name = lvm;
common = disk/lvm.c;
@ -868,8 +917,14 @@ module = {
};
module = {
name = ata_pthru;
common = disk/ata_pthru.c;
name = ahci;
common = disk/ahci.c;
enable = pci;
};
module = {
name = pata;
common = disk/pata.c;
enable = pci;
enable = mips_qemu_mips;
};
@ -884,8 +939,6 @@ module = {
name = usbms;
common = disk/usbms.c;
enable = usb;
enable = emu;
emu_condition = COND_GRUB_EMU_USB;
};
module = {
@ -944,24 +997,16 @@ module = {
};
module = {
name = afs_be;
common = fs/afs_be.c;
};
module = {
name = befs;
common = fs/befs.c;
};
module = {
name = befs_be;
common = fs/befs_be.c;
name = bfs;
common = fs/bfs.c;
};
module = {
name = btrfs;
common = fs/btrfs.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 = {
@ -969,6 +1014,21 @@ module = {
common = fs/cpio.c;
};
module = {
name = cpio_be;
common = fs/cpio_be.c;
};
module = {
name = newc;
common = fs/newc.c;
};
module = {
name = odc;
common = fs/odc.c;
};
module = {
name = ext2;
common = fs/ext2.c;
@ -979,6 +1039,11 @@ module = {
common = fs/fat.c;
};
module = {
name = exfat;
common = fs/exfat.c;
};
module = {
name = fshelp;
common = fs/fshelp.c;
@ -1087,6 +1152,11 @@ module = {
common = fs/zfs/zfs_fletcher.c;
};
module = {
name = zfscrypt;
common = fs/zfs/zfscrypt.c;
};
module = {
name = zfsinfo;
common = fs/zfs/zfsinfo.c;
@ -1094,7 +1164,7 @@ module = {
module = {
name = pxe;
i386_pc = fs/i386/pc/pxe.c;
i386_pc = net/drivers/i386/pc/pxe.c;
enable = i386_pc;
};
@ -1186,6 +1256,9 @@ module = {
efi = lib/efi/datetime.c;
sparc64_ieee1275 = lib/ieee1275/datetime.c;
powerpc_ieee1275 = lib/ieee1275/datetime.c;
sparc64_ieee1275 = lib/ieee1275/cmos.c;
powerpc_ieee1275 = lib/ieee1275/cmos.c;
mips_arc = lib/arc/datetime.c;
enable = noemu;
};
@ -1219,6 +1292,13 @@ module = {
enable = x86;
};
module = {
name = plan9;
i386_pc = loader/i386/pc/plan9.c;
enable = i386_pc;
};
module = {
name = linux16;
i386_pc = loader/i386/pc/linux.c;
@ -1292,7 +1372,9 @@ module = {
name = chain;
efi = loader/efi/chainloader.c;
i386_pc = loader/i386/pc/chainloader.c;
i386_coreboot = loader/i386/coreboot/chainloader.c;
enable = i386_pc;
enable = i386_coreboot;
enable = efi;
};
@ -1351,7 +1433,7 @@ module = {
extra_dist = script/yylex.l;
extra_dist = script/parser.y;
cflags = '$(CFLAGS_POSIX) -Wno-error';
cflags = '$(CFLAGS_POSIX)';
cppflags = '$(CPPFLAGS_POSIX)';
};
@ -1385,6 +1467,11 @@ module = {
common = partmap/sun.c;
};
module = {
name = part_plan;
common = partmap/plan.c;
};
module = {
name = part_dvh;
common = partmap/dvh.c;
@ -1422,9 +1509,7 @@ module = {
common = term/serial.c;
x86 = term/ns8250.c;
enable = emu;
enable = x86;
emu_condition = COND_GRUB_EMU_USB;
};
module = {
@ -1448,8 +1533,10 @@ module = {
module = {
name = vga;
i386_pc = video/i386/pc/vga.c;
common = video/i386/pc/vga.c;
enable = i386_pc;
enable = i386_coreboot;
enable = i386_multiboot;
};
module = {
@ -1527,8 +1614,10 @@ module = {
module = {
name = vbe;
i386_pc = video/i386/pc/vbe.c;
common = video/i386/pc/vbe.c;
enable = i386_pc;
enable = i386_coreboot;
enable = i386_multiboot;
};
module = {
@ -1565,6 +1654,49 @@ module = {
common = hook/datehook.c;
};
module = {
name = net;
common = net/net.c;
common = net/dns.c;
common = net/bootp.c;
common = net/ip.c;
common = net/udp.c;
common = net/tcp.c;
common = net/icmp.c;
common = net/icmp6.c;
common = net/ethernet.c;
common = net/arp.c;
common = net/netbuff.c;
};
module = {
name = tftp;
common = net/tftp.c;
};
module = {
name = http;
common = net/http.c;
};
module = {
name = ofnet;
common = net/drivers/ieee1275/ofnet.c;
enable = ieee1275;
};
module = {
name = efinet;
common = net/drivers/efi/efinet.c;
enable = efi;
};
module = {
name = emunet;
emu = net/drivers/emu/emunet.c;
enable = emu;
};
module = {
name = legacycfg;
common = commands/legacycfg.c;
@ -1588,6 +1720,14 @@ module = {
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 = {
name = testload;
common = commands/testload.c;
@ -1604,3 +1744,29 @@ module = {
common = commands/keylayouts.c;
enable = videomodules;
};
module = {
name = priority_queue;
common = lib/priority_queue.c;
};
module = {
name = time;
common = commands/time.c;
};
module = {
name = cacheinfo;
common = commands/cacheinfo.c;
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/boot.h>
#include <grub/machine/boot.h>
/*

View file

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

View file

@ -19,7 +19,6 @@
#include <config.h>
#include <grub/symbol.h>
#include <grub/boot.h>
#include <grub/machine/boot.h>
#include <grub/machine/kernel.h>
#include <multiboot.h>
@ -200,21 +199,12 @@ real_code_2:
1:
movl %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx
#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200
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
movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx
addl $((0x9000 - 0x8200) - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx
2:
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
ljmp $(DATA_ADDR >> 4), $0

View file

@ -0,0 +1,351 @@
/*
* 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
/* Don't remove this push: it's an argument. */
push %ecx
call _LzmaDecodeA
pop %ecx
/* _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

@ -1,2 +1,2 @@
#define FULOONG 1
#define FULOONG2F 1
#include "fwstart.S"

View file

@ -26,7 +26,7 @@
#include <grub/cs5536.h>
#include <grub/smbus.h>
#ifdef FULOONG
#ifdef FULOONG2F
#define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT2
#define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200
#else
@ -43,10 +43,10 @@
start:
_start:
__start:
/* Put serial init as soon as possible. But on Fuloong serial is past
Geode, so on Fuloong we need Geode first.
/* Put serial init as soon as possible. But on Fuloong2f serial is past
Geode, so on Fuloong2f we need Geode first.
*/
#ifndef FULOONG
#ifndef FULOONG2F
bal serial_hw_init
nop
#endif
@ -72,7 +72,7 @@ retry_cs5536:
bnel $t2, $t3, 1b
sll $t4, $t4, 1
#ifndef FULOONG
#ifndef FULOONG2F
bal message
addiu $a0, $a0, %lo(cs5536_found)
bal printhex
@ -95,7 +95,7 @@ retry_cs5536:
bal gpio_init
nop
#ifdef FULOONG
#ifdef FULOONG2F
bal serial_hw_init
nop
#endif
@ -130,7 +130,7 @@ retry_cs5536:
sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0)
sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0)
/* Yeeloong and Fuloong have only one memory slot. */
/* Yeeloong and Fuloong2f have only one memory slot. */
/* Output first byte on serial for debugging. */
ori $a1, $zero, GRUB_SMB_RAM_START_ADDR
bal read_spd
@ -252,7 +252,7 @@ gpio_init:
/* In: none. Out: none. Clobbered: $t0, $t1, $t2, $a0, $a1, $a2. */
serial_hw_init:
move $t2, $ra
#ifdef FULOONG
#ifdef FULOONG2F
lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_LEG_IO)
addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_LEG_IO)
lui $a1, %hi (GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3 \
@ -471,7 +471,7 @@ regdump:
.quad 0x0100020200010101 /* 4 */
.quad 0x0a04030603050203 /* 6 */
.quad 0x0f0e040000010a0b /* 7 */
#ifdef FULOONG
#ifdef FULOONG2F
.quad 0x0000000100000001 /* 8 */
#else
.quad 0x0000010200000102 /* 8 */
@ -482,7 +482,7 @@ regdump:
.quad 0x002a3c0615000000 /* c */
.quad 0x002a002a002a002a /* d */
.quad 0x002a002a002a002a /* e */
#ifdef FULOONG
#ifdef FULOONG2F
.quad 0x00b40020005b0004 /* f */
#else
.quad 0x00b40020006d0004 /* f */
@ -503,7 +503,7 @@ regdump:
/* Dump of GPIO connections. FIXME: Remove useless and macroify. */
gpio_dump:
#ifdef FULOONG
#ifdef FULOONG2F
.long 0xffff0000, 0x2eefd110, 0xffff0000, 0xffff0000
.long 0x2eefd110, 0xffff0000, 0x1000efff, 0xefff1000
.long 0x3df3c20c, 0xffff0000, 0xffff0000, 0xffff0000
@ -740,8 +740,8 @@ continue:
lui $t0, %hi(cached_continue - 0x20000000)
addiu $t0, $t0, %lo(cached_continue - 0x20000000)
jr $t0
#ifdef FULOONG
addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_FULOONG)
#ifdef FULOONG2F
addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_FULOONG2F)
#else
addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_YEELOONG)
#endif

View file

@ -38,13 +38,13 @@ start:
bal codestart
nop
base:
. = _start + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE
. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
compressed_size:
.long 0
. = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
uncompressed_size:
.long 0
. = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR
uncompressed_addr:
.long 0
codestart:
@ -54,8 +54,22 @@ codestart:
/* Parse arguments. Has to be done before relocation.
So need to do it in asm. */
#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
lui $t0, %hi (((16 << 20) - 264 + 4) | 0x80000000)
lw $t1, %lo (((16 << 20) - 264 + 4) | 0x80000000) ($t0)
lui $t2, 0x1234
ori $t2, 0x5678
bne $t1, $t2, 1f
nop
lui $t0, %hi (((16 << 20) - 264) | 0x80000000)
b 2f
lw $s4, %lo (((16 << 20) - 264) | 0x80000000) ($t0)
1:
li $s4, 0
2:
#endif
#ifdef GRUB_MACHINE_MIPS_LOONGSON
@ -95,7 +109,7 @@ argcont:
DO_PARSE (memsizestr, $s4)
DO_PARSE (highmemsizestr, $s5)
DO_CHECKT1 (pmon_yeeloong_verstr, GRUB_ARCH_MACHINE_YEELOONG)
DO_CHECKT1 (pmon_fuloong_verstr, GRUB_ARCH_MACHINE_FULOONG)
DO_CHECKT1 (pmon_fuloong2f_verstr, GRUB_ARCH_MACHINE_FULOONG2F)
2:
b argcont
addiu $t0, $t0, 4
@ -141,11 +155,12 @@ memsizestr: .asciiz "memsize="
highmemsizestr: .asciiz "highmemsize="
machtype_yeeloong_str1: .asciiz "machtype=8.9"
machtype_yeeloong_str2: .asciiz "machtype=lemote-yeeloong-"
machtype_fuloong_str: .asciiz "machtype=lemote-fuloong-"
machtype_fuloong2f_str: .asciiz "machtype=lemote-fuloong-2f"
machtype_fuloong2e_str: .asciiz "machtype=lemote-fuloong-2e"
pmon_yeeloong_str: .asciiz "PMON_VER=LM8"
pmon_fuloong_str: .asciiz "PMON_VER=LM6"
pmon_fuloong2f_str: .asciiz "PMON_VER=LM6"
pmon_yeeloong_verstr: .asciiz "Version=LM8"
pmon_fuloong_verstr: .asciiz "Version=LM6"
pmon_fuloong2f_verstr: .asciiz "Version=LM6"
.p2align 2
argdone:
@ -159,8 +174,9 @@ argdone:
DO_CHECKA1 (machtype_yeeloong_str1, GRUB_ARCH_MACHINE_YEELOONG)
DO_CHECKA1 (machtype_yeeloong_str2, GRUB_ARCH_MACHINE_YEELOONG)
DO_CHECKA1 (pmon_yeeloong_str, GRUB_ARCH_MACHINE_YEELOONG)
DO_CHECKA1 (machtype_fuloong_str, GRUB_ARCH_MACHINE_FULOONG)
DO_CHECKA1 (pmon_fuloong_str, GRUB_ARCH_MACHINE_FULOONG)
DO_CHECKA1 (machtype_fuloong2f_str, GRUB_ARCH_MACHINE_FULOONG2F)
DO_CHECKA1 (machtype_fuloong2e_str, GRUB_ARCH_MACHINE_FULOONG2E)
DO_CHECKA1 (pmon_fuloong2f_str, GRUB_ARCH_MACHINE_FULOONG2F)
addiu $a0, $a0, -1
b argdone
addiu $a1, $a1, 4
@ -224,9 +240,9 @@ cmdlinedone:
subu $a0, $a0, $t0
addu $a0, $a0, $s0
lw $a1, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0)
lw $a2, (GRUB_KERNEL_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0)
lw $a3, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0)
lw $a1, (GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0)
lw $a2, (GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0)
lw $a3, (GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0)
move $s1, $a1
/* $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/>.
*/
#include <grub/boot.h>
#include <grub/machine/boot.h>
.text
@ -29,9 +28,6 @@ pic_base:
call boot_continue
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
* 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.
@ -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
* load address plus the size of the prepended A.OUT header (32 bytes).
*/
. = _start + GRUB_BOOT_MACHINE_BOOT_DEVPATH
boot_path:
. = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE
boot_path_end:

View file

@ -17,7 +17,6 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/boot.h>
#include <grub/machine/boot.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)
return grub_error (GRUB_ERR_IO, "SM stalled");
}
return GRUB_ERR_NONE;
}
grub_err_t
@ -281,7 +279,7 @@ grub_cs5536_init_geode (grub_pci_device_t dev)
| GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0
| GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1);
break;
case GRUB_ARCH_MACHINE_FULOONG:
case GRUB_ARCH_MACHINE_FULOONG2F:
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LEG_IO,
GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3
| GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1

View file

@ -115,16 +115,6 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook)
continue;
}
#ifdef GRUB_MACHINE_MIPS_LOONGSON
/* Skip ghosts. */
if (id == GRUB_LOONGSON_OHCI_PCIID
&& dev.function == GRUB_LOONGSON_OHCI_GHOST_FUNCTION)
continue;
if (id == GRUB_LOONGSON_EHCI_PCIID
&& dev.function == GRUB_LOONGSON_EHCI_GHOST_FUNCTION)
continue;
#endif
if (hook (dev, id))
return;

View file

@ -454,10 +454,12 @@ grub_ohci_pci_iter (grub_pci_device_t dev,
fail:
if (o)
{
grub_dma_free (o->td_chunk);
grub_dma_free (o->ed_bulk_chunk);
grub_dma_free (o->ed_ctrl_chunk);
grub_dma_free (o->hcca_chunk);
}
grub_free (o);
return 0;
@ -1150,8 +1152,8 @@ grub_ohci_check_transfer (grub_usb_controller_t dev,
return parse_halt (dev, transfer, actual);
/* Finished ED detection */
if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf) ==
(grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf) ) /* Empty ED */
if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xfU) ==
(grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xfU) ) /* Empty ED */
{
/* Check the HALT bit */
/* It looks like nonsense - it was tested previously...
@ -1424,18 +1426,22 @@ static struct grub_usb_controller_dev usb_controller =
.detect_dev = grub_ohci_detect_dev
};
static struct grub_preboot *fini_hnd;
GRUB_MOD_INIT(ohci)
{
COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_td) == 32);
COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_ed) == 16);
grub_ohci_inithw ();
grub_usb_controller_dev_register (&usb_controller);
grub_loader_register_preboot_hook (grub_ohci_fini_hw, grub_ohci_restore_hw,
fini_hnd = grub_loader_register_preboot_hook (grub_ohci_fini_hw,
grub_ohci_restore_hw,
GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
}
GRUB_MOD_FINI(ohci)
{
grub_ohci_fini_hw (0);
grub_loader_unregister_preboot_hook (fini_hnd);
grub_usb_controller_dev_unregister (&usb_controller);
}

View file

@ -36,11 +36,33 @@ GRUB_MOD_LICENSE ("GPLv3+");
typedef enum
{
GRUB_UHCI_REG_USBCMD = 0x00,
GRUB_UHCI_REG_USBINTR = 0x04,
GRUB_UHCI_REG_FLBASEADD = 0x08,
GRUB_UHCI_REG_PORTSC1 = 0x10,
GRUB_UHCI_REG_PORTSC2 = 0x12
GRUB_UHCI_REG_PORTSC2 = 0x12,
GRUB_UHCI_REG_USBLEGSUP = 0xc0
} grub_uhci_reg_t;
/* R/WC legacy support bits */
#define GRUB_UHCI_LEGSUP_END_A20GATE (1 << 15)
#define GRUB_UHCI_TRAP_BY_64H_WSTAT (1 << 11)
#define GRUB_UHCI_TRAP_BY_64H_RSTAT (1 << 10)
#define GRUB_UHCI_TRAP_BY_60H_WSTAT (1 << 9)
#define GRUB_UHCI_TRAP_BY_60H_RSTAT (1 << 8)
/* Reset all legacy support - clear all R/WC bits and all R/W bits */
#define GRUB_UHCI_RESET_LEGSUP_SMI ( GRUB_UHCI_LEGSUP_END_A20GATE \
| GRUB_UHCI_TRAP_BY_64H_WSTAT \
| GRUB_UHCI_TRAP_BY_64H_RSTAT \
| GRUB_UHCI_TRAP_BY_60H_WSTAT \
| GRUB_UHCI_TRAP_BY_60H_RSTAT )
/* Some UHCI commands */
#define GRUB_UHCI_CMD_RUN_STOP (1 << 0)
#define GRUB_UHCI_CMD_HCRESET (1 << 1)
#define GRUB_UHCI_CMD_MAXP (1 << 7)
/* Important bits in structures */
#define GRUB_UHCI_LINK_TERMINATE 1
#define GRUB_UHCI_LINK_QUEUE_HEAD 2
@ -181,6 +203,11 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
if (class != 0x0c || subclass != 0x03 || interf != 0x00)
return 0;
/* Set bus master - needed for coreboot or broken BIOSes */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
grub_pci_write_word(addr,
GRUB_PCI_COMMAND_BUS_MASTER | grub_pci_read_word(addr));
/* Determine IO base address. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG4);
base = grub_pci_read (addr);
@ -195,6 +222,19 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
u->iobase = base & GRUB_UHCI_IOMASK;
/* Reset PIRQ and SMI */
addr = grub_pci_make_address (dev, GRUB_UHCI_REG_USBLEGSUP);
grub_pci_write_word(addr, GRUB_UHCI_RESET_LEGSUP_SMI);
/* Reset the HC */
grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, GRUB_UHCI_CMD_HCRESET);
grub_millisleep(5);
/* Disable interrupts and commands (just to be safe) */
grub_uhci_writereg16(u, GRUB_UHCI_REG_USBINTR, 0);
/* Finish HC reset, HC remains disabled */
grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, 0);
/* Read back to be sure PCI write is done */
grub_uhci_readreg16(u, GRUB_UHCI_REG_USBCMD);
/* Reserve a page for the frame list. */
u->framelist = grub_memalign (4096, 4096);
if (! u->framelist)
@ -252,9 +292,6 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
u->td[N_TD - 2].linkptr = 0;
u->tdfree = u->td;
/* Make sure UHCI is disabled! */
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 0);
/* Setup the frame list pointers. Since no isochronous transfers
are and will be supported, they all point to the (same!) queue
head. */
@ -285,7 +322,8 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
u->qh[N_QH - 1].linkptr = 1;
/* Enable UHCI again. */
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 1 | (1 << 7));
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD,
GRUB_UHCI_CMD_RUN_STOP | GRUB_UHCI_CMD_MAXP);
/* UHCI is initialized and ready for transfers. */
grub_dprintf ("uhci", "UHCI initialized\n");
@ -506,8 +544,11 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev,
{
grub_size_t actual = 0;
/* Terminate and free. */
if (td_prev)
{
td_prev->linkptr2 = 0;
td_prev->linkptr = 1;
}
if (cdata->td_first)
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;
}
#if defined (__i386__) || defined (__x86_64__)
grub_err_t
grub_acpi_create_ebda (void)
{
@ -165,7 +166,7 @@ grub_acpi_create_ebda (void)
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;
if (! ebda || ebda_kb_len > 16)
ebda_kb_len = 0;
@ -173,14 +174,14 @@ grub_acpi_create_ebda (void)
/* FIXME: use low-memory mm allocation once it's available. */
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",
(unsigned long long) highestlow);
if (! highestlow)
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
"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);
if (! mmapregion)
return grub_errno;
@ -297,6 +298,7 @@ grub_acpi_create_ebda (void)
return GRUB_ERR_NONE;
}
#endif
/* Create tables common to ACPIv1 and ACPIv2+ */
static void
@ -328,13 +330,13 @@ setup_common_tables (void)
if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE,
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;
/* Does a revision 2 exist at all? */
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;
}
@ -365,7 +367,7 @@ setup_common_tables (void)
rsdt->creator_rev = root_creator_rev;
for (cur = acpi_tables; cur; cur = cur->next)
*(rsdt_entry++) = PTR_TO_UINT32 (cur->addr);
*(rsdt_entry++) = (grub_addr_t) cur->addr;
/* Recompute checksum. */
rsdt->checksum = 0;
@ -383,7 +385,7 @@ setv1table (void)
sizeof (rsdpv1_new->signature));
grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid));
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 = 1 + ~grub_byte_checksum (rsdpv1_new,
sizeof (*rsdpv1_new));
@ -408,7 +410,7 @@ setv2table (void)
xsdt_entry = (grub_uint64_t *)(xsdt + 1);
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);
xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables;
xsdt->revision = 1;
@ -428,12 +430,12 @@ setv2table (void)
grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid,
sizeof (rsdpv2_new->rsdpv1.oemid));
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 = 1 + ~grub_byte_checksum
(&(rsdpv2_new->rsdpv1), sizeof (rsdpv2_new->rsdpv1));
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 = 1 + ~grub_byte_checksum (rsdpv2_new,
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_acpi_rsdp_v10 *rsdp;
struct efiemu_acpi_table *cur, *t;
grub_err_t err;
int i, mmapregion;
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. */
rev1 = ! 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. */
for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
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];
struct efiemu_acpi_table *table;
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;
for (i = 0; i < 4;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. */
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"))
&& (! load_only || grub_strword (load_only, "dsdt"))
&& dsdt->length >= sizeof (*dsdt))
@ -732,13 +733,20 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
}
acpi_tables = 0;
if (! state[9].set && (err = grub_acpi_create_ebda ()))
#if defined (__i386__) || defined (__x86_64__)
if (! state[9].set)
{
grub_err_t err;
err = grub_acpi_create_ebda ();
if (err)
{
rsdpv1_new = 0;
rsdpv2_new = 0;
grub_mmap_free_and_unregister (mmapregion);
return err;
}
}
#endif
#ifdef GRUB_MACHINE_EFI
{

View file

@ -33,6 +33,7 @@ typedef uint8_t grub_uint8_t;
#endif
#include <grub/acpi.h>
#include <grub/i18n.h>
#ifndef GRUB_DSDT_TEST
#include <grub/misc.h>
@ -327,6 +328,6 @@ grub_acpi_halt (void)
grub_millisleep (1500);
grub_printf ("ACPI shutdown failed\n");
grub_puts_ (N_("ACPI shutdown failed"));
}
#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 int grub_loader_noreturn;
struct grub_preboot_t
struct grub_preboot
{
grub_err_t (*preboot_func) (int);
grub_err_t (*preboot_rest_func) (void);
grub_loader_preboot_hook_prio_t prio;
struct grub_preboot_t *next;
struct grub_preboot_t *prev;
struct grub_preboot *next;
struct grub_preboot *prev;
};
static int grub_loader_loaded;
static struct grub_preboot_t *preboots_head = 0,
static struct grub_preboot *preboots_head = 0,
*preboots_tail = 0;
int
@ -51,18 +51,18 @@ grub_loader_is_loaded (void)
}
/* Register a preboot hook. */
void *
struct grub_preboot *
grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
grub_err_t (*preboot_rest_func) (void),
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)
return 0;
new_preboot = (struct grub_preboot_t *)
grub_malloc (sizeof (struct grub_preboot_t));
new_preboot = (struct grub_preboot *)
grub_malloc (sizeof (struct grub_preboot));
if (! new_preboot)
{
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
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)
preb->next->prev = preb->prev;
@ -143,7 +143,7 @@ grub_err_t
grub_loader_boot (void)
{
grub_err_t err = GRUB_ERR_NONE;
struct grub_preboot_t *cur;
struct grub_preboot *cur;
if (! grub_loader_loaded)
return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel");

View file

@ -0,0 +1,58 @@
/* cacheinfo.c - disk cache statistics */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2010 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/dl.h>
#include <grub/misc.h>
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub/disk.h>
static grub_err_t
grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
unsigned long hits, misses;
grub_disk_cache_get_performance (&hits, &misses);
grub_printf_ (N_("Disk cache: hits = %lu, misses = %lu "), hits, misses);
if (hits + misses)
{
unsigned long ratio = hits * 10000 / (hits + misses);
grub_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100);
}
else
grub_puts_ (N_("(N/A)"));
return 0;
}
static grub_command_t cmd_cacheinfo;
GRUB_MOD_INIT(cacheinfo)
{
cmd_cacheinfo =
grub_register_command ("cacheinfo", grub_rescue_cmd_info,
0, N_("Get disk cache info."));
}
GRUB_MOD_FINI(cacheinfo)
{
grub_unregister_command (cmd_cacheinfo);
}

View file

@ -42,7 +42,7 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
if (argc != 2)
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]);
file1 = grub_file_open (args[0]);
@ -51,7 +51,7 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
goto cleanup;
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 (file2), args[1]);
else
@ -78,9 +78,9 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
{
if (buf1[i] != buf2[i])
{
grub_printf ("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n",
(unsigned long long) (i + pos), buf1[i], args[0],
buf2[i], args[1]);
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], buf2[i], args[1]);
goto cleanup;
}
}
@ -89,14 +89,13 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
}
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:
if (buf1)
grub_free (buf1);
if (buf2)
grub_free (buf2);
if (file1)
grub_file_close (file1);

View file

@ -56,24 +56,24 @@ scan_card (grub_pci_device_t dev, grub_pci_id_t pciid)
{
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;
base = grub_pci_read (addr);
if ((! base) || (base & GRUB_PCI_ADDR_SPACE_IO) ||
(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
{
base &= GRUB_PCI_ADDR_MEM_MASK;
base += p->mmio_reg;
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
{
*((volatile grub_uint32_t *) base) = 0;
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++;
}
grub_printf ("Unknown graphic card: %x\n", pciid);
grub_dprintf ("fixvideo", "Unknown graphic card: %x\n", pciid);
}
return 0;

View file

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

View file

@ -231,7 +231,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
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;
}

View file

@ -24,13 +24,12 @@
GRUB_MOD_LICENSE ("GPLv3+");
static grub_err_t
static grub_err_t __attribute__ ((noreturn))
grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
grub_halt ();
return 0;
}
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);
if (err)
{
grub_printf ("%s: READ ERROR\n", p);
grub_printf_ (N_("%s: READ ERROR\n"), p);
if (!keep)
{
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)
{
grub_printf ("%s: HASH MISMATCH\n", p);
grub_printf_ (N_("%s: HASH MISMATCH\n"), p);
if (!keep)
{
grub_file_close (hashlist);
@ -166,7 +166,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
mismatch++;
continue;
}
grub_printf ("%s: OK\n", p);
grub_printf_ (N_("%s: OK\n"), p);
}
if (mismatch || unread)
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)
{
cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0,
"hashsum -h HASH [-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]",
N_("-h HASH [-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]"),
N_("Compute or check hash checksum."),
options);
cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, 0,

View file

@ -18,6 +18,7 @@
*/
#include <grub/ata.h>
#include <grub/scsi.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/misc.h>
@ -63,60 +64,64 @@ enum grub_ata_smart_commands
static int quiet = 0;
static grub_err_t
grub_hdparm_do_ata_cmd (grub_disk_t disk, grub_uint8_t cmd,
grub_hdparm_do_ata_cmd (grub_ata_t ata, grub_uint8_t cmd,
grub_uint8_t features, grub_uint8_t sectors,
void * buffer, int size)
{
struct grub_disk_ata_pass_through_parms apt;
grub_memset (&apt, 0, sizeof (apt));
apt.taskfile[GRUB_ATA_REG_CMD] = cmd;
apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
apt.taskfile[GRUB_ATA_REG_SECTORS] = sectors;
apt.taskfile.cmd = cmd;
apt.taskfile.features = features;
apt.taskfile.sectors = sectors;
apt.taskfile.disk = 0xE0;
apt.buffer = buffer;
apt.size = size;
if (grub_disk_ata_pass_through (disk, &apt))
if (ata->dev->readwrite (ata, &apt, 0))
return grub_errno;
return GRUB_ERR_NONE;
}
static int
grub_hdparm_do_check_powermode_cmd (grub_disk_t disk)
grub_hdparm_do_check_powermode_cmd (grub_ata_t ata)
{
struct grub_disk_ata_pass_through_parms apt;
grub_memset (&apt, 0, sizeof (apt));
apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_CHECK_POWER_MODE;
apt.taskfile.cmd = GRUB_ATA_CMD_CHECK_POWER_MODE;
apt.taskfile.disk = 0xE0;
if (grub_disk_ata_pass_through (disk, &apt))
if (ata->dev->readwrite (ata, &apt, 0))
return -1;
return apt.taskfile[GRUB_ATA_REG_SECTORS];
return apt.taskfile.sectors;
}
static int
grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features)
grub_hdparm_do_smart_cmd (grub_ata_t ata, grub_uint8_t features)
{
struct grub_disk_ata_pass_through_parms apt;
grub_memset (&apt, 0, sizeof (apt));
apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_SMART;
apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
apt.taskfile[GRUB_ATA_REG_LBAMID] = 0x4f;
apt.taskfile[GRUB_ATA_REG_LBAHIGH] = 0xc2;
apt.taskfile.cmd = GRUB_ATA_CMD_SMART;
apt.taskfile.features = features;
apt.taskfile.lba_mid = 0x4f;
apt.taskfile.lba_high = 0xc2;
apt.taskfile.disk = 0xE0;
if (grub_disk_ata_pass_through (disk, &apt))
if (ata->dev->readwrite (ata, &apt, 0))
return -1;
if (features == GRUB_ATA_FEAT_SMART_STATUS)
{
if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0x4f
&& apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0xc2)
if ( apt.taskfile.lba_mid == 0x4f
&& apt.taskfile.lba_high == 0xc2)
return 0; /* Good SMART status. */
else if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0xf4
&& apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0x2c)
else if ( apt.taskfile.lba_mid == 0xf4
&& apt.taskfile.lba_high == 0x2c)
return 1; /* Bad SMART status. */
else
return -1;
@ -126,12 +131,12 @@ grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features)
static grub_err_t
grub_hdparm_simple_cmd (const char * msg,
grub_disk_t disk, grub_uint8_t cmd)
grub_ata_t ata, grub_uint8_t cmd)
{
if (! quiet && msg)
grub_printf ("%s", msg);
grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, 0, 0, NULL, 0);
grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, 0, 0, NULL, 0);
if (! quiet && msg)
grub_printf ("%s\n", ! err ? "" : ": not supported");
@ -140,7 +145,7 @@ grub_hdparm_simple_cmd (const char * msg,
static grub_err_t
grub_hdparm_set_val_cmd (const char * msg, int val,
grub_disk_t disk, grub_uint8_t cmd,
grub_ata_t ata, grub_uint8_t cmd,
grub_uint8_t features, grub_uint8_t sectors)
{
if (! quiet && msg && *msg)
@ -151,7 +156,7 @@ grub_hdparm_set_val_cmd (const char * msg, int val,
grub_printf ("Disable %s", msg);
}
grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, features, sectors,
grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, features, sectors,
NULL, 0);
if (! quiet && msg)
@ -160,22 +165,20 @@ grub_hdparm_set_val_cmd (const char * msg, int val,
}
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;
for (i = 0; i < bytes / 2; i++)
dest16[i] = grub_be_to_cpu16 (src16[i]);
return dest;
dest[i] = grub_be_to_cpu16 (src16[i]);
dest[i] = 0;
return (char *) dest;
}
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. */
char tmp[40];
grub_uint16_t tmp[21];
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 ("Serial: \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20));
@ -275,6 +278,7 @@ static grub_err_t
grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
{
struct grub_arg_list *state = ctxt->state;
struct grub_ata *ata;
/* Check command line. */
if (argc != 1)
@ -285,9 +289,6 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
return grub_error (GRUB_ERR_BAD_ARGUMENT, "argument is not a device name");
args[0][len - 1] = 0;
if (! grub_disk_ata_pass_through)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "ATA pass through not available");
int i = 0;
int apm = get_int_arg (&state[i++]);
int power = state[i++].set;
@ -313,15 +314,37 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
return grub_error (GRUB_ERR_BAD_ARGUMENT, "partition not allowed");
}
switch (disk->dev->id)
{
case GRUB_DISK_DEVICE_ATA_ID:
ata = disk->data;
break;
case GRUB_DISK_DEVICE_SCSI_ID:
if (((disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF)
== GRUB_SCSI_SUBSYSTEM_PATA
|| (((disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF)
== GRUB_SCSI_SUBSYSTEM_AHCI))
{
ata = ((struct grub_scsi *) disk->data)->data;
break;
}
default:
return grub_error (GRUB_ERR_IO, "not an ATA device");
}
/* Change settings. */
if (aam >= 0)
grub_hdparm_set_val_cmd ("Automatic Acoustic Management", (aam ? aam : -1),
disk, GRUB_ATA_CMD_SET_FEATURES, (aam ? 0x42 : 0xc2), aam);
ata, GRUB_ATA_CMD_SET_FEATURES,
(aam ? 0x42 : 0xc2), aam);
if (apm >= 0)
grub_hdparm_set_val_cmd ("Advanced Power Management",
(apm != 255 ? apm : -1), disk, GRUB_ATA_CMD_SET_FEATURES,
(apm != 255 ? 0x05 : 0x85), (apm != 255 ? apm : 0));
(apm != 255 ? apm : -1), ata,
GRUB_ATA_CMD_SET_FEATURES,
(apm != 255 ? 0x05 : 0x85),
(apm != 255 ? apm : 0));
if (standby_tout >= 0)
{
@ -332,28 +355,28 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
grub_printf (")");
}
/* The IDLE cmd sets disk to idle mode and configures standby timer. */
grub_hdparm_set_val_cmd ("", -1, disk, GRUB_ATA_CMD_IDLE, 0, standby_tout);
grub_hdparm_set_val_cmd ("", -1, ata, GRUB_ATA_CMD_IDLE, 0, standby_tout);
}
if (enable_smart >= 0)
{
if (! quiet)
grub_printf ("%sable SMART operations", (enable_smart ? "En" : "Dis"));
int err = grub_hdparm_do_smart_cmd (disk, (enable_smart ?
int err = grub_hdparm_do_smart_cmd (ata, (enable_smart ?
GRUB_ATA_FEAT_SMART_ENABLE : GRUB_ATA_FEAT_SMART_DISABLE));
if (! quiet)
grub_printf ("%s\n", err ? ": not supported" : "");
}
if (sec_freeze)
grub_hdparm_simple_cmd ("Freeze security settings", disk,
grub_hdparm_simple_cmd ("Freeze security settings", ata,
GRUB_ATA_CMD_SECURITY_FREEZE_LOCK);
/* Print/dump IDENTIFY. */
if (ident || dumpid)
{
char buf[GRUB_DISK_SECTOR_SIZE];
if (grub_hdparm_do_ata_cmd (disk, GRUB_ATA_CMD_IDENTIFY_DEVICE,
grub_uint16_t buf[GRUB_DISK_SECTOR_SIZE / 2];
if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE,
0, 0, buf, sizeof (buf)))
grub_printf ("Cannot read ATA IDENTIFY data\n");
else
@ -361,7 +384,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
if (ident)
grub_hdparm_print_identify (buf);
if (dumpid)
hexdump (0, buf, sizeof (buf));
hexdump (0, (char *) buf, sizeof (buf));
}
}
@ -369,7 +392,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
if (power)
{
grub_printf ("Disk power mode is: ");
int mode = grub_hdparm_do_check_powermode_cmd (disk);
int mode = grub_hdparm_do_check_powermode_cmd (ata);
if (mode < 0)
grub_printf ("unknown\n");
else
@ -385,7 +408,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
{
if (! quiet)
grub_printf ("SMART status is: ");
int err = grub_hdparm_do_smart_cmd (disk, GRUB_ATA_FEAT_SMART_STATUS);
int err = grub_hdparm_do_smart_cmd (ata, GRUB_ATA_FEAT_SMART_STATUS);
if (! quiet)
grub_printf ("%s\n", (err < 0 ? "unknown" :
err == 0 ? "OK" : "*BAD*"));
@ -394,11 +417,11 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
/* Change power mode. */
if (standby_now)
grub_hdparm_simple_cmd ("Set disk to standby mode", disk,
grub_hdparm_simple_cmd ("Set disk to standby mode", ata,
GRUB_ATA_CMD_STANDBY_IMMEDIATE);
if (sleep_now)
grub_hdparm_simple_cmd ("Set disk to sleep mode", disk,
grub_hdparm_simple_cmd ("Set disk to sleep mode", ata,
GRUB_ATA_CMD_SLEEP);
grub_disk_close (disk);

View file

@ -20,6 +20,7 @@
#include <grub/command.h>
#include <grub/misc.h>
#include <grub/cmos.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -46,12 +47,17 @@ grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)),
{
int byte, bit;
grub_err_t err;
grub_uint8_t value;
err = parse_args (argc, argv, &byte, &bit);
if (err)
return err;
if (grub_cmos_read (byte) & (1 << bit))
err = grub_cmos_read (byte, &value);
if (err)
return err;
if (value & (1 << bit))
return GRUB_ERR_NONE;
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
@ -63,13 +69,16 @@ grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)),
{
int byte, bit;
grub_err_t err;
grub_uint8_t value;
err = parse_args (argc, argv, &byte, &bit);
if (err)
return err;
err = grub_cmos_read (byte, &value);
if (err)
return err;
grub_cmos_write (byte, grub_cmos_read (byte) & (~(1 << bit)));
return GRUB_ERR_NONE;
return grub_cmos_write (byte, value & (~(1 << bit)));
}
static grub_command_t cmd, cmd_clean;
@ -78,11 +87,11 @@ static grub_command_t cmd, cmd_clean;
GRUB_MOD_INIT(cmostest)
{
cmd = grub_register_command ("cmostest", grub_cmd_cmostest,
"cmostest BYTE:BIT",
"Test bit at BYTE:BIT in CMOS.");
N_("BYTE:BIT"),
N_("Test bit at BYTE:BIT in CMOS."));
cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean,
"cmosclean BYTE:BIT",
"Clean bit at BYTE:BIT in CMOS.");
N_("BYTE:BIT"),
N_("Clean bit at BYTE:BIT in CMOS."));
}
GRUB_MOD_FINI(cmostest)

View file

@ -32,7 +32,7 @@
GRUB_MOD_LICENSE ("GPLv3+");
/* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */
static grub_uint32_t *const int13slot = UINT_TO_PTR (4 * 0x13);
static grub_uint32_t *const int13slot = (grub_uint32_t *) (4 * 0x13);
/* Remember to update enum opt_idxs accordingly. */
static const struct grub_arg_option options[] = {
@ -178,11 +178,11 @@ list_mappings (void)
/* Show: list mappings. */
if (! map_head)
{
grub_printf ("No drives have been remapped\n");
grub_puts_ (N_("No drives have been remapped"));
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;
while (curnode)
{
@ -363,7 +363,7 @@ uninstall_int13_handler (void)
static int
grub_get_root_biosnumber_drivemap (void)
{
char *biosnum;
const char *biosnum;
int ret = -1;
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))
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"
"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.cseg, info.cseg_len, info.offset,
info.cseg_16, info.cseg_16_len,
info.dseg, info.dseg_len);
grub_xputs (info.flags & GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED
? "16-bit protected interface supported\n"
: "16-bit protected interface unsupported\n");
? _("16-bit protected interface supported\n")
: _("16-bit protected interface unsupported\n"));
grub_xputs (info.flags & GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED
? "32-bit protected interface supported\n"
: "32-bit protected interface unsupported\n");
? _("32-bit protected interface supported\n")
: _("32-bit protected interface unsupported\n"));
grub_xputs (info.flags & GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN
? "CPU Idle slows down processor\n"
: "CPU Idle doesn't slow down processor\n");
? _("CPU Idle slows down processor\n")
: _("CPU Idle doesn't slow down processor\n"));
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
? "APM disengaged\n" : "APM engaged\n");
? _("APM disengaged\n") : _("APM engaged\n"));
return GRUB_ERR_NONE;
}

View file

@ -192,7 +192,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
file = grub_file_open (args[0]);
if (! file)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]);
if (grub_file_read (file, &tempo, sizeof (tempo)) != sizeof (tempo))
{
@ -227,7 +227,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
if (*end)
/* Was not a number either, assume it was supposed to be a file name. */
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]);
grub_dprintf ("play","tempo = %d\n", tempo);

View file

@ -1,54 +0,0 @@
/* pxe.c - command to control the pxe driver */
/*
* 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/dl.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/machine/pxe.h>
#include <grub/command.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_err_t
grub_cmd_pxe_unload (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
if (! grub_pxe_pxenv)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment");
grub_pxe_unload ();
return 0;
}
static grub_command_t cmd;
GRUB_MOD_INIT(pxecmd)
{
cmd = grub_register_command ("pxe_unload", grub_cmd_pxe_unload,
0,
N_("Unload PXE environment."));
}
GRUB_MOD_FINI(pxecmd)
{
grub_unregister_command (cmd);
}

View file

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

View file

@ -344,7 +344,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
int bsd_part = -1;
{
grub_device_t dev;
char *hdbiasstr;
const char *hdbiasstr;
int hdbias = 0;
hdbiasstr = grub_env_get ("legacy_hdbias");
if (hdbiasstr)
@ -723,7 +723,7 @@ grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unuse
if (argc == 0)
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))
return GRUB_ACCESS_DENIED;

View file

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

View file

@ -31,6 +31,7 @@
#include <grub/extcmd.h>
#include <grub/datetime.h>
#include <grub/i18n.h>
#include <grub/net.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -60,6 +61,22 @@ grub_ls_list_devices (int longlist)
grub_device_iterate (grub_ls_print_devices);
grub_xputs ("\n");
#ifndef GRUB_UTIL
{
grub_net_app_level_t proto;
int first = 1;
FOR_NET_APP_LEVEL (proto)
{
if (first)
grub_puts_ (N_ ("Network protocols:"));
first = 0;
grub_printf ("%s ", proto->name);
}
grub_xputs ("\n");
}
#endif
grub_refresh ();
return 0;

View file

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

View file

@ -29,7 +29,7 @@ struct grub_pci_classname
{
int class;
int subclass;
char *desc;
const char *desc;
};
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[] =
{
{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}
};

View file

@ -28,19 +28,19 @@
static const struct grub_arg_option options[] =
{
{"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,
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,
N_("Keyboard key for this entry."), "KEY", ARG_TYPE_STRING},
N_("Keyboard key for this entry."), N_("KEY"), ARG_TYPE_STRING},
{"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}
};
static struct
{
char *name;
const char *name;
int key;
} hotkey_aliases[] =
{

View file

@ -90,26 +90,6 @@ grub_mini_cmd_help (struct grub_command *cmd __attribute__ ((unused)),
return 0;
}
#if 0
static void
grub_rescue_cmd_info (void)
{
extern void grub_disk_cache_get_performance (unsigned long *,
unsigned long *);
unsigned long hits, misses;
grub_disk_cache_get_performance (&hits, &misses);
grub_printf ("Disk cache: hits = %u, misses = %u ", hits, misses);
if (hits + misses)
{
unsigned long ratio = hits * 10000 / (hits + misses);
grub_printf ("(%u.%u%%)\n", ratio / 100, ratio % 100);
}
else
grub_printf ("(N/A)\n");
}
#endif
/* dump ADDRESS [SIZE] */
static grub_err_t
grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)),
@ -165,7 +145,7 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
{
grub_dl_t mod;
grub_printf ("Name\tRef Count\tDependencies\n");
grub_printf_ (N_("Name\tRef Count\tDependencies\n"));
FOR_DL_MODULES (mod)
{
grub_dl_dep_t dep;
@ -185,13 +165,13 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
}
/* exit */
static grub_err_t
static grub_err_t __attribute__ ((noreturn))
grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
grub_exit ();
return 0;
/* Not reached. */
}
static grub_command_t cmd_cat, cmd_help;

View file

@ -23,6 +23,7 @@
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/cs5536.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -38,43 +39,44 @@ grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)),
if (!grub_cs5536_find (&dev))
{
grub_printf ("No CS5536 found\n");
grub_puts_ (N_("No CS5536 found"));
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));
err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase);
if (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;
i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++)
{
struct grub_smbus_spd 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);
if (err)
{
grub_print_error ();
continue;
}
grub_printf ("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_("Written SPD bytes: %d B.\n"), spd.written_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)
{
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,
sizeof (spd.ddr2.part_number));
str[sizeof (spd.ddr2.part_number)] = 0;
grub_printf ("Part no: %s.\n", str);
grub_printf_ (N_("Part no: %s.\n"), str);
}
else
grub_printf ("Memory type: Unknown.\n");
grub_puts_ (N_("Memory type: Unknown."));
}
return GRUB_ERR_NONE;
@ -85,7 +87,7 @@ static grub_command_t cmd;
GRUB_MOD_INIT(lsspd)
{
cmd = grub_register_command ("lsspd", grub_cmd_lsspd, 0,
"Print Memory information.");
N_("Print Memory information."));
}
GRUB_MOD_FINI(lsspd)

View file

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

View file

@ -74,7 +74,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
{
const char *val = "none";
if (dev->net)
val = dev->net->dev->name;
val = dev->net->protocol->name;
if (dev->disk)
val = dev->disk->dev->name;
if (state[0].set)
@ -136,7 +136,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
return err;
if (! label)
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)
grub_env_set (state[0].arg, label);

View file

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

View file

@ -66,12 +66,12 @@ static struct pci_register pci_registers[] =
static const struct grub_arg_option options[] =
{
{0, 'd', 0, "Select device by vendor and device IDs.",
"[vendor]:[device]", ARG_TYPE_STRING},
{0, 's', 0, "Select device by its position on the bus.",
"[bus]:[slot][.func]", ARG_TYPE_STRING},
{0, 'v', 0, "Save read value into variable VARNAME.",
"VARNAME", ARG_TYPE_STRING},
{0, 'd', 0, N_("Select device by vendor and device IDs."),
N_("[vendor]:[device]"), ARG_TYPE_STRING},
{0, 's', 0, N_("Select device by its position on the bus."),
N_("[bus]:[slot][.func]"), ARG_TYPE_STRING},
{0, 'v', 0, N_("Save read value into variable VARNAME."),
N_("VARNAME"), ARG_TYPE_STRING},
{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)
{
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_device (dev),
grub_pci_get_function (dev),

68
grub-core/commands/time.c Normal file
View file

@ -0,0 +1,68 @@
/* echo.c - Command to display a line of text */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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 <grub/time.h>
#include <grub/misc.h>
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_err_t
grub_cmd_time (grub_command_t ctxt __attribute__ ((unused)),
int argc, char **args)
{
grub_command_t cmd;
grub_uint32_t start;
grub_uint32_t end;
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "command expected");
cmd = grub_command_find (args[0]);
if (!cmd)
return grub_error (GRUB_ERR_UNKNOWN_COMMAND, "Unknown command `%s'\n",
args[0]);
start = grub_get_time_ms ();
(cmd->func) (cmd, argc - 1, &args[1]);
end = grub_get_time_ms ();
grub_printf_ (N_("Elapsed time: %d.%03d seconds \n"), (end - start) / 1000,
(end - start) % 1000);
return grub_errno;
}
static grub_command_t cmd;
GRUB_MOD_INIT(time)
{
cmd = grub_register_command ("time", grub_cmd_time,
N_("COMMAND [ARGS]"),
N_("Measure time used by COMMAND"));
}
GRUB_MOD_FINI(time)
{
grub_unregister_command (cmd);
}

View file

@ -28,6 +28,7 @@
GRUB_MOD_LICENSE ("GPLv3+");
static unsigned height, width, depth;
static struct grub_video_mode_info *current_mode;
static int
hook (const struct grub_video_mode_info *info)
@ -41,14 +42,20 @@ hook (const struct grub_video_mode_info *info)
if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID)
grub_printf (" ");
else
{
if (current_mode && info->mode_number == current_mode->mode_number)
grub_printf ("*");
else
grub_printf (" ");
grub_printf (" 0x%03x ", info->mode_number);
}
grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp);
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. */
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->green_mask_size,
info->blue_mask_size,
@ -58,27 +65,51 @@ hook (const struct grub_video_mode_info *info)
info->blue_field_pos,
info->reserved_field_pos);
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)
grub_printf ("YUV ");
grub_xputs (_("YUV "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR)
grub_printf ("Planar ");
grub_xputs (_("Planar "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES)
grub_printf ("Hercules ");
grub_xputs (_("Hercules "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA)
grub_printf ("CGA ");
grub_xputs (_("CGA "));
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)
grub_printf ("Monochrome ");
grub_xputs (_("Monochrome "));
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN)
grub_printf ("Unknown ");
grub_xputs (_("Unknown "));
grub_printf ("\n");
grub_xputs ("\n");
return 0;
}
static void
print_edid (struct grub_video_edid_info *edid_info)
{
unsigned int edid_width, edid_height;
if (grub_video_edid_checksum (edid_info))
{
grub_puts_ (N_(" EDID checksum invalid"));
grub_errno = GRUB_ERR_NONE;
return;
}
grub_printf_ (N_(" EDID version: %u.%u\n"),
edid_info->version, edid_info->revision);
if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height)
== GRUB_ERR_NONE)
grub_printf_ (N_(" Preferred mode: %ux%u\n"), edid_width, edid_height);
else
{
grub_printf_ (N_(" No preferred mode available\n"));
grub_errno = GRUB_ERR_NONE;
}
}
static grub_err_t
grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
@ -116,25 +147,38 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
id = grub_video_get_driver_id ();
grub_printf ("List of supported video modes:\n");
grub_printf ("Legend: P=Packed pixel, D=Direct color, "
"mask/pos=R/G/B/reserved\n");
grub_puts_ (N_("List of supported video modes:"));
grub_puts_ (N_("Legend: P=Packed pixel, D=Direct color, "
"mask/pos=R/G/B/reserved"));
FOR_VIDEO_ADAPTERS (adapter)
{
grub_printf ("Adapter '%s':\n", adapter->name);
struct grub_video_mode_info info;
struct grub_video_edid_info edid_info;
grub_printf_ (N_("Adapter '%s':\n"), adapter->name);
if (!adapter->iterate)
{
grub_printf (" No info available\n");
grub_puts_ (N_(" No info available"));
continue;
}
if (adapter->id != id)
current_mode = NULL;
if (adapter->id == id)
{
if (grub_video_get_info (&info) == GRUB_ERR_NONE)
current_mode = &info;
else
/* Don't worry about errors. */
grub_errno = GRUB_ERR_NONE;
}
else
{
if (adapter->init ())
{
grub_printf (" Failed\n");
grub_puts_ (N_(" Failed"));
grub_errno = GRUB_ERR_NONE;
continue;
}
@ -145,6 +189,13 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
adapter->iterate (hook);
if (adapter->get_edid && adapter->get_edid (&edid_info) == GRUB_ERR_NONE)
print_edid (&edid_info);
else
grub_errno = GRUB_ERR_NONE;
current_mode = NULL;
if (adapter->id != id)
{
if (adapter->fini ())
@ -164,12 +215,13 @@ static grub_command_t cmd_vbe;
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 "
"resolution is given show only modes"
" matching it."));
#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 "
"resolution is given show only modes"
" 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_MODE_TYPE_RGB
| GRUB_VIDEO_MODE_TYPE_ALPHA);
if (!text_layer)
goto fail;
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;
return grub_errno;
fail:
grub_video_delete_render_target (text_layer);
grub_video_restore ();
return grub_errno;
}
static grub_command_t cmd;

View file

@ -139,6 +139,7 @@ make_regex (const char *start, const char *end, regex_t *regexp)
case '.':
case '(':
case ')':
case '@':
buffer[i++] = '\\';
buffer[i++] = ch;
break;
@ -255,7 +256,6 @@ match_devices (const regex_t *regexp, int noparts)
for (i = 0; devs && devs[i]; i++)
grub_free (devs[i]);
if (devs)
grub_free (devs);
return 0;
@ -288,6 +288,8 @@ match_files (const char *prefix, const char *suffix, const char *end,
if (regexec (regexp, name, 0, 0, 0))
return 0;
grub_dprintf ("expand", "matched\n");
buffer = grub_xasprintf ("%s%s", dir, name);
if (! buffer)
return 1;
@ -340,19 +342,16 @@ match_files (const char *prefix, const char *suffix, const char *end,
fail:
if (dir)
grub_free (dir);
for (i = 0; files && files[i]; i++)
grub_free (files[i]);
if (files)
grub_free (files);
if (dev)
grub_device_close (dev);
if (device_name)
grub_free (device_name);
grub_error_pop ();
@ -423,8 +422,6 @@ wildcard_expand (const char *s, char ***strs)
while (*start)
{
split_path (start, &noregexop, &regexop);
if (noregexop >= regexop) /* no more wildcards */
break;
if (make_regex (noregexop, regexop, &regexp))
goto fail;
@ -439,7 +436,7 @@ wildcard_expand (const char *s, char ***strs)
else if (*start == '/') /* no device part */
{
char *root;
const char *root;
char *prefix;
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 *ptr;
grub_uint8_t ctx[GRUB_MD_MD5->contextsize];
int low = 0;
if (argc < 1)
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));
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[12], (unsigned int) xnu_uuid[13],
(unsigned int) xnu_uuid[14], (unsigned int) xnu_uuid[15]);
if (!low)
for (ptr = uuid_string; *ptr; ptr++)
*ptr = grub_toupper (*ptr);
if (argc == 1)
grub_printf ("%s", uuid_string);
grub_printf ("%s\n", uuid_string);
if (argc > 1)
grub_env_set (args[1], uuid_string);
@ -91,9 +100,10 @@ static grub_command_t cmd;
GRUB_MOD_INIT (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 "
"suitable for XNU."));
"suitable for XNU. If -l is given keep "
"it lowercase as done by blkid."));
}
GRUB_MOD_FINI (xnu_uuid)

View file

@ -0,0 +1,89 @@
/*
* AFsplitter - Anti forensic information splitter
* Copyright 2004, Clemens Fruhwirth <clemens@endorphin.org>
*
* AFsplitter diffuses information over a large stripe of data,
* therefor supporting secure data destruction.
*
* This program is grub_free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the grub_free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the grub_free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <grub/crypto.h>
#include <grub/mm.h>
#include <grub/misc.h>
gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
grub_uint8_t * dst, grub_size_t blocksize,
grub_size_t blocknumbers);
static void
diffuse (const gcry_md_spec_t * hash, grub_uint8_t * src,
grub_uint8_t * dst, grub_size_t size)
{
grub_size_t i;
grub_uint32_t IV; /* host byte order independend hash IV */
grub_size_t fullblocks = size / hash->mdlen;
int padding = size % hash->mdlen;
grub_uint8_t final[hash->mdlen];
grub_uint8_t temp[sizeof (IV) + hash->mdlen];
/* hash block the whole data set with different IVs to produce
* more than just a single data block
*/
for (i = 0; i < fullblocks; i++)
{
IV = grub_cpu_to_be32 (i);
grub_memcpy (temp, &IV, sizeof (IV));
grub_memcpy (temp + sizeof (IV), src + hash->mdlen * i, hash->mdlen);
grub_crypto_hash (hash, dst + hash->mdlen * i, temp,
sizeof (IV) + hash->mdlen);
}
if (padding)
{
IV = grub_cpu_to_be32 (i);
grub_memcpy (temp, &IV, sizeof (IV));
grub_memcpy (temp + sizeof (IV), src + hash->mdlen * i, padding);
grub_crypto_hash (hash, final, temp, sizeof (IV) + padding);
grub_memcpy (dst + hash->mdlen * i, final, padding);
}
}
/**
* Merges the splitted master key stored on disk into the original key
*/
gcry_err_code_t
AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst,
grub_size_t blocksize, grub_size_t blocknumbers)
{
grub_size_t i;
grub_uint8_t *bufblock;
bufblock = grub_zalloc (blocksize);
if (bufblock == NULL)
return GPG_ERR_OUT_OF_MEMORY;
grub_memset (bufblock, 0, blocksize);
for (i = 0; i < blocknumbers - 1; i++)
{
grub_crypto_xor (bufblock, src + (blocksize * i), bufblock, blocksize);
diffuse (hash, bufblock, bufblock, blocksize);
}
grub_crypto_xor (dst, src + (i * blocksize), bufblock, blocksize);
grub_free (bufblock);
return GPG_ERR_NO_ERROR;
}

738
grub-core/disk/ahci.c Normal file
View file

@ -0,0 +1,738 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2007, 2008, 2009, 2010 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/dl.h>
#include <grub/disk.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/pci.h>
#include <grub/ata.h>
#include <grub/scsi.h>
#include <grub/misc.h>
#include <grub/list.h>
#include <grub/loader.h>
GRUB_MOD_LICENSE ("GPLv3+");
struct grub_ahci_cmd_head
{
grub_uint32_t config;
grub_uint32_t transfered;
grub_uint64_t command_table_base;
grub_uint32_t unused[4];
};
struct grub_ahci_prdt_entry
{
grub_uint64_t data_base;
grub_uint32_t unused;
grub_uint32_t size;
};
struct grub_ahci_cmd_table
{
grub_uint8_t cfis[0x40];
grub_uint8_t command[0x10];
grub_uint8_t reserved[0x30];
struct grub_ahci_prdt_entry prdt[1];
};
struct grub_ahci_hba_port
{
grub_uint64_t command_list_base;
grub_uint64_t fis_base;
grub_uint32_t intstatus;
grub_uint32_t inten;
grub_uint32_t command;
grub_uint32_t unused1;
grub_uint32_t task_file_data;
grub_uint32_t sig;
grub_uint32_t status;
grub_uint32_t unused2;
grub_uint32_t sata_error;
grub_uint32_t sata_active;
grub_uint32_t command_issue;
grub_uint32_t unused3;
grub_uint32_t fbs;
grub_uint32_t unused4[15];
};
enum grub_ahci_hba_port_command
{
GRUB_AHCI_HBA_PORT_CMD_ST = 0x01,
GRUB_AHCI_HBA_PORT_CMD_FRE = 0x10,
GRUB_AHCI_HBA_PORT_CMD_CR = 0x8000,
GRUB_AHCI_HBA_PORT_CMD_FR = 0x4000,
};
struct grub_ahci_hba
{
grub_uint32_t cap;
grub_uint32_t global_control;
grub_uint32_t intr_status;
grub_uint32_t ports_implemented;
grub_uint32_t unused1[6];
grub_uint32_t bios_handoff;
grub_uint32_t unused2[53];
struct grub_ahci_hba_port ports[32];
};
struct grub_ahci_received_fis
{
char raw[4096];
};
enum
{
GRUB_AHCI_HBA_CAP_NPORTS_MASK = 0x1f
};
enum
{
GRUB_AHCI_HBA_GLOBAL_CONTROL_RESET = 0x00000001,
GRUB_AHCI_HBA_GLOBAL_CONTROL_INTR_EN = 0x00000002,
GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN = 0x80000000,
};
enum
{
GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED = 1,
GRUB_AHCI_BIOS_HANDOFF_OS_OWNED = 2,
GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED = 8,
GRUB_AHCI_BIOS_HANDOFF_RWC = 8
};
struct grub_ahci_device
{
struct grub_ahci_device *next;
volatile struct grub_ahci_hba *hba;
int port;
int num;
struct grub_pci_dma_chunk *command_list_chunk;
volatile struct grub_ahci_cmd_head *command_list;
struct grub_pci_dma_chunk *command_table_chunk;
volatile struct grub_ahci_cmd_table *command_table;
struct grub_pci_dma_chunk *rfis;
int present;
};
static grub_err_t
grub_ahci_readwrite_real (struct grub_ahci_device *dev,
struct grub_disk_ata_pass_through_parms *parms,
int spinup);
enum
{
GRUB_AHCI_CONFIG_READ = 0,
GRUB_AHCI_CONFIG_CFIS_LENGTH_MASK = 0x1f,
GRUB_AHCI_CONFIG_ATAPI = 0x20,
GRUB_AHCI_CONFIG_WRITE = 0x40,
GRUB_AHCI_CONFIG_PREFETCH = 0x80,
GRUB_AHCI_CONFIG_RESET = 0x100,
GRUB_AHCI_CONFIG_BIST = 0x200,
GRUB_AHCI_CONFIG_CLEAR_R_OK = 0x400,
GRUB_AHCI_CONFIG_PMP_MASK = 0xf000,
GRUB_AHCI_CONFIG_PRDT_LENGTH_MASK = 0xffff0000,
};
#define GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT 0
#define GRUB_AHCI_CONFIG_PMP_SHIFT 12
#define GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT 16
#define GRUB_AHCI_INTERRUPT_ON_COMPLETE 0x80000000
#define GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH 0x200000
static struct grub_ahci_device *grub_ahci_devices;
static int numdevs;
static int
init_port (struct grub_ahci_device *dev)
{
struct grub_pci_dma_chunk *command_list;
struct grub_pci_dma_chunk *command_table;
grub_uint64_t endtime;
command_list = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head));
if (!command_list)
return 1;
command_table = grub_memalign_dma32 (1024,
sizeof (struct grub_ahci_cmd_table));
if (!command_table)
{
grub_dma_free (command_list);
return 1;
}
grub_dprintf ("ahci", "found device ahci%d (port %d)\n", dev->num, dev->port);
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
endtime = grub_get_time_ms () + 1000;
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't stop FR\n");
goto out;
}
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
endtime = grub_get_time_ms () + 1000;
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't stop CR\n");
goto out;
}
dev->hba->ports[dev->port].fbs = 2;
dev->rfis = grub_memalign_dma32 (4096,
sizeof (struct grub_ahci_received_fis));
grub_memset ((char *) grub_dma_get_virt (dev->rfis), 0,
sizeof (struct grub_ahci_received_fis));
dev->hba->ports[dev->port].fis_base = grub_dma_get_phys (dev->rfis);
dev->hba->ports[dev->port].command_list_base
= grub_dma_get_phys (command_list);
dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_FRE;
while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't start FR\n");
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
goto out;
}
dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST;
while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't start CR\n");
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_CR;
goto out_stop_fr;
}
dev->hba->ports[dev->port].command
= (dev->hba->ports[dev->port].command & 0x0fffffff) | (1 << 28) | 2 | 4;
dev->command_list_chunk = command_list;
dev->command_list = grub_dma_get_virt (command_list);
dev->command_table_chunk = command_table;
dev->command_table = grub_dma_get_virt (command_table);
dev->command_list->command_table_base
= grub_dma_get_phys (command_table);
return 0;
out_stop_fr:
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
endtime = grub_get_time_ms () + 1000;
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't stop FR\n");
break;
}
out:
grub_dma_free (command_list);
grub_dma_free (command_table);
grub_dma_free (dev->rfis);
return 1;
}
static int NESTED_FUNC_ATTR
grub_ahci_pciinit (grub_pci_device_t dev,
grub_pci_id_t pciid __attribute__ ((unused)))
{
grub_pci_address_t addr;
grub_uint32_t class;
grub_uint32_t bar;
unsigned i, nports;
volatile struct grub_ahci_hba *hba;
/* Read class. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
class = grub_pci_read (addr);
/* Check if this class ID matches that of a PCI IDE Controller. */
if (class >> 8 != 0x010601)
return 0;
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG5);
bar = grub_pci_read (addr);
if ((bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK
| GRUB_PCI_ADDR_MEM_PREFETCH))
!= (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32))
return 0;
hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK,
sizeof (hba));
if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED))
{
grub_uint64_t endtime;
grub_dprintf ("ahci", "Requesting AHCI ownership\n");
hba->bios_handoff = (hba->bios_handoff & ~GRUB_AHCI_BIOS_HANDOFF_RWC)
| GRUB_AHCI_BIOS_HANDOFF_OS_OWNED;
grub_dprintf ("ahci", "Waiting for BIOS to give up ownership\n");
endtime = grub_get_time_ms () + 1000;
while ((hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED)
&& grub_get_time_ms () < endtime);
if (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED)
{
grub_dprintf ("ahci", "Forcibly taking ownership\n");
hba->bios_handoff = GRUB_AHCI_BIOS_HANDOFF_OS_OWNED;
hba->bios_handoff |= GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED;
}
else
grub_dprintf ("ahci", "AHCI ownership obtained\n");
}
else
grub_dprintf ("ahci", "AHCI is already in OS mode\n");
if (!(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN))
grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n");
else
grub_dprintf ("ahci", "AHCI is in AHCI mode.\n");
for (i = 0; i < 5; i++)
{
hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN;
grub_millisleep (1);
if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)
break;
}
if (i == 5)
{
grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n");
return 0;
}
/*
{
grub_uint64_t endtime;
hba->global_control |= 1;
endtime = grub_get_time_ms () + 1000;
while (hba->global_control & 1)
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't reset AHCI\n");
return 0;
}
}
for (i = 0; i < 5; i++)
{
hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN;
grub_millisleep (1);
if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)
break;
}
if (i == 5)
{
grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n");
return 0;
}
*/
nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1;
grub_dprintf ("ahci", "%d AHCI ports\n", nports);
for (i = 0; i < nports; i++)
{
struct grub_ahci_device *adev;
grub_uint32_t st;
if (!(hba->ports_implemented & (1 << i)))
continue;
grub_dprintf ("ahci", "status %d:%x\n", i, hba->ports[i].status);
/* FIXME: support hotplugging. */
st = hba->ports[i].status;
if ((st & 0xf) != 0x3 && (st & 0xf) != 0x1)
continue;
adev = grub_malloc (sizeof (*adev));
if (!adev)
return 1;
adev->hba = hba;
adev->port = i;
adev->present = 1;
adev->num = numdevs++;
if (init_port (adev))
{
grub_free (adev);
return 1;
}
grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices),
GRUB_AS_LIST (adev));
}
return 0;
}
static grub_err_t
grub_ahci_initialize (void)
{
grub_pci_iterate (grub_ahci_pciinit);
return grub_errno;
}
static grub_err_t
grub_ahci_fini_hw (int noreturn __attribute__ ((unused)))
{
struct grub_ahci_device *dev;
for (dev = grub_ahci_devices; dev; dev = dev->next)
{
grub_uint64_t endtime;
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
endtime = grub_get_time_ms () + 1000;
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't stop FR\n");
break;
}
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
endtime = grub_get_time_ms () + 1000;
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't stop CR\n");
break;
}
grub_dma_free (dev->command_list_chunk);
grub_dma_free (dev->command_table_chunk);
grub_dma_free (dev->rfis);
dev->command_list_chunk = NULL;
dev->command_table_chunk = NULL;
dev->rfis = NULL;
}
return GRUB_ERR_NONE;
}
static grub_err_t
grub_ahci_restore_hw (void)
{
struct grub_ahci_device **pdev;
for (pdev = &grub_ahci_devices; *pdev; pdev = &((*pdev)->next))
if (init_port (*pdev))
{
struct grub_ahci_device *odev;
odev = *pdev;
*pdev = (*pdev)->next;
grub_free (odev);
}
return GRUB_ERR_NONE;
}
static int
grub_ahci_iterate (int (*hook) (int id, int bus),
grub_disk_pull_t pull)
{
struct grub_ahci_device *dev;
if (pull != GRUB_DISK_PULL_NONE)
return 0;
FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num))
return 1;
return 0;
}
#if 0
static int
find_free_cmd_slot (struct grub_ahci_device *dev)
{
int i;
for (i = 0; i < 32; i++)
{
if (dev->hda->ports[dev->port].command_issue & (1 << i))
continue;
if (dev->hda->ports[dev->port].sata_active & (1 << i))
continue;
return i;
}
return -1;
}
#endif
enum
{
GRUB_AHCI_FIS_REG_H2D = 0x27
};
static const int register_map[11] = { 3 /* Features */,
12 /* Sectors */,
4 /* LBA low */,
5 /* LBA mid */,
6 /* LBA high */,
7 /* Device */,
2 /* CMD register */,
13 /* Sectors 48 */,
8 /* LBA48 low */,
9 /* LBA48 mid */,
10 /* LBA48 high */ };
static grub_err_t
grub_ahci_readwrite_real (struct grub_ahci_device *dev,
struct grub_disk_ata_pass_through_parms *parms,
int spinup)
{
struct grub_pci_dma_chunk *bufc;
grub_uint64_t endtime;
unsigned i;
grub_err_t err = GRUB_ERR_NONE;
grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data);
if ((dev->hba->ports[dev->port].task_file_data & 0x80))
{
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
endtime = grub_get_time_ms () + 1000;
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't stop CR\n");
break;
}
dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST;
endtime = grub_get_time_ms () + (spinup ? 10000 : 1000);
while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "couldn't start CR\n");
break;
}
}
dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error;
grub_dprintf("ahci", "grub_ahci_read (size=%llu, cmdsize = %llu)\n",
(unsigned long long) parms->size,
(unsigned long long) parms->cmdsize);
if (parms->cmdsize != 0 && parms->cmdsize != 12 && parms->cmdsize != 16)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "incorrect ATAPI command size");
if (parms->size > GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too big data buffer");
bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1));
dev->hba->ports[dev->port].command |= 8;
grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data);
/* FIXME: support port multipliers. */
dev->command_list[0].config
= (5 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT)
// | GRUB_AHCI_CONFIG_CLEAR_R_OK
| (0 << GRUB_AHCI_CONFIG_PMP_SHIFT)
| (1 << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT)
| (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0)
| (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ)
| (parms->taskfile.cmd == 8 ? (1 << 8) : 0);
dev->command_list[0].transfered = 0;
dev->command_list[0].command_table_base
= grub_dma_get_phys (dev->command_table_chunk);
grub_memset ((char *) dev->command_list[0].unused, 0,
sizeof (dev->command_list[0].unused));
grub_memset ((char *) &dev->command_table[0], 0,
sizeof (dev->command_table[0]));
if (parms->cmdsize)
grub_memcpy ((char *) dev->command_table[0].command, parms->cmd,
parms->cmdsize);
dev->command_table[0].cfis[0] = GRUB_AHCI_FIS_REG_H2D;
dev->command_table[0].cfis[1] = 0x80;
for (i = 0; i < sizeof (parms->taskfile.raw); i++)
dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i];
grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n",
dev->command_table[0].cfis[0], dev->command_table[0].cfis[1],
dev->command_table[0].cfis[2], dev->command_table[0].cfis[3],
dev->command_table[0].cfis[4], dev->command_table[0].cfis[5],
dev->command_table[0].cfis[6], dev->command_table[0].cfis[7]);
grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n",
dev->command_table[0].cfis[8], dev->command_table[0].cfis[9],
dev->command_table[0].cfis[10], dev->command_table[0].cfis[11],
dev->command_table[0].cfis[12], dev->command_table[0].cfis[13],
dev->command_table[0].cfis[14], dev->command_table[0].cfis[15]);
dev->command_table[0].prdt[0].data_base = grub_dma_get_phys (bufc);
dev->command_table[0].prdt[0].unused = 0;
dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1)
| GRUB_AHCI_INTERRUPT_ON_COMPLETE;
grub_dprintf ("ahci", "PRDT = %" PRIxGRUB_UINT64_T ", %x, %x (%"
PRIuGRUB_SIZE ")\n",
dev->command_table[0].prdt[0].data_base,
dev->command_table[0].prdt[0].unused,
dev->command_table[0].prdt[0].size,
(char *) &dev->command_table[0].prdt[0]
- (char *) &dev->command_table[0]);
if (parms->write)
grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size);
grub_dprintf ("ahci", "AHCI command schedulded\n");
grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data);
dev->hba->ports[dev->port].inten = 0xffffffff;//(1 << 2) | (1 << 5);
dev->hba->ports[dev->port].intstatus = 0xffffffff;//(1 << 2) | (1 << 5);
grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data);
dev->hba->ports[dev->port].command_issue |= 1;
grub_dprintf ("ahci", "AHCI sig = %x\n", dev->hba->ports[dev->port].sig);
grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data);
endtime = grub_get_time_ms () + (spinup ? 10000 : 1000);
while ((dev->hba->ports[dev->port].command_issue & 1))
if (grub_get_time_ms () > endtime)
{
grub_dprintf ("ahci", "AHCI status <%x %x %x>\n",
dev->hba->ports[dev->port].command_issue,
dev->hba->ports[dev->port].intstatus,
dev->hba->ports[dev->port].task_file_data);
err = grub_error (GRUB_ERR_IO, "AHCI transfer timeouted");
break;
}
grub_dprintf ("ahci", "AHCI command completed <%x %x %x %x %x, %x %x>\n",
dev->hba->ports[dev->port].command_issue,
dev->hba->ports[dev->port].intstatus,
dev->hba->ports[dev->port].task_file_data,
dev->command_list[0].transfered,
dev->hba->ports[dev->port].sata_error,
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x00],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x18]);
grub_dprintf ("ahci",
"last PIO FIS %08x %08x %08x %08x %08x %08x %08x %08x\n",
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x08],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x09],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0a],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0b],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0c],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0d],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0e],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0f]);
grub_dprintf ("ahci",
"last REG FIS %08x %08x %08x %08x %08x %08x %08x %08x\n",
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x10],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x11],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x12],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x13],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x14],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x15],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x16],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x17]);
if (!parms->write)
grub_memcpy (parms->buffer, (char *) grub_dma_get_virt (bufc), parms->size);
grub_dma_free (bufc);
return err;
}
static grub_err_t
grub_ahci_readwrite (grub_ata_t disk,
struct grub_disk_ata_pass_through_parms *parms,
int spinup)
{
return grub_ahci_readwrite_real (disk->data, parms, spinup);
}
static grub_err_t
grub_ahci_open (int id, int devnum, struct grub_ata *ata)
{
struct grub_ahci_device *dev;
if (id != GRUB_SCSI_SUBSYSTEM_AHCI)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an AHCI device");
FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
if (dev->num == devnum)
break;
if (! dev)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such AHCI device");
grub_dprintf ("ahci", "opening AHCI dev `ahci%d'\n", dev->num);
ata->data = dev;
ata->dma = 1;
ata->present = &dev->present;
return GRUB_ERR_NONE;
}
static struct grub_ata_dev grub_ahci_dev =
{
.iterate = grub_ahci_iterate,
.open = grub_ahci_open,
.readwrite = grub_ahci_readwrite,
};
static struct grub_preboot *fini_hnd;
GRUB_MOD_INIT(ahci)
{
/* To prevent two drivers operating on the same disks. */
grub_disk_firmware_is_tainted = 1;
if (grub_disk_firmware_fini)
{
grub_disk_firmware_fini ();
grub_disk_firmware_fini = NULL;
}
/* AHCI initialization. */
grub_ahci_initialize ();
/* AHCI devices are handled by scsi.mod. */
grub_ata_dev_register (&grub_ahci_dev);
fini_hnd = grub_loader_register_preboot_hook (grub_ahci_fini_hw,
grub_ahci_restore_hw,
GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
}
GRUB_MOD_FINI(ahci)
{
grub_ahci_fini_hw (0);
grub_loader_unregister_preboot_hook (fini_hnd);
grub_ata_dev_unregister (&grub_ahci_dev);
}

View file

@ -1,7 +1,7 @@
/* ofdisk.c - Open Firmware disk access. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2006,2007,2008,2009 Free Software Foundation, Inc.
* Copyright (C) 2004,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
@ -79,7 +79,8 @@ arcdisk_hash_add (char *devpath)
static int
grub_arcdisk_iterate (int (*hook_in) (const char *name))
grub_arcdisk_iterate (int (*hook_in) (const char *name),
grub_disk_pull_t pull)
{
auto int hook (const char *name, const struct grub_arc_component *comp);
int hook (const char *name, const struct grub_arc_component *comp)
@ -90,6 +91,9 @@ grub_arcdisk_iterate (int (*hook_in) (const char *name))
return 0;
return hook_in (name);
}
if (pull != GRUB_DISK_PULL_NONE)
return 0;
return grub_arc_iterate_devs (hook, 1);
}
@ -105,11 +109,6 @@ reopen (const char *name)
grub_dprintf ("arcdisk", "using already opened %s\n", name);
return GRUB_ERR_NONE;
}
if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle))
{
grub_dprintf ("arcdisk", "couldn't open %s\n", name);
return grub_error (GRUB_ERR_IO, "couldn't open %s", name);
}
if (last_path)
{
GRUB_ARC_FIRMWARE_VECTOR->close (last_handle);
@ -117,6 +116,11 @@ reopen (const char *name)
last_path = NULL;
last_handle = 0;
}
if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle))
{
grub_dprintf ("arcdisk", "couldn't open %s\n", name);
return grub_error (GRUB_ERR_IO, "couldn't open %s", name);
}
last_path = grub_strdup (name);
if (!last_path)
return grub_errno;

File diff suppressed because it is too large Load diff

View file

@ -1,108 +0,0 @@
/* ata_pthru.c - ATA pass through for ata.mod. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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/ata.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/mm.h>
GRUB_MOD_LICENSE ("GPLv3+");
/* ATA pass through support, used by hdparm.mod. */
static grub_err_t
grub_ata_pass_through (grub_disk_t disk,
struct grub_disk_ata_pass_through_parms *parms)
{
if (disk->dev->id != GRUB_DISK_DEVICE_ATA_ID)
return grub_error (GRUB_ERR_BAD_DEVICE,
"device not accessed via ata.mod");
struct grub_ata_device *dev = (struct grub_ata_device *) disk->data;
if (! (parms->size == 0 || parms->size == GRUB_DISK_SECTOR_SIZE))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"ATA multi-sector read and DATA OUT not implemented");
grub_dprintf ("ata", "ata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x\n",
parms->taskfile[GRUB_ATA_REG_CMD],
parms->taskfile[GRUB_ATA_REG_FEATURES],
parms->taskfile[GRUB_ATA_REG_SECTORS]);
grub_dprintf ("ata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%d\n",
parms->taskfile[GRUB_ATA_REG_LBAHIGH],
parms->taskfile[GRUB_ATA_REG_LBAMID],
parms->taskfile[GRUB_ATA_REG_LBALOW], parms->size);
/* Set registers. */
grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4
| (parms->taskfile[GRUB_ATA_REG_DISK] & 0xf));
if (grub_ata_check_ready (dev))
return grub_errno;
int i;
for (i = GRUB_ATA_REG_FEATURES; i <= GRUB_ATA_REG_LBAHIGH; i++)
grub_ata_regset (dev, i, parms->taskfile[i]);
/* Start command. */
grub_ata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile[GRUB_ATA_REG_CMD]);
/* Wait for !BSY. */
if (grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
return grub_errno;
/* Check status. */
grub_int8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
grub_dprintf ("ata", "status=0x%x\n", sts);
/* Transfer data. */
if ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_DRQ)
{
if (parms->size != GRUB_DISK_SECTOR_SIZE)
return grub_error (GRUB_ERR_READ_ERROR, "DRQ unexpected");
grub_ata_pio_read (dev, parms->buffer, GRUB_DISK_SECTOR_SIZE);
}
/* Return registers. */
for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++)
parms->taskfile[i] = grub_ata_regget (dev, i);
grub_dprintf ("ata", "status=0x%x, error=0x%x, sectors=0x%x\n",
parms->taskfile[GRUB_ATA_REG_STATUS],
parms->taskfile[GRUB_ATA_REG_ERROR],
parms->taskfile[GRUB_ATA_REG_SECTORS]);
if (parms->taskfile[GRUB_ATA_REG_STATUS]
& (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
return grub_error (GRUB_ERR_READ_ERROR, "ATA passthrough failed");
return GRUB_ERR_NONE;
}
GRUB_MOD_INIT(ata_pthru)
{
/* Register ATA pass through function. */
grub_disk_ata_pass_through = grub_ata_pass_through;
}
GRUB_MOD_FINI(ata_pthru)
{
if (grub_disk_ata_pass_through == grub_ata_pass_through)
grub_disk_ata_pass_through = NULL;
}

883
grub-core/disk/cryptodisk.c Normal file
View file

@ -0,0 +1,883 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2007,2010,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 <grub/cryptodisk.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/dl.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
#ifdef GRUB_UTIL
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <grub/emu/hostdisk.h>
#include <unistd.h>
#include <string.h>
#endif
GRUB_MOD_LICENSE ("GPLv3+");
grub_cryptodisk_dev_t grub_cryptodisk_list;
static const struct grub_arg_option options[] =
{
{"uuid", 'u', 0, N_("Mount by UUID."), 0, 0},
{"all", 'a', 0, N_("Mount all."), 0, 0},
{"boot", 'b', 0, N_("Mount all volumes marked as boot."), 0, 0},
{0, 0, 0, 0, 0, 0}
};
/* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */
#define GF_POLYNOM 0x87
static inline int GF_PER_SECTOR (const struct grub_cryptodisk *dev)
{
return 1U << (dev->log_sector_size - GRUB_CRYPTODISK_GF_LOG_BYTES);
}
static grub_cryptodisk_t cryptodisk_list = NULL;
static grub_uint8_t n = 0;
static void
gf_mul_x (grub_uint8_t *g)
{
int over = 0, over2 = 0;
unsigned j;
for (j = 0; j < GRUB_CRYPTODISK_GF_BYTES; j++)
{
over2 = !!(g[j] & 0x80);
g[j] <<= 1;
g[j] |= over;
over = over2;
}
if (over)
g[0] ^= GF_POLYNOM;
}
static void
gf_mul_x_be (grub_uint8_t *g)
{
int over = 0, over2 = 0;
int j;
for (j = (int) GRUB_CRYPTODISK_GF_BYTES - 1; j >= 0; j--)
{
over2 = !!(g[j] & 0x80);
g[j] <<= 1;
g[j] |= over;
over = over2;
}
if (over)
g[GRUB_CRYPTODISK_GF_BYTES - 1] ^= GF_POLYNOM;
}
static void
gf_mul_be (grub_uint8_t *o, const grub_uint8_t *a, const grub_uint8_t *b)
{
unsigned i;
grub_uint8_t t[GRUB_CRYPTODISK_GF_BYTES];
grub_memset (o, 0, GRUB_CRYPTODISK_GF_BYTES);
grub_memcpy (t, b, GRUB_CRYPTODISK_GF_BYTES);
for (i = 0; i < GRUB_CRYPTODISK_GF_SIZE; i++)
{
if (((a[GRUB_CRYPTODISK_GF_BYTES - i / 8 - 1] >> (i % 8))) & 1)
grub_crypto_xor (o, o, t, GRUB_CRYPTODISK_GF_BYTES);
gf_mul_x_be (t);
}
}
static gcry_err_code_t
grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
void *out, void *in, grub_size_t size,
void *iv)
{
grub_uint8_t *inptr, *outptr, *end;
grub_uint8_t ivt[cipher->cipher->blocksize];
if (!cipher->cipher->decrypt)
return GPG_ERR_NOT_SUPPORTED;
if (size % cipher->cipher->blocksize != 0)
return GPG_ERR_INV_ARG;
end = (grub_uint8_t *) in + size;
for (inptr = in, outptr = out; inptr < end;
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
{
grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize);
}
return GPG_ERR_NO_ERROR;
}
struct lrw_sector
{
grub_uint8_t low[GRUB_CRYPTODISK_GF_BYTES];
grub_uint8_t high[GRUB_CRYPTODISK_GF_BYTES];
grub_uint8_t low_byte, low_byte_c;
};
static void
generate_lrw_sector (struct lrw_sector *sec,
const struct grub_cryptodisk *dev,
const grub_uint8_t *iv)
{
grub_uint8_t idx[GRUB_CRYPTODISK_GF_BYTES];
grub_uint16_t c;
int j;
grub_memcpy (idx, iv, GRUB_CRYPTODISK_GF_BYTES);
sec->low_byte = (idx[GRUB_CRYPTODISK_GF_BYTES - 1]
& (GF_PER_SECTOR (dev) - 1));
sec->low_byte_c = (((GF_PER_SECTOR (dev) - 1) & ~sec->low_byte) + 1);
idx[GRUB_CRYPTODISK_GF_BYTES - 1] &= ~(GF_PER_SECTOR (dev) - 1);
gf_mul_be (sec->low, dev->lrw_key, idx);
if (!sec->low_byte)
return;
c = idx[GRUB_CRYPTODISK_GF_BYTES - 1] + GF_PER_SECTOR (dev);
if (c & 0x100)
{
for (j = GRUB_CRYPTODISK_GF_BYTES - 2; j >= 0; j--)
{
idx[j]++;
if (idx[j] != 0)
break;
}
}
idx[GRUB_CRYPTODISK_GF_BYTES - 1] = c;
gf_mul_be (sec->high, dev->lrw_key, idx);
}
static void __attribute__ ((unused))
lrw_xor (const struct lrw_sector *sec,
const struct grub_cryptodisk *dev,
grub_uint8_t *b)
{
unsigned i;
for (i = 0; i < sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES;
i += GRUB_CRYPTODISK_GF_BYTES)
grub_crypto_xor (b + i, b + i, sec->low, GRUB_CRYPTODISK_GF_BYTES);
grub_crypto_xor (b, b, dev->lrw_precalc + GRUB_CRYPTODISK_GF_BYTES * sec->low_byte,
sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES);
if (!sec->low_byte)
return;
for (i = sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES;
i < (1U << dev->log_sector_size); i += GRUB_CRYPTODISK_GF_BYTES)
grub_crypto_xor (b + i, b + i, sec->high, GRUB_CRYPTODISK_GF_BYTES);
grub_crypto_xor (b + sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES,
b + sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES,
dev->lrw_precalc, sec->low_byte * GRUB_CRYPTODISK_GF_BYTES);
}
gcry_err_code_t
grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
grub_uint8_t * data, grub_size_t len,
grub_disk_addr_t sector)
{
grub_size_t i;
gcry_err_code_t err;
/* The only mode without IV. */
if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey)
return grub_crypto_ecb_decrypt (dev->cipher, data, data, len);
for (i = 0; i < len; i += (1U << dev->log_sector_size))
{
grub_size_t sz = ((dev->cipher->cipher->blocksize
+ sizeof (grub_uint32_t) - 1)
/ sizeof (grub_uint32_t));
grub_uint32_t iv[sz];
if (dev->rekey)
{
grub_uint64_t zone = sector >> dev->rekey_shift;
if (zone != dev->last_rekey)
{
err = dev->rekey (dev, zone);
if (err)
return err;
dev->last_rekey = zone;
}
}
grub_memset (iv, 0, sz * sizeof (iv[0]));
switch (dev->mode_iv)
{
case GRUB_CRYPTODISK_MODE_IV_NULL:
break;
case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH:
{
grub_uint64_t tmp;
grub_uint64_t ctx[(dev->iv_hash->contextsize + 7) / 8];
grub_memset (ctx, 0, sizeof (ctx));
tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
dev->iv_hash->init (ctx);
dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
dev->iv_hash->final (ctx);
grub_memcpy (iv, dev->iv_hash->read (ctx), sizeof (iv));
}
break;
case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
iv[1] = grub_cpu_to_le32 (sector >> 32);
case GRUB_CRYPTODISK_MODE_IV_PLAIN:
iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
break;
case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
& 0xFFFFFFFF);
break;
case GRUB_CRYPTODISK_MODE_IV_BENBI:
{
grub_uint64_t num = (sector << dev->benbi_log) + 1;
iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
}
break;
case GRUB_CRYPTODISK_MODE_IV_ESSIV:
iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
dev->cipher->cipher->blocksize);
if (err)
return err;
}
switch (dev->mode)
{
case GRUB_CRYPTODISK_MODE_CBC:
err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
(1U << dev->log_sector_size), iv);
if (err)
return err;
break;
case GRUB_CRYPTODISK_MODE_PCBC:
err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
(1U << dev->log_sector_size), iv);
if (err)
return err;
break;
case GRUB_CRYPTODISK_MODE_XTS:
{
unsigned j;
err = grub_crypto_ecb_encrypt (dev->secondary_cipher, iv, iv,
dev->cipher->cipher->blocksize);
if (err)
return err;
for (j = 0; j < (1U << dev->log_sector_size);
j += dev->cipher->cipher->blocksize)
{
grub_crypto_xor (data + i + j, data + i + j, iv,
dev->cipher->cipher->blocksize);
err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j,
data + i + j,
dev->cipher->cipher->blocksize);
if (err)
return err;
grub_crypto_xor (data + i + j, data + i + j, iv,
dev->cipher->cipher->blocksize);
gf_mul_x ((grub_uint8_t *) iv);
}
}
break;
case GRUB_CRYPTODISK_MODE_LRW:
{
struct lrw_sector sec;
generate_lrw_sector (&sec, dev, (grub_uint8_t *) iv);
lrw_xor (&sec, dev, data + i);
err = grub_crypto_ecb_decrypt (dev->cipher, data + i,
data + i,
(1U << dev->log_sector_size));
if (err)
return err;
lrw_xor (&sec, dev, data + i);
}
break;
case GRUB_CRYPTODISK_MODE_ECB:
grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
(1U << dev->log_sector_size));
break;
default:
return GPG_ERR_NOT_IMPLEMENTED;
}
sector++;
}
return GPG_ERR_NO_ERROR;
}
gcry_err_code_t
grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t keysize)
{
gcry_err_code_t err;
int real_keysize;
real_keysize = keysize;
if (dev->mode == GRUB_CRYPTODISK_MODE_XTS)
real_keysize /= 2;
if (dev->mode == GRUB_CRYPTODISK_MODE_LRW)
real_keysize -= dev->cipher->cipher->blocksize;
/* Set the PBKDF2 output as the cipher key. */
err = grub_crypto_cipher_set_key (dev->cipher, key, real_keysize);
if (err)
return err;
/* Configure ESSIV if necessary. */
if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_ESSIV)
{
grub_size_t essiv_keysize = dev->essiv_hash->mdlen;
grub_uint8_t hashed_key[essiv_keysize];
grub_crypto_hash (dev->essiv_hash, hashed_key, key, keysize);
err = grub_crypto_cipher_set_key (dev->essiv_cipher,
hashed_key, essiv_keysize);
if (err)
return err;
}
if (dev->mode == GRUB_CRYPTODISK_MODE_XTS)
{
err = grub_crypto_cipher_set_key (dev->secondary_cipher,
key + real_keysize,
keysize / 2);
if (err)
return err;
}
if (dev->mode == GRUB_CRYPTODISK_MODE_LRW)
{
unsigned i;
grub_uint8_t idx[GRUB_CRYPTODISK_GF_BYTES];
grub_free (dev->lrw_precalc);
grub_memcpy (dev->lrw_key, key + real_keysize,
dev->cipher->cipher->blocksize);
dev->lrw_precalc = grub_malloc ((1U << dev->log_sector_size));
if (!dev->lrw_precalc)
return GPG_ERR_OUT_OF_MEMORY;
grub_memset (idx, 0, GRUB_CRYPTODISK_GF_BYTES);
for (i = 0; i < (1U << dev->log_sector_size);
i += GRUB_CRYPTODISK_GF_BYTES)
{
idx[GRUB_CRYPTODISK_GF_BYTES - 1] = i / GRUB_CRYPTODISK_GF_BYTES;
gf_mul_be (dev->lrw_precalc + i, idx, dev->lrw_key);
}
}
return GPG_ERR_NO_ERROR;
}
static int
grub_cryptodisk_iterate (int (*hook) (const char *name),
grub_disk_pull_t pull)
{
grub_cryptodisk_t i;
if (pull != GRUB_DISK_PULL_NONE)
return 0;
for (i = cryptodisk_list; i != NULL; i = i->next)
{
char buf[30];
grub_snprintf (buf, sizeof (buf), "crypto%lu", i->id);
if (hook (buf))
return 1;
}
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cryptodisk_open (const char *name, grub_disk_t disk)
{
grub_cryptodisk_t dev;
if (grub_memcmp (name, "crypto", sizeof ("crypto") - 1) != 0)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
if (grub_memcmp (name, "cryptouuid/", sizeof ("cryptouuid/") - 1) == 0)
{
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
if (grub_strcasecmp (name + sizeof ("cryptouuid/") - 1, dev->uuid) == 0)
break;
}
else
{
unsigned long id = grub_strtoul (name + sizeof ("crypto") - 1, 0, 0);
if (grub_errno)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
/* Search for requested device in the list of CRYPTODISK devices. */
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
if (dev->id == id)
break;
}
if (!dev)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
disk->log_sector_size = dev->log_sector_size;
#ifdef GRUB_UTIL
if (dev->cheat)
{
if (dev->cheat_fd == -1)
dev->cheat_fd = open (dev->cheat, O_RDONLY);
if (dev->cheat_fd == -1)
return grub_error (GRUB_ERR_IO, "couldn't open %s: %s",
dev->cheat, strerror (errno));
}
#endif
if (!dev->source_disk)
{
grub_dprintf ("cryptodisk", "Opening device %s\n", name);
/* Try to open the source disk and populate the requested disk. */
dev->source_disk = grub_disk_open (dev->source);
if (!dev->source_disk)
return grub_errno;
}
disk->data = dev;
disk->total_sectors = dev->total_length;
disk->id = dev->id;
dev->ref++;
return GRUB_ERR_NONE;
}
static void
grub_cryptodisk_close (grub_disk_t disk)
{
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
grub_dprintf ("cryptodisk", "Closing disk\n");
dev->ref--;
if (dev->ref != 0)
return;
#ifdef GRUB_UTIL
if (dev->cheat)
{
close (dev->cheat_fd);
dev->cheat_fd = -1;
}
#endif
grub_disk_close (dev->source_disk);
dev->source_disk = NULL;
}
static grub_err_t
grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
grub_err_t err;
gcry_err_code_t gcry_err;
#ifdef GRUB_UTIL
if (dev->cheat)
{
err = grub_util_fd_seek (dev->cheat_fd, dev->cheat,
sector << disk->log_sector_size);
if (err)
return err;
if (grub_util_fd_read (dev->cheat_fd, buf, size << disk->log_sector_size)
!= (ssize_t) (size << disk->log_sector_size))
return grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'",
dev->cheat);
return GRUB_ERR_NONE;
}
#endif
grub_dprintf ("cryptodisk",
"Reading %" PRIuGRUB_SIZE " sectors from sector 0x%"
PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
size, sector, dev->offset);
err = grub_disk_read (dev->source_disk,
(sector << (disk->log_sector_size
- GRUB_DISK_SECTOR_BITS)) + dev->offset, 0,
size << disk->log_sector_size, buf);
if (err)
{
grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err);
return err;
}
gcry_err = grub_cryptodisk_decrypt (dev, (grub_uint8_t *) buf,
size << disk->log_sector_size,
sector);
return grub_crypto_gcry_error (gcry_err);
}
static grub_err_t
grub_cryptodisk_write (grub_disk_t disk __attribute ((unused)),
grub_disk_addr_t sector __attribute ((unused)),
grub_size_t size __attribute ((unused)),
const char *buf __attribute ((unused)))
{
return GRUB_ERR_NOT_IMPLEMENTED_YET;
}
#ifdef GRUB_UTIL
static grub_disk_memberlist_t
grub_cryptodisk_memberlist (grub_disk_t disk)
{
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
grub_disk_memberlist_t list = NULL;
list = grub_malloc (sizeof (*list));
if (list)
{
list->disk = dev->source_disk;
list->next = NULL;
}
return list;
}
#endif
static void
cryptodisk_cleanup (void)
{
grub_cryptodisk_t dev = cryptodisk_list;
grub_cryptodisk_t tmp;
while (dev != NULL)
{
grub_free (dev->source);
grub_free (dev->cipher);
grub_free (dev->secondary_cipher);
grub_free (dev->essiv_cipher);
tmp = dev->next;
grub_free (dev);
dev = tmp;
}
}
grub_err_t
grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
grub_disk_t source)
{
newdev->source = grub_strdup (name);
if (!newdev->source)
{
grub_free (newdev);
return grub_errno;
}
newdev->id = n++;
newdev->source_id = source->id;
newdev->source_dev_id = source->dev->id;
newdev->next = cryptodisk_list;
cryptodisk_list = newdev;
return GRUB_ERR_NONE;
}
grub_cryptodisk_t
grub_cryptodisk_get_by_uuid (const char *uuid)
{
grub_cryptodisk_t dev;
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
if (grub_strcasecmp (dev->uuid, uuid) == 0)
return dev;
return NULL;
}
grub_cryptodisk_t
grub_cryptodisk_get_by_source_disk (grub_disk_t disk)
{
grub_cryptodisk_t dev;
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
if (dev->source_id == disk->id && dev->source_dev_id == disk->dev->id)
return dev;
return NULL;
}
#ifdef GRUB_UTIL
grub_err_t
grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name,
grub_disk_t source, const char *cheat)
{
newdev->cheat = grub_strdup (cheat);
newdev->source = grub_strdup (name);
if (!newdev->source || !newdev->cheat)
{
grub_free (newdev->source);
grub_free (newdev->cheat);
return grub_errno;
}
newdev->cheat_fd = -1;
newdev->source_id = source->id;
newdev->source_dev_id = source->dev->id;
newdev->id = n++;
newdev->next = cryptodisk_list;
cryptodisk_list = newdev;
return GRUB_ERR_NONE;
}
void
grub_util_cryptodisk_print_abstraction (grub_disk_t disk)
{
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
grub_printf ("cryptodisk %s ", dev->modname);
if (dev->cipher)
grub_printf ("%s ", dev->cipher->cipher->modname);
if (dev->secondary_cipher)
grub_printf ("%s ", dev->secondary_cipher->cipher->modname);
if (dev->essiv_cipher)
grub_printf ("%s ", dev->essiv_cipher->cipher->modname);
if (dev->hash)
grub_printf ("%s ", dev->hash->modname);
if (dev->essiv_hash)
grub_printf ("%s ", dev->essiv_hash->modname);
if (dev->iv_hash)
grub_printf ("%s ", dev->iv_hash->modname);
}
void
grub_util_cryptodisk_print_uuid (grub_disk_t disk)
{
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
grub_printf ("%s ", dev->uuid);
}
#endif
static int check_boot, have_it;
static char *search_uuid;
static void
cryptodisk_close (grub_cryptodisk_t dev)
{
grub_crypto_cipher_close (dev->cipher);
grub_crypto_cipher_close (dev->secondary_cipher);
grub_crypto_cipher_close (dev->essiv_cipher);
grub_free (dev);
}
static grub_err_t
grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
{
grub_err_t err;
grub_cryptodisk_t dev;
grub_cryptodisk_dev_t cr;
dev = grub_cryptodisk_get_by_source_disk (source);
if (dev)
return GRUB_ERR_NONE;
FOR_CRYPTODISK_DEVS (cr)
{
dev = cr->scan (source, search_uuid, check_boot);
if (grub_errno)
return grub_errno;
if (!dev)
continue;
err = cr->recover_key (source, dev);
if (err)
{
cryptodisk_close (dev);
return err;
}
grub_cryptodisk_insert (dev, name, source);
have_it = 1;
return GRUB_ERR_NONE;
}
return GRUB_ERR_NONE;
}
#ifdef GRUB_UTIL
#include <grub/util/misc.h>
grub_err_t
grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
{
grub_err_t err;
grub_cryptodisk_t dev;
grub_cryptodisk_dev_t cr;
grub_disk_t source;
/* Try to open disk. */
source = grub_disk_open (sourcedev);
if (!source)
return grub_errno;
dev = grub_cryptodisk_get_by_source_disk (source);
if (dev)
{
grub_disk_close (source);
return GRUB_ERR_NONE;
}
FOR_CRYPTODISK_DEVS (cr)
{
dev = cr->scan (source, search_uuid, check_boot);
if (grub_errno)
return grub_errno;
if (!dev)
continue;
grub_util_info ("cheatmounted %s (%s) at %s", sourcedev, dev->modname,
cheat);
err = grub_cryptodisk_cheat_insert (dev, sourcedev, source, cheat);
grub_disk_close (source);
if (err)
grub_free (dev);
return GRUB_ERR_NONE;
}
grub_disk_close (source);
return GRUB_ERR_NONE;
}
#endif
static int
grub_cryptodisk_scan_device (const char *name)
{
grub_err_t err;
grub_disk_t source;
/* Try to open disk. */
source = grub_disk_open (name);
if (!source)
return grub_errno;
err = grub_cryptodisk_scan_device_real (name, source);
grub_disk_close (source);
if (err)
grub_print_error ();
return have_it && search_uuid ? 1 : 0;
}
static grub_err_t
grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = ctxt->state;
if (argc < 1 && !state[1].set && !state[2].set)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
have_it = 0;
if (state[0].set)
{
grub_cryptodisk_t dev;
dev = grub_cryptodisk_get_by_uuid (args[0]);
if (dev)
{
grub_dprintf ("cryptodisk",
"already mounted as crypto%lu\n", dev->id);
return GRUB_ERR_NONE;
}
check_boot = state[2].set;
search_uuid = args[0];
grub_device_iterate (&grub_cryptodisk_scan_device);
search_uuid = NULL;
if (!have_it)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
return GRUB_ERR_NONE;
}
else if (state[1].set || (argc == 0 && state[2].set))
{
search_uuid = NULL;
check_boot = state[2].set;
grub_device_iterate (&grub_cryptodisk_scan_device);
search_uuid = NULL;
return GRUB_ERR_NONE;
}
else
{
grub_err_t err;
grub_disk_t disk;
grub_cryptodisk_t dev;
search_uuid = NULL;
check_boot = state[2].set;
disk = grub_disk_open (args[0]);
if (!disk)
return grub_errno;
dev = grub_cryptodisk_get_by_source_disk (disk);
if (dev)
{
grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id);
grub_disk_close (disk);
return GRUB_ERR_NONE;
}
err = grub_cryptodisk_scan_device_real (args[0], disk);
grub_disk_close (disk);
return err;
}
}
static struct grub_disk_dev grub_cryptodisk_dev = {
.name = "cryptodisk",
.id = GRUB_DISK_DEVICE_CRYPTODISK_ID,
.iterate = grub_cryptodisk_iterate,
.open = grub_cryptodisk_open,
.close = grub_cryptodisk_close,
.read = grub_cryptodisk_read,
.write = grub_cryptodisk_write,
#ifdef GRUB_UTIL
.memberlist = grub_cryptodisk_memberlist,
#endif
.next = 0
};
static grub_extcmd_t cmd;
GRUB_MOD_INIT (cryptodisk)
{
grub_disk_dev_register (&grub_cryptodisk_dev);
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
N_("SOURCE|-u UUID|-a|-b"),
N_("Mount a crypto device."), options);
}
GRUB_MOD_FINI (cryptodisk)
{
grub_disk_dev_unregister (&grub_cryptodisk_dev);
cryptodisk_cleanup ();
}

View file

@ -33,12 +33,10 @@ struct grub_efidisk_data
grub_efi_device_path_t *device_path;
grub_efi_device_path_t *last_device_path;
grub_efi_block_io_t *block_io;
grub_efi_disk_io_t *disk_io;
struct grub_efidisk_data *next;
};
/* GUIDs. */
static grub_efi_guid_t disk_io_guid = GRUB_EFI_DISK_IO_GUID;
/* GUID. */
static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID;
static struct grub_efidisk_data *fd_devices;
@ -86,54 +84,6 @@ find_last_device_path (const grub_efi_device_path_t *dp)
return p;
}
/* Compare device paths. */
static int
compare_device_paths (const grub_efi_device_path_t *dp1,
const grub_efi_device_path_t *dp2)
{
if (! dp1 || ! dp2)
/* Return non-zero. */
return 1;
while (1)
{
grub_efi_uint8_t type1, type2;
grub_efi_uint8_t subtype1, subtype2;
grub_efi_uint16_t len1, len2;
int ret;
type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
if (type1 != type2)
return (int) type2 - (int) type1;
subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
if (subtype1 != subtype2)
return (int) subtype1 - (int) subtype2;
len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
if (len1 != len2)
return (int) len1 - (int) len2;
ret = grub_memcmp (dp1, dp2, len1);
if (ret != 0)
return ret;
if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
break;
dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
}
return 0;
}
static struct grub_efidisk_data *
make_devices (void)
{
@ -143,7 +93,7 @@ make_devices (void)
struct grub_efidisk_data *devices = 0;
/* Find handles which support the disk io interface. */
handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &disk_io_guid,
handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &block_io_guid,
0, &num_handles);
if (! handles)
return 0;
@ -155,7 +105,6 @@ make_devices (void)
grub_efi_device_path_t *ldp;
struct grub_efidisk_data *d;
grub_efi_block_io_t *bio;
grub_efi_disk_io_t *dio;
dp = grub_efi_get_device_path (*handle);
if (! dp)
@ -168,9 +117,7 @@ make_devices (void)
bio = grub_efi_open_protocol (*handle, &block_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
dio = grub_efi_open_protocol (*handle, &disk_io_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (! bio || ! dio)
if (! bio)
/* This should not happen... Why? */
continue;
@ -186,7 +133,6 @@ make_devices (void)
d->device_path = dp;
d->last_device_path = ldp;
d->block_io = bio;
d->disk_io = dio;
d->next = devices;
devices = d;
}
@ -220,7 +166,7 @@ find_parent_device (struct grub_efidisk_data *devices,
if (parent == d)
continue;
if (compare_device_paths (parent->device_path, dp) == 0)
if (grub_efi_compare_device_paths (parent->device_path, dp) == 0)
{
/* Found. */
if (! parent->last_device_path)
@ -255,7 +201,7 @@ iterate_child_devices (struct grub_efidisk_data *devices,
ldp->length[0] = sizeof (*ldp);
ldp->length[1] = 0;
if (compare_device_paths (dp, d->device_path) == 0)
if (grub_efi_compare_device_paths (dp, d->device_path) == 0)
if (hook (p))
{
grub_free (dp);
@ -279,10 +225,10 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d)
{
int ret;
ret = compare_device_paths (find_last_device_path ((*p)->device_path),
ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path),
find_last_device_path (d->device_path));
if (ret == 0)
ret = compare_device_paths ((*p)->device_path,
ret = grub_efi_compare_device_paths ((*p)->device_path,
d->device_path);
if (ret == 0)
return;
@ -432,23 +378,28 @@ enumerate_disks (void)
}
static int
grub_efidisk_iterate (int (*hook) (const char *name))
grub_efidisk_iterate (int (*hook) (const char *name),
grub_disk_pull_t pull)
{
struct grub_efidisk_data *d;
char buf[16];
int count;
for (d = fd_devices, count = 0; d; d = d->next, count++)
switch (pull)
{
grub_snprintf (buf, sizeof (buf), "fd%d", count);
case GRUB_DISK_PULL_NONE:
for (d = hd_devices, count = 0; d; d = d->next, count++)
{
grub_snprintf (buf, sizeof (buf), "hd%d", count);
grub_dprintf ("efidisk", "iterating %s\n", buf);
if (hook (buf))
return 1;
}
for (d = hd_devices, count = 0; d; d = d->next, count++)
break;
case GRUB_DISK_PULL_REMOVABLE:
for (d = fd_devices, count = 0; d; d = d->next, count++)
{
grub_snprintf (buf, sizeof (buf), "hd%d", count);
grub_snprintf (buf, sizeof (buf), "fd%d", count);
grub_dprintf ("efidisk", "iterating %s\n", buf);
if (hook (buf))
return 1;
@ -461,6 +412,10 @@ grub_efidisk_iterate (int (*hook) (const char *name))
if (hook (buf))
return 1;
}
break;
default:
return 0;
}
return 0;
}
@ -536,8 +491,13 @@ grub_efidisk_open (const char *name, struct grub_disk *disk)
and total sectors should be replaced with total blocks. */
grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n",
m, (unsigned long long) m->last_block, m->block_size);
disk->total_sectors = (m->last_block
* (m->block_size >> GRUB_DISK_SECTOR_BITS));
disk->total_sectors = m->last_block + 1;
if (m->block_size & (m->block_size - 1) || !m->block_size)
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
m->block_size);
for (disk->log_sector_size = 0;
(1U << disk->log_sector_size) < m->block_size;
disk->log_sector_size++);
disk->data = d;
grub_dprintf ("efidisk", "opening %s succeeded\n", name);
@ -558,21 +518,19 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector,
{
/* For now, use the disk io interface rather than the block io's. */
struct grub_efidisk_data *d;
grub_efi_disk_io_t *dio;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
d = disk->data;
dio = d->disk_io;
bio = d->block_io;
grub_dprintf ("efidisk",
"reading 0x%lx sectors at the sector 0x%llx from %s\n",
(unsigned long) size, (unsigned long long) sector, disk->name);
status = efi_call_5 (dio->read, dio, bio->media->media_id,
(grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
(grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
status = efi_call_5 (bio->read_blocks, bio, bio->media->media_id,
(grub_efi_uint64_t) sector,
(grub_efi_uintn_t) size << disk->log_sector_size,
buf);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error");
@ -586,21 +544,19 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector,
{
/* For now, use the disk io interface rather than the block io's. */
struct grub_efidisk_data *d;
grub_efi_disk_io_t *dio;
grub_efi_block_io_t *bio;
grub_efi_status_t status;
d = disk->data;
dio = d->disk_io;
bio = d->block_io;
grub_dprintf ("efidisk",
"writing 0x%lx sectors at the sector 0x%llx to %s\n",
(unsigned long) size, (unsigned long long) sector, disk->name);
status = efi_call_5 (dio->write, dio, bio->media->media_id,
(grub_efi_uint64_t) sector << GRUB_DISK_SECTOR_BITS,
(grub_efi_uintn_t) size << GRUB_DISK_SECTOR_BITS,
status = efi_call_5 (bio->write_blocks, bio, bio->media->media_id,
(grub_efi_uint64_t) sector,
(grub_efi_uintn_t) size << disk->log_sector_size,
(void *) buf);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_WRITE_ERROR, "efidisk write error");
@ -711,28 +667,10 @@ grub_efidisk_get_device_handle (grub_disk_t disk)
char *
grub_efidisk_get_device_name (grub_efi_handle_t *handle)
{
grub_efi_device_path_t *dp, *ldp;
dp = grub_efi_get_device_path (handle);
if (! dp)
return 0;
ldp = find_last_device_path (dp);
if (! ldp)
return 0;
if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
{
grub_efi_device_path_t *dp, *ldp, *sdp;
/* This is a hard disk partition. */
grub_disk_t parent = 0;
grub_partition_t tpart = NULL;
char *device_name;
grub_efi_device_path_t *dup_dp, *dup_ldp;
grub_efi_hard_drive_device_path_t hd;
auto int find_parent_disk (const char *name);
auto int find_partition (grub_disk_t disk, const grub_partition_t part);
/* Find the disk which is the parent of a given hard disk partition. */
int find_parent_disk (const char *name)
@ -748,7 +686,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
struct grub_efidisk_data *d;
d = disk->data;
if (compare_device_paths (d->device_path, dup_dp) == 0)
if (grub_efi_compare_device_paths (d->device_path, sdp) == 0)
{
parent = disk;
return 1;
@ -759,6 +697,24 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
return 0;
}
dp = grub_efi_get_device_path (handle);
if (! dp)
return 0;
ldp = find_last_device_path (dp);
if (! ldp)
return 0;
if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
{
char *partition_name = NULL;
char *device_name;
grub_efi_device_path_t *dup_dp, *dup_ldp;
grub_efi_hard_drive_device_path_t hd;
auto int find_partition (grub_disk_t disk, const grub_partition_t part);
/* Find the identical partition. */
int find_partition (grub_disk_t disk __attribute__ ((unused)),
const grub_partition_t part)
@ -766,7 +722,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
if (grub_partition_get_start (part) == hd.partition_start
&& grub_partition_get_len (part) == hd.partition_size)
{
tpart = part;
partition_name = grub_partition_get_name (part);
return 1;
}
@ -785,7 +741,11 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
dup_ldp->length[0] = sizeof (*dup_ldp);
dup_ldp->length[1] = 0;
grub_efidisk_iterate (find_parent_disk);
sdp = dup_dp;
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_NONE);
if (!parent)
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_REMOVABLE);
grub_free (dup_dp);
if (! parent)
@ -793,16 +753,21 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
/* Find a partition which matches the hard drive device path. */
grub_memcpy (&hd, ldp, sizeof (hd));
if (hd.partition_start == 0
&& hd.partition_size == grub_disk_get_size (parent))
{
device_name = grub_strdup (parent->name);
}
else
{
grub_partition_iterate (parent, find_partition);
if (! tpart)
if (! partition_name)
{
grub_disk_close (parent);
return 0;
}
{
char *partition_name = grub_partition_get_name (tpart);
device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
grub_free (partition_name);
}
@ -813,38 +778,17 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
else
{
/* This should be an entire disk. */
auto int find_disk (const char *name);
char *device_name = 0;
int find_disk (const char *name)
{
grub_disk_t disk;
sdp = dp;
disk = grub_disk_open (name);
if (! disk)
return 1;
if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
{
struct grub_efidisk_data *d;
d = disk->data;
if (compare_device_paths (d->device_path, dp) == 0)
{
device_name = grub_strdup (disk->name);
grub_disk_close (disk);
return 1;
}
}
grub_disk_close (disk);
return 0;
}
grub_efidisk_iterate (find_disk);
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_NONE);
if (!parent)
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_REMOVABLE);
if (!parent)
return NULL;
device_name = grub_strdup (parent->name);
grub_disk_close (parent);
return device_name;
}
return 0;
}

568
grub-core/disk/geli.c Normal file
View file

@ -0,0 +1,568 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2007,2010,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/>.
*/
/* This file is loosely based on FreeBSD geli implementation
(but no code was directly copied). FreeBSD geli is distributed under
following terms: */
/*-
* Copyright (c) 2005-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <grub/cryptodisk.h>
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/dl.h>
#include <grub/err.h>
#include <grub/disk.h>
#include <grub/crypto.h>
#include <grub/partition.h>
#include <grub/i18n.h>
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
{
grub_uint8_t iv_key[64];
grub_uint8_t cipher_key[64];
grub_uint8_t hmac[64];
} __attribute__ ((packed));
struct grub_geli_phdr
{
grub_uint8_t magic[16];
#define GELI_MAGIC "GEOM::ELI"
grub_uint32_t version;
grub_uint32_t flags;
grub_uint16_t alg;
grub_uint16_t keylen;
grub_uint16_t unused3[5];
grub_uint32_t sector_size;
grub_uint8_t keys_used;
grub_uint32_t niter;
grub_uint8_t salt[64];
struct grub_geli_key keys[2];
} __attribute__ ((packed));
enum
{
GRUB_GELI_FLAGS_ONETIME = 1,
GRUB_GELI_FLAGS_BOOT = 2,
};
/* FIXME: support version 0. */
/* FIXME: support big-endian pre-version-4 volumes. */
/* FIXME: support for keyfiles. */
/* FIXME: support for HMAC. */
const char *algorithms[] = {
[0x01] = "des",
[0x02] = "3des",
[0x03] = "blowfish",
[0x04] = "cast5",
/* FIXME: 0x05 is skipjack, but we don't have it. */
[0x0b] = "aes",
/* FIXME: 0x10 is null. */
[0x15] = "camellia128",
[0x16] = "aes"
};
#define MAX_PASSPHRASE 256
static gcry_err_code_t
geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno)
{
gcry_err_code_t gcry_err;
const struct {
char magic[4];
grub_uint64_t zone;
} __attribute__ ((packed)) tohash
= { {'e', 'k', 'e', 'y'}, grub_cpu_to_le64 (zoneno) };
grub_uint64_t key[(dev->hash->mdlen + 7) / 8];
grub_dprintf ("geli", "rekeying %" PRIuGRUB_UINT64_T " keysize=%d\n",
zoneno, dev->rekey_derived_size);
gcry_err = grub_crypto_hmac_buffer (dev->hash, dev->rekey_key, 64,
&tohash, sizeof (tohash), key);
if (gcry_err)
return grub_crypto_gcry_error (gcry_err);
return grub_cryptodisk_setkey (dev, (grub_uint8_t *) key,
dev->rekey_derived_size);
}
static inline int
ascii2hex (char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return 0;
}
static inline gcry_err_code_t
make_uuid (const struct grub_geli_phdr *header,
char *uuid)
{
grub_uint8_t uuidbin[GRUB_MD_SHA256->mdlen];
gcry_err_code_t err;
grub_uint8_t *iptr;
char *optr;
err = grub_crypto_hmac_buffer (GRUB_MD_SHA256,
header->salt, sizeof (header->salt),
"uuid", sizeof ("uuid") - 1, uuidbin);
if (err)
return err;
optr = uuid;
for (iptr = uuidbin; iptr < &uuidbin[ARRAY_SIZE (uuidbin)]; iptr++)
{
grub_snprintf (optr, 3, "%02x", *iptr);
optr += 2;
}
*optr = 0;
return GPG_ERR_NO_ERROR;
}
#ifdef GRUB_UTIL
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <grub/emu/hostdisk.h>
#include <unistd.h>
#include <string.h>
#include <grub/emu/misc.h>
char *
grub_util_get_geli_uuid (const char *dev)
{
int fd = open (dev, O_RDONLY);
grub_uint64_t s;
unsigned log_secsize;
grub_uint8_t hdr[512];
struct grub_geli_phdr *header;
char *uuid;
gcry_err_code_t err;
if (fd < 0)
return NULL;
s = grub_util_get_fd_sectors (fd, &log_secsize);
grub_util_fd_seek (fd, dev, (s << log_secsize) - 512);
uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1);
if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0)
grub_util_error (_("couldn't read ELI metadata"));
COMPILE_TIME_ASSERT (sizeof (header) <= 512);
header = (void *) &hdr;
/* Look for GELI magic sequence. */
if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC))
|| grub_le_to_cpu32 (header->version) > 5
|| grub_le_to_cpu32 (header->version) < 1)
grub_util_error (_("wrong ELI magic or version"));
err = make_uuid ((void *) &hdr, uuid);
if (err)
return NULL;
return uuid;
}
#endif
static grub_cryptodisk_t
configure_ciphers (grub_disk_t disk, const char *check_uuid,
int boot_only)
{
grub_cryptodisk_t newdev;
struct grub_geli_phdr header;
grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL;
const struct gcry_cipher_spec *ciph;
const char *ciphername = NULL;
gcry_err_code_t gcry_err;
char uuid[GRUB_MD_SHA256->mdlen * 2 + 1];
grub_disk_addr_t sector;
grub_err_t err;
sector = grub_disk_get_size (disk);
if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
return NULL;
/* Read the GELI header. */
err = grub_disk_read (disk, sector - 1, 0, sizeof (header), &header);
if (err)
return NULL;
/* Look for GELI magic sequence. */
if (grub_memcmp (header.magic, GELI_MAGIC, sizeof (GELI_MAGIC))
|| grub_le_to_cpu32 (header.version) > 5
|| grub_le_to_cpu32 (header.version) < 1)
{
grub_dprintf ("geli", "wrong magic %02x\n", header.magic[0]);
return NULL;
}
if ((grub_le_to_cpu32 (header.sector_size)
& (grub_le_to_cpu32 (header.sector_size) - 1))
|| grub_le_to_cpu32 (header.sector_size) == 0)
{
grub_dprintf ("geli", "incorrect sector size %d\n",
grub_le_to_cpu32 (header.sector_size));
return NULL;
}
if (grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_ONETIME)
{
grub_dprintf ("geli", "skipping one-time volume\n");
return NULL;
}
if (boot_only && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT))
{
grub_dprintf ("geli", "not a boot volume\n");
return NULL;
}
gcry_err = make_uuid (&header, uuid);
if (gcry_err)
{
grub_crypto_gcry_error (gcry_err);
return NULL;
}
if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
{
grub_dprintf ("geli", "%s != %s\n", uuid, check_uuid);
return NULL;
}
if (grub_le_to_cpu16 (header.alg) >= ARRAY_SIZE (algorithms)
|| algorithms[grub_le_to_cpu16 (header.alg)] == NULL)
{
grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher 0x%x unknown",
grub_le_to_cpu16 (header.alg));
return NULL;
}
ciphername = algorithms[grub_le_to_cpu16 (header.alg)];
ciph = grub_crypto_lookup_cipher_by_name (ciphername);
if (!ciph)
{
grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available",
ciphername);
return NULL;
}
/* Configure the cipher used for the bulk data. */
cipher = grub_crypto_cipher_open (ciph);
if (!cipher)
return NULL;
if (grub_le_to_cpu16 (header.alg) == 0x16)
{
secondary_cipher = grub_crypto_cipher_open (ciph);
if (!secondary_cipher)
return NULL;
}
if (grub_le_to_cpu16 (header.keylen) > 1024)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
grub_le_to_cpu16 (header.keylen));
return NULL;
}
newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
if (!newdev)
return NULL;
newdev->cipher = cipher;
newdev->secondary_cipher = secondary_cipher;
newdev->offset = 0;
newdev->source_disk = NULL;
newdev->benbi_log = 0;
if (grub_le_to_cpu16 (header.alg) == 0x16)
{
newdev->mode = GRUB_CRYPTODISK_MODE_XTS;
newdev->mode_iv = GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64;
}
else
{
newdev->mode = GRUB_CRYPTODISK_MODE_CBC;
newdev->mode_iv = GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH;
}
newdev->essiv_cipher = NULL;
newdev->essiv_hash = NULL;
newdev->hash = GRUB_MD_SHA512;
newdev->iv_hash = GRUB_MD_SHA256;
for (newdev->log_sector_size = 0;
(1U << newdev->log_sector_size) < grub_le_to_cpu32 (header.sector_size);
newdev->log_sector_size++);
if (grub_le_to_cpu32 (header.version) >= 5)
{
newdev->rekey = geli_rekey;
newdev->rekey_shift = 20;
}
#ifdef GRUB_UTIL
newdev->modname = "geli";
#endif
newdev->total_length = grub_disk_get_size (disk) - 1;
grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= 32 * 2 + 1);
return newdev;
}
static grub_err_t
recover_key (grub_disk_t source, grub_cryptodisk_t dev)
{
grub_size_t keysize;
grub_uint8_t digest[dev->hash->mdlen];
grub_uint8_t geomkey[dev->hash->mdlen];
grub_uint8_t verify_key[dev->hash->mdlen];
grub_uint8_t zero[dev->cipher->cipher->blocksize];
char passphrase[MAX_PASSPHRASE] = "";
unsigned i;
gcry_err_code_t gcry_err;
struct grub_geli_phdr header;
char *tmp;
grub_disk_addr_t sector;
grub_err_t err;
sector = grub_disk_get_size (source);
if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not a geli");
/* Read the GELI header. */
err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header);
if (err)
return err;
keysize = grub_le_to_cpu16 (header.keylen) / 8;
grub_memset (zero, 0, sizeof (zero));
grub_puts_ (N_("Attempting to decrypt master key..."));
/* Get the passphrase from the user. */
tmp = NULL;
if (source->partition)
tmp = grub_partition_get_name (source->partition);
grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
source->partition ? "," : "", tmp ? : "",
dev->uuid);
grub_free (tmp);
if (!grub_password_get (passphrase, MAX_PASSPHRASE))
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
/* Calculate the PBKDF2 of the user supplied passphrase. */
if (grub_le_to_cpu32 (header.niter) != 0)
{
grub_uint8_t pbkdf_key[64];
gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
grub_strlen (passphrase),
header.salt,
sizeof (header.salt),
grub_le_to_cpu32 (header.niter),
pbkdf_key, sizeof (pbkdf_key));
if (gcry_err)
return grub_crypto_gcry_error (gcry_err);
gcry_err = grub_crypto_hmac_buffer (dev->hash, NULL, 0, pbkdf_key,
sizeof (pbkdf_key), geomkey);
if (gcry_err)
return grub_crypto_gcry_error (gcry_err);
}
else
{
struct grub_crypto_hmac_handle *hnd;
hnd = grub_crypto_hmac_init (dev->hash, NULL, 0);
if (!hnd)
return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY);
grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt));
grub_crypto_hmac_write (hnd, passphrase, grub_strlen (passphrase));
gcry_err = grub_crypto_hmac_fini (hnd, geomkey);
if (gcry_err)
return grub_crypto_gcry_error (gcry_err);
}
gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey,
sizeof (geomkey), "\1", 1, digest);
if (gcry_err)
return grub_crypto_gcry_error (gcry_err);
gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey,
sizeof (geomkey), "\0", 1, verify_key);
if (gcry_err)
return grub_crypto_gcry_error (gcry_err);
grub_dprintf ("geli", "keylen = %" PRIuGRUB_SIZE "\n", keysize);
/* Try to recover master key from each active keyslot. */
for (i = 0; i < ARRAY_SIZE (header.keys); i++)
{
struct grub_geli_key candidate_key;
grub_uint8_t key_hmac[dev->hash->mdlen];
/* Check if keyslot is enabled. */
if (! (header.keys_used & (1 << i)))
continue;
grub_dprintf ("geli", "Trying keyslot %d\n", i);
gcry_err = grub_crypto_cipher_set_key (dev->cipher,
digest, keysize);
if (gcry_err)
return grub_crypto_gcry_error (gcry_err);
gcry_err = grub_crypto_cbc_decrypt (dev->cipher, &candidate_key,
&header.keys[i],
sizeof (candidate_key),
zero);
if (gcry_err)
return grub_crypto_gcry_error (gcry_err);
gcry_err = grub_crypto_hmac_buffer (dev->hash, verify_key,
sizeof (verify_key),
&candidate_key,
(sizeof (candidate_key)
- sizeof (candidate_key.hmac)),
key_hmac);
if (gcry_err)
return grub_crypto_gcry_error (gcry_err);
if (grub_memcmp (candidate_key.hmac, key_hmac, dev->hash->mdlen) != 0)
continue;
grub_printf_ (N_("Slot %d opened\n"), i);
/* Set the master key. */
if (!dev->rekey)
{
grub_size_t real_keysize = keysize;
if (grub_le_to_cpu16 (header.alg) == 0x16)
real_keysize *= 2;
gcry_err = grub_cryptodisk_setkey (dev, candidate_key.cipher_key,
real_keysize);
if (gcry_err)
return grub_crypto_gcry_error (gcry_err);
}
else
{
grub_size_t real_keysize = keysize;
if (grub_le_to_cpu16 (header.alg) == 0x16)
real_keysize *= 2;
/* For a reason I don't know, the IV key is used in rekeying. */
grub_memcpy (dev->rekey_key, candidate_key.iv_key,
sizeof (candidate_key.iv_key));
dev->rekey_derived_size = real_keysize;
dev->last_rekey = -1;
COMPILE_TIME_ASSERT (sizeof (dev->rekey_key)
>= sizeof (candidate_key.iv_key));
}
dev->iv_prefix_len = sizeof (candidate_key.iv_key);
grub_memcpy (dev->iv_prefix, candidate_key.iv_key,
sizeof (candidate_key.iv_key));
COMPILE_TIME_ASSERT (sizeof (dev->iv_prefix) >= sizeof (candidate_key.iv_key));
return GRUB_ERR_NONE;
}
return GRUB_ACCESS_DENIED;
}
struct grub_cryptodisk_dev geli_crypto = {
.scan = configure_ciphers,
.recover_key = recover_key
};
GRUB_MOD_INIT (geli)
{
grub_cryptodisk_dev_register (&geli_crypto);
}
GRUB_MOD_FINI (geli)
{
grub_cryptodisk_dev_unregister (&geli_crypto);
}

View file

@ -27,8 +27,12 @@
int grub_disk_host_i_want_a_reference;
static int
grub_host_iterate (int (*hook) (const char *name))
grub_host_iterate (int (*hook) (const char *name),
grub_disk_pull_t pull)
{
if (pull != GRUB_DISK_PULL_NONE)
return 0;
if (hook ("host"))
return 1;
return 0;

View file

@ -27,6 +27,7 @@
#include <grub/misc.h>
#include <grub/err.h>
#include <grub/term.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -284,12 +285,16 @@ grub_biosdisk_call_hook (int (*hook) (const char *name), int drive)
}
static int
grub_biosdisk_iterate (int (*hook) (const char *name))
grub_biosdisk_iterate (int (*hook) (const char *name),
grub_disk_pull_t pull __attribute__ ((unused)))
{
int drive;
int num_floppies;
int drive;
/* For hard disks, attempt to read the MBR. */
switch (pull)
{
case GRUB_DISK_PULL_NONE:
for (drive = 0x80; drive < 0x90; drive++)
{
if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
@ -302,7 +307,9 @@ grub_biosdisk_iterate (int (*hook) (const char *name))
if (grub_biosdisk_call_hook (hook, drive))
return 1;
}
return 0;
case GRUB_DISK_PULL_REMOVABLE:
if (cd_drive)
{
if (grub_biosdisk_call_hook (hook, cd_drive))
@ -314,7 +321,10 @@ grub_biosdisk_iterate (int (*hook) (const char *name))
for (drive = 0; drive < num_floppies; drive++)
if (grub_biosdisk_call_hook (hook, drive))
return 1;
return 0;
default:
return 0;
}
return 0;
}
@ -340,7 +350,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
if ((cd_drive) && (drive == cd_drive))
{
data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM;
data->sectors = 32;
data->sectors = 8;
disk->log_sector_size = 11;
/* TODO: get the correct size. */
total_sectors = GRUB_DISK_SIZE_UNKNOWN;
}
@ -349,6 +360,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
/* HDD */
int version;
disk->log_sector_size = 9;
version = grub_biosdisk_check_int13_extensions (drive);
if (version)
{
@ -369,6 +382,15 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
correctly but returns zero. So if it is zero, compute
it by C/H/S returned by the LBA BIOS call. */
total_sectors = drp->cylinders * drp->heads * drp->sectors;
if (drp->bytes_per_sector
&& !(drp->bytes_per_sector & (drp->bytes_per_sector - 1))
&& drp->bytes_per_sector >= 512
&& drp->bytes_per_sector <= 16384)
{
for (disk->log_sector_size = 0;
(1 << disk->log_sector_size) < drp->bytes_per_sector;
disk->log_sector_size++);
}
}
}
}
@ -431,7 +453,7 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR
+ (data->sectors
<< GRUB_DISK_SECTOR_BITS));
<< disk->log_sector_size));
dap->length = sizeof (*dap);
dap->reserved = 0;
dap->blocks = size;
@ -445,9 +467,6 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
if (cmd)
return grub_error (GRUB_ERR_WRITE_ERROR, "can\'t write to cdrom");
dap->blocks = ALIGN_UP (dap->blocks, 4) >> 2;
dap->block >>= 2;
for (i = 0; i < GRUB_BIOSDISK_CDROM_RETRY_COUNT; i++)
if (! grub_biosdisk_rw_int13_extensions (0x42, data->drive, dap))
break;
@ -503,10 +522,12 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
/* Return the number of sectors which can be read safely at a time. */
static grub_size_t
get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors)
get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector)
{
grub_size_t size;
grub_uint64_t offset;
struct grub_biosdisk_data *data = disk->data;
grub_uint32_t sectors = data->sectors;
/* OFFSET = SECTOR % SECTORS */
grub_divmod64 (sector, sectors, &offset);
@ -514,8 +535,8 @@ get_safe_sectors (grub_disk_addr_t sector, grub_uint32_t sectors)
size = sectors - offset;
/* Limit the max to 0x7f because of Phoenix EDD. */
if (size > 0x7f)
size = 0x7f;
if (size > ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size))
size = ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size);
return size;
}
@ -524,21 +545,11 @@ static grub_err_t
grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
struct grub_biosdisk_data *data = disk->data;
while (size)
{
grub_size_t len;
grub_size_t cdoff = 0;
len = get_safe_sectors (sector, data->sectors);
if (data->flags & GRUB_BIOSDISK_FLAG_CDROM)
{
cdoff = (sector & 3) << GRUB_DISK_SECTOR_BITS;
len = ALIGN_UP (sector + len, 4) - (sector & ~3);
sector &= ~3;
}
len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
@ -547,9 +558,10 @@ grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
grub_memcpy (buf, (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + cdoff),
len << GRUB_DISK_SECTOR_BITS);
buf += len << GRUB_DISK_SECTOR_BITS;
grub_memcpy (buf, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR,
len << disk->log_sector_size);
buf += len << disk->log_sector_size;
sector += len;
size -= len;
}
@ -570,18 +582,18 @@ grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
{
grub_size_t len;
len = get_safe_sectors (sector, data->sectors);
len = get_safe_sectors (disk, sector);
if (len > size)
len = size;
grub_memcpy ((void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, buf,
len << GRUB_DISK_SECTOR_BITS);
len << disk->log_sector_size);
if (grub_biosdisk_rw (GRUB_BIOSDISK_WRITE, disk, sector, len,
GRUB_MEMORY_MACHINE_SCRATCH_SEG))
return grub_errno;
buf += len << GRUB_DISK_SECTOR_BITS;
buf += len << disk->log_sector_size;
sector += len;
size -= len;
}
@ -611,10 +623,11 @@ GRUB_MOD_INIT(biosdisk)
{
struct grub_biosdisk_cdrp *cdrp
= (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
grub_uint8_t boot_drive;
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;
}
grub_disk_firmware_fini = grub_disk_biosdisk_fini;
@ -622,15 +635,16 @@ GRUB_MOD_INIT(biosdisk)
grub_memset (cdrp, 0, sizeof (*cdrp));
cdrp->size = sizeof (*cdrp);
cdrp->media_type = 0xFF;
if ((! grub_biosdisk_get_cdinfo_int13_extensions (grub_boot_drive, cdrp)) &&
((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK)
boot_drive = (grub_boot_device >> 24);
if ((! grub_biosdisk_get_cdinfo_int13_extensions (boot_drive, cdrp))
&& ((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK)
== GRUB_BIOSDISK_CDTYPE_NO_EMUL))
cd_drive = cdrp->drive_no;
/* Since diskboot.S rejects devices over 0x90 it must be a CD booted with
cdboot.S
*/
if (grub_boot_drive >= 0x90)
cd_drive = grub_boot_drive;
if (boot_drive >= 0x90)
cd_drive = boot_drive;
grub_disk_dev_register (&grub_biosdisk_dev);
}

View file

@ -32,7 +32,8 @@ struct grub_nand_data
};
static int
grub_nand_iterate (int (*hook) (const char *name))
grub_nand_iterate (int (*hook) (const char *name),
grub_disk_pull_t pull)
{
auto int dev_iterate (struct grub_ieee1275_devalias *alias);
int dev_iterate (struct grub_ieee1275_devalias *alias)
@ -46,6 +47,9 @@ grub_nand_iterate (int (*hook) (const char *name))
return 0;
}
if (pull != GRUB_DISK_PULL_NONE)
return 0;
return grub_devalias_iterate (dev_iterate);
}

View file

@ -152,9 +152,14 @@ scan (void)
}
static int
grub_ofdisk_iterate (int (*hook) (const char *name))
grub_ofdisk_iterate (int (*hook) (const char *name),
grub_disk_pull_t pull)
{
unsigned i;
if (pull != GRUB_DISK_PULL_NONE)
return 0;
scan ();
for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++)
@ -252,14 +257,24 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
grub_dprintf ("disk", "Opening `%s'.\n", devpath);
if (grub_ieee1275_finddevice (devpath, &dev))
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties");
{
grub_free (devpath);
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"can't read device properties");
}
if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop),
&actual))
{
grub_free (devpath);
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
}
if (grub_strcmp (prop, "block"))
{
grub_free (devpath);
return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device");
}
/* XXX: There is no property to read the number of blocks. There
should be a property `#blocks', but it is not there. Perhaps it

View file

@ -133,9 +133,12 @@ fail:
static int
grub_loopback_iterate (int (*hook) (const char *name))
grub_loopback_iterate (int (*hook) (const char *name),
grub_disk_pull_t pull)
{
struct grub_loopback *d;
if (pull != GRUB_DISK_PULL_NONE)
return 0;
for (d = loopback_list; d; d = d->next)
{
if (hook (d->devname))

470
grub-core/disk/luks.c Normal file
View file

@ -0,0 +1,470 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2007,2010,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 <grub/cryptodisk.h>
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/dl.h>
#include <grub/err.h>
#include <grub/disk.h>
#include <grub/crypto.h>
#include <grub/partition.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
#define MAX_PASSPHRASE 256
#define LUKS_KEY_ENABLED 0x00AC71F3
/* On disk LUKS header */
struct grub_luks_phdr
{
grub_uint8_t magic[6];
#define LUKS_MAGIC "LUKS\xBA\xBE"
grub_uint16_t version;
char cipherName[32];
char cipherMode[32];
char hashSpec[32];
grub_uint32_t payloadOffset;
grub_uint32_t keyBytes;
grub_uint8_t mkDigest[20];
grub_uint8_t mkDigestSalt[32];
grub_uint32_t mkDigestIterations;
char uuid[40];
struct
{
grub_uint32_t active;
grub_uint32_t passwordIterations;
grub_uint8_t passwordSalt[32];
grub_uint32_t keyMaterialOffset;
grub_uint32_t stripes;
} keyblock[8];
} __attribute__ ((packed));
typedef struct grub_luks_phdr *grub_luks_phdr_t;
gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
grub_uint8_t * dst, grub_size_t blocksize,
grub_size_t blocknumbers);
static grub_cryptodisk_t
configure_ciphers (grub_disk_t disk, const char *check_uuid,
int check_boot)
{
grub_cryptodisk_t newdev;
const char *iptr;
struct grub_luks_phdr header;
char *optr;
char uuid[sizeof (header.uuid) + 1];
char ciphername[sizeof (header.cipherName) + 1];
char ciphermode[sizeof (header.cipherMode) + 1];
char *cipheriv = NULL;
char hashspec[sizeof (header.hashSpec) + 1];
grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL;
grub_crypto_cipher_handle_t essiv_cipher = NULL;
const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL;
const struct gcry_cipher_spec *ciph;
grub_cryptodisk_mode_t mode;
grub_cryptodisk_mode_iv_t mode_iv;
int benbi_log = 0;
grub_err_t err;
if (check_boot)
return NULL;
/* Read the LUKS header. */
err = grub_disk_read (disk, 0, 0, sizeof (header), &header);
if (err)
{
if (err == GRUB_ERR_OUT_OF_RANGE)
grub_errno = GRUB_ERR_NONE;
return NULL;
}
/* Look for LUKS magic sequence. */
if (grub_memcmp (header.magic, LUKS_MAGIC, sizeof (header.magic))
|| grub_be_to_cpu16 (header.version) != 1)
return NULL;
optr = uuid;
for (iptr = header.uuid; iptr < &header.uuid[ARRAY_SIZE (header.uuid)];
iptr++)
{
if (*iptr != '-')
*optr++ = *iptr;
}
*optr = 0;
if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0)
{
grub_dprintf ("luks", "%s != %s\n", uuid, check_uuid);
return NULL;
}
/* Make sure that strings are null terminated. */
grub_memcpy (ciphername, header.cipherName, sizeof (header.cipherName));
ciphername[sizeof (header.cipherName)] = 0;
grub_memcpy (ciphermode, header.cipherMode, sizeof (header.cipherMode));
ciphermode[sizeof (header.cipherMode)] = 0;
grub_memcpy (hashspec, header.hashSpec, sizeof (header.hashSpec));
hashspec[sizeof (header.hashSpec)] = 0;
ciph = grub_crypto_lookup_cipher_by_name (ciphername);
if (!ciph)
{
grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available",
ciphername);
return NULL;
}
/* Configure the cipher used for the bulk data. */
cipher = grub_crypto_cipher_open (ciph);
if (!cipher)
return NULL;
if (grub_be_to_cpu32 (header.keyBytes) > 1024)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
grub_be_to_cpu32 (header.keyBytes));
return NULL;
}
/* Configure the cipher mode. */
if (grub_strcmp (ciphermode, "ecb") == 0)
{
mode = GRUB_CRYPTODISK_MODE_ECB;
mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
cipheriv = NULL;
}
else if (grub_strcmp (ciphermode, "plain") == 0)
{
mode = GRUB_CRYPTODISK_MODE_CBC;
mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
cipheriv = NULL;
}
else if (grub_memcmp (ciphermode, "cbc-", sizeof ("cbc-") - 1) == 0)
{
mode = GRUB_CRYPTODISK_MODE_CBC;
cipheriv = ciphermode + sizeof ("cbc-") - 1;
}
else if (grub_memcmp (ciphermode, "pcbc-", sizeof ("pcbc-") - 1) == 0)
{
mode = GRUB_CRYPTODISK_MODE_PCBC;
cipheriv = ciphermode + sizeof ("pcbc-") - 1;
}
else if (grub_memcmp (ciphermode, "xts-", sizeof ("xts-") - 1) == 0)
{
mode = GRUB_CRYPTODISK_MODE_XTS;
cipheriv = ciphermode + sizeof ("xts-") - 1;
secondary_cipher = grub_crypto_cipher_open (ciph);
if (!secondary_cipher)
{
grub_crypto_cipher_close (cipher);
return NULL;
}
if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
{
grub_crypto_cipher_close (cipher);
grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
cipher->cipher->blocksize);
return NULL;
}
if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
{
grub_crypto_cipher_close (cipher);
grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d",
secondary_cipher->cipher->blocksize);
return NULL;
}
}
else if (grub_memcmp (ciphermode, "lrw-", sizeof ("lrw-") - 1) == 0)
{
mode = GRUB_CRYPTODISK_MODE_LRW;
cipheriv = ciphermode + sizeof ("lrw-") - 1;
if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES)
{
grub_crypto_cipher_close (cipher);
grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d",
cipher->cipher->blocksize);
return NULL;
}
}
else
{
grub_crypto_cipher_close (cipher);
grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s",
ciphermode);
return NULL;
}
if (cipheriv == NULL);
else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0)
mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN;
else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0)
mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64;
else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0)
{
if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1)
|| cipher->cipher->blocksize == 0)
grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported benbi blocksize: %d",
cipher->cipher->blocksize);
for (benbi_log = 0;
(cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE;
benbi_log++);
mode_iv = GRUB_CRYPTODISK_MODE_IV_BENBI;
}
else if (grub_memcmp (cipheriv, "null", sizeof ("null") - 1) == 0)
mode_iv = GRUB_CRYPTODISK_MODE_IV_NULL;
else if (grub_memcmp (cipheriv, "essiv:", sizeof ("essiv:") - 1) == 0)
{
char *hash_str = cipheriv + 6;
mode_iv = GRUB_CRYPTODISK_MODE_IV_ESSIV;
/* Configure the hash and cipher used for ESSIV. */
essiv_hash = grub_crypto_lookup_md_by_name (hash_str);
if (!essiv_hash)
{
grub_crypto_cipher_close (cipher);
grub_error (GRUB_ERR_FILE_NOT_FOUND,
"Couldn't load %s hash", hash_str);
return NULL;
}
essiv_cipher = grub_crypto_cipher_open (ciph);
if (!essiv_cipher)
{
grub_crypto_cipher_close (cipher);
return NULL;
}
}
else
{
grub_crypto_cipher_close (cipher);
grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s",
cipheriv);
return NULL;
}
/* Configure the hash used for the AF splitter and HMAC. */
hash = grub_crypto_lookup_md_by_name (hashspec);
if (!hash)
{
grub_crypto_cipher_close (cipher);
grub_crypto_cipher_close (essiv_cipher);
grub_crypto_cipher_close (secondary_cipher);
grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash",
hashspec);
return NULL;
}
newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
if (!newdev)
return NULL;
newdev->cipher = cipher;
newdev->offset = grub_be_to_cpu32 (header.payloadOffset);
newdev->source_disk = NULL;
newdev->benbi_log = benbi_log;
newdev->mode = mode;
newdev->mode_iv = mode_iv;
newdev->secondary_cipher = secondary_cipher;
newdev->essiv_cipher = essiv_cipher;
newdev->essiv_hash = essiv_hash;
newdev->hash = hash;
newdev->log_sector_size = 9;
newdev->total_length = grub_disk_get_size (disk) - newdev->offset;
grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
#ifdef GRUB_UTIL
newdev->modname = "luks";
#endif
COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid));
return newdev;
}
static grub_err_t
luks_recover_key (grub_disk_t source,
grub_cryptodisk_t dev)
{
struct grub_luks_phdr header;
grub_size_t keysize;
grub_uint8_t *split_key = NULL;
char passphrase[MAX_PASSPHRASE] = "";
grub_uint8_t candidate_digest[sizeof (header.mkDigest)];
unsigned i;
grub_size_t length;
grub_err_t err;
grub_size_t max_stripes = 1;
char *tmp;
err = grub_disk_read (source, 0, 0, sizeof (header), &header);
if (err)
return err;
grub_puts_ (N_("Attempting to decrypt master key..."));
keysize = grub_be_to_cpu32 (header.keyBytes);
for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
if (grub_be_to_cpu32 (header.keyblock[i].active) == LUKS_KEY_ENABLED
&& grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes)
max_stripes = grub_be_to_cpu32 (header.keyblock[i].stripes);
split_key = grub_malloc (keysize * max_stripes);
if (!split_key)
return grub_errno;
/* Get the passphrase from the user. */
tmp = NULL;
if (source->partition)
tmp = grub_partition_get_name (source->partition);
grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
source->partition ? "," : "", tmp ? : "",
dev->uuid);
grub_free (tmp);
if (!grub_password_get (passphrase, MAX_PASSPHRASE))
{
grub_free (split_key);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
}
/* Try to recover master key from each active keyslot. */
for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
{
gcry_err_code_t gcry_err;
grub_uint8_t candidate_key[keysize];
grub_uint8_t digest[keysize];
/* Check if keyslot is enabled. */
if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED)
continue;
grub_dprintf ("luks", "Trying keyslot %d\n", i);
/* Calculate the PBKDF2 of the user supplied passphrase. */
gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
grub_strlen (passphrase),
header.keyblock[i].passwordSalt,
sizeof (header.keyblock[i].passwordSalt),
grub_be_to_cpu32 (header.keyblock[i].
passwordIterations),
digest, keysize);
if (gcry_err)
{
grub_free (split_key);
return grub_crypto_gcry_error (gcry_err);
}
grub_dprintf ("luks", "PBKDF2 done\n");
gcry_err = grub_cryptodisk_setkey (dev, digest, keysize);
if (gcry_err)
{
grub_free (split_key);
return grub_crypto_gcry_error (gcry_err);
}
length = (keysize * grub_be_to_cpu32 (header.keyblock[i].stripes));
/* Read and decrypt the key material from the disk. */
err = grub_disk_read (source,
grub_be_to_cpu32 (header.keyblock
[i].keyMaterialOffset), 0,
length, split_key);
if (err)
{
grub_free (split_key);
return err;
}
gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
if (gcry_err)
{
grub_free (split_key);
return grub_crypto_gcry_error (gcry_err);
}
/* Merge the decrypted key material to get the candidate master key. */
gcry_err = AF_merge (dev->hash, split_key, candidate_key, keysize,
grub_be_to_cpu32 (header.keyblock[i].stripes));
if (gcry_err)
{
grub_free (split_key);
return grub_crypto_gcry_error (gcry_err);
}
grub_dprintf ("luks", "candidate key recovered\n");
/* Calculate the PBKDF2 of the candidate master key. */
gcry_err = grub_crypto_pbkdf2 (dev->hash, candidate_key,
grub_be_to_cpu32 (header.keyBytes),
header.mkDigestSalt,
sizeof (header.mkDigestSalt),
grub_be_to_cpu32
(header.mkDigestIterations),
candidate_digest,
sizeof (candidate_digest));
if (gcry_err)
{
grub_free (split_key);
return grub_crypto_gcry_error (gcry_err);
}
/* Compare the calculated PBKDF2 to the digest stored
in the header to see if it's correct. */
if (grub_memcmp (candidate_digest, header.mkDigest,
sizeof (header.mkDigest)) != 0)
{
grub_dprintf ("luks", "bad digest\n");
continue;
}
grub_printf_ (N_("Slot %d opened\n"), i);
/* Set the master key. */
gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize);
if (gcry_err)
{
grub_free (split_key);
return grub_crypto_gcry_error (gcry_err);
}
grub_free (split_key);
return GRUB_ERR_NONE;
}
return GRUB_ACCESS_DENIED;
}
struct grub_cryptodisk_dev luks_crypto = {
.scan = configure_ciphers,
.recover_key = luks_recover_key
};
GRUB_MOD_INIT (luks)
{
COMPILE_TIME_ASSERT (sizeof (((struct grub_luks_phdr *) 0)->uuid)
< GRUB_CRYPTODISK_MAX_UUID_LENGTH);
grub_cryptodisk_dev_register (&luks_crypto);
}
GRUB_MOD_FINI (luks)
{
grub_cryptodisk_dev_unregister (&luks_crypto);
}

View file

@ -1,7 +1,7 @@
/* lvm.c - module to read Logical Volumes. */
/*
* 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
* it under the terms of the GNU General Public License as published by
@ -23,22 +23,28 @@
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/lvm.h>
#include <grub/partition.h>
#include <grub/i18n.h>
#ifdef GRUB_UTIL
#include <grub/emu/misc.h>
#include <grub/emu/hostdisk.h>
#endif
GRUB_MOD_LICENSE ("GPLv3+");
static struct grub_lvm_vg *vg_list;
static int lv_count;
static int scan_depth = 0;
static int is_lv_readable (struct grub_lvm_lv *lv);
/* Go the string STR and return the number after STR. *P will point
at the number. In case STR is not found, *P will be NULL and the
return value will be 0. */
static int
grub_lvm_getvalue (char **p, char *str)
grub_lvm_getvalue (char **p, const char *str)
{
*p = grub_strstr (*p, str);
if (! *p)
@ -63,7 +69,7 @@ grub_lvm_checkvalue (char **p, char *str, char *tmpl)
#endif
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);
while (1)
@ -95,48 +101,8 @@ grub_lvm_check_flag (char *p, char *str, char *flag)
}
}
static int
grub_lvm_iterate (int (*hook) (const char *name))
{
struct grub_lvm_vg *vg;
for (vg = vg_list; vg; vg = vg->next)
{
struct grub_lvm_lv *lv;
if (vg->lvs)
for (lv = vg->lvs; lv; lv = lv->next)
if (lv->visible && hook (lv->name))
return 1;
}
return 0;
}
#ifdef GRUB_UTIL
static grub_disk_memberlist_t
grub_lvm_memberlist (grub_disk_t disk)
{
struct grub_lvm_lv *lv = disk->data;
grub_disk_memberlist_t list = NULL, tmp;
struct grub_lvm_pv *pv;
if (lv->vg->pvs)
for (pv = lv->vg->pvs; pv; pv = pv->next)
{
if (!pv->disk)
grub_util_error ("Couldn't find PV %s. Check your device.map",
pv->name);
tmp = grub_malloc (sizeof (*tmp));
tmp->disk = pv->disk;
tmp->next = list;
list = tmp;
}
return list;
}
#endif
static grub_err_t
grub_lvm_open (const char *name, grub_disk_t disk)
static struct grub_lvm_lv *
find_lv (const char *name)
{
struct grub_lvm_vg *vg;
struct grub_lvm_lv *lv = NULL;
@ -144,166 +110,20 @@ grub_lvm_open (const char *name, grub_disk_t disk)
{
if (vg->lvs)
for (lv = vg->lvs; lv; lv = lv->next)
if (! grub_strcmp (lv->name, name))
break;
if (lv)
break;
if ((grub_strcmp (lv->fullname, name) == 0
|| grub_strcmp (lv->compatname, name) == 0)
&& is_lv_readable (lv))
return lv;
}
if (! lv)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown LVM device %s", name);
disk->id = lv->number;
disk->data = lv;
disk->total_sectors = lv->size;
return 0;
return NULL;
}
static void
grub_lvm_close (grub_disk_t disk __attribute ((unused)))
do_lvm_scan (const char *scan_for)
{
return;
}
static grub_err_t
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
grub_size_t size, char *buf);
static grub_err_t
read_node (const struct grub_lvm_node *node, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
/* Check whether we actually know the physical volume we want to
read from. */
if (node->pv)
auto int grub_lvm_scan_device (const char *name);
int grub_lvm_scan_device (const char *name)
{
if (node->pv->disk)
return grub_disk_read (node->pv->disk, sector + node->pv->start, 0,
size << GRUB_DISK_SECTOR_BITS, buf);
else
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"physical volume %s not found", node->pv->name);
}
if (node->lv)
return read_lv (node->lv, sector, size, buf);
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name);
}
static grub_err_t
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
grub_err_t err = 0;
struct grub_lvm_vg *vg = lv->vg;
struct grub_lvm_segment *seg = lv->segments;
struct grub_lvm_node *node;
grub_uint64_t offset;
grub_uint64_t extent;
unsigned int i;
if (!lv)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume");
extent = grub_divmod64 (sector, vg->extent_size, NULL);
/* Find the right segment. */
for (i = 0; i < lv->segment_count; i++)
{
if ((seg->start_extent <= extent)
&& ((seg->start_extent + seg->extent_count) > extent))
{
break;
}
seg++;
}
if (i == lv->segment_count)
return grub_error (GRUB_ERR_READ_ERROR, "incorrect segment");
switch (seg->type)
{
case GRUB_LVM_STRIPED:
if (seg->node_count == 1)
{
/* This segment is linear, so that's easy. We just need to find
out the offset in the physical volume and read SIZE bytes
from that. */
struct grub_lvm_node *stripe = seg->nodes;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
node = stripe;
seg_offset = ((grub_uint64_t) stripe->start
* (grub_uint64_t) vg->extent_size);
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size) + seg_offset;
}
else
{
/* This is a striped segment. We have to find the right PV
similar to RAID0. */
struct grub_lvm_node *stripe = seg->nodes;
grub_uint64_t a, b;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
grub_uint64_t stripenr;
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size);
a = grub_divmod64 (offset, seg->stripe_size, NULL);
grub_divmod64 (a, seg->node_count, &stripenr);
a = grub_divmod64 (offset, seg->stripe_size * seg->node_count, NULL);
grub_divmod64 (offset, seg->stripe_size, &b);
offset = a * seg->stripe_size + b;
stripe += stripenr;
node = stripe;
seg_offset = ((grub_uint64_t) stripe->start
* (grub_uint64_t) vg->extent_size);
offset += seg_offset;
}
return read_node (node, offset, size, buf);
case GRUB_LVM_MIRROR:
i = 0;
while (1)
{
err = read_node (&seg->nodes[i], sector, size, buf);
if (!err)
return err;
if (++i >= seg->node_count)
return err;
grub_errno = GRUB_ERR_NONE;
}
}
return grub_error (GRUB_ERR_IO, "unknown LVM segment");
}
static grub_err_t
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
return read_lv (disk->data, sector, size, buf);
}
static grub_err_t
grub_lvm_write (grub_disk_t disk __attribute ((unused)),
grub_disk_addr_t sector __attribute ((unused)),
grub_size_t size __attribute ((unused)),
const char *buf __attribute ((unused)))
{
return GRUB_ERR_NOT_IMPLEMENTED_YET;
}
static int
grub_lvm_scan_device (const char *name)
{
grub_err_t err;
grub_disk_t disk;
grub_uint64_t mda_offset, mda_size;
@ -332,6 +152,19 @@ grub_lvm_scan_device (const char *name)
return 0;
}
for (vg = vg_list; vg; vg = vg->next)
for (pv = vg->pvs; pv; pv = pv->next)
if (pv->disk && pv->disk->id == disk->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);
return 0;
}
/* Search for label. */
for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++)
{
@ -573,11 +406,43 @@ grub_lvm_scan_device (const char *name)
q++;
s = q - p;
lv->name = grub_malloc (vgname_len + 1 + s + 1);
grub_memcpy (lv->name, vgname, vgname_len);
lv->name[vgname_len] = '-';
grub_memcpy (lv->name + vgname_len + 1, p, s);
lv->name[vgname_len + 1 + s] = '\0';
lv->name = grub_strndup (p, s);
if (!lv->name)
goto lvs_fail;
lv->compatname = grub_malloc (vgname_len + 1 + s + 1);
if (!lv->compatname)
goto lvs_fail;
grub_memcpy (lv->compatname, vgname, vgname_len);
lv->compatname[vgname_len] = '-';
grub_memcpy (lv->compatname + vgname_len + 1, p, s);
lv->compatname[vgname_len + 1 + s] = '\0';
{
const char *iptr;
char *optr;
lv->fullname = grub_malloc (sizeof("lvm/") + 2 * vgname_len
+ 1 + 2 * s + 1);
if (!lv->fullname)
goto lvs_fail;
optr = lv->fullname;
grub_memcpy (optr, "lvm/", sizeof ("lvm/") - 1);
optr += sizeof ("lvm/") - 1;
for (iptr = vgname; iptr < vgname + vgname_len; iptr++)
{
*optr++ = *iptr;
if (*iptr == '-')
*optr++ = '-';
}
*optr++ = '-';
for (iptr = p; iptr < p + s; iptr++)
{
*optr++ = *iptr;
if (*iptr == '-')
*optr++ = '-';
}
*optr++ = 0;
}
lv->size = 0;
@ -857,7 +722,285 @@ grub_lvm_scan_device (const char *name)
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
grub_errno = GRUB_ERR_NONE;
grub_print_error ();
if (scan_for && find_lv (scan_for))
return 1;
return 0;
}
scan_depth++;
grub_device_iterate (&grub_lvm_scan_device);
scan_depth--;
}
static int
grub_lvm_iterate (int (*hook) (const char *name),
grub_disk_pull_t pull)
{
struct grub_lvm_vg *vg;
unsigned old_count = 0;
if (pull == GRUB_DISK_PULL_RESCAN && scan_depth)
return 0;
if (pull == GRUB_DISK_PULL_RESCAN)
{
old_count = lv_count;
if (!scan_depth)
do_lvm_scan (NULL);
}
if (pull != GRUB_DISK_PULL_RESCAN && pull != GRUB_DISK_PULL_NONE)
return GRUB_ERR_NONE;
for (vg = vg_list; vg; vg = vg->next)
{
struct grub_lvm_lv *lv;
if (vg->lvs)
for (lv = vg->lvs; lv; lv = lv->next)
if (lv->visible && lv->number >= old_count)
{
if (hook (lv->fullname))
return 1;
}
}
return 0;
}
#ifdef GRUB_UTIL
static grub_disk_memberlist_t
grub_lvm_memberlist (grub_disk_t disk)
{
struct grub_lvm_lv *lv = disk->data;
grub_disk_memberlist_t list = NULL, tmp;
struct grub_lvm_pv *pv;
if (lv->vg->pvs)
for (pv = lv->vg->pvs; pv; pv = pv->next)
{
if (!pv->disk)
grub_util_error (_("Couldn't find PV %s. Check your device.map"),
pv->name);
tmp = grub_malloc (sizeof (*tmp));
tmp->disk = pv->disk;
tmp->next = list;
list = tmp;
}
return list;
}
#endif
static grub_err_t
grub_lvm_open (const char *name, grub_disk_t disk)
{
struct grub_lvm_lv *lv = NULL;
int explicit = 0;
if (grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) == 0)
explicit = 1;
lv = find_lv (name);
if (! lv && !scan_depth && explicit)
{
do_lvm_scan (name);
if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
lv = find_lv (name);
}
if (! lv)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown LVM device %s", name);
disk->id = lv->number;
disk->data = lv;
disk->total_sectors = lv->size;
return 0;
}
static void
grub_lvm_close (grub_disk_t disk __attribute ((unused)))
{
return;
}
static grub_err_t
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
grub_size_t size, char *buf);
static grub_err_t
read_node (const struct grub_lvm_node *node, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
/* Check whether we actually know the physical volume we want to
read from. */
if (node->pv)
{
if (node->pv->disk)
return grub_disk_read (node->pv->disk, sector + node->pv->start, 0,
size << GRUB_DISK_SECTOR_BITS, buf);
else
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"physical volume %s not found", node->pv->name);
}
if (node->lv)
return read_lv (node->lv, sector, size, buf);
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name);
}
static grub_err_t
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
grub_err_t err = 0;
struct grub_lvm_vg *vg = lv->vg;
struct grub_lvm_segment *seg = lv->segments;
struct grub_lvm_node *node;
grub_uint64_t offset;
grub_uint64_t extent;
unsigned int i;
if (!lv)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume");
extent = grub_divmod64 (sector, vg->extent_size, NULL);
/* Find the right segment. */
for (i = 0; i < lv->segment_count; i++)
{
if ((seg->start_extent <= extent)
&& ((seg->start_extent + seg->extent_count) > extent))
{
break;
}
seg++;
}
if (i == lv->segment_count)
return grub_error (GRUB_ERR_READ_ERROR, "incorrect segment");
switch (seg->type)
{
case GRUB_LVM_STRIPED:
if (seg->node_count == 1)
{
/* This segment is linear, so that's easy. We just need to find
out the offset in the physical volume and read SIZE bytes
from that. */
struct grub_lvm_node *stripe = seg->nodes;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
node = stripe;
seg_offset = ((grub_uint64_t) stripe->start
* (grub_uint64_t) vg->extent_size);
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size) + seg_offset;
}
else
{
/* This is a striped segment. We have to find the right PV
similar to RAID0. */
struct grub_lvm_node *stripe = seg->nodes;
grub_uint64_t a, b;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
grub_uint64_t stripenr;
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size);
a = grub_divmod64 (offset, seg->stripe_size, NULL);
grub_divmod64 (a, seg->node_count, &stripenr);
a = grub_divmod64 (offset, seg->stripe_size * seg->node_count, NULL);
grub_divmod64 (offset, seg->stripe_size, &b);
offset = a * seg->stripe_size + b;
stripe += stripenr;
node = stripe;
seg_offset = ((grub_uint64_t) stripe->start
* (grub_uint64_t) vg->extent_size);
offset += seg_offset;
}
return read_node (node, offset, size, buf);
case GRUB_LVM_MIRROR:
i = 0;
while (1)
{
err = read_node (&seg->nodes[i], sector, size, buf);
if (!err)
return err;
if (++i >= seg->node_count)
return err;
grub_errno = GRUB_ERR_NONE;
}
}
return grub_error (GRUB_ERR_IO, "unknown LVM segment");
}
static grub_err_t
is_node_readable (const struct grub_lvm_node *node)
{
/* Check whether we actually know the physical volume we want to
read from. */
if (node->pv)
return !!(node->pv->disk);
if (node->lv)
return is_lv_readable (node->lv);
return 0;
}
static int
is_lv_readable (struct grub_lvm_lv *lv)
{
unsigned int i, j;
if (!lv)
return 0;
/* Find the right segment. */
for (i = 0; i < lv->segment_count; i++)
switch (lv->segments[i].type)
{
case GRUB_LVM_STRIPED:
for (j = 0; j < lv->segments[i].node_count; j++)
if (!is_node_readable (lv->segments[i].nodes + j))
return 0;
break;
case GRUB_LVM_MIRROR:
for (j = 0; j < lv->segments[i].node_count; j++)
if (is_node_readable (lv->segments[i].nodes + j))
break;
if (j == lv->segments[i].node_count)
return 0;
default:
return 0;
}
return 1;
}
static grub_err_t
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
return read_lv (disk->data, sector, size, buf);
}
static grub_err_t
grub_lvm_write (grub_disk_t disk __attribute ((unused)),
grub_disk_addr_t sector __attribute ((unused)),
grub_size_t size __attribute ((unused)),
const char *buf __attribute ((unused)))
{
return GRUB_ERR_NOT_IMPLEMENTED_YET;
}
static struct grub_disk_dev grub_lvm_dev =
@ -878,13 +1021,6 @@ static struct grub_disk_dev grub_lvm_dev =
GRUB_MOD_INIT(lvm)
{
grub_device_iterate (&grub_lvm_scan_device);
if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
grub_disk_dev_register (&grub_lvm_dev);
}

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->index = grub_le_to_cpu32 (sb.this_disk.number);
array->uuid_len = 16;
array->uuid = grub_malloc (16);
uuid = grub_malloc (16);
array->uuid = (char *) uuid;
if (!array->uuid)
return grub_errno;
uuid = (grub_uint32_t *) array->uuid;
uuid[0] = grub_swap_bytes32 (sb.set_uuid0);
uuid[1] = grub_swap_bytes32 (sb.set_uuid1);
uuid[2] = grub_swap_bytes32 (sb.set_uuid2);

View file

@ -30,8 +30,12 @@ static char *memdisk_addr;
static grub_off_t memdisk_size = 0;
static int
grub_memdisk_iterate (int (*hook) (const char *name))
grub_memdisk_iterate (int (*hook) (const char *name),
grub_disk_pull_t pull)
{
if (pull != GRUB_DISK_PULL_NONE)
return 0;
return hook ("memdisk");
}
@ -82,9 +86,8 @@ static struct grub_disk_dev grub_memdisk_dev =
GRUB_MOD_INIT(memdisk)
{
auto int hook (struct grub_module_header *);
int hook (struct grub_module_header *header)
{
struct grub_module_header *header;
FOR_MODULES (header)
if (header->type == OBJ_TYPE_MEMDISK)
{
char *memdisk_orig_addr;
@ -99,13 +102,8 @@ GRUB_MOD_INIT(memdisk)
grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
grub_disk_dev_register (&grub_memdisk_dev);
return 1;
break;
}
return 0;
}
grub_module_iterate (hook);
}
GRUB_MOD_FINI(memdisk)

538
grub-core/disk/pata.c Normal file
View file

@ -0,0 +1,538 @@
/* ata_pthru.c - ATA pass through for ata.mod. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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/ata.h>
#include <grub/scsi.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/mm.h>
#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
#include <grub/pci.h>
#include <grub/cs5536.h>
#else
#define GRUB_MACHINE_PCI_IO_BASE 0xb4000000
#endif
#include <grub/time.h>
GRUB_MOD_LICENSE ("GPLv3+");
/* At the moment, only two IDE ports are supported. */
static const grub_port_t grub_pata_ioaddress[] = { GRUB_ATA_CH0_PORT1,
GRUB_ATA_CH1_PORT1 };
struct grub_pata_device
{
/* IDE port to use. */
int port;
/* IO addresses on which the registers for this device can be
found. */
grub_port_t ioaddress;
/* Two devices can be connected to a single cable. Use this field
to select device 0 (commonly known as "master") or device 1
(commonly known as "slave"). */
int device;
int present;
struct grub_pata_device *next;
};
static struct grub_pata_device *grub_pata_devices;
static inline void
grub_pata_regset (struct grub_pata_device *dev, int reg, int val)
{
grub_outb (val, dev->ioaddress + reg);
}
static inline grub_uint8_t
grub_pata_regget (struct grub_pata_device *dev, int reg)
{
return grub_inb (dev->ioaddress + reg);
}
/* Wait for !BSY. */
static grub_err_t
grub_pata_wait_not_busy (struct grub_pata_device *dev, int milliseconds)
{
/* ATA requires 400ns (after a write to CMD register) or
1 PIO cycle (after a DRQ block transfer) before
first check of BSY. */
grub_millisleep (1);
int i = 1;
grub_uint8_t sts;
while ((sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS))
& GRUB_ATA_STATUS_BUSY)
{
if (i >= milliseconds)
{
grub_dprintf ("pata", "timeout: %dms, status=0x%x\n",
milliseconds, sts);
return grub_error (GRUB_ERR_TIMEOUT, "PATA timeout");
}
grub_millisleep (1);
i++;
}
return GRUB_ERR_NONE;
}
static inline grub_err_t
grub_pata_check_ready (struct grub_pata_device *dev, int spinup)
{
if (grub_pata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY)
return grub_pata_wait_not_busy (dev, spinup ? GRUB_ATA_TOUT_SPINUP
: GRUB_ATA_TOUT_STD);
return GRUB_ERR_NONE;
}
static inline void
grub_pata_wait (void)
{
grub_millisleep (50);
}
static void
grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size)
{
unsigned int i;
/* Read in the data, word by word. */
for (i = 0; i < size / 2; i++)
grub_set_unaligned16 (buf + 2 * i,
grub_le_to_cpu16 (grub_inw(dev->ioaddress
+ GRUB_ATA_REG_DATA)));
if (size & 1)
buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress
+ GRUB_ATA_REG_DATA));
}
static void
grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size)
{
unsigned int i;
/* Write the data, word by word. */
for (i = 0; i < size / 2; i++)
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. */
static grub_err_t
grub_pata_readwrite (struct grub_ata *disk,
struct grub_disk_ata_pass_through_parms *parms,
int spinup)
{
struct grub_pata_device *dev = (struct grub_pata_device *) disk->data;
grub_size_t nread = 0;
int i;
if (! (parms->cmdsize == 0 || parms->cmdsize == 12))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"ATAPI non-12 byte commands not supported");
grub_dprintf ("pata", "pata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x\n",
parms->taskfile.cmd,
parms->taskfile.features,
parms->taskfile.sectors);
grub_dprintf ("pata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%"
PRIuGRUB_SIZE "\n",
parms->taskfile.lba_high,
parms->taskfile.lba_mid,
parms->taskfile.lba_low, parms->size);
/* Set registers. */
grub_pata_regset (dev, GRUB_ATA_REG_DISK, (dev->device << 4)
| (parms->taskfile.disk & 0xef));
if (grub_pata_check_ready (dev, spinup))
return grub_errno;
for (i = GRUB_ATA_REG_SECTORS; i <= GRUB_ATA_REG_LBAHIGH; i++)
grub_pata_regset (dev, i,
parms->taskfile.raw[7 + (i - GRUB_ATA_REG_SECTORS)]);
for (i = GRUB_ATA_REG_FEATURES; i <= GRUB_ATA_REG_LBAHIGH; i++)
grub_pata_regset (dev, i, parms->taskfile.raw[i - GRUB_ATA_REG_FEATURES]);
/* Start command. */
grub_pata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile.cmd);
/* Wait for !BSY. */
if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
return grub_errno;
/* Check status. */
grub_int8_t sts = grub_pata_regget (dev, GRUB_ATA_REG_STATUS);
grub_dprintf ("pata", "status=0x%x\n", sts);
if (parms->cmdsize)
{
grub_uint8_t irs;
/* Wait for !BSY. */
if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
return grub_errno;
irs = grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON);
/* OK if DRQ is asserted and interrupt reason is as expected. */
if (!((sts & GRUB_ATA_STATUS_DRQ)
&& (irs & GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_CMD_OUT))
return grub_error (GRUB_ERR_READ_ERROR, "ATAPI protocol error");
/* Write the packet. */
grub_pata_pio_write (dev, parms->cmd, parms->cmdsize);
}
/* Transfer data. */
while (nread < parms->size
&& ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
== GRUB_ATA_STATUS_DRQ)
&& (!parms->cmdsize
|| ((grub_pata_regget (dev, GRUB_ATAPI_REG_IREASON)
& GRUB_ATAPI_IREASON_MASK) == GRUB_ATAPI_IREASON_DATA_IN)))
{
unsigned cnt;
/* Wait for !BSY. */
if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
return grub_errno;
if (parms->cmdsize)
{
cnt = grub_pata_regget (dev, GRUB_ATAPI_REG_CNTHIGH) << 8
| grub_pata_regget (dev, GRUB_ATAPI_REG_CNTLOW);
grub_dprintf("pata", "DRQ count=%u\n", cnt);
/* Count of last transfer may be uneven. */
if (! (0 < cnt && cnt <= parms->size - nread
&& (! (cnt & 1) || cnt == parms->size - nread)))
return grub_error (GRUB_ERR_READ_ERROR,
"invalid ATAPI transfer count");
}
else
cnt = GRUB_DISK_SECTOR_SIZE;
if (cnt > parms->size - nread)
cnt = parms->size - nread;
if (parms->write)
grub_pata_pio_write (dev, (char *) parms->buffer + nread, cnt);
else
grub_pata_pio_read (dev, (char *) parms->buffer + nread, cnt);
nread += cnt;
}
if (parms->write)
{
/* Check for write error. */
if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
return grub_errno;
if (grub_pata_regget (dev, GRUB_ATA_REG_STATUS)
& (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
return grub_error (GRUB_ERR_WRITE_ERROR, "ATA write error");
}
parms->size = nread;
/* Wait for !BSY. */
if (grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
return grub_errno;
/* Return registers. */
for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++)
parms->taskfile.raw[i - GRUB_ATA_REG_FEATURES] = grub_pata_regget (dev, i);
grub_dprintf ("pata", "status=0x%x, error=0x%x, sectors=0x%x\n",
parms->taskfile.status,
parms->taskfile.error,
parms->taskfile.sectors);
if (parms->taskfile.status
& (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
return grub_error (GRUB_ERR_READ_ERROR, "PATA passthrough failed");
return GRUB_ERR_NONE;
}
static grub_err_t
check_device (struct grub_pata_device *dev)
{
grub_pata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4);
grub_pata_wait ();
/* Try to detect if the port is in use by writing to it,
waiting for a while and reading it again. If the value
was preserved, there is a device connected. */
grub_pata_regset (dev, GRUB_ATA_REG_SECTORS, 0x5A);
grub_pata_wait ();
grub_uint8_t sec = grub_pata_regget (dev, GRUB_ATA_REG_SECTORS);
grub_dprintf ("ata", "sectors=0x%x\n", sec);
if (sec != 0x5A)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no device connected");
/* The above test may detect a second (slave) device
connected to a SATA controller which supports only one
(master) device. It is not safe to use the status register
READY bit to check for controller channel existence. Some
ATAPI commands (RESET, DIAGNOSTIC) may clear this bit. */
return GRUB_ERR_NONE;
}
static grub_err_t
grub_pata_device_initialize (int port, int device, int addr)
{
struct grub_pata_device *dev;
struct grub_pata_device **devp;
grub_err_t err;
grub_dprintf ("pata", "detecting device %d,%d (0x%x)\n",
port, device, addr);
dev = grub_malloc (sizeof(*dev));
if (! dev)
return grub_errno;
/* Setup the device information. */
dev->port = port;
dev->device = device;
dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE;
dev->present = 1;
dev->next = NULL;
/* Register the device. */
for (devp = &grub_pata_devices; *devp; devp = &(*devp)->next);
*devp = dev;
err = check_device (dev);
if (err)
grub_print_error ();
return 0;
}
#ifndef GRUB_MACHINE_MIPS_QEMU_MIPS
static int NESTED_FUNC_ATTR
grub_pata_pciinit (grub_pci_device_t dev,
grub_pci_id_t pciid)
{
static int compat_use[2] = { 0 };
grub_pci_address_t addr;
grub_uint32_t class;
grub_uint32_t bar1;
grub_uint32_t bar2;
int rega;
int i;
static int controller = 0;
int cs5536 = 0;
int nports = 2;
/* Read class. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
class = grub_pci_read (addr);
/* AMD CS5536 Southbridge. */
if (pciid == GRUB_CS5536_PCIID)
{
cs5536 = 1;
nports = 1;
}
/* Check if this class ID matches that of a PCI IDE Controller. */
if (!cs5536 && (class >> 16 != 0x0101))
return 0;
for (i = 0; i < nports; i++)
{
/* Set to 0 when the channel operated in compatibility mode. */
int compat;
/* We don't support non-compatibility mode for CS5536. */
if (cs5536)
compat = 0;
else
compat = (class >> (8 + 2 * i)) & 1;
rega = 0;
/* If the channel is in compatibility mode, just assign the
default registers. */
if (compat == 0 && !compat_use[i])
{
rega = grub_pata_ioaddress[i];
compat_use[i] = 1;
}
else if (compat)
{
/* Read the BARs, which either contain a mmapped IO address
or the IO port address. */
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES
+ sizeof (grub_uint64_t) * i);
bar1 = grub_pci_read (addr);
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES
+ sizeof (grub_uint64_t) * i
+ sizeof (grub_uint32_t));
bar2 = grub_pci_read (addr);
/* Check if the BARs describe an IO region. */
if ((bar1 & 1) && (bar2 & 1))
{
rega = bar1 & ~3;
}
}
grub_dprintf ("pata",
"PCI dev (%d,%d,%d) compat=%d rega=0x%x\n",
grub_pci_get_bus (dev), grub_pci_get_device (dev),
grub_pci_get_function (dev), compat, rega);
if (rega)
{
grub_errno = GRUB_ERR_NONE;
grub_pata_device_initialize (controller * 2 + i, 0, rega);
/* Most errors raised by grub_ata_device_initialize() are harmless.
They just indicate this particular drive is not responding, most
likely because it doesn't exist. We might want to ignore specific
error types here, instead of printing them. */
if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
grub_pata_device_initialize (controller * 2 + i, 1, rega);
/* Likewise. */
if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
}
}
controller++;
return 0;
}
static grub_err_t
grub_pata_initialize (void)
{
grub_pci_iterate (grub_pata_pciinit);
return 0;
}
#else
static grub_err_t
grub_pata_initialize (void)
{
int i;
for (i = 0; i < 2; i++)
{
grub_pata_device_initialize (i, 0, grub_pata_ioaddress[i]);
grub_pata_device_initialize (i, 1, grub_pata_ioaddress[i]);
}
return 0;
}
#endif
static grub_err_t
grub_pata_open (int id, int devnum, struct grub_ata *ata)
{
struct grub_pata_device *dev;
struct grub_pata_device *devfnd = 0;
grub_err_t err;
if (id != GRUB_SCSI_SUBSYSTEM_PATA)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a PATA device");
for (dev = grub_pata_devices; dev; dev = dev->next)
{
if (dev->port * 2 + dev->device == devnum)
{
devfnd = dev;
break;
}
}
grub_dprintf ("pata", "opening PATA dev `ata%d'\n", devnum);
if (! devfnd)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such PATA device");
err = check_device (devfnd);
if (err)
return err;
ata->data = devfnd;
ata->dma = 0;
ata->present = &devfnd->present;
return GRUB_ERR_NONE;
}
static int
grub_pata_iterate (int (*hook) (int id, int bus),
grub_disk_pull_t pull)
{
struct grub_pata_device *dev;
if (pull != GRUB_DISK_PULL_NONE)
return 0;
for (dev = grub_pata_devices; dev; dev = dev->next)
if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device))
return 1;
return 0;
}
static struct grub_ata_dev grub_pata_dev =
{
.iterate = grub_pata_iterate,
.open = grub_pata_open,
.readwrite = grub_pata_readwrite,
};
GRUB_MOD_INIT(ata_pthru)
{
/* To prevent two drivers operating on the same disks. */
grub_disk_firmware_is_tainted = 1;
if (grub_disk_firmware_fini)
{
grub_disk_firmware_fini ();
grub_disk_firmware_fini = NULL;
}
/* ATA initialization. */
grub_pata_initialize ();
grub_ata_dev_register (&grub_pata_dev);
}
GRUB_MOD_FINI(ata_pthru)
{
grub_ata_dev_unregister (&grub_pata_dev);
}

View file

@ -23,6 +23,7 @@
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/raid.h>
#include <grub/partition.h>
#ifdef GRUB_UTIL
#include <grub/util/misc.h>
#endif
@ -33,6 +34,11 @@ GRUB_MOD_LICENSE ("GPLv3+");
static struct grub_raid_array *array_list;
grub_raid5_recover_func_t grub_raid5_recover_func;
grub_raid6_recover_func_t grub_raid6_recover_func;
static grub_raid_t grub_raid_list;
static int inscnt = 0;
static struct grub_raid_array *
find_array (const char *name);
static char
@ -78,14 +84,102 @@ grub_is_array_readable (struct grub_raid_array *array)
return 0;
}
static grub_err_t
insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
grub_disk_addr_t start_sector, const char *scanner_name,
grub_raid_t raid __attribute__ ((unused)));
static int scan_depth = 0;
static void
scan_devices (const char *arname)
{
grub_raid_t raid;
auto int hook (const char *name);
int hook (const char *name)
{
grub_disk_t disk;
struct grub_raid_array array;
struct grub_raid_array *arr;
grub_disk_addr_t start_sector;
grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n",
raid->name, name);
#ifdef GRUB_UTIL
grub_util_info ("Scanning for %s RAID devices on disk %s",
raid->name, name);
#endif
disk = grub_disk_open (name);
if (!disk)
return 0;
for (arr = array_list; arr != NULL; arr = arr->next)
{
struct grub_raid_member *m;
for (m = arr->members; m < arr->members + arr->nr_devs; m++)
if (m->device && m->device->id == disk->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);
return 0;
}
}
if ((disk->total_sectors != GRUB_ULONG_MAX) &&
(! raid->detect (disk, &array, &start_sector)) &&
(! insert_array (disk, &array, start_sector, raid->name,
raid)))
return 0;
/* This error usually means it's not raid, no need to display
it. */
if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
grub_disk_close (disk);
if (arname && find_array (arname))
return 1;
return 0;
}
if (scan_depth)
return;
scan_depth++;
for (raid = grub_raid_list; raid; raid = raid->next)
grub_device_iterate (&hook);
scan_depth--;
}
static int
grub_raid_iterate (int (*hook) (const char *name))
grub_raid_iterate (int (*hook) (const char *name),
grub_disk_pull_t pull)
{
struct grub_raid_array *array;
int islcnt = 0;
if (pull == GRUB_DISK_PULL_RESCAN)
{
islcnt = inscnt;
scan_devices (NULL);
}
if (pull != GRUB_DISK_PULL_NONE && pull != GRUB_DISK_PULL_RESCAN)
return 0;
for (array = array_list; array != NULL; array = array->next)
{
if (grub_is_array_readable (array))
if (grub_is_array_readable (array) && array->became_readable_at >= islcnt)
if (hook (array->name))
return 1;
}
@ -134,11 +228,10 @@ ascii2hex (char c)
return 0;
}
static grub_err_t
grub_raid_open (const char *name, grub_disk_t disk)
static struct grub_raid_array *
find_array (const char *name)
{
struct grub_raid_array *array;
unsigned n;
if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0)
{
@ -155,7 +248,7 @@ grub_raid_open (const char *name, grub_disk_t disk)
if (uuid_len == (unsigned) array->uuid_len
&& grub_memcmp (uuidbin, array->uuid, uuid_len) == 0)
if (grub_is_array_readable (array))
break;
return array;
}
}
else
@ -163,7 +256,32 @@ grub_raid_open (const char *name, grub_disk_t disk)
{
if (!grub_strcmp (array->name, name))
if (grub_is_array_readable (array))
break;
return array;
}
return NULL;
}
static grub_err_t
grub_raid_open (const char *name, grub_disk_t disk)
{
struct grub_raid_array *array;
unsigned n;
if (grub_memcmp (name, "md", sizeof ("md") - 1) != 0)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s",
name);
array = find_array (name);
if (! array)
{
scan_devices (name);
if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
array = find_array (name);
}
if (!array)
@ -214,23 +332,6 @@ grub_raid_close (grub_disk_t disk __attribute ((unused)))
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
grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
@ -524,6 +625,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
grub_raid_t raid __attribute__ ((unused)))
{
struct grub_raid_array *array = 0, *p;
int was_readable = 0;
/* See whether the device is part of an array we have already seen a
device from. */
@ -534,6 +636,8 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
grub_free (new_array->uuid);
array = p;
was_readable = grub_is_array_readable (array);
/* Do some checks before adding the device to the array. */
if (new_array->index >= array->allocated_devs)
@ -679,6 +783,49 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
scanner_name);
#endif
{
int max_used_number = 0, len, need_new_name = 0;
int add_us = 0;
len = grub_strlen (array->name);
if (len && grub_isdigit (array->name[len-1]))
add_us = 1;
for (p = array_list; p != NULL; p = p->next)
{
int cur_num;
char *num, *end;
if (grub_strncmp (p->name, array->name, len) != 0)
continue;
if (p->name[len] == 0)
{
need_new_name = 1;
continue;
}
if (add_us && p->name[len] != '_')
continue;
if (add_us)
num = p->name + len + 1;
else
num = p->name + len;
if (!grub_isdigit (num[0]))
continue;
cur_num = grub_strtoull (num, &end, 10);
if (end[0])
continue;
if (cur_num > max_used_number)
max_used_number = cur_num;
}
if (need_new_name)
{
char *tmp;
tmp = grub_xasprintf ("%s%s%d", array->name, add_us ? "_" : "",
max_used_number + 1);
if (!tmp)
return grub_errno;
grub_free (array->name);
array->name = tmp;
}
}
/* Add our new array to the list. */
array->next = array_list;
array_list = array;
@ -693,12 +840,12 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
array->members[new_array->index].device = disk;
array->members[new_array->index].start_sector = start_sector;
array->nr_devs++;
if (!was_readable && grub_is_array_readable (array))
array->became_readable_at = inscnt++;
return 0;
}
static grub_raid_t grub_raid_list;
static void
free_array (void)
{
@ -729,45 +876,8 @@ free_array (void)
void
grub_raid_register (grub_raid_t raid)
{
auto int hook (const char *name);
int hook (const char *name)
{
grub_disk_t disk;
struct grub_raid_array array;
grub_disk_addr_t start_sector;
grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n",
grub_raid_list->name, name);
#ifdef GRUB_UTIL
grub_util_info ("Scanning for %s RAID devices on disk %s",
grub_raid_list->name, name);
#endif
disk = grub_disk_open (name);
if (!disk)
return 0;
if ((disk->total_sectors != GRUB_ULONG_MAX) &&
(! grub_raid_list->detect (disk, &array, &start_sector)) &&
(! insert_array (disk, &array, start_sector, grub_raid_list->name,
grub_raid_list)))
return 0;
/* This error usually means it's not raid, no need to display
it. */
if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
grub_disk_close (disk);
return 0;
}
raid->next = grub_raid_list;
grub_raid_list = raid;
grub_device_iterate (&hook);
}
void

View file

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

View file

@ -23,69 +23,43 @@
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/raid.h>
#include <grub/crypto.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_uint8_t raid6_table1[256][256];
static grub_uint8_t raid6_table2[256][256];
/* x**y. */
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
grub_raid_block_mul (grub_uint8_t mul, char *buf, int size)
grub_raid_block_mulx (int mul, char *buf, int size)
{
int i;
grub_uint8_t *p;
p = (grub_uint8_t *) buf;
for (i = 0; i < size; i++, p++)
*p = raid6_table1[mul][*p];
if (*p)
*p = powx[mul + powx_inv[*p]];
}
static void
grub_raid6_init_table (void)
{
int i, j;
int i;
for (i = 0; i < 256; i++)
raid6_table1[i][1] = raid6_table1[1][i] = i;
for (i = 2; i < 256; i++)
for (j = i; j < 256; j++)
grub_uint8_t cur = 1;
for (i = 0; i < 255; i++)
{
int n;
grub_uint8_t c;
n = i >> 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];
powx[i] = cur;
powx[i + 255] = cur;
powx_inv[cur] = i;
if (cur & 0x80)
cur = (cur << 1) ^ poly;
else
cur <<= 1;
}
}
@ -122,12 +96,12 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
{
if ((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)))
{
grub_raid_block_xor (pbuf, buf, size);
grub_raid_block_mul (raid6_table2[i][i], buf, size);
grub_raid_block_xor (qbuf, buf, size);
grub_crypto_xor (pbuf, pbuf, buf, size);
grub_raid_block_mulx (i, buf, size);
grub_crypto_xor (qbuf, qbuf, buf, size);
}
else
{
@ -154,10 +128,10 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
/* One bad device */
if ((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)))
{
grub_raid_block_xor (buf, pbuf, size);
grub_crypto_xor (buf, buf, pbuf, size);
goto quit;
}
@ -169,17 +143,17 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
grub_errno = GRUB_ERR_NONE;
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;
grub_raid_block_xor (buf, qbuf, size);
grub_raid_block_mul (raid6_table2[255 - bad1][255 - bad1], buf,
grub_crypto_xor (buf, buf, qbuf, size);
grub_raid_block_mulx (255 - bad1, buf,
size);
}
else
{
/* Two bad devices */
grub_uint8_t c;
int c;
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,
array->members[i].start_sector + sector,
array->members[p].start_sector + sector,
0, size, buf))
goto quit;
grub_raid_block_xor (pbuf, buf, size);
grub_crypto_xor (pbuf, pbuf, buf, size);
if (grub_disk_read (array->members[q].device,
array->members[i].start_sector + sector,
array->members[q].start_sector + sector,
0, size, buf))
goto quit;
grub_raid_block_xor (qbuf, buf, size);
grub_crypto_xor (qbuf, qbuf, buf, size);
c = raid6_table2[bad2][bad1];
grub_raid_block_mul (c, qbuf, size);
c = (255 - bad1 + (255 - powx_inv[(powx[bad2 - bad1 + 255] ^ 1)])) % 255;
grub_raid_block_mulx (c, qbuf, size);
c = raid6_table1[raid6_table2[bad2][bad2]][c];
grub_raid_block_mul (c, pbuf, size);
c = (bad2 + c) % 255;
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);
}

View file

@ -32,6 +32,12 @@ GRUB_MOD_LICENSE ("GPLv3+");
static grub_scsi_dev_t grub_scsi_dev_list;
const char grub_scsi_names[GRUB_SCSI_NUM_SUBSYSTEMS][5] = {
[GRUB_SCSI_SUBSYSTEM_USBMS] = "usb",
[GRUB_SCSI_SUBSYSTEM_PATA] = "ata",
[GRUB_SCSI_SUBSYSTEM_AHCI] = "ahci"
};
void
grub_scsi_dev_register (grub_scsi_dev_t dev)
{
@ -316,13 +322,14 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector,
static int
grub_scsi_iterate (int (*hook) (const char *name))
grub_scsi_iterate (int (*hook) (const char *name),
grub_disk_pull_t pull)
{
grub_scsi_dev_t p;
auto int scsi_iterate (int bus, int luns);
auto int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns);
int scsi_iterate (int bus, int luns)
int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns)
{
int i;
@ -331,7 +338,7 @@ grub_scsi_iterate (int (*hook) (const char *name))
{
char *sname;
int ret;
sname = grub_xasprintf ("%s%d", p->name, bus);
sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus);
if (!sname)
return 1;
ret = hook (sname);
@ -345,7 +352,7 @@ grub_scsi_iterate (int (*hook) (const char *name))
{
char *sname;
int ret;
sname = grub_xasprintf ("%s%d%c", p->name, bus, 'a' + i);
sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i);
if (!sname)
return 1;
ret = hook (sname);
@ -357,7 +364,7 @@ grub_scsi_iterate (int (*hook) (const char *name))
}
for (p = grub_scsi_dev_list; p; p = p->next)
if (p->iterate && (p->iterate) (scsi_iterate))
if (p->iterate && (p->iterate) (scsi_iterate, pull))
return 1;
return 0;
@ -372,6 +379,7 @@ grub_scsi_open (const char *name, grub_disk_t disk)
int lun, bus;
grub_uint64_t maxtime;
const char *nameend;
unsigned id;
nameend = name + grub_strlen (name) - 1;
/* Try to detect a LUN ('a'-'z'), otherwise just use the first
@ -396,15 +404,25 @@ grub_scsi_open (const char *name, grub_disk_t disk)
if (! scsi)
return grub_errno;
for (id = 0; id < ARRAY_SIZE (grub_scsi_names); id++)
if (grub_strncmp (grub_scsi_names[id], name, nameend - name) == 0)
break;
if (id == ARRAY_SIZE (grub_scsi_names))
{
grub_free (scsi);
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a SCSI disk");
}
for (p = grub_scsi_dev_list; p; p = p->next)
{
if (grub_strncmp (p->name, name, nameend - name) != 0)
if (p->open (id, bus, scsi))
{
grub_errno = GRUB_ERR_NONE;
continue;
}
if (p->open (bus, scsi))
continue;
disk->id = grub_make_scsi_id (p->id, bus, lun);
disk->id = grub_make_scsi_id (id, bus, lun);
disk->data = scsi;
scsi->dev = p;
scsi->lun = lun;
@ -465,22 +483,26 @@ grub_scsi_open (const char *name, grub_disk_t disk)
return err;
}
/* SCSI blocks can be something else than 512, although GRUB
wants 512 byte blocks. */
disk->total_sectors = ((grub_uint64_t)scsi->size
* (grub_uint64_t)scsi->blocksize)
>> GRUB_DISK_SECTOR_BITS;
disk->total_sectors = scsi->size;
if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
{
grub_free (scsi);
return grub_error (GRUB_ERR_IO, "invalid sector size %d",
scsi->blocksize);
}
for (disk->log_sector_size = 0;
(1 << disk->log_sector_size) < scsi->blocksize;
disk->log_sector_size++);
grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n",
scsi->size, scsi->blocksize);
grub_dprintf ("scsi", "Disk total 512 sectors = %llu\n",
grub_dprintf ("scsi", "Disk total sectors = %llu\n",
(unsigned long long) disk->total_sectors);
return GRUB_ERR_NONE;
}
grub_free (scsi);
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a SCSI disk");
}
@ -503,36 +525,36 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
scsi = disk->data;
/* SCSI sectors are variable in size. GRUB uses 512 byte
sectors. */
if (scsi->blocksize != GRUB_DISK_SECTOR_SIZE)
while (size)
{
unsigned spb = scsi->blocksize >> GRUB_DISK_SECTOR_BITS;
if (spb == 0 || (scsi->blocksize & (GRUB_DISK_SECTOR_SIZE - 1)) != 0)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported SCSI block size");
grub_uint64_t sector_mod = 0;
sector = grub_divmod64 (sector, spb, &sector_mod);
if (! (sector_mod == 0 && size % spb == 0))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unaligned SCSI read not supported");
size /= spb;
}
/* PATA doesn't support more than 32K reads.
Not sure about AHCI and USB. If it's confirmed that either of
them can do bigger reads reliably this value can be moved to 'scsi'
structure. */
grub_size_t len = 32768 >> disk->log_sector_size;
grub_err_t err;
if (len > size)
len = size;
/* Depending on the type, select a read function. */
switch (scsi->devtype)
{
case grub_scsi_devtype_direct:
return grub_scsi_read10 (disk, sector, size, buf);
err = grub_scsi_read10 (disk, sector, len, buf);
if (err)
return err;
break;
case grub_scsi_devtype_cdrom:
return grub_scsi_read12 (disk, sector, size, buf);
err = grub_scsi_read12 (disk, sector, len, buf);
if (err)
return err;
break;
}
size -= len;
sector += len;
buf += len << disk->log_sector_size;
}
/* XXX: Never reached. */
return GRUB_ERR_NONE;
#if 0 /* Workaround - it works - but very slowly, from some reason

View file

@ -211,16 +211,20 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
static int
grub_usbms_iterate (int (*hook) (int bus, int luns))
grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns),
grub_disk_pull_t pull)
{
unsigned i;
if (pull != GRUB_DISK_PULL_NONE)
return 0;
grub_usb_poll_devices ();
for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++)
if (grub_usbms_devices[i])
{
if (hook (i, grub_usbms_devices[i]->luns))
if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns))
return 1;
}
@ -390,8 +394,12 @@ grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
}
static grub_err_t
grub_usbms_open (int devnum, struct grub_scsi *scsi)
grub_usbms_open (int id, int devnum, struct grub_scsi *scsi)
{
if (id != GRUB_SCSI_SUBSYSTEM_USBMS)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"not USB Mass Storage device");
grub_usb_poll_devices ();
if (!grub_usbms_devices[devnum])
@ -406,8 +414,6 @@ grub_usbms_open (int devnum, struct grub_scsi *scsi)
static struct grub_scsi_dev grub_usbms_dev =
{
.name = "usb",
.id = GRUB_SCSI_SUBSYSTEM_USBMS,
.iterate = grub_usbms_iterate,
.open = grub_usbms_open,
.read = grub_usbms_read,

View file

@ -26,7 +26,7 @@
#define bit_LM (1 << 29)
char *
const char *
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)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"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;
tbl = (struct grub_efiemu_configuration_table *) grub_malloc (sizeof (*tbl));
@ -226,7 +227,7 @@ grub_efiemu_autocore (void)
{
const char *prefix;
char *filename;
char *suffix;
const char *suffix;
grub_err_t err;
if (grub_efiemu_sizeof_uintn_t () != 0)

View file

@ -201,10 +201,10 @@ efiemu_alloc_requests (void)
- (requested_memory[reqorder[i]] % GRUB_EFIEMU_PAGESIZE);
if (align_overhead == GRUB_EFIEMU_PAGESIZE)
align_overhead = 0;
curptr = ((grub_uint8_t *)curptr) + align_overhead;
curptr = ((grub_uint8_t *) curptr) + align_overhead;
/* 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]);
}
@ -404,7 +404,8 @@ grub_efiemu_mmap_fill (void)
GRUB_EFI_ACPI_MEMORY_NVS);
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:
return grub_efiemu_add_to_mmap (addr, size,
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),
sizeof (cur->guid));
if (cur->get_table)
conftables[i].vendor_table
= PTR_TO_UINT64 (cur->get_table (cur->data));
conftables[i].vendor_table = (grub_addr_t) cur->get_table (cur->data);
else
conftables[i].vendor_table = PTR_TO_UINT64 (cur->data);
conftables[i].vendor_table = (grub_addr_t) cur->data;
}
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
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_written++;
@ -179,10 +179,10 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle,
/* Compute the value */
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)
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 */
switch (size)
@ -248,16 +248,16 @@ grub_efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
switch (cur_relloc->size)
{
case 8:
*((grub_uint64_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
*((grub_uint64_t *) (grub_addr_t) cur_relloc->addr) += corr;
break;
case 4:
*((grub_uint32_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
*((grub_uint32_t *) (grub_addr_t) cur_relloc->addr) += corr;
break;
case 2:
*((grub_uint16_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
*((grub_uint16_t *) (grub_addr_t) cur_relloc->addr) += corr;
break;
case 1:
*((grub_uint8_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
*((grub_uint8_t *) (grub_addr_t) cur_relloc->addr) += corr;
break;
}
}

View file

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

View file

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

View file

@ -25,6 +25,7 @@
#include <grub/dl.h>
#include <grub/types.h>
#include <grub/fshelp.h>
#include <grub/charset.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -32,15 +33,11 @@ GRUB_MOD_LICENSE ("GPLv3+");
struct grub_affs_bblock
{
grub_uint8_t type[3];
grub_uint8_t flags;
grub_uint8_t version;
grub_uint32_t checksum;
grub_uint32_t rootblock;
} __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. */
struct grub_affs_rblock
{
@ -85,19 +82,19 @@ struct grub_affs_file
#define GRUB_AFFS_BLOCKPTR_OFFSET 24
#define GRUB_AFFS_SYMLINK_OFFSET 24
#define GRUB_AFFS_SYMLINK_SIZE(blocksize) ((blocksize) - 225)
#define GRUB_AFFS_FILETYPE_DIR -3
#define GRUB_AFFS_FILETYPE_REG 2
#define GRUB_AFFS_FILETYPE_REG 0xfffffffd
#define GRUB_AFFS_FILETYPE_DIR 2
#define GRUB_AFFS_FILETYPE_SYMLINK 3
struct grub_fshelp_node
{
struct grub_affs_data *data;
grub_disk_addr_t block;
grub_uint32_t block;
struct grub_fshelp_node *parent;
struct grub_affs_file di;
grub_uint32_t *block_cache;
grub_uint32_t last_block_cache;
};
/* Information about a "mounted" affs filesystem. */
@ -120,32 +117,46 @@ static grub_dl_t my_mod;
static grub_disk_addr_t
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;
int block = node->block;
struct grub_affs_file file;
struct grub_affs_data *data = node->data;
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
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
- GRUB_AFFS_FILE_LOCATION),
sizeof (file), &file);
if (grub_errno)
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. */
fileblock = mod;
grub_disk_read (data->disk, block,
grub_disk_read (data->disk, node->block_cache[target],
GRUB_AFFS_BLOCKPTR_OFFSET
+ (data->htsize - fileblock - 1) * sizeof (pos),
+ (data->htsize - mod - 1) * sizeof (pos),
sizeof (pos), &pos);
if (grub_errno)
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);
}
/* 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 *
grub_affs_mount (grub_disk_t disk)
{
@ -178,7 +174,7 @@ grub_affs_mount (grub_disk_t disk)
int checksum = 0;
int blocksize = 0;
data = grub_malloc (sizeof (struct grub_affs_data));
data = grub_zalloc (sizeof (struct grub_affs_data));
if (!data)
return 0;
@ -196,18 +192,12 @@ grub_affs_mount (grub_disk_t disk)
}
/* 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");
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
for that person because in that case this won't work. */
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;
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)
return 0;
grub_disk_read (data->disk, node->block, GRUB_AFFS_SYMLINK_OFFSET,
GRUB_AFFS_SYMLINK_SIZE (data->blocksize), symlink);
symlink_size, symlink);
if (grub_errno)
{
grub_free (symlink);
return 0;
}
symlink[symlink_size] = 1;
grub_dprintf ("affs", "Symlink: `%s'\n", symlink);
return symlink;
}
@ -300,25 +293,25 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
struct grub_affs_data *data = dir->data;
grub_uint32_t *hashtable;
auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name,
grub_disk_addr_t block,
auto int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block,
const struct grub_affs_file *fil);
int NESTED_FUNC_ATTR grub_affs_create_node (const char *name,
grub_disk_addr_t block,
int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block,
const struct grub_affs_file *fil)
{
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)
{
grub_free (hashtable);
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;
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;
else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_SYMLINK)
type = GRUB_FSHELP_SYMLINK;
@ -330,7 +323,10 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
node->di = *fil;
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);
return 1;
@ -339,7 +335,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
}
/* Create the directory entries for `.' and `..'. */
node = grub_malloc (sizeof (*node));
node = grub_zalloc (sizeof (*node));
if (!node)
return 1;
@ -348,7 +344,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
return 1;
if (dir->parent)
{
node = grub_malloc (sizeof (*node));
node = grub_zalloc (sizeof (*node));
if (!node)
return 1;
*node = *dir->parent;
@ -356,7 +352,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
return 1;
}
hashtable = grub_malloc (data->htsize * sizeof (*hashtable));
hashtable = grub_zalloc (data->htsize * sizeof (*hashtable));
if (!hashtable)
return 1;
@ -367,7 +363,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
for (i = 0; i < data->htsize; i++)
{
grub_uint64_t next;
grub_uint32_t next;
if (!hashtable[i])
continue;
@ -385,9 +381,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
if (grub_errno)
goto fail;
file.name[file.namelen] = '\0';
if (grub_affs_create_node ((char *) (file.name), next, &file))
if (grub_affs_create_node (next, &file))
return 1;
next = grub_be_to_cpu32 (file.next);
@ -441,10 +435,13 @@ grub_affs_open (struct grub_file *file, const char *name)
return grub_errno;
}
static grub_err_t
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_dl_unref (my_mod);
@ -452,7 +449,6 @@ grub_affs_close (grub_file_t file)
return GRUB_ERR_NONE;
}
/* Read LEN bytes data from FILE into BUF. */
static grub_ssize_t
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 *) file->data;
int size = grub_affs_read_file (&data->diropen, file->read_hook,
file->offset, len, buf);
return size;
return grub_fshelp_read_file (data->diropen.data->disk, &data->diropen,
file->read_hook,
file->offset, len, buf, grub_affs_read_block,
grub_be_to_cpu32 (data->diropen.di.size), 0);
}
static grub_err_t
grub_affs_dir (grub_device_t device, const char *path,
int (*hook) (const char *filename,

View file

@ -1,720 +1,3 @@
/* afs.c - The native AtheOS file-system. */
/*
* 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/>.
*/
#define MODE_AFS 1
#include "bfs.c"
#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,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

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