merge mainline into hints
This commit is contained in:
commit
17785932df
448 changed files with 43023 additions and 10176 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)';
|
||||
|
|
16
acinclude.m4
16
acinclude.m4
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)))
|
||||
|
|
91
configure.ac
91
configure.ac
|
@ -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], [
|
||||
SAVE_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -march=loongson2f"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
|
||||
[grub_cv_cc_march_loongson2f=yes],
|
||||
[grub_cv_cc_march_loongson2f=no])
|
||||
CFLAGS="$SAVE_CFLAGS"
|
||||
])
|
||||
# By default, GCC 4.6 generates .eh_frame sections containing unwind
|
||||
# information in some cases where it previously did not. GRUB doesn't need
|
||||
# these and they just use up vital space. Restore the old compiler
|
||||
# behaviour.
|
||||
AC_CACHE_CHECK([whether -fno-asynchronous-unwind-tables works], [grub_cv_cc_fno_asynchronous_unwind_tables], [
|
||||
SAVE_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -fno-dwarf2-cfi-asm"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
|
||||
[grub_cv_cc_fno_asynchronous_unwind_tables=yes],
|
||||
[grub_cv_cc_fno_asynchronous_unwind_tables=no])
|
||||
CFLAGS="$SAVE_CFLAGS"
|
||||
])
|
||||
|
||||
if test "x$grub_cv_cc_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 "*******************************************************"
|
||||
]
|
||||
|
|
179
docs/grub.texi
179
docs/grub.texi
|
@ -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:
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
4
docs/man/grub-mkstandalone.h2m
Normal file
4
docs/man/grub-mkstandalone.h2m
Normal 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
2
docs/man/grub-mount.h2m
Normal file
|
@ -0,0 +1,2 @@
|
|||
[NAME]
|
||||
grub-mount \- export GRUB filesystem with FUSE
|
134
gentpl.py
134
gentpl.py
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/boot.h>
|
||||
#include <grub/machine/boot.h>
|
||||
|
||||
/*
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
351
grub-core/boot/i386/pc/startup_raw.S
Normal file
351
grub-core/boot/i386/pc/startup_raw.S
Normal 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):
|
|
@ -1,2 +1,2 @@
|
|||
#define FULOONG 1
|
||||
#define FULOONG2F 1
|
||||
#include "fwstart.S"
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
lw $s4, %lo (((16 << 20) - 264) | 0x80000000) ($t0)
|
||||
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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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_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,
|
||||
GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
td_prev->linkptr2 = 0;
|
||||
td_prev->linkptr = 1;
|
||||
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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
rsdpv1_new = 0;
|
||||
rsdpv2_new = 0;
|
||||
grub_mmap_free_and_unregister (mmapregion);
|
||||
return err;
|
||||
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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
58
grub-core/commands/cacheinfo.c
Normal file
58
grub-core/commands/cacheinfo.c
Normal 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);
|
||||
}
|
|
@ -42,8 +42,8 @@ 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],
|
||||
args[1]);
|
||||
grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0],
|
||||
args[1]);
|
||||
|
||||
file1 = grub_file_open (args[0]);
|
||||
file2 = grub_file_open (args[1]);
|
||||
|
@ -51,9 +51,9 @@ 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",
|
||||
(unsigned long long) grub_file_size (file1), args[0],
|
||||
(unsigned long long) grub_file_size (file2), args[1]);
|
||||
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
|
||||
{
|
||||
pos = 0;
|
||||
|
@ -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,15 +89,14 @@ 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);
|
||||
grub_free (buf1);
|
||||
grub_free (buf2);
|
||||
if (file1)
|
||||
grub_file_close (file1);
|
||||
if (file2)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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."));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
||||
"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",
|
||||
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_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"),
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,11 +46,11 @@ 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",
|
||||
(long long) addr, (long long) size, type);
|
||||
grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n"),
|
||||
(long long) addr, (long long) size, type);
|
||||
return 0;
|
||||
}
|
||||
#ifndef GRUB_MACHINE_EMU
|
||||
|
|
|
@ -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[] =
|
||||
|
|
|
@ -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}
|
||||
};
|
||||
|
||||
|
|
|
@ -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[] =
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_pci_get_device (dev), grub_pci_get_function (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)
|
||||
|
|
|
@ -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"
|
||||
"Use \"parttool PARTITION help\" for the list "
|
||||
"of available commands.";
|
||||
N_("Perform COMMANDS on partition.\n"
|
||||
"Use \"parttool PARTITION help\" for the list "
|
||||
"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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
68
grub-core/commands/time.c
Normal 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);
|
||||
}
|
|
@ -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,44 +42,74 @@ hook (const struct grub_video_mode_info *info)
|
|||
if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID)
|
||||
grub_printf (" ");
|
||||
else
|
||||
grub_printf (" 0x%03x ", info->mode_number);
|
||||
{
|
||||
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",
|
||||
info->red_mask_size,
|
||||
info->green_mask_size,
|
||||
info->blue_mask_size,
|
||||
info->reserved_mask_size,
|
||||
info->red_field_pos,
|
||||
info->green_field_pos,
|
||||
info->blue_field_pos,
|
||||
info->reserved_field_pos);
|
||||
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,
|
||||
info->reserved_mask_size,
|
||||
info->red_field_pos,
|
||||
info->green_field_pos,
|
||||
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."));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,8 +256,7 @@ match_devices (const regex_t *regexp, int noparts)
|
|||
for (i = 0; devs && devs[i]; i++)
|
||||
grub_free (devs[i]);
|
||||
|
||||
if (devs)
|
||||
grub_free (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,20 +342,17 @@ match_files (const char *prefix, const char *suffix, const char *end,
|
|||
|
||||
fail:
|
||||
|
||||
if (dir)
|
||||
grub_free (dir);
|
||||
grub_free (dir);
|
||||
|
||||
for (i = 0; files && files[i]; i++)
|
||||
grub_free (files[i]);
|
||||
|
||||
if (files)
|
||||
grub_free (files);
|
||||
grub_free (files);
|
||||
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
|
||||
if (device_name)
|
||||
grub_free (device_name);
|
||||
grub_free (device_name);
|
||||
|
||||
grub_error_pop ();
|
||||
return 0;
|
||||
|
@ -423,8 +422,6 @@ wildcard_expand (const char *s, char ***strs)
|
|||
while (*start)
|
||||
{
|
||||
split_path (start, &noregexop, ®exop);
|
||||
if (noregexop >= regexop) /* no more wildcards */
|
||||
break;
|
||||
|
||||
if (make_regex (noregexop, regexop, ®exp))
|
||||
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");
|
||||
|
|
|
@ -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]);
|
||||
for (ptr = uuid_string; *ptr; ptr++)
|
||||
*ptr = grub_toupper (*ptr);
|
||||
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)
|
||||
|
|
89
grub-core/disk/AFSplitter.c
Normal file
89
grub-core/disk/AFSplitter.c
Normal 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
738
grub-core/disk/ahci.c
Normal 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);
|
||||
}
|
|
@ -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
|
@ -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
883
grub-core/disk/cryptodisk.c
Normal 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 ();
|
||||
}
|
|
@ -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,11 +225,11 @@ 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),
|
||||
find_last_device_path (d->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,
|
||||
d->device_path);
|
||||
ret = grub_efi_compare_device_paths ((*p)->device_path,
|
||||
d->device_path);
|
||||
if (ret == 0)
|
||||
return;
|
||||
else if (ret > 0)
|
||||
|
@ -432,34 +378,43 @@ 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);
|
||||
grub_dprintf ("efidisk", "iterating %s\n", buf);
|
||||
if (hook (buf))
|
||||
return 1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case GRUB_DISK_PULL_REMOVABLE:
|
||||
for (d = fd_devices, count = 0; d; d = d->next, count++)
|
||||
{
|
||||
grub_snprintf (buf, sizeof (buf), "fd%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++)
|
||||
{
|
||||
grub_snprintf (buf, sizeof (buf), "hd%d", count);
|
||||
grub_dprintf ("efidisk", "iterating %s\n", buf);
|
||||
if (hook (buf))
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (d = cd_devices, count = 0; d; d = d->next, count++)
|
||||
{
|
||||
grub_snprintf (buf, sizeof (buf), "cd%d", count);
|
||||
grub_dprintf ("efidisk", "iterating %s\n", buf);
|
||||
if (hook (buf))
|
||||
return 1;
|
||||
for (d = cd_devices, count = 0; d; d = d->next, count++)
|
||||
{
|
||||
grub_snprintf (buf, sizeof (buf), "cd%d", count);
|
||||
grub_dprintf ("efidisk", "iterating %s\n", buf);
|
||||
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,22 +518,20 @@ 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,
|
||||
buf);
|
||||
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,7 +667,35 @@ 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;
|
||||
grub_efi_device_path_t *dp, *ldp, *sdp;
|
||||
/* This is a hard disk partition. */
|
||||
grub_disk_t parent = 0;
|
||||
auto int find_parent_disk (const char *name);
|
||||
|
||||
/* Find the disk which is the parent of a given hard disk partition. */
|
||||
int find_parent_disk (const char *name)
|
||||
{
|
||||
grub_disk_t disk;
|
||||
|
||||
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 (grub_efi_compare_device_paths (d->device_path, sdp) == 0)
|
||||
{
|
||||
parent = disk;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
grub_disk_close (disk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dp = grub_efi_get_device_path (handle);
|
||||
if (! dp)
|
||||
|
@ -725,40 +709,12 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
|||
&& (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp)
|
||||
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
|
||||
{
|
||||
/* This is a hard disk partition. */
|
||||
grub_disk_t parent = 0;
|
||||
grub_partition_t tpart = NULL;
|
||||
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_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)
|
||||
{
|
||||
grub_disk_t disk;
|
||||
|
||||
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, dup_dp) == 0)
|
||||
{
|
||||
parent = disk;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
grub_disk_close (disk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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,19 +753,24 @@ 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));
|
||||
grub_partition_iterate (parent, find_partition);
|
||||
|
||||
if (! tpart)
|
||||
if (hd.partition_start == 0
|
||||
&& hd.partition_size == grub_disk_get_size (parent))
|
||||
{
|
||||
grub_disk_close (parent);
|
||||
return 0;
|
||||
device_name = grub_strdup (parent->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_partition_iterate (parent, find_partition);
|
||||
|
||||
{
|
||||
char *partition_name = grub_partition_get_name (tpart);
|
||||
device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
|
||||
grub_free (partition_name);
|
||||
}
|
||||
if (! partition_name)
|
||||
{
|
||||
grub_disk_close (parent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
|
||||
grub_free (partition_name);
|
||||
}
|
||||
grub_disk_close (parent);
|
||||
|
||||
return device_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
568
grub-core/disk/geli.c
Normal 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);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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,37 +285,46 @@ 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. */
|
||||
for (drive = 0x80; drive < 0x90; drive++)
|
||||
switch (pull)
|
||||
{
|
||||
if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
|
||||
GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
|
||||
case GRUB_DISK_PULL_NONE:
|
||||
for (drive = 0x80; drive < 0x90; drive++)
|
||||
{
|
||||
grub_dprintf ("disk", "Read error when probing drive 0x%2x\n", drive);
|
||||
break;
|
||||
if (grub_biosdisk_rw_standard (0x02, drive, 0, 0, 1, 1,
|
||||
GRUB_MEMORY_MACHINE_SCRATCH_SEG) != 0)
|
||||
{
|
||||
grub_dprintf ("disk", "Read error when probing drive 0x%2x\n", drive);
|
||||
break;
|
||||
}
|
||||
|
||||
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))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (grub_biosdisk_call_hook (hook, drive))
|
||||
return 1;
|
||||
/* For floppy disks, we can get the number safely. */
|
||||
num_floppies = grub_biosdisk_get_num_floppies ();
|
||||
for (drive = 0; drive < num_floppies; drive++)
|
||||
if (grub_biosdisk_call_hook (hook, drive))
|
||||
return 1;
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cd_drive)
|
||||
{
|
||||
if (grub_biosdisk_call_hook (hook, cd_drive))
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For floppy disks, we can get the number safely. */
|
||||
num_floppies = grub_biosdisk_get_num_floppies ();
|
||||
for (drive = 0; drive < num_floppies; drive++)
|
||||
if (grub_biosdisk_call_hook (hook, drive))
|
||||
return 1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -610,11 +622,12 @@ grub_disk_biosdisk_fini (void)
|
|||
GRUB_MOD_INIT(biosdisk)
|
||||
{
|
||||
struct grub_biosdisk_cdrp *cdrp
|
||||
= (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||
= (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||
grub_uint8_t boot_drive;
|
||||
|
||||
if (grub_disk_firmware_is_tainted)
|
||||
{
|
||||
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)
|
||||
== GRUB_BIOSDISK_CDTYPE_NO_EMUL))
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
|
||||
{
|
||||
grub_free (devpath);
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
|
||||
}
|
||||
|
||||
if (grub_strcmp (prop, "block"))
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device");
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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
470
grub-core/disk/luks.c
Normal 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);
|
||||
}
|
1302
grub-core/disk/lvm.c
1302
grub-core/disk/lvm.c
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
|
|
|
@ -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,30 +86,24 @@ 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)
|
||||
{
|
||||
if (header->type == OBJ_TYPE_MEMDISK)
|
||||
{
|
||||
char *memdisk_orig_addr;
|
||||
memdisk_orig_addr = (char *) header + sizeof (struct grub_module_header);
|
||||
struct grub_module_header *header;
|
||||
FOR_MODULES (header)
|
||||
if (header->type == OBJ_TYPE_MEMDISK)
|
||||
{
|
||||
char *memdisk_orig_addr;
|
||||
memdisk_orig_addr = (char *) header + sizeof (struct grub_module_header);
|
||||
|
||||
grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
|
||||
grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr);
|
||||
|
||||
memdisk_size = header->size - sizeof (struct grub_module_header);
|
||||
memdisk_addr = grub_malloc (memdisk_size);
|
||||
memdisk_size = header->size - sizeof (struct grub_module_header);
|
||||
memdisk_addr = grub_malloc (memdisk_size);
|
||||
|
||||
grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
|
||||
grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
|
||||
grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n");
|
||||
grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
|
||||
|
||||
grub_disk_dev_register (&grub_memdisk_dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
grub_module_iterate (hook);
|
||||
grub_disk_dev_register (&grub_memdisk_dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(memdisk)
|
||||
|
|
538
grub-core/disk/pata.c
Normal file
538
grub-core/disk/pata.c
Normal 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);
|
||||
}
|
|
@ -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,8 +256,33 @@ 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)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s",
|
||||
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -23,70 +23,44 @@
|
|||
#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++)
|
||||
{
|
||||
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];
|
||||
}
|
||||
grub_uint8_t cur = 1;
|
||||
for (i = 0; i < 255; i++)
|
||||
{
|
||||
powx[i] = cur;
|
||||
powx[i + 255] = cur;
|
||||
powx_inv[cur] = i;
|
||||
if (cur & 0x80)
|
||||
cur = (cur << 1) ^ poly;
|
||||
else
|
||||
cur <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
@ -122,12 +96,12 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
|
|||
{
|
||||
if ((array->members[pos].device) &&
|
||||
(! 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
continue;
|
||||
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");
|
||||
/* 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:
|
||||
err = grub_scsi_read10 (disk, sector, len, buf);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
||||
grub_uint64_t sector_mod = 0;
|
||||
sector = grub_divmod64 (sector, spb, §or_mod);
|
||||
|
||||
if (! (sector_mod == 0 && size % spb == 0))
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unaligned SCSI read not supported");
|
||||
|
||||
size /= spb;
|
||||
case grub_scsi_devtype_cdrom:
|
||||
err = grub_scsi_read12 (disk, sector, len, buf);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
}
|
||||
size -= len;
|
||||
sector += len;
|
||||
buf += len << disk->log_sector_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);
|
||||
|
||||
case grub_scsi_devtype_cdrom:
|
||||
return grub_scsi_read12 (disk, sector, size, buf);
|
||||
}
|
||||
|
||||
/* XXX: Never reached. */
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
#if 0 /* Workaround - it works - but very slowly, from some reason
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#define bit_LM (1 << 29)
|
||||
|
||||
char *
|
||||
const char *
|
||||
grub_efiemu_get_default_core_name (void)
|
||||
{
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) ();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
/* befs.c - The native BeOS/Haiku file-system. */
|
||||
#define MODE_BFS 1
|
||||
#include "afs.c"
|
|
@ -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
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
Loading…
Reference in a new issue