merge mainline into ehci
This commit is contained in:
commit
cefa01261b
443 changed files with 38931 additions and 11122 deletions
|
@ -48,6 +48,7 @@ grub-kbdcomp
|
||||||
grub-macho2img
|
grub-macho2img
|
||||||
grub-menulst2cfg
|
grub-menulst2cfg
|
||||||
grub-mk*
|
grub-mk*
|
||||||
|
grub-mount
|
||||||
grub-pe2elf
|
grub-pe2elf
|
||||||
grub-probe
|
grub-probe
|
||||||
grub_probe_init.c
|
grub_probe_init.c
|
||||||
|
|
|
@ -101,8 +101,7 @@ CLEANFILES += widthspec.h
|
||||||
# Install config.h into platformdir
|
# Install config.h into platformdir
|
||||||
platform_HEADERS = config.h
|
platform_HEADERS = config.h
|
||||||
|
|
||||||
pkglib_DATA += grub-mkconfig_lib
|
pkgdata_DATA += grub-mkconfig_lib
|
||||||
pkglib_DATA += update-grub_lib
|
|
||||||
|
|
||||||
|
|
||||||
if COND_i386_coreboot
|
if COND_i386_coreboot
|
||||||
|
|
|
@ -29,10 +29,15 @@ library = {
|
||||||
common = grub-core/lib/pbkdf2.c;
|
common = grub-core/lib/pbkdf2.c;
|
||||||
common = grub-core/commands/extcmd.c;
|
common = grub-core/commands/extcmd.c;
|
||||||
common = grub-core/lib/arg.c;
|
common = grub-core/lib/arg.c;
|
||||||
|
common = grub-core/disk/ldm.c;
|
||||||
|
common = grub-core/disk/diskfilter.c;
|
||||||
|
common = grub-core/partmap/gpt.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
library = {
|
library = {
|
||||||
name = libgrubmods.a;
|
name = libgrubmods.a;
|
||||||
|
cflags = '$(CFLAGS_POSIX) -Wno-undef';
|
||||||
|
cppflags = '-I$(top_srcdir)/grub-core/lib/minilzo -I$(srcdir)/grub-core/lib/xzembed -DMINILZO_HAVE_CONFIG_H';
|
||||||
|
|
||||||
common_nodist = grub_script.tab.c;
|
common_nodist = grub_script.tab.c;
|
||||||
common_nodist = grub_script.yy.c;
|
common_nodist = grub_script.yy.c;
|
||||||
|
@ -41,6 +46,7 @@ library = {
|
||||||
common_nodist = grub_script.tab.h;
|
common_nodist = grub_script.tab.h;
|
||||||
|
|
||||||
common = grub-core/commands/blocklist.c;
|
common = grub-core/commands/blocklist.c;
|
||||||
|
common = grub-core/commands/xnu_uuid.c;
|
||||||
common = grub-core/commands/testload.c;
|
common = grub-core/commands/testload.c;
|
||||||
common = grub-core/commands/ls.c;
|
common = grub-core/commands/ls.c;
|
||||||
common = grub-core/disk/dmraid_nvidia.c;
|
common = grub-core/disk/dmraid_nvidia.c;
|
||||||
|
@ -50,16 +56,17 @@ library = {
|
||||||
common = grub-core/disk/mdraid1x_linux.c;
|
common = grub-core/disk/mdraid1x_linux.c;
|
||||||
common = grub-core/disk/raid5_recover.c;
|
common = grub-core/disk/raid5_recover.c;
|
||||||
common = grub-core/disk/raid6_recover.c;
|
common = grub-core/disk/raid6_recover.c;
|
||||||
common = grub-core/disk/raid.c;
|
|
||||||
common = grub-core/fs/affs.c;
|
common = grub-core/fs/affs.c;
|
||||||
common = grub-core/fs/afs_be.c;
|
|
||||||
common = grub-core/fs/afs.c;
|
common = grub-core/fs/afs.c;
|
||||||
common = grub-core/fs/befs_be.c;
|
common = grub-core/fs/bfs.c;
|
||||||
common = grub-core/fs/befs.c;
|
|
||||||
common = grub-core/fs/btrfs.c;
|
common = grub-core/fs/btrfs.c;
|
||||||
common = grub-core/fs/cpio.c;
|
common = grub-core/fs/cpio.c;
|
||||||
|
common = grub-core/fs/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/ext2.c;
|
||||||
common = grub-core/fs/fat.c;
|
common = grub-core/fs/fat.c;
|
||||||
|
common = grub-core/fs/exfat.c;
|
||||||
common = grub-core/fs/fshelp.c;
|
common = grub-core/fs/fshelp.c;
|
||||||
common = grub-core/fs/hfs.c;
|
common = grub-core/fs/hfs.c;
|
||||||
common = grub-core/fs/hfsplus.c;
|
common = grub-core/fs/hfsplus.c;
|
||||||
|
@ -80,7 +87,9 @@ library = {
|
||||||
common = grub-core/fs/ufs2.c;
|
common = grub-core/fs/ufs2.c;
|
||||||
common = grub-core/fs/ufs.c;
|
common = grub-core/fs/ufs.c;
|
||||||
common = grub-core/fs/xfs.c;
|
common = grub-core/fs/xfs.c;
|
||||||
|
common = grub-core/fs/zfs/zfscrypt.c;
|
||||||
common = grub-core/fs/zfs/zfs.c;
|
common = grub-core/fs/zfs/zfs.c;
|
||||||
|
common = grub-core/fs/zfs/zfsinfo.c;
|
||||||
common = grub-core/fs/zfs/zfs_lzjb.c;
|
common = grub-core/fs/zfs/zfs_lzjb.c;
|
||||||
common = grub-core/fs/zfs/zfs_sha256.c;
|
common = grub-core/fs/zfs/zfs_sha256.c;
|
||||||
common = grub-core/fs/zfs/zfs_fletcher.c;
|
common = grub-core/fs/zfs/zfs_fletcher.c;
|
||||||
|
@ -89,14 +98,16 @@ library = {
|
||||||
common = grub-core/lib/LzFind.c;
|
common = grub-core/lib/LzFind.c;
|
||||||
common = grub-core/lib/LzmaEnc.c;
|
common = grub-core/lib/LzmaEnc.c;
|
||||||
common = grub-core/lib/crc.c;
|
common = grub-core/lib/crc.c;
|
||||||
|
common = grub-core/lib/adler32.c;
|
||||||
|
common = grub-core/lib/crc64.c;
|
||||||
common = grub-core/normal/datetime.c;
|
common = grub-core/normal/datetime.c;
|
||||||
common = grub-core/normal/misc.c;
|
common = grub-core/normal/misc.c;
|
||||||
common = grub-core/partmap/acorn.c;
|
common = grub-core/partmap/acorn.c;
|
||||||
common = grub-core/partmap/amiga.c;
|
common = grub-core/partmap/amiga.c;
|
||||||
common = grub-core/partmap/apple.c;
|
common = grub-core/partmap/apple.c;
|
||||||
common = grub-core/partmap/gpt.c;
|
|
||||||
common = grub-core/partmap/msdos.c;
|
common = grub-core/partmap/msdos.c;
|
||||||
common = grub-core/partmap/sun.c;
|
common = grub-core/partmap/sun.c;
|
||||||
|
common = grub-core/partmap/plan.c;
|
||||||
common = grub-core/partmap/dvh.c;
|
common = grub-core/partmap/dvh.c;
|
||||||
common = grub-core/partmap/sunpc.c;
|
common = grub-core/partmap/sunpc.c;
|
||||||
common = grub-core/partmap/bsdlabel.c;
|
common = grub-core/partmap/bsdlabel.c;
|
||||||
|
@ -106,7 +117,12 @@ library = {
|
||||||
common = grub-core/script/script.c;
|
common = grub-core/script/script.c;
|
||||||
common = grub-core/script/argv.c;
|
common = grub-core/script/argv.c;
|
||||||
common = grub-core/io/gzio.c;
|
common = grub-core/io/gzio.c;
|
||||||
|
common = grub-core/io/lzopio.c;
|
||||||
common = grub-core/kern/ia64/dl_helper.c;
|
common = grub-core/kern/ia64/dl_helper.c;
|
||||||
|
common = grub-core/lib/minilzo/minilzo.c;
|
||||||
|
common = grub-core/lib/xzembed/xz_dec_bcj.c;
|
||||||
|
common = grub-core/lib/xzembed/xz_dec_lzma2.c;
|
||||||
|
common = grub-core/lib/xzembed/xz_dec_stream.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
program = {
|
program = {
|
||||||
|
@ -229,6 +245,22 @@ program = {
|
||||||
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
|
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
program = {
|
||||||
|
name = grub-mount;
|
||||||
|
mansection = 1;
|
||||||
|
common_nodist = grub_fstest_init.c;
|
||||||
|
common = util/grub-mount.c;
|
||||||
|
common = grub-core/kern/emu/hostfs.c;
|
||||||
|
common = grub-core/disk/host.c;
|
||||||
|
|
||||||
|
ldadd = libgrubmods.a;
|
||||||
|
ldadd = libgrubgcry.a;
|
||||||
|
ldadd = libgrubkern.a;
|
||||||
|
ldadd = grub-core/gnulib/libgnu.a;
|
||||||
|
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) -lfuse';
|
||||||
|
condition = COND_GRUB_MOUNT;
|
||||||
|
};
|
||||||
|
|
||||||
program = {
|
program = {
|
||||||
name = grub-mkfont;
|
name = grub-mkfont;
|
||||||
mansection = 1;
|
mansection = 1;
|
||||||
|
@ -253,10 +285,7 @@ program = {
|
||||||
|
|
||||||
common = util/grub-mkdevicemap.c;
|
common = util/grub-mkdevicemap.c;
|
||||||
common = util/deviceiter.c;
|
common = util/deviceiter.c;
|
||||||
nosparc64 = util/devicemap.c;
|
common = util/devicemap.c;
|
||||||
|
|
||||||
sparc64_ieee1275 = util/ieee1275/ofpath.c;
|
|
||||||
sparc64_ieee1275 = util/ieee1275/devicemap.c;
|
|
||||||
|
|
||||||
ldadd = libgrubmods.a;
|
ldadd = libgrubmods.a;
|
||||||
ldadd = libgrubgcry.a;
|
ldadd = libgrubgcry.a;
|
||||||
|
@ -270,6 +299,7 @@ program = {
|
||||||
installdir = sbin;
|
installdir = sbin;
|
||||||
mansection = 8;
|
mansection = 8;
|
||||||
common = util/grub-probe.c;
|
common = util/grub-probe.c;
|
||||||
|
common = util/ieee1275/ofpath.c;
|
||||||
|
|
||||||
ldadd = libgrubmods.a;
|
ldadd = libgrubmods.a;
|
||||||
ldadd = libgrubgcry.a;
|
ldadd = libgrubgcry.a;
|
||||||
|
@ -359,6 +389,13 @@ script = {
|
||||||
condition = COND_HOST_KFREEBSD;
|
condition = COND_HOST_KFREEBSD;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
script = {
|
||||||
|
name = '10_illumos';
|
||||||
|
common = util/grub.d/10_illumos.in;
|
||||||
|
installdir = grubconf;
|
||||||
|
condition = COND_HOST_ILLUMOS;
|
||||||
|
};
|
||||||
|
|
||||||
script = {
|
script = {
|
||||||
name = '10_netbsd';
|
name = '10_netbsd';
|
||||||
common = util/grub.d/10_netbsd.in;
|
common = util/grub.d/10_netbsd.in;
|
||||||
|
@ -462,12 +499,6 @@ script = {
|
||||||
installdir = noinst;
|
installdir = noinst;
|
||||||
};
|
};
|
||||||
|
|
||||||
script = {
|
|
||||||
name = update-grub_lib;
|
|
||||||
common = util/update-grub_lib.in;
|
|
||||||
installdir = noinst;
|
|
||||||
};
|
|
||||||
|
|
||||||
script = {
|
script = {
|
||||||
name = grub-kbdcomp;
|
name = grub-kbdcomp;
|
||||||
common = util/grub-kbdcomp.in;
|
common = util/grub-kbdcomp.in;
|
||||||
|
@ -645,6 +676,21 @@ program = {
|
||||||
ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
|
ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
program = {
|
||||||
|
testcase;
|
||||||
|
name = printf_test;
|
||||||
|
common = tests/printf_unit_test.c;
|
||||||
|
common = tests/lib/unit_test.c;
|
||||||
|
common = grub-core/kern/list.c;
|
||||||
|
common = grub-core/kern/misc.c;
|
||||||
|
common = grub-core/tests/lib/test.c;
|
||||||
|
ldadd = libgrubmods.a;
|
||||||
|
ldadd = libgrubgcry.a;
|
||||||
|
ldadd = libgrubkern.a;
|
||||||
|
ldadd = grub-core/gnulib/libgnu.a;
|
||||||
|
ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
|
||||||
|
};
|
||||||
|
|
||||||
program = {
|
program = {
|
||||||
name = grub-menulst2cfg;
|
name = grub-menulst2cfg;
|
||||||
mansection = 1;
|
mansection = 1;
|
||||||
|
|
|
@ -137,7 +137,7 @@ KERNEL_HEADER_FILES =
|
||||||
|
|
||||||
man_MANS =
|
man_MANS =
|
||||||
noinst_DATA =
|
noinst_DATA =
|
||||||
pkglib_DATA =
|
pkgdata_DATA =
|
||||||
bin_SCRIPTS =
|
bin_SCRIPTS =
|
||||||
sbin_SCRIPTS =
|
sbin_SCRIPTS =
|
||||||
bin_PROGRAMS =
|
bin_PROGRAMS =
|
||||||
|
@ -147,7 +147,6 @@ check_SCRIPTS =
|
||||||
grubconf_DATA =
|
grubconf_DATA =
|
||||||
check_PROGRAMS =
|
check_PROGRAMS =
|
||||||
noinst_SCRIPTS =
|
noinst_SCRIPTS =
|
||||||
pkglib_SCRIPTS =
|
|
||||||
noinst_PROGRAMS =
|
noinst_PROGRAMS =
|
||||||
grubconf_SCRIPTS =
|
grubconf_SCRIPTS =
|
||||||
noinst_LIBRARIES =
|
noinst_LIBRARIES =
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
#undef _FILE_OFFSET_BITS
|
#undef _FILE_OFFSET_BITS
|
||||||
#define _LARGEFILE_SOURCE
|
#define _LARGEFILE_SOURCE
|
||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
#if defined(__PPC__) && !defined(__powerpc__)
|
||||||
|
#define __powerpc__ 1
|
||||||
|
#endif
|
||||||
#if defined (GRUB_UTIL) || !defined (GRUB_MACHINE)
|
#if defined (GRUB_UTIL) || !defined (GRUB_MACHINE)
|
||||||
#include <config-util.h>
|
#include <config-util.h>
|
||||||
#define NESTED_FUNC_ATTR
|
#define NESTED_FUNC_ATTR
|
||||||
|
@ -39,6 +42,8 @@
|
||||||
/* Define to 1 to enable disk cache statistics. */
|
/* Define to 1 to enable disk cache statistics. */
|
||||||
#define DISK_CACHE_STATS @DISK_CACHE_STATS@
|
#define DISK_CACHE_STATS @DISK_CACHE_STATS@
|
||||||
|
|
||||||
|
#define RE_ENABLE_I18N 1
|
||||||
|
|
||||||
#if defined(__i386__)
|
#if defined(__i386__)
|
||||||
#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1)))
|
#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1)))
|
||||||
#else
|
#else
|
||||||
|
|
133
configure.ac
133
configure.ac
|
@ -154,6 +154,7 @@ case "$host_os" in
|
||||||
linux*) host_kernel=linux ;;
|
linux*) host_kernel=linux ;;
|
||||||
freebsd* | kfreebsd*-gnu) host_kernel=kfreebsd ;;
|
freebsd* | kfreebsd*-gnu) host_kernel=kfreebsd ;;
|
||||||
netbsd*) host_kernel=netbsd ;;
|
netbsd*) host_kernel=netbsd ;;
|
||||||
|
solaris*) host_kernel=illumos ;;
|
||||||
cygwin) host_kernel=windows ;;
|
cygwin) host_kernel=windows ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -176,7 +177,7 @@ esac
|
||||||
if test x${target_cpu} = xmipsel ; then
|
if test x${target_cpu} = xmipsel ; then
|
||||||
machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo mips_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`"
|
machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo mips_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`"
|
||||||
else
|
else
|
||||||
machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`"
|
machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,` -DGRUB_TARGET_CPU_`echo ${target_cpu} | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`=1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
HOST_CPPFLAGS="$HOST_CPPFLAGS $machine_CPPFLAGS"
|
HOST_CPPFLAGS="$HOST_CPPFLAGS $machine_CPPFLAGS"
|
||||||
|
@ -233,7 +234,7 @@ for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson ); then
|
if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips); then
|
||||||
AC_MSG_ERROR([qemu and loongson ports need unifont])
|
AC_MSG_ERROR([qemu and loongson ports need unifont])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -297,7 +298,7 @@ fi
|
||||||
|
|
||||||
# Check for functions and headers.
|
# Check for functions and headers.
|
||||||
AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getextmntent)
|
AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getextmntent)
|
||||||
AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h)
|
AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h limits.h)
|
||||||
|
|
||||||
AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default
|
AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
@ -412,6 +413,23 @@ if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then
|
||||||
TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm"
|
TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# By default, GCC 4.6 generates .eh_frame sections containing unwind
|
||||||
|
# information in some cases where it previously did not. GRUB doesn't need
|
||||||
|
# these and they just use up vital space. Restore the old compiler
|
||||||
|
# behaviour.
|
||||||
|
AC_CACHE_CHECK([whether -fno-asynchronous-unwind-tables works], [grub_cv_cc_fno_asynchronous_unwind_tables], [
|
||||||
|
SAVE_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS -fno-dwarf2-cfi-asm"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
|
||||||
|
[grub_cv_cc_fno_asynchronous_unwind_tables=yes],
|
||||||
|
[grub_cv_cc_fno_asynchronous_unwind_tables=no])
|
||||||
|
CFLAGS="$SAVE_CFLAGS"
|
||||||
|
])
|
||||||
|
|
||||||
|
if test "x$grub_cv_cc_fno_asynchronous_unwind_tables" = xyes; then
|
||||||
|
TARGET_CFLAGS="$TARGET_CFLAGS -fno-asynchronous-unwind-tables"
|
||||||
|
fi
|
||||||
|
|
||||||
grub_apple_target_cc
|
grub_apple_target_cc
|
||||||
if test x$grub_cv_apple_target_cc = xyes ; then
|
if test x$grub_cv_apple_target_cc = xyes ; then
|
||||||
TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DAPPLE_CC=1"
|
TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DAPPLE_CC=1"
|
||||||
|
@ -459,10 +477,45 @@ case "${host_os}" in
|
||||||
esac
|
esac
|
||||||
AC_MSG_RESULT([$TARGET_OBJ2ELF])
|
AC_MSG_RESULT([$TARGET_OBJ2ELF])
|
||||||
|
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([efiemu],
|
||||||
|
[AS_HELP_STRING([--enable-efiemu],
|
||||||
|
[build and install the efiemu runtimes (default=guessed)])])
|
||||||
|
if test x"$enable_efiemu" = xno ; then
|
||||||
|
efiemu_excuse="explicitly disabled"
|
||||||
|
fi
|
||||||
|
if test x"$target_cpu" != xi386 ; then
|
||||||
|
efiemu_excuse="only available on i386"
|
||||||
|
fi
|
||||||
|
if test x"$platform" = xefi ; then
|
||||||
|
efiemu_excuse="not available on efi"
|
||||||
|
fi
|
||||||
|
if test x"$efiemu_excuse" = x ; then
|
||||||
|
AC_CACHE_CHECK([whether options required for efiemu work], grub_cv_cc_efiemu, [
|
||||||
|
CFLAGS="$CFLAGS -m64 -mcmodel=large -mno-red-zone -nostdlib"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
|
||||||
|
[grub_cv_cc_efiemu=yes],
|
||||||
|
[grub_cv_cc_efiemu=no])
|
||||||
|
])
|
||||||
|
if test x$grub_cv_cc_efiemu = xno; then
|
||||||
|
efiemu_excuse="cannot compile with -m64 -mcmodel=large -mno-red-zone -nostdlib"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test x"$enable_efiemu" = xyes && test x"$efiemu_excuse" != x ; then
|
||||||
|
AC_MSG_ERROR([efiemu runtime was explicitly requested but can't be compiled])
|
||||||
|
fi
|
||||||
|
if test x"$efiemu_excuse" = x ; then
|
||||||
|
enable_efiemu=yes
|
||||||
|
else
|
||||||
|
enable_efiemu=no
|
||||||
|
fi
|
||||||
|
AC_SUBST([enable_efiemu])
|
||||||
|
|
||||||
if test "x$target_m32" = x1; then
|
if test "x$target_m32" = x1; then
|
||||||
# Force 32-bit mode.
|
# Force 32-bit mode.
|
||||||
TARGET_CFLAGS="$TARGET_CFLAGS -m32"
|
TARGET_CFLAGS="$TARGET_CFLAGS -m32"
|
||||||
TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m32"
|
TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m32"
|
||||||
|
TARGET_CPPFLAGS="$TARGET_CPPFLAGS -m32"
|
||||||
TARGET_LDFLAGS="$TARGET_LDFLAGS -m32"
|
TARGET_LDFLAGS="$TARGET_LDFLAGS -m32"
|
||||||
TARGET_MODULE_FORMAT="elf32"
|
TARGET_MODULE_FORMAT="elf32"
|
||||||
fi
|
fi
|
||||||
|
@ -471,6 +524,7 @@ if test "x$target_m64" = x1; then
|
||||||
# Force 64-bit mode.
|
# Force 64-bit mode.
|
||||||
TARGET_CFLAGS="$TARGET_CFLAGS -m64"
|
TARGET_CFLAGS="$TARGET_CFLAGS -m64"
|
||||||
TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m64"
|
TARGET_CCASFLAGS="$TARGET_CCASFLAGS -m64"
|
||||||
|
TARGET_CPPFLAGS="$TARGET_CPPFLAGS -m64"
|
||||||
TARGET_LDFLAGS="$TARGET_LDFLAGS -m64"
|
TARGET_LDFLAGS="$TARGET_LDFLAGS -m64"
|
||||||
TARGET_MODULE_FORMAT="elf64"
|
TARGET_MODULE_FORMAT="elf64"
|
||||||
fi
|
fi
|
||||||
|
@ -587,7 +641,7 @@ CFLAGS="$CFLAGS -Wl,--defsym,abort=main"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check for libgcc symbols
|
# Check for libgcc symbols
|
||||||
AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x __ia64_trampoline __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3 __moddi3 __divdi3)
|
AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x __ia64_trampoline __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3 __moddi3 __divdi3 __ctzdi2 __ctzsi2)
|
||||||
|
|
||||||
if test "x$TARGET_APPLE_CC" = x1 ; then
|
if test "x$TARGET_APPLE_CC" = x1 ; then
|
||||||
CFLAGS="$TARGET_CFLAGS -nostdlib"
|
CFLAGS="$TARGET_CFLAGS -nostdlib"
|
||||||
|
@ -616,39 +670,6 @@ if test "x$target_cpu" = xi386; then
|
||||||
grub_I386_ASM_ADDR32
|
grub_I386_ASM_ADDR32
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_ARG_ENABLE([efiemu],
|
|
||||||
[AS_HELP_STRING([--enable-efiemu],
|
|
||||||
[build and install the efiemu runtimes (default=guessed)])])
|
|
||||||
if test x"$enable_efiemu" = xno ; then
|
|
||||||
efiemu_excuse="explicitly disabled"
|
|
||||||
fi
|
|
||||||
if test x"$target_cpu" != xi386 ; then
|
|
||||||
efiemu_excuse="only available on i386"
|
|
||||||
fi
|
|
||||||
if test x"$platform" = xefi ; then
|
|
||||||
efiemu_excuse="not available on efi"
|
|
||||||
fi
|
|
||||||
if test x"$efiemu_excuse" = x ; then
|
|
||||||
AC_CACHE_CHECK([whether options required for efiemu work], grub_cv_cc_efiemu, [
|
|
||||||
CFLAGS="$CFLAGS -m64 -mcmodel=large -mno-red-zone -nostdlib"
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
|
|
||||||
[grub_cv_cc_efiemu=yes],
|
|
||||||
[grub_cv_cc_efiemu=no])
|
|
||||||
])
|
|
||||||
if test x$grub_cv_cc_efiemu = xno; then
|
|
||||||
efiemu_excuse="cannot compile with -m64 -mcmodel=large -mno-red-zone -nostdlib"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if test x"$enable_efiemu" = xyes && test x"$efiemu_excuse" != x ; then
|
|
||||||
AC_MSG_ERROR([efiemu runtime was explicitly requested but can't be compiled])
|
|
||||||
fi
|
|
||||||
if test x"$efiemu_excuse" = x ; then
|
|
||||||
enable_efiemu=yes
|
|
||||||
else
|
|
||||||
enable_efiemu=no
|
|
||||||
fi
|
|
||||||
AC_SUBST([enable_efiemu])
|
|
||||||
|
|
||||||
if test "$platform" != emu; then
|
if test "$platform" != emu; then
|
||||||
AC_CACHE_CHECK([whether -nostdinc -isystem works], [grub_cv_cc_isystem], [
|
AC_CACHE_CHECK([whether -nostdinc -isystem works], [grub_cv_cc_isystem], [
|
||||||
SAVED_CPPFLAGS="$CPPFLAGS"
|
SAVED_CPPFLAGS="$CPPFLAGS"
|
||||||
|
@ -867,6 +888,37 @@ AC_SUBST([enable_grub_mkfont])
|
||||||
AC_SUBST([freetype_cflags])
|
AC_SUBST([freetype_cflags])
|
||||||
AC_SUBST([freetype_libs])
|
AC_SUBST([freetype_libs])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([grub-mount],
|
||||||
|
[AS_HELP_STRING([--enable-grub-mount],
|
||||||
|
[build and install the `grub-mount' utility (default=guessed)])])
|
||||||
|
if test x"$enable_grub_mount" = xno ; then
|
||||||
|
grub_mount_excuse="explicitly disabled"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x"$grub_mount_excuse" = x ; then
|
||||||
|
AC_CHECK_LIB([fuse], [fuse_main_real], [],
|
||||||
|
[grub_mount_excuse="need FUSE library"])
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x"$grub_mount_excuse" = x ; then
|
||||||
|
# Check for fuse headers.
|
||||||
|
SAVED_CPPFLAGS="$CPPFLAGS"
|
||||||
|
CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26"
|
||||||
|
AC_CHECK_HEADERS([fuse/fuse.h], [],
|
||||||
|
[grub_mount_excuse=["need FUSE headers"]])
|
||||||
|
CPPFLAGS="$SAVED_CPPFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test x"$enable_grub_mount" = xyes && test x"$grub_mount_excuse" != x ; then
|
||||||
|
AC_MSG_ERROR([grub-mount was explicitly requested but can't be compiled])
|
||||||
|
fi
|
||||||
|
if test x"$grub_mount_excuse" = x ; then
|
||||||
|
enable_grub_mount=yes
|
||||||
|
else
|
||||||
|
enable_grub_mount=no
|
||||||
|
fi
|
||||||
|
AC_SUBST([enable_grub_mount])
|
||||||
|
|
||||||
AC_ARG_ENABLE([device-mapper],
|
AC_ARG_ENABLE([device-mapper],
|
||||||
[AS_HELP_STRING([--enable-device-mapper],
|
[AS_HELP_STRING([--enable-device-mapper],
|
||||||
[enable Linux device-mapper support (default=guessed)])])
|
[enable Linux device-mapper support (default=guessed)])])
|
||||||
|
@ -974,12 +1026,14 @@ AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux])
|
||||||
AM_CONDITIONAL([COND_HOST_NETBSD], [test x$host_kernel = xnetbsd])
|
AM_CONDITIONAL([COND_HOST_NETBSD], [test x$host_kernel = xnetbsd])
|
||||||
AM_CONDITIONAL([COND_HOST_WINDOWS], [test x$host_kernel = xwindows])
|
AM_CONDITIONAL([COND_HOST_WINDOWS], [test x$host_kernel = xwindows])
|
||||||
AM_CONDITIONAL([COND_HOST_KFREEBSD], [test x$host_kernel = xkfreebsd])
|
AM_CONDITIONAL([COND_HOST_KFREEBSD], [test x$host_kernel = xkfreebsd])
|
||||||
|
AM_CONDITIONAL([COND_HOST_ILLUMOS], [test x$host_kernel = xillumos])
|
||||||
|
|
||||||
AM_CONDITIONAL([COND_MAN_PAGES], [test x$cross_compiling = xno -a x$HELP2MAN != x])
|
AM_CONDITIONAL([COND_MAN_PAGES], [test x$cross_compiling = xno -a x$HELP2MAN != x])
|
||||||
AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes])
|
AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes])
|
||||||
AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes])
|
AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes])
|
||||||
AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes])
|
AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes])
|
||||||
AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes])
|
AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes])
|
||||||
|
AM_CONDITIONAL([COND_GRUB_MOUNT], [test x$enable_grub_mount = xyes])
|
||||||
AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x])
|
AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x])
|
||||||
AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x])
|
AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x])
|
||||||
AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1])
|
AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1])
|
||||||
|
@ -1066,5 +1120,10 @@ echo grub-mkfont: Yes
|
||||||
else
|
else
|
||||||
echo grub-mkfont: No "($grub_mkfont_excuse)"
|
echo grub-mkfont: No "($grub_mkfont_excuse)"
|
||||||
fi
|
fi
|
||||||
|
if [ x"$grub_mount_excuse" = x ]; then
|
||||||
|
echo grub-mount: Yes
|
||||||
|
else
|
||||||
|
echo grub-mount: No "($grub_mount_excuse)"
|
||||||
|
fi
|
||||||
echo "*******************************************************"
|
echo "*******************************************************"
|
||||||
]
|
]
|
||||||
|
|
|
@ -77,6 +77,7 @@ This edition documents version @value{VERSION}.
|
||||||
* Finding your way around::
|
* Finding your way around::
|
||||||
* Coding style::
|
* Coding style::
|
||||||
* Contributing Changes::
|
* Contributing Changes::
|
||||||
|
* Porting::
|
||||||
* Error Handling::
|
* Error Handling::
|
||||||
* CIA::
|
* CIA::
|
||||||
* BIOS port memory map::
|
* BIOS port memory map::
|
||||||
|
@ -447,6 +448,315 @@ If your intention is to just get started, please do not submit a inclusion
|
||||||
request. Instead, please subscribe to the mailing list, and communicate first
|
request. Instead, please subscribe to the mailing list, and communicate first
|
||||||
(e.g. sending a patch, asking a question, commenting on another message...).
|
(e.g. sending a patch, asking a question, commenting on another message...).
|
||||||
|
|
||||||
|
@node Porting
|
||||||
|
@chapter Porting
|
||||||
|
|
||||||
|
GRUB2 is designed to be easily portable accross platforms. But because of the
|
||||||
|
nature of bootloader every new port must be done separately. Here is how I did
|
||||||
|
MIPS (loongson and ARC) and Xen ports. Note than this is more of suggestions,
|
||||||
|
not absolute truth.
|
||||||
|
|
||||||
|
First of all grab any architecture specifications you can find in public
|
||||||
|
(please avoid NDA).
|
||||||
|
|
||||||
|
First stage is ``Hello world''. I've done it outside of GRUB for simplicity.
|
||||||
|
Your task is to have a small program which is loadable as bootloader and
|
||||||
|
clearly shows its presence to you. If you have easily accessible console
|
||||||
|
you can just print a message. If you have a mapped framebuffer you know address
|
||||||
|
of, you can draw a square. If you have a debug facility, just hanging without
|
||||||
|
crashing might be enough. For the first stage you can choose to load the
|
||||||
|
bootloader across the network since format for network image is often easier
|
||||||
|
than for local boot and it skips the need of small intermediary stages and
|
||||||
|
nvram handling. Additionally you can often have a good idea of the needed
|
||||||
|
format by running ``file'' on any netbootable executable for given platform.
|
||||||
|
|
||||||
|
This program should probably have 2 parts: an assembler and C one. Assembler one
|
||||||
|
handles BSS cleaning and other needed setup (on some platforms you may need
|
||||||
|
to switch modes or copy the executable to its definitive position). So your code
|
||||||
|
may look like (x86 assembly for illustration purposes)
|
||||||
|
|
||||||
|
@example
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
movl $_bss_start, %edi
|
||||||
|
movl $_end, %ecx
|
||||||
|
subl %edi, %ecx
|
||||||
|
xorl %eax, %eax
|
||||||
|
cld
|
||||||
|
rep
|
||||||
|
stosb
|
||||||
|
call main
|
||||||
|
@end example
|
||||||
|
|
||||||
|
@example
|
||||||
|
|
||||||
|
static const char msg[] = "Hello, world";
|
||||||
|
|
||||||
|
void
|
||||||
|
putchar (int c)
|
||||||
|
@{
|
||||||
|
...
|
||||||
|
@}
|
||||||
|
|
||||||
|
void
|
||||||
|
main (void)
|
||||||
|
@{
|
||||||
|
const char *ptr = msg;
|
||||||
|
while (*ptr)
|
||||||
|
putchar (*ptr++);
|
||||||
|
while (1);
|
||||||
|
@}
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Sometimes you need a third file: assembly stubs for ABI-compatibility.
|
||||||
|
|
||||||
|
Once this file is functional it's time to move it into GRUB2. The startup
|
||||||
|
assembly file goes to grub-core/kern/$cpu/$platform/startup.S. You should also
|
||||||
|
include grub/symbol.h and replace call to entry point with call to
|
||||||
|
EXT_C(grub_main). The C file goes to grub-core/kern/$cpu/$platform/init.c
|
||||||
|
and its entry point is renamed to void grub_machine_init (void). Keep final
|
||||||
|
infinite loop for now. Stubs file if any goes to
|
||||||
|
grub-core/kern/$cpu/$platform/callwrap.S. Sometimes either $cpu or $platform
|
||||||
|
is dropped if file is used on several cpus respectivelyplatforms.
|
||||||
|
Check those locations if they already have what you're looking for.
|
||||||
|
|
||||||
|
Then modify in configure.ac the following parts:
|
||||||
|
|
||||||
|
CPU names:
|
||||||
|
|
||||||
|
@example
|
||||||
|
case "$target_cpu" in
|
||||||
|
i[[3456]]86) target_cpu=i386 ;;
|
||||||
|
amd64) target_cpu=x86_64 ;;
|
||||||
|
sparc) target_cpu=sparc64 ;;
|
||||||
|
s390x) target_cpu=s390 ;;
|
||||||
|
...
|
||||||
|
esac
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Sometimes CPU have additional architecture names which don't influence booting.
|
||||||
|
You might want to have some canonical name to avoid having bunch of identical
|
||||||
|
platforms with different names.
|
||||||
|
|
||||||
|
NOTE: it doesn't influence compile optimisations which depend solely on
|
||||||
|
chosen compiler and compile options.
|
||||||
|
|
||||||
|
@example
|
||||||
|
if test "x$with_platform" = x; then
|
||||||
|
case "$target_cpu"-"$target_vendor" in
|
||||||
|
i386-apple) platform=efi ;;
|
||||||
|
i386-*) platform=pc ;;
|
||||||
|
x86_64-apple) platform=efi ;;
|
||||||
|
x86_64-*) platform=pc ;;
|
||||||
|
powerpc-*) platform=ieee1275 ;;
|
||||||
|
...
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
...
|
||||||
|
fi
|
||||||
|
@end example
|
||||||
|
|
||||||
|
This part deals with guessing the platform from CPU and vendor. Sometimes you
|
||||||
|
need to use 32-bit mode for booting even if OS runs in 64-bit one. If so add
|
||||||
|
your platform to:
|
||||||
|
|
||||||
|
@example
|
||||||
|
case "$target_cpu"-"$platform" in
|
||||||
|
x86_64-efi) ;;
|
||||||
|
x86_64-emu) ;;
|
||||||
|
x86_64-*) target_cpu=i386 ;;
|
||||||
|
powerpc64-ieee1275) target_cpu=powerpc ;;
|
||||||
|
esac
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Add your platform to the list of supported ones:
|
||||||
|
|
||||||
|
@example
|
||||||
|
case "$target_cpu"-"$platform" in
|
||||||
|
i386-efi) ;;
|
||||||
|
x86_64-efi) ;;
|
||||||
|
i386-pc) ;;
|
||||||
|
i386-multiboot) ;;
|
||||||
|
i386-coreboot) ;;
|
||||||
|
...
|
||||||
|
esac
|
||||||
|
@end example
|
||||||
|
|
||||||
|
If explicit -m32 or -m64 is needed add it to:
|
||||||
|
|
||||||
|
@example
|
||||||
|
case "$target_cpu" in
|
||||||
|
i386 | powerpc) target_m32=1 ;;
|
||||||
|
x86_64 | sparc64) target_m64=1 ;;
|
||||||
|
esac
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Finally you need to add a conditional to the following block:
|
||||||
|
|
||||||
|
@example
|
||||||
|
AM_CONDITIONAL([COND_mips_arc], [test x$target_cpu = xmips -a x$platform = xarc])
|
||||||
|
AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275])
|
||||||
|
AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275])
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Next stop is gentpl.py. You need to add your platform to the list of supported
|
||||||
|
ones (sorry that this list is duplicated):
|
||||||
|
|
||||||
|
@example
|
||||||
|
GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot",
|
||||||
|
"i386_multiboot", "i386_ieee1275", "x86_64_efi",
|
||||||
|
"mips_loongson", "sparc64_ieee1275",
|
||||||
|
"powerpc_ieee1275", "mips_arc", "ia64_efi",
|
||||||
|
"mips_qemu_mips", "s390_mainframe" ]
|
||||||
|
@end example
|
||||||
|
|
||||||
|
You may also want already to add new platform to one or several of available
|
||||||
|
groups. In particular we always have a group for each CPU even when only
|
||||||
|
one platform for given CPU is available.
|
||||||
|
|
||||||
|
Then comes grub-core/Makefile.core.def. In the block ``kernel'' you'll need
|
||||||
|
to define ldflags for your platform ($cpu_$platform_ldflags). You also need to
|
||||||
|
declare startup asm file ($cpu_$platform_startup) as well as any other files
|
||||||
|
(e.g. init.c and callwrap.S) (e.g. $cpu_$platform = kern/$cpu/$platform/init.c).
|
||||||
|
At this stage you will also need to add dummy dl.c and cache.S with functions
|
||||||
|
grub_err_t grub_arch_dl_check_header (void *ehdr), grub_err_t
|
||||||
|
grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c) and
|
||||||
|
void grub_arch_sync_caches (void *address, grub_size_t len) (cache.S). They
|
||||||
|
won't be used for now.
|
||||||
|
|
||||||
|
You will need to create directory include/$cpu/$platform and a file
|
||||||
|
include/$cpu/types.h. The later folowing this template:
|
||||||
|
|
||||||
|
@example
|
||||||
|
#ifndef GRUB_TYPES_CPU_HEADER
|
||||||
|
#define GRUB_TYPES_CPU_HEADER 1
|
||||||
|
|
||||||
|
/* The size of void *. */
|
||||||
|
#define GRUB_TARGET_SIZEOF_VOID_P 4
|
||||||
|
|
||||||
|
/* The size of long. */
|
||||||
|
#define GRUB_TARGET_SIZEOF_LONG 4
|
||||||
|
|
||||||
|
/* mycpu is big-endian. */
|
||||||
|
#define GRUB_TARGET_WORDS_BIGENDIAN 1
|
||||||
|
/* Alternatively: mycpu is little-endian. */
|
||||||
|
#undef GRUB_TARGET_WORDS_BIGENDIAN
|
||||||
|
|
||||||
|
#endif /* ! GRUB_TYPES_CPU_HEADER */
|
||||||
|
@end example
|
||||||
|
|
||||||
|
You will also need to add a dummy file to datetime and setjmp modules to
|
||||||
|
avoid any of it having no files. It can be just completely empty at this stage.
|
||||||
|
|
||||||
|
You'll need to make grub-mkimage.c (util/grub_mkimage.c) aware of the needed
|
||||||
|
format. For most commonly used formats like ELF, PE, aout or raw the support
|
||||||
|
is already present and you'll need to make it follow the existant code paths
|
||||||
|
for your platform adding adjustments if necessary. When done compile:
|
||||||
|
|
||||||
|
@example
|
||||||
|
./autogen.sh
|
||||||
|
./configure --target=$cpu --with-platform=$platform TARGET_CC=.. OBJCOPY=... STRIP=...
|
||||||
|
make > /dev/null
|
||||||
|
@end example
|
||||||
|
|
||||||
|
And create image
|
||||||
|
|
||||||
|
@example
|
||||||
|
./grub-mkimage -d grub-core -O $format_id -o test.img
|
||||||
|
@end example
|
||||||
|
|
||||||
|
And it's time to test your test.img.
|
||||||
|
|
||||||
|
If it works next stage is to have heap, console and timer.
|
||||||
|
|
||||||
|
To have the heap working you need to determine which regions are suitable for
|
||||||
|
heap usage, allocate them from firmware and map (if applicable). Then call
|
||||||
|
grub_mm_init_region (vois *start, grub_size_t s) for every of this region.
|
||||||
|
As a shortcut for early port you can allocate right after _end or have
|
||||||
|
a big static array for heap. If you do you'll probably need to come back to
|
||||||
|
this later. As for output console you should distinguish between an array of
|
||||||
|
text, terminfo or graphics-based console. Many of real-world examples don't
|
||||||
|
fit perfectly into any of these categories but one of the models is easier
|
||||||
|
to be used as base. In second and third case you should add your platform to
|
||||||
|
terminfokernel respectively videoinkernel group. A good example of array of
|
||||||
|
text is i386-pc (kern/i386/pc/init.c and term/i386/pc/console.c).
|
||||||
|
Of terminfo is ieee1275 (kern/ieee1275/init.c and term/ieee1275/console.c).
|
||||||
|
Of video is loongson (kern/mips/loongson/init.c). Note that terminfo has
|
||||||
|
to be inited in 2 stages: one before (to get at least rudimentary console
|
||||||
|
as early as possible) and another after the heap (to get full-featured console).
|
||||||
|
For the input there are string of keys, terminfo and direct hardware. For string
|
||||||
|
of keys look at i386-pc (same files), for termino ieee1275 (same files) and for
|
||||||
|
hardware loongson (kern/mips/loongson/init.c and term/at_keyboard.c).
|
||||||
|
|
||||||
|
For the timer you'll need to call grub_install_get_time_ms (...) with as sole
|
||||||
|
argument a function returning a grub_uint64_t of a number of milliseconds
|
||||||
|
elapsed since arbitrary point in the past.
|
||||||
|
|
||||||
|
Once these steps accomplished you can remove the inifinite loop and you should
|
||||||
|
be able to get to the minimal console. Next step is to have module loading
|
||||||
|
working. For this you'll need to fill kern/$cpu/dl.c and kern/$cpu/cache.S
|
||||||
|
with real handling of relocations and respectively the real sync of I and D
|
||||||
|
caches. Also you'll need to decide where in the image to store the modules.
|
||||||
|
Usual way is to have it concatenated at the end. In this case you'll need to
|
||||||
|
modify startup.S to copy modules out of bss to let's say ALIGN_UP (_end, 8)
|
||||||
|
before cleaning out bss. You'll probably find useful to add total_module_size
|
||||||
|
field to startup.S. In init.c you need to set grub_modbase to the address
|
||||||
|
where modules can be found. You may need grub_modules_get_end () to avoid
|
||||||
|
declaring the space occupied by modules as usable for heap. You can test modules
|
||||||
|
with:
|
||||||
|
|
||||||
|
@example
|
||||||
|
./grub-mkimage -d grub-core -O $format_id -o test.img hello
|
||||||
|
@end example
|
||||||
|
|
||||||
|
and then running ``hello'' in the shell.
|
||||||
|
|
||||||
|
Once this works, you should think of implementing disk access. Look around
|
||||||
|
disk/ for examples.
|
||||||
|
|
||||||
|
Then, very importantly, you probably need to implement the actual loader
|
||||||
|
(examples available in loader/)
|
||||||
|
|
||||||
|
Last step to have minimally usable port is to add support to grub-install to
|
||||||
|
put GRUB in a place where firmware or platform will pick it up.
|
||||||
|
|
||||||
|
Next steps are: filling datetime.c, setjmp.S, network (net/drivers),
|
||||||
|
video (video/), halt (lib/), reboot (lib/).
|
||||||
|
|
||||||
|
Please add your platform to Platform limitations and Supported kernels chapter
|
||||||
|
in user documentation and mention any steps you skipped which result in reduced
|
||||||
|
features or performance. Here is the quick checklist of features. Some of them
|
||||||
|
are less important than others and skipping them is completely ok, just needs
|
||||||
|
to be mentioned in user documentation.
|
||||||
|
|
||||||
|
Checklist:
|
||||||
|
@itemize
|
||||||
|
@item Is heap big enough?
|
||||||
|
@item Which charset is supported by console?
|
||||||
|
@item Does platform have disk driver?
|
||||||
|
@item Do you have network card support?
|
||||||
|
@item Are you able to retrieve datetime (with date)?
|
||||||
|
@item Are you able to set datetime (with date)?
|
||||||
|
@item Is serial supported?
|
||||||
|
@item Do you have direct disk support?
|
||||||
|
@item Do you have direct keyboard support?
|
||||||
|
@item Do you have USB support?
|
||||||
|
@item Do you support loading through network?
|
||||||
|
@item Do you support loading from disk?
|
||||||
|
@item Do you support chainloading?
|
||||||
|
@item Do you support network chainloading?
|
||||||
|
@item Does cpuid command supports checking all
|
||||||
|
CPU features that the user might want conditionalise on
|
||||||
|
(64-bit mode, hypervisor,...)
|
||||||
|
@item Do you support hints? How reliable are they?
|
||||||
|
@item Does platform have ACPI? If so do ``acpi'' and ``lsacpi'' modules work?
|
||||||
|
@item Do any of platform-specific operations mentioned in the relevant section of
|
||||||
|
user manual makes sense on your platform?
|
||||||
|
@item Does your platform support PCI? If so is there an appropriate driver for
|
||||||
|
GRUB?
|
||||||
|
@item Do you support badram?
|
||||||
|
@end itemize
|
||||||
|
|
||||||
@node Error Handling
|
@node Error Handling
|
||||||
@chapter Error Handling
|
@chapter Error Handling
|
||||||
|
|
||||||
|
|
373
docs/grub.texi
373
docs/grub.texi
|
@ -89,7 +89,10 @@ This edition documents version @value{VERSION}.
|
||||||
* Interface:: The menu and the command-line
|
* Interface:: The menu and the command-line
|
||||||
* Environment:: GRUB environment variables
|
* Environment:: GRUB environment variables
|
||||||
* Commands:: The list of available builtin commands
|
* Commands:: The list of available builtin commands
|
||||||
|
* Internationalisation:: Topics relating to language support
|
||||||
* Security:: Authentication and authorisation
|
* Security:: Authentication and authorisation
|
||||||
|
* Platform limitations:: The list of platform-specific limitations
|
||||||
|
* Platform-specific operations:: Platform-specific operations
|
||||||
* Supported kernels:: The list of supported kernels
|
* Supported kernels:: The list of supported kernels
|
||||||
* Troubleshooting:: Error messages produced by GRUB
|
* Troubleshooting:: Error messages produced by GRUB
|
||||||
* Invoking grub-install:: How to use the GRUB installer
|
* Invoking grub-install:: How to use the GRUB installer
|
||||||
|
@ -340,11 +343,17 @@ devices, partitions, and files in a directory depending on context.
|
||||||
@item Support multiple filesystem types
|
@item Support multiple filesystem types
|
||||||
Support multiple filesystem types transparently, plus a useful explicit
|
Support multiple filesystem types transparently, plus a useful explicit
|
||||||
blocklist notation. The currently supported filesystem types are @dfn{Amiga
|
blocklist notation. The currently supported filesystem types are @dfn{Amiga
|
||||||
Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS}, @dfn{cpio}, @dfn{Linux
|
Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS},
|
||||||
ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{HFS}, @dfn{HFS+},
|
@dfn{BtrFS} (including raid0, raid1, raid10, gzip and lzo),
|
||||||
@dfn{ISO9660}, @dfn{JFS}, @dfn{Minix fs}, @dfn{nilfs2}, @dfn{NTFS},
|
@dfn{cpio} (little- and big-endian bin, odc and newc variants),
|
||||||
@dfn{ReiserFS}, @dfn{Amiga Smart FileSystem (SFS)}, @dfn{tar}, @dfn{UDF},
|
@dfn{Linux ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{exFAT}, @dfn{HFS},
|
||||||
@dfn{BSD UFS/UFS2}, and @dfn{XFS}. @xref{Filesystem}, for more information.
|
@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
|
@item Support automatic decompression
|
||||||
Can decompress files which were compressed by @command{gzip} or
|
Can decompress files which were compressed by @command{gzip} or
|
||||||
|
@ -784,6 +793,7 @@ magic.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
* General boot methods:: How to boot OSes with GRUB generally
|
* 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
|
* OS-specific notes:: Notes on some operating systems
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
@ -855,6 +865,31 @@ required. @xref{DOS/Windows}.
|
||||||
|
|
||||||
Chain-loading is only supported on PC BIOS and EFI platforms.
|
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
|
@node OS-specific notes
|
||||||
@section Some caveats on OS-specific issues
|
@section Some caveats on OS-specific issues
|
||||||
|
@ -2203,42 +2238,67 @@ you see the files in a device or use the command @command{search}
|
||||||
The device syntax is like this:
|
The device syntax is like this:
|
||||||
|
|
||||||
@example
|
@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
|
@end example
|
||||||
|
|
||||||
@samp{[]} means the parameter is optional. @var{device} should be
|
@samp{[]} means the parameter is optional. @var{device} depends on the disk
|
||||||
either @samp{fd} or @samp{hd} followed by a digit, like @samp{fd0}.
|
driver in use. BIOS and EFI disks use either @samp{fd} or @samp{hd} followed
|
||||||
But you can also set @var{device} to a hexadecimal or a decimal number
|
by a digit, like @samp{fd0}, or @samp{cd}.
|
||||||
which is a BIOS drive number, so the following are equivalent:
|
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.
|
||||||
|
Hostdisk uses names specified in device.map or hostdisk/<OS NAME>.
|
||||||
|
For crypto and RAID (md) additionally you can use the syntax
|
||||||
|
<driver name>uuid/<uuid>.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
|
(fd0)
|
||||||
(hd0)
|
(hd0)
|
||||||
(0x80)
|
(cd)
|
||||||
(128)
|
(ahci0)
|
||||||
|
(ata0)
|
||||||
|
(crypto0)
|
||||||
|
(usb0)
|
||||||
|
(cryptouuid/123456789abcdef0123456789abcdef0)
|
||||||
|
(mduuid/123456789abcdef0123456789abcdef0)
|
||||||
|
(lv/system-root)
|
||||||
|
(md/myraid)
|
||||||
|
(md/0)
|
||||||
|
(ieee1275/disk2)
|
||||||
|
(ieee1275//pci@@1f\,0/ide@@d/disk@@2)
|
||||||
|
(memdisk)
|
||||||
|
(host)
|
||||||
|
(myloop)
|
||||||
|
(hostdisk//dev/sda)
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
@var{part-num} represents the partition number of @var{device}, starting
|
@var{part-num} represents the partition number of @var{device}, starting
|
||||||
from one for primary partitions and from five for extended partitions,
|
from one. @var{partname} is optional but is recommended since disk may have
|
||||||
and @var{bsd-subpart-letter} represents the BSD disklabel subpartition,
|
several top-level partmaps. Specifying third and later component you can access
|
||||||
such as @samp{a} or @samp{e}.
|
to subpartitions.
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
The syntax @samp{(hd0)} represents using the entire disk (or the
|
The syntax @samp{(hd0)} represents using the entire disk (or the
|
||||||
MBR when installing GRUB), while the syntax @samp{(hd0,1)}
|
MBR when installing GRUB), while the syntax @samp{(hd0,1)}
|
||||||
represents using the first partition of the disk (or the boot sector
|
represents using the first partition of the disk (or the boot sector
|
||||||
of the partition when installing GRUB).
|
of the partition when installing GRUB).
|
||||||
|
|
||||||
If you enabled the network support, the special drive @samp{(pxe)} is
|
@example
|
||||||
also available. Before using the network drive, you must initialize the
|
(hd0,msdos1)
|
||||||
network. @xref{Network}, for more information.
|
(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
|
If you boot GRUB from a CD-ROM, @samp{(cd)} is available. @xref{Making
|
||||||
a GRUB bootable CD-ROM}, for details.
|
a GRUB bootable CD-ROM}, for details.
|
||||||
|
@ -3867,6 +3927,93 @@ Unset the environment variable @var{envvar}.
|
||||||
|
|
||||||
This command is not yet implemented for GRUB 2, although it is planned.
|
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 filenames in FAT, Joliet part of
|
||||||
|
ISO9660 are treated as UTF-16 as per specification. AFS and BFS are 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, SFS
|
||||||
|
and HFS never use unicode and GRUB assumes them to be in Latin1, Latin1
|
||||||
|
and MacRoman respectively. GRUB handles filesystem case-insensitivity 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. The filesystems in questions are
|
||||||
|
NTFS (except POSIX namespace), HFS+ (by default), FAT, exFAT and
|
||||||
|
ZFS (configurable on per-subvolume basis by property ``casesensitivity'',
|
||||||
|
default sensitive). On ZFS subvolumes marked as case insensitive files
|
||||||
|
containing lowercase international characters are inaccessible.
|
||||||
|
Also like all supported filesystems except HFS+ and ZFS (configurable on
|
||||||
|
per-subvolume basis by property ``normalization'', default none) GRUB makes
|
||||||
|
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 normalized ZFS subvolumes filenames out of normalisation 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, half (e.g. left half tilde or combining overline) and double ones.
|
||||||
|
Ligatures aren't supported though. This should cover European, Middle Eastern
|
||||||
|
(if you don't mind lack of lam-alif ligature in Arabic) and East Asian scripts.
|
||||||
|
Notable unsupported scripts are Brahmic family and derived as well as
|
||||||
|
Mongolian, Tifinagh, Korean Jamo (precomposed characters have no problem)
|
||||||
|
and tonal writing (2e5-2e9). GRUB also ignores deprecated (as specified
|
||||||
|
in Unicode) characters (e.g. tags). GRUB also doesn't handle so called
|
||||||
|
``annotation characters'' 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.
|
||||||
|
|
||||||
|
@chapter Regexp
|
||||||
|
Regexps work on unicode characters, however no attempt at checking cannonical
|
||||||
|
equivalence has been made. Moreover the classes like [:alpha:] match only
|
||||||
|
ASCII subset.
|
||||||
|
|
||||||
|
@chapter Other
|
||||||
|
IEEE1275 aliases are matched case-insensitively except non-ASCII which is
|
||||||
|
matched as binary. Similar behaviour is for matching OSBundleRequired.
|
||||||
|
Since IEEE1275 aliases and OSBundleRequired don't contain any non-ASCII it
|
||||||
|
should never be a problem in practice.
|
||||||
|
Case-sensitive identifiers are matched as raw strings, no canonical
|
||||||
|
equivalence check is performed. Case-insenstive identifiers are matched
|
||||||
|
as RAW but additionally [a-z] is equivalent to [A-Z]. GRUB-defined
|
||||||
|
identifiers use only ASCII and so should user-defined ones.
|
||||||
|
Identifiers containing non-ASCII may work but aren't supported.
|
||||||
|
Only the ASCII space characters (space U+0020, tab U+000b, CR U+000d and
|
||||||
|
LF U+000a) are recognised. Other unicode space characters aren't a valid
|
||||||
|
field separator.
|
||||||
|
|
||||||
@node Security
|
@node Security
|
||||||
@chapter Authentication and authorisation
|
@chapter Authentication and authorisation
|
||||||
|
@ -3935,6 +4082,167 @@ adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2}
|
||||||
commands.
|
commands.
|
||||||
|
|
||||||
|
|
||||||
|
@node Platform limitations
|
||||||
|
@chapter Platform limitations
|
||||||
|
|
||||||
|
GRUB2 is designed to be portable and is actually ported across platforms. We
|
||||||
|
try to keep all platforms at the level. Unfortunately some platforms are better
|
||||||
|
supported than others. This is detailed in current and 2 following sections.
|
||||||
|
|
||||||
|
ARC platform is unable to change datetime (firmware doesn't seem to provide a
|
||||||
|
function for it).
|
||||||
|
EMU has similar limitation.
|
||||||
|
|
||||||
|
Console charset refers only to firmware-assisted console. gfxterm is always
|
||||||
|
Unicode (see Internationalisation section for its limitations). Serial is
|
||||||
|
configurable to UTF-8 or ASCII (see Internationalisation). In case of qemu
|
||||||
|
and coreboot ports the refered console is vga_text. Loongson always uses
|
||||||
|
gfxterm.
|
||||||
|
|
||||||
|
Most limited one is ASCII. CP437 provides additionally pseudographics.
|
||||||
|
GRUB2 doesn't use any language characters from CP437 as often CP437 is replaced
|
||||||
|
by national encoding compatible only in pseudographics.
|
||||||
|
Unicode is the most versatile charset which supports many languages. However
|
||||||
|
the actual console may be much more limited depending on firmware
|
||||||
|
|
||||||
|
On BIOS network is supported only if the image is loaded through network.
|
||||||
|
On sparc64 GRUB is unable to determine which server it was booted from.
|
||||||
|
|
||||||
|
On platforms not having direct serial support (as indicated in the line serial)
|
||||||
|
you can still redirect firmware console to serial if it allows so.
|
||||||
|
|
||||||
|
Direct ATA/AHCI support allows to circumvent various firmware limitations but
|
||||||
|
isn't needed for normal operation except on baremetal ports.
|
||||||
|
|
||||||
|
AT keyboard support allows keyboard layout remapping and support for keys not
|
||||||
|
available through firmware. It isn't needed for normal operation except
|
||||||
|
baremetal ports.
|
||||||
|
|
||||||
|
USB support provides benefits similar to ATA (for USB disks) or AT (for USB
|
||||||
|
keyboards). In addition it allows USBserial.
|
||||||
|
|
||||||
|
Chainloading refers to the ability to load another bootloader through the same protocol
|
||||||
|
|
||||||
|
Hints allow faster disk discovery by already knowing in advance which is the disk in
|
||||||
|
question. On some platforms hints are correct unless you move the disk between boots.
|
||||||
|
On other platforms it's just an educated guess.
|
||||||
|
Note that hint failure results in just reduced performance, not a failure
|
||||||
|
|
||||||
|
BadRAM is the ability to mark some of the RAM as ``bad''. Note: due to protocol
|
||||||
|
limitations mips-loongson (with Linux protocol)
|
||||||
|
and mips-qemu_mips can use only memory up to first hole.
|
||||||
|
|
||||||
|
@multitable @columnfractions .20 .20 .20 .20 .20
|
||||||
|
@item @tab BIOS @tab Coreboot @tab Multiboot @tab Qemu
|
||||||
|
@item video @tab yes @tab yes @tab yes @tab yes
|
||||||
|
@item console charset @tab CP437 @tab CP437 @tab CP437 @tab CP437
|
||||||
|
@item network @tab yes (*) @tab no @tab no @tab no
|
||||||
|
@item serial @tab yes @tab yes @tab yes @tab yes
|
||||||
|
@item ATA/AHCI @tab yes @tab yes @tab yes @tab yes
|
||||||
|
@item AT keyboard @tab yes @tab yes @tab yes @tab yes
|
||||||
|
@item USB @tab yes @tab yes @tab yes @tab yes
|
||||||
|
@item chainloader @tab local @tab yes @tab yes @tab no
|
||||||
|
@item cpuid @tab partial @tab partial @tab partial @tab partial
|
||||||
|
@item hints @tab guess @tab guess @tab guess @tab guess
|
||||||
|
@item PCI @tab yes @tab yes @tab yes @tab yes
|
||||||
|
@item badram @tab yes @tab yes @tab yes @tab yes
|
||||||
|
@item compression @tab always @tab pointless @tab no @tab no
|
||||||
|
@item exit @tab yes @tab no @tab no @tab no
|
||||||
|
@end multitable
|
||||||
|
|
||||||
|
@multitable @columnfractions .20 .20 .20 .20 .20
|
||||||
|
@item @tab ia32 EFI @tab amd64 EFI @tab ia32 IEEE1275 @tab Itanium
|
||||||
|
@item video @tab yes @tab yes @tab no @tab no
|
||||||
|
@item console charset @tab Unicode @tab Unicode @tab ASCII @tab Unicode
|
||||||
|
@item network @tab yes @tab yes @tab yes @tab yes
|
||||||
|
@item serial @tab yes @tab yes @tab yes @tab no
|
||||||
|
@item ATA/AHCI @tab yes @tab yes @tab yes @tab no
|
||||||
|
@item AT keyboard @tab yes @tab yes @tab yes @tab no
|
||||||
|
@item USB @tab yes @tab yes @tab yes @tab no
|
||||||
|
@item chainloader @tab local @tab local @tab no @tab local
|
||||||
|
@item cpuid @tab partial @tab partial @tab partial @tab no
|
||||||
|
@item hints @tab guess @tab guess @tab good @tab guess
|
||||||
|
@item PCI @tab yes @tab yes @tab yes @tab no
|
||||||
|
@item badram @tab yes @tab yes @tab no @tab yes
|
||||||
|
@item compression @tab no @tab no @tab no @tab no
|
||||||
|
@item exit @tab yes @tab yes @tab yes @tab yes
|
||||||
|
@end multitable
|
||||||
|
|
||||||
|
@multitable @columnfractions .20 .20 .20 .20 .20
|
||||||
|
@item @tab Loongson @tab sparc64 @tab Powerpc @tab ARC
|
||||||
|
@item video @tab yes @tab no @tab yes @tab no
|
||||||
|
@item console charset @tab N/A @tab ASCII @tab ASCII @tab ASCII
|
||||||
|
@item network @tab no @tab yes (*) @tab yes @tab no
|
||||||
|
@item serial @tab yes @tab no @tab no @tab no
|
||||||
|
@item ATA/AHCI @tab yes @tab no @tab no @tab no
|
||||||
|
@item AT keyboard @tab yes @tab no @tab no @tab no
|
||||||
|
@item USB @tab yes @tab no @tab no @tab no
|
||||||
|
@item chainloader @tab yes @tab no @tab no @tab no
|
||||||
|
@item cpuid @tab no @tab no @tab no @tab no
|
||||||
|
@item hints @tab good @tab good @tab good @tab no
|
||||||
|
@item PCI @tab yes @tab no @tab no @tab no
|
||||||
|
@item badram @tab yes (*) @tab no @tab no @tab no
|
||||||
|
@item compression @tab configurable @tab no @tab no @tab configurable
|
||||||
|
@item exit @tab no @tab yes @tab yes @tab yes
|
||||||
|
@end multitable
|
||||||
|
|
||||||
|
@multitable @columnfractions .20 .20 .20 .20 .20
|
||||||
|
@item @tab MIPS qemu @tab emu
|
||||||
|
@item video @tab no @tab no
|
||||||
|
@item console charset @tab CP437 @tab ASCII
|
||||||
|
@item network @tab no @tab yes
|
||||||
|
@item serial @tab yes @tab no
|
||||||
|
@item ATA/AHCI @tab yes @tab no
|
||||||
|
@item AT keyboard @tab yes @tab no
|
||||||
|
@item USB @tab N/A @tab yes
|
||||||
|
@item chainloader @tab yes @tab no
|
||||||
|
@item cpuid @tab no @tab no
|
||||||
|
@item hints @tab guess @tab no
|
||||||
|
@item PCI @tab no @tab no
|
||||||
|
@item badram @tab yes (*) @tab no
|
||||||
|
@item compression @tab configurable @tab no
|
||||||
|
@item exit @tab no @tab yes
|
||||||
|
@end multitable
|
||||||
|
|
||||||
|
@node Platform-specific operations
|
||||||
|
@chapter Outline
|
||||||
|
|
||||||
|
Some platforms have features which allows to implement
|
||||||
|
some commands useless or not implementable on others.
|
||||||
|
|
||||||
|
Quick summary:
|
||||||
|
|
||||||
|
Information retrieval:
|
||||||
|
|
||||||
|
@itemize
|
||||||
|
@item mipsel-loongson: lsspd
|
||||||
|
@item mips-arc: lsdev
|
||||||
|
@item efi: lsefisystab, lssal, lsefimmap
|
||||||
|
@item i386-pc: lsapm
|
||||||
|
@item acpi-enabled (i386-pc, i386-coreboot, i386-multiboot, *-efi): lsacpi
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
Workarounds for platform-specific issues:
|
||||||
|
@itemize
|
||||||
|
@item i386-efi/x86_64-efi: loadbios, fixvideo
|
||||||
|
@item acpi-enabled (i386-pc, i386-coreboot, i386-multiboot, *-efi):
|
||||||
|
acpi (override ACPI tables)
|
||||||
|
@item i386-pc: drivemap
|
||||||
|
@item i386-pc: sendkey
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
Advanced operations for power users:
|
||||||
|
@itemize
|
||||||
|
@item x86: iorw (direct access to I/O ports)
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
Miscelaneous:
|
||||||
|
@itemize
|
||||||
|
@item cmos (x86-*, ieee1275, mips-qemu_mips, mips-loongson): cmostest
|
||||||
|
(used on some laptops to check for special power-on key)
|
||||||
|
@item i386-pc: play
|
||||||
|
@end itemize
|
||||||
|
|
||||||
@node Supported kernels
|
@node Supported kernels
|
||||||
@chapter Supported boot targets
|
@chapter Supported boot targets
|
||||||
|
|
||||||
|
@ -3943,6 +4251,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
|
||||||
@item @tab BIOS @tab Coreboot
|
@item @tab BIOS @tab Coreboot
|
||||||
@item BIOS chainloading @tab yes @tab no (1)
|
@item BIOS chainloading @tab yes @tab no (1)
|
||||||
@item NTLDR @tab yes @tab no (1)
|
@item NTLDR @tab yes @tab no (1)
|
||||||
|
@item Plan9 @tab yes @tab no (1)
|
||||||
@item Freedos @tab yes @tab no (1)
|
@item Freedos @tab yes @tab no (1)
|
||||||
@item FreeBSD bootloader @tab yes @tab crashes (1)
|
@item FreeBSD bootloader @tab yes @tab crashes (1)
|
||||||
@item 32-bit kFreeBSD @tab yes @tab crashes (2,6)
|
@item 32-bit kFreeBSD @tab yes @tab crashes (2,6)
|
||||||
|
@ -3968,6 +4277,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
|
||||||
@item @tab Multiboot @tab Qemu
|
@item @tab Multiboot @tab Qemu
|
||||||
@item BIOS chainloading @tab no (1) @tab no (1)
|
@item BIOS chainloading @tab no (1) @tab no (1)
|
||||||
@item NTLDR @tab no (1) @tab no (1)
|
@item NTLDR @tab no (1) @tab no (1)
|
||||||
|
@item Plan9 @tab no (1) @tab no (1)
|
||||||
@item FreeDOS @tab no (1) @tab no (1)
|
@item FreeDOS @tab no (1) @tab no (1)
|
||||||
@item FreeBSD bootloader @tab crashes (1) @tab crashes (1)
|
@item FreeBSD bootloader @tab crashes (1) @tab crashes (1)
|
||||||
@item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6)
|
@item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6)
|
||||||
|
@ -3990,9 +4300,10 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
|
||||||
@end multitable
|
@end multitable
|
||||||
|
|
||||||
@multitable @columnfractions .50 .22 .22
|
@multitable @columnfractions .50 .22 .22
|
||||||
@item @tab 32-bit EFI @tab 64-bit EFI
|
@item @tab ia32 EFI @tab amd64 EFI
|
||||||
@item BIOS chainloading @tab no (1) @tab no (1)
|
@item BIOS chainloading @tab no (1) @tab no (1)
|
||||||
@item NTLDR @tab no (1) @tab no (1)
|
@item NTLDR @tab no (1) @tab no (1)
|
||||||
|
@item Plan9 @tab no (1) @tab no (1)
|
||||||
@item FreeDOS @tab no (1) @tab no (1)
|
@item FreeDOS @tab no (1) @tab no (1)
|
||||||
@item FreeBSD bootloader @tab crashes (1) @tab crashes (1)
|
@item FreeBSD bootloader @tab crashes (1) @tab crashes (1)
|
||||||
@item 32-bit kFreeBSD @tab headless @tab headless
|
@item 32-bit kFreeBSD @tab headless @tab headless
|
||||||
|
@ -4015,9 +4326,10 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
|
||||||
@end multitable
|
@end multitable
|
||||||
|
|
||||||
@multitable @columnfractions .50 .22 .22
|
@multitable @columnfractions .50 .22 .22
|
||||||
@item @tab IEEE1275
|
@item @tab ia32 IEEE1275
|
||||||
@item BIOS chainloading @tab no (1)
|
@item BIOS chainloading @tab no (1)
|
||||||
@item NTLDR @tab no (1)
|
@item NTLDR @tab no (1)
|
||||||
|
@item Plan9 @tab no (1)
|
||||||
@item FreeDOS @tab no (1)
|
@item FreeDOS @tab no (1)
|
||||||
@item FreeBSD bootloader @tab crashes (1)
|
@item FreeBSD bootloader @tab crashes (1)
|
||||||
@item 32-bit kFreeBSD @tab crashes (6)
|
@item 32-bit kFreeBSD @tab crashes (6)
|
||||||
|
@ -4048,7 +4360,8 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
|
||||||
@item Requires ACPI
|
@item Requires ACPI
|
||||||
@end enumerate
|
@end enumerate
|
||||||
|
|
||||||
PowerPC and Sparc ports support only Linux. MIPS port supports Linux and multiboot2.
|
PowerPC, IA64 and Sparc64 ports support only Linux. MIPS port supports Linux
|
||||||
|
and multiboot2.
|
||||||
|
|
||||||
@chapter Boot tests
|
@chapter Boot tests
|
||||||
|
|
||||||
|
|
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
|
129
gentpl.py
129
gentpl.py
|
@ -47,7 +47,6 @@ GROUPS["terminfomodule"] = GRUB_PLATFORMS[:];
|
||||||
for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i)
|
for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i)
|
||||||
|
|
||||||
# Miscelaneous groups schedulded to disappear in future
|
# Miscelaneous groups schedulded to disappear in future
|
||||||
GROUPS["nosparc64"] = GRUB_PLATFORMS[:]; GROUPS["nosparc64"].remove("sparc64_ieee1275")
|
|
||||||
GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"]
|
GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"]
|
||||||
GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc")
|
GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc")
|
||||||
|
|
||||||
|
@ -183,6 +182,17 @@ def foreach_platform_specific_value(platform, suffix, nonetag, closure):
|
||||||
r += "[+ ELSE +][+ FOR " + nonetag + " +]" + closure("[+ ." + nonetag + " +]") + "[+ ENDFOR +][+ ENDIF +]"
|
r += "[+ ELSE +][+ FOR " + nonetag + " +]" + closure("[+ ." + nonetag + " +]") + "[+ ENDFOR +][+ ENDIF +]"
|
||||||
return r
|
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,
|
# Template for handling values from sum of all groups for a platform,
|
||||||
# for example:
|
# for example:
|
||||||
|
@ -245,10 +255,18 @@ def foreach_enabled_platform(closure):
|
||||||
# emu_condition = COND_GRUB_EMU_USB;
|
# 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):
|
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 += snippet
|
||||||
r += foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "endif " + cond + "\n")
|
r += "[+ endif_" + platform + "_conditionals +]"
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def platform_specific_values(platform, suffix, nonetag):
|
def platform_specific_values(platform, suffix, nonetag):
|
||||||
|
@ -261,18 +279,69 @@ def platform_values(platform, suffix):
|
||||||
def extra_dist():
|
def extra_dist():
|
||||||
return foreach_value("extra_dist", lambda value: value + " ")
|
return foreach_value("extra_dist", lambda value: value + " ")
|
||||||
|
|
||||||
def platform_sources(p): return platform_values(p, "")
|
def define_macro_for_platform_sources(p):
|
||||||
def platform_nodist_sources(p): return platform_values(p, "_nodist")
|
return define_autogen_macro(
|
||||||
def platform_dependencies(p): return platform_values(p, "dependencies", "_dependencies")
|
"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")
|
# Returns Autogen code which defines the autogen macros that collect
|
||||||
def platform_cflags(p): return platform_specific_values(p, "_cflags", "cflags")
|
# platform specific values for cflags, ldflags, etc. tags.
|
||||||
def platform_ldflags(p): return platform_specific_values(p, "_ldflags", "ldflags")
|
#
|
||||||
def platform_cppflags(p): return platform_specific_values(p, "_cppflags", "cppflags")
|
def define_macro_for_platform_startup(p):
|
||||||
def platform_ccasflags(p): return platform_specific_values(p, "_ccasflags", "ccasflags")
|
return define_autogen_macro(
|
||||||
def platform_stripflags(p): return platform_specific_values(p, "_stripflags", "stripflags")
|
"get_" + p + "_startup",
|
||||||
def platform_objcopyflags(p): return platform_specific_values(p, "_objcopyflags", "objcopyflags")
|
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.
|
# Emit snippet only the first time through for the current name.
|
||||||
|
@ -489,7 +558,6 @@ def script_rules():
|
||||||
def data_rules():
|
def data_rules():
|
||||||
return rules("data", data)
|
return rules("data", data)
|
||||||
|
|
||||||
print "[+ AutoGen5 template +]\n"
|
|
||||||
a = module_rules()
|
a = module_rules()
|
||||||
b = kernel_rules()
|
b = kernel_rules()
|
||||||
c = image_rules()
|
c = image_rules()
|
||||||
|
@ -499,11 +567,28 @@ f = script_rules()
|
||||||
g = data_rules()
|
g = data_rules()
|
||||||
z = global_variable_initializers()
|
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 z # initializer for all vars
|
||||||
print a
|
print (a)
|
||||||
print b
|
print (b)
|
||||||
print c
|
print (c)
|
||||||
print d
|
print (d)
|
||||||
print e
|
print (e)
|
||||||
print f
|
print (f)
|
||||||
print g
|
print (g)
|
||||||
|
|
|
@ -78,13 +78,11 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
|
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
|
||||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
|
||||||
|
|
||||||
if COND_i386_pc
|
if COND_i386_pc
|
||||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loader.h
|
|
||||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h
|
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h
|
||||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h
|
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h
|
||||||
|
|
|
@ -18,6 +18,18 @@ script = {
|
||||||
common = modinfo.sh.in;
|
common = modinfo.sh.in;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
script = {
|
||||||
|
installdir = noinst;
|
||||||
|
name = gmodule.pl;
|
||||||
|
common = gmodule.pl.in;
|
||||||
|
};
|
||||||
|
|
||||||
|
script = {
|
||||||
|
installdir = noinst;
|
||||||
|
name = gdb_grub;
|
||||||
|
common = gdb_grub.in;
|
||||||
|
};
|
||||||
|
|
||||||
kernel = {
|
kernel = {
|
||||||
name = kernel;
|
name = kernel;
|
||||||
|
|
||||||
|
@ -34,7 +46,7 @@ kernel = {
|
||||||
ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment';
|
ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment';
|
||||||
|
|
||||||
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
|
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
|
||||||
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
|
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000';
|
||||||
|
|
||||||
i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)';
|
i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)';
|
||||||
i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
|
i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
|
||||||
|
@ -101,7 +113,7 @@ kernel = {
|
||||||
ieee1275 = kern/ieee1275/ieee1275.c;
|
ieee1275 = kern/ieee1275/ieee1275.c;
|
||||||
ieee1275 = kern/ieee1275/mmap.c;
|
ieee1275 = kern/ieee1275/mmap.c;
|
||||||
ieee1275 = kern/ieee1275/openfw.c;
|
ieee1275 = kern/ieee1275/openfw.c;
|
||||||
ieee1275 = term/ieee1275/ofconsole.c;
|
ieee1275 = term/ieee1275/console.c;
|
||||||
ieee1275 = kern/ieee1275/init.c;
|
ieee1275 = kern/ieee1275/init.c;
|
||||||
|
|
||||||
terminfoinkernel = term/terminfo.c;
|
terminfoinkernel = term/terminfo.c;
|
||||||
|
@ -356,6 +368,15 @@ image = {
|
||||||
enable = mips;
|
enable = mips;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
image = {
|
||||||
|
name = lzma_decompress;
|
||||||
|
i386_pc = boot/i386/pc/startup_raw.S;
|
||||||
|
|
||||||
|
objcopyflags = '-O binary';
|
||||||
|
ldflags = '$(TARGET_IMG_LDFLAGS) -Wl,-Ttext,0x8200';
|
||||||
|
enable = i386_pc;
|
||||||
|
};
|
||||||
|
|
||||||
image = {
|
image = {
|
||||||
name = fwstart;
|
name = fwstart;
|
||||||
mips_loongson = boot/mips/loongson/fwstart.S;
|
mips_loongson = boot/mips/loongson/fwstart.S;
|
||||||
|
@ -400,11 +421,15 @@ module = {
|
||||||
module = {
|
module = {
|
||||||
name = usb;
|
name = usb;
|
||||||
common = bus/usb/usb.c;
|
common = bus/usb/usb.c;
|
||||||
noemu = bus/usb/usbtrans.c;
|
common = bus/usb/usbtrans.c;
|
||||||
noemu = bus/usb/usbhub.c;
|
common = bus/usb/usbhub.c;
|
||||||
enable = emu;
|
|
||||||
enable = usb;
|
enable = usb;
|
||||||
emu_condition = COND_GRUB_EMU_USB;
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = emuusb;
|
||||||
|
common = bus/usb/usb.c;
|
||||||
|
condition = COND_GRUB_EMU_USB;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -445,18 +470,22 @@ module = {
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = pci;
|
name = pci;
|
||||||
noemu = bus/pci.c;
|
common = bus/pci.c;
|
||||||
emu = bus/emu/pci.c;
|
|
||||||
emu = commands/lspci.c;
|
|
||||||
|
|
||||||
enable = emu;
|
|
||||||
enable = i386_pc;
|
enable = i386_pc;
|
||||||
enable = i386_efi;
|
enable = i386_efi;
|
||||||
enable = x86_64_efi;
|
enable = x86_64_efi;
|
||||||
enable = i386_ieee1275;
|
enable = i386_ieee1275;
|
||||||
enable = i386_coreboot;
|
enable = i386_coreboot;
|
||||||
enable = i386_multiboot;
|
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 = {
|
module = {
|
||||||
|
@ -631,6 +660,20 @@ module = {
|
||||||
emu = lib/emu/halt.c;
|
emu = lib/emu/halt.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = reboot;
|
||||||
|
i386 = lib/i386/reboot.c;
|
||||||
|
i386 = lib/i386/reboot_trampoline.S;
|
||||||
|
ia64_efi = lib/efi/reboot.c;
|
||||||
|
x86_64_efi = lib/efi/reboot.c;
|
||||||
|
powerpc_ieee1275 = lib/ieee1275/reboot.c;
|
||||||
|
sparc64_ieee1275 = lib/ieee1275/reboot.c;
|
||||||
|
mips_arc = lib/mips/arc/reboot.c;
|
||||||
|
mips_loongson = lib/mips/loongson/reboot.c;
|
||||||
|
mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
|
||||||
|
common = commands/reboot.c;
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = hashsum;
|
name = hashsum;
|
||||||
common = commands/hashsum.c;
|
common = commands/hashsum.c;
|
||||||
|
@ -731,11 +774,6 @@ module = {
|
||||||
common = commands/read.c;
|
common = commands/read.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
|
||||||
name = reboot;
|
|
||||||
common = commands/reboot.c;
|
|
||||||
};
|
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = search;
|
name = search;
|
||||||
common = commands/search_wrap.c;
|
common = commands/search_wrap.c;
|
||||||
|
@ -760,7 +798,7 @@ module = {
|
||||||
module = {
|
module = {
|
||||||
name = setpci;
|
name = setpci;
|
||||||
common = commands/setpci.c;
|
common = commands/setpci.c;
|
||||||
enable = x86;
|
enable = pci;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -794,8 +832,6 @@ module = {
|
||||||
name = usbtest;
|
name = usbtest;
|
||||||
common = commands/usbtest.c;
|
common = commands/usbtest.c;
|
||||||
enable = usb;
|
enable = usb;
|
||||||
enable = emu;
|
|
||||||
emu_condition = COND_GRUB_EMU_USB;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -844,6 +880,11 @@ module = {
|
||||||
common = disk/lvm.c;
|
common = disk/lvm.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = ldm;
|
||||||
|
common = disk/ldm.c;
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = mdraid09;
|
name = mdraid09;
|
||||||
common = disk/mdraid_linux.c;
|
common = disk/mdraid_linux.c;
|
||||||
|
@ -855,8 +896,8 @@ module = {
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = raid;
|
name = diskfilter;
|
||||||
common = disk/raid.c;
|
common = disk/diskfilter.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -909,8 +950,6 @@ module = {
|
||||||
name = usbms;
|
name = usbms;
|
||||||
common = disk/usbms.c;
|
common = disk/usbms.c;
|
||||||
enable = usb;
|
enable = usb;
|
||||||
enable = emu;
|
|
||||||
emu_condition = COND_GRUB_EMU_USB;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -969,24 +1008,16 @@ module = {
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = afs_be;
|
name = bfs;
|
||||||
common = fs/afs_be.c;
|
common = fs/bfs.c;
|
||||||
};
|
|
||||||
|
|
||||||
module = {
|
|
||||||
name = befs;
|
|
||||||
common = fs/befs.c;
|
|
||||||
};
|
|
||||||
|
|
||||||
module = {
|
|
||||||
name = befs_be;
|
|
||||||
common = fs/befs_be.c;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = btrfs;
|
name = btrfs;
|
||||||
common = fs/btrfs.c;
|
common = fs/btrfs.c;
|
||||||
common = lib/crc.c;
|
common = lib/crc.c;
|
||||||
|
cflags = '$(CFLAGS_POSIX) -Wno-undef';
|
||||||
|
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -994,6 +1025,21 @@ module = {
|
||||||
common = fs/cpio.c;
|
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 = {
|
module = {
|
||||||
name = ext2;
|
name = ext2;
|
||||||
common = fs/ext2.c;
|
common = fs/ext2.c;
|
||||||
|
@ -1004,6 +1050,11 @@ module = {
|
||||||
common = fs/fat.c;
|
common = fs/fat.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = exfat;
|
||||||
|
common = fs/exfat.c;
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = fshelp;
|
name = fshelp;
|
||||||
common = fs/fshelp.c;
|
common = fs/fshelp.c;
|
||||||
|
@ -1077,6 +1128,8 @@ module = {
|
||||||
module = {
|
module = {
|
||||||
name = squash4;
|
name = squash4;
|
||||||
common = fs/squash4.c;
|
common = fs/squash4.c;
|
||||||
|
cflags = '$(CFLAGS_POSIX) -Wno-undef';
|
||||||
|
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -1112,6 +1165,11 @@ module = {
|
||||||
common = fs/zfs/zfs_fletcher.c;
|
common = fs/zfs/zfs_fletcher.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = zfscrypt;
|
||||||
|
common = fs/zfs/zfscrypt.c;
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = zfsinfo;
|
name = zfsinfo;
|
||||||
common = fs/zfs/zfsinfo.c;
|
common = fs/zfs/zfsinfo.c;
|
||||||
|
@ -1247,6 +1305,13 @@ module = {
|
||||||
enable = x86;
|
enable = x86;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = plan9;
|
||||||
|
i386_pc = loader/i386/pc/plan9.c;
|
||||||
|
enable = i386_pc;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = linux16;
|
name = linux16;
|
||||||
i386_pc = loader/i386/pc/linux.c;
|
i386_pc = loader/i386/pc/linux.c;
|
||||||
|
@ -1381,7 +1446,7 @@ module = {
|
||||||
extra_dist = script/yylex.l;
|
extra_dist = script/yylex.l;
|
||||||
extra_dist = script/parser.y;
|
extra_dist = script/parser.y;
|
||||||
|
|
||||||
cflags = '$(CFLAGS_POSIX) -Wno-error';
|
cflags = '$(CFLAGS_POSIX)';
|
||||||
cppflags = '$(CPPFLAGS_POSIX)';
|
cppflags = '$(CPPFLAGS_POSIX)';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1415,6 +1480,11 @@ module = {
|
||||||
common = partmap/sun.c;
|
common = partmap/sun.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = part_plan;
|
||||||
|
common = partmap/plan.c;
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = part_dvh;
|
name = part_dvh;
|
||||||
common = partmap/dvh.c;
|
common = partmap/dvh.c;
|
||||||
|
@ -1452,9 +1522,7 @@ module = {
|
||||||
common = term/serial.c;
|
common = term/serial.c;
|
||||||
x86 = term/ns8250.c;
|
x86 = term/ns8250.c;
|
||||||
|
|
||||||
enable = emu;
|
|
||||||
enable = x86;
|
enable = x86;
|
||||||
emu_condition = COND_GRUB_EMU_USB;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
|
@ -1602,9 +1670,13 @@ module = {
|
||||||
module = {
|
module = {
|
||||||
name = net;
|
name = net;
|
||||||
common = net/net.c;
|
common = net/net.c;
|
||||||
|
common = net/dns.c;
|
||||||
common = net/bootp.c;
|
common = net/bootp.c;
|
||||||
common = net/ip.c;
|
common = net/ip.c;
|
||||||
common = net/udp.c;
|
common = net/udp.c;
|
||||||
|
common = net/tcp.c;
|
||||||
|
common = net/icmp.c;
|
||||||
|
common = net/icmp6.c;
|
||||||
common = net/ethernet.c;
|
common = net/ethernet.c;
|
||||||
common = net/arp.c;
|
common = net/arp.c;
|
||||||
common = net/netbuff.c;
|
common = net/netbuff.c;
|
||||||
|
@ -1615,6 +1687,11 @@ module = {
|
||||||
common = net/tftp.c;
|
common = net/tftp.c;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = http;
|
||||||
|
common = net/http.c;
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = ofnet;
|
name = ofnet;
|
||||||
common = net/drivers/ieee1275/ofnet.c;
|
common = net/drivers/ieee1275/ofnet.c;
|
||||||
|
@ -1656,6 +1733,14 @@ module = {
|
||||||
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed';
|
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = lzopio;
|
||||||
|
common = io/lzopio.c;
|
||||||
|
common = lib/minilzo/minilzo.c;
|
||||||
|
cflags = '$(CFLAGS_POSIX) -Wno-undef';
|
||||||
|
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = testload;
|
name = testload;
|
||||||
common = commands/testload.c;
|
common = commands/testload.c;
|
||||||
|
@ -1673,6 +1758,11 @@ module = {
|
||||||
enable = videomodules;
|
enable = videomodules;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = priority_queue;
|
||||||
|
common = lib/priority_queue.c;
|
||||||
|
};
|
||||||
|
|
||||||
module = {
|
module = {
|
||||||
name = time;
|
name = time;
|
||||||
common = commands/time.c;
|
common = commands/time.c;
|
||||||
|
@ -1683,3 +1773,13 @@ module = {
|
||||||
common = commands/cacheinfo.c;
|
common = commands/cacheinfo.c;
|
||||||
condition = COND_ENABLE_CACHE_STATS;
|
condition = COND_ENABLE_CACHE_STATS;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = adler32;
|
||||||
|
common = lib/adler32.c;
|
||||||
|
};
|
||||||
|
|
||||||
|
module = {
|
||||||
|
name = crc64;
|
||||||
|
common = lib/crc64.c;
|
||||||
|
};
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grub/symbol.h>
|
#include <grub/symbol.h>
|
||||||
#include <grub/boot.h>
|
|
||||||
#include <grub/machine/boot.h>
|
#include <grub/machine/boot.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grub/symbol.h>
|
#include <grub/symbol.h>
|
||||||
#include <grub/boot.h>
|
|
||||||
#include <grub/machine/boot.h>
|
#include <grub/machine/boot.h>
|
||||||
#include <grub/machine/kernel.h>
|
#include <grub/machine/kernel.h>
|
||||||
#include <multiboot.h>
|
#include <multiboot.h>
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <grub/symbol.h>
|
#include <grub/symbol.h>
|
||||||
#include <grub/boot.h>
|
|
||||||
#include <grub/machine/boot.h>
|
#include <grub/machine/boot.h>
|
||||||
#include <grub/machine/kernel.h>
|
#include <grub/machine/kernel.h>
|
||||||
#include <multiboot.h>
|
#include <multiboot.h>
|
||||||
|
@ -178,20 +177,21 @@ real_code_2:
|
||||||
pushw %es
|
pushw %es
|
||||||
popw %ds
|
popw %ds
|
||||||
|
|
||||||
#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200
|
movl $0x1000, %ecx
|
||||||
movl $0x200, %ecx
|
|
||||||
addl %ecx, %esi
|
|
||||||
#else
|
|
||||||
movl $(GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4), %ecx
|
|
||||||
addl $0x200, %esi
|
addl $0x200, %esi
|
||||||
#endif
|
|
||||||
movl $DATA_ADDR, %edi
|
movl $DATA_ADDR, %edi
|
||||||
|
|
||||||
call LOCAL(move_memory)
|
call LOCAL(move_memory)
|
||||||
|
|
||||||
/* Check for multiboot signature. */
|
/* Check for multiboot signature. */
|
||||||
cmpl $MULTIBOOT_HEADER_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART)
|
movl $DATA_ADDR, %edi
|
||||||
|
3:
|
||||||
|
movl %ss:(%edi), %eax
|
||||||
|
cmpl $MULTIBOOT_HEADER_MAGIC, %eax
|
||||||
jz 1f
|
jz 1f
|
||||||
|
addl $4, %edi
|
||||||
|
cmpl $(DATA_ADDR + 0x1000), %edi
|
||||||
|
jne 3b
|
||||||
|
|
||||||
movl (ramdisk_image - start), %esi
|
movl (ramdisk_image - start), %esi
|
||||||
movl (ramdisk_size - start), %ecx
|
movl (ramdisk_size - start), %ecx
|
||||||
|
@ -200,21 +200,13 @@ real_code_2:
|
||||||
|
|
||||||
1:
|
1:
|
||||||
|
|
||||||
movl %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx
|
movl $(DATA_ADDR + 0x1000), %edi
|
||||||
#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200
|
movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx
|
||||||
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - 0x200), %ecx
|
addl $GRUB_DECOMPRESSOR_I386_PC_MAX_DECOMPRESSOR_SIZE, %ecx
|
||||||
#else
|
|
||||||
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx
|
|
||||||
#endif
|
|
||||||
|
|
||||||
2:
|
2:
|
||||||
call LOCAL(move_memory)
|
call LOCAL(move_memory)
|
||||||
|
|
||||||
movsbl %dh, %eax
|
|
||||||
movl %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART)
|
|
||||||
movsbl (reg_edx + 2 - start), %eax
|
|
||||||
movl %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART)
|
|
||||||
|
|
||||||
movb $0xFF, %dh
|
movb $0xFF, %dh
|
||||||
|
|
||||||
ljmp $(DATA_ADDR >> 4), $0
|
ljmp $(DATA_ADDR >> 4), $0
|
||||||
|
|
354
grub-core/boot/i386/pc/startup_raw.S
Normal file
354
grub-core/boot/i386/pc/startup_raw.S
Normal file
|
@ -0,0 +1,354 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
. = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH
|
||||||
|
.short (LOCAL(reed_solomon_part) - _start)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the area for all of the special variables.
|
||||||
|
*/
|
||||||
|
. = _start + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE
|
||||||
|
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) - LOCAL(reed_solomon_part)), %edx
|
||||||
|
movl reed_solomon_redundancy, %ecx
|
||||||
|
leal LOCAL(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
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
LOCAL(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
|
||||||
|
|
||||||
|
#ifdef ENABLE_LZMA
|
||||||
|
#include "lzma_decode.S"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.p2align 4
|
||||||
|
|
||||||
|
LOCAL(decompressor_end):
|
|
@ -38,13 +38,13 @@ start:
|
||||||
bal codestart
|
bal codestart
|
||||||
nop
|
nop
|
||||||
base:
|
base:
|
||||||
. = _start + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE
|
. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
|
||||||
compressed_size:
|
compressed_size:
|
||||||
.long 0
|
.long 0
|
||||||
. = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE
|
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
|
||||||
uncompressed_size:
|
uncompressed_size:
|
||||||
.long 0
|
.long 0
|
||||||
. = _start + GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR
|
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR
|
||||||
uncompressed_addr:
|
uncompressed_addr:
|
||||||
.long 0
|
.long 0
|
||||||
codestart:
|
codestart:
|
||||||
|
@ -240,9 +240,9 @@ cmdlinedone:
|
||||||
subu $a0, $a0, $t0
|
subu $a0, $a0, $t0
|
||||||
addu $a0, $a0, $s0
|
addu $a0, $a0, $s0
|
||||||
|
|
||||||
lw $a1, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0)
|
lw $a1, (GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0)
|
||||||
lw $a2, (GRUB_KERNEL_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0)
|
lw $a2, (GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0)
|
||||||
lw $a3, (GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0)
|
lw $a3, (GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0)
|
||||||
move $s1, $a1
|
move $s1, $a1
|
||||||
|
|
||||||
/* $a0 contains source compressed address, $a1 is destination,
|
/* $a0 contains source compressed address, $a1 is destination,
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grub/boot.h>
|
|
||||||
#include <grub/machine/boot.h>
|
#include <grub/machine/boot.h>
|
||||||
|
|
||||||
.text
|
.text
|
||||||
|
@ -29,9 +28,6 @@ pic_base:
|
||||||
call boot_continue
|
call boot_continue
|
||||||
mov %o4, CIF_REG
|
mov %o4, CIF_REG
|
||||||
|
|
||||||
. = _start + GRUB_BOOT_MACHINE_VER_MAJ
|
|
||||||
boot_version: .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
|
|
||||||
|
|
||||||
/* The offsets to these locations are defined by the
|
/* The offsets to these locations are defined by the
|
||||||
* GRUB_BOOT_MACHINE_foo macros in include/grub/sparc/ieee1275/boot.h,
|
* GRUB_BOOT_MACHINE_foo macros in include/grub/sparc/ieee1275/boot.h,
|
||||||
* and grub-setup uses this to patch these next three values as needed.
|
* and grub-setup uses this to patch these next three values as needed.
|
||||||
|
@ -44,6 +40,7 @@ boot_version: .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
|
||||||
* After loading in that block we will execute it by jumping to the
|
* After loading in that block we will execute it by jumping to the
|
||||||
* load address plus the size of the prepended A.OUT header (32 bytes).
|
* load address plus the size of the prepended A.OUT header (32 bytes).
|
||||||
*/
|
*/
|
||||||
|
. = _start + GRUB_BOOT_MACHINE_BOOT_DEVPATH
|
||||||
boot_path:
|
boot_path:
|
||||||
. = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE
|
. = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE
|
||||||
boot_path_end:
|
boot_path_end:
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grub/boot.h>
|
|
||||||
#include <grub/machine/boot.h>
|
#include <grub/machine/boot.h>
|
||||||
#include <grub/offsets.h>
|
#include <grub/offsets.h>
|
||||||
|
|
||||||
|
|
|
@ -97,8 +97,6 @@ grub_cs5536_smbus_wait (grub_port_t smbbase)
|
||||||
if (grub_get_time_ms () > start + 40)
|
if (grub_get_time_ms () > start + 40)
|
||||||
return grub_error (GRUB_ERR_IO, "SM stalled");
|
return grub_error (GRUB_ERR_IO, "SM stalled");
|
||||||
}
|
}
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
|
|
|
@ -1152,8 +1152,8 @@ grub_ohci_check_transfer (grub_usb_controller_t dev,
|
||||||
return parse_halt (dev, transfer, actual);
|
return parse_halt (dev, transfer, actual);
|
||||||
|
|
||||||
/* Finished ED detection */
|
/* Finished ED detection */
|
||||||
if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf) ==
|
if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xfU) ==
|
||||||
(grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf) ) /* Empty ED */
|
(grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xfU) ) /* Empty ED */
|
||||||
{
|
{
|
||||||
/* Check the HALT bit */
|
/* Check the HALT bit */
|
||||||
/* It looks like nonsense - it was tested previously...
|
/* It looks like nonsense - it was tested previously...
|
||||||
|
@ -1426,7 +1426,7 @@ static struct grub_usb_controller_dev usb_controller =
|
||||||
.detect_dev = grub_ohci_detect_dev
|
.detect_dev = grub_ohci_detect_dev
|
||||||
};
|
};
|
||||||
|
|
||||||
static void *fini_hnd;
|
static struct grub_preboot *fini_hnd;
|
||||||
|
|
||||||
GRUB_MOD_INIT(ohci)
|
GRUB_MOD_INIT(ohci)
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,11 +36,33 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
GRUB_UHCI_REG_USBCMD = 0x00,
|
GRUB_UHCI_REG_USBCMD = 0x00,
|
||||||
|
GRUB_UHCI_REG_USBINTR = 0x04,
|
||||||
GRUB_UHCI_REG_FLBASEADD = 0x08,
|
GRUB_UHCI_REG_FLBASEADD = 0x08,
|
||||||
GRUB_UHCI_REG_PORTSC1 = 0x10,
|
GRUB_UHCI_REG_PORTSC1 = 0x10,
|
||||||
GRUB_UHCI_REG_PORTSC2 = 0x12
|
GRUB_UHCI_REG_PORTSC2 = 0x12,
|
||||||
|
GRUB_UHCI_REG_USBLEGSUP = 0xc0
|
||||||
} grub_uhci_reg_t;
|
} 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_TERMINATE 1
|
||||||
#define GRUB_UHCI_LINK_QUEUE_HEAD 2
|
#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)
|
if (class != 0x0c || subclass != 0x03 || interf != 0x00)
|
||||||
return 0;
|
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. */
|
/* Determine IO base address. */
|
||||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG4);
|
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG4);
|
||||||
base = grub_pci_read (addr);
|
base = grub_pci_read (addr);
|
||||||
|
@ -195,6 +222,19 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
||||||
|
|
||||||
u->iobase = base & GRUB_UHCI_IOMASK;
|
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. */
|
/* Reserve a page for the frame list. */
|
||||||
u->framelist = grub_memalign (4096, 4096);
|
u->framelist = grub_memalign (4096, 4096);
|
||||||
if (! u->framelist)
|
if (! u->framelist)
|
||||||
|
@ -252,9 +292,6 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
||||||
u->td[N_TD - 2].linkptr = 0;
|
u->td[N_TD - 2].linkptr = 0;
|
||||||
u->tdfree = u->td;
|
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
|
/* Setup the frame list pointers. Since no isochronous transfers
|
||||||
are and will be supported, they all point to the (same!) queue
|
are and will be supported, they all point to the (same!) queue
|
||||||
head. */
|
head. */
|
||||||
|
@ -285,7 +322,8 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
||||||
u->qh[N_QH - 1].linkptr = 1;
|
u->qh[N_QH - 1].linkptr = 1;
|
||||||
|
|
||||||
/* Enable UHCI again. */
|
/* 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. */
|
/* UHCI is initialized and ready for transfers. */
|
||||||
grub_dprintf ("uhci", "UHCI initialized\n");
|
grub_dprintf ("uhci", "UHCI initialized\n");
|
||||||
|
@ -506,8 +544,11 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev,
|
||||||
{
|
{
|
||||||
grub_size_t actual = 0;
|
grub_size_t actual = 0;
|
||||||
/* Terminate and free. */
|
/* Terminate and free. */
|
||||||
|
if (td_prev)
|
||||||
|
{
|
||||||
td_prev->linkptr2 = 0;
|
td_prev->linkptr2 = 0;
|
||||||
td_prev->linkptr = 1;
|
td_prev->linkptr = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (cdata->td_first)
|
if (cdata->td_first)
|
||||||
grub_free_queue (u, cdata->qh, cdata->td_first, NULL, &actual);
|
grub_free_queue (u, cdata->qh, cdata->td_first, NULL, &actual);
|
||||||
|
|
|
@ -340,7 +340,7 @@ grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc)
|
||||||
void
|
void
|
||||||
grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc)
|
grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc)
|
||||||
{
|
{
|
||||||
grub_list_remove (GRUB_AS_LIST_P (&attach_hooks), GRUB_AS_LIST (desc));
|
grub_list_remove (GRUB_AS_LIST (desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -167,11 +167,13 @@ grub_usb_add_hub (grub_usb_device_t dev)
|
||||||
if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp)
|
if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp)
|
||||||
== GRUB_USB_EP_INTERRUPT)
|
== GRUB_USB_EP_INTERRUPT)
|
||||||
{
|
{
|
||||||
|
grub_size_t len;
|
||||||
dev->hub_endpoint = endp;
|
dev->hub_endpoint = endp;
|
||||||
|
len = endp->maxpacket;
|
||||||
|
if (len > sizeof (dev->statuschange))
|
||||||
|
len = sizeof (dev->statuschange);
|
||||||
dev->hub_transfer
|
dev->hub_transfer
|
||||||
= grub_usb_bulk_read_background (dev, endp->endp_addr,
|
= grub_usb_bulk_read_background (dev, endp->endp_addr, len,
|
||||||
grub_min (endp->maxpacket,
|
|
||||||
sizeof (dev->statuschange)),
|
|
||||||
(char *) &dev->statuschange);
|
(char *) &dev->statuschange);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -323,7 +325,7 @@ poll_nonroot_hub (grub_usb_device_t dev)
|
||||||
grub_usb_err_t err;
|
grub_usb_err_t err;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
grub_uint8_t changed;
|
grub_uint8_t changed;
|
||||||
grub_size_t actual;
|
grub_size_t actual, len;
|
||||||
int j, total;
|
int j, total;
|
||||||
|
|
||||||
if (!dev->hub_transfer)
|
if (!dev->hub_transfer)
|
||||||
|
@ -336,10 +338,11 @@ poll_nonroot_hub (grub_usb_device_t dev)
|
||||||
|
|
||||||
changed = dev->statuschange;
|
changed = dev->statuschange;
|
||||||
|
|
||||||
|
len = dev->hub_endpoint->maxpacket;
|
||||||
|
if (len > sizeof (dev->statuschange))
|
||||||
|
len = sizeof (dev->statuschange);
|
||||||
dev->hub_transfer
|
dev->hub_transfer
|
||||||
= grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr,
|
= grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr, len,
|
||||||
grub_min (dev->hub_endpoint->maxpacket,
|
|
||||||
sizeof (dev->statuschange)),
|
|
||||||
(char *) &dev->statuschange);
|
(char *) &dev->statuschange);
|
||||||
|
|
||||||
if (err || actual == 0 || changed == 0)
|
if (err || actual == 0 || changed == 0)
|
||||||
|
|
|
@ -138,6 +138,7 @@ iszero (grub_uint8_t *reg, int size)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined (__i386__) || defined (__x86_64__)
|
||||||
grub_err_t
|
grub_err_t
|
||||||
grub_acpi_create_ebda (void)
|
grub_acpi_create_ebda (void)
|
||||||
{
|
{
|
||||||
|
@ -165,7 +166,7 @@ grub_acpi_create_ebda (void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ebda = (grub_uint8_t *) UINT_TO_PTR ((*((grub_uint16_t *)0x40e)) << 4);
|
ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4);
|
||||||
ebda_kb_len = *(grub_uint16_t *) ebda;
|
ebda_kb_len = *(grub_uint16_t *) ebda;
|
||||||
if (! ebda || ebda_kb_len > 16)
|
if (! ebda || ebda_kb_len > 16)
|
||||||
ebda_kb_len = 0;
|
ebda_kb_len = 0;
|
||||||
|
@ -173,14 +174,14 @@ grub_acpi_create_ebda (void)
|
||||||
|
|
||||||
/* FIXME: use low-memory mm allocation once it's available. */
|
/* FIXME: use low-memory mm allocation once it's available. */
|
||||||
grub_mmap_iterate (find_hook);
|
grub_mmap_iterate (find_hook);
|
||||||
targetebda = (grub_uint8_t *) UINT_TO_PTR (highestlow);
|
targetebda = (grub_uint8_t *) (grub_addr_t) highestlow;
|
||||||
grub_dprintf ("acpi", "creating ebda @%llx\n",
|
grub_dprintf ("acpi", "creating ebda @%llx\n",
|
||||||
(unsigned long long) highestlow);
|
(unsigned long long) highestlow);
|
||||||
if (! highestlow)
|
if (! highestlow)
|
||||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||||
"couldn't find space for the new EBDA");
|
"couldn't find space for the new EBDA");
|
||||||
|
|
||||||
mmapregion = grub_mmap_register (PTR_TO_UINT64 (targetebda), ebda_len,
|
mmapregion = grub_mmap_register ((grub_addr_t) targetebda, ebda_len,
|
||||||
GRUB_MEMORY_RESERVED);
|
GRUB_MEMORY_RESERVED);
|
||||||
if (! mmapregion)
|
if (! mmapregion)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
@ -297,6 +298,7 @@ grub_acpi_create_ebda (void)
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Create tables common to ACPIv1 and ACPIv2+ */
|
/* Create tables common to ACPIv1 and ACPIv2+ */
|
||||||
static void
|
static void
|
||||||
|
@ -328,13 +330,13 @@ setup_common_tables (void)
|
||||||
if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE,
|
if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE,
|
||||||
sizeof (fadt->hdr.signature)) == 0)
|
sizeof (fadt->hdr.signature)) == 0)
|
||||||
{
|
{
|
||||||
fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt);
|
fadt->dsdt_addr = (grub_addr_t) table_dsdt;
|
||||||
fadt->facs_addr = facs_addr;
|
fadt->facs_addr = facs_addr;
|
||||||
|
|
||||||
/* Does a revision 2 exist at all? */
|
/* Does a revision 2 exist at all? */
|
||||||
if (fadt->hdr.revision >= 3)
|
if (fadt->hdr.revision >= 3)
|
||||||
{
|
{
|
||||||
fadt->dsdt_xaddr = PTR_TO_UINT64 (table_dsdt);
|
fadt->dsdt_xaddr = (grub_addr_t) table_dsdt;
|
||||||
fadt->facs_xaddr = facs_addr;
|
fadt->facs_xaddr = facs_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +367,7 @@ setup_common_tables (void)
|
||||||
rsdt->creator_rev = root_creator_rev;
|
rsdt->creator_rev = root_creator_rev;
|
||||||
|
|
||||||
for (cur = acpi_tables; cur; cur = cur->next)
|
for (cur = acpi_tables; cur; cur = cur->next)
|
||||||
*(rsdt_entry++) = PTR_TO_UINT32 (cur->addr);
|
*(rsdt_entry++) = (grub_addr_t) cur->addr;
|
||||||
|
|
||||||
/* Recompute checksum. */
|
/* Recompute checksum. */
|
||||||
rsdt->checksum = 0;
|
rsdt->checksum = 0;
|
||||||
|
@ -383,7 +385,7 @@ setv1table (void)
|
||||||
sizeof (rsdpv1_new->signature));
|
sizeof (rsdpv1_new->signature));
|
||||||
grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid));
|
grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid));
|
||||||
rsdpv1_new->revision = 0;
|
rsdpv1_new->revision = 0;
|
||||||
rsdpv1_new->rsdt_addr = PTR_TO_UINT32 (rsdt_addr);
|
rsdpv1_new->rsdt_addr = (grub_addr_t) rsdt_addr;
|
||||||
rsdpv1_new->checksum = 0;
|
rsdpv1_new->checksum = 0;
|
||||||
rsdpv1_new->checksum = 1 + ~grub_byte_checksum (rsdpv1_new,
|
rsdpv1_new->checksum = 1 + ~grub_byte_checksum (rsdpv1_new,
|
||||||
sizeof (*rsdpv1_new));
|
sizeof (*rsdpv1_new));
|
||||||
|
@ -408,7 +410,7 @@ setv2table (void)
|
||||||
|
|
||||||
xsdt_entry = (grub_uint64_t *)(xsdt + 1);
|
xsdt_entry = (grub_uint64_t *)(xsdt + 1);
|
||||||
for (cur = acpi_tables; cur; cur = cur->next)
|
for (cur = acpi_tables; cur; cur = cur->next)
|
||||||
*(xsdt_entry++) = PTR_TO_UINT64 (cur->addr);
|
*(xsdt_entry++) = (grub_addr_t) cur->addr;
|
||||||
grub_memcpy (&(xsdt->signature), "XSDT", 4);
|
grub_memcpy (&(xsdt->signature), "XSDT", 4);
|
||||||
xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables;
|
xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables;
|
||||||
xsdt->revision = 1;
|
xsdt->revision = 1;
|
||||||
|
@ -428,12 +430,12 @@ setv2table (void)
|
||||||
grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid,
|
grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid,
|
||||||
sizeof (rsdpv2_new->rsdpv1.oemid));
|
sizeof (rsdpv2_new->rsdpv1.oemid));
|
||||||
rsdpv2_new->rsdpv1.revision = rev2;
|
rsdpv2_new->rsdpv1.revision = rev2;
|
||||||
rsdpv2_new->rsdpv1.rsdt_addr = PTR_TO_UINT32 (rsdt_addr);
|
rsdpv2_new->rsdpv1.rsdt_addr = (grub_addr_t) rsdt_addr;
|
||||||
rsdpv2_new->rsdpv1.checksum = 0;
|
rsdpv2_new->rsdpv1.checksum = 0;
|
||||||
rsdpv2_new->rsdpv1.checksum = 1 + ~grub_byte_checksum
|
rsdpv2_new->rsdpv1.checksum = 1 + ~grub_byte_checksum
|
||||||
(&(rsdpv2_new->rsdpv1), sizeof (rsdpv2_new->rsdpv1));
|
(&(rsdpv2_new->rsdpv1), sizeof (rsdpv2_new->rsdpv1));
|
||||||
rsdpv2_new->length = sizeof (*rsdpv2_new);
|
rsdpv2_new->length = sizeof (*rsdpv2_new);
|
||||||
rsdpv2_new->xsdt_addr = PTR_TO_UINT64 (xsdt);
|
rsdpv2_new->xsdt_addr = (grub_addr_t) xsdt;
|
||||||
rsdpv2_new->checksum = 0;
|
rsdpv2_new->checksum = 0;
|
||||||
rsdpv2_new->checksum = 1 + ~grub_byte_checksum (rsdpv2_new,
|
rsdpv2_new->checksum = 1 + ~grub_byte_checksum (rsdpv2_new,
|
||||||
rsdpv2_new->length);
|
rsdpv2_new->length);
|
||||||
|
@ -463,7 +465,6 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||||
struct grub_arg_list *state = ctxt->state;
|
struct grub_arg_list *state = ctxt->state;
|
||||||
struct grub_acpi_rsdp_v10 *rsdp;
|
struct grub_acpi_rsdp_v10 *rsdp;
|
||||||
struct efiemu_acpi_table *cur, *t;
|
struct efiemu_acpi_table *cur, *t;
|
||||||
grub_err_t err;
|
|
||||||
int i, mmapregion;
|
int i, mmapregion;
|
||||||
int numoftables;
|
int numoftables;
|
||||||
|
|
||||||
|
@ -506,7 +507,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||||
/* Set revision variables to replicate the same version as host. */
|
/* Set revision variables to replicate the same version as host. */
|
||||||
rev1 = ! rsdp->revision;
|
rev1 = ! rsdp->revision;
|
||||||
rev2 = rsdp->revision;
|
rev2 = rsdp->revision;
|
||||||
rsdt = (struct grub_acpi_table_header *) UINT_TO_PTR (rsdp->rsdt_addr);
|
rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr;
|
||||||
/* Load host tables. */
|
/* Load host tables. */
|
||||||
for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
|
for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
|
||||||
entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
|
entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
|
||||||
|
@ -516,7 +517,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||||
char signature[5];
|
char signature[5];
|
||||||
struct efiemu_acpi_table *table;
|
struct efiemu_acpi_table *table;
|
||||||
struct grub_acpi_table_header *curtable
|
struct grub_acpi_table_header *curtable
|
||||||
= (struct grub_acpi_table_header *) UINT_TO_PTR (*entry_ptr);
|
= (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr;
|
||||||
signature[4] = 0;
|
signature[4] = 0;
|
||||||
for (i = 0; i < 4;i++)
|
for (i = 0; i < 4;i++)
|
||||||
signature[i] = grub_tolower (curtable->signature[i]);
|
signature[i] = grub_tolower (curtable->signature[i]);
|
||||||
|
@ -540,7 +541,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||||
|
|
||||||
/* Load DSDT if not excluded. */
|
/* Load DSDT if not excluded. */
|
||||||
dsdt = (struct grub_acpi_table_header *)
|
dsdt = (struct grub_acpi_table_header *)
|
||||||
UINT_TO_PTR (fadt->dsdt_addr);
|
(grub_addr_t) fadt->dsdt_addr;
|
||||||
if (dsdt && (! exclude || ! grub_strword (exclude, "dsdt"))
|
if (dsdt && (! exclude || ! grub_strword (exclude, "dsdt"))
|
||||||
&& (! load_only || grub_strword (load_only, "dsdt"))
|
&& (! load_only || grub_strword (load_only, "dsdt"))
|
||||||
&& dsdt->length >= sizeof (*dsdt))
|
&& dsdt->length >= sizeof (*dsdt))
|
||||||
|
@ -648,15 +649,17 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||||
{
|
{
|
||||||
grub_file_close (file);
|
grub_file_close (file);
|
||||||
free_tables ();
|
free_tables ();
|
||||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
return grub_errno;
|
||||||
"couldn't read file %s", args[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (grub_file_read (file, buf, size) != (int) size)
|
if (grub_file_read (file, buf, size) != (int) size)
|
||||||
{
|
{
|
||||||
grub_file_close (file);
|
grub_file_close (file);
|
||||||
free_tables ();
|
free_tables ();
|
||||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[i]);
|
if (!grub_errno)
|
||||||
|
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||||
|
args[i]);
|
||||||
|
return grub_errno;
|
||||||
}
|
}
|
||||||
grub_file_close (file);
|
grub_file_close (file);
|
||||||
|
|
||||||
|
@ -732,13 +735,20 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
||||||
}
|
}
|
||||||
acpi_tables = 0;
|
acpi_tables = 0;
|
||||||
|
|
||||||
if (! state[9].set && (err = grub_acpi_create_ebda ()))
|
#if defined (__i386__) || defined (__x86_64__)
|
||||||
|
if (! state[9].set)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
err = grub_acpi_create_ebda ();
|
||||||
|
if (err)
|
||||||
{
|
{
|
||||||
rsdpv1_new = 0;
|
rsdpv1_new = 0;
|
||||||
rsdpv2_new = 0;
|
rsdpv2_new = 0;
|
||||||
grub_mmap_free_and_unregister (mmapregion);
|
grub_mmap_free_and_unregister (mmapregion);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef GRUB_MACHINE_EFI
|
#ifdef GRUB_MACHINE_EFI
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,6 +33,7 @@ typedef uint8_t grub_uint8_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <grub/acpi.h>
|
#include <grub/acpi.h>
|
||||||
|
#include <grub/i18n.h>
|
||||||
|
|
||||||
#ifndef GRUB_DSDT_TEST
|
#ifndef GRUB_DSDT_TEST
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
|
@ -327,6 +328,6 @@ grub_acpi_halt (void)
|
||||||
|
|
||||||
grub_millisleep (1500);
|
grub_millisleep (1500);
|
||||||
|
|
||||||
grub_printf ("ACPI shutdown failed\n");
|
grub_puts_ (N_("ACPI shutdown failed"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -31,17 +31,17 @@ static grub_err_t (*grub_loader_boot_func) (void);
|
||||||
static grub_err_t (*grub_loader_unload_func) (void);
|
static grub_err_t (*grub_loader_unload_func) (void);
|
||||||
static int grub_loader_noreturn;
|
static int grub_loader_noreturn;
|
||||||
|
|
||||||
struct grub_preboot_t
|
struct grub_preboot
|
||||||
{
|
{
|
||||||
grub_err_t (*preboot_func) (int);
|
grub_err_t (*preboot_func) (int);
|
||||||
grub_err_t (*preboot_rest_func) (void);
|
grub_err_t (*preboot_rest_func) (void);
|
||||||
grub_loader_preboot_hook_prio_t prio;
|
grub_loader_preboot_hook_prio_t prio;
|
||||||
struct grub_preboot_t *next;
|
struct grub_preboot *next;
|
||||||
struct grub_preboot_t *prev;
|
struct grub_preboot *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int grub_loader_loaded;
|
static int grub_loader_loaded;
|
||||||
static struct grub_preboot_t *preboots_head = 0,
|
static struct grub_preboot *preboots_head = 0,
|
||||||
*preboots_tail = 0;
|
*preboots_tail = 0;
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -51,18 +51,18 @@ grub_loader_is_loaded (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register a preboot hook. */
|
/* Register a preboot hook. */
|
||||||
void *
|
struct grub_preboot *
|
||||||
grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
|
grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
|
||||||
grub_err_t (*preboot_rest_func) (void),
|
grub_err_t (*preboot_rest_func) (void),
|
||||||
grub_loader_preboot_hook_prio_t prio)
|
grub_loader_preboot_hook_prio_t prio)
|
||||||
{
|
{
|
||||||
struct grub_preboot_t *cur, *new_preboot;
|
struct grub_preboot *cur, *new_preboot;
|
||||||
|
|
||||||
if (! preboot_func && ! preboot_rest_func)
|
if (! preboot_func && ! preboot_rest_func)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
new_preboot = (struct grub_preboot_t *)
|
new_preboot = (struct grub_preboot *)
|
||||||
grub_malloc (sizeof (struct grub_preboot_t));
|
grub_malloc (sizeof (struct grub_preboot));
|
||||||
if (! new_preboot)
|
if (! new_preboot)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, "hook not added");
|
grub_error (GRUB_ERR_OUT_OF_MEMORY, "hook not added");
|
||||||
|
@ -96,9 +96,9 @@ grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_loader_unregister_preboot_hook (void *hnd)
|
grub_loader_unregister_preboot_hook (struct grub_preboot *hnd)
|
||||||
{
|
{
|
||||||
struct grub_preboot_t *preb = hnd;
|
struct grub_preboot *preb = hnd;
|
||||||
|
|
||||||
if (preb->next)
|
if (preb->next)
|
||||||
preb->next->prev = preb->prev;
|
preb->next->prev = preb->prev;
|
||||||
|
@ -143,7 +143,7 @@ grub_err_t
|
||||||
grub_loader_boot (void)
|
grub_loader_boot (void)
|
||||||
{
|
{
|
||||||
grub_err_t err = GRUB_ERR_NONE;
|
grub_err_t err = GRUB_ERR_NONE;
|
||||||
struct grub_preboot_t *cur;
|
struct grub_preboot *cur;
|
||||||
|
|
||||||
if (! grub_loader_loaded)
|
if (! grub_loader_loaded)
|
||||||
return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel");
|
return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel");
|
||||||
|
|
|
@ -31,14 +31,14 @@ grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)),
|
||||||
unsigned long hits, misses;
|
unsigned long hits, misses;
|
||||||
|
|
||||||
grub_disk_cache_get_performance (&hits, &misses);
|
grub_disk_cache_get_performance (&hits, &misses);
|
||||||
grub_printf ("Disk cache: hits = %lu, misses = %lu ", hits, misses);
|
grub_printf_ (N_("Disk cache: hits = %lu, misses = %lu "), hits, misses);
|
||||||
if (hits + misses)
|
if (hits + misses)
|
||||||
{
|
{
|
||||||
unsigned long ratio = hits * 10000 / (hits + misses);
|
unsigned long ratio = hits * 10000 / (hits + misses);
|
||||||
grub_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100);
|
grub_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
grub_printf ("(N/A)\n");
|
grub_puts_ (N_("(N/A)"));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
|
||||||
if (argc != 2)
|
if (argc != 2)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");
|
||||||
|
|
||||||
grub_printf ("Compare file `%s' with `%s':\n", args[0],
|
grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0],
|
||||||
args[1]);
|
args[1]);
|
||||||
|
|
||||||
file1 = grub_file_open (args[0]);
|
file1 = grub_file_open (args[0]);
|
||||||
|
@ -51,7 +51,7 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (grub_file_size (file1) != grub_file_size (file2))
|
if (grub_file_size (file1) != grub_file_size (file2))
|
||||||
grub_printf ("Files differ in size: %llu [%s], %llu [%s]\n",
|
grub_printf_ (N_("Files differ in size: %llu [%s], %llu [%s]\n"),
|
||||||
(unsigned long long) grub_file_size (file1), args[0],
|
(unsigned long long) grub_file_size (file1), args[0],
|
||||||
(unsigned long long) grub_file_size (file2), args[1]);
|
(unsigned long long) grub_file_size (file2), args[1]);
|
||||||
else
|
else
|
||||||
|
@ -78,9 +78,9 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
|
||||||
{
|
{
|
||||||
if (buf1[i] != buf2[i])
|
if (buf1[i] != buf2[i])
|
||||||
{
|
{
|
||||||
grub_printf ("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n",
|
grub_printf_ (N_("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n"),
|
||||||
(unsigned long long) (i + pos), buf1[i], args[0],
|
(unsigned long long) (i + pos), buf1[i],
|
||||||
buf2[i], args[1]);
|
args[0], buf2[i], args[1]);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
|
||||||
}
|
}
|
||||||
while (rd2);
|
while (rd2);
|
||||||
|
|
||||||
grub_printf ("The files are identical.\n");
|
/* TRANSLATORS: it's always exactly 2 files. */
|
||||||
|
grub_printf_ (N_("The files are identical.\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
|
@ -56,24 +56,24 @@ scan_card (grub_pci_device_t dev, grub_pci_id_t pciid)
|
||||||
{
|
{
|
||||||
grub_target_addr_t base;
|
grub_target_addr_t base;
|
||||||
|
|
||||||
grub_printf ("Found graphic card: %s\n", p->name);
|
grub_dprintf ("fixvideo", "Found graphic card: %s\n", p->name);
|
||||||
addr += 8 + p->mmio_bar * 4;
|
addr += 8 + p->mmio_bar * 4;
|
||||||
base = grub_pci_read (addr);
|
base = grub_pci_read (addr);
|
||||||
if ((! base) || (base & GRUB_PCI_ADDR_SPACE_IO) ||
|
if ((! base) || (base & GRUB_PCI_ADDR_SPACE_IO) ||
|
||||||
(base & GRUB_PCI_ADDR_MEM_PREFETCH))
|
(base & GRUB_PCI_ADDR_MEM_PREFETCH))
|
||||||
grub_printf ("Invalid MMIO bar %d\n", p->mmio_bar);
|
grub_dprintf ("fixvideo", "Invalid MMIO bar %d\n", p->mmio_bar);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
base &= GRUB_PCI_ADDR_MEM_MASK;
|
base &= GRUB_PCI_ADDR_MEM_MASK;
|
||||||
base += p->mmio_reg;
|
base += p->mmio_reg;
|
||||||
|
|
||||||
if (*((volatile grub_uint32_t *) base) != p->mmio_old)
|
if (*((volatile grub_uint32_t *) base) != p->mmio_old)
|
||||||
grub_printf ("Old value don't match\n");
|
grub_dprintf ("fixvideo", "Old value doesn't match\n");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*((volatile grub_uint32_t *) base) = 0;
|
*((volatile grub_uint32_t *) base) = 0;
|
||||||
if (*((volatile grub_uint32_t *) base))
|
if (*((volatile grub_uint32_t *) base))
|
||||||
grub_printf ("Set MMIO fails\n");
|
grub_dprintf ("fixvideo", "Setting MMIO fails\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ scan_card (grub_pci_device_t dev, grub_pci_id_t pciid)
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_printf ("Unknown graphic card: %x\n", pciid);
|
grub_dprintf ("fixvideo", "Unknown graphic card: %x\n", pciid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -49,7 +49,7 @@ enable_rom_area (void)
|
||||||
rom_ptr = (grub_uint32_t *) VBIOS_ADDR;
|
rom_ptr = (grub_uint32_t *) VBIOS_ADDR;
|
||||||
if (*rom_ptr != BLANK_MEM)
|
if (*rom_ptr != BLANK_MEM)
|
||||||
{
|
{
|
||||||
grub_printf ("ROM image is present.\n");
|
grub_puts_ (N_("ROM image is present."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ enable_rom_area (void)
|
||||||
*rom_ptr = 0;
|
*rom_ptr = 0;
|
||||||
if (*rom_ptr != 0)
|
if (*rom_ptr != 0)
|
||||||
{
|
{
|
||||||
grub_printf ("Can\'t enable ROM area.\n");
|
grub_puts_ (N_("Can\'t enable ROM area."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ GRUB_MOD_INIT(loadbios)
|
||||||
0, N_("Fake BIOS."));
|
0, N_("Fake BIOS."));
|
||||||
|
|
||||||
cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
|
cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
|
||||||
"BIOS_DUMP [INT10_DUMP]",
|
N_("BIOS_DUMP [INT10_DUMP]"),
|
||||||
N_("Load BIOS dump."));
|
N_("Load BIOS dump."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -231,7 +231,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_printf ("New MBR is written to '%s'\n", args[0]);
|
grub_printf_ (N_("New MBR is written to '%s'\n"), args[0]);
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,12 @@
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t __attribute__ ((noreturn))
|
||||||
grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)),
|
grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)),
|
||||||
int argc __attribute__ ((unused)),
|
int argc __attribute__ ((unused)),
|
||||||
char **args __attribute__ ((unused)))
|
char **args __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
grub_halt ();
|
grub_halt ();
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_command_t cmd;
|
static grub_command_t cmd;
|
||||||
|
|
|
@ -141,7 +141,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
|
||||||
grub_file_close (file);
|
grub_file_close (file);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_printf ("%s: READ ERROR\n", p);
|
grub_printf_ (N_("%s: READ ERROR\n"), p);
|
||||||
if (!keep)
|
if (!keep)
|
||||||
{
|
{
|
||||||
grub_file_close (hashlist);
|
grub_file_close (hashlist);
|
||||||
|
@ -155,7 +155,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
|
||||||
}
|
}
|
||||||
if (grub_crypto_memcmp (expected, actual, hash->mdlen) != 0)
|
if (grub_crypto_memcmp (expected, actual, hash->mdlen) != 0)
|
||||||
{
|
{
|
||||||
grub_printf ("%s: HASH MISMATCH\n", p);
|
grub_printf_ (N_("%s: HASH MISMATCH\n"), p);
|
||||||
if (!keep)
|
if (!keep)
|
||||||
{
|
{
|
||||||
grub_file_close (hashlist);
|
grub_file_close (hashlist);
|
||||||
|
@ -166,7 +166,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
|
||||||
mismatch++;
|
mismatch++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
grub_printf ("%s: OK\n", p);
|
grub_printf_ (N_("%s: OK\n"), p);
|
||||||
}
|
}
|
||||||
if (mismatch || unread)
|
if (mismatch || unread)
|
||||||
return grub_error (GRUB_ERR_TEST_FAILURE,
|
return grub_error (GRUB_ERR_TEST_FAILURE,
|
||||||
|
@ -257,8 +257,8 @@ static grub_extcmd_t cmd, cmd_md5, cmd_sha1, cmd_sha256, cmd_sha512, cmd_crc;
|
||||||
GRUB_MOD_INIT(hashsum)
|
GRUB_MOD_INIT(hashsum)
|
||||||
{
|
{
|
||||||
cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0,
|
cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0,
|
||||||
"hashsum -h HASH [-c FILE [-p PREFIX]] "
|
N_("-h HASH [-c FILE [-p PREFIX]] "
|
||||||
"[FILE1 [FILE2 ...]]",
|
"[FILE1 [FILE2 ...]]"),
|
||||||
N_("Compute or check hash checksum."),
|
N_("Compute or check hash checksum."),
|
||||||
options);
|
options);
|
||||||
cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, 0,
|
cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, 0,
|
||||||
|
|
|
@ -165,22 +165,20 @@ grub_hdparm_set_val_cmd (const char * msg, int val,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
le16_to_char (char *dest, const grub_uint16_t * src16, unsigned bytes)
|
le16_to_char (grub_uint16_t *dest, const grub_uint16_t * src16, unsigned bytes)
|
||||||
{
|
{
|
||||||
grub_uint16_t * dest16 = (grub_uint16_t *) dest;
|
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < bytes / 2; i++)
|
for (i = 0; i < bytes / 2; i++)
|
||||||
dest16[i] = grub_be_to_cpu16 (src16[i]);
|
dest[i] = grub_be_to_cpu16 (src16[i]);
|
||||||
return dest;
|
dest[i] = 0;
|
||||||
|
return (char *) dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
grub_hdparm_print_identify (const char * idbuf)
|
grub_hdparm_print_identify (const grub_uint16_t * idw)
|
||||||
{
|
{
|
||||||
const grub_uint16_t * idw = (const grub_uint16_t *) idbuf;
|
|
||||||
|
|
||||||
/* Print identity strings. */
|
/* Print identity strings. */
|
||||||
char tmp[40];
|
grub_uint16_t tmp[21];
|
||||||
grub_printf ("Model: \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40));
|
grub_printf ("Model: \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40));
|
||||||
grub_printf ("Firmware: \"%.8s\"\n", le16_to_char (tmp, &idw[23], 8));
|
grub_printf ("Firmware: \"%.8s\"\n", le16_to_char (tmp, &idw[23], 8));
|
||||||
grub_printf ("Serial: \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20));
|
grub_printf ("Serial: \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20));
|
||||||
|
@ -377,7 +375,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
||||||
/* Print/dump IDENTIFY. */
|
/* Print/dump IDENTIFY. */
|
||||||
if (ident || dumpid)
|
if (ident || dumpid)
|
||||||
{
|
{
|
||||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
grub_uint16_t buf[GRUB_DISK_SECTOR_SIZE / 2];
|
||||||
if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE,
|
if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE,
|
||||||
0, 0, buf, sizeof (buf)))
|
0, 0, buf, sizeof (buf)))
|
||||||
grub_printf ("Cannot read ATA IDENTIFY data\n");
|
grub_printf ("Cannot read ATA IDENTIFY data\n");
|
||||||
|
@ -386,7 +384,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
||||||
if (ident)
|
if (ident)
|
||||||
grub_hdparm_print_identify (buf);
|
grub_hdparm_print_identify (buf);
|
||||||
if (dumpid)
|
if (dumpid)
|
||||||
hexdump (0, buf, sizeof (buf));
|
hexdump (0, (char *) buf, sizeof (buf));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <grub/command.h>
|
#include <grub/command.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/cmos.h>
|
#include <grub/cmos.h>
|
||||||
|
#include <grub/i18n.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -86,11 +87,11 @@ static grub_command_t cmd, cmd_clean;
|
||||||
GRUB_MOD_INIT(cmostest)
|
GRUB_MOD_INIT(cmostest)
|
||||||
{
|
{
|
||||||
cmd = grub_register_command ("cmostest", grub_cmd_cmostest,
|
cmd = grub_register_command ("cmostest", grub_cmd_cmostest,
|
||||||
"cmostest BYTE:BIT",
|
N_("BYTE:BIT"),
|
||||||
"Test bit at BYTE:BIT in CMOS.");
|
N_("Test bit at BYTE:BIT in CMOS."));
|
||||||
cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean,
|
cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean,
|
||||||
"cmosclean BYTE:BIT",
|
N_("BYTE:BIT"),
|
||||||
"Clean bit at BYTE:BIT in CMOS.");
|
N_("Clean bit at BYTE:BIT in CMOS."));
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(cmostest)
|
GRUB_MOD_FINI(cmostest)
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
/* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */
|
/* 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. */
|
/* Remember to update enum opt_idxs accordingly. */
|
||||||
static const struct grub_arg_option options[] = {
|
static const struct grub_arg_option options[] = {
|
||||||
|
@ -178,11 +178,11 @@ list_mappings (void)
|
||||||
/* Show: list mappings. */
|
/* Show: list mappings. */
|
||||||
if (! map_head)
|
if (! map_head)
|
||||||
{
|
{
|
||||||
grub_printf ("No drives have been remapped\n");
|
grub_puts_ (N_("No drives have been remapped"));
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_printf ("OS disk #num ------> GRUB/BIOS device\n");
|
grub_puts_ (N_("OS disk #num ------> GRUB/BIOS device"));
|
||||||
drivemap_node_t *curnode = map_head;
|
drivemap_node_t *curnode = map_head;
|
||||||
while (curnode)
|
while (curnode)
|
||||||
{
|
{
|
||||||
|
@ -363,7 +363,7 @@ uninstall_int13_handler (void)
|
||||||
static int
|
static int
|
||||||
grub_get_root_biosnumber_drivemap (void)
|
grub_get_root_biosnumber_drivemap (void)
|
||||||
{
|
{
|
||||||
char *biosnum;
|
const char *biosnum;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
grub_device_t dev;
|
grub_device_t dev;
|
||||||
|
|
||||||
|
|
|
@ -74,27 +74,27 @@ grub_cmd_lsapm (grub_command_t cmd __attribute__ ((unused)),
|
||||||
if (!grub_apm_get_info (&info))
|
if (!grub_apm_get_info (&info))
|
||||||
return grub_error (GRUB_ERR_IO, "no APM found");
|
return grub_error (GRUB_ERR_IO, "no APM found");
|
||||||
|
|
||||||
grub_printf ("Vesion %u.%u\n"
|
grub_printf_ (N_("Vesion %u.%u\n"
|
||||||
"32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n"
|
"32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n"
|
||||||
"16-bit CS = 0x%x, len = 0x%x\n"
|
"16-bit CS = 0x%x, len = 0x%x\n"
|
||||||
"DS = 0x%x, len = 0x%x\n",
|
"DS = 0x%x, len = 0x%x\n"),
|
||||||
info.version >> 8, info.version & 0xff,
|
info.version >> 8, info.version & 0xff,
|
||||||
info.cseg, info.cseg_len, info.offset,
|
info.cseg, info.cseg_len, info.offset,
|
||||||
info.cseg_16, info.cseg_16_len,
|
info.cseg_16, info.cseg_16_len,
|
||||||
info.dseg, info.dseg_len);
|
info.dseg, info.dseg_len);
|
||||||
grub_xputs (info.flags & GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED
|
grub_xputs (info.flags & GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED
|
||||||
? "16-bit protected interface supported\n"
|
? _("16-bit protected interface supported\n")
|
||||||
: "16-bit protected interface unsupported\n");
|
: _("16-bit protected interface unsupported\n"));
|
||||||
grub_xputs (info.flags & GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED
|
grub_xputs (info.flags & GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED
|
||||||
? "32-bit protected interface supported\n"
|
? _("32-bit protected interface supported\n")
|
||||||
: "32-bit protected interface unsupported\n");
|
: _("32-bit protected interface unsupported\n"));
|
||||||
grub_xputs (info.flags & GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN
|
grub_xputs (info.flags & GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN
|
||||||
? "CPU Idle slows down processor\n"
|
? _("CPU Idle slows down processor\n")
|
||||||
: "CPU Idle doesn't slow down processor\n");
|
: _("CPU Idle doesn't slow down processor\n"));
|
||||||
grub_xputs (info.flags & GRUB_APM_FLAGS_DISABLED
|
grub_xputs (info.flags & GRUB_APM_FLAGS_DISABLED
|
||||||
? "APM disabled\n" : "APM enabled\n");
|
? _("APM disabled\n") : _("APM enabled\n"));
|
||||||
grub_xputs (info.flags & GRUB_APM_FLAGS_DISENGAGED
|
grub_xputs (info.flags & GRUB_APM_FLAGS_DISENGAGED
|
||||||
? "APM disengaged\n" : "APM engaged\n");
|
? _("APM disengaged\n") : _("APM engaged\n"));
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <grub/extcmd.h>
|
#include <grub/extcmd.h>
|
||||||
#include <grub/cpu/io.h>
|
#include <grub/cpu/io.h>
|
||||||
#include <grub/loader.h>
|
#include <grub/loader.h>
|
||||||
|
#include <grub/i18n.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv2+");
|
GRUB_MOD_LICENSE ("GPLv2+");
|
||||||
|
|
||||||
|
@ -35,23 +36,23 @@ static int keylen = 0;
|
||||||
static int noled = 0;
|
static int noled = 0;
|
||||||
static const struct grub_arg_option options[] =
|
static const struct grub_arg_option options[] =
|
||||||
{
|
{
|
||||||
{"num", 'n', 0, "set numlock mode", "[on|off]", ARG_TYPE_STRING},
|
{"num", 'n', 0, N_("set numlock mode"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"caps", 'c', 0, "set capslock mode", "[on|off]", ARG_TYPE_STRING},
|
{"caps", 'c', 0, N_("set capslock mode"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"scroll", 's', 0, "set scrolllock mode", "[on|off]", ARG_TYPE_STRING},
|
{"scroll", 's', 0, N_("set scrolllock mode"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"insert", 0, 0, "set insert mode", "[on|off]", ARG_TYPE_STRING},
|
{"insert", 0, 0, N_("set insert mode"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"pause", 0, 0, "set pause mode", "[on|off]", ARG_TYPE_STRING},
|
{"pause", 0, 0, N_("set pause mode"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"left-shift", 0, 0, "press left shift", "[on|off]", ARG_TYPE_STRING},
|
{"left-shift", 0, 0, N_("press left shift"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"right-shift", 0, 0, "press right shift", "[on|off]", ARG_TYPE_STRING},
|
{"right-shift", 0, 0, N_("press right shift"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"sysrq", 0, 0, "press SysRq", "[on|off]", ARG_TYPE_STRING},
|
{"sysrq", 0, 0, N_("press SysRq"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"numkey", 0, 0, "press NumLock key", "[on|off]", ARG_TYPE_STRING},
|
{"numkey", 0, 0, N_("press NumLock key"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"capskey", 0, 0, "press CapsLock key", "[on|off]", ARG_TYPE_STRING},
|
{"capskey", 0, 0, N_("press CapsLock key"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"scrollkey", 0, 0, "press ScrollLock key", "[on|off]", ARG_TYPE_STRING},
|
{"scrollkey", 0, 0, N_("press ScrollLock key"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"insertkey", 0, 0, "press Insert key", "[on|off]", ARG_TYPE_STRING},
|
{"insertkey", 0, 0, N_("press Insert key"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"left-alt", 0, 0, "press left alt", "[on|off]", ARG_TYPE_STRING},
|
{"left-alt", 0, 0, N_("press left alt"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"right-alt", 0, 0, "press right alt", "[on|off]", ARG_TYPE_STRING},
|
{"right-alt", 0, 0, N_("press right alt"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"left-ctrl", 0, 0, "press left ctrl", "[on|off]", ARG_TYPE_STRING},
|
{"left-ctrl", 0, 0, N_("press left ctrl"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"right-ctrl", 0, 0, "press right ctrl", "[on|off]", ARG_TYPE_STRING},
|
{"right-ctrl", 0, 0, N_("press right ctrl"), "[on|off]", ARG_TYPE_STRING},
|
||||||
{"no-led", 0, 0, "don't update LED state", 0, 0},
|
{"no-led", 0, 0, N_("don't update LED state"), 0, 0},
|
||||||
{0, 0, 0, 0, 0, 0}
|
{0, 0, 0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
static int simple_flag_offsets[]
|
static int simple_flag_offsets[]
|
||||||
|
@ -62,8 +63,8 @@ static grub_uint32_t andmask = 0xffffffff, ormask = 0;
|
||||||
struct
|
struct
|
||||||
keysym
|
keysym
|
||||||
{
|
{
|
||||||
char *unshifted_name; /* the name in unshifted state */
|
const char *unshifted_name; /* the name in unshifted state */
|
||||||
char *shifted_name; /* the name in shifted state */
|
const char *shifted_name; /* the name in shifted state */
|
||||||
unsigned char unshifted_ascii; /* the ascii code in unshifted state */
|
unsigned char unshifted_ascii; /* the ascii code in unshifted state */
|
||||||
unsigned char shifted_ascii; /* the ascii code in shifted state */
|
unsigned char shifted_ascii; /* the ascii code in shifted state */
|
||||||
unsigned char keycode; /* keyboard scancode */
|
unsigned char keycode; /* keyboard scancode */
|
||||||
|
@ -364,13 +365,13 @@ grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_extcmd_t cmd;
|
static grub_extcmd_t cmd;
|
||||||
static void *preboot_hook;
|
static struct grub_preboot *preboot_hook;
|
||||||
|
|
||||||
GRUB_MOD_INIT (sendkey)
|
GRUB_MOD_INIT (sendkey)
|
||||||
{
|
{
|
||||||
cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, 0,
|
cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, 0,
|
||||||
"sendkey [KEYSTROKE1] [KEYSTROKE2] ...",
|
N_("[KEYSTROKE1] [KEYSTROKE2] ..."),
|
||||||
"Emulate a keystroke", options);
|
N_("Emulate a keystroke"), options);
|
||||||
|
|
||||||
preboot_hook
|
preboot_hook
|
||||||
= grub_loader_register_preboot_hook (grub_sendkey_preboot,
|
= grub_loader_register_preboot_hook (grub_sendkey_preboot,
|
||||||
|
|
|
@ -31,7 +31,7 @@ grub_cmd_suspend (grub_command_t cmd __attribute__ ((unused)),
|
||||||
int argc __attribute__ ((unused)),
|
int argc __attribute__ ((unused)),
|
||||||
char **args __attribute__ ((unused)))
|
char **args __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
grub_printf ("Run 'go' to resume GRUB.\n");
|
grub_puts_ (N_("Run 'go' to resume GRUB."));
|
||||||
grub_ieee1275_enter ();
|
grub_ieee1275_enter ();
|
||||||
grub_cls ();
|
grub_cls ();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -344,7 +344,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||||
int bsd_part = -1;
|
int bsd_part = -1;
|
||||||
{
|
{
|
||||||
grub_device_t dev;
|
grub_device_t dev;
|
||||||
char *hdbiasstr;
|
const char *hdbiasstr;
|
||||||
int hdbias = 0;
|
int hdbias = 0;
|
||||||
hdbiasstr = grub_env_get ("legacy_hdbias");
|
hdbiasstr = grub_env_get ("legacy_hdbias");
|
||||||
if (hdbiasstr)
|
if (hdbiasstr)
|
||||||
|
@ -723,7 +723,7 @@ grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unuse
|
||||||
|
|
||||||
if (argc == 0)
|
if (argc == 0)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected");
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected");
|
||||||
grub_printf ("Enter password:");
|
grub_puts_ (N_("Enter password: "));
|
||||||
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
|
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
|
||||||
return GRUB_ACCESS_DENIED;
|
return GRUB_ACCESS_DENIED;
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ open_envblk_file (char *filename)
|
||||||
|
|
||||||
if (! filename)
|
if (! filename)
|
||||||
{
|
{
|
||||||
char *prefix;
|
const char *prefix;
|
||||||
|
|
||||||
prefix = grub_env_get ("prefix");
|
prefix = grub_env_get ("prefix");
|
||||||
if (prefix)
|
if (prefix)
|
||||||
|
@ -346,7 +346,7 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
|
|
||||||
while (argc)
|
while (argc)
|
||||||
{
|
{
|
||||||
char *value;
|
const char *value;
|
||||||
|
|
||||||
value = grub_env_get (args[0]);
|
value = grub_env_get (args[0]);
|
||||||
if (value)
|
if (value)
|
||||||
|
|
|
@ -26,13 +26,13 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
static const char *names[] =
|
static const char *names[] =
|
||||||
{
|
{
|
||||||
[GRUB_MEMORY_AVAILABLE] = "available",
|
[GRUB_MEMORY_AVAILABLE] = N_("available"),
|
||||||
[GRUB_MEMORY_RESERVED] = "reserved",
|
[GRUB_MEMORY_RESERVED] = N_("reserved"),
|
||||||
[GRUB_MEMORY_ACPI] = "ACPI reclamaible",
|
[GRUB_MEMORY_ACPI] = N_("ACPI reclamaible"),
|
||||||
[GRUB_MEMORY_NVS] = "NVS",
|
[GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage"),
|
||||||
[GRUB_MEMORY_BADRAM] = "BadRAM",
|
[GRUB_MEMORY_BADRAM] = N_("BadRAM"),
|
||||||
[GRUB_MEMORY_CODE] = "firmware code",
|
[GRUB_MEMORY_CODE] = N_("firmware code"),
|
||||||
[GRUB_MEMORY_HOLE] = "hole"
|
[GRUB_MEMORY_HOLE] = N_("hole")
|
||||||
};
|
};
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -46,10 +46,10 @@ grub_cmd_lsmmap (grub_command_t cmd __attribute__ ((unused)),
|
||||||
grub_memory_type_t type)
|
grub_memory_type_t type)
|
||||||
{
|
{
|
||||||
if (type < ARRAY_SIZE (names) && names[type])
|
if (type < ARRAY_SIZE (names) && names[type])
|
||||||
grub_printf ("base_addr = 0x%llx, length = 0x%llx, %s\n",
|
grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, %s\n"),
|
||||||
(long long) addr, (long long) size, names[type]);
|
(long long) addr, (long long) size, _(names[type]));
|
||||||
else
|
else
|
||||||
grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n",
|
grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n"),
|
||||||
(long long) addr, (long long) size, type);
|
(long long) addr, (long long) size, type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ struct grub_pci_classname
|
||||||
{
|
{
|
||||||
int class;
|
int class;
|
||||||
int subclass;
|
int subclass;
|
||||||
char *desc;
|
const char *desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct grub_pci_classname grub_pci_classes[] =
|
static const struct grub_pci_classname grub_pci_classes[] =
|
||||||
|
|
|
@ -31,7 +31,7 @@ static grub_command_t cmd_write_byte, cmd_write_word, cmd_write_dword;
|
||||||
static const struct grub_arg_option options[] =
|
static const struct grub_arg_option options[] =
|
||||||
{
|
{
|
||||||
{0, 'v', 0, N_("Save read value into variable VARNAME."),
|
{0, 'v', 0, N_("Save read value into variable VARNAME."),
|
||||||
"VARNAME", ARG_TYPE_STRING},
|
N_("VARNAME"), ARG_TYPE_STRING},
|
||||||
{0, 0, 0, 0, 0, 0}
|
{0, 0, 0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,19 +28,19 @@
|
||||||
static const struct grub_arg_option options[] =
|
static const struct grub_arg_option options[] =
|
||||||
{
|
{
|
||||||
{"class", 1, GRUB_ARG_OPTION_REPEATABLE,
|
{"class", 1, GRUB_ARG_OPTION_REPEATABLE,
|
||||||
N_("Menu entry type."), "STRING", ARG_TYPE_STRING},
|
N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING},
|
||||||
{"users", 2, 0,
|
{"users", 2, 0,
|
||||||
N_("Users allowed to boot this entry."), "USERNAME", ARG_TYPE_STRING},
|
N_("Users allowed to boot this entry."), N_("USERNAME"), ARG_TYPE_STRING},
|
||||||
{"hotkey", 3, 0,
|
{"hotkey", 3, 0,
|
||||||
N_("Keyboard key for this entry."), "KEY", ARG_TYPE_STRING},
|
N_("Keyboard key for this entry."), N_("KEY"), ARG_TYPE_STRING},
|
||||||
{"source", 4, 0,
|
{"source", 4, 0,
|
||||||
N_("Menu entry definition as a string."), "STRING", ARG_TYPE_STRING},
|
N_("Menu entry definition as a string."), N_("STRING"), ARG_TYPE_STRING},
|
||||||
{0, 0, 0, 0, 0, 0}
|
{0, 0, 0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
char *name;
|
const char *name;
|
||||||
int key;
|
int key;
|
||||||
} hotkey_aliases[] =
|
} hotkey_aliases[] =
|
||||||
{
|
{
|
||||||
|
|
|
@ -145,7 +145,7 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
|
||||||
{
|
{
|
||||||
grub_dl_t mod;
|
grub_dl_t mod;
|
||||||
|
|
||||||
grub_printf ("Name\tRef Count\tDependencies\n");
|
grub_printf_ (N_("Name\tRef Count\tDependencies\n"));
|
||||||
FOR_DL_MODULES (mod)
|
FOR_DL_MODULES (mod)
|
||||||
{
|
{
|
||||||
grub_dl_dep_t dep;
|
grub_dl_dep_t dep;
|
||||||
|
@ -165,13 +165,13 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
|
||||||
}
|
}
|
||||||
|
|
||||||
/* exit */
|
/* exit */
|
||||||
static grub_err_t
|
static grub_err_t __attribute__ ((noreturn))
|
||||||
grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
|
grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
|
||||||
int argc __attribute__ ((unused)),
|
int argc __attribute__ ((unused)),
|
||||||
char *argv[] __attribute__ ((unused)))
|
char *argv[] __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
grub_exit ();
|
grub_exit ();
|
||||||
return 0;
|
/* Not reached. */
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_command_t cmd_cat, cmd_help;
|
static grub_command_t cmd_cat, cmd_help;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/command.h>
|
#include <grub/command.h>
|
||||||
#include <grub/cs5536.h>
|
#include <grub/cs5536.h>
|
||||||
|
#include <grub/i18n.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -38,43 +39,44 @@ grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
|
||||||
if (!grub_cs5536_find (&dev))
|
if (!grub_cs5536_find (&dev))
|
||||||
{
|
{
|
||||||
grub_printf ("No CS5536 found\n");
|
grub_puts_ (N_("No CS5536 found"));
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
grub_printf ("CS5536 at %d:%d.%d\n", grub_pci_get_bus (dev),
|
grub_printf_ (N_("CS5536 at %d:%d.%d\n"), grub_pci_get_bus (dev),
|
||||||
grub_pci_get_device (dev), grub_pci_get_function (dev));
|
grub_pci_get_device (dev), grub_pci_get_function (dev));
|
||||||
|
|
||||||
err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase);
|
err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
grub_printf ("SMB base = 0x%x\n", smbbase);
|
grub_printf_ (N_("SMB base = 0x%x\n"), smbbase);
|
||||||
|
|
||||||
for (i = GRUB_SMB_RAM_START_ADDR;
|
for (i = GRUB_SMB_RAM_START_ADDR;
|
||||||
i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++)
|
i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++)
|
||||||
{
|
{
|
||||||
struct grub_smbus_spd spd;
|
struct grub_smbus_spd spd;
|
||||||
grub_memset (&spd, 0, sizeof (spd));
|
grub_memset (&spd, 0, sizeof (spd));
|
||||||
grub_printf ("Device %d\n", i);
|
grub_printf_ (N_("Device %d\n"), i);
|
||||||
err = grub_cs5536_read_spd (smbbase, i, &spd);
|
err = grub_cs5536_read_spd (smbbase, i, &spd);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_print_error ();
|
grub_print_error ();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
grub_printf ("Written SPD bytes: %d B.\n", spd.written_size);
|
grub_printf_ (N_("Written SPD bytes: %d B.\n"), spd.written_size);
|
||||||
grub_printf ("Total flash size: %d B.\n", 1 << spd.log_total_flash_size);
|
grub_printf_ (N_("Total flash size: %d B.\n"),
|
||||||
|
1 << spd.log_total_flash_size);
|
||||||
if (spd.memory_type == GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2)
|
if (spd.memory_type == GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2)
|
||||||
{
|
{
|
||||||
char str[sizeof (spd.ddr2.part_number) + 1];
|
char str[sizeof (spd.ddr2.part_number) + 1];
|
||||||
grub_printf ("Memory type: DDR2.\n");
|
grub_puts_ (N_("Memory type: DDR2."));
|
||||||
grub_memcpy (str, spd.ddr2.part_number,
|
grub_memcpy (str, spd.ddr2.part_number,
|
||||||
sizeof (spd.ddr2.part_number));
|
sizeof (spd.ddr2.part_number));
|
||||||
str[sizeof (spd.ddr2.part_number)] = 0;
|
str[sizeof (spd.ddr2.part_number)] = 0;
|
||||||
grub_printf ("Part no: %s.\n", str);
|
grub_printf_ (N_("Part no: %s.\n"), str);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
grub_printf ("Memory type: Unknown.\n");
|
grub_puts_ (N_("Memory type: Unknown."));
|
||||||
}
|
}
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
@ -85,7 +87,7 @@ static grub_command_t cmd;
|
||||||
GRUB_MOD_INIT(lsspd)
|
GRUB_MOD_INIT(lsspd)
|
||||||
{
|
{
|
||||||
cmd = grub_register_command ("lsspd", grub_cmd_lsspd, 0,
|
cmd = grub_register_command ("lsspd", grub_cmd_lsspd, 0,
|
||||||
"Print Memory information.");
|
N_("Print Memory information."));
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(lsspd)
|
GRUB_MOD_FINI(lsspd)
|
||||||
|
|
|
@ -37,9 +37,9 @@ static struct grub_parttool *parts = 0;
|
||||||
static int curhandle = 0;
|
static int curhandle = 0;
|
||||||
static grub_dl_t mymod;
|
static grub_dl_t mymod;
|
||||||
static char helpmsg[] =
|
static char helpmsg[] =
|
||||||
"Perform COMMANDS on partition.\n"
|
N_("Perform COMMANDS on partition.\n"
|
||||||
"Use \"parttool PARTITION help\" for the list "
|
"Use \"parttool PARTITION help\" for the list "
|
||||||
"of available commands.";
|
"of available commands.");
|
||||||
|
|
||||||
int
|
int
|
||||||
grub_parttool_register(const char *part_name,
|
grub_parttool_register(const char *part_name,
|
||||||
|
@ -128,7 +128,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GRUB_PARTTOOL_ARG_VAL:
|
case GRUB_PARTTOOL_ARG_VAL:
|
||||||
grub_printf ("=VAL");
|
grub_xputs (_("=VAL"));
|
||||||
spacing -= 4;
|
spacing -= 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -137,18 +137,18 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
|
||||||
}
|
}
|
||||||
while (spacing-- > 0)
|
while (spacing-- > 0)
|
||||||
grub_printf (" ");
|
grub_printf (" ");
|
||||||
grub_printf ("%s\n", curarg->desc);
|
grub_puts_ (curarg->desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (! found)
|
if (! found)
|
||||||
grub_printf ("Sorry no parttool is available for %s\n",
|
grub_printf_ (N_("Sorry no parttool is available for %s\n"),
|
||||||
dev->disk->partition->partmap->name);
|
dev->disk->partition->partmap->name);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc < 1)
|
if (argc < 1)
|
||||||
{
|
{
|
||||||
grub_printf ("%s\n", helpmsg);
|
grub_puts_ (helpmsg);
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments");
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
return err;
|
return err;
|
||||||
if (! label)
|
if (! label)
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
"uuid for this FS isn't supported yet");
|
"label for this FS isn't supported yet");
|
||||||
|
|
||||||
if (state[0].set)
|
if (state[0].set)
|
||||||
grub_env_set (state[0].arg, label);
|
grub_env_set (state[0].arg, label);
|
||||||
|
|
|
@ -24,13 +24,12 @@
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t __attribute__ ((noreturn))
|
||||||
grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)),
|
grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)),
|
||||||
int argc __attribute__ ((unused)),
|
int argc __attribute__ ((unused)),
|
||||||
char **args __attribute__ ((unused)))
|
char **args __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
grub_reboot ();
|
grub_reboot ();
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_command_t cmd;
|
static grub_command_t cmd;
|
||||||
|
|
|
@ -33,11 +33,21 @@
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
struct cache_entry
|
||||||
|
{
|
||||||
|
struct cache_entry *next;
|
||||||
|
char *key;
|
||||||
|
char *value;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct cache_entry *cache;
|
||||||
|
|
||||||
void
|
void
|
||||||
FUNC_NAME (const char *key, const char *var, int no_floppy,
|
FUNC_NAME (const char *key, const char *var, int no_floppy,
|
||||||
char **hints, unsigned nhints)
|
char **hints, unsigned nhints)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
int is_cache = 0;
|
||||||
grub_fs_autoload_hook_t saved_autoload;
|
grub_fs_autoload_hook_t saved_autoload;
|
||||||
|
|
||||||
auto int iterate_device (const char *name);
|
auto int iterate_device (const char *name);
|
||||||
|
@ -50,6 +60,12 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
|
||||||
name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
|
name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#ifdef DO_SEARCH_FS_UUID
|
||||||
|
#define compare_fn grub_strcasecmp
|
||||||
|
#else
|
||||||
|
#define compare_fn grub_strcmp
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DO_SEARCH_FILE
|
#ifdef DO_SEARCH_FILE
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
|
@ -81,10 +97,8 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
|
||||||
fs = grub_fs_probe (dev);
|
fs = grub_fs_probe (dev);
|
||||||
|
|
||||||
#ifdef DO_SEARCH_FS_UUID
|
#ifdef DO_SEARCH_FS_UUID
|
||||||
#define compare_fn grub_strcasecmp
|
|
||||||
#define read_fn uuid
|
#define read_fn uuid
|
||||||
#else
|
#else
|
||||||
#define compare_fn grub_strcmp
|
|
||||||
#define read_fn label
|
#define read_fn label
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -106,6 +120,31 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!is_cache && found && count == 0)
|
||||||
|
{
|
||||||
|
struct cache_entry *cache_ent;
|
||||||
|
cache_ent = grub_malloc (sizeof (*cache_ent));
|
||||||
|
if (cache_ent)
|
||||||
|
{
|
||||||
|
cache_ent->key = grub_strdup (key);
|
||||||
|
cache_ent->value = grub_strdup (name);
|
||||||
|
if (cache_ent->value && cache_ent->key)
|
||||||
|
{
|
||||||
|
cache_ent->next = cache;
|
||||||
|
cache = cache_ent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
grub_free (cache_ent->value);
|
||||||
|
grub_free (cache_ent->key);
|
||||||
|
grub_free (cache_ent);
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
|
@ -143,6 +182,32 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
|
||||||
void try (void)
|
void try (void)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
struct cache_entry **prev;
|
||||||
|
struct cache_entry *cache_ent;
|
||||||
|
|
||||||
|
for (prev = &cache, cache_ent = *prev; cache_ent;
|
||||||
|
prev = &cache_ent->next, cache_ent = *prev)
|
||||||
|
if (compare_fn (cache_ent->key, key) == 0)
|
||||||
|
break;
|
||||||
|
if (cache_ent)
|
||||||
|
{
|
||||||
|
is_cache = 1;
|
||||||
|
if (iterate_device (cache_ent->value))
|
||||||
|
{
|
||||||
|
is_cache = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
is_cache = 0;
|
||||||
|
/* Cache entry was outdated. Remove it. */
|
||||||
|
if (!count)
|
||||||
|
{
|
||||||
|
grub_free (cache_ent->key);
|
||||||
|
grub_free (cache_ent->value);
|
||||||
|
grub_free (cache_ent);
|
||||||
|
*prev = cache_ent->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < nhints; i++)
|
for (i = 0; i < nhints; i++)
|
||||||
{
|
{
|
||||||
char *end;
|
char *end;
|
||||||
|
@ -164,16 +229,19 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
|
||||||
dev = grub_device_open (hints[i]);
|
dev = grub_device_open (hints[i]);
|
||||||
if (!dev)
|
if (!dev)
|
||||||
{
|
{
|
||||||
|
if (!*end)
|
||||||
*end = ',';
|
*end = ',';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!dev->disk)
|
if (!dev->disk)
|
||||||
{
|
{
|
||||||
grub_device_close (dev);
|
grub_device_close (dev);
|
||||||
|
if (!*end)
|
||||||
*end = ',';
|
*end = ',';
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ret = grub_partition_iterate (dev->disk, part_hook);
|
ret = grub_partition_iterate (dev->disk, part_hook);
|
||||||
|
if (!*end)
|
||||||
*end = ',';
|
*end = ',';
|
||||||
grub_device_close (dev);
|
grub_device_close (dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
@ -42,6 +42,21 @@ static const struct grub_arg_option options[] =
|
||||||
{"hint", 'h', GRUB_ARG_OPTION_REPEATABLE,
|
{"hint", 'h', GRUB_ARG_OPTION_REPEATABLE,
|
||||||
N_("First try the device HINT. If HINT ends in comma, "
|
N_("First try the device HINT. If HINT ends in comma, "
|
||||||
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
|
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
|
||||||
|
{"hint-ieee1275", 0, GRUB_ARG_OPTION_REPEATABLE,
|
||||||
|
N_("First try the device HINT if on IEEE1275. If HINT ends in comma, "
|
||||||
|
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
|
||||||
|
{"hint-bios", 0, GRUB_ARG_OPTION_REPEATABLE,
|
||||||
|
N_("First try the device HINT if on BIOS. If HINT ends in comma, "
|
||||||
|
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
|
||||||
|
{"hint-baremetal", 0, GRUB_ARG_OPTION_REPEATABLE,
|
||||||
|
N_("First try the device HINT. If HINT ends in comma, "
|
||||||
|
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
|
||||||
|
{"hint-efi", 0, GRUB_ARG_OPTION_REPEATABLE,
|
||||||
|
N_("First try the device HINT if on EFI. If HINT ends in comma, "
|
||||||
|
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
|
||||||
|
{"hint-arc", 0, GRUB_ARG_OPTION_REPEATABLE,
|
||||||
|
N_("First try the device HINT if on ARC. If HINT ends in comma, "
|
||||||
|
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
|
||||||
{0, 0, 0, 0, 0, 0}
|
{0, 0, 0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -52,7 +67,12 @@ enum options
|
||||||
SEARCH_FS_UUID,
|
SEARCH_FS_UUID,
|
||||||
SEARCH_SET,
|
SEARCH_SET,
|
||||||
SEARCH_NO_FLOPPY,
|
SEARCH_NO_FLOPPY,
|
||||||
SEARCH_HINT
|
SEARCH_HINT,
|
||||||
|
SEARCH_HINT_IEEE1275,
|
||||||
|
SEARCH_HINT_BIOS,
|
||||||
|
SEARCH_HINT_BAREMETAL,
|
||||||
|
SEARCH_HINT_EFI,
|
||||||
|
SEARCH_HINT_ARC,
|
||||||
};
|
};
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -60,27 +80,98 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||||
{
|
{
|
||||||
struct grub_arg_list *state = ctxt->state;
|
struct grub_arg_list *state = ctxt->state;
|
||||||
const char *var = 0;
|
const char *var = 0;
|
||||||
int nhints = 0;
|
int i = 0, j = 0, nhints = 0;
|
||||||
|
char **hints = NULL;
|
||||||
|
|
||||||
if (state[SEARCH_HINT].set)
|
if (state[SEARCH_HINT].set)
|
||||||
while (state[SEARCH_HINT].args[nhints])
|
for (i = 0; state[SEARCH_HINT].args[i]; i++)
|
||||||
nhints++;
|
nhints++;
|
||||||
|
|
||||||
if (argc == 0)
|
#ifdef GRUB_MACHINE_IEEE1275
|
||||||
|
if (state[SEARCH_HINT_IEEE1275].set)
|
||||||
|
for (i = 0; state[SEARCH_HINT_IEEE1275].args[i]; i++)
|
||||||
|
nhints++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_EFI
|
||||||
|
if (state[SEARCH_HINT_EFI].set)
|
||||||
|
for (i = 0; state[SEARCH_HINT_EFI].args[i]; i++)
|
||||||
|
nhints++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_PCBIOS
|
||||||
|
if (state[SEARCH_HINT_BIOS].set)
|
||||||
|
for (i = 0; state[SEARCH_HINT_BIOS].args[i]; i++)
|
||||||
|
nhints++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_ARC
|
||||||
|
if (state[SEARCH_HINT_ARC].set)
|
||||||
|
for (i = 0; state[SEARCH_HINT_ARC].args[i]; i++)
|
||||||
|
nhints++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (state[SEARCH_HINT_BAREMETAL].set)
|
||||||
|
for (i = 0; state[SEARCH_HINT_BAREMETAL].args[i]; i++)
|
||||||
|
nhints++;
|
||||||
|
|
||||||
|
hints = grub_malloc (sizeof (hints[0]) * nhints);
|
||||||
|
if (!hints)
|
||||||
|
return grub_errno;
|
||||||
|
j = 0;
|
||||||
|
|
||||||
|
if (state[SEARCH_HINT].set)
|
||||||
|
for (i = 0; state[SEARCH_HINT].args[i]; i++)
|
||||||
|
hints[j++] = state[SEARCH_HINT].args[i];
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_IEEE1275
|
||||||
|
if (state[SEARCH_HINT_IEEE1275].set)
|
||||||
|
for (i = 0; state[SEARCH_HINT_IEEE1275].args[i]; i++)
|
||||||
|
hints[j++] = state[SEARCH_HINT_IEEE1275].args[i];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_EFI
|
||||||
|
if (state[SEARCH_HINT_EFI].set)
|
||||||
|
for (i = 0; state[SEARCH_HINT_EFI].args[i]; i++)
|
||||||
|
hints[j++] = state[SEARCH_HINT_EFI].args[i];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_ARC
|
||||||
|
if (state[SEARCH_HINT_ARC].set)
|
||||||
|
for (i = 0; state[SEARCH_HINT_ARC].args[i]; i++)
|
||||||
|
hints[j++] = state[SEARCH_HINT_ARC].args[i];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GRUB_MACHINE_PCBIOS
|
||||||
|
if (state[SEARCH_HINT_BIOS].set)
|
||||||
|
for (i = 0; state[SEARCH_HINT_BIOS].args[i]; i++)
|
||||||
|
hints[j++] = state[SEARCH_HINT_BIOS].args[i];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (state[SEARCH_HINT_BAREMETAL].set)
|
||||||
|
for (i = 0; state[SEARCH_HINT_BAREMETAL].args[i]; i++)
|
||||||
|
hints[j++] = state[SEARCH_HINT_BAREMETAL].args[i];
|
||||||
|
|
||||||
|
/* Skip hints for future platforms. */
|
||||||
|
for (j = 0; j < argc; j++)
|
||||||
|
if (grub_memcmp (args[j], "--hint-", sizeof ("--hint-") - 1) != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (argc == j)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified");
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified");
|
||||||
|
|
||||||
if (state[SEARCH_SET].set)
|
if (state[SEARCH_SET].set)
|
||||||
var = state[SEARCH_SET].arg ? state[SEARCH_SET].arg : "root";
|
var = state[SEARCH_SET].arg ? state[SEARCH_SET].arg : "root";
|
||||||
|
|
||||||
if (state[SEARCH_LABEL].set)
|
if (state[SEARCH_LABEL].set)
|
||||||
grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set,
|
grub_search_label (args[j], var, state[SEARCH_NO_FLOPPY].set,
|
||||||
state[SEARCH_HINT].args, nhints);
|
hints, nhints);
|
||||||
else if (state[SEARCH_FS_UUID].set)
|
else if (state[SEARCH_FS_UUID].set)
|
||||||
grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set,
|
grub_search_fs_uuid (args[j], var, state[SEARCH_NO_FLOPPY].set,
|
||||||
state[SEARCH_HINT].args, nhints);
|
hints, nhints);
|
||||||
else if (state[SEARCH_FILE].set)
|
else if (state[SEARCH_FILE].set)
|
||||||
grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set,
|
grub_search_fs_file (args[j], var, state[SEARCH_NO_FLOPPY].set,
|
||||||
state[SEARCH_HINT].args, nhints);
|
hints, nhints);
|
||||||
else
|
else
|
||||||
return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type");
|
return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type");
|
||||||
|
|
||||||
|
@ -92,7 +183,8 @@ static grub_extcmd_t cmd;
|
||||||
GRUB_MOD_INIT(search)
|
GRUB_MOD_INIT(search)
|
||||||
{
|
{
|
||||||
cmd =
|
cmd =
|
||||||
grub_register_extcmd ("search", grub_cmd_search, GRUB_COMMAND_FLAG_EXTRACTOR,
|
grub_register_extcmd ("search", grub_cmd_search,
|
||||||
|
GRUB_COMMAND_FLAG_EXTRACTOR | GRUB_COMMAND_ACCEPT_DASH,
|
||||||
N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]"
|
N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]"
|
||||||
" NAME"),
|
" NAME"),
|
||||||
N_("Search devices by file, filesystem label"
|
N_("Search devices by file, filesystem label"
|
||||||
|
|
|
@ -66,12 +66,12 @@ static struct pci_register pci_registers[] =
|
||||||
|
|
||||||
static const struct grub_arg_option options[] =
|
static const struct grub_arg_option options[] =
|
||||||
{
|
{
|
||||||
{0, 'd', 0, "Select device by vendor and device IDs.",
|
{0, 'd', 0, N_("Select device by vendor and device IDs."),
|
||||||
"[vendor]:[device]", ARG_TYPE_STRING},
|
N_("[vendor]:[device]"), ARG_TYPE_STRING},
|
||||||
{0, 's', 0, "Select device by its position on the bus.",
|
{0, 's', 0, N_("Select device by its position on the bus."),
|
||||||
"[bus]:[slot][.func]", ARG_TYPE_STRING},
|
N_("[bus]:[slot][.func]"), ARG_TYPE_STRING},
|
||||||
{0, 'v', 0, "Save read value into variable VARNAME.",
|
{0, 'v', 0, N_("Save read value into variable VARNAME."),
|
||||||
"VARNAME", ARG_TYPE_STRING},
|
N_("VARNAME"), ARG_TYPE_STRING},
|
||||||
{0, 0, 0, 0, 0, 0}
|
{0, 0, 0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid)
|
||||||
|
|
||||||
if (!write_mask)
|
if (!write_mask)
|
||||||
{
|
{
|
||||||
grub_printf ("Register %x of %d:%d.%d is %x\n", regaddr,
|
grub_printf (N_("Register %x of %d:%d.%d is %x\n"), regaddr,
|
||||||
grub_pci_get_bus (dev),
|
grub_pci_get_bus (dev),
|
||||||
grub_pci_get_device (dev),
|
grub_pci_get_device (dev),
|
||||||
grub_pci_get_function (dev),
|
grub_pci_get_function (dev),
|
||||||
|
|
|
@ -31,6 +31,7 @@ struct grub_term_autoload *grub_term_output_autoload = NULL;
|
||||||
struct abstract_terminal
|
struct abstract_terminal
|
||||||
{
|
{
|
||||||
struct abstract_terminal *next;
|
struct abstract_terminal *next;
|
||||||
|
struct abstract_terminal *prev;
|
||||||
const char *name;
|
const char *name;
|
||||||
grub_err_t (*init) (struct abstract_terminal *term);
|
grub_err_t (*init) (struct abstract_terminal *term);
|
||||||
grub_err_t (*fini) (struct abstract_terminal *term);
|
grub_err_t (*fini) (struct abstract_terminal *term);
|
||||||
|
@ -94,11 +95,15 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
for (term = *disabled; term; term = term->next)
|
for (term = *disabled; term; term = term->next)
|
||||||
if (grub_strcmp (args[i], term->name) == 0)
|
if (grub_strcmp (args[i], term->name) == 0
|
||||||
|
|| (grub_strcmp (args[i], "ofconsole") == 0
|
||||||
|
&& grub_strcmp ("console", term->name) == 0))
|
||||||
break;
|
break;
|
||||||
if (term == 0)
|
if (term == 0)
|
||||||
for (term = *enabled; term; term = term->next)
|
for (term = *enabled; term; term = term->next)
|
||||||
if (grub_strcmp (args[i], term->name) == 0)
|
if (grub_strcmp (args[i], term->name) == 0
|
||||||
|
|| (grub_strcmp (args[i], "ofconsole") == 0
|
||||||
|
&& grub_strcmp ("console", term->name) == 0))
|
||||||
break;
|
break;
|
||||||
if (term)
|
if (term)
|
||||||
break;
|
break;
|
||||||
|
@ -107,6 +112,8 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
||||||
args[i]);
|
args[i]);
|
||||||
for (aut = autoloads; aut; aut = aut->next)
|
for (aut = autoloads; aut; aut = aut->next)
|
||||||
if (grub_strcmp (args[i], aut->name) == 0
|
if (grub_strcmp (args[i], aut->name) == 0
|
||||||
|
|| (grub_strcmp (args[i], "ofconsole") == 0
|
||||||
|
&& grub_strcmp ("console", aut->name) == 0)
|
||||||
|| (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*'
|
|| (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*'
|
||||||
&& grub_memcmp (args[i], aut->name,
|
&& grub_memcmp (args[i], aut->name,
|
||||||
grub_strlen (aut->name) - 1) == 0))
|
grub_strlen (aut->name) - 1) == 0))
|
||||||
|
@ -130,14 +137,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
||||||
for (i = 1; i < argc; i++)
|
for (i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
for (term = *disabled; term; term = term->next)
|
for (term = *disabled; term; term = term->next)
|
||||||
if (grub_strcmp (args[i], term->name) == 0)
|
if (grub_strcmp (args[i], term->name) == 0
|
||||||
|
|| (grub_strcmp (args[i], "ofconsole") == 0
|
||||||
|
&& grub_strcmp ("console", term->name) == 0))
|
||||||
break;
|
break;
|
||||||
if (term)
|
if (term)
|
||||||
{
|
{
|
||||||
if (term->init && term->init (term) != GRUB_ERR_NONE)
|
if (term->init && term->init (term) != GRUB_ERR_NONE)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
grub_list_remove (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
|
grub_list_remove (GRUB_AS_LIST (term));
|
||||||
grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
|
grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,14 +158,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
||||||
for (i = 1; i < argc; i++)
|
for (i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
for (term = *enabled; term; term = term->next)
|
for (term = *enabled; term; term = term->next)
|
||||||
if (grub_strcmp (args[i], term->name) == 0)
|
if (grub_strcmp (args[i], term->name) == 0
|
||||||
|
|| (grub_strcmp (args[i], "ofconsole") == 0
|
||||||
|
&& grub_strcmp ("console", term->name) == 0))
|
||||||
break;
|
break;
|
||||||
if (term)
|
if (term)
|
||||||
{
|
{
|
||||||
if (!term->next && term == *enabled)
|
if (!term->next && term == *enabled)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
"can't remove the last terminal");
|
"can't remove the last terminal");
|
||||||
grub_list_remove (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
|
grub_list_remove (GRUB_AS_LIST (term));
|
||||||
if (term->fini)
|
if (term->fini)
|
||||||
term->fini (term);
|
term->fini (term);
|
||||||
grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
|
grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
|
||||||
|
@ -167,14 +178,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
{
|
{
|
||||||
for (term = *disabled; term; term = term->next)
|
for (term = *disabled; term; term = term->next)
|
||||||
if (grub_strcmp (args[i], term->name) == 0)
|
if (grub_strcmp (args[i], term->name) == 0
|
||||||
|
|| (grub_strcmp (args[i], "ofconsole") == 0
|
||||||
|
&& grub_strcmp ("console", term->name) == 0))
|
||||||
break;
|
break;
|
||||||
if (term)
|
if (term)
|
||||||
{
|
{
|
||||||
if (term->init && term->init (term) != GRUB_ERR_NONE)
|
if (term->init && term->init (term) != GRUB_ERR_NONE)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
grub_list_remove (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
|
grub_list_remove (GRUB_AS_LIST (term));
|
||||||
grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
|
grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,14 +198,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
||||||
{
|
{
|
||||||
next = term->next;
|
next = term->next;
|
||||||
for (i = 0; i < argc; i++)
|
for (i = 0; i < argc; i++)
|
||||||
if (grub_strcmp (args[i], term->name) == 0)
|
if (grub_strcmp (args[i], term->name) == 0
|
||||||
|
|| (grub_strcmp (args[i], "ofconsole") == 0
|
||||||
|
&& grub_strcmp ("console", term->name) == 0))
|
||||||
break;
|
break;
|
||||||
if (i == argc)
|
if (i == argc)
|
||||||
{
|
{
|
||||||
if (!term->next && term == *enabled)
|
if (!term->next && term == *enabled)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
"can't remove the last terminal");
|
"can't remove the last terminal");
|
||||||
grub_list_remove (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term));
|
grub_list_remove (GRUB_AS_LIST (term));
|
||||||
if (term->fini)
|
if (term->fini)
|
||||||
term->fini (term);
|
term->fini (term);
|
||||||
grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
|
grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
|
||||||
|
@ -208,6 +223,7 @@ grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)),
|
||||||
int argc, char **args)
|
int argc, char **args)
|
||||||
{
|
{
|
||||||
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, next);
|
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, next);
|
||||||
|
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, prev);
|
||||||
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, name);
|
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, name);
|
||||||
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, init);
|
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, init);
|
||||||
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, fini);
|
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, fini);
|
||||||
|
@ -224,6 +240,7 @@ grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)),
|
||||||
int argc, char **args)
|
int argc, char **args)
|
||||||
{
|
{
|
||||||
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, next);
|
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, next);
|
||||||
|
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, prev);
|
||||||
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, name);
|
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, name);
|
||||||
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, init);
|
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, init);
|
||||||
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, fini);
|
(void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, fini);
|
||||||
|
|
|
@ -47,7 +47,7 @@ grub_cmd_time (grub_command_t ctxt __attribute__ ((unused)),
|
||||||
(cmd->func) (cmd, argc - 1, &args[1]);
|
(cmd->func) (cmd, argc - 1, &args[1]);
|
||||||
end = grub_get_time_ms ();
|
end = grub_get_time_ms ();
|
||||||
|
|
||||||
grub_printf ("Elapsed time: %d.%03d seconds \n", (end - start) / 1000,
|
grub_printf_ (N_("Elapsed time: %d.%03d seconds \n"), (end - start) / 1000,
|
||||||
(end - start) % 1000);
|
(end - start) % 1000);
|
||||||
|
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
|
@ -52,10 +52,10 @@ hook (const struct grub_video_mode_info *info)
|
||||||
grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp);
|
grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp);
|
||||||
|
|
||||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
|
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
|
||||||
grub_printf ("Text-only ");
|
grub_xputs (_("Text-only "));
|
||||||
/* Show mask and position details for direct color modes. */
|
/* Show mask and position details for direct color modes. */
|
||||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB)
|
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB)
|
||||||
grub_printf ("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d",
|
grub_printf_ (N_("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d"),
|
||||||
info->red_mask_size,
|
info->red_mask_size,
|
||||||
info->green_mask_size,
|
info->green_mask_size,
|
||||||
info->blue_mask_size,
|
info->blue_mask_size,
|
||||||
|
@ -65,23 +65,23 @@ hook (const struct grub_video_mode_info *info)
|
||||||
info->blue_field_pos,
|
info->blue_field_pos,
|
||||||
info->reserved_field_pos);
|
info->reserved_field_pos);
|
||||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
|
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
|
||||||
grub_printf ("Packed ");
|
grub_xputs (_("Packed "));
|
||||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV)
|
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV)
|
||||||
grub_printf ("YUV ");
|
grub_xputs (_("YUV "));
|
||||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR)
|
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR)
|
||||||
grub_printf ("Planar ");
|
grub_xputs (_("Planar "));
|
||||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES)
|
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES)
|
||||||
grub_printf ("Hercules ");
|
grub_xputs (_("Hercules "));
|
||||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA)
|
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA)
|
||||||
grub_printf ("CGA ");
|
grub_xputs (_("CGA "));
|
||||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_NONCHAIN4)
|
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_NONCHAIN4)
|
||||||
grub_printf ("Non-chain 4 ");
|
grub_xputs (_("Non-chain 4 "));
|
||||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP)
|
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP)
|
||||||
grub_printf ("Monochrome ");
|
grub_xputs (_("Monochrome "));
|
||||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN)
|
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN)
|
||||||
grub_printf ("Unknown ");
|
grub_xputs (_("Unknown "));
|
||||||
|
|
||||||
grub_printf ("\n");
|
grub_xputs ("\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -93,19 +93,19 @@ print_edid (struct grub_video_edid_info *edid_info)
|
||||||
|
|
||||||
if (grub_video_edid_checksum (edid_info))
|
if (grub_video_edid_checksum (edid_info))
|
||||||
{
|
{
|
||||||
grub_printf (" EDID checksum invalid\n");
|
grub_puts_ (N_(" EDID checksum invalid"));
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_printf (" EDID version: %u.%u\n",
|
grub_printf_ (N_(" EDID version: %u.%u\n"),
|
||||||
edid_info->version, edid_info->revision);
|
edid_info->version, edid_info->revision);
|
||||||
if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height)
|
if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height)
|
||||||
== GRUB_ERR_NONE)
|
== GRUB_ERR_NONE)
|
||||||
grub_printf (" Preferred mode: %ux%u\n", edid_width, edid_height);
|
grub_printf_ (N_(" Preferred mode: %ux%u\n"), edid_width, edid_height);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
grub_printf (" No preferred mode available\n");
|
grub_printf_ (N_(" No preferred mode available\n"));
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,20 +147,20 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
|
||||||
id = grub_video_get_driver_id ();
|
id = grub_video_get_driver_id ();
|
||||||
|
|
||||||
grub_printf ("List of supported video modes:\n");
|
grub_puts_ (N_("List of supported video modes:"));
|
||||||
grub_printf ("Legend: P=Packed pixel, D=Direct color, "
|
grub_puts_ (N_("Legend: P=Packed pixel, D=Direct color, "
|
||||||
"mask/pos=R/G/B/reserved\n");
|
"mask/pos=R/G/B/reserved"));
|
||||||
|
|
||||||
FOR_VIDEO_ADAPTERS (adapter)
|
FOR_VIDEO_ADAPTERS (adapter)
|
||||||
{
|
{
|
||||||
struct grub_video_mode_info info;
|
struct grub_video_mode_info info;
|
||||||
struct grub_video_edid_info edid_info;
|
struct grub_video_edid_info edid_info;
|
||||||
|
|
||||||
grub_printf ("Adapter '%s':\n", adapter->name);
|
grub_printf_ (N_("Adapter '%s':\n"), adapter->name);
|
||||||
|
|
||||||
if (!adapter->iterate)
|
if (!adapter->iterate)
|
||||||
{
|
{
|
||||||
grub_printf (" No info available\n");
|
grub_puts_ (N_(" No info available"));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
|
||||||
{
|
{
|
||||||
if (adapter->init ())
|
if (adapter->init ())
|
||||||
{
|
{
|
||||||
grub_printf (" Failed\n");
|
grub_puts_ (N_(" Failed"));
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -215,12 +215,13 @@ static grub_command_t cmd_vbe;
|
||||||
|
|
||||||
GRUB_MOD_INIT(videoinfo)
|
GRUB_MOD_INIT(videoinfo)
|
||||||
{
|
{
|
||||||
cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, "[WxH[xD]]",
|
cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, N_("[WxH[xD]]"),
|
||||||
N_("List available video modes. If "
|
N_("List available video modes. If "
|
||||||
"resolution is given show only modes"
|
"resolution is given show only modes"
|
||||||
" matching it."));
|
" matching it."));
|
||||||
#ifdef GRUB_MACHINE_PCBIOS
|
#ifdef GRUB_MACHINE_PCBIOS
|
||||||
cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo, "[WxH[xD]]",
|
cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo,
|
||||||
|
N_("[WxH[xD]]"),
|
||||||
N_("List available video modes. If "
|
N_("List available video modes. If "
|
||||||
"resolution is given show only modes"
|
"resolution is given show only modes"
|
||||||
" matching it."));
|
" matching it."));
|
||||||
|
|
|
@ -74,6 +74,8 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
|
||||||
grub_video_create_render_target (&text_layer, width, height,
|
grub_video_create_render_target (&text_layer, width, height,
|
||||||
GRUB_VIDEO_MODE_TYPE_RGB
|
GRUB_VIDEO_MODE_TYPE_RGB
|
||||||
| GRUB_VIDEO_MODE_TYPE_ALPHA);
|
| GRUB_VIDEO_MODE_TYPE_ALPHA);
|
||||||
|
if (!text_layer)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
grub_video_set_active_render_target (text_layer);
|
grub_video_set_active_render_target (text_layer);
|
||||||
|
|
||||||
|
@ -191,6 +193,11 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
grub_video_delete_render_target (text_layer);
|
||||||
|
grub_video_restore ();
|
||||||
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_command_t cmd;
|
static grub_command_t cmd;
|
||||||
|
|
|
@ -326,10 +326,15 @@ match_files (const char *prefix, const char *suffix, const char *end,
|
||||||
if (! fs)
|
if (! fs)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
if (dir[0] == '(')
|
||||||
|
{
|
||||||
path = grub_strchr (dir, ')');
|
path = grub_strchr (dir, ')');
|
||||||
if (! path)
|
if (!path)
|
||||||
goto fail;
|
goto fail;
|
||||||
path++;
|
path++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
path = dir;
|
||||||
|
|
||||||
if (fs->dir (dev, path, match))
|
if (fs->dir (dev, path, match))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -431,25 +436,8 @@ wildcard_expand (const char *s, char ***strs)
|
||||||
if (start == noregexop) /* device part has regexop */
|
if (start == noregexop) /* device part has regexop */
|
||||||
paths = match_devices (®exp, *start != '(');
|
paths = match_devices (®exp, *start != '(');
|
||||||
|
|
||||||
else if (*start == '(') /* device part explicit wo regexop */
|
else /* device part explicit wo regexop */
|
||||||
paths = match_files ("", start, noregexop, ®exp);
|
paths = match_files ("", start, noregexop, ®exp);
|
||||||
|
|
||||||
else if (*start == '/') /* no device part */
|
|
||||||
{
|
|
||||||
char *root;
|
|
||||||
char *prefix;
|
|
||||||
|
|
||||||
root = grub_env_get ("root");
|
|
||||||
if (! root)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
prefix = grub_xasprintf ("(%s)", root);
|
|
||||||
if (! prefix)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
paths = match_files (prefix, start, noregexop, ®exp);
|
|
||||||
grub_free (prefix);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,10 +51,18 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
|
||||||
char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
|
char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
|
||||||
char *ptr;
|
char *ptr;
|
||||||
grub_uint8_t ctx[GRUB_MD_MD5->contextsize];
|
grub_uint8_t ctx[GRUB_MD_MD5->contextsize];
|
||||||
|
int low = 0;
|
||||||
|
|
||||||
if (argc < 1)
|
if (argc < 1)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required");
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required");
|
||||||
|
|
||||||
|
if (argc > 1 && grub_strcmp (args[0], "-l") == 0)
|
||||||
|
{
|
||||||
|
low = 1;
|
||||||
|
argc--;
|
||||||
|
args++;
|
||||||
|
}
|
||||||
|
|
||||||
serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16));
|
serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16));
|
||||||
|
|
||||||
GRUB_MD_MD5->init (&ctx);
|
GRUB_MD_MD5->init (&ctx);
|
||||||
|
@ -75,10 +83,11 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
|
||||||
(unsigned int) xnu_uuid[10], (unsigned int) xnu_uuid[11],
|
(unsigned int) xnu_uuid[10], (unsigned int) xnu_uuid[11],
|
||||||
(unsigned int) xnu_uuid[12], (unsigned int) xnu_uuid[13],
|
(unsigned int) xnu_uuid[12], (unsigned int) xnu_uuid[13],
|
||||||
(unsigned int) xnu_uuid[14], (unsigned int) xnu_uuid[15]);
|
(unsigned int) xnu_uuid[14], (unsigned int) xnu_uuid[15]);
|
||||||
|
if (!low)
|
||||||
for (ptr = uuid_string; *ptr; ptr++)
|
for (ptr = uuid_string; *ptr; ptr++)
|
||||||
*ptr = grub_toupper (*ptr);
|
*ptr = grub_toupper (*ptr);
|
||||||
if (argc == 1)
|
if (argc == 1)
|
||||||
grub_printf ("%s", uuid_string);
|
grub_printf ("%s\n", uuid_string);
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
grub_env_set (args[1], uuid_string);
|
grub_env_set (args[1], uuid_string);
|
||||||
|
|
||||||
|
@ -91,9 +100,10 @@ static grub_command_t cmd;
|
||||||
GRUB_MOD_INIT (xnu_uuid)
|
GRUB_MOD_INIT (xnu_uuid)
|
||||||
{
|
{
|
||||||
cmd = grub_register_command ("xnu_uuid", grub_cmd_xnu_uuid,
|
cmd = grub_register_command ("xnu_uuid", grub_cmd_xnu_uuid,
|
||||||
N_("GRUBUUID [VARNAME]"),
|
N_("[-l] GRUBUUID [VARNAME]"),
|
||||||
N_("Transform 64-bit UUID to format "
|
N_("Transform 64-bit UUID to format "
|
||||||
"suitable for XNU."));
|
"suitable for XNU. If -l is given keep "
|
||||||
|
"it lowercase as done by blkid."));
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI (xnu_uuid)
|
GRUB_MOD_FINI (xnu_uuid)
|
||||||
|
|
|
@ -121,6 +121,7 @@ enum
|
||||||
struct grub_ahci_device
|
struct grub_ahci_device
|
||||||
{
|
{
|
||||||
struct grub_ahci_device *next;
|
struct grub_ahci_device *next;
|
||||||
|
struct grub_ahci_device **prev;
|
||||||
volatile struct grub_ahci_hba *hba;
|
volatile struct grub_ahci_hba *hba;
|
||||||
int port;
|
int port;
|
||||||
int num;
|
int num;
|
||||||
|
@ -305,7 +306,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
||||||
else
|
else
|
||||||
grub_dprintf ("ahci", "AHCI is already in OS mode\n");
|
grub_dprintf ("ahci", "AHCI is already in OS mode\n");
|
||||||
|
|
||||||
if (~(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN))
|
if (!(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN))
|
||||||
grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n");
|
grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n");
|
||||||
else
|
else
|
||||||
grub_dprintf ("ahci", "AHCI is in AHCI mode.\n");
|
grub_dprintf ("ahci", "AHCI is in AHCI mode.\n");
|
||||||
|
@ -692,6 +693,7 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata)
|
||||||
|
|
||||||
ata->data = dev;
|
ata->data = dev;
|
||||||
ata->dma = 1;
|
ata->dma = 1;
|
||||||
|
ata->maxbuffer = GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH;
|
||||||
ata->present = &dev->present;
|
ata->present = &dev->present;
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
@ -706,7 +708,7 @@ static struct grub_ata_dev grub_ahci_dev =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void *fini_hnd;
|
static struct grub_preboot *fini_hnd;
|
||||||
|
|
||||||
GRUB_MOD_INIT(ahci)
|
GRUB_MOD_INIT(ahci)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
static grub_arc_fileno_t last_handle = 0;
|
static grub_arc_fileno_t last_handle = 0;
|
||||||
static char *last_path = NULL;
|
static char *last_path = NULL;
|
||||||
|
static int handle_writable = 0;
|
||||||
|
|
||||||
static int lnum = 0;
|
static int lnum = 0;
|
||||||
|
|
||||||
|
@ -100,11 +101,12 @@ grub_arcdisk_iterate (int (*hook_in) (const char *name),
|
||||||
#define RAW_SUFFIX "partition(10)"
|
#define RAW_SUFFIX "partition(10)"
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
reopen (const char *name)
|
reopen (const char *name, int writable)
|
||||||
{
|
{
|
||||||
grub_arc_fileno_t handle;
|
grub_arc_fileno_t handle;
|
||||||
|
|
||||||
if (last_path && grub_strcmp (last_path, name) == 0)
|
if (last_path && grub_strcmp (last_path, name) == 0
|
||||||
|
&& (!writable || handle_writable))
|
||||||
{
|
{
|
||||||
grub_dprintf ("arcdisk", "using already opened %s\n", name);
|
grub_dprintf ("arcdisk", "using already opened %s\n", name);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
@ -115,12 +117,16 @@ reopen (const char *name)
|
||||||
grub_free (last_path);
|
grub_free (last_path);
|
||||||
last_path = NULL;
|
last_path = NULL;
|
||||||
last_handle = 0;
|
last_handle = 0;
|
||||||
|
handle_writable = 0;
|
||||||
}
|
}
|
||||||
if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle))
|
if (GRUB_ARC_FIRMWARE_VECTOR->open (name,
|
||||||
|
writable ? GRUB_ARC_FILE_ACCESS_OPEN_RW
|
||||||
|
: GRUB_ARC_FILE_ACCESS_OPEN_RO, &handle))
|
||||||
{
|
{
|
||||||
grub_dprintf ("arcdisk", "couldn't open %s\n", name);
|
grub_dprintf ("arcdisk", "couldn't open %s\n", name);
|
||||||
return grub_error (GRUB_ERR_IO, "couldn't open %s", name);
|
return grub_error (GRUB_ERR_IO, "couldn't open %s", name);
|
||||||
}
|
}
|
||||||
|
handle_writable = writable;
|
||||||
last_path = grub_strdup (name);
|
last_path = grub_strdup (name);
|
||||||
if (!last_path)
|
if (!last_path)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
@ -180,7 +186,7 @@ grub_arcdisk_open (const char *name, grub_disk_t disk)
|
||||||
if (!hash)
|
if (!hash)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
err = reopen (fullname);
|
err = reopen (fullname, 0);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -234,7 +240,7 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
grub_uint64_t totl = size << 9;
|
grub_uint64_t totl = size << 9;
|
||||||
grub_arc_err_t r;
|
grub_arc_err_t r;
|
||||||
|
|
||||||
err = reopen (disk->data);
|
err = reopen (disk->data, 0);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0);
|
r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0);
|
||||||
|
@ -258,12 +264,36 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_arcdisk_write (grub_disk_t disk __attribute ((unused)),
|
grub_arcdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
grub_disk_addr_t sector __attribute ((unused)),
|
grub_size_t size, const char *buf)
|
||||||
grub_size_t size __attribute ((unused)),
|
|
||||||
const char *buf __attribute ((unused)))
|
|
||||||
{
|
{
|
||||||
return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
grub_err_t err;
|
||||||
|
grub_uint64_t pos = sector << 9;
|
||||||
|
unsigned long count;
|
||||||
|
grub_uint64_t totl = size << 9;
|
||||||
|
grub_arc_err_t r;
|
||||||
|
|
||||||
|
err = reopen (disk->data, 1);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0);
|
||||||
|
if (r)
|
||||||
|
{
|
||||||
|
grub_dprintf ("arcdisk", "seek to 0x%" PRIxGRUB_UINT64_T " failed: %ld\n",
|
||||||
|
pos, r);
|
||||||
|
return grub_error (GRUB_ERR_IO, "couldn't seek");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (totl)
|
||||||
|
{
|
||||||
|
if (GRUB_ARC_FIRMWARE_VECTOR->write (last_handle, buf,
|
||||||
|
totl, &count))
|
||||||
|
return grub_error (GRUB_ERR_WRITE_ERROR, "write failed");
|
||||||
|
totl -= count;
|
||||||
|
buf += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct grub_disk_dev grub_arcdisk_dev =
|
static struct grub_disk_dev grub_arcdisk_dev =
|
||||||
|
|
|
@ -29,29 +29,27 @@ static grub_ata_dev_t grub_ata_dev_list;
|
||||||
|
|
||||||
/* Byteorder has to be changed before strings can be read. */
|
/* Byteorder has to be changed before strings can be read. */
|
||||||
static void
|
static void
|
||||||
grub_ata_strncpy (char *dst, char *src, grub_size_t len)
|
grub_ata_strncpy (grub_uint16_t *dst16, grub_uint16_t *src16, grub_size_t len)
|
||||||
{
|
{
|
||||||
grub_uint16_t *src16 = (grub_uint16_t *) src;
|
|
||||||
grub_uint16_t *dst16 = (grub_uint16_t *) dst;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < len / 2; i++)
|
for (i = 0; i < len / 2; i++)
|
||||||
*(dst16++) = grub_be_to_cpu16 (*(src16++));
|
*(dst16++) = grub_be_to_cpu16 (*(src16++));
|
||||||
dst[len] = '\0';
|
dst16[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
grub_ata_dumpinfo (struct grub_ata *dev, char *info)
|
grub_ata_dumpinfo (struct grub_ata *dev, grub_uint16_t *info)
|
||||||
{
|
{
|
||||||
char text[41];
|
grub_uint16_t text[21];
|
||||||
|
|
||||||
/* The device information was read, dump it for debugging. */
|
/* The device information was read, dump it for debugging. */
|
||||||
grub_ata_strncpy (text, info + 20, 20);
|
grub_ata_strncpy (text, info + 10, 20);
|
||||||
grub_dprintf ("ata", "Serial: %s\n", text);
|
grub_dprintf ("ata", "Serial: %s\n", (char *) text);
|
||||||
grub_ata_strncpy (text, info + 46, 8);
|
grub_ata_strncpy (text, info + 23, 8);
|
||||||
grub_dprintf ("ata", "Firmware: %s\n", text);
|
grub_dprintf ("ata", "Firmware: %s\n", (char *) text);
|
||||||
grub_ata_strncpy (text, info + 54, 40);
|
grub_ata_strncpy (text, info + 27, 40);
|
||||||
grub_dprintf ("ata", "Model: %s\n", text);
|
grub_dprintf ("ata", "Model: %s\n", (char *) text);
|
||||||
|
|
||||||
if (! dev->atapi)
|
if (! dev->atapi)
|
||||||
{
|
{
|
||||||
|
@ -65,7 +63,7 @@ static grub_err_t
|
||||||
grub_atapi_identify (struct grub_ata *dev)
|
grub_atapi_identify (struct grub_ata *dev)
|
||||||
{
|
{
|
||||||
struct grub_disk_ata_pass_through_parms parms;
|
struct grub_disk_ata_pass_through_parms parms;
|
||||||
char *info;
|
grub_uint16_t *info;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
|
||||||
info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
|
info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
|
||||||
|
@ -105,17 +103,19 @@ static grub_err_t
|
||||||
grub_ata_identify (struct grub_ata *dev)
|
grub_ata_identify (struct grub_ata *dev)
|
||||||
{
|
{
|
||||||
struct grub_disk_ata_pass_through_parms parms;
|
struct grub_disk_ata_pass_through_parms parms;
|
||||||
char *info;
|
grub_uint64_t *info64;
|
||||||
|
grub_uint32_t *info32;
|
||||||
grub_uint16_t *info16;
|
grub_uint16_t *info16;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
|
||||||
info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
|
info64 = grub_malloc (GRUB_DISK_SECTOR_SIZE);
|
||||||
if (! info)
|
info32 = (grub_uint32_t *) info64;
|
||||||
|
info16 = (grub_uint16_t *) info64;
|
||||||
|
if (! info16)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
info16 = (grub_uint16_t *) info;
|
|
||||||
grub_memset (&parms, 0, sizeof (parms));
|
grub_memset (&parms, 0, sizeof (parms));
|
||||||
parms.buffer = info;
|
parms.buffer = info16;
|
||||||
parms.size = GRUB_DISK_SECTOR_SIZE;
|
parms.size = GRUB_DISK_SECTOR_SIZE;
|
||||||
parms.taskfile.disk = 0xE0;
|
parms.taskfile.disk = 0xE0;
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ grub_ata_identify (struct grub_ata *dev)
|
||||||
if (err || parms.size != GRUB_DISK_SECTOR_SIZE)
|
if (err || parms.size != GRUB_DISK_SECTOR_SIZE)
|
||||||
{
|
{
|
||||||
grub_uint8_t sts = parms.taskfile.status;
|
grub_uint8_t sts = parms.taskfile.status;
|
||||||
grub_free (info);
|
grub_free (info16);
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ
|
if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ
|
||||||
| GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR
|
| GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR
|
||||||
|
@ -167,14 +167,14 @@ grub_ata_identify (struct grub_ata *dev)
|
||||||
|
|
||||||
/* Determine the amount of sectors. */
|
/* Determine the amount of sectors. */
|
||||||
if (dev->addr != GRUB_ATA_LBA48)
|
if (dev->addr != GRUB_ATA_LBA48)
|
||||||
dev->size = grub_le_to_cpu32(*((grub_uint32_t *) &info16[60]));
|
dev->size = grub_le_to_cpu32 (info32[30]);
|
||||||
else
|
else
|
||||||
dev->size = grub_le_to_cpu64(*((grub_uint64_t *) &info16[100]));
|
dev->size = grub_le_to_cpu64 (info64[25]);
|
||||||
|
|
||||||
if (info16[106] & (1 << 12))
|
if (info16[106] & (1 << 12))
|
||||||
{
|
{
|
||||||
grub_uint32_t secsize;
|
grub_uint32_t secsize;
|
||||||
secsize = grub_le_to_cpu32 (*((grub_uint32_t *) &info16[117]));
|
secsize = grub_le_to_cpu32 (grub_get_unaligned32 (&info16[117]));
|
||||||
if (secsize & (secsize - 1) || !secsize
|
if (secsize & (secsize - 1) || !secsize
|
||||||
|| secsize > 1048576)
|
|| secsize > 1048576)
|
||||||
secsize = 256;
|
secsize = 256;
|
||||||
|
@ -191,9 +191,9 @@ grub_ata_identify (struct grub_ata *dev)
|
||||||
dev->heads = info16[3];
|
dev->heads = info16[3];
|
||||||
dev->sectors_per_track = info16[6];
|
dev->sectors_per_track = info16[6];
|
||||||
|
|
||||||
grub_ata_dumpinfo (dev, info);
|
grub_ata_dumpinfo (dev, info16);
|
||||||
|
|
||||||
grub_free(info);
|
grub_free (info16);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -278,6 +278,7 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
grub_ata_addressing_t addressing = ata->addr;
|
grub_ata_addressing_t addressing = ata->addr;
|
||||||
grub_size_t batch;
|
grub_size_t batch;
|
||||||
int cmd, cmd_write;
|
int cmd, cmd_write;
|
||||||
|
grub_size_t nsectors = 0;
|
||||||
|
|
||||||
grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n",
|
grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n",
|
||||||
(unsigned long long) size, rw);
|
(unsigned long long) size, rw);
|
||||||
|
@ -316,7 +317,9 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_size_t nsectors = 0;
|
if (batch > (ata->maxbuffer >> ata->log_sector_size))
|
||||||
|
batch = (ata->maxbuffer >> ata->log_sector_size);
|
||||||
|
|
||||||
while (nsectors < size)
|
while (nsectors < size)
|
||||||
{
|
{
|
||||||
struct grub_disk_ata_pass_through_parms parms;
|
struct grub_disk_ata_pass_through_parms parms;
|
||||||
|
@ -534,7 +537,7 @@ grub_atapi_write (struct grub_scsi *scsi __attribute__((unused)),
|
||||||
grub_size_t cmdsize __attribute__((unused)),
|
grub_size_t cmdsize __attribute__((unused)),
|
||||||
char *cmd __attribute__((unused)),
|
char *cmd __attribute__((unused)),
|
||||||
grub_size_t size __attribute__((unused)),
|
grub_size_t size __attribute__((unused)),
|
||||||
char *buf __attribute__((unused)))
|
const char *buf __attribute__((unused)))
|
||||||
{
|
{
|
||||||
// XXX: scsi.mod does not use write yet.
|
// XXX: scsi.mod does not use write yet.
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ATAPI write not implemented");
|
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ATAPI write not implemented");
|
||||||
|
|
|
@ -128,6 +128,29 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
|
||||||
return GPG_ERR_NO_ERROR;
|
return GPG_ERR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gcry_err_code_t
|
||||||
|
grub_crypto_pcbc_encrypt (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);
|
||||||
|
grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
|
||||||
|
cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
|
||||||
|
grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize);
|
||||||
|
}
|
||||||
|
return GPG_ERR_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
struct lrw_sector
|
struct lrw_sector
|
||||||
{
|
{
|
||||||
grub_uint8_t low[GRUB_CRYPTODISK_GF_BYTES];
|
grub_uint8_t low[GRUB_CRYPTODISK_GF_BYTES];
|
||||||
|
@ -189,17 +212,18 @@ lrw_xor (const struct lrw_sector *sec,
|
||||||
dev->lrw_precalc, sec->low_byte * GRUB_CRYPTODISK_GF_BYTES);
|
dev->lrw_precalc, sec->low_byte * GRUB_CRYPTODISK_GF_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcry_err_code_t
|
static gcry_err_code_t
|
||||||
grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
|
||||||
grub_uint8_t * data, grub_size_t len,
|
grub_uint8_t * data, grub_size_t len,
|
||||||
grub_disk_addr_t sector)
|
grub_disk_addr_t sector, int encrypt)
|
||||||
{
|
{
|
||||||
grub_size_t i;
|
grub_size_t i;
|
||||||
gcry_err_code_t err;
|
gcry_err_code_t err;
|
||||||
|
|
||||||
/* The only mode without IV. */
|
/* The only mode without IV. */
|
||||||
if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey)
|
if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey)
|
||||||
return grub_crypto_ecb_decrypt (dev->cipher, data, data, len);
|
return (encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len)
|
||||||
|
: grub_crypto_ecb_decrypt (dev->cipher, data, data, len));
|
||||||
|
|
||||||
for (i = 0; i < len; i += (1U << dev->log_sector_size))
|
for (i = 0; i < len; i += (1U << dev->log_sector_size))
|
||||||
{
|
{
|
||||||
|
@ -269,6 +293,10 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
||||||
switch (dev->mode)
|
switch (dev->mode)
|
||||||
{
|
{
|
||||||
case GRUB_CRYPTODISK_MODE_CBC:
|
case GRUB_CRYPTODISK_MODE_CBC:
|
||||||
|
if (encrypt)
|
||||||
|
err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i,
|
||||||
|
(1U << dev->log_sector_size), iv);
|
||||||
|
else
|
||||||
err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
|
err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
|
||||||
(1U << dev->log_sector_size), iv);
|
(1U << dev->log_sector_size), iv);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -276,6 +304,10 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GRUB_CRYPTODISK_MODE_PCBC:
|
case GRUB_CRYPTODISK_MODE_PCBC:
|
||||||
|
if (encrypt)
|
||||||
|
err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i,
|
||||||
|
(1U << dev->log_sector_size), iv);
|
||||||
|
else
|
||||||
err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
|
err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
|
||||||
(1U << dev->log_sector_size), iv);
|
(1U << dev->log_sector_size), iv);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -294,6 +326,11 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
||||||
{
|
{
|
||||||
grub_crypto_xor (data + i + j, data + i + j, iv,
|
grub_crypto_xor (data + i + j, data + i + j, iv,
|
||||||
dev->cipher->cipher->blocksize);
|
dev->cipher->cipher->blocksize);
|
||||||
|
if (encrypt)
|
||||||
|
err = grub_crypto_ecb_encrypt (dev->cipher, data + i + j,
|
||||||
|
data + i + j,
|
||||||
|
dev->cipher->cipher->blocksize);
|
||||||
|
else
|
||||||
err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j,
|
err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j,
|
||||||
data + i + j,
|
data + i + j,
|
||||||
dev->cipher->cipher->blocksize);
|
dev->cipher->cipher->blocksize);
|
||||||
|
@ -312,6 +349,11 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
||||||
generate_lrw_sector (&sec, dev, (grub_uint8_t *) iv);
|
generate_lrw_sector (&sec, dev, (grub_uint8_t *) iv);
|
||||||
lrw_xor (&sec, dev, data + i);
|
lrw_xor (&sec, dev, data + i);
|
||||||
|
|
||||||
|
if (encrypt)
|
||||||
|
err = grub_crypto_ecb_encrypt (dev->cipher, data + i,
|
||||||
|
data + i,
|
||||||
|
(1U << dev->log_sector_size));
|
||||||
|
else
|
||||||
err = grub_crypto_ecb_decrypt (dev->cipher, data + i,
|
err = grub_crypto_ecb_decrypt (dev->cipher, data + i,
|
||||||
data + i,
|
data + i,
|
||||||
(1U << dev->log_sector_size));
|
(1U << dev->log_sector_size));
|
||||||
|
@ -321,6 +363,10 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GRUB_CRYPTODISK_MODE_ECB:
|
case GRUB_CRYPTODISK_MODE_ECB:
|
||||||
|
if (encrypt)
|
||||||
|
grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i,
|
||||||
|
(1U << dev->log_sector_size));
|
||||||
|
else
|
||||||
grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
|
grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
|
||||||
(1U << dev->log_sector_size));
|
(1U << dev->log_sector_size));
|
||||||
break;
|
break;
|
||||||
|
@ -332,6 +378,14 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
||||||
return GPG_ERR_NO_ERROR;
|
return GPG_ERR_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gcry_err_code_t
|
||||||
|
grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
||||||
|
grub_uint8_t * data, grub_size_t len,
|
||||||
|
grub_disk_addr_t sector)
|
||||||
|
{
|
||||||
|
return grub_cryptodisk_endecrypt (dev, data, len, sector, 0);
|
||||||
|
}
|
||||||
|
|
||||||
gcry_err_code_t
|
gcry_err_code_t
|
||||||
grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t keysize)
|
grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t keysize)
|
||||||
{
|
{
|
||||||
|
@ -526,19 +580,61 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err);
|
grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
gcry_err = grub_cryptodisk_decrypt (dev, (grub_uint8_t *) buf,
|
gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
|
||||||
size << disk->log_sector_size,
|
size << disk->log_sector_size,
|
||||||
sector);
|
sector, 0);
|
||||||
return grub_crypto_gcry_error (gcry_err);
|
return grub_crypto_gcry_error (gcry_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_cryptodisk_write (grub_disk_t disk __attribute ((unused)),
|
grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
grub_disk_addr_t sector __attribute ((unused)),
|
grub_size_t size, const char *buf)
|
||||||
grub_size_t size __attribute ((unused)),
|
|
||||||
const char *buf __attribute ((unused)))
|
|
||||||
{
|
{
|
||||||
return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
|
||||||
|
gcry_err_code_t gcry_err;
|
||||||
|
char *tmp;
|
||||||
|
grub_err_t 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_write (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
|
||||||
|
|
||||||
|
tmp = grub_malloc (size << disk->log_sector_size);
|
||||||
|
if (!tmp)
|
||||||
|
return grub_errno;
|
||||||
|
grub_memcpy (tmp, buf, size << disk->log_sector_size);
|
||||||
|
|
||||||
|
grub_dprintf ("cryptodisk",
|
||||||
|
"Writing %" PRIuGRUB_SIZE " sectors to sector 0x%"
|
||||||
|
PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
|
||||||
|
size, sector, dev->offset);
|
||||||
|
|
||||||
|
gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp,
|
||||||
|
size << disk->log_sector_size,
|
||||||
|
sector, 1);
|
||||||
|
if (gcry_err)
|
||||||
|
{
|
||||||
|
grub_free (tmp);
|
||||||
|
return grub_crypto_gcry_error (gcry_err);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = grub_disk_write (dev->source_disk,
|
||||||
|
(sector << (disk->log_sector_size
|
||||||
|
- GRUB_DISK_SECTOR_BITS)) + dev->offset,
|
||||||
|
0, size << disk->log_sector_size, tmp);
|
||||||
|
grub_free (tmp);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GRUB_UTIL
|
#ifdef GRUB_UTIL
|
||||||
|
@ -562,6 +658,7 @@ grub_cryptodisk_memberlist (grub_disk_t disk)
|
||||||
static void
|
static void
|
||||||
cryptodisk_cleanup (void)
|
cryptodisk_cleanup (void)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
grub_cryptodisk_t dev = cryptodisk_list;
|
grub_cryptodisk_t dev = cryptodisk_list;
|
||||||
grub_cryptodisk_t tmp;
|
grub_cryptodisk_t tmp;
|
||||||
|
|
||||||
|
@ -575,6 +672,7 @@ cryptodisk_cleanup (void)
|
||||||
grub_free (dev);
|
grub_free (dev);
|
||||||
dev = tmp;
|
dev = tmp;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
|
|
1081
grub-core/disk/diskfilter.c
Normal file
1081
grub-core/disk/diskfilter.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -22,7 +22,7 @@
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/raid.h>
|
#include <grub/diskfilter.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -90,70 +90,91 @@ struct grub_nv_super
|
||||||
struct grub_nv_array array; /* Array information */
|
struct grub_nv_array array; /* Array information */
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
static grub_err_t
|
static struct grub_diskfilter_vg *
|
||||||
grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array,
|
grub_dmraid_nv_detect (grub_disk_t disk,
|
||||||
|
struct grub_diskfilter_pv_id *id,
|
||||||
grub_disk_addr_t *start_sector)
|
grub_disk_addr_t *start_sector)
|
||||||
{
|
{
|
||||||
grub_disk_addr_t sector;
|
grub_disk_addr_t sector;
|
||||||
struct grub_nv_super sb;
|
struct grub_nv_super sb;
|
||||||
|
int level;
|
||||||
|
int layout;
|
||||||
|
grub_uint64_t disk_size;
|
||||||
|
char *uuid;
|
||||||
|
|
||||||
if (disk->partition)
|
if (disk->partition)
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "skip partition");
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "skip partition");
|
||||||
sector = grub_disk_get_size (disk) - 2;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sector = grub_disk_get_size (disk);
|
||||||
|
if (sector == GRUB_DISK_SIZE_UNKNOWN)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
sector -= 2;
|
||||||
if (grub_disk_read (disk, sector, 0, sizeof (sb), &sb))
|
if (grub_disk_read (disk, sector, 0, sizeof (sb), &sb))
|
||||||
return grub_errno;
|
return NULL;
|
||||||
|
|
||||||
if (grub_memcmp (sb.vendor, NV_ID_STRING, 6))
|
if (grub_memcmp (sb.vendor, NV_ID_STRING, 6))
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (sb.version != NV_VERSION)
|
if (sb.version != NV_VERSION)
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
{
|
||||||
|
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
"unknown version: %d.%d", sb.version);
|
"unknown version: %d.%d", sb.version);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
switch (sb.array.raid_level)
|
switch (sb.array.raid_level)
|
||||||
{
|
{
|
||||||
case NV_LEVEL_0:
|
case NV_LEVEL_0:
|
||||||
array->level = 0;
|
level = 0;
|
||||||
array->disk_size = sb.capacity / sb.array.total_volumes;
|
disk_size = sb.capacity / sb.array.total_volumes;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV_LEVEL_1:
|
case NV_LEVEL_1:
|
||||||
array->level = 1;
|
level = 1;
|
||||||
array->disk_size = sb.capacity;
|
disk_size = sb.capacity;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NV_LEVEL_5:
|
case NV_LEVEL_5:
|
||||||
array->level = 5;
|
level = 5;
|
||||||
array->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
|
layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
|
||||||
array->disk_size = sb.capacity / (sb.array.total_volumes - 1);
|
disk_size = sb.capacity / (sb.array.total_volumes - 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
"unsupported RAID level: %d", sb.array.raid_level);
|
"unsupported RAID level: %d", sb.array.raid_level);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
array->name = NULL;
|
uuid = grub_malloc (sizeof (sb.array.signature));
|
||||||
array->number = 0;
|
if (! uuid)
|
||||||
array->total_devs = sb.array.total_volumes;
|
return NULL;
|
||||||
array->chunk_size = sb.array.stripe_block_size;
|
|
||||||
array->index = sb.unit_number;
|
|
||||||
array->uuid_len = sizeof (sb.array.signature);
|
|
||||||
array->uuid = grub_malloc (sizeof (sb.array.signature));
|
|
||||||
if (! array->uuid)
|
|
||||||
return grub_errno;
|
|
||||||
|
|
||||||
grub_memcpy (array->uuid, (char *) &sb.array.signature,
|
grub_memcpy (uuid, (char *) &sb.array.signature,
|
||||||
sizeof (sb.array.signature));
|
sizeof (sb.array.signature));
|
||||||
|
|
||||||
|
id->uuidlen = 0;
|
||||||
|
id->id = sb.unit_number;
|
||||||
|
|
||||||
*start_sector = 0;
|
*start_sector = 0;
|
||||||
|
|
||||||
return 0;
|
return grub_diskfilter_make_raid (sizeof (sb.array.signature),
|
||||||
|
uuid, sb.array.total_volumes,
|
||||||
|
NULL, disk_size,
|
||||||
|
sb.array.stripe_block_size, layout,
|
||||||
|
level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct grub_raid grub_dmraid_nv_dev =
|
static struct grub_diskfilter grub_dmraid_nv_dev =
|
||||||
{
|
{
|
||||||
.name = "dmraid_nv",
|
.name = "dmraid_nv",
|
||||||
.detect = grub_dmraid_nv_detect,
|
.detect = grub_dmraid_nv_detect,
|
||||||
|
@ -162,10 +183,10 @@ static struct grub_raid grub_dmraid_nv_dev =
|
||||||
|
|
||||||
GRUB_MOD_INIT(dm_nv)
|
GRUB_MOD_INIT(dm_nv)
|
||||||
{
|
{
|
||||||
grub_raid_register (&grub_dmraid_nv_dev);
|
grub_diskfilter_register (&grub_dmraid_nv_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(dm_nv)
|
GRUB_MOD_FINI(dm_nv)
|
||||||
{
|
{
|
||||||
grub_raid_unregister (&grub_dmraid_nv_dev);
|
grub_diskfilter_unregister (&grub_dmraid_nv_dev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -664,38 +664,52 @@ grub_efidisk_get_device_handle (grub_disk_t disk)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NEEDED_BUFLEN sizeof ("XdXXXXXXXXXX")
|
||||||
|
static inline int
|
||||||
|
get_diskname_from_path_real (const grub_efi_device_path_t *path,
|
||||||
|
struct grub_efidisk_data *head,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
struct grub_efidisk_data *d;
|
||||||
|
for (d = head, count = 0; d; d = d->next, count++)
|
||||||
|
if (grub_efi_compare_device_paths (d->device_path, path) == 0)
|
||||||
|
{
|
||||||
|
grub_snprintf (buf, NEEDED_BUFLEN - 1, "d%d", count);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
get_diskname_from_path (const grub_efi_device_path_t *path,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
if (get_diskname_from_path_real (path, hd_devices, buf + 1))
|
||||||
|
{
|
||||||
|
buf[0] = 'h';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_diskname_from_path_real (path, fd_devices, buf + 1))
|
||||||
|
{
|
||||||
|
buf[0] = 'f';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_diskname_from_path_real (path, cd_devices, buf + 1))
|
||||||
|
{
|
||||||
|
buf[0] = 'c';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||||
{
|
{
|
||||||
grub_efi_device_path_t *dp, *ldp, *sdp;
|
grub_efi_device_path_t *dp, *ldp;
|
||||||
/* This is a hard disk partition. */
|
char device_name[NEEDED_BUFLEN];
|
||||||
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);
|
dp = grub_efi_get_device_path (handle);
|
||||||
if (! dp)
|
if (! dp)
|
||||||
|
@ -710,9 +724,11 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||||
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
|
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
|
||||||
{
|
{
|
||||||
char *partition_name = NULL;
|
char *partition_name = NULL;
|
||||||
char *device_name;
|
char *dev_name;
|
||||||
grub_efi_device_path_t *dup_dp, *dup_ldp;
|
grub_efi_device_path_t *dup_dp, *dup_ldp;
|
||||||
grub_efi_hard_drive_device_path_t hd;
|
grub_efi_hard_drive_device_path_t hd;
|
||||||
|
grub_disk_t parent = 0;
|
||||||
|
|
||||||
auto int find_partition (grub_disk_t disk, const grub_partition_t part);
|
auto int find_partition (grub_disk_t disk, const grub_partition_t part);
|
||||||
|
|
||||||
/* Find the identical partition. */
|
/* Find the identical partition. */
|
||||||
|
@ -741,11 +757,9 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||||
dup_ldp->length[0] = sizeof (*dup_ldp);
|
dup_ldp->length[0] = sizeof (*dup_ldp);
|
||||||
dup_ldp->length[1] = 0;
|
dup_ldp->length[1] = 0;
|
||||||
|
|
||||||
sdp = dup_dp;
|
if (!get_diskname_from_path (dup_dp, device_name))
|
||||||
|
return 0;
|
||||||
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_NONE);
|
parent = grub_disk_open (device_name);
|
||||||
if (!parent)
|
|
||||||
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_REMOVABLE);
|
|
||||||
grub_free (dup_dp);
|
grub_free (dup_dp);
|
||||||
|
|
||||||
if (! parent)
|
if (! parent)
|
||||||
|
@ -756,7 +770,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||||
if (hd.partition_start == 0
|
if (hd.partition_start == 0
|
||||||
&& hd.partition_size == grub_disk_get_size (parent))
|
&& hd.partition_size == grub_disk_get_size (parent))
|
||||||
{
|
{
|
||||||
device_name = grub_strdup (parent->name);
|
dev_name = grub_strdup (parent->name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -768,29 +782,18 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
|
dev_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
|
||||||
grub_free (partition_name);
|
grub_free (partition_name);
|
||||||
}
|
}
|
||||||
grub_disk_close (parent);
|
grub_disk_close (parent);
|
||||||
|
|
||||||
return device_name;
|
return dev_name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This should be an entire disk. */
|
/* This should be an entire disk. */
|
||||||
char *device_name = 0;
|
if (!get_diskname_from_path (dp, device_name))
|
||||||
|
|
||||||
sdp = dp;
|
|
||||||
|
|
||||||
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;
|
return 0;
|
||||||
|
return grub_strdup (device_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,38 @@
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
/* Dirty trick to solve circular dependency. */
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
|
||||||
|
#include <grub/util/misc.h>
|
||||||
|
|
||||||
|
#undef GRUB_MD_SHA256
|
||||||
|
#undef GRUB_MD_SHA512
|
||||||
|
|
||||||
|
static const gcry_md_spec_t *
|
||||||
|
grub_md_sha256_real (void)
|
||||||
|
{
|
||||||
|
const gcry_md_spec_t *ret;
|
||||||
|
ret = grub_crypto_lookup_md_by_name ("sha256");
|
||||||
|
if (!ret)
|
||||||
|
grub_util_error ("Coulnd't load sha256");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gcry_md_spec_t *
|
||||||
|
grub_md_sha512_real (void)
|
||||||
|
{
|
||||||
|
const gcry_md_spec_t *ret;
|
||||||
|
ret = grub_crypto_lookup_md_by_name ("sha512");
|
||||||
|
if (!ret)
|
||||||
|
grub_util_error ("Coulnd't load sha512");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GRUB_MD_SHA256 grub_md_sha256_real()
|
||||||
|
#define GRUB_MD_SHA512 grub_md_sha512_real()
|
||||||
|
#endif
|
||||||
|
|
||||||
struct grub_geli_key
|
struct grub_geli_key
|
||||||
{
|
{
|
||||||
grub_uint8_t iv_key[64];
|
grub_uint8_t iv_key[64];
|
||||||
|
@ -194,7 +226,7 @@ grub_util_get_geli_uuid (const char *dev)
|
||||||
|
|
||||||
uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1);
|
uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1);
|
||||||
if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0)
|
if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0)
|
||||||
grub_util_error ("couldn't read ELI metadata");
|
grub_util_error (_("couldn't read ELI metadata"));
|
||||||
|
|
||||||
COMPILE_TIME_ASSERT (sizeof (header) <= 512);
|
COMPILE_TIME_ASSERT (sizeof (header) <= 512);
|
||||||
header = (void *) &hdr;
|
header = (void *) &hdr;
|
||||||
|
@ -203,7 +235,7 @@ grub_util_get_geli_uuid (const char *dev)
|
||||||
if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC))
|
if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC))
|
||||||
|| grub_le_to_cpu32 (header->version) > 5
|
|| grub_le_to_cpu32 (header->version) > 5
|
||||||
|| grub_le_to_cpu32 (header->version) < 1)
|
|| grub_le_to_cpu32 (header->version) < 1)
|
||||||
grub_util_error ("wrong ELI magic or version");
|
grub_util_error (_("wrong ELI magic or version"));
|
||||||
|
|
||||||
err = make_uuid ((void *) &hdr, uuid);
|
err = make_uuid ((void *) &hdr, uuid);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -386,13 +418,13 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
|
||||||
keysize = grub_le_to_cpu16 (header.keylen) / 8;
|
keysize = grub_le_to_cpu16 (header.keylen) / 8;
|
||||||
grub_memset (zero, 0, sizeof (zero));
|
grub_memset (zero, 0, sizeof (zero));
|
||||||
|
|
||||||
grub_printf ("Attempting to decrypt master key...\n");
|
grub_puts_ (N_("Attempting to decrypt master key..."));
|
||||||
|
|
||||||
/* Get the passphrase from the user. */
|
/* Get the passphrase from the user. */
|
||||||
tmp = NULL;
|
tmp = NULL;
|
||||||
if (source->partition)
|
if (source->partition)
|
||||||
tmp = grub_partition_get_name (source->partition);
|
tmp = grub_partition_get_name (source->partition);
|
||||||
grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name,
|
grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
|
||||||
source->partition ? "," : "", tmp ? : "",
|
source->partition ? "," : "", tmp ? : "",
|
||||||
dev->uuid);
|
dev->uuid);
|
||||||
grub_free (tmp);
|
grub_free (tmp);
|
||||||
|
@ -481,7 +513,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
|
||||||
|
|
||||||
if (grub_memcmp (candidate_key.hmac, key_hmac, dev->hash->mdlen) != 0)
|
if (grub_memcmp (candidate_key.hmac, key_hmac, dev->hash->mdlen) != 0)
|
||||||
continue;
|
continue;
|
||||||
grub_printf ("Slot %d opened\n", i);
|
grub_printf_ (N_("Slot %d opened\n"), i);
|
||||||
|
|
||||||
/* Set the master key. */
|
/* Set the master key. */
|
||||||
if (!dev->rekey)
|
if (!dev->rekey)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/term.h>
|
#include <grub/term.h>
|
||||||
|
#include <grub/i18n.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -622,10 +623,11 @@ GRUB_MOD_INIT(biosdisk)
|
||||||
{
|
{
|
||||||
struct grub_biosdisk_cdrp *cdrp
|
struct grub_biosdisk_cdrp *cdrp
|
||||||
= (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
= (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
|
||||||
|
grub_uint8_t boot_drive;
|
||||||
|
|
||||||
if (grub_disk_firmware_is_tainted)
|
if (grub_disk_firmware_is_tainted)
|
||||||
{
|
{
|
||||||
grub_printf ("Firmware is marked as tainted, refusing to initialize.\n");
|
grub_puts_ (N_("Firmware is marked as tainted, refusing to initialize."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
grub_disk_firmware_fini = grub_disk_biosdisk_fini;
|
grub_disk_firmware_fini = grub_disk_biosdisk_fini;
|
||||||
|
@ -633,15 +635,16 @@ GRUB_MOD_INIT(biosdisk)
|
||||||
grub_memset (cdrp, 0, sizeof (*cdrp));
|
grub_memset (cdrp, 0, sizeof (*cdrp));
|
||||||
cdrp->size = sizeof (*cdrp);
|
cdrp->size = sizeof (*cdrp);
|
||||||
cdrp->media_type = 0xFF;
|
cdrp->media_type = 0xFF;
|
||||||
if ((! grub_biosdisk_get_cdinfo_int13_extensions (grub_boot_drive, cdrp)) &&
|
boot_drive = (grub_boot_device >> 24);
|
||||||
((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK)
|
if ((! grub_biosdisk_get_cdinfo_int13_extensions (boot_drive, cdrp))
|
||||||
|
&& ((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK)
|
||||||
== GRUB_BIOSDISK_CDTYPE_NO_EMUL))
|
== GRUB_BIOSDISK_CDTYPE_NO_EMUL))
|
||||||
cd_drive = cdrp->drive_no;
|
cd_drive = cdrp->drive_no;
|
||||||
/* Since diskboot.S rejects devices over 0x90 it must be a CD booted with
|
/* Since diskboot.S rejects devices over 0x90 it must be a CD booted with
|
||||||
cdboot.S
|
cdboot.S
|
||||||
*/
|
*/
|
||||||
if (grub_boot_drive >= 0x90)
|
if (boot_drive >= 0x90)
|
||||||
cd_drive = grub_boot_drive;
|
cd_drive = boot_drive;
|
||||||
|
|
||||||
grub_disk_dev_register (&grub_biosdisk_dev);
|
grub_disk_dev_register (&grub_biosdisk_dev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,10 +198,16 @@ grub_ofdisk_iterate (int (*hook) (const char *name),
|
||||||
if (grub_strncmp (ent->shortest, "cdrom", 5) == 0)
|
if (grub_strncmp (ent->shortest, "cdrom", 5) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (hook (ent->shortest))
|
{
|
||||||
|
char buffer[sizeof ("ieee1275/") + grub_strlen (ent->shortest)];
|
||||||
|
char *ptr;
|
||||||
|
ptr = grub_stpcpy (buffer, "ieee1275/");
|
||||||
|
grub_strcpy (ptr, ent->shortest);
|
||||||
|
if (hook (buffer))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,7 +247,10 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
|
||||||
char prop[64];
|
char prop[64];
|
||||||
grub_ssize_t actual;
|
grub_ssize_t actual;
|
||||||
|
|
||||||
devpath = compute_dev_path (name);
|
if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0)
|
||||||
|
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||||
|
"not IEEE1275 device");
|
||||||
|
devpath = compute_dev_path (name + sizeof ("ieee1275/") - 1);
|
||||||
if (! devpath)
|
if (! devpath)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
|
@ -302,10 +311,9 @@ grub_ofdisk_close (grub_disk_t disk)
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector)
|
||||||
grub_size_t size, char *buf)
|
|
||||||
{
|
{
|
||||||
grub_ssize_t status, actual;
|
grub_ssize_t status;
|
||||||
unsigned long long pos;
|
unsigned long long pos;
|
||||||
|
|
||||||
if (disk->data != last_devpath)
|
if (disk->data != last_devpath)
|
||||||
|
@ -334,15 +342,28 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
last_devpath = disk->data;
|
last_devpath = disk->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = sector * 512UL;
|
pos = sector << GRUB_DISK_SECTOR_BITS;
|
||||||
|
|
||||||
grub_ieee1275_seek (last_ihandle, pos, &status);
|
grub_ieee1275_seek (last_ihandle, pos, &status);
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return grub_error (GRUB_ERR_READ_ERROR,
|
return grub_error (GRUB_ERR_READ_ERROR,
|
||||||
"seek error, can't seek block %llu",
|
"seek error, can't seek block %llu",
|
||||||
(long long) sector);
|
(long long) sector);
|
||||||
grub_ieee1275_read (last_ihandle, buf, size * 512UL, &actual);
|
return 0;
|
||||||
if (actual != (grub_ssize_t) (size * 512UL))
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
|
grub_size_t size, char *buf)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
grub_ssize_t actual;
|
||||||
|
err = grub_ofdisk_prepare (disk, sector);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
grub_ieee1275_read (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS,
|
||||||
|
&actual);
|
||||||
|
if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
||||||
return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu",
|
return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu",
|
||||||
(long long) sector);
|
(long long) sector);
|
||||||
|
|
||||||
|
@ -350,12 +371,21 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_ofdisk_write (grub_disk_t disk __attribute ((unused)),
|
grub_ofdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
grub_disk_addr_t sector __attribute ((unused)),
|
grub_size_t size, const char *buf)
|
||||||
grub_size_t size __attribute ((unused)),
|
|
||||||
const char *buf __attribute ((unused)))
|
|
||||||
{
|
{
|
||||||
return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
grub_err_t err;
|
||||||
|
grub_ssize_t actual;
|
||||||
|
err = grub_ofdisk_prepare (disk, sector);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
grub_ieee1275_write (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS,
|
||||||
|
&actual);
|
||||||
|
if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
||||||
|
return grub_error (GRUB_ERR_WRITE_ERROR, "write error on block: %llu",
|
||||||
|
(long long) sector);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct grub_disk_dev grub_ofdisk_dev =
|
static struct grub_disk_dev grub_ofdisk_dev =
|
||||||
|
|
997
grub-core/disk/ldm.c
Normal file
997
grub-core/disk/ldm.c
Normal file
|
@ -0,0 +1,997 @@
|
||||||
|
/*
|
||||||
|
* GRUB -- GRand Unified Bootloader
|
||||||
|
* Copyright (C) 2006,2007,2008,2009,2011 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* 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/err.h>
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/diskfilter.h>
|
||||||
|
#include <grub/gpt_partition.h>
|
||||||
|
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
#include <grub/emu/misc.h>
|
||||||
|
#include <grub/emu/hostdisk.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
#define LDM_GUID_STRLEN 64
|
||||||
|
#define LDM_NAME_STRLEN 32
|
||||||
|
|
||||||
|
typedef grub_uint8_t *grub_ldm_id_t;
|
||||||
|
|
||||||
|
enum { STRIPE = 1, SPANNED = 2, RAID5 = 3 };
|
||||||
|
|
||||||
|
#define LDM_LABEL_SECTOR 6
|
||||||
|
struct grub_ldm_vblk {
|
||||||
|
char magic[4];
|
||||||
|
grub_uint8_t unused1[12];
|
||||||
|
grub_uint16_t update_status;
|
||||||
|
grub_uint8_t flags;
|
||||||
|
grub_uint8_t type;
|
||||||
|
grub_uint32_t unused2;
|
||||||
|
grub_uint8_t dynamic[104];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
#define LDM_VBLK_MAGIC "VBLK"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STATUS_CONSISTENT = 0,
|
||||||
|
STATUS_STILL_ACTIVE = 1,
|
||||||
|
STATUS_NOT_ACTIVE_YET = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ENTRY_COMPONENT = 0x32,
|
||||||
|
ENTRY_PARTITION = 0x33,
|
||||||
|
ENTRY_DISK = 0x34,
|
||||||
|
ENTRY_VOLUME = 0x51,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct grub_ldm_label
|
||||||
|
{
|
||||||
|
char magic[8];
|
||||||
|
grub_uint32_t unused1;
|
||||||
|
grub_uint16_t ver_major;
|
||||||
|
grub_uint16_t ver_minor;
|
||||||
|
grub_uint8_t unused2[32];
|
||||||
|
char disk_guid[LDM_GUID_STRLEN];
|
||||||
|
char host_guid[LDM_GUID_STRLEN];
|
||||||
|
char group_guid[LDM_GUID_STRLEN];
|
||||||
|
char group_name[LDM_NAME_STRLEN];
|
||||||
|
grub_uint8_t unused3[11];
|
||||||
|
grub_uint64_t pv_start;
|
||||||
|
grub_uint64_t pv_size;
|
||||||
|
grub_uint64_t config_start;
|
||||||
|
grub_uint64_t config_size;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
|
#define LDM_MAGIC "PRIVHEAD"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static inline grub_uint64_t
|
||||||
|
read_int (grub_uint8_t *in, grub_size_t s)
|
||||||
|
{
|
||||||
|
grub_uint8_t *ptr2;
|
||||||
|
grub_uint64_t ret;
|
||||||
|
ret = 0;
|
||||||
|
for (ptr2 = in; ptr2 < in + s; ptr2++)
|
||||||
|
{
|
||||||
|
ret <<= 8;
|
||||||
|
ret |= *ptr2;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const grub_gpt_part_type_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM;
|
||||||
|
|
||||||
|
static grub_disk_addr_t
|
||||||
|
gpt_ldm_sector (grub_disk_t dsk)
|
||||||
|
{
|
||||||
|
grub_disk_addr_t sector = 0;
|
||||||
|
grub_err_t err;
|
||||||
|
auto int hook (grub_disk_t disk, const grub_partition_t p);
|
||||||
|
int hook (grub_disk_t disk, const grub_partition_t p)
|
||||||
|
{
|
||||||
|
struct grub_gpt_partentry gptdata;
|
||||||
|
grub_partition_t p2;
|
||||||
|
|
||||||
|
p2 = disk->partition;
|
||||||
|
disk->partition = p->parent;
|
||||||
|
if (grub_disk_read (disk, p->offset, p->index,
|
||||||
|
sizeof (gptdata), &gptdata))
|
||||||
|
{
|
||||||
|
disk->partition = p2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
disk->partition = p2;
|
||||||
|
|
||||||
|
if (! grub_memcmp (&gptdata.type, &ldm_type, 16))
|
||||||
|
{
|
||||||
|
sector = p->start + p->len - 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
err = grub_gpt_partition_map_iterate (dsk, hook);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct grub_diskfilter_vg *
|
||||||
|
make_vg (grub_disk_t disk,
|
||||||
|
const struct grub_ldm_label *label)
|
||||||
|
{
|
||||||
|
grub_disk_addr_t startsec, endsec, cursec;
|
||||||
|
struct grub_diskfilter_vg *vg;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
/* First time we see this volume group. We've to create the
|
||||||
|
whole volume group structure. */
|
||||||
|
vg = grub_malloc (sizeof (*vg));
|
||||||
|
if (! vg)
|
||||||
|
return NULL;
|
||||||
|
vg->extent_size = 1;
|
||||||
|
vg->name = grub_malloc (LDM_NAME_STRLEN + 1);
|
||||||
|
vg->uuid = grub_malloc (LDM_GUID_STRLEN + 1);
|
||||||
|
if (! vg->uuid || !vg->name)
|
||||||
|
{
|
||||||
|
grub_free (vg->uuid);
|
||||||
|
grub_free (vg->name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
grub_memcpy (vg->uuid, label->group_guid, LDM_GUID_STRLEN);
|
||||||
|
grub_memcpy (vg->name, label->group_name, LDM_NAME_STRLEN);
|
||||||
|
vg->name[LDM_NAME_STRLEN] = 0;
|
||||||
|
vg->uuid[LDM_GUID_STRLEN] = 0;
|
||||||
|
vg->uuid_len = grub_strlen (vg->uuid);
|
||||||
|
|
||||||
|
vg->lvs = NULL;
|
||||||
|
vg->pvs = NULL;
|
||||||
|
|
||||||
|
startsec = grub_be_to_cpu64 (label->config_start);
|
||||||
|
endsec = startsec + grub_be_to_cpu64 (label->config_size);
|
||||||
|
|
||||||
|
/* First find disks. */
|
||||||
|
for (cursec = startsec + 0x12; cursec < endsec; cursec++)
|
||||||
|
{
|
||||||
|
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
|
||||||
|
/ sizeof (struct grub_ldm_vblk)];
|
||||||
|
unsigned i;
|
||||||
|
err = grub_disk_read (disk, cursec, 0,
|
||||||
|
sizeof(vblk), &vblk);
|
||||||
|
if (err)
|
||||||
|
goto fail2;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE (vblk); i++)
|
||||||
|
{
|
||||||
|
struct grub_diskfilter_pv *pv;
|
||||||
|
grub_uint8_t *ptr;
|
||||||
|
if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
|
||||||
|
sizeof (vblk[i].magic)) != 0)
|
||||||
|
continue;
|
||||||
|
if (grub_be_to_cpu16 (vblk[i].update_status)
|
||||||
|
!= STATUS_CONSISTENT
|
||||||
|
&& grub_be_to_cpu16 (vblk[i].update_status)
|
||||||
|
!= STATUS_STILL_ACTIVE)
|
||||||
|
continue;
|
||||||
|
if (vblk[i].type != ENTRY_DISK)
|
||||||
|
continue;
|
||||||
|
pv = grub_zalloc (sizeof (*pv));
|
||||||
|
if (!pv)
|
||||||
|
goto fail2;
|
||||||
|
|
||||||
|
pv->disk = 0;
|
||||||
|
ptr = vblk[i].dynamic;
|
||||||
|
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
|
+ sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (pv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
pv->internal_id = grub_malloc (ptr[0] + 2);
|
||||||
|
if (!pv->internal_id)
|
||||||
|
{
|
||||||
|
grub_free (pv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
grub_memcpy (pv->internal_id, ptr, (grub_size_t) ptr[0] + 1);
|
||||||
|
pv->internal_id[(grub_size_t) ptr[0] + 1] = 0;
|
||||||
|
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
|
+ sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (pv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
/* ptr = name. */
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr + *ptr + 1
|
||||||
|
>= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (pv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
pv->id.uuidlen = *ptr;
|
||||||
|
pv->id.uuid = grub_malloc (pv->id.uuidlen + 1);
|
||||||
|
grub_memcpy (pv->id.uuid, ptr + 1, pv->id.uuidlen);
|
||||||
|
pv->id.uuid[pv->id.uuidlen] = 0;
|
||||||
|
|
||||||
|
pv->next = vg->pvs;
|
||||||
|
vg->pvs = pv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then find LVs. */
|
||||||
|
for (cursec = startsec + 0x12; cursec < endsec; cursec++)
|
||||||
|
{
|
||||||
|
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
|
||||||
|
/ sizeof (struct grub_ldm_vblk)];
|
||||||
|
unsigned i;
|
||||||
|
err = grub_disk_read (disk, cursec, 0,
|
||||||
|
sizeof(vblk), &vblk);
|
||||||
|
if (err)
|
||||||
|
goto fail2;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE (vblk); i++)
|
||||||
|
{
|
||||||
|
struct grub_diskfilter_lv *lv;
|
||||||
|
grub_uint8_t *ptr;
|
||||||
|
if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
|
||||||
|
sizeof (vblk[i].magic)) != 0)
|
||||||
|
continue;
|
||||||
|
if (grub_be_to_cpu16 (vblk[i].update_status)
|
||||||
|
!= STATUS_CONSISTENT
|
||||||
|
&& grub_be_to_cpu16 (vblk[i].update_status)
|
||||||
|
!= STATUS_STILL_ACTIVE)
|
||||||
|
continue;
|
||||||
|
if (vblk[i].type != ENTRY_VOLUME)
|
||||||
|
continue;
|
||||||
|
lv = grub_zalloc (sizeof (*lv));
|
||||||
|
if (!lv)
|
||||||
|
goto fail2;
|
||||||
|
|
||||||
|
lv->vg = vg;
|
||||||
|
lv->segment_count = 1;
|
||||||
|
lv->segment_alloc = 1;
|
||||||
|
lv->visible = 1;
|
||||||
|
lv->segments = grub_zalloc (sizeof (*lv->segments));
|
||||||
|
if (!lv->segments)
|
||||||
|
goto fail2;
|
||||||
|
lv->segments->start_extent = 0;
|
||||||
|
lv->segments->type = GRUB_DISKFILTER_MIRROR;
|
||||||
|
lv->segments->node_count = 0;
|
||||||
|
lv->segments->node_alloc = 8;
|
||||||
|
lv->segments->nodes = grub_zalloc (sizeof (*lv->segments->nodes)
|
||||||
|
* lv->segments->node_alloc);
|
||||||
|
if (!lv->segments->nodes)
|
||||||
|
goto fail2;
|
||||||
|
ptr = vblk[i].dynamic;
|
||||||
|
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
|
+ sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (lv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
lv->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
|
||||||
|
if (!lv->internal_id)
|
||||||
|
{
|
||||||
|
grub_free (lv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
grub_memcpy (lv->internal_id, ptr, ptr[0] + 1);
|
||||||
|
lv->internal_id[ptr[0] + 1] = 0;
|
||||||
|
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
|
+ sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (lv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
lv->name = grub_malloc (*ptr + 1);
|
||||||
|
if (!lv->name)
|
||||||
|
{
|
||||||
|
grub_free (lv->internal_id);
|
||||||
|
grub_free (lv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
grub_memcpy (lv->name, ptr + 1, *ptr);
|
||||||
|
lv->name[*ptr] = 0;
|
||||||
|
lv->fullname = grub_xasprintf ("ldm/%s/%s",
|
||||||
|
vg->uuid, lv->name);
|
||||||
|
if (!lv->fullname)
|
||||||
|
{
|
||||||
|
grub_free (lv->internal_id);
|
||||||
|
grub_free (lv->name);
|
||||||
|
grub_free (lv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr + *ptr + 1
|
||||||
|
>= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (lv->internal_id);
|
||||||
|
grub_free (lv->name);
|
||||||
|
grub_free (lv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
/* ptr = volume type. */
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (lv->internal_id);
|
||||||
|
grub_free (lv->name);
|
||||||
|
grub_free (lv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
/* ptr = flags. */
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (lv->internal_id);
|
||||||
|
grub_free (lv->name);
|
||||||
|
grub_free (lv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip state, type, unknown, volume number, zeros, flags. */
|
||||||
|
ptr += 14 + 1 + 1 + 1 + 3 + 1;
|
||||||
|
/* ptr = number of children. */
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (lv->internal_id);
|
||||||
|
grub_free (lv->name);
|
||||||
|
grub_free (lv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (lv->internal_id);
|
||||||
|
grub_free (lv->name);
|
||||||
|
grub_free (lv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Skip 2 more fields. */
|
||||||
|
ptr += 8 + 8;
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
|
||||||
|
|| ptr + *ptr + 1>= vblk[i].dynamic
|
||||||
|
+ sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (lv->internal_id);
|
||||||
|
grub_free (lv->name);
|
||||||
|
grub_free (lv);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
lv->size = read_int (ptr + 1, *ptr);
|
||||||
|
lv->segments->extent_count = lv->size;
|
||||||
|
|
||||||
|
lv->next = vg->lvs;
|
||||||
|
vg->lvs = lv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now the components. */
|
||||||
|
for (cursec = startsec + 0x12; cursec < endsec; cursec++)
|
||||||
|
{
|
||||||
|
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
|
||||||
|
/ sizeof (struct grub_ldm_vblk)];
|
||||||
|
unsigned i;
|
||||||
|
err = grub_disk_read (disk, cursec, 0,
|
||||||
|
sizeof(vblk), &vblk);
|
||||||
|
if (err)
|
||||||
|
goto fail2;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE (vblk); i++)
|
||||||
|
{
|
||||||
|
struct grub_diskfilter_lv *comp;
|
||||||
|
struct grub_diskfilter_lv *lv;
|
||||||
|
grub_uint8_t type;
|
||||||
|
|
||||||
|
grub_uint8_t *ptr;
|
||||||
|
if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
|
||||||
|
sizeof (vblk[i].magic)) != 0)
|
||||||
|
continue;
|
||||||
|
if (grub_be_to_cpu16 (vblk[i].update_status)
|
||||||
|
!= STATUS_CONSISTENT
|
||||||
|
&& grub_be_to_cpu16 (vblk[i].update_status)
|
||||||
|
!= STATUS_STILL_ACTIVE)
|
||||||
|
continue;
|
||||||
|
if (vblk[i].type != ENTRY_COMPONENT)
|
||||||
|
continue;
|
||||||
|
comp = grub_zalloc (sizeof (*comp));
|
||||||
|
if (!comp)
|
||||||
|
goto fail2;
|
||||||
|
comp->visible = 0;
|
||||||
|
comp->name = 0;
|
||||||
|
comp->fullname = 0;
|
||||||
|
|
||||||
|
ptr = vblk[i].dynamic;
|
||||||
|
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
comp->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2);
|
||||||
|
if (!comp->internal_id)
|
||||||
|
{
|
||||||
|
grub_free (comp);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
grub_memcpy (comp->internal_id, ptr, ptr[0] + 1);
|
||||||
|
comp->internal_id[ptr[0] + 1] = 0;
|
||||||
|
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (comp->internal_id);
|
||||||
|
grub_free (comp);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
/* ptr = name. */
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (comp->internal_id);
|
||||||
|
grub_free (comp);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
/* ptr = state. */
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
type = *ptr++;
|
||||||
|
/* skip zeros. */
|
||||||
|
ptr += 4;
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (comp->internal_id);
|
||||||
|
grub_free (comp);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ptr = number of children. */
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (comp->internal_id);
|
||||||
|
grub_free (comp);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
ptr += 8 + 8;
|
||||||
|
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
|
+ sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (comp->internal_id);
|
||||||
|
grub_free (comp);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
for (lv = vg->lvs; lv; lv = lv->next)
|
||||||
|
{
|
||||||
|
if (lv->internal_id[0] == ptr[0]
|
||||||
|
&& grub_memcmp (lv->internal_id + 1, ptr + 1, ptr[0]) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!lv)
|
||||||
|
{
|
||||||
|
grub_free (comp->internal_id);
|
||||||
|
grub_free (comp);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
comp->size = lv->size;
|
||||||
|
if (type == SPANNED)
|
||||||
|
{
|
||||||
|
comp->segment_alloc = 8;
|
||||||
|
comp->segment_count = 0;
|
||||||
|
comp->segments = grub_malloc (sizeof (*comp->segments)
|
||||||
|
* comp->segment_alloc);
|
||||||
|
if (!comp->segments)
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
comp->segment_alloc = 1;
|
||||||
|
comp->segment_count = 1;
|
||||||
|
comp->segments = grub_malloc (sizeof (*comp->segments));
|
||||||
|
if (!comp->segments)
|
||||||
|
goto fail2;
|
||||||
|
comp->segments->start_extent = 0;
|
||||||
|
comp->segments->extent_count = lv->size;
|
||||||
|
comp->segments->layout = 0;
|
||||||
|
if (type == STRIPE)
|
||||||
|
comp->segments->type = GRUB_DISKFILTER_STRIPED;
|
||||||
|
else if (type == RAID5)
|
||||||
|
{
|
||||||
|
comp->segments->type = GRUB_DISKFILTER_RAID5;
|
||||||
|
comp->segments->layout = GRUB_RAID_LAYOUT_SYMMETRIC_MASK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto fail2;
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
ptr++;
|
||||||
|
if (!(vblk[i].flags & 0x10))
|
||||||
|
goto fail2;
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
|
||||||
|
|| ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
|
+ sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (comp->internal_id);
|
||||||
|
grub_free (comp);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
comp->segments->stripe_size = read_int (ptr + 1, *ptr);
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
|
+ sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
grub_free (comp->internal_id);
|
||||||
|
grub_free (comp);
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
comp->segments->node_count = read_int (ptr + 1, *ptr);
|
||||||
|
comp->segments->node_alloc = comp->segments->node_count;
|
||||||
|
comp->segments->nodes = grub_zalloc (sizeof (*comp->segments->nodes)
|
||||||
|
* comp->segments->node_alloc);
|
||||||
|
if (!lv->segments->nodes)
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lv->segments->node_alloc == lv->segments->node_count)
|
||||||
|
{
|
||||||
|
void *t;
|
||||||
|
lv->segments->node_alloc *= 2;
|
||||||
|
t = grub_realloc (lv->segments->nodes,
|
||||||
|
sizeof (*lv->segments->nodes)
|
||||||
|
* lv->segments->node_alloc);
|
||||||
|
if (!t)
|
||||||
|
goto fail2;
|
||||||
|
lv->segments->nodes = t;
|
||||||
|
}
|
||||||
|
lv->segments->nodes[lv->segments->node_count].pv = 0;
|
||||||
|
lv->segments->nodes[lv->segments->node_count].start = 0;
|
||||||
|
lv->segments->nodes[lv->segments->node_count++].lv = comp;
|
||||||
|
comp->next = vg->lvs;
|
||||||
|
vg->lvs = comp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Partitions. */
|
||||||
|
for (cursec = startsec + 0x12; cursec < endsec; cursec++)
|
||||||
|
{
|
||||||
|
struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE
|
||||||
|
/ sizeof (struct grub_ldm_vblk)];
|
||||||
|
unsigned i;
|
||||||
|
err = grub_disk_read (disk, cursec, 0,
|
||||||
|
sizeof(vblk), &vblk);
|
||||||
|
if (err)
|
||||||
|
goto fail2;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE (vblk); i++)
|
||||||
|
{
|
||||||
|
struct grub_diskfilter_lv *comp;
|
||||||
|
struct grub_diskfilter_node part;
|
||||||
|
grub_disk_addr_t start, size;
|
||||||
|
|
||||||
|
grub_uint8_t *ptr;
|
||||||
|
if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC,
|
||||||
|
sizeof (vblk[i].magic)) != 0)
|
||||||
|
continue;
|
||||||
|
if (grub_be_to_cpu16 (vblk[i].update_status)
|
||||||
|
!= STATUS_CONSISTENT
|
||||||
|
&& grub_be_to_cpu16 (vblk[i].update_status)
|
||||||
|
!= STATUS_STILL_ACTIVE)
|
||||||
|
continue;
|
||||||
|
if (vblk[i].type != ENTRY_PARTITION)
|
||||||
|
continue;
|
||||||
|
part.lv = 0;
|
||||||
|
part.pv = 0;
|
||||||
|
|
||||||
|
ptr = vblk[i].dynamic;
|
||||||
|
if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
/* ID */
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
/* ptr = name. */
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip zeros and logcommit id. */
|
||||||
|
ptr += 4 + 8;
|
||||||
|
if (ptr + 16 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
part.start = read_int (ptr, 8);
|
||||||
|
start = read_int (ptr + 8, 8);
|
||||||
|
ptr += 16;
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
|
||||||
|
|| ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
size = read_int (ptr + 1, *ptr);
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
|
||||||
|
|| ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (comp = vg->lvs; comp; comp = comp->next)
|
||||||
|
if (comp->internal_id[0] == ptr[0]
|
||||||
|
&& grub_memcmp (ptr + 1, comp->internal_id + 1,
|
||||||
|
comp->internal_id[0]) == 0)
|
||||||
|
goto out;
|
||||||
|
continue;
|
||||||
|
out:
|
||||||
|
if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)
|
||||||
|
|| ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
struct grub_diskfilter_pv *pv;
|
||||||
|
for (pv = vg->pvs; pv; pv = pv->next)
|
||||||
|
if (pv->internal_id[0] == ptr[0]
|
||||||
|
&& grub_memcmp (pv->internal_id + 1, ptr + 1, ptr[0]) == 0)
|
||||||
|
part.pv = pv;
|
||||||
|
|
||||||
|
if (comp->segment_alloc == 1)
|
||||||
|
{
|
||||||
|
unsigned index;
|
||||||
|
ptr += *ptr + 1;
|
||||||
|
if (ptr + *ptr + 1 >= vblk[i].dynamic
|
||||||
|
+ sizeof (vblk[i].dynamic))
|
||||||
|
{
|
||||||
|
goto fail2;
|
||||||
|
}
|
||||||
|
index = read_int (ptr + 1, *ptr);
|
||||||
|
if (index < comp->segments->node_count)
|
||||||
|
comp->segments->nodes[index] = part;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (comp->segment_alloc == comp->segment_count)
|
||||||
|
{
|
||||||
|
void *t;
|
||||||
|
comp->segment_alloc *= 2;
|
||||||
|
t = grub_realloc (comp->segments,
|
||||||
|
comp->segment_alloc
|
||||||
|
* sizeof (*comp->segments));
|
||||||
|
if (!t)
|
||||||
|
goto fail2;
|
||||||
|
comp->segments = t;
|
||||||
|
}
|
||||||
|
comp->segments[comp->segment_count].start_extent = start;
|
||||||
|
comp->segments[comp->segment_count].extent_count = size;
|
||||||
|
comp->segments[comp->segment_count].type = GRUB_DISKFILTER_STRIPED;
|
||||||
|
comp->segments[comp->segment_count].node_count = 1;
|
||||||
|
comp->segments[comp->segment_count].node_alloc = 1;
|
||||||
|
comp->segments[comp->segment_count].nodes
|
||||||
|
= grub_malloc (sizeof (*comp->segments[comp->segment_count].nodes));
|
||||||
|
if (!comp->segments[comp->segment_count].nodes)
|
||||||
|
goto fail2;
|
||||||
|
comp->segments[comp->segment_count].nodes[0] = part;
|
||||||
|
comp->segment_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (grub_diskfilter_vg_register (vg))
|
||||||
|
goto fail2;
|
||||||
|
return vg;
|
||||||
|
fail2:
|
||||||
|
{
|
||||||
|
struct grub_diskfilter_lv *lv, *next_lv;
|
||||||
|
struct grub_diskfilter_pv *pv, *next_pv;
|
||||||
|
for (lv = vg->lvs; lv; lv = next_lv)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < lv->segment_count; i++)
|
||||||
|
grub_free (lv->segments[i].nodes);
|
||||||
|
|
||||||
|
next_lv = lv->next;
|
||||||
|
grub_free (lv->segments);
|
||||||
|
grub_free (lv->internal_id);
|
||||||
|
grub_free (lv->name);
|
||||||
|
grub_free (lv->fullname);
|
||||||
|
grub_free (lv);
|
||||||
|
}
|
||||||
|
for (pv = vg->pvs; pv; pv = next_pv)
|
||||||
|
{
|
||||||
|
next_pv = pv->next;
|
||||||
|
grub_free (pv->id.uuid);
|
||||||
|
grub_free (pv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grub_free (vg->uuid);
|
||||||
|
grub_free (vg);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct grub_diskfilter_vg *
|
||||||
|
grub_ldm_detect (grub_disk_t disk,
|
||||||
|
struct grub_diskfilter_pv_id *id,
|
||||||
|
grub_disk_addr_t *start_sector)
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
struct grub_ldm_label label;
|
||||||
|
struct grub_diskfilter_vg *vg;
|
||||||
|
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
grub_util_info ("scanning %s for LDM", disk->name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
grub_disk_addr_t sector;
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
sector = LDM_LABEL_SECTOR;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* LDM is never inside a partition. */
|
||||||
|
if (disk->partition)
|
||||||
|
continue;
|
||||||
|
sector = grub_disk_get_size (disk);
|
||||||
|
if (sector == GRUB_DISK_SIZE_UNKNOWN)
|
||||||
|
continue;
|
||||||
|
sector--;
|
||||||
|
break;
|
||||||
|
/* FIXME: try the third copy. */
|
||||||
|
case 2:
|
||||||
|
sector = gpt_ldm_sector (disk);
|
||||||
|
if (!sector)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
err = grub_disk_read (disk, sector, 0,
|
||||||
|
sizeof(label), &label);
|
||||||
|
if (err)
|
||||||
|
return NULL;
|
||||||
|
if (grub_memcmp (label.magic, LDM_MAGIC, sizeof (label.magic)) == 0
|
||||||
|
&& grub_be_to_cpu16 (label.ver_major) == 0x02
|
||||||
|
&& grub_be_to_cpu16 (label.ver_minor) >= 0x0b
|
||||||
|
&& grub_be_to_cpu16 (label.ver_minor) <= 0x0c)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return if we didn't find a label. */
|
||||||
|
if (i == 3)
|
||||||
|
{
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
grub_util_info ("no LDM signature found");
|
||||||
|
#endif
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
id->uuid = grub_malloc (LDM_GUID_STRLEN + 1);
|
||||||
|
if (!id->uuid)
|
||||||
|
return NULL;
|
||||||
|
grub_memcpy (id->uuid, label.disk_guid, LDM_GUID_STRLEN);
|
||||||
|
id->uuid[LDM_GUID_STRLEN] = 0;
|
||||||
|
id->uuidlen = grub_strlen ((char *) id->uuid);
|
||||||
|
*start_sector = grub_be_to_cpu64 (label.pv_start);
|
||||||
|
|
||||||
|
{
|
||||||
|
grub_size_t s;
|
||||||
|
for (s = 0; s < LDM_GUID_STRLEN && label.group_guid[s]; s++);
|
||||||
|
vg = grub_diskfilter_get_vg_by_uuid (s, label.group_guid);
|
||||||
|
if (! vg)
|
||||||
|
vg = make_vg (disk, &label);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vg)
|
||||||
|
{
|
||||||
|
grub_free (id->uuid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return vg;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
|
||||||
|
char *
|
||||||
|
grub_util_get_ldm (grub_disk_t disk, grub_disk_addr_t start)
|
||||||
|
{
|
||||||
|
struct grub_diskfilter_pv *pv = NULL;
|
||||||
|
struct grub_diskfilter_vg *vg = NULL;
|
||||||
|
struct grub_diskfilter_lv *res, *lv;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
pv = grub_diskfilter_get_pv_from_disk (disk, &vg);
|
||||||
|
|
||||||
|
if (!pv)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (lv = vg->lvs; lv; lv = lv->next)
|
||||||
|
if (lv->segment_count == 1 && lv->segments->node_count == 1
|
||||||
|
&& lv->segments->type == GRUB_DISKFILTER_STRIPED
|
||||||
|
&& lv->segments->nodes->pv == pv
|
||||||
|
&& lv->segments->nodes->start + pv->start_sector == start)
|
||||||
|
{
|
||||||
|
res = lv;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (lv = vg->lvs; lv; lv = lv->next)
|
||||||
|
if (lv->segment_count == 1 && lv->segments->node_count == 1
|
||||||
|
&& lv->segments->type == GRUB_DISKFILTER_MIRROR
|
||||||
|
&& lv->segments->nodes->lv == lv)
|
||||||
|
{
|
||||||
|
res = lv;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (res->fullname)
|
||||||
|
return grub_strdup (lv->fullname);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
grub_util_is_ldm (grub_disk_t disk)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
grub_disk_addr_t sector;
|
||||||
|
grub_err_t err;
|
||||||
|
struct grub_ldm_label label;
|
||||||
|
|
||||||
|
switch (i)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
sector = LDM_LABEL_SECTOR;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
/* LDM is never inside a partition. */
|
||||||
|
if (disk->partition)
|
||||||
|
continue;
|
||||||
|
sector = grub_disk_get_size (disk);
|
||||||
|
if (sector == GRUB_DISK_SIZE_UNKNOWN)
|
||||||
|
continue;
|
||||||
|
sector--;
|
||||||
|
break;
|
||||||
|
/* FIXME: try the third copy. */
|
||||||
|
case 2:
|
||||||
|
sector = gpt_ldm_sector (disk);
|
||||||
|
if (!sector)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
err = grub_disk_read (disk, sector, 0, sizeof(label), &label);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* This check is more relaxed on purpose. */
|
||||||
|
if (grub_memcmp (label.magic, LDM_MAGIC, sizeof (label.magic)) == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors,
|
||||||
|
grub_embed_type_t embed_type,
|
||||||
|
grub_disk_addr_t **sectors)
|
||||||
|
{
|
||||||
|
struct grub_diskfilter_pv *pv = NULL;
|
||||||
|
struct grub_diskfilter_vg *vg;
|
||||||
|
struct grub_diskfilter_lv *lv;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
if (embed_type != GRUB_EMBED_PCBIOS)
|
||||||
|
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
|
"GPT curently supports only PC-BIOS embedding");
|
||||||
|
if (disk->partition)
|
||||||
|
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "disk isn't LDM");
|
||||||
|
pv = grub_diskfilter_get_pv_from_disk (disk, &vg);
|
||||||
|
if (!pv)
|
||||||
|
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "disk isn't LDM");
|
||||||
|
for (lv = vg->lvs; lv; lv = lv->next)
|
||||||
|
{
|
||||||
|
struct grub_diskfilter_lv *comp;
|
||||||
|
struct grub_ldm_partition *part;
|
||||||
|
|
||||||
|
if (!lv->visible || !lv->fullname)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (lv->segment_count != 1)
|
||||||
|
continue;
|
||||||
|
if (lv->segments->type != GRUB_DISKFILTER_MIRROR
|
||||||
|
|| lv->segments->node_count != 1
|
||||||
|
|| lv->segments->start_extent != 0
|
||||||
|
|| lv->segments->extent_count != lv->size)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
comp = lv->segments->nodes->lv;
|
||||||
|
if (!comp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (comp->segment_count != 1 || comp->size != lv->size)
|
||||||
|
continue;
|
||||||
|
if (comp->segments->type != GRUB_DISKFILTER_STRIPED
|
||||||
|
|| comp->segments->node_count != 1
|
||||||
|
|| comp->segments->start_extent != 0
|
||||||
|
|| comp->segments->extent_count != lv->size)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* How to implement proper check is to be discussed. */
|
||||||
|
#if 1
|
||||||
|
if (1)
|
||||||
|
continue;
|
||||||
|
#else
|
||||||
|
if (grub_strcmp (lv->name, "Volume5") != 0)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
if (lv->size < *nsectors)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
|
"Your LDM embed Partition is too small;"
|
||||||
|
" embedding won't be possible!");
|
||||||
|
*nsectors = lv->size;
|
||||||
|
*sectors = grub_malloc (*nsectors * sizeof (**sectors));
|
||||||
|
if (!*sectors)
|
||||||
|
return grub_errno;
|
||||||
|
for (i = 0; i < *nsectors; i++)
|
||||||
|
(*sectors)[i] = (lv->segments->nodes->start
|
||||||
|
+ comp->segments->nodes->start
|
||||||
|
+ comp->segments->nodes->pv->start_sector + i);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return grub_error (GRUB_ERR_FILE_NOT_FOUND,
|
||||||
|
"This LDM no Embedding Partition;"
|
||||||
|
" embedding won't be possible!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct grub_diskfilter grub_ldm_dev = {
|
||||||
|
.name = "ldm",
|
||||||
|
.detect = grub_ldm_detect,
|
||||||
|
.next = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
GRUB_MOD_INIT (ldm)
|
||||||
|
{
|
||||||
|
grub_diskfilter_register (&grub_ldm_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
GRUB_MOD_FINI (ldm)
|
||||||
|
{
|
||||||
|
grub_diskfilter_unregister (&grub_ldm_dev);
|
||||||
|
}
|
|
@ -316,7 +316,7 @@ luks_recover_key (grub_disk_t source,
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
grub_printf ("Attempting to decrypt master key...\n");
|
grub_puts_ (N_("Attempting to decrypt master key..."));
|
||||||
keysize = grub_be_to_cpu32 (header.keyBytes);
|
keysize = grub_be_to_cpu32 (header.keyBytes);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
|
for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
|
||||||
|
@ -332,7 +332,7 @@ luks_recover_key (grub_disk_t source,
|
||||||
tmp = NULL;
|
tmp = NULL;
|
||||||
if (source->partition)
|
if (source->partition)
|
||||||
tmp = grub_partition_get_name (source->partition);
|
tmp = grub_partition_get_name (source->partition);
|
||||||
grub_printf ("Enter passphrase for %s%s%s (%s): ", source->name,
|
grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
|
||||||
source->partition ? "," : "", tmp ? : "",
|
source->partition ? "," : "", tmp ? : "",
|
||||||
dev->uuid);
|
dev->uuid);
|
||||||
grub_free (tmp);
|
grub_free (tmp);
|
||||||
|
@ -434,7 +434,7 @@ luks_recover_key (grub_disk_t source,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_printf ("Slot %d opened\n", i);
|
grub_printf_ (N_("Slot %d opened\n"), i);
|
||||||
|
|
||||||
/* Set the master key. */
|
/* Set the master key. */
|
||||||
gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize);
|
gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* lvm.c - module to read Logical Volumes. */
|
/* lvm.c - module to read Logical Volumes. */
|
||||||
/*
|
/*
|
||||||
* GRUB -- GRand Unified Bootloader
|
* GRUB -- GRand Unified Bootloader
|
||||||
* Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc.
|
* Copyright (C) 2006,2007,2008,2009,2011 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* GRUB is free software: you can redistribute it and/or modify
|
* GRUB is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -23,6 +23,8 @@
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/lvm.h>
|
#include <grub/lvm.h>
|
||||||
|
#include <grub/partition.h>
|
||||||
|
#include <grub/i18n.h>
|
||||||
|
|
||||||
#ifdef GRUB_UTIL
|
#ifdef GRUB_UTIL
|
||||||
#include <grub/emu/misc.h>
|
#include <grub/emu/misc.h>
|
||||||
|
@ -31,24 +33,18 @@
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
static struct grub_lvm_vg *vg_list;
|
|
||||||
static int lv_count;
|
|
||||||
static int scan_depth = 0;
|
|
||||||
|
|
||||||
static int is_lv_readable (struct grub_lvm_lv *lv);
|
|
||||||
|
|
||||||
|
|
||||||
/* Go the string STR and return the number after STR. *P will point
|
/* Go the string STR and return the number after STR. *P will point
|
||||||
at the number. In case STR is not found, *P will be NULL and the
|
at the number. In case STR is not found, *P will be NULL and the
|
||||||
return value will be 0. */
|
return value will be 0. */
|
||||||
static int
|
static int
|
||||||
grub_lvm_getvalue (char **p, char *str)
|
grub_lvm_getvalue (char **p, const char *str)
|
||||||
{
|
{
|
||||||
*p = grub_strstr (*p, str);
|
*p = grub_strstr (*p, str);
|
||||||
if (! *p)
|
if (! *p)
|
||||||
return 0;
|
return 0;
|
||||||
*p += grub_strlen (str);
|
*p += grub_strlen (str);
|
||||||
return grub_strtoul (*p, NULL, 10);
|
return grub_strtoul (*p, p, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -67,7 +63,7 @@ grub_lvm_checkvalue (char **p, char *str, char *tmpl)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_lvm_check_flag (char *p, char *str, char *flag)
|
grub_lvm_check_flag (char *p, const char *str, const char *flag)
|
||||||
{
|
{
|
||||||
int len_str = grub_strlen (str), len_flag = grub_strlen (flag);
|
int len_str = grub_strlen (str), len_flag = grub_strlen (flag);
|
||||||
while (1)
|
while (1)
|
||||||
|
@ -99,31 +95,12 @@ grub_lvm_check_flag (char *p, char *str, char *flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct grub_lvm_lv *
|
static struct grub_diskfilter_vg *
|
||||||
find_lv (const char *name)
|
grub_lvm_detect (grub_disk_t disk,
|
||||||
|
struct grub_diskfilter_pv_id *id,
|
||||||
|
grub_disk_addr_t *start_sector)
|
||||||
{
|
{
|
||||||
struct grub_lvm_vg *vg;
|
|
||||||
struct grub_lvm_lv *lv = NULL;
|
|
||||||
for (vg = vg_list; vg; vg = vg->next)
|
|
||||||
{
|
|
||||||
if (vg->lvs)
|
|
||||||
for (lv = vg->lvs; lv; lv = lv->next)
|
|
||||||
if ((grub_strcmp (lv->fullname, name) == 0
|
|
||||||
|| grub_strcmp (lv->compatname, name) == 0)
|
|
||||||
&& is_lv_readable (lv))
|
|
||||||
return lv;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
do_lvm_scan (const char *scan_for)
|
|
||||||
{
|
|
||||||
auto int grub_lvm_scan_device (const char *name);
|
|
||||||
int grub_lvm_scan_device (const char *name)
|
|
||||||
{
|
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
grub_disk_t disk;
|
|
||||||
grub_uint64_t mda_offset, mda_size;
|
grub_uint64_t mda_offset, mda_size;
|
||||||
char buf[GRUB_LVM_LABEL_SIZE];
|
char buf[GRUB_LVM_LABEL_SIZE];
|
||||||
char vg_id[GRUB_LVM_ID_STRLEN+1];
|
char vg_id[GRUB_LVM_ID_STRLEN+1];
|
||||||
|
@ -135,29 +112,8 @@ do_lvm_scan (const char *scan_for)
|
||||||
struct grub_lvm_mda_header *mdah;
|
struct grub_lvm_mda_header *mdah;
|
||||||
struct grub_lvm_raw_locn *rlocn;
|
struct grub_lvm_raw_locn *rlocn;
|
||||||
unsigned int i, j, vgname_len;
|
unsigned int i, j, vgname_len;
|
||||||
struct grub_lvm_vg *vg;
|
struct grub_diskfilter_vg *vg;
|
||||||
struct grub_lvm_pv *pv;
|
struct grub_diskfilter_pv *pv;
|
||||||
|
|
||||||
#ifdef GRUB_UTIL
|
|
||||||
grub_util_info ("scanning %s for LVM", name);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
disk = grub_disk_open (name);
|
|
||||||
if (!disk)
|
|
||||||
{
|
|
||||||
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (vg = vg_list; vg; vg = vg->next)
|
|
||||||
for (pv = vg->pvs; pv; pv = pv->next)
|
|
||||||
if (pv->disk && pv->disk->id == disk->id
|
|
||||||
&& pv->disk->dev->id == disk->dev->id)
|
|
||||||
{
|
|
||||||
grub_disk_close (disk);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Search for label. */
|
/* Search for label. */
|
||||||
for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++)
|
for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++)
|
||||||
|
@ -281,11 +237,7 @@ do_lvm_scan (const char *scan_for)
|
||||||
grub_memcpy (vg_id, p, GRUB_LVM_ID_STRLEN);
|
grub_memcpy (vg_id, p, GRUB_LVM_ID_STRLEN);
|
||||||
vg_id[GRUB_LVM_ID_STRLEN] = '\0';
|
vg_id[GRUB_LVM_ID_STRLEN] = '\0';
|
||||||
|
|
||||||
for (vg = vg_list; vg; vg = vg->next)
|
vg = grub_diskfilter_get_vg_by_uuid (GRUB_LVM_ID_STRLEN, vg_id);
|
||||||
{
|
|
||||||
if (! grub_memcmp(vg_id, vg->id, GRUB_LVM_ID_STRLEN))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! vg)
|
if (! vg)
|
||||||
{
|
{
|
||||||
|
@ -295,7 +247,11 @@ do_lvm_scan (const char *scan_for)
|
||||||
if (! vg)
|
if (! vg)
|
||||||
goto fail3;
|
goto fail3;
|
||||||
vg->name = vgname;
|
vg->name = vgname;
|
||||||
grub_memcpy (vg->id, vg_id, GRUB_LVM_ID_STRLEN+1);
|
vg->uuid = grub_malloc (GRUB_LVM_ID_STRLEN);
|
||||||
|
if (! vg->uuid)
|
||||||
|
goto fail3;
|
||||||
|
grub_memcpy (vg->uuid, vg_id, GRUB_LVM_ID_STRLEN);
|
||||||
|
vg->uuid_len = GRUB_LVM_ID_STRLEN;
|
||||||
|
|
||||||
vg->extent_size = grub_lvm_getvalue (&p, "extent_size = ");
|
vg->extent_size = grub_lvm_getvalue (&p, "extent_size = ");
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
|
@ -324,7 +280,7 @@ do_lvm_scan (const char *scan_for)
|
||||||
if (*p == '}')
|
if (*p == '}')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
pv = grub_malloc (sizeof (*pv));
|
pv = grub_zalloc (sizeof (*pv));
|
||||||
q = p;
|
q = p;
|
||||||
while (*q != ' ')
|
while (*q != ' ')
|
||||||
q++;
|
q++;
|
||||||
|
@ -339,10 +295,13 @@ do_lvm_scan (const char *scan_for)
|
||||||
goto pvs_fail;
|
goto pvs_fail;
|
||||||
p += sizeof("id = \"") - 1;
|
p += sizeof("id = \"") - 1;
|
||||||
|
|
||||||
grub_memcpy (pv->id, p, GRUB_LVM_ID_STRLEN);
|
pv->id.uuid = grub_malloc (GRUB_LVM_ID_STRLEN);
|
||||||
pv->id[GRUB_LVM_ID_STRLEN] = '\0';
|
if (!pv->id.uuid)
|
||||||
|
goto pvs_fail;
|
||||||
|
grub_memcpy (pv->id.uuid, p, GRUB_LVM_ID_STRLEN);
|
||||||
|
pv->id.uuidlen = GRUB_LVM_ID_STRLEN;
|
||||||
|
|
||||||
pv->start = grub_lvm_getvalue (&p, "pe_start = ");
|
pv->start_sector = grub_lvm_getvalue (&p, "pe_start = ");
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
{
|
{
|
||||||
#ifdef GRUB_UTIL
|
#ifdef GRUB_UTIL
|
||||||
|
@ -376,15 +335,15 @@ do_lvm_scan (const char *scan_for)
|
||||||
p = grub_strstr (p, "logical_volumes");
|
p = grub_strstr (p, "logical_volumes");
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
p += 18;
|
p += sizeof ("logical_volumes = ") - 1;
|
||||||
|
|
||||||
/* And add all the lvs to the volume group. */
|
/* And add all the lvs to the volume group. */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
int skip_lv = 0;
|
int skip_lv = 0;
|
||||||
struct grub_lvm_lv *lv;
|
struct grub_diskfilter_lv *lv;
|
||||||
struct grub_lvm_segment *seg;
|
struct grub_diskfilter_segment *seg;
|
||||||
int is_pvmove;
|
int is_pvmove;
|
||||||
|
|
||||||
while (grub_isspace (*p))
|
while (grub_isspace (*p))
|
||||||
|
@ -393,7 +352,7 @@ do_lvm_scan (const char *scan_for)
|
||||||
if (*p == '}')
|
if (*p == '}')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
lv = grub_malloc (sizeof (*lv));
|
lv = grub_zalloc (sizeof (*lv));
|
||||||
|
|
||||||
q = p;
|
q = p;
|
||||||
while (*q != ' ')
|
while (*q != ' ')
|
||||||
|
@ -403,25 +362,17 @@ do_lvm_scan (const char *scan_for)
|
||||||
lv->name = grub_strndup (p, s);
|
lv->name = grub_strndup (p, s);
|
||||||
if (!lv->name)
|
if (!lv->name)
|
||||||
goto lvs_fail;
|
goto lvs_fail;
|
||||||
lv->compatname = grub_malloc (vgname_len + 1 + s + 1);
|
|
||||||
if (!lv->compatname)
|
|
||||||
goto lvs_fail;
|
|
||||||
grub_memcpy (lv->compatname, vgname, vgname_len);
|
|
||||||
lv->compatname[vgname_len] = '-';
|
|
||||||
grub_memcpy (lv->compatname + vgname_len + 1, p, s);
|
|
||||||
lv->compatname[vgname_len + 1 + s] = '\0';
|
|
||||||
|
|
||||||
{
|
{
|
||||||
const char *iptr;
|
const char *iptr;
|
||||||
char *optr;
|
char *optr;
|
||||||
lv->fullname = grub_malloc (sizeof("lvm/") + 2 * vgname_len
|
lv->fullname = grub_malloc (sizeof ("lvm/") - 1 + 2 * vgname_len
|
||||||
+ 1 + 2 * s + 1);
|
+ 1 + 2 * s + 1);
|
||||||
if (!lv->fullname)
|
if (!lv->fullname)
|
||||||
goto lvs_fail;
|
goto lvs_fail;
|
||||||
|
|
||||||
optr = lv->fullname;
|
grub_memcpy (lv->fullname, "lvm/", sizeof ("lvm/") - 1);
|
||||||
grub_memcpy (optr, "lvm/", sizeof ("lvm/") - 1);
|
optr = lv->fullname + sizeof ("lvm/") - 1;
|
||||||
optr += sizeof ("lvm/") - 1;
|
|
||||||
for (iptr = vgname; iptr < vgname + vgname_len; iptr++)
|
for (iptr = vgname; iptr < vgname + vgname_len; iptr++)
|
||||||
{
|
{
|
||||||
*optr++ = *iptr;
|
*optr++ = *iptr;
|
||||||
|
@ -493,9 +444,9 @@ do_lvm_scan (const char *scan_for)
|
||||||
if (grub_memcmp (p, "striped\"",
|
if (grub_memcmp (p, "striped\"",
|
||||||
sizeof ("striped\"") - 1) == 0)
|
sizeof ("striped\"") - 1) == 0)
|
||||||
{
|
{
|
||||||
struct grub_lvm_node *stripe;
|
struct grub_diskfilter_node *stripe;
|
||||||
|
|
||||||
seg->type = GRUB_LVM_STRIPED;
|
seg->type = GRUB_DISKFILTER_STRIPED;
|
||||||
seg->node_count = grub_lvm_getvalue (&p, "stripe_count = ");
|
seg->node_count = grub_lvm_getvalue (&p, "stripe_count = ");
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
{
|
{
|
||||||
|
@ -540,7 +491,10 @@ do_lvm_scan (const char *scan_for)
|
||||||
grub_memcpy (stripe->name, p, s);
|
grub_memcpy (stripe->name, p, s);
|
||||||
stripe->name[s] = '\0';
|
stripe->name[s] = '\0';
|
||||||
|
|
||||||
stripe->start = grub_lvm_getvalue (&p, ",");
|
p = q + 1;
|
||||||
|
|
||||||
|
stripe->start = grub_lvm_getvalue (&p, ",")
|
||||||
|
* vg->extent_size;
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -550,7 +504,7 @@ do_lvm_scan (const char *scan_for)
|
||||||
else if (grub_memcmp (p, "mirror\"", sizeof ("mirror\"") - 1)
|
else if (grub_memcmp (p, "mirror\"", sizeof ("mirror\"") - 1)
|
||||||
== 0)
|
== 0)
|
||||||
{
|
{
|
||||||
seg->type = GRUB_LVM_MIRROR;
|
seg->type = GRUB_DISKFILTER_MIRROR;
|
||||||
seg->node_count = grub_lvm_getvalue (&p, "mirror_count = ");
|
seg->node_count = grub_lvm_getvalue (&p, "mirror_count = ");
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
{
|
{
|
||||||
|
@ -599,6 +553,94 @@ do_lvm_scan (const char *scan_for)
|
||||||
if (is_pvmove)
|
if (is_pvmove)
|
||||||
seg->node_count = 1;
|
seg->node_count = 1;
|
||||||
}
|
}
|
||||||
|
else if (grub_memcmp (p, "raid", sizeof ("raid") - 1)
|
||||||
|
== 0 && (p[sizeof ("raid") - 1] >= '4'
|
||||||
|
&& p[sizeof ("raid") - 1] <= '6')
|
||||||
|
&& p[sizeof ("raidX") - 1] == '"')
|
||||||
|
{
|
||||||
|
switch (p[sizeof ("raid") - 1])
|
||||||
|
{
|
||||||
|
case '4':
|
||||||
|
seg->type = GRUB_DISKFILTER_RAID4;
|
||||||
|
seg->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
seg->type = GRUB_DISKFILTER_RAID5;
|
||||||
|
seg->layout = GRUB_RAID_LAYOUT_LEFT_SYMMETRIC;
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
seg->type = GRUB_DISKFILTER_RAID6;
|
||||||
|
seg->layout = (GRUB_RAID_LAYOUT_RIGHT_ASYMMETRIC
|
||||||
|
| GRUB_RAID_LAYOUT_MUL_FROM_POS);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
seg->node_count = grub_lvm_getvalue (&p, "device_count = ");
|
||||||
|
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
grub_util_info ("unknown device_count\n");
|
||||||
|
#endif
|
||||||
|
goto lvs_segment_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
grub_util_info ("unknown stripe_size\n");
|
||||||
|
#endif
|
||||||
|
goto lvs_segment_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
seg->nodes = grub_zalloc (sizeof (seg->nodes[0])
|
||||||
|
* seg->node_count);
|
||||||
|
|
||||||
|
p = grub_strstr (p, "raids = [");
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
#ifdef GRUB_UTIL
|
||||||
|
grub_util_info ("unknown mirrors\n");
|
||||||
|
#endif
|
||||||
|
goto lvs_segment_fail2;
|
||||||
|
}
|
||||||
|
p += sizeof("raids = [") - 1;
|
||||||
|
|
||||||
|
for (j = 0; j < seg->node_count; j++)
|
||||||
|
{
|
||||||
|
char *lvname;
|
||||||
|
|
||||||
|
p = grub_strchr (p, '"');
|
||||||
|
p = p ? grub_strchr (p + 1, '"') : 0;
|
||||||
|
p = p ? grub_strchr (p + 1, '"') : 0;
|
||||||
|
if (p == NULL)
|
||||||
|
continue;
|
||||||
|
q = ++p;
|
||||||
|
while (*q != '"')
|
||||||
|
q++;
|
||||||
|
|
||||||
|
s = q - p;
|
||||||
|
|
||||||
|
lvname = grub_malloc (s + 1);
|
||||||
|
if (lvname == NULL)
|
||||||
|
goto lvs_segment_fail2;
|
||||||
|
|
||||||
|
grub_memcpy (lvname, p, s);
|
||||||
|
lvname[s] = '\0';
|
||||||
|
seg->nodes[j].name = lvname;
|
||||||
|
p = q + 1;
|
||||||
|
}
|
||||||
|
if (seg->type == GRUB_DISKFILTER_RAID4)
|
||||||
|
{
|
||||||
|
char *tmp;
|
||||||
|
tmp = seg->nodes[0].name;
|
||||||
|
grub_memmove (seg->nodes, seg->nodes + 1,
|
||||||
|
sizeof (seg->nodes[0])
|
||||||
|
* (seg->node_count - 1));
|
||||||
|
seg->nodes[seg->node_count - 1].name = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef GRUB_UTIL
|
#ifdef GRUB_UTIL
|
||||||
|
@ -637,7 +679,6 @@ do_lvm_scan (const char *scan_for)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
lv->number = lv_count++;
|
|
||||||
lv->vg = vg;
|
lv->vg = vg;
|
||||||
lv->next = vg->lvs;
|
lv->next = vg->lvs;
|
||||||
vg->lvs = lv;
|
vg->lvs = lv;
|
||||||
|
@ -652,8 +693,8 @@ do_lvm_scan (const char *scan_for)
|
||||||
|
|
||||||
/* Match lvs. */
|
/* Match lvs. */
|
||||||
{
|
{
|
||||||
struct grub_lvm_lv *lv1;
|
struct grub_diskfilter_lv *lv1;
|
||||||
struct grub_lvm_lv *lv2;
|
struct grub_diskfilter_lv *lv2;
|
||||||
for (lv1 = vg->lvs; lv1; lv1 = lv1->next)
|
for (lv1 = vg->lvs; lv1; lv1 = lv1->next)
|
||||||
for (i = 0; i < lv1->segment_count; i++)
|
for (i = 0; i < lv1->segment_count; i++)
|
||||||
for (j = 0; j < lv1->segments[i].node_count; j++)
|
for (j = 0; j < lv1->segments[i].node_count; j++)
|
||||||
|
@ -670,37 +711,28 @@ do_lvm_scan (const char *scan_for)
|
||||||
}
|
}
|
||||||
if (lv1->segments[i].nodes[j].pv == NULL)
|
if (lv1->segments[i].nodes[j].pv == NULL)
|
||||||
for (lv2 = vg->lvs; lv2; lv2 = lv2->next)
|
for (lv2 = vg->lvs; lv2; lv2 = lv2->next)
|
||||||
if (grub_strcmp (lv2->name + grub_strlen (vg->name) + 1,
|
if (grub_strcmp (lv2->name,
|
||||||
lv1->segments[i].nodes[j].name) == 0)
|
lv1->segments[i].nodes[j].name) == 0)
|
||||||
lv1->segments[i].nodes[j].lv = lv2;
|
lv1->segments[i].nodes[j].lv = lv2;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if (grub_diskfilter_vg_register (vg))
|
||||||
vg->next = vg_list;
|
goto fail4;
|
||||||
vg_list = vg;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
grub_free (vgname);
|
grub_free (vgname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Match the device we are currently reading from with the right
|
id->uuid = grub_malloc (GRUB_LVM_ID_STRLEN);
|
||||||
PV. */
|
if (!id->uuid)
|
||||||
if (vg->pvs)
|
goto fail4;
|
||||||
for (pv = vg->pvs; pv; pv = pv->next)
|
grub_memcpy (id->uuid, pv_id, GRUB_LVM_ID_STRLEN);
|
||||||
{
|
id->uuidlen = GRUB_LVM_ID_STRLEN;
|
||||||
if (! grub_memcmp (pv->id, pv_id, GRUB_LVM_ID_STRLEN))
|
grub_free (metadatabuf);
|
||||||
{
|
*start_sector = -1;
|
||||||
/* This could happen to LVM on RAID, pv->disk points to the
|
return vg;
|
||||||
raid device, we shouldn't change it. */
|
|
||||||
if (! pv->disk)
|
|
||||||
pv->disk = grub_disk_open (name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
goto fail2;
|
|
||||||
|
|
||||||
/* Failure path. */
|
/* Failure path. */
|
||||||
fail4:
|
fail4:
|
||||||
|
@ -708,319 +740,26 @@ do_lvm_scan (const char *scan_for)
|
||||||
fail3:
|
fail3:
|
||||||
grub_free (vgname);
|
grub_free (vgname);
|
||||||
|
|
||||||
/* Normal exit path. */
|
|
||||||
fail2:
|
fail2:
|
||||||
grub_free (metadatabuf);
|
grub_free (metadatabuf);
|
||||||
fail:
|
fail:
|
||||||
grub_disk_close (disk);
|
return NULL;
|
||||||
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
grub_print_error ();
|
|
||||||
if (scan_for && find_lv (scan_for))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
scan_depth++;
|
|
||||||
grub_device_iterate (&grub_lvm_scan_device);
|
|
||||||
scan_depth--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
grub_lvm_iterate (int (*hook) (const char *name),
|
|
||||||
grub_disk_pull_t pull)
|
|
||||||
{
|
|
||||||
struct grub_lvm_vg *vg;
|
|
||||||
unsigned old_count = 0;
|
|
||||||
if (pull == GRUB_DISK_PULL_RESCAN && scan_depth)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (pull == GRUB_DISK_PULL_RESCAN)
|
|
||||||
{
|
|
||||||
old_count = lv_count;
|
|
||||||
if (!scan_depth)
|
|
||||||
do_lvm_scan (NULL);
|
|
||||||
}
|
|
||||||
if (pull != GRUB_DISK_PULL_RESCAN && pull != GRUB_DISK_PULL_NONE)
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
for (vg = vg_list; vg; vg = vg->next)
|
|
||||||
{
|
|
||||||
struct grub_lvm_lv *lv;
|
|
||||||
if (vg->lvs)
|
|
||||||
for (lv = vg->lvs; lv; lv = lv->next)
|
|
||||||
if (lv->visible && lv->number >= old_count)
|
|
||||||
{
|
|
||||||
if (hook (lv->fullname))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef GRUB_UTIL
|
|
||||||
static grub_disk_memberlist_t
|
|
||||||
grub_lvm_memberlist (grub_disk_t disk)
|
|
||||||
{
|
|
||||||
struct grub_lvm_lv *lv = disk->data;
|
|
||||||
grub_disk_memberlist_t list = NULL, tmp;
|
|
||||||
struct grub_lvm_pv *pv;
|
|
||||||
|
|
||||||
if (lv->vg->pvs)
|
|
||||||
for (pv = lv->vg->pvs; pv; pv = pv->next)
|
|
||||||
{
|
|
||||||
if (!pv->disk)
|
|
||||||
grub_util_error ("Couldn't find PV %s. Check your device.map",
|
|
||||||
pv->name);
|
|
||||||
tmp = grub_malloc (sizeof (*tmp));
|
|
||||||
tmp->disk = pv->disk;
|
|
||||||
tmp->next = list;
|
|
||||||
list = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_lvm_open (const char *name, grub_disk_t disk)
|
|
||||||
{
|
|
||||||
struct grub_lvm_lv *lv = NULL;
|
|
||||||
int explicit = 0;
|
|
||||||
|
|
||||||
if (grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) == 0)
|
|
||||||
explicit = 1;
|
|
||||||
|
|
||||||
lv = find_lv (name);
|
|
||||||
|
|
||||||
if (! lv && !scan_depth && explicit)
|
|
||||||
{
|
|
||||||
do_lvm_scan (name);
|
|
||||||
if (grub_errno)
|
|
||||||
{
|
|
||||||
grub_print_error ();
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
lv = find_lv (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! lv)
|
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown LVM device %s", name);
|
|
||||||
|
|
||||||
disk->id = lv->number;
|
|
||||||
disk->data = lv;
|
|
||||||
disk->total_sectors = lv->size;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
grub_lvm_close (grub_disk_t disk __attribute ((unused)))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
|
|
||||||
grub_size_t size, char *buf);
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
read_node (const struct grub_lvm_node *node, grub_disk_addr_t sector,
|
|
||||||
grub_size_t size, char *buf)
|
|
||||||
{
|
|
||||||
/* Check whether we actually know the physical volume we want to
|
|
||||||
read from. */
|
|
||||||
if (node->pv)
|
|
||||||
{
|
|
||||||
if (node->pv->disk)
|
|
||||||
return grub_disk_read (node->pv->disk, sector + node->pv->start, 0,
|
|
||||||
size << GRUB_DISK_SECTOR_BITS, buf);
|
|
||||||
else
|
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
|
||||||
"physical volume %s not found", node->pv->name);
|
|
||||||
|
|
||||||
}
|
|
||||||
if (node->lv)
|
|
||||||
return read_lv (node->lv, sector, size, buf);
|
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
|
|
||||||
grub_size_t size, char *buf)
|
|
||||||
{
|
|
||||||
grub_err_t err = 0;
|
|
||||||
struct grub_lvm_vg *vg = lv->vg;
|
|
||||||
struct grub_lvm_segment *seg = lv->segments;
|
|
||||||
struct grub_lvm_node *node;
|
|
||||||
grub_uint64_t offset;
|
|
||||||
grub_uint64_t extent;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (!lv)
|
|
||||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume");
|
|
||||||
|
|
||||||
extent = grub_divmod64 (sector, vg->extent_size, NULL);
|
|
||||||
|
|
||||||
/* Find the right segment. */
|
|
||||||
for (i = 0; i < lv->segment_count; i++)
|
|
||||||
{
|
|
||||||
if ((seg->start_extent <= extent)
|
|
||||||
&& ((seg->start_extent + seg->extent_count) > extent))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
seg++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == lv->segment_count)
|
|
||||||
return grub_error (GRUB_ERR_READ_ERROR, "incorrect segment");
|
|
||||||
|
|
||||||
switch (seg->type)
|
|
||||||
{
|
|
||||||
case GRUB_LVM_STRIPED:
|
|
||||||
if (seg->node_count == 1)
|
|
||||||
{
|
|
||||||
/* This segment is linear, so that's easy. We just need to find
|
|
||||||
out the offset in the physical volume and read SIZE bytes
|
|
||||||
from that. */
|
|
||||||
struct grub_lvm_node *stripe = seg->nodes;
|
|
||||||
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
|
|
||||||
|
|
||||||
node = stripe;
|
|
||||||
seg_offset = ((grub_uint64_t) stripe->start
|
|
||||||
* (grub_uint64_t) vg->extent_size);
|
|
||||||
|
|
||||||
offset = sector - ((grub_uint64_t) seg->start_extent
|
|
||||||
* (grub_uint64_t) vg->extent_size) + seg_offset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This is a striped segment. We have to find the right PV
|
|
||||||
similar to RAID0. */
|
|
||||||
struct grub_lvm_node *stripe = seg->nodes;
|
|
||||||
grub_uint64_t a, b;
|
|
||||||
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
|
|
||||||
grub_uint64_t stripenr;
|
|
||||||
|
|
||||||
offset = sector - ((grub_uint64_t) seg->start_extent
|
|
||||||
* (grub_uint64_t) vg->extent_size);
|
|
||||||
|
|
||||||
a = grub_divmod64 (offset, seg->stripe_size, NULL);
|
|
||||||
grub_divmod64 (a, seg->node_count, &stripenr);
|
|
||||||
|
|
||||||
a = grub_divmod64 (offset, seg->stripe_size * seg->node_count, NULL);
|
|
||||||
grub_divmod64 (offset, seg->stripe_size, &b);
|
|
||||||
offset = a * seg->stripe_size + b;
|
|
||||||
|
|
||||||
stripe += stripenr;
|
|
||||||
node = stripe;
|
|
||||||
|
|
||||||
seg_offset = ((grub_uint64_t) stripe->start
|
|
||||||
* (grub_uint64_t) vg->extent_size);
|
|
||||||
|
|
||||||
offset += seg_offset;
|
|
||||||
}
|
|
||||||
return read_node (node, offset, size, buf);
|
|
||||||
case GRUB_LVM_MIRROR:
|
|
||||||
i = 0;
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
err = read_node (&seg->nodes[i], sector, size, buf);
|
|
||||||
if (!err)
|
|
||||||
return err;
|
|
||||||
if (++i >= seg->node_count)
|
|
||||||
return err;
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return grub_error (GRUB_ERR_IO, "unknown LVM segment");
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
is_node_readable (const struct grub_lvm_node *node)
|
|
||||||
{
|
|
||||||
/* Check whether we actually know the physical volume we want to
|
|
||||||
read from. */
|
|
||||||
if (node->pv)
|
|
||||||
return !!(node->pv->disk);
|
|
||||||
if (node->lv)
|
|
||||||
return is_lv_readable (node->lv);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
is_lv_readable (struct grub_lvm_lv *lv)
|
|
||||||
{
|
|
||||||
unsigned int i, j;
|
|
||||||
|
|
||||||
if (!lv)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Find the right segment. */
|
|
||||||
for (i = 0; i < lv->segment_count; i++)
|
|
||||||
switch (lv->segments[i].type)
|
|
||||||
{
|
|
||||||
case GRUB_LVM_STRIPED:
|
|
||||||
for (j = 0; j < lv->segments[i].node_count; j++)
|
|
||||||
if (!is_node_readable (lv->segments[i].nodes + j))
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
case GRUB_LVM_MIRROR:
|
|
||||||
for (j = 0; j < lv->segments[i].node_count; j++)
|
|
||||||
if (is_node_readable (lv->segments[i].nodes + j))
|
|
||||||
break;
|
|
||||||
if (j == lv->segments[i].node_count)
|
|
||||||
return 0;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|
||||||
grub_size_t size, char *buf)
|
|
||||||
{
|
|
||||||
return read_lv (disk->data, sector, size, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_lvm_write (grub_disk_t disk __attribute ((unused)),
|
|
||||||
grub_disk_addr_t sector __attribute ((unused)),
|
|
||||||
grub_size_t size __attribute ((unused)),
|
|
||||||
const char *buf __attribute ((unused)))
|
|
||||||
{
|
|
||||||
return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct grub_disk_dev grub_lvm_dev =
|
|
||||||
{
|
|
||||||
.name = "lvm",
|
|
||||||
.id = GRUB_DISK_DEVICE_LVM_ID,
|
|
||||||
.iterate = grub_lvm_iterate,
|
|
||||||
.open = grub_lvm_open,
|
|
||||||
.close = grub_lvm_close,
|
|
||||||
.read = grub_lvm_read,
|
|
||||||
.write = grub_lvm_write,
|
|
||||||
#ifdef GRUB_UTIL
|
|
||||||
.memberlist = grub_lvm_memberlist,
|
|
||||||
#endif
|
|
||||||
.next = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
GRUB_MOD_INIT(lvm)
|
|
||||||
|
static struct grub_diskfilter grub_lvm_dev = {
|
||||||
|
.name = "lvm",
|
||||||
|
.detect = grub_lvm_detect,
|
||||||
|
.next = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
GRUB_MOD_INIT (lvm)
|
||||||
{
|
{
|
||||||
grub_disk_dev_register (&grub_lvm_dev);
|
grub_diskfilter_register (&grub_lvm_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(lvm)
|
GRUB_MOD_FINI (lvm)
|
||||||
{
|
{
|
||||||
grub_disk_dev_unregister (&grub_lvm_dev);
|
grub_diskfilter_unregister (&grub_lvm_dev);
|
||||||
vg_list = NULL;
|
|
||||||
/* FIXME: free the lvm list. */
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/raid.h>
|
#include <grub/diskfilter.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -103,8 +103,9 @@ struct grub_raid_super_1x
|
||||||
|
|
||||||
#define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */
|
#define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */
|
||||||
|
|
||||||
static grub_err_t
|
static struct grub_diskfilter_vg *
|
||||||
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
grub_mdraid_detect (grub_disk_t disk,
|
||||||
|
struct grub_diskfilter_pv_id *id,
|
||||||
grub_disk_addr_t *start_sector)
|
grub_disk_addr_t *start_sector)
|
||||||
{
|
{
|
||||||
grub_disk_addr_t sector = 0;
|
grub_disk_addr_t sector = 0;
|
||||||
|
@ -142,7 +143,7 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
||||||
|
|
||||||
if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x),
|
if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x),
|
||||||
&sb))
|
&sb))
|
||||||
return grub_errno;
|
return NULL;
|
||||||
|
|
||||||
if (grub_le_to_cpu32 (sb.magic) != SB_MAGIC
|
if (grub_le_to_cpu32 (sb.magic) != SB_MAGIC
|
||||||
|| grub_le_to_cpu64 (sb.super_offset) != sector)
|
|| grub_le_to_cpu64 (sb.super_offset) != sector)
|
||||||
|
@ -154,9 +155,12 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
||||||
grub_uint32_t level;
|
grub_uint32_t level;
|
||||||
|
|
||||||
if (grub_le_to_cpu32 (sb.major_version) != 1)
|
if (grub_le_to_cpu32 (sb.major_version) != 1)
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
{
|
||||||
|
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
"Unsupported RAID version: %d",
|
"Unsupported RAID version: %d",
|
||||||
grub_le_to_cpu32 (sb.major_version));
|
grub_le_to_cpu32 (sb.major_version));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
level = grub_le_to_cpu32 (sb.level);
|
level = grub_le_to_cpu32 (sb.level);
|
||||||
|
|
||||||
|
@ -166,8 +170,11 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
||||||
|
|
||||||
if (level != 0 && level != 1 && level != 4 &&
|
if (level != 0 && level != 1 && level != 4 &&
|
||||||
level != 5 && level != 6 && level != 10)
|
level != 5 && level != 6 && level != 10)
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
{
|
||||||
|
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
"Unsupported RAID level: %d", sb.level);
|
"Unsupported RAID level: %d", sb.level);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* 1.x superblocks don't have a fixed size on disk. So we have to
|
/* 1.x superblocks don't have a fixed size on disk. So we have to
|
||||||
read it again now that we now the max device count. */
|
read it again now that we now the max device count. */
|
||||||
|
@ -175,62 +182,68 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
||||||
+ 2 * grub_le_to_cpu32 (sb.max_dev);
|
+ 2 * grub_le_to_cpu32 (sb.max_dev);
|
||||||
real_sb = grub_malloc (sb_size);
|
real_sb = grub_malloc (sb_size);
|
||||||
if (! real_sb)
|
if (! real_sb)
|
||||||
return grub_errno;
|
return NULL;
|
||||||
|
|
||||||
if (grub_disk_read (disk, sector, 0, sb_size, real_sb))
|
if (grub_disk_read (disk, sector, 0, sb_size, real_sb))
|
||||||
{
|
{
|
||||||
grub_free (real_sb);
|
grub_free (real_sb);
|
||||||
return grub_errno;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
array->name = grub_strdup (real_sb->set_name);
|
struct grub_diskfilter_vg *array;
|
||||||
if (! array->name)
|
char *uuid;
|
||||||
{
|
|
||||||
grub_free (real_sb);
|
|
||||||
return grub_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
array->number = 0;
|
|
||||||
array->level = grub_le_to_cpu32 (real_sb->level);
|
|
||||||
array->layout = grub_le_to_cpu32 (real_sb->layout);
|
|
||||||
array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks);
|
|
||||||
if (real_sb->size)
|
|
||||||
array->disk_size = grub_le_to_cpu64 (real_sb->size);
|
|
||||||
else
|
|
||||||
array->disk_size = grub_le_to_cpu64 (real_sb->data_size);
|
|
||||||
array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);
|
|
||||||
|
|
||||||
if (grub_le_to_cpu32 (real_sb->dev_number) >=
|
if (grub_le_to_cpu32 (real_sb->dev_number) >=
|
||||||
grub_le_to_cpu32 (real_sb->max_dev))
|
grub_le_to_cpu32 (real_sb->max_dev))
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
|
||||||
"spares aren't implemented");
|
|
||||||
|
|
||||||
array->index = grub_le_to_cpu16
|
|
||||||
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
|
|
||||||
if (array->index >= array->total_devs)
|
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
|
||||||
"spares aren't implemented");
|
|
||||||
array->uuid_len = 16;
|
|
||||||
array->uuid = grub_malloc (16);
|
|
||||||
if (!array->uuid)
|
|
||||||
{
|
{
|
||||||
grub_free (real_sb);
|
grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
return grub_errno;
|
"spares aren't implemented");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_memcpy (array->uuid, real_sb->set_uuid, 16);
|
id->uuidlen = 0;
|
||||||
|
id->id = grub_le_to_cpu16
|
||||||
|
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
|
||||||
|
|
||||||
|
uuid = grub_malloc (16);
|
||||||
|
if (!uuid)
|
||||||
|
{
|
||||||
|
grub_free (real_sb);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_memcpy (uuid, real_sb->set_uuid, 16);
|
||||||
|
|
||||||
*start_sector = grub_le_to_cpu64 (real_sb->data_offset);
|
*start_sector = grub_le_to_cpu64 (real_sb->data_offset);
|
||||||
|
|
||||||
|
if (grub_le_to_cpu32 (real_sb->dev_number)
|
||||||
|
>= grub_le_to_cpu32 (real_sb->raid_disks))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
|
"spares aren't implemented");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
array = grub_diskfilter_make_raid (16, uuid,
|
||||||
|
grub_le_to_cpu32 (real_sb->raid_disks),
|
||||||
|
real_sb->set_name,
|
||||||
|
(real_sb->size)
|
||||||
|
? grub_le_to_cpu64 (real_sb->size)
|
||||||
|
: grub_le_to_cpu64 (real_sb->data_size),
|
||||||
|
grub_le_to_cpu32 (real_sb->chunksize),
|
||||||
|
grub_le_to_cpu32 (real_sb->layout),
|
||||||
|
grub_le_to_cpu32 (real_sb->level));
|
||||||
|
|
||||||
grub_free (real_sb);
|
grub_free (real_sb);
|
||||||
return 0;
|
return array;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 1.x raid");
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "not 1.x raid");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct grub_raid grub_mdraid_dev = {
|
static struct grub_diskfilter grub_mdraid_dev = {
|
||||||
.name = "mdraid1x",
|
.name = "mdraid1x",
|
||||||
.detect = grub_mdraid_detect,
|
.detect = grub_mdraid_detect,
|
||||||
.next = 0
|
.next = 0
|
||||||
|
@ -238,10 +251,10 @@ static struct grub_raid grub_mdraid_dev = {
|
||||||
|
|
||||||
GRUB_MOD_INIT (mdraid1x)
|
GRUB_MOD_INIT (mdraid1x)
|
||||||
{
|
{
|
||||||
grub_raid_register (&grub_mdraid_dev);
|
grub_diskfilter_register (&grub_mdraid_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI (mdraid1x)
|
GRUB_MOD_FINI (mdraid1x)
|
||||||
{
|
{
|
||||||
grub_raid_unregister (&grub_mdraid_dev);
|
grub_diskfilter_unregister (&grub_mdraid_dev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/raid.h>
|
#include <grub/diskfilter.h>
|
||||||
|
|
||||||
/* Linux RAID on disk structures and constants,
|
/* Linux RAID on disk structures and constants,
|
||||||
copied from include/linux/raid/md_p.h. */
|
copied from include/linux/raid/md_p.h. */
|
||||||
|
@ -161,8 +161,9 @@ struct grub_raid_super_09
|
||||||
struct grub_raid_disk_09 this_disk;
|
struct grub_raid_disk_09 this_disk;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
static grub_err_t
|
static struct grub_diskfilter_vg *
|
||||||
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
grub_mdraid_detect (grub_disk_t disk,
|
||||||
|
struct grub_diskfilter_pv_id *id,
|
||||||
grub_disk_addr_t *start_sector)
|
grub_disk_addr_t *start_sector)
|
||||||
{
|
{
|
||||||
grub_disk_addr_t sector;
|
grub_disk_addr_t sector;
|
||||||
|
@ -174,22 +175,31 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
||||||
/* The sector where the mdraid 0.90 superblock is stored, if available. */
|
/* The sector where the mdraid 0.90 superblock is stored, if available. */
|
||||||
size = grub_disk_get_size (disk);
|
size = grub_disk_get_size (disk);
|
||||||
if (size == GRUB_DISK_SIZE_UNKNOWN)
|
if (size == GRUB_DISK_SIZE_UNKNOWN)
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid");
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
sector = NEW_SIZE_SECTORS (size);
|
sector = NEW_SIZE_SECTORS (size);
|
||||||
|
|
||||||
if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb))
|
if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb))
|
||||||
return grub_errno;
|
return NULL;
|
||||||
|
|
||||||
/* Look whether there is a mdraid 0.90 superblock. */
|
/* Look whether there is a mdraid 0.90 superblock. */
|
||||||
if (grub_le_to_cpu32 (sb.md_magic) != SB_MAGIC)
|
if (grub_le_to_cpu32 (sb.md_magic) != SB_MAGIC)
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid");
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (grub_le_to_cpu32 (sb.major_version) != 0
|
if (grub_le_to_cpu32 (sb.major_version) != 0
|
||||||
|| grub_le_to_cpu32 (sb.minor_version) != 90)
|
|| grub_le_to_cpu32 (sb.minor_version) != 90)
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
{
|
||||||
|
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
"unsupported RAID version: %d.%d",
|
"unsupported RAID version: %d.%d",
|
||||||
grub_le_to_cpu32 (sb.major_version),
|
grub_le_to_cpu32 (sb.major_version),
|
||||||
grub_le_to_cpu32 (sb.minor_version));
|
grub_le_to_cpu32 (sb.minor_version));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: Check the checksum. */
|
/* FIXME: Check the checksum. */
|
||||||
|
|
||||||
|
@ -200,27 +210,23 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
||||||
|
|
||||||
if (level != 0 && level != 1 && level != 4 &&
|
if (level != 0 && level != 1 && level != 4 &&
|
||||||
level != 5 && level != 6 && level != 10)
|
level != 5 && level != 6 && level != 10)
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
{
|
||||||
|
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
"unsupported RAID level: %d", level);
|
"unsupported RAID level: %d", level);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (grub_le_to_cpu32 (sb.this_disk.number) == 0xffff
|
if (grub_le_to_cpu32 (sb.this_disk.number) == 0xffff
|
||||||
|| grub_le_to_cpu32 (sb.this_disk.number) == 0xfffe)
|
|| grub_le_to_cpu32 (sb.this_disk.number) == 0xfffe)
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
{
|
||||||
|
grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
"spares aren't implemented");
|
"spares aren't implemented");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
array->name = NULL;
|
uuid = grub_malloc (16);
|
||||||
array->number = grub_le_to_cpu32 (sb.md_minor);
|
if (!uuid)
|
||||||
array->level = level;
|
return NULL;
|
||||||
array->layout = grub_le_to_cpu32 (sb.layout);
|
|
||||||
array->total_devs = grub_le_to_cpu32 (sb.raid_disks);
|
|
||||||
array->disk_size = (sb.size) ? grub_le_to_cpu32 (sb.size) * 2 : sector;
|
|
||||||
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);
|
|
||||||
if (!array->uuid)
|
|
||||||
return grub_errno;
|
|
||||||
|
|
||||||
uuid = (grub_uint32_t *) array->uuid;
|
|
||||||
uuid[0] = grub_swap_bytes32 (sb.set_uuid0);
|
uuid[0] = grub_swap_bytes32 (sb.set_uuid0);
|
||||||
uuid[1] = grub_swap_bytes32 (sb.set_uuid1);
|
uuid[1] = grub_swap_bytes32 (sb.set_uuid1);
|
||||||
uuid[2] = grub_swap_bytes32 (sb.set_uuid2);
|
uuid[2] = grub_swap_bytes32 (sb.set_uuid2);
|
||||||
|
@ -228,10 +234,21 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
||||||
|
|
||||||
*start_sector = 0;
|
*start_sector = 0;
|
||||||
|
|
||||||
return 0;
|
id->uuidlen = 0;
|
||||||
|
id->id = grub_le_to_cpu32 (sb.this_disk.number);
|
||||||
|
|
||||||
|
char buf[32];
|
||||||
|
grub_snprintf (buf, sizeof (buf), "md%d", grub_le_to_cpu32 (sb.md_minor));
|
||||||
|
return grub_diskfilter_make_raid (16, (char *) uuid,
|
||||||
|
grub_le_to_cpu32 (sb.raid_disks), buf,
|
||||||
|
(sb.size) ? grub_le_to_cpu32 (sb.size) * 2
|
||||||
|
: sector,
|
||||||
|
grub_le_to_cpu32 (sb.chunk_size) >> 9,
|
||||||
|
grub_le_to_cpu32 (sb.layout),
|
||||||
|
level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct grub_raid grub_mdraid_dev = {
|
static struct grub_diskfilter grub_mdraid_dev = {
|
||||||
.name = "mdraid09",
|
.name = "mdraid09",
|
||||||
.detect = grub_mdraid_detect,
|
.detect = grub_mdraid_detect,
|
||||||
.next = 0
|
.next = 0
|
||||||
|
@ -239,10 +256,10 @@ static struct grub_raid grub_mdraid_dev = {
|
||||||
|
|
||||||
GRUB_MOD_INIT (mdraid09)
|
GRUB_MOD_INIT (mdraid09)
|
||||||
{
|
{
|
||||||
grub_raid_register (&grub_mdraid_dev);
|
grub_diskfilter_register (&grub_mdraid_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI (mdraid09)
|
GRUB_MOD_FINI (mdraid09)
|
||||||
{
|
{
|
||||||
grub_raid_unregister (&grub_mdraid_dev);
|
grub_diskfilter_unregister (&grub_mdraid_dev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,9 +86,8 @@ static struct grub_disk_dev grub_memdisk_dev =
|
||||||
|
|
||||||
GRUB_MOD_INIT(memdisk)
|
GRUB_MOD_INIT(memdisk)
|
||||||
{
|
{
|
||||||
auto int hook (struct grub_module_header *);
|
struct grub_module_header *header;
|
||||||
int hook (struct grub_module_header *header)
|
FOR_MODULES (header)
|
||||||
{
|
|
||||||
if (header->type == OBJ_TYPE_MEMDISK)
|
if (header->type == OBJ_TYPE_MEMDISK)
|
||||||
{
|
{
|
||||||
char *memdisk_orig_addr;
|
char *memdisk_orig_addr;
|
||||||
|
@ -103,13 +102,8 @@ GRUB_MOD_INIT(memdisk)
|
||||||
grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
|
grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size);
|
||||||
|
|
||||||
grub_disk_dev_register (&grub_memdisk_dev);
|
grub_disk_dev_register (&grub_memdisk_dev);
|
||||||
return 1;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
grub_module_iterate (hook);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(memdisk)
|
GRUB_MOD_FINI(memdisk)
|
||||||
|
|
|
@ -116,12 +116,13 @@ grub_pata_wait (void)
|
||||||
static void
|
static void
|
||||||
grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size)
|
grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size)
|
||||||
{
|
{
|
||||||
grub_uint16_t *buf16 = (grub_uint16_t *) buf;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* Read in the data, word by word. */
|
/* Read in the data, word by word. */
|
||||||
for (i = 0; i < size / 2; i++)
|
for (i = 0; i < size / 2; i++)
|
||||||
buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA));
|
grub_set_unaligned16 (buf + 2 * i,
|
||||||
|
grub_le_to_cpu16 (grub_inw(dev->ioaddress
|
||||||
|
+ GRUB_ATA_REG_DATA)));
|
||||||
if (size & 1)
|
if (size & 1)
|
||||||
buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress
|
buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress
|
||||||
+ GRUB_ATA_REG_DATA));
|
+ GRUB_ATA_REG_DATA));
|
||||||
|
@ -130,12 +131,11 @@ grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size)
|
||||||
static void
|
static void
|
||||||
grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size)
|
grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size)
|
||||||
{
|
{
|
||||||
grub_uint16_t *buf16 = (grub_uint16_t *) buf;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
/* Write the data, word by word. */
|
/* Write the data, word by word. */
|
||||||
for (i = 0; i < size / 2; i++)
|
for (i = 0; i < size / 2; i++)
|
||||||
grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA);
|
grub_outw(grub_cpu_to_le16 (grub_get_unaligned16 (buf + 2 * i)), dev->ioaddress + GRUB_ATA_REG_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ATA pass through support, used by hdparm.mod. */
|
/* ATA pass through support, used by hdparm.mod. */
|
||||||
|
@ -484,6 +484,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata)
|
||||||
|
|
||||||
ata->data = devfnd;
|
ata->data = devfnd;
|
||||||
ata->dma = 0;
|
ata->dma = 0;
|
||||||
|
ata->maxbuffer = 256 * 512;
|
||||||
ata->present = &devfnd->present;
|
ata->present = &devfnd->present;
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
|
|
@ -1,934 +0,0 @@
|
||||||
/* raid.c - module to read RAID arrays. */
|
|
||||||
/*
|
|
||||||
* GRUB -- GRand Unified Bootloader
|
|
||||||
* Copyright (C) 2006,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/err.h>
|
|
||||||
#include <grub/misc.h>
|
|
||||||
#include <grub/raid.h>
|
|
||||||
#ifdef GRUB_UTIL
|
|
||||||
#include <grub/util/misc.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
|
||||||
|
|
||||||
/* Linked list of RAID arrays. */
|
|
||||||
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
|
|
||||||
grub_is_array_readable (struct grub_raid_array *array)
|
|
||||||
{
|
|
||||||
switch (array->level)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
if (array->nr_devs == array->total_devs)
|
|
||||||
return 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
if (array->nr_devs >= 1)
|
|
||||||
return 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
case 5:
|
|
||||||
case 6:
|
|
||||||
case 10:
|
|
||||||
{
|
|
||||||
unsigned int n;
|
|
||||||
|
|
||||||
if (array->level == 10)
|
|
||||||
{
|
|
||||||
n = array->layout & 0xFF;
|
|
||||||
if (n == 1)
|
|
||||||
n = (array->layout >> 8) & 0xFF;
|
|
||||||
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
n = array->level / 3;
|
|
||||||
|
|
||||||
if (array->nr_devs >= array->total_devs - n)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 == m->device->dev->id)
|
|
||||||
{
|
|
||||||
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_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) && array->became_readable_at >= islcnt)
|
|
||||||
if (hook (array->name))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef GRUB_UTIL
|
|
||||||
static grub_disk_memberlist_t
|
|
||||||
grub_raid_memberlist (grub_disk_t disk)
|
|
||||||
{
|
|
||||||
struct grub_raid_array *array = disk->data;
|
|
||||||
grub_disk_memberlist_t list = NULL, tmp;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
for (i = 0; i < array->total_devs; i++)
|
|
||||||
if (array->members[i].device)
|
|
||||||
{
|
|
||||||
tmp = grub_malloc (sizeof (*tmp));
|
|
||||||
tmp->disk = array->members[i].device;
|
|
||||||
tmp->next = list;
|
|
||||||
list = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
grub_raid_getname (struct grub_disk *disk)
|
|
||||||
{
|
|
||||||
struct grub_raid_array *array = disk->data;
|
|
||||||
|
|
||||||
return array->driver->name;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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 struct grub_raid_array *
|
|
||||||
find_array (const char *name)
|
|
||||||
{
|
|
||||||
struct grub_raid_array *array;
|
|
||||||
|
|
||||||
if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0)
|
|
||||||
{
|
|
||||||
const char *uuidstr = name + sizeof ("mduuid/") - 1;
|
|
||||||
grub_size_t uuid_len = grub_strlen (uuidstr) / 2;
|
|
||||||
grub_uint8_t uuidbin[uuid_len];
|
|
||||||
unsigned i;
|
|
||||||
for (i = 0; i < uuid_len; i++)
|
|
||||||
uuidbin[i] = ascii2hex (uuidstr[2 * i + 1])
|
|
||||||
| (ascii2hex (uuidstr[2 * i]) << 4);
|
|
||||||
|
|
||||||
for (array = array_list; array != NULL; array = array->next)
|
|
||||||
{
|
|
||||||
if (uuid_len == (unsigned) array->uuid_len
|
|
||||||
&& grub_memcmp (uuidbin, array->uuid, uuid_len) == 0)
|
|
||||||
if (grub_is_array_readable (array))
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
for (array = array_list; array != NULL; array = array->next)
|
|
||||||
{
|
|
||||||
if (!grub_strcmp (array->name, name))
|
|
||||||
if (grub_is_array_readable (array))
|
|
||||||
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",
|
|
||||||
name);
|
|
||||||
|
|
||||||
disk->id = array->number;
|
|
||||||
disk->data = array;
|
|
||||||
|
|
||||||
grub_dprintf ("raid", "%s: total_devs=%d, disk_size=%lld\n", name,
|
|
||||||
array->total_devs, (unsigned long long) array->disk_size);
|
|
||||||
|
|
||||||
switch (array->level)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
disk->total_sectors = array->disk_size;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 10:
|
|
||||||
n = array->layout & 0xFF;
|
|
||||||
if (n == 1)
|
|
||||||
n = (array->layout >> 8) & 0xFF;
|
|
||||||
|
|
||||||
disk->total_sectors = grub_divmod64 (array->total_devs *
|
|
||||||
array->disk_size,
|
|
||||||
n, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
case 4:
|
|
||||||
case 5:
|
|
||||||
case 6:
|
|
||||||
n = array->level / 3;
|
|
||||||
|
|
||||||
disk->total_sectors = (array->total_devs - n) * array->disk_size;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
grub_dprintf ("raid", "%s: level=%d, total_sectors=%lld\n", name,
|
|
||||||
array->level, (unsigned long long) disk->total_sectors);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
struct grub_raid_array *array = disk->data;
|
|
||||||
grub_err_t err = 0;
|
|
||||||
|
|
||||||
switch (array->level)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
case 10:
|
|
||||||
{
|
|
||||||
grub_disk_addr_t read_sector, far_ofs;
|
|
||||||
grub_uint64_t disknr, b, near, far, ofs;
|
|
||||||
|
|
||||||
read_sector = grub_divmod64 (sector, array->chunk_size, &b);
|
|
||||||
far = ofs = near = 1;
|
|
||||||
far_ofs = 0;
|
|
||||||
|
|
||||||
if (array->level == 1)
|
|
||||||
near = array->total_devs;
|
|
||||||
else if (array->level == 10)
|
|
||||||
{
|
|
||||||
near = array->layout & 0xFF;
|
|
||||||
far = (array->layout >> 8) & 0xFF;
|
|
||||||
if (array->layout >> 16)
|
|
||||||
{
|
|
||||||
ofs = far;
|
|
||||||
far_ofs = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
far_ofs = grub_divmod64 (array->disk_size,
|
|
||||||
far * array->chunk_size, 0);
|
|
||||||
|
|
||||||
far_ofs *= array->chunk_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
read_sector = grub_divmod64 (read_sector * near, array->total_devs,
|
|
||||||
&disknr);
|
|
||||||
|
|
||||||
ofs *= array->chunk_size;
|
|
||||||
read_sector *= ofs;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
grub_size_t read_size;
|
|
||||||
unsigned int i, j;
|
|
||||||
|
|
||||||
read_size = array->chunk_size - b;
|
|
||||||
if (read_size > size)
|
|
||||||
read_size = size;
|
|
||||||
|
|
||||||
for (i = 0; i < near; i++)
|
|
||||||
{
|
|
||||||
unsigned int k;
|
|
||||||
|
|
||||||
k = disknr;
|
|
||||||
for (j = 0; j < far; j++)
|
|
||||||
{
|
|
||||||
if (array->members[k].device)
|
|
||||||
{
|
|
||||||
if (grub_errno == GRUB_ERR_READ_ERROR)
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
|
|
||||||
err = grub_disk_read (array->members[k].device,
|
|
||||||
array->members[k].start_sector +
|
|
||||||
read_sector + j * far_ofs + b,
|
|
||||||
0,
|
|
||||||
read_size << GRUB_DISK_SECTOR_BITS,
|
|
||||||
buf);
|
|
||||||
if (! err)
|
|
||||||
break;
|
|
||||||
else if (err != GRUB_ERR_READ_ERROR)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
err = grub_error (GRUB_ERR_READ_ERROR,
|
|
||||||
"disk missing");
|
|
||||||
|
|
||||||
k++;
|
|
||||||
if (k == array->total_devs)
|
|
||||||
k = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! err)
|
|
||||||
break;
|
|
||||||
|
|
||||||
disknr++;
|
|
||||||
if (disknr == array->total_devs)
|
|
||||||
{
|
|
||||||
disknr = 0;
|
|
||||||
read_sector += ofs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
buf += read_size << GRUB_DISK_SECTOR_BITS;
|
|
||||||
size -= read_size;
|
|
||||||
if (! size)
|
|
||||||
break;
|
|
||||||
|
|
||||||
b = 0;
|
|
||||||
disknr += (near - i);
|
|
||||||
while (disknr >= array->total_devs)
|
|
||||||
{
|
|
||||||
disknr -= array->total_devs;
|
|
||||||
read_sector += ofs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
case 5:
|
|
||||||
case 6:
|
|
||||||
{
|
|
||||||
grub_disk_addr_t read_sector;
|
|
||||||
grub_uint64_t b, p, n, disknr, e;
|
|
||||||
|
|
||||||
/* n = 1 for level 4 and 5, 2 for level 6. */
|
|
||||||
n = array->level / 3;
|
|
||||||
|
|
||||||
/* Find the first sector to read. */
|
|
||||||
read_sector = grub_divmod64 (sector, array->chunk_size, &b);
|
|
||||||
read_sector = grub_divmod64 (read_sector, array->total_devs - n,
|
|
||||||
&disknr);
|
|
||||||
if (array->level >= 5)
|
|
||||||
{
|
|
||||||
grub_divmod64 (read_sector, array->total_devs, &p);
|
|
||||||
|
|
||||||
if (! (array->layout & GRUB_RAID_LAYOUT_RIGHT_MASK))
|
|
||||||
p = array->total_devs - 1 - p;
|
|
||||||
|
|
||||||
if (array->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK)
|
|
||||||
{
|
|
||||||
disknr += p + n;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
grub_uint32_t q;
|
|
||||||
|
|
||||||
q = p + (n - 1);
|
|
||||||
if (q >= array->total_devs)
|
|
||||||
q -= array->total_devs;
|
|
||||||
|
|
||||||
if (disknr >= p)
|
|
||||||
disknr += n;
|
|
||||||
else if (disknr >= q)
|
|
||||||
disknr += q + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (disknr >= array->total_devs)
|
|
||||||
disknr -= array->total_devs;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
p = array->total_devs - n;
|
|
||||||
|
|
||||||
read_sector *= array->chunk_size;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
grub_size_t read_size;
|
|
||||||
int next_level;
|
|
||||||
|
|
||||||
read_size = array->chunk_size - b;
|
|
||||||
if (read_size > size)
|
|
||||||
read_size = size;
|
|
||||||
|
|
||||||
e = 0;
|
|
||||||
if (array->members[disknr].device)
|
|
||||||
{
|
|
||||||
/* Reset read error. */
|
|
||||||
if (grub_errno == GRUB_ERR_READ_ERROR)
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
|
|
||||||
err = grub_disk_read (array->members[disknr].device,
|
|
||||||
array->members[disknr].start_sector +
|
|
||||||
read_sector + b, 0,
|
|
||||||
read_size << GRUB_DISK_SECTOR_BITS,
|
|
||||||
buf);
|
|
||||||
|
|
||||||
if ((err) && (err != GRUB_ERR_READ_ERROR))
|
|
||||||
break;
|
|
||||||
e++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
err = GRUB_ERR_READ_ERROR;
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
if (array->nr_devs < array->total_devs - n + e)
|
|
||||||
break;
|
|
||||||
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
|
||||||
if (array->level == 6)
|
|
||||||
{
|
|
||||||
err = ((grub_raid6_recover_func) ?
|
|
||||||
(*grub_raid6_recover_func) (array, disknr, p,
|
|
||||||
buf, read_sector + b,
|
|
||||||
read_size) :
|
|
||||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
|
||||||
"raid6rec is not loaded"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
err = ((grub_raid5_recover_func) ?
|
|
||||||
(*grub_raid5_recover_func) (array, disknr,
|
|
||||||
buf, read_sector + b,
|
|
||||||
read_size) :
|
|
||||||
grub_error (GRUB_ERR_BAD_DEVICE,
|
|
||||||
"raid5rec is not loaded"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf += read_size << GRUB_DISK_SECTOR_BITS;
|
|
||||||
size -= read_size;
|
|
||||||
if (! size)
|
|
||||||
break;
|
|
||||||
|
|
||||||
b = 0;
|
|
||||||
disknr++;
|
|
||||||
|
|
||||||
if (array->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK)
|
|
||||||
{
|
|
||||||
if (disknr == array->total_devs)
|
|
||||||
disknr = 0;
|
|
||||||
|
|
||||||
next_level = (disknr == p);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (disknr == p)
|
|
||||||
disknr += n;
|
|
||||||
|
|
||||||
next_level = (disknr >= array->total_devs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (next_level)
|
|
||||||
{
|
|
||||||
read_sector += array->chunk_size;
|
|
||||||
|
|
||||||
if (array->level >= 5)
|
|
||||||
{
|
|
||||||
if (array->layout & GRUB_RAID_LAYOUT_RIGHT_MASK)
|
|
||||||
p = (p == array->total_devs - 1) ? 0 : p + 1;
|
|
||||||
else
|
|
||||||
p = (p == 0) ? array->total_devs - 1 : p - 1;
|
|
||||||
|
|
||||||
if (array->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK)
|
|
||||||
{
|
|
||||||
disknr = p + n;
|
|
||||||
if (disknr >= array->total_devs)
|
|
||||||
disknr -= array->total_devs;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
disknr -= array->total_devs;
|
|
||||||
if (disknr == p)
|
|
||||||
disknr += n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
disknr = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_raid_write (grub_disk_t disk __attribute ((unused)),
|
|
||||||
grub_disk_addr_t sector __attribute ((unused)),
|
|
||||||
grub_size_t size __attribute ((unused)),
|
|
||||||
const char *buf __attribute ((unused)))
|
|
||||||
{
|
|
||||||
return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
|
||||||
}
|
|
||||||
|
|
||||||
static 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)))
|
|
||||||
{
|
|
||||||
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. */
|
|
||||||
for (p = array_list; p != NULL; p = p->next)
|
|
||||||
if ((p->uuid_len == new_array->uuid_len) &&
|
|
||||||
(! grub_memcmp (p->uuid, new_array->uuid, p->uuid_len)))
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
void *tmp;
|
|
||||||
unsigned int newnum = 2 * (new_array->index + 1);
|
|
||||||
tmp = grub_realloc (array->members, newnum
|
|
||||||
* sizeof (array->members[0]));
|
|
||||||
if (!tmp)
|
|
||||||
return grub_errno;
|
|
||||||
array->members = tmp;
|
|
||||||
grub_memset (array->members + array->allocated_devs,
|
|
||||||
0, (newnum - array->allocated_devs)
|
|
||||||
* sizeof (array->members[0]));
|
|
||||||
array->allocated_devs = newnum;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: Check whether the update time of the superblocks are
|
|
||||||
the same. */
|
|
||||||
|
|
||||||
if (array->total_devs == array->nr_devs)
|
|
||||||
/* We found more members of the array than the array
|
|
||||||
actually has according to its superblock. This shouldn't
|
|
||||||
happen normally. */
|
|
||||||
return grub_error (GRUB_ERR_BAD_DEVICE,
|
|
||||||
"superfluous RAID member (%d found)",
|
|
||||||
array->total_devs);
|
|
||||||
|
|
||||||
if (array->members[new_array->index].device != NULL)
|
|
||||||
/* We found multiple devices with the same number. Again,
|
|
||||||
this shouldn't happen. */
|
|
||||||
return grub_error (GRUB_ERR_BAD_DEVICE,
|
|
||||||
"found two disks with the index %d for RAID %s",
|
|
||||||
new_array->index, array->name);
|
|
||||||
|
|
||||||
if (new_array->disk_size < array->disk_size)
|
|
||||||
array->disk_size = new_array->disk_size;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add an array to the list if we didn't find any. */
|
|
||||||
if (!array)
|
|
||||||
{
|
|
||||||
array = grub_malloc (sizeof (*array));
|
|
||||||
if (!array)
|
|
||||||
{
|
|
||||||
grub_free (new_array->uuid);
|
|
||||||
return grub_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
*array = *new_array;
|
|
||||||
array->nr_devs = 0;
|
|
||||||
#ifdef GRUB_UTIL
|
|
||||||
array->driver = raid;
|
|
||||||
#endif
|
|
||||||
array->allocated_devs = 32;
|
|
||||||
if (new_array->index >= array->allocated_devs)
|
|
||||||
array->allocated_devs = 2 * (new_array->index + 1);
|
|
||||||
|
|
||||||
array->members = grub_zalloc (array->allocated_devs
|
|
||||||
* sizeof (array->members[0]));
|
|
||||||
|
|
||||||
if (!array->members)
|
|
||||||
{
|
|
||||||
grub_free (new_array->uuid);
|
|
||||||
return grub_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! array->name)
|
|
||||||
{
|
|
||||||
for (p = array_list; p != NULL; p = p->next)
|
|
||||||
{
|
|
||||||
if (p->number == array->number)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array->name || p)
|
|
||||||
{
|
|
||||||
/* The number is already in use, so we need to find a new one.
|
|
||||||
(Or, in the case of named arrays, the array doesn't have its
|
|
||||||
own number, but we need one that doesn't clash for use as a key
|
|
||||||
in the disk cache. */
|
|
||||||
int i = array->name ? 0x40000000 : 0;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
for (p = array_list; p != NULL; p = p->next)
|
|
||||||
{
|
|
||||||
if (p->number == i)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! p)
|
|
||||||
{
|
|
||||||
/* We found an unused number. */
|
|
||||||
array->number = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mdraid 1.x superblocks have only a name stored not a number.
|
|
||||||
Use it directly as GRUB device. */
|
|
||||||
if (! array->name)
|
|
||||||
{
|
|
||||||
array->name = grub_xasprintf ("md%d", array->number);
|
|
||||||
if (! array->name)
|
|
||||||
{
|
|
||||||
grub_free (array->members);
|
|
||||||
grub_free (array->uuid);
|
|
||||||
grub_free (array);
|
|
||||||
|
|
||||||
return grub_errno;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Strip off the homehost if present. */
|
|
||||||
char *colon = grub_strchr (array->name, ':');
|
|
||||||
char *new_name = grub_xasprintf ("md/%s",
|
|
||||||
colon ? colon + 1 : array->name);
|
|
||||||
|
|
||||||
if (! new_name)
|
|
||||||
{
|
|
||||||
grub_free (array->members);
|
|
||||||
grub_free (array->uuid);
|
|
||||||
grub_free (array);
|
|
||||||
|
|
||||||
return grub_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
grub_free (array->name);
|
|
||||||
array->name = new_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
grub_dprintf ("raid", "Found array %s (%s)\n", array->name,
|
|
||||||
scanner_name);
|
|
||||||
#ifdef GRUB_UTIL
|
|
||||||
grub_util_info ("Found array %s (%s)", array->name,
|
|
||||||
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;
|
|
||||||
|
|
||||||
/* RAID 1 doesn't use a chunksize but code assumes one so set
|
|
||||||
one. */
|
|
||||||
if (array->level == 1)
|
|
||||||
array->chunk_size = 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add the device to the 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 void
|
|
||||||
free_array (void)
|
|
||||||
{
|
|
||||||
struct grub_raid_array *array;
|
|
||||||
|
|
||||||
array = array_list;
|
|
||||||
while (array)
|
|
||||||
{
|
|
||||||
struct grub_raid_array *p;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
p = array;
|
|
||||||
array = array->next;
|
|
||||||
|
|
||||||
for (i = 0; i < p->allocated_devs; i++)
|
|
||||||
if (p->members[i].device)
|
|
||||||
grub_disk_close (p->members[i].device);
|
|
||||||
grub_free (p->members);
|
|
||||||
|
|
||||||
grub_free (p->uuid);
|
|
||||||
grub_free (p->name);
|
|
||||||
grub_free (p);
|
|
||||||
}
|
|
||||||
|
|
||||||
array_list = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
grub_raid_register (grub_raid_t raid)
|
|
||||||
{
|
|
||||||
raid->next = grub_raid_list;
|
|
||||||
grub_raid_list = raid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
grub_raid_unregister (grub_raid_t raid)
|
|
||||||
{
|
|
||||||
grub_raid_t *p, q;
|
|
||||||
|
|
||||||
for (p = &grub_raid_list, q = *p; q; p = &(q->next), q = q->next)
|
|
||||||
if (q == raid)
|
|
||||||
{
|
|
||||||
*p = q->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct grub_disk_dev grub_raid_dev =
|
|
||||||
{
|
|
||||||
.name = "raid",
|
|
||||||
.id = GRUB_DISK_DEVICE_RAID_ID,
|
|
||||||
.iterate = grub_raid_iterate,
|
|
||||||
.open = grub_raid_open,
|
|
||||||
.close = grub_raid_close,
|
|
||||||
.read = grub_raid_read,
|
|
||||||
.write = grub_raid_write,
|
|
||||||
#ifdef GRUB_UTIL
|
|
||||||
.memberlist = grub_raid_memberlist,
|
|
||||||
.raidname = grub_raid_getname,
|
|
||||||
#endif
|
|
||||||
.next = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
GRUB_MOD_INIT(raid)
|
|
||||||
{
|
|
||||||
grub_disk_dev_register (&grub_raid_dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
GRUB_MOD_FINI(raid)
|
|
||||||
{
|
|
||||||
grub_disk_dev_unregister (&grub_raid_dev);
|
|
||||||
free_array ();
|
|
||||||
}
|
|
|
@ -22,12 +22,13 @@
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/raid.h>
|
#include <grub/diskfilter.h>
|
||||||
|
#include <grub/crypto.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_raid5_recover (struct grub_raid_array *array, int disknr,
|
grub_raid5_recover (struct grub_diskfilter_segment *array, int disknr,
|
||||||
char *buf, grub_disk_addr_t sector, int size)
|
char *buf, grub_disk_addr_t sector, int size)
|
||||||
{
|
{
|
||||||
char *buf2;
|
char *buf2;
|
||||||
|
@ -40,16 +41,15 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr,
|
||||||
|
|
||||||
grub_memset (buf, 0, size);
|
grub_memset (buf, 0, size);
|
||||||
|
|
||||||
for (i = 0; i < (int) array->total_devs; i++)
|
for (i = 0; i < (int) array->node_count; i++)
|
||||||
{
|
{
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
|
||||||
if (i == disknr)
|
if (i == disknr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
err = grub_disk_read (array->members[i].device,
|
err = grub_diskfilter_read_node (&array->nodes[i], sector,
|
||||||
array->members[i].start_sector + sector,
|
size >> GRUB_DISK_SECTOR_BITS, buf2);
|
||||||
0, size, buf2);
|
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
|
@ -57,7 +57,7 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_raid_block_xor (buf, buf2, size);
|
grub_crypto_xor (buf, buf, buf2, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_free (buf2);
|
grub_free (buf2);
|
||||||
|
|
|
@ -22,75 +22,49 @@
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/err.h>
|
#include <grub/err.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/raid.h>
|
#include <grub/diskfilter.h>
|
||||||
|
#include <grub/crypto.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
static grub_uint8_t raid6_table1[256][256];
|
/* x**y. */
|
||||||
static grub_uint8_t raid6_table2[256][256];
|
static grub_uint8_t powx[255 * 2];
|
||||||
|
/* Such an s that x**s = y */
|
||||||
|
static int powx_inv[256];
|
||||||
|
static const grub_uint8_t poly = 0x1d;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
grub_raid_block_mul (grub_uint8_t mul, char *buf, int size)
|
grub_raid_block_mulx (int mul, char *buf, int size)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
grub_uint8_t *p;
|
grub_uint8_t *p;
|
||||||
|
|
||||||
p = (grub_uint8_t *) buf;
|
p = (grub_uint8_t *) buf;
|
||||||
for (i = 0; i < size; i++, p++)
|
for (i = 0; i < size; i++, p++)
|
||||||
*p = raid6_table1[mul][*p];
|
if (*p)
|
||||||
|
*p = powx[mul + powx_inv[*p]];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
grub_raid6_init_table (void)
|
grub_raid6_init_table (void)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 256; i++)
|
grub_uint8_t cur = 1;
|
||||||
raid6_table1[i][1] = raid6_table1[1][i] = i;
|
for (i = 0; i < 255; i++)
|
||||||
|
|
||||||
for (i = 2; i < 256; i++)
|
|
||||||
for (j = i; j < 256; j++)
|
|
||||||
{
|
{
|
||||||
int n;
|
powx[i] = cur;
|
||||||
grub_uint8_t c;
|
powx[i + 255] = cur;
|
||||||
|
powx_inv[cur] = i;
|
||||||
n = i >> 1;
|
if (cur & 0x80)
|
||||||
|
cur = (cur << 1) ^ poly;
|
||||||
c = raid6_table1[n][j];
|
else
|
||||||
c = (c << 1) ^ ((c & 0x80) ? 0x1d : 0);
|
cur <<= 1;
|
||||||
if (i & 1)
|
|
||||||
c ^= j;
|
|
||||||
|
|
||||||
raid6_table1[j][i] = raid6_table1[i][j] = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
raid6_table2[0][0] = 1;
|
|
||||||
for (i = 1; i < 256; i++)
|
|
||||||
raid6_table2[i][i] = raid6_table1[raid6_table2[i - 1][i - 1]][2];
|
|
||||||
|
|
||||||
for (i = 0; i < 254; i++)
|
|
||||||
for (j = 0; j < 254; j++)
|
|
||||||
{
|
|
||||||
grub_uint8_t c, n;
|
|
||||||
int k;
|
|
||||||
|
|
||||||
if (i == j)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
k = i - j;
|
|
||||||
if (k < 0)
|
|
||||||
k += 255;
|
|
||||||
|
|
||||||
c = n = raid6_table2[k][k] ^ 1;
|
|
||||||
for (k = 0; k < 253; k++)
|
|
||||||
c = raid6_table1[c][n];
|
|
||||||
|
|
||||||
raid6_table2[i][j] = raid6_table1[raid6_table2[255 - j][255 - j]][c];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
|
grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p,
|
||||||
char *buf, grub_disk_addr_t sector, int size)
|
char *buf, grub_disk_addr_t sector, int size)
|
||||||
{
|
{
|
||||||
int i, q, pos;
|
int i, q, pos;
|
||||||
|
@ -107,27 +81,30 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
|
||||||
goto quit;
|
goto quit;
|
||||||
|
|
||||||
q = p + 1;
|
q = p + 1;
|
||||||
if (q == (int) array->total_devs)
|
if (q == (int) array->node_count)
|
||||||
q = 0;
|
q = 0;
|
||||||
|
|
||||||
pos = q + 1;
|
pos = q + 1;
|
||||||
if (pos == (int) array->total_devs)
|
if (pos == (int) array->node_count)
|
||||||
pos = 0;
|
pos = 0;
|
||||||
|
|
||||||
for (i = 0; i < (int) array->total_devs - 2; i++)
|
for (i = 0; i < (int) array->node_count - 2; i++)
|
||||||
{
|
{
|
||||||
|
int c;
|
||||||
|
if (array->layout & GRUB_RAID_LAYOUT_MUL_FROM_POS)
|
||||||
|
c = pos;
|
||||||
|
else
|
||||||
|
c = i;
|
||||||
if (pos == disknr)
|
if (pos == disknr)
|
||||||
bad1 = i;
|
bad1 = c;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((array->members[pos].device) &&
|
if (! grub_diskfilter_read_node (&array->nodes[pos], sector,
|
||||||
(! grub_disk_read (array->members[pos].device,
|
size >> GRUB_DISK_SECTOR_BITS, buf))
|
||||||
array->members[i].start_sector + sector,
|
|
||||||
0, size, buf)))
|
|
||||||
{
|
{
|
||||||
grub_raid_block_xor (pbuf, buf, size);
|
grub_crypto_xor (pbuf, pbuf, buf, size);
|
||||||
grub_raid_block_mul (raid6_table2[i][i], buf, size);
|
grub_raid_block_mulx (c, buf, size);
|
||||||
grub_raid_block_xor (qbuf, buf, size);
|
grub_crypto_xor (qbuf, qbuf, buf, size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -135,13 +112,13 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
|
||||||
if (bad2 >= 0)
|
if (bad2 >= 0)
|
||||||
goto quit;
|
goto quit;
|
||||||
|
|
||||||
bad2 = i;
|
bad2 = c;
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos++;
|
pos++;
|
||||||
if (pos == (int) array->total_devs)
|
if (pos == (int) array->node_count)
|
||||||
pos = 0;
|
pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,62 +129,46 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
|
||||||
if (bad2 < 0)
|
if (bad2 < 0)
|
||||||
{
|
{
|
||||||
/* One bad device */
|
/* One bad device */
|
||||||
if ((array->members[p].device) &&
|
if ((! grub_diskfilter_read_node (&array->nodes[p], sector,
|
||||||
(! grub_disk_read (array->members[p].device,
|
size >> GRUB_DISK_SECTOR_BITS, buf)))
|
||||||
array->members[i].start_sector + sector,
|
|
||||||
0, size, buf)))
|
|
||||||
{
|
{
|
||||||
grub_raid_block_xor (buf, pbuf, size);
|
grub_crypto_xor (buf, buf, pbuf, size);
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! array->members[q].device)
|
|
||||||
{
|
|
||||||
grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore");
|
|
||||||
goto quit;
|
goto quit;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
if (grub_disk_read (array->members[q].device,
|
if (grub_diskfilter_read_node (&array->nodes[q], sector,
|
||||||
array->members[i].start_sector + sector, 0, size, buf))
|
size >> GRUB_DISK_SECTOR_BITS, buf))
|
||||||
goto quit;
|
goto quit;
|
||||||
|
|
||||||
grub_raid_block_xor (buf, qbuf, size);
|
grub_crypto_xor (buf, buf, qbuf, size);
|
||||||
grub_raid_block_mul (raid6_table2[255 - bad1][255 - bad1], buf,
|
grub_raid_block_mulx (255 - bad1, buf,
|
||||||
size);
|
size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Two bad devices */
|
/* Two bad devices */
|
||||||
grub_uint8_t c;
|
int c;
|
||||||
|
|
||||||
if ((! array->members[p].device) || (! array->members[q].device))
|
if (grub_diskfilter_read_node (&array->nodes[p], sector,
|
||||||
{
|
size >> GRUB_DISK_SECTOR_BITS, buf))
|
||||||
grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore");
|
|
||||||
goto quit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (grub_disk_read (array->members[p].device,
|
|
||||||
array->members[i].start_sector + sector,
|
|
||||||
0, size, buf))
|
|
||||||
goto quit;
|
goto quit;
|
||||||
|
|
||||||
grub_raid_block_xor (pbuf, buf, size);
|
grub_crypto_xor (pbuf, pbuf, buf, size);
|
||||||
|
|
||||||
if (grub_disk_read (array->members[q].device,
|
if (grub_diskfilter_read_node (&array->nodes[q], sector,
|
||||||
array->members[i].start_sector + sector,
|
size >> GRUB_DISK_SECTOR_BITS, buf))
|
||||||
0, size, buf))
|
|
||||||
goto quit;
|
goto quit;
|
||||||
|
|
||||||
grub_raid_block_xor (qbuf, buf, size);
|
grub_crypto_xor (qbuf, qbuf, buf, size);
|
||||||
|
|
||||||
c = raid6_table2[bad2][bad1];
|
c = (255 - bad1 + (255 - powx_inv[(powx[bad2 - bad1 + 255] ^ 1)])) % 255;
|
||||||
grub_raid_block_mul (c, qbuf, size);
|
grub_raid_block_mulx (c, qbuf, size);
|
||||||
|
|
||||||
c = raid6_table1[raid6_table2[bad2][bad2]][c];
|
c = (bad2 + c) % 255;
|
||||||
grub_raid_block_mul (c, pbuf, size);
|
grub_raid_block_mulx (c, pbuf, size);
|
||||||
|
|
||||||
grub_raid_block_xor (pbuf, qbuf, size);
|
grub_crypto_xor (pbuf, pbuf, qbuf, size);
|
||||||
grub_memcpy (buf, pbuf, size);
|
grub_memcpy (buf, pbuf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -153,14 +153,14 @@ grub_scsi_inquiry (grub_scsi_t scsi)
|
||||||
|
|
||||||
/* Read the capacity and block size of SCSI. */
|
/* Read the capacity and block size of SCSI. */
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_scsi_read_capacity (grub_scsi_t scsi)
|
grub_scsi_read_capacity10 (grub_scsi_t scsi)
|
||||||
{
|
{
|
||||||
struct grub_scsi_read_capacity rc;
|
struct grub_scsi_read_capacity10 rc;
|
||||||
struct grub_scsi_read_capacity_data rcd;
|
struct grub_scsi_read_capacity10_data rcd;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
grub_err_t err_sense;
|
grub_err_t err_sense;
|
||||||
|
|
||||||
rc.opcode = grub_scsi_cmd_read_capacity;
|
rc.opcode = grub_scsi_cmd_read_capacity10;
|
||||||
rc.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
|
rc.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
|
||||||
rc.logical_block_addr = 0;
|
rc.logical_block_addr = 0;
|
||||||
rc.reserved1 = 0;
|
rc.reserved1 = 0;
|
||||||
|
@ -182,7 +182,42 @@ grub_scsi_read_capacity (grub_scsi_t scsi)
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
scsi->size = grub_be_to_cpu32 (rcd.size);
|
scsi->last_block = grub_be_to_cpu32 (rcd.last_block);
|
||||||
|
scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize);
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the capacity and block size of SCSI. */
|
||||||
|
static grub_err_t
|
||||||
|
grub_scsi_read_capacity16 (grub_scsi_t scsi)
|
||||||
|
{
|
||||||
|
struct grub_scsi_read_capacity16 rc;
|
||||||
|
struct grub_scsi_read_capacity16_data rcd;
|
||||||
|
grub_err_t err;
|
||||||
|
grub_err_t err_sense;
|
||||||
|
|
||||||
|
rc.opcode = grub_scsi_cmd_read_capacity16;
|
||||||
|
rc.lun = (scsi->lun << GRUB_SCSI_LUN_SHIFT) | 0x10;
|
||||||
|
rc.logical_block_addr = 0;
|
||||||
|
rc.alloc_len = grub_cpu_to_be32 (sizeof (rcd));
|
||||||
|
rc.PMI = 0;
|
||||||
|
rc.control = 0;
|
||||||
|
|
||||||
|
err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc,
|
||||||
|
sizeof (rcd), (char *) &rcd);
|
||||||
|
|
||||||
|
/* Each SCSI command should be followed by Request Sense.
|
||||||
|
If not so, many devices STALLs or definitely freezes. */
|
||||||
|
err_sense = grub_scsi_request_sense (scsi);
|
||||||
|
if (err_sense != GRUB_ERR_NONE)
|
||||||
|
grub_errno = err;
|
||||||
|
/* err_sense is ignored for now and Request Sense Data also... */
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
scsi->last_block = grub_be_to_cpu64 (rcd.last_block);
|
||||||
scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize);
|
scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize);
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
@ -253,12 +288,43 @@ grub_scsi_read12 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
/* Send a SCSI request for DISK: read SIZE sectors starting with
|
||||||
|
sector SECTOR to BUF. */
|
||||||
|
static grub_err_t
|
||||||
|
grub_scsi_read16 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
|
grub_size_t size, char *buf)
|
||||||
|
{
|
||||||
|
grub_scsi_t scsi;
|
||||||
|
struct grub_scsi_read16 rd;
|
||||||
|
grub_err_t err;
|
||||||
|
grub_err_t err_sense;
|
||||||
|
|
||||||
|
scsi = disk->data;
|
||||||
|
|
||||||
|
rd.opcode = grub_scsi_cmd_read16;
|
||||||
|
rd.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
|
||||||
|
rd.lba = grub_cpu_to_be64 (sector);
|
||||||
|
rd.size = grub_cpu_to_be32 (size);
|
||||||
|
rd.reserved = 0;
|
||||||
|
rd.control = 0;
|
||||||
|
|
||||||
|
err = scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf);
|
||||||
|
|
||||||
|
/* Each SCSI command should be followed by Request Sense.
|
||||||
|
If not so, many devices STALLs or definitely freezes. */
|
||||||
|
err_sense = grub_scsi_request_sense (scsi);
|
||||||
|
if (err_sense != GRUB_ERR_NONE)
|
||||||
|
grub_errno = err;
|
||||||
|
/* err_sense is ignored for now and Request Sense Data also... */
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
|
/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
|
||||||
sectors starting with SECTOR. */
|
sectors starting with SECTOR. */
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector,
|
grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
grub_size_t size, char *buf)
|
grub_size_t size, const char *buf)
|
||||||
{
|
{
|
||||||
grub_scsi_t scsi;
|
grub_scsi_t scsi;
|
||||||
struct grub_scsi_write10 wr;
|
struct grub_scsi_write10 wr;
|
||||||
|
@ -287,6 +353,8 @@ grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
|
/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
|
||||||
sectors starting with SECTOR. */
|
sectors starting with SECTOR. */
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -320,6 +388,39 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
|
||||||
|
sectors starting with SECTOR. */
|
||||||
|
static grub_err_t
|
||||||
|
grub_scsi_write16 (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
|
grub_size_t size, const char *buf)
|
||||||
|
{
|
||||||
|
grub_scsi_t scsi;
|
||||||
|
struct grub_scsi_write16 wr;
|
||||||
|
grub_err_t err;
|
||||||
|
grub_err_t err_sense;
|
||||||
|
|
||||||
|
scsi = disk->data;
|
||||||
|
|
||||||
|
wr.opcode = grub_scsi_cmd_write16;
|
||||||
|
wr.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT;
|
||||||
|
wr.lba = grub_cpu_to_be64 (sector);
|
||||||
|
wr.size = grub_cpu_to_be32 (size);
|
||||||
|
wr.reserved = 0;
|
||||||
|
wr.control = 0;
|
||||||
|
|
||||||
|
err = scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf);
|
||||||
|
|
||||||
|
/* Each SCSI command should be followed by Request Sense.
|
||||||
|
If not so, many devices STALLs or definitely freezes. */
|
||||||
|
err_sense = grub_scsi_request_sense (scsi);
|
||||||
|
if (err_sense != GRUB_ERR_NONE)
|
||||||
|
grub_errno = err;
|
||||||
|
/* err_sense is ignored for now and Request Sense Data also... */
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_scsi_iterate (int (*hook) (const char *name),
|
grub_scsi_iterate (int (*hook) (const char *name),
|
||||||
|
@ -475,15 +576,26 @@ grub_scsi_open (const char *name, grub_disk_t disk)
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
|
||||||
/* Read capacity of media */
|
/* Read capacity of media */
|
||||||
err = grub_scsi_read_capacity (scsi);
|
err = grub_scsi_read_capacity10 (scsi);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_free (scsi);
|
grub_free (scsi);
|
||||||
grub_dprintf ("scsi", "READ CAPACITY failed\n");
|
grub_dprintf ("scsi", "READ CAPACITY10 failed\n");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
disk->total_sectors = scsi->size;
|
if (scsi->last_block == 0xffffffff)
|
||||||
|
{
|
||||||
|
err = grub_scsi_read_capacity16 (scsi);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_free (scsi);
|
||||||
|
grub_dprintf ("scsi", "READ CAPACITY16 failed\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
disk->total_sectors = scsi->last_block + 1;
|
||||||
if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
|
if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize)
|
||||||
{
|
{
|
||||||
grub_free (scsi);
|
grub_free (scsi);
|
||||||
|
@ -491,11 +603,11 @@ grub_scsi_open (const char *name, grub_disk_t disk)
|
||||||
scsi->blocksize);
|
scsi->blocksize);
|
||||||
}
|
}
|
||||||
for (disk->log_sector_size = 0;
|
for (disk->log_sector_size = 0;
|
||||||
(1 << disk->log_sector_size) < scsi->blocksize;
|
(1U << disk->log_sector_size) < scsi->blocksize;
|
||||||
disk->log_sector_size++);
|
disk->log_sector_size++);
|
||||||
|
|
||||||
grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n",
|
grub_dprintf ("scsi", "last_block=%" PRIuGRUB_UINT64_T ", blocksize=%u\n",
|
||||||
scsi->size, scsi->blocksize);
|
scsi->last_block, scsi->blocksize);
|
||||||
grub_dprintf ("scsi", "Disk total sectors = %llu\n",
|
grub_dprintf ("scsi", "Disk total sectors = %llu\n",
|
||||||
(unsigned long long) disk->total_sectors);
|
(unsigned long long) disk->total_sectors);
|
||||||
|
|
||||||
|
@ -539,12 +651,18 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
switch (scsi->devtype)
|
switch (scsi->devtype)
|
||||||
{
|
{
|
||||||
case grub_scsi_devtype_direct:
|
case grub_scsi_devtype_direct:
|
||||||
|
if (sector >> 32)
|
||||||
|
err = grub_scsi_read16 (disk, sector, len, buf);
|
||||||
|
else
|
||||||
err = grub_scsi_read10 (disk, sector, len, buf);
|
err = grub_scsi_read10 (disk, sector, len, buf);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case grub_scsi_devtype_cdrom:
|
case grub_scsi_devtype_cdrom:
|
||||||
|
if (sector >> 32)
|
||||||
|
err = grub_scsi_read16 (disk, sector, len, buf);
|
||||||
|
else
|
||||||
err = grub_scsi_read12 (disk, sector, len, buf);
|
err = grub_scsi_read12 (disk, sector, len, buf);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -595,13 +713,41 @@ grub_scsi_write (grub_disk_t disk __attribute((unused)),
|
||||||
grub_size_t size __attribute((unused)),
|
grub_size_t size __attribute((unused)),
|
||||||
const char *buf __attribute((unused)))
|
const char *buf __attribute((unused)))
|
||||||
{
|
{
|
||||||
#if 0
|
grub_scsi_t scsi;
|
||||||
/* XXX: Not tested yet! */
|
|
||||||
|
|
||||||
/* XXX: This should depend on the device type? */
|
scsi = disk->data;
|
||||||
return grub_scsi_write10 (disk, sector, size, buf);
|
|
||||||
#endif
|
if (scsi->devtype == grub_scsi_devtype_cdrom)
|
||||||
return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
return grub_error (GRUB_ERR_IO, "no CD burning");
|
||||||
|
|
||||||
|
while (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:
|
||||||
|
if (sector >> 32)
|
||||||
|
err = grub_scsi_write16 (disk, sector, len, buf);
|
||||||
|
else
|
||||||
|
err = grub_scsi_write10 (disk, sector, len, buf);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size -= len;
|
||||||
|
sector += len;
|
||||||
|
buf += len << disk->log_sector_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -388,9 +388,9 @@ grub_usbms_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||||
grub_size_t size, char *buf)
|
grub_size_t size, const char *buf)
|
||||||
{
|
{
|
||||||
return grub_usbms_transfer (scsi, cmdsize, cmd, size, buf, 1);
|
return grub_usbms_transfer (scsi, cmdsize, cmd, size, (char *) buf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#define bit_LM (1 << 29)
|
#define bit_LM (1 << 29)
|
||||||
|
|
||||||
char *
|
const char *
|
||||||
grub_efiemu_get_default_core_name (void)
|
grub_efiemu_get_default_core_name (void)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,8 @@ grub_efiemu_register_configuration_table (grub_efi_guid_t guid,
|
||||||
if (! get_table && ! data)
|
if (! get_table && ! data)
|
||||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||||
"you must set at least get_table or data");
|
"you must set at least get_table or data");
|
||||||
if ((err = grub_efiemu_unregister_configuration_table (guid)))
|
err = grub_efiemu_unregister_configuration_table (guid);
|
||||||
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
tbl = (struct grub_efiemu_configuration_table *) grub_malloc (sizeof (*tbl));
|
tbl = (struct grub_efiemu_configuration_table *) grub_malloc (sizeof (*tbl));
|
||||||
|
@ -226,7 +227,7 @@ grub_efiemu_autocore (void)
|
||||||
{
|
{
|
||||||
const char *prefix;
|
const char *prefix;
|
||||||
char *filename;
|
char *filename;
|
||||||
char *suffix;
|
const char *suffix;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
|
||||||
if (grub_efiemu_sizeof_uintn_t () != 0)
|
if (grub_efiemu_sizeof_uintn_t () != 0)
|
||||||
|
|
|
@ -201,10 +201,10 @@ efiemu_alloc_requests (void)
|
||||||
- (requested_memory[reqorder[i]] % GRUB_EFIEMU_PAGESIZE);
|
- (requested_memory[reqorder[i]] % GRUB_EFIEMU_PAGESIZE);
|
||||||
if (align_overhead == GRUB_EFIEMU_PAGESIZE)
|
if (align_overhead == GRUB_EFIEMU_PAGESIZE)
|
||||||
align_overhead = 0;
|
align_overhead = 0;
|
||||||
curptr = ((grub_uint8_t *)curptr) + align_overhead;
|
curptr = ((grub_uint8_t *) curptr) + align_overhead;
|
||||||
|
|
||||||
/* Add the region to memory map */
|
/* Add the region to memory map */
|
||||||
grub_efiemu_add_to_mmap (PTR_TO_UINT64 (typestart),
|
grub_efiemu_add_to_mmap ((grub_addr_t) typestart,
|
||||||
curptr - typestart, reqorder[i]);
|
curptr - typestart, reqorder[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,7 +404,8 @@ grub_efiemu_mmap_fill (void)
|
||||||
GRUB_EFI_ACPI_MEMORY_NVS);
|
GRUB_EFI_ACPI_MEMORY_NVS);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
grub_printf ("Unknown memory type %d. Assuming unusable\n", type);
|
grub_dprintf ("efiemu",
|
||||||
|
"Unknown memory type %d. Assuming unusable\n", type);
|
||||||
case GRUB_MEMORY_RESERVED:
|
case GRUB_MEMORY_RESERVED:
|
||||||
return grub_efiemu_add_to_mmap (addr, size,
|
return grub_efiemu_add_to_mmap (addr, size,
|
||||||
GRUB_EFI_UNUSABLE_MEMORY);
|
GRUB_EFI_UNUSABLE_MEMORY);
|
||||||
|
|
|
@ -97,10 +97,9 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks,
|
||||||
grub_memcpy (&(conftables[i].vendor_guid), &(cur->guid),
|
grub_memcpy (&(conftables[i].vendor_guid), &(cur->guid),
|
||||||
sizeof (cur->guid));
|
sizeof (cur->guid));
|
||||||
if (cur->get_table)
|
if (cur->get_table)
|
||||||
conftables[i].vendor_table
|
conftables[i].vendor_table = (grub_addr_t) cur->get_table (cur->data);
|
||||||
= PTR_TO_UINT64 (cur->get_table (cur->data));
|
|
||||||
else
|
else
|
||||||
conftables[i].vendor_table = PTR_TO_UINT64 (cur->data);
|
conftables[i].vendor_table = (grub_addr_t) cur->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = SUFFIX (grub_efiemu_crc) ();
|
err = SUFFIX (grub_efiemu_crc) ();
|
||||||
|
|
|
@ -21,6 +21,12 @@
|
||||||
As it emulates only runtime serviceit isn't able
|
As it emulates only runtime serviceit isn't able
|
||||||
to chainload EFI bootloader on non-EFI system (TODO) */
|
to chainload EFI bootloader on non-EFI system (TODO) */
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
#include <grub/i386/types.h>
|
||||||
|
#else
|
||||||
|
#include <grub/x86_64/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <grub/symbol.h>
|
#include <grub/symbol.h>
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/efi/api.h>
|
#include <grub/efi/api.h>
|
||||||
|
@ -369,16 +375,16 @@ grub_efi_status_t EFI_FUNC
|
||||||
switch (cur_relloc->size)
|
switch (cur_relloc->size)
|
||||||
{
|
{
|
||||||
case 8:
|
case 8:
|
||||||
*((grub_uint64_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
|
*((grub_uint64_t *) (grub_addr_t) cur_relloc->addr) += corr;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
*((grub_uint32_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
|
*((grub_uint32_t *) (grub_addr_t) cur_relloc->addr) += corr;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
*((grub_uint16_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
|
*((grub_uint16_t *) (grub_addr_t) cur_relloc->addr) += corr;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
*((grub_uint8_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
|
*((grub_uint8_t *) (grub_addr_t) cur_relloc->addr) += corr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,7 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle,
|
||||||
else
|
else
|
||||||
ptv_rels[ptv_written].plustype = 0;
|
ptv_rels[ptv_written].plustype = 0;
|
||||||
|
|
||||||
ptv_rels[ptv_written].addr = PTR_TO_UINT64 (addr);
|
ptv_rels[ptv_written].addr = (grub_addr_t) addr;
|
||||||
ptv_rels[ptv_written].size = size;
|
ptv_rels[ptv_written].size = size;
|
||||||
ptv_written++;
|
ptv_written++;
|
||||||
|
|
||||||
|
@ -179,10 +179,10 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle,
|
||||||
|
|
||||||
/* Compute the value */
|
/* Compute the value */
|
||||||
if (minus_handle)
|
if (minus_handle)
|
||||||
value -= PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (minus_handle));
|
value -= (grub_addr_t) grub_efiemu_mm_obtain_request (minus_handle);
|
||||||
|
|
||||||
if (plus_handle)
|
if (plus_handle)
|
||||||
value += PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (plus_handle));
|
value += (grub_addr_t) grub_efiemu_mm_obtain_request (plus_handle);
|
||||||
|
|
||||||
/* Write the value */
|
/* Write the value */
|
||||||
switch (size)
|
switch (size)
|
||||||
|
@ -248,16 +248,16 @@ grub_efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
|
||||||
switch (cur_relloc->size)
|
switch (cur_relloc->size)
|
||||||
{
|
{
|
||||||
case 8:
|
case 8:
|
||||||
*((grub_uint64_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
|
*((grub_uint64_t *) (grub_addr_t) cur_relloc->addr) += corr;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
*((grub_uint32_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
|
*((grub_uint32_t *) (grub_addr_t) cur_relloc->addr) += corr;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
*((grub_uint16_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
|
*((grub_uint16_t *) (grub_addr_t) cur_relloc->addr) += corr;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
*((grub_uint8_t *) UINT_TO_PTR (cur_relloc->addr)) += corr;
|
*((grub_uint8_t *) (grub_addr_t) cur_relloc->addr) += corr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,8 +250,7 @@ open_section (grub_file_t file, struct font_file_section *section)
|
||||||
}
|
}
|
||||||
else if (retval < 0)
|
else if (retval < 0)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_FONT,
|
/* Read error. */
|
||||||
"font format error: can't read section name");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,8 +264,7 @@ open_section (grub_file_t file, struct font_file_section *section)
|
||||||
}
|
}
|
||||||
else if (retval < 0)
|
else if (retval < 0)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_FONT,
|
/* Read error. */
|
||||||
"font format error: can't read section length");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,7 +606,7 @@ grub_font_load (const char *filename)
|
||||||
|
|
||||||
if (!font->name)
|
if (!font->name)
|
||||||
{
|
{
|
||||||
grub_printf ("Note: Font has no name.\n");
|
grub_dprintf ("font", "Font has no name.\n");
|
||||||
font->name = grub_strdup ("Unknown");
|
font->name = grub_strdup ("Unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ lsfonts_command (grub_command_t cmd __attribute__ ((unused)),
|
||||||
{
|
{
|
||||||
struct grub_font_node *node;
|
struct grub_font_node *node;
|
||||||
|
|
||||||
grub_printf ("Loaded fonts:\n");
|
grub_puts_ (N_("Loaded fonts:"));
|
||||||
for (node = grub_font_list; node; node = node->next)
|
for (node = grub_font_list; node; node = node->next)
|
||||||
{
|
{
|
||||||
grub_font_t font = node->value;
|
grub_font_t font = node->value;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <grub/dl.h>
|
#include <grub/dl.h>
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/fshelp.h>
|
#include <grub/fshelp.h>
|
||||||
|
#include <grub/charset.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
|
@ -85,19 +86,19 @@ struct grub_affs_file
|
||||||
#define GRUB_AFFS_BLOCKPTR_OFFSET 24
|
#define GRUB_AFFS_BLOCKPTR_OFFSET 24
|
||||||
#define GRUB_AFFS_SYMLINK_OFFSET 24
|
#define GRUB_AFFS_SYMLINK_OFFSET 24
|
||||||
|
|
||||||
#define GRUB_AFFS_SYMLINK_SIZE(blocksize) ((blocksize) - 225)
|
#define GRUB_AFFS_FILETYPE_REG 0xfffffffd
|
||||||
|
#define GRUB_AFFS_FILETYPE_DIR 2
|
||||||
#define GRUB_AFFS_FILETYPE_DIR -3
|
|
||||||
#define GRUB_AFFS_FILETYPE_REG 2
|
|
||||||
#define GRUB_AFFS_FILETYPE_SYMLINK 3
|
#define GRUB_AFFS_FILETYPE_SYMLINK 3
|
||||||
|
|
||||||
|
|
||||||
struct grub_fshelp_node
|
struct grub_fshelp_node
|
||||||
{
|
{
|
||||||
struct grub_affs_data *data;
|
struct grub_affs_data *data;
|
||||||
grub_disk_addr_t block;
|
grub_uint32_t block;
|
||||||
struct grub_fshelp_node *parent;
|
struct grub_fshelp_node *parent;
|
||||||
struct grub_affs_file di;
|
struct grub_affs_file di;
|
||||||
|
grub_uint32_t *block_cache;
|
||||||
|
grub_uint32_t last_block_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Information about a "mounted" affs filesystem. */
|
/* Information about a "mounted" affs filesystem. */
|
||||||
|
@ -120,32 +121,46 @@ static grub_dl_t my_mod;
|
||||||
static grub_disk_addr_t
|
static grub_disk_addr_t
|
||||||
grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
{
|
{
|
||||||
int links;
|
grub_uint32_t target, curblock;
|
||||||
grub_uint32_t pos;
|
grub_uint32_t pos;
|
||||||
int block = node->block;
|
|
||||||
struct grub_affs_file file;
|
struct grub_affs_file file;
|
||||||
struct grub_affs_data *data = node->data;
|
struct grub_affs_data *data = node->data;
|
||||||
grub_uint64_t mod;
|
grub_uint64_t mod;
|
||||||
|
|
||||||
|
if (!node->block_cache)
|
||||||
|
{
|
||||||
|
node->block_cache = grub_malloc ((((grub_be_to_cpu32 (node->di.size)
|
||||||
|
+ 511) >> 9) / data->htsize + 1)
|
||||||
|
* sizeof (node->block_cache[0]));
|
||||||
|
if (!node->block_cache)
|
||||||
|
return -1;
|
||||||
|
node->last_block_cache = 0;
|
||||||
|
node->block_cache[0] = node->block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Files are at most 2G on AFFS, so no need for 64-bit division. */
|
||||||
|
target = (grub_uint32_t) fileblock / data->htsize;
|
||||||
|
mod = (grub_uint32_t) fileblock % data->htsize;
|
||||||
/* Find the block that points to the fileblock we are looking up by
|
/* Find the block that points to the fileblock we are looking up by
|
||||||
following the chain until the right table is reached. */
|
following the chain until the right table is reached. */
|
||||||
for (links = grub_divmod64 (fileblock, data->htsize, &mod); links; links--)
|
for (curblock = node->last_block_cache + 1; curblock <= target; curblock++)
|
||||||
{
|
{
|
||||||
grub_disk_read (data->disk, block + data->blocksize - 1,
|
grub_disk_read (data->disk,
|
||||||
|
node->block_cache[curblock - 1] + data->blocksize - 1,
|
||||||
data->blocksize * (GRUB_DISK_SECTOR_SIZE
|
data->blocksize * (GRUB_DISK_SECTOR_SIZE
|
||||||
- GRUB_AFFS_FILE_LOCATION),
|
- GRUB_AFFS_FILE_LOCATION),
|
||||||
sizeof (file), &file);
|
sizeof (file), &file);
|
||||||
if (grub_errno)
|
if (grub_errno)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
block = grub_be_to_cpu32 (file.extension);
|
node->block_cache[curblock] = grub_be_to_cpu32 (file.extension);
|
||||||
|
node->last_block_cache = curblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Translate the fileblock to the block within the right table. */
|
/* Translate the fileblock to the block within the right table. */
|
||||||
fileblock = mod;
|
grub_disk_read (data->disk, node->block_cache[target],
|
||||||
grub_disk_read (data->disk, block,
|
|
||||||
GRUB_AFFS_BLOCKPTR_OFFSET
|
GRUB_AFFS_BLOCKPTR_OFFSET
|
||||||
+ (data->htsize - fileblock - 1) * sizeof (pos),
|
+ (data->htsize - mod - 1) * sizeof (pos),
|
||||||
sizeof (pos), &pos);
|
sizeof (pos), &pos);
|
||||||
if (grub_errno)
|
if (grub_errno)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -153,21 +168,6 @@ grub_affs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
||||||
return grub_be_to_cpu32 (pos);
|
return grub_be_to_cpu32 (pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Read LEN bytes from the file described by DATA starting with byte
|
|
||||||
POS. Return the amount of read bytes in READ. */
|
|
||||||
static grub_ssize_t
|
|
||||||
grub_affs_read_file (grub_fshelp_node_t node,
|
|
||||||
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
|
|
||||||
unsigned offset, unsigned length),
|
|
||||||
int pos, grub_size_t len, char *buf)
|
|
||||||
{
|
|
||||||
return grub_fshelp_read_file (node->data->disk, node, read_hook,
|
|
||||||
pos, len, buf, grub_affs_read_block,
|
|
||||||
grub_be_to_cpu32 (node->di.size), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct grub_affs_data *
|
static struct grub_affs_data *
|
||||||
grub_affs_mount (grub_disk_t disk)
|
grub_affs_mount (grub_disk_t disk)
|
||||||
{
|
{
|
||||||
|
@ -178,7 +178,7 @@ grub_affs_mount (grub_disk_t disk)
|
||||||
int checksum = 0;
|
int checksum = 0;
|
||||||
int blocksize = 0;
|
int blocksize = 0;
|
||||||
|
|
||||||
data = grub_malloc (sizeof (struct grub_affs_data));
|
data = grub_zalloc (sizeof (struct grub_affs_data));
|
||||||
if (!data)
|
if (!data)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -202,12 +202,6 @@ grub_affs_mount (grub_disk_t disk)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the bootblock. */
|
|
||||||
grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock),
|
|
||||||
&data->bblock);
|
|
||||||
if (grub_errno)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* No sane person uses more than 8KB for a block. At least I hope
|
/* No sane person uses more than 8KB for a block. At least I hope
|
||||||
for that person because in that case this won't work. */
|
for that person because in that case this won't work. */
|
||||||
rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE * 16);
|
rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE * 16);
|
||||||
|
@ -270,18 +264,21 @@ grub_affs_read_symlink (grub_fshelp_node_t node)
|
||||||
{
|
{
|
||||||
struct grub_affs_data *data = node->data;
|
struct grub_affs_data *data = node->data;
|
||||||
char *symlink;
|
char *symlink;
|
||||||
|
const grub_size_t symlink_size = (data->blocksize * GRUB_DISK_SECTOR_SIZE
|
||||||
|
- 225);
|
||||||
|
|
||||||
symlink = grub_malloc (GRUB_AFFS_SYMLINK_SIZE (data->blocksize));
|
symlink = grub_malloc (symlink_size + 1);
|
||||||
if (!symlink)
|
if (!symlink)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
grub_disk_read (data->disk, node->block, GRUB_AFFS_SYMLINK_OFFSET,
|
grub_disk_read (data->disk, node->block, GRUB_AFFS_SYMLINK_OFFSET,
|
||||||
GRUB_AFFS_SYMLINK_SIZE (data->blocksize), symlink);
|
symlink_size, symlink);
|
||||||
if (grub_errno)
|
if (grub_errno)
|
||||||
{
|
{
|
||||||
grub_free (symlink);
|
grub_free (symlink);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
symlink[symlink_size] = 1;
|
||||||
grub_dprintf ("affs", "Symlink: `%s'\n", symlink);
|
grub_dprintf ("affs", "Symlink: `%s'\n", symlink);
|
||||||
return symlink;
|
return symlink;
|
||||||
}
|
}
|
||||||
|
@ -300,25 +297,26 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
struct grub_affs_data *data = dir->data;
|
struct grub_affs_data *data = dir->data;
|
||||||
grub_uint32_t *hashtable;
|
grub_uint32_t *hashtable;
|
||||||
|
|
||||||
auto int NESTED_FUNC_ATTR grub_affs_create_node (const char *name,
|
auto int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block,
|
||||||
grub_disk_addr_t block,
|
|
||||||
const struct grub_affs_file *fil);
|
const struct grub_affs_file *fil);
|
||||||
|
|
||||||
int NESTED_FUNC_ATTR grub_affs_create_node (const char *name,
|
int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block,
|
||||||
grub_disk_addr_t block,
|
|
||||||
const struct grub_affs_file *fil)
|
const struct grub_affs_file *fil)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
node = grub_malloc (sizeof (*node));
|
grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1];
|
||||||
|
grub_size_t len;
|
||||||
|
|
||||||
|
node = grub_zalloc (sizeof (*node));
|
||||||
if (!node)
|
if (!node)
|
||||||
{
|
{
|
||||||
grub_free (hashtable);
|
grub_free (hashtable);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((int) grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR)
|
if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG)
|
||||||
type = GRUB_FSHELP_REG;
|
type = GRUB_FSHELP_REG;
|
||||||
else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_REG)
|
else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_DIR)
|
||||||
type = GRUB_FSHELP_DIR;
|
type = GRUB_FSHELP_DIR;
|
||||||
else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_SYMLINK)
|
else if (grub_be_to_cpu32 (fil->type) == GRUB_AFFS_FILETYPE_SYMLINK)
|
||||||
type = GRUB_FSHELP_SYMLINK;
|
type = GRUB_FSHELP_SYMLINK;
|
||||||
|
@ -330,7 +328,12 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
node->di = *fil;
|
node->di = *fil;
|
||||||
node->parent = dir;
|
node->parent = dir;
|
||||||
|
|
||||||
if (hook (name, type, node))
|
len = fil->namelen;
|
||||||
|
if (len > sizeof (fil->name))
|
||||||
|
len = sizeof (fil->name);
|
||||||
|
*grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0';
|
||||||
|
|
||||||
|
if (hook ((char *) name_u8, type, node))
|
||||||
{
|
{
|
||||||
grub_free (hashtable);
|
grub_free (hashtable);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -339,7 +342,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create the directory entries for `.' and `..'. */
|
/* Create the directory entries for `.' and `..'. */
|
||||||
node = grub_malloc (sizeof (*node));
|
node = grub_zalloc (sizeof (*node));
|
||||||
if (!node)
|
if (!node)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -348,7 +351,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
return 1;
|
return 1;
|
||||||
if (dir->parent)
|
if (dir->parent)
|
||||||
{
|
{
|
||||||
node = grub_malloc (sizeof (*node));
|
node = grub_zalloc (sizeof (*node));
|
||||||
if (!node)
|
if (!node)
|
||||||
return 1;
|
return 1;
|
||||||
*node = *dir->parent;
|
*node = *dir->parent;
|
||||||
|
@ -356,7 +359,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
hashtable = grub_malloc (data->htsize * sizeof (*hashtable));
|
hashtable = grub_zalloc (data->htsize * sizeof (*hashtable));
|
||||||
if (!hashtable)
|
if (!hashtable)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -367,7 +370,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
|
|
||||||
for (i = 0; i < data->htsize; i++)
|
for (i = 0; i < data->htsize; i++)
|
||||||
{
|
{
|
||||||
grub_uint64_t next;
|
grub_uint32_t next;
|
||||||
|
|
||||||
if (!hashtable[i])
|
if (!hashtable[i])
|
||||||
continue;
|
continue;
|
||||||
|
@ -385,9 +388,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir,
|
||||||
if (grub_errno)
|
if (grub_errno)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
file.name[file.namelen] = '\0';
|
if (grub_affs_create_node (next, &file))
|
||||||
|
|
||||||
if (grub_affs_create_node ((char *) (file.name), next, &file))
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
next = grub_be_to_cpu32 (file.next);
|
next = grub_be_to_cpu32 (file.next);
|
||||||
|
@ -441,10 +442,13 @@ grub_affs_open (struct grub_file *file, const char *name)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_affs_close (grub_file_t file)
|
grub_affs_close (grub_file_t file)
|
||||||
{
|
{
|
||||||
|
struct grub_affs_data *data =
|
||||||
|
(struct grub_affs_data *) file->data;
|
||||||
|
|
||||||
|
grub_free (data->diropen.block_cache);
|
||||||
grub_free (file->data);
|
grub_free (file->data);
|
||||||
|
|
||||||
grub_dl_unref (my_mod);
|
grub_dl_unref (my_mod);
|
||||||
|
@ -452,7 +456,6 @@ grub_affs_close (grub_file_t file)
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Read LEN bytes data from FILE into BUF. */
|
/* Read LEN bytes data from FILE into BUF. */
|
||||||
static grub_ssize_t
|
static grub_ssize_t
|
||||||
grub_affs_read (grub_file_t file, char *buf, grub_size_t len)
|
grub_affs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
|
@ -460,13 +463,12 @@ grub_affs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
struct grub_affs_data *data =
|
struct grub_affs_data *data =
|
||||||
(struct grub_affs_data *) file->data;
|
(struct grub_affs_data *) file->data;
|
||||||
|
|
||||||
int size = grub_affs_read_file (&data->diropen, file->read_hook,
|
return grub_fshelp_read_file (data->diropen.data->disk, &data->diropen,
|
||||||
file->offset, len, buf);
|
file->read_hook,
|
||||||
|
file->offset, len, buf, grub_affs_read_block,
|
||||||
return size;
|
grub_be_to_cpu32 (data->diropen.di.size), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_affs_dir (grub_device_t device, const char *path,
|
grub_affs_dir (grub_device_t device, const char *path,
|
||||||
int (*hook) (const char *filename,
|
int (*hook) (const char *filename,
|
||||||
|
@ -531,6 +533,7 @@ grub_affs_label (grub_device_t device, char **label)
|
||||||
data = grub_affs_mount (disk);
|
data = grub_affs_mount (disk);
|
||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
|
grub_size_t len;
|
||||||
/* The rootblock maps quite well on a file header block, it's
|
/* The rootblock maps quite well on a file header block, it's
|
||||||
something we can use here. */
|
something we can use here. */
|
||||||
grub_disk_read (data->disk, grub_be_to_cpu32 (data->bblock.rootblock),
|
grub_disk_read (data->disk, grub_be_to_cpu32 (data->bblock.rootblock),
|
||||||
|
@ -540,7 +543,12 @@ grub_affs_label (grub_device_t device, char **label)
|
||||||
if (grub_errno)
|
if (grub_errno)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
*label = grub_strndup ((char *) (file.name), file.namelen);
|
len = file.namelen;
|
||||||
|
if (len > sizeof (file.name))
|
||||||
|
len = sizeof (file.name);
|
||||||
|
*label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1);
|
||||||
|
if (*label)
|
||||||
|
*grub_latin1_to_utf8 ((grub_uint8_t *) *label, file.name, len) = '\0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*label = 0;
|
*label = 0;
|
||||||
|
|
|
@ -1,720 +1,3 @@
|
||||||
/* afs.c - The native AtheOS file-system. */
|
#define MODE_AFS 1
|
||||||
/*
|
#include "bfs.c"
|
||||||
* GRUB -- GRand Unified Bootloader
|
|
||||||
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
|
|
||||||
*
|
|
||||||
* GRUB is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* GRUB is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <grub/err.h>
|
|
||||||
#include <grub/file.h>
|
|
||||||
#include <grub/mm.h>
|
|
||||||
#include <grub/misc.h>
|
|
||||||
#include <grub/disk.h>
|
|
||||||
#include <grub/dl.h>
|
|
||||||
#include <grub/types.h>
|
|
||||||
#include <grub/fshelp.h>
|
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
|
||||||
|
|
||||||
#ifdef MODE_BIGENDIAN
|
|
||||||
#define GRUB_AFS_FSNAME_SUFFIX "_be"
|
|
||||||
#else
|
|
||||||
#define GRUB_AFS_FSNAME_SUFFIX ""
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MODE_BFS
|
|
||||||
#define GRUB_AFS_FSNAME "befs" GRUB_AFS_FSNAME_SUFFIX
|
|
||||||
#else
|
|
||||||
#define GRUB_AFS_FSNAME "afs" GRUB_AFS_FSNAME_SUFFIX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GRUB_AFS_DIRECT_BLOCK_COUNT 12
|
|
||||||
#define GRUB_AFS_BLOCKS_PER_DI_RUN 4
|
|
||||||
|
|
||||||
#ifdef MODE_BFS
|
|
||||||
#define GRUB_AFS_SBLOCK_SECTOR 1
|
|
||||||
#define GRUB_AFS_SBLOCK_MAGIC1 0x42465331 /* BFS1. */
|
|
||||||
#else
|
|
||||||
#define GRUB_AFS_SBLOCK_SECTOR 2
|
|
||||||
#define GRUB_AFS_SBLOCK_MAGIC1 0x41465331 /* AFS1. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GRUB_AFS_SBLOCK_MAGIC2 0xdd121031
|
|
||||||
#define GRUB_AFS_SBLOCK_MAGIC3 0x15b6830e
|
|
||||||
|
|
||||||
#define GRUB_AFS_INODE_MAGIC 0x64358428
|
|
||||||
|
|
||||||
#ifdef MODE_BFS
|
|
||||||
#define GRUB_AFS_BTREE_MAGIC 0x69f6c2e8
|
|
||||||
#else
|
|
||||||
#define GRUB_AFS_BTREE_MAGIC 0x65768995
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define GRUB_AFS_BNODE_SIZE 1024
|
|
||||||
|
|
||||||
#define GRUB_AFS_S_IFMT 00170000
|
|
||||||
#define GRUB_AFS_S_IFLNK 0120000
|
|
||||||
|
|
||||||
#define GRUB_AFS_S_IFREG 0100000
|
|
||||||
#define GRUB_AFS_S_IFDIR 0040000
|
|
||||||
#define GRUB_AFS_S_IFIFO 0010000
|
|
||||||
|
|
||||||
#define GRUB_AFS_NULL_VAL ((grub_afs_bvalue_t)-1)
|
|
||||||
|
|
||||||
#ifdef MODE_BIGENDIAN
|
|
||||||
#define grub_afs_to_cpu16(x) grub_be_to_cpu16 (x)
|
|
||||||
#define grub_afs_to_cpu32(x) grub_be_to_cpu32 (x)
|
|
||||||
#define grub_afs_to_cpu64(x) grub_be_to_cpu64 (x)
|
|
||||||
#else
|
|
||||||
#define grub_afs_to_cpu16(x) grub_le_to_cpu16 (x)
|
|
||||||
#define grub_afs_to_cpu32(x) grub_le_to_cpu32 (x)
|
|
||||||
#define grub_afs_to_cpu64(x) grub_le_to_cpu64 (x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MODE_BFS
|
|
||||||
#define B_KEY_INDEX_ALIGN 8
|
|
||||||
#else
|
|
||||||
#define B_KEY_INDEX_ALIGN 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define B_KEY_INDEX_OFFSET(node) ((grub_uint16_t *) \
|
|
||||||
((char *) (node) \
|
|
||||||
+ ALIGN_UP (sizeof (struct grub_afs_bnode) \
|
|
||||||
+ node->key_size, \
|
|
||||||
B_KEY_INDEX_ALIGN)))
|
|
||||||
|
|
||||||
#define B_KEY_VALUE_OFFSET(node) ((grub_afs_bvalue_t *) \
|
|
||||||
((char *) B_KEY_INDEX_OFFSET (node) + \
|
|
||||||
node->key_count * 2))
|
|
||||||
|
|
||||||
typedef grub_uint64_t grub_afs_off_t;
|
|
||||||
typedef grub_uint64_t grub_afs_bigtime;
|
|
||||||
typedef grub_uint64_t grub_afs_bvalue_t;
|
|
||||||
|
|
||||||
struct grub_afs_blockrun
|
|
||||||
{
|
|
||||||
grub_uint32_t group;
|
|
||||||
grub_uint16_t start;
|
|
||||||
grub_uint16_t len;
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
|
|
||||||
struct grub_afs_datastream
|
|
||||||
{
|
|
||||||
struct grub_afs_blockrun direct[GRUB_AFS_DIRECT_BLOCK_COUNT];
|
|
||||||
grub_afs_off_t max_direct_range;
|
|
||||||
struct grub_afs_blockrun indirect;
|
|
||||||
grub_afs_off_t max_indirect_range;
|
|
||||||
struct grub_afs_blockrun double_indirect;
|
|
||||||
grub_afs_off_t max_double_indirect_range;
|
|
||||||
grub_afs_off_t size;
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
|
|
||||||
struct grub_afs_bnode
|
|
||||||
{
|
|
||||||
grub_afs_bvalue_t left;
|
|
||||||
grub_afs_bvalue_t right;
|
|
||||||
grub_afs_bvalue_t overflow;
|
|
||||||
#ifdef MODE_BFS
|
|
||||||
grub_uint16_t key_count;
|
|
||||||
grub_uint16_t key_size;
|
|
||||||
#else
|
|
||||||
grub_uint32_t key_count;
|
|
||||||
grub_uint32_t key_size;
|
|
||||||
#endif
|
|
||||||
char key_data[0];
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
|
|
||||||
#ifdef MODE_BFS
|
|
||||||
struct grub_afs_btree
|
|
||||||
{
|
|
||||||
grub_uint32_t magic;
|
|
||||||
grub_uint32_t unused1;
|
|
||||||
grub_uint32_t tree_depth;
|
|
||||||
grub_uint32_t unused2;
|
|
||||||
grub_afs_bvalue_t root;
|
|
||||||
grub_uint32_t unused3[4];
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
#else
|
|
||||||
struct grub_afs_btree
|
|
||||||
{
|
|
||||||
grub_uint32_t magic;
|
|
||||||
grub_afs_bvalue_t root;
|
|
||||||
grub_uint32_t tree_depth;
|
|
||||||
grub_afs_bvalue_t last_node;
|
|
||||||
grub_afs_bvalue_t first_free;
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Beware that following structure describes AtheFS and if you write code
|
|
||||||
which uses currently unused fields check it with both AtheFS and BeFS.
|
|
||||||
*/
|
|
||||||
struct grub_afs_sblock
|
|
||||||
{
|
|
||||||
char name[32];
|
|
||||||
grub_uint32_t magic1;
|
|
||||||
grub_uint32_t byte_order;
|
|
||||||
grub_uint32_t block_size;
|
|
||||||
grub_uint32_t block_shift;
|
|
||||||
grub_afs_off_t num_blocks;
|
|
||||||
grub_afs_off_t used_blocks;
|
|
||||||
grub_uint32_t inode_size;
|
|
||||||
grub_uint32_t magic2;
|
|
||||||
grub_uint32_t block_per_group; /* Number of blocks per allocation
|
|
||||||
group. (Max 65536) */
|
|
||||||
grub_uint32_t alloc_group_shift; /* Number of bits to shift a group
|
|
||||||
number to get a byte address. */
|
|
||||||
grub_uint32_t alloc_group_count;
|
|
||||||
grub_uint32_t flags;
|
|
||||||
struct grub_afs_blockrun log_block;
|
|
||||||
grub_afs_off_t log_start;
|
|
||||||
grub_uint32_t valid_log_blocks;
|
|
||||||
grub_uint32_t log_size;
|
|
||||||
grub_uint32_t magic3;
|
|
||||||
struct grub_afs_blockrun root_dir; /* Root dir inode. */
|
|
||||||
struct grub_afs_blockrun deleted_files; /* Directory containing files
|
|
||||||
scheduled for deletion. */
|
|
||||||
struct grub_afs_blockrun index_dir; /* Directory of index files. */
|
|
||||||
grub_uint32_t boot_loader_size;
|
|
||||||
grub_uint32_t pad[7];
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
|
|
||||||
struct grub_afs_inode
|
|
||||||
{
|
|
||||||
grub_uint32_t magic1;
|
|
||||||
struct grub_afs_blockrun inode_num;
|
|
||||||
grub_uint32_t uid;
|
|
||||||
grub_uint32_t gid;
|
|
||||||
grub_uint32_t mode;
|
|
||||||
grub_uint32_t flags;
|
|
||||||
#ifndef MODE_BFS
|
|
||||||
grub_uint32_t link_count;
|
|
||||||
#endif
|
|
||||||
grub_afs_bigtime create_time;
|
|
||||||
grub_afs_bigtime modified_time;
|
|
||||||
struct grub_afs_blockrun parent;
|
|
||||||
struct grub_afs_blockrun attrib_dir;
|
|
||||||
grub_uint32_t index_type; /* Key data-key only used for index files. */
|
|
||||||
grub_uint32_t inode_size;
|
|
||||||
grub_uint32_t unused;
|
|
||||||
struct grub_afs_datastream stream;
|
|
||||||
grub_uint32_t pad[4];
|
|
||||||
grub_uint32_t small_data[1];
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
|
|
||||||
struct grub_fshelp_node
|
|
||||||
{
|
|
||||||
struct grub_afs_data *data;
|
|
||||||
struct grub_afs_inode inode;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct grub_afs_data
|
|
||||||
{
|
|
||||||
grub_disk_t disk;
|
|
||||||
struct grub_afs_sblock sblock;
|
|
||||||
struct grub_afs_inode *inode;
|
|
||||||
struct grub_fshelp_node diropen;
|
|
||||||
};
|
|
||||||
|
|
||||||
static grub_dl_t my_mod;
|
|
||||||
|
|
||||||
static grub_afs_off_t
|
|
||||||
grub_afs_run_to_num (struct grub_afs_sblock *sb,
|
|
||||||
struct grub_afs_blockrun *run)
|
|
||||||
{
|
|
||||||
return ((grub_afs_off_t) grub_afs_to_cpu32 (run->group)
|
|
||||||
* sb->block_per_group + grub_afs_to_cpu16 (run->start));
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_afs_read_inode (struct grub_afs_data *data,
|
|
||||||
grub_uint32_t ino, struct grub_afs_inode *inode)
|
|
||||||
{
|
|
||||||
return grub_disk_read (data->disk,
|
|
||||||
ino *
|
|
||||||
(data->sblock.block_size >> GRUB_DISK_SECTOR_BITS),
|
|
||||||
0, sizeof (struct grub_afs_inode),
|
|
||||||
inode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_disk_addr_t
|
|
||||||
grub_afs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
|
|
||||||
{
|
|
||||||
struct grub_afs_sblock *sb = &node->data->sblock;
|
|
||||||
struct grub_afs_datastream *ds = &node->inode.stream;
|
|
||||||
|
|
||||||
if (fileblock < grub_afs_to_cpu64 (ds->max_direct_range))
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < GRUB_AFS_DIRECT_BLOCK_COUNT; i++)
|
|
||||||
{
|
|
||||||
if (fileblock < grub_afs_to_cpu16 (ds->direct[i].len))
|
|
||||||
return grub_afs_run_to_num (sb, &ds->direct[i]) + fileblock;
|
|
||||||
fileblock -= grub_afs_to_cpu16 (ds->direct[i].len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (fileblock < grub_afs_to_cpu64 (ds->max_indirect_range))
|
|
||||||
{
|
|
||||||
int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
|
|
||||||
struct grub_afs_blockrun indir[ptrs_per_blk];
|
|
||||||
grub_afs_off_t blk = grub_afs_run_to_num (sb, &ds->indirect);
|
|
||||||
int i;
|
|
||||||
|
|
||||||
fileblock -= grub_afs_to_cpu64 (ds->max_direct_range);
|
|
||||||
for (i = 0; i < ds->indirect.len; i++, blk++)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
|
|
||||||
if (grub_disk_read (node->data->disk,
|
|
||||||
blk * (sb->block_size >> GRUB_DISK_SECTOR_BITS),
|
|
||||||
0, sizeof (indir),
|
|
||||||
indir))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (j = 0; j < ptrs_per_blk; j++)
|
|
||||||
{
|
|
||||||
if (fileblock < grub_afs_to_cpu16 (indir[j].len))
|
|
||||||
return grub_afs_run_to_num (sb, &indir[j]) + fileblock;
|
|
||||||
|
|
||||||
fileblock -= grub_afs_to_cpu16 (indir[j].len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int ptrs_per_blk = sb->block_size / sizeof (struct grub_afs_blockrun);
|
|
||||||
struct grub_afs_blockrun indir[ptrs_per_blk];
|
|
||||||
|
|
||||||
/* ([idblk][idptr]) ([dblk][dptr]) [blk] */
|
|
||||||
int cur_pos = fileblock - grub_afs_to_cpu64 (ds->max_indirect_range);
|
|
||||||
|
|
||||||
int dptr_size = GRUB_AFS_BLOCKS_PER_DI_RUN;
|
|
||||||
int dblk_size = dptr_size * ptrs_per_blk;
|
|
||||||
int idptr_size = dblk_size * GRUB_AFS_BLOCKS_PER_DI_RUN;
|
|
||||||
int idblk_size = idptr_size * ptrs_per_blk;
|
|
||||||
|
|
||||||
int off = cur_pos % GRUB_AFS_BLOCKS_PER_DI_RUN;
|
|
||||||
int dptr = (cur_pos / dptr_size) % ptrs_per_blk;
|
|
||||||
int dblk = (cur_pos / dblk_size) % GRUB_AFS_BLOCKS_PER_DI_RUN;
|
|
||||||
int idptr = (cur_pos / idptr_size) % ptrs_per_blk;
|
|
||||||
int idblk = (cur_pos / idblk_size);
|
|
||||||
|
|
||||||
if (grub_disk_read (node->data->disk,
|
|
||||||
(grub_afs_run_to_num (sb, &ds->double_indirect)
|
|
||||||
+ idblk) *
|
|
||||||
(sb->block_size >> GRUB_DISK_SECTOR_BITS),
|
|
||||||
0, sizeof (indir),
|
|
||||||
indir))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (grub_disk_read (node->data->disk,
|
|
||||||
(grub_afs_run_to_num (sb, &indir[idptr]) + dblk) *
|
|
||||||
(sb->block_size >> GRUB_DISK_SECTOR_BITS),
|
|
||||||
0, sizeof (indir),
|
|
||||||
indir))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return grub_afs_run_to_num (sb, &indir[dptr]) + off;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_ssize_t
|
|
||||||
grub_afs_read_file (grub_fshelp_node_t node,
|
|
||||||
void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
|
|
||||||
unsigned offset, unsigned length),
|
|
||||||
int pos, grub_size_t len, char *buf)
|
|
||||||
{
|
|
||||||
return grub_fshelp_read_file (node->data->disk, node, read_hook,
|
|
||||||
pos, len, buf, grub_afs_read_block,
|
|
||||||
grub_afs_to_cpu64 (node->inode.stream.size),
|
|
||||||
node->data->sblock.block_shift
|
|
||||||
- GRUB_DISK_SECTOR_BITS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
grub_afs_read_symlink (grub_fshelp_node_t node)
|
|
||||||
{
|
|
||||||
char *ret;
|
|
||||||
grub_afs_off_t size = grub_afs_to_cpu64 (node->inode.stream.size);
|
|
||||||
|
|
||||||
if (size == 0)
|
|
||||||
{
|
|
||||||
size = sizeof (node->inode.stream);
|
|
||||||
ret = grub_zalloc (size + 1);
|
|
||||||
if (! ret)
|
|
||||||
return 0;
|
|
||||||
grub_memcpy (ret, (char *) &(node->inode.stream),
|
|
||||||
sizeof (node->inode.stream));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
ret = grub_zalloc (size + 1);
|
|
||||||
if (! ret)
|
|
||||||
return 0;
|
|
||||||
grub_afs_read_file (node, 0, 0, size, ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
grub_afs_iterate_dir (grub_fshelp_node_t dir,
|
|
||||||
int NESTED_FUNC_ATTR
|
|
||||||
(*hook) (const char *filename,
|
|
||||||
enum grub_fshelp_filetype filetype,
|
|
||||||
grub_fshelp_node_t node))
|
|
||||||
{
|
|
||||||
struct grub_afs_btree head;
|
|
||||||
char node_data [GRUB_AFS_BNODE_SIZE];
|
|
||||||
struct grub_afs_bnode *node = (struct grub_afs_bnode *) node_data;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if ((dir->inode.stream.size == 0)
|
|
||||||
|| ((grub_afs_to_cpu32 (dir->inode.mode) & GRUB_AFS_S_IFMT)
|
|
||||||
!= GRUB_AFS_S_IFDIR))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
grub_afs_read_file (dir, 0, 0, sizeof (head), (char *) &head);
|
|
||||||
if (grub_errno)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
grub_afs_read_file (dir, 0, grub_afs_to_cpu64 (head.root),
|
|
||||||
GRUB_AFS_BNODE_SIZE, (char *) node);
|
|
||||||
if (grub_errno)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (i = 0; i < (int) grub_afs_to_cpu32 (head.tree_depth) - 1; i++)
|
|
||||||
{
|
|
||||||
grub_afs_bvalue_t blk;
|
|
||||||
|
|
||||||
blk = grub_afs_to_cpu64(B_KEY_VALUE_OFFSET (node) [0]);
|
|
||||||
grub_afs_read_file (dir, 0, blk, GRUB_AFS_BNODE_SIZE, (char *) node);
|
|
||||||
if (grub_errno)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node->key_count)
|
|
||||||
{
|
|
||||||
grub_uint32_t cur_key = 0;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
int key_start, key_size;
|
|
||||||
grub_uint16_t *index;
|
|
||||||
|
|
||||||
index = B_KEY_INDEX_OFFSET (node);
|
|
||||||
|
|
||||||
key_start = (cur_key > 0)
|
|
||||||
? grub_afs_to_cpu16 (index[cur_key - 1]) : 0;
|
|
||||||
key_size = grub_afs_to_cpu16 (index[cur_key]) - key_start;
|
|
||||||
if (key_size > 0)
|
|
||||||
{
|
|
||||||
char filename [key_size + 1];
|
|
||||||
struct grub_fshelp_node *fdiro;
|
|
||||||
int mode, type;
|
|
||||||
|
|
||||||
fdiro = grub_malloc (sizeof (struct grub_fshelp_node));
|
|
||||||
if (! fdiro)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fdiro->data = dir->data;
|
|
||||||
if (grub_afs_read_inode (dir->data,
|
|
||||||
grub_afs_to_cpu64
|
|
||||||
(B_KEY_VALUE_OFFSET (node) [cur_key]),
|
|
||||||
&fdiro->inode))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
grub_memcpy (filename, &node->key_data[key_start], key_size);
|
|
||||||
filename [key_size] = 0;
|
|
||||||
|
|
||||||
mode = (grub_afs_to_cpu32 (fdiro->inode.mode) & GRUB_AFS_S_IFMT);
|
|
||||||
if (mode == GRUB_AFS_S_IFDIR)
|
|
||||||
type = GRUB_FSHELP_DIR;
|
|
||||||
else if (mode == GRUB_AFS_S_IFREG)
|
|
||||||
type = GRUB_FSHELP_REG;
|
|
||||||
else if (mode == GRUB_AFS_S_IFLNK)
|
|
||||||
type = GRUB_FSHELP_SYMLINK;
|
|
||||||
else
|
|
||||||
type = GRUB_FSHELP_UNKNOWN;
|
|
||||||
|
|
||||||
if (hook (filename, type, fdiro))
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_key++;
|
|
||||||
if (cur_key >= grub_afs_to_cpu32 (node->key_count))
|
|
||||||
{
|
|
||||||
if (node->right == GRUB_AFS_NULL_VAL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
grub_afs_read_file (dir, 0, grub_afs_to_cpu64 (node->right),
|
|
||||||
GRUB_AFS_BNODE_SIZE, (char *) node);
|
|
||||||
if (grub_errno)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
cur_key = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
grub_afs_validate_sblock (struct grub_afs_sblock *sb)
|
|
||||||
{
|
|
||||||
if (grub_afs_to_cpu32 (sb->magic1) == GRUB_AFS_SBLOCK_MAGIC1)
|
|
||||||
{
|
|
||||||
sb->magic2 = grub_afs_to_cpu32 (sb->magic2);
|
|
||||||
sb->magic3 = grub_afs_to_cpu32 (sb->magic3);
|
|
||||||
sb->block_shift = grub_afs_to_cpu32 (sb->block_shift);
|
|
||||||
sb->block_size = grub_afs_to_cpu32 (sb->block_size);
|
|
||||||
sb->used_blocks = grub_afs_to_cpu64 (sb->used_blocks);
|
|
||||||
sb->num_blocks = grub_afs_to_cpu64 (sb->num_blocks);
|
|
||||||
sb->inode_size = grub_afs_to_cpu32 (sb->inode_size);
|
|
||||||
sb->alloc_group_count = grub_afs_to_cpu32 (sb->alloc_group_count);
|
|
||||||
sb->alloc_group_shift = grub_afs_to_cpu32 (sb->alloc_group_shift);
|
|
||||||
sb->block_per_group = grub_afs_to_cpu32 (sb->block_per_group);
|
|
||||||
sb->alloc_group_count = grub_afs_to_cpu32 (sb->alloc_group_count);
|
|
||||||
sb->log_size = grub_afs_to_cpu32 (sb->log_size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ((sb->magic2 != GRUB_AFS_SBLOCK_MAGIC2) ||
|
|
||||||
(sb->magic3 != GRUB_AFS_SBLOCK_MAGIC3))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#ifdef MODE_BFS
|
|
||||||
sb->block_per_group = 1 << (sb->alloc_group_shift);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (((grub_uint32_t) (1 << sb->block_shift) != sb->block_size)
|
|
||||||
|| (sb->used_blocks > sb->num_blocks )
|
|
||||||
|| (sb->inode_size != sb->block_size)
|
|
||||||
|| (0 == sb->block_size)
|
|
||||||
#ifndef MODE_BFS
|
|
||||||
|| ((grub_uint32_t) (1 << sb->alloc_group_shift) !=
|
|
||||||
sb->block_per_group * sb->block_size)
|
|
||||||
|| (sb->alloc_group_count * sb->block_per_group < sb->num_blocks)
|
|
||||||
|| (grub_afs_to_cpu16 (sb->log_block.len) != sb->log_size)
|
|
||||||
|| (grub_afs_to_cpu32 (sb->valid_log_blocks) > sb->log_size)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct grub_afs_data *
|
|
||||||
grub_afs_mount (grub_disk_t disk)
|
|
||||||
{
|
|
||||||
struct grub_afs_data *data = 0;
|
|
||||||
|
|
||||||
data = grub_malloc (sizeof (struct grub_afs_data));
|
|
||||||
if (!data)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Read the superblock. */
|
|
||||||
if (grub_disk_read (disk, GRUB_AFS_SBLOCK_SECTOR, 0,
|
|
||||||
sizeof (struct grub_afs_sblock), &data->sblock))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (! grub_afs_validate_sblock (&data->sblock))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
data->diropen.data = data;
|
|
||||||
data->inode = &data->diropen.inode;
|
|
||||||
data->disk = disk;
|
|
||||||
|
|
||||||
if (grub_afs_read_inode (data,
|
|
||||||
grub_afs_run_to_num (&data->sblock,
|
|
||||||
&data->sblock.root_dir),
|
|
||||||
data->inode))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
return data;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
grub_error (GRUB_ERR_BAD_FS, "not an " GRUB_AFS_FSNAME " filesystem");
|
|
||||||
|
|
||||||
grub_free (data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_afs_open (struct grub_file *file, const char *name)
|
|
||||||
{
|
|
||||||
struct grub_afs_data *data;
|
|
||||||
struct grub_fshelp_node *fdiro = 0;
|
|
||||||
|
|
||||||
grub_dl_ref (my_mod);
|
|
||||||
|
|
||||||
data = grub_afs_mount (file->device->disk);
|
|
||||||
if (! data)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_afs_iterate_dir,
|
|
||||||
grub_afs_read_symlink, GRUB_FSHELP_REG);
|
|
||||||
if (grub_errno)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_afs_inode));
|
|
||||||
grub_free (fdiro);
|
|
||||||
|
|
||||||
file->size = grub_afs_to_cpu64 (data->inode->stream.size);
|
|
||||||
file->data = data;
|
|
||||||
file->offset = 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
grub_free (data);
|
|
||||||
|
|
||||||
grub_dl_unref (my_mod);
|
|
||||||
|
|
||||||
return grub_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_ssize_t
|
|
||||||
grub_afs_read (grub_file_t file, char *buf, grub_size_t len)
|
|
||||||
{
|
|
||||||
struct grub_afs_data *data = (struct grub_afs_data *) file->data;
|
|
||||||
|
|
||||||
return grub_afs_read_file (&data->diropen, file->read_hook,
|
|
||||||
file->offset, len, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_afs_close (grub_file_t file)
|
|
||||||
{
|
|
||||||
grub_free (file->data);
|
|
||||||
|
|
||||||
grub_dl_unref (my_mod);
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_afs_dir (grub_device_t device, const char *path,
|
|
||||||
int (*hook) (const char *filename,
|
|
||||||
const struct grub_dirhook_info *info))
|
|
||||||
{
|
|
||||||
struct grub_afs_data *data = 0;
|
|
||||||
struct grub_fshelp_node *fdiro = 0;
|
|
||||||
|
|
||||||
auto int NESTED_FUNC_ATTR iterate (const char *filename,
|
|
||||||
enum grub_fshelp_filetype filetype,
|
|
||||||
grub_fshelp_node_t node);
|
|
||||||
|
|
||||||
int NESTED_FUNC_ATTR iterate (const char *filename,
|
|
||||||
enum grub_fshelp_filetype filetype,
|
|
||||||
grub_fshelp_node_t node)
|
|
||||||
{
|
|
||||||
struct grub_dirhook_info info;
|
|
||||||
grub_memset (&info, 0, sizeof (info));
|
|
||||||
info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
|
|
||||||
info.mtimeset = 1;
|
|
||||||
#ifdef MODE_BFS
|
|
||||||
info.mtime = grub_afs_to_cpu64 (node->inode.modified_time) >> 16;
|
|
||||||
#else
|
|
||||||
info.mtime = grub_divmod64 (grub_afs_to_cpu64 (node->inode.modified_time),
|
|
||||||
1000000, 0);
|
|
||||||
#endif
|
|
||||||
grub_free (node);
|
|
||||||
return hook (filename, &info);
|
|
||||||
}
|
|
||||||
|
|
||||||
grub_dl_ref (my_mod);
|
|
||||||
|
|
||||||
data = grub_afs_mount (device->disk);
|
|
||||||
if (! data)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_afs_iterate_dir,
|
|
||||||
grub_afs_read_symlink, GRUB_FSHELP_DIR);
|
|
||||||
if (grub_errno)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
grub_afs_iterate_dir (fdiro, iterate);
|
|
||||||
|
|
||||||
if (fdiro != &data->diropen)
|
|
||||||
grub_free (fdiro);
|
|
||||||
|
|
||||||
fail:
|
|
||||||
grub_free (data);
|
|
||||||
|
|
||||||
grub_dl_unref (my_mod);
|
|
||||||
|
|
||||||
return grub_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
static grub_err_t
|
|
||||||
grub_afs_label (grub_device_t device, char **label)
|
|
||||||
{
|
|
||||||
struct grub_afs_data *data;
|
|
||||||
grub_disk_t disk = device->disk;
|
|
||||||
|
|
||||||
grub_dl_ref (my_mod);
|
|
||||||
|
|
||||||
data = grub_afs_mount (disk);
|
|
||||||
if (data)
|
|
||||||
*label = grub_strndup (data->sblock.name, sizeof (data->sblock.name));
|
|
||||||
else
|
|
||||||
*label = NULL;
|
|
||||||
|
|
||||||
grub_dl_unref (my_mod);
|
|
||||||
|
|
||||||
grub_free (data);
|
|
||||||
|
|
||||||
return grub_errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static struct grub_fs grub_afs_fs = {
|
|
||||||
.name = GRUB_AFS_FSNAME,
|
|
||||||
.dir = grub_afs_dir,
|
|
||||||
.open = grub_afs_open,
|
|
||||||
.read = grub_afs_read,
|
|
||||||
.close = grub_afs_close,
|
|
||||||
.label = grub_afs_label,
|
|
||||||
.next = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined (MODE_BIGENDIAN) && defined (MODE_BFS)
|
|
||||||
GRUB_MOD_INIT (befs_be)
|
|
||||||
#elif defined (MODE_BFS)
|
|
||||||
GRUB_MOD_INIT (befs)
|
|
||||||
#elif defined (MODE_BIGENDIAN)
|
|
||||||
GRUB_MOD_INIT (afs_be)
|
|
||||||
#else
|
|
||||||
GRUB_MOD_INIT (afs)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
grub_fs_register (&grub_afs_fs);
|
|
||||||
my_mod = mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined (MODE_BIGENDIAN) && defined (MODE_BFS)
|
|
||||||
GRUB_MOD_FINI (befs_be)
|
|
||||||
#elif defined (MODE_BFS)
|
|
||||||
GRUB_MOD_FINI (befs)
|
|
||||||
#elif defined (MODE_BIGENDIAN)
|
|
||||||
GRUB_MOD_FINI (afs_be)
|
|
||||||
#else
|
|
||||||
GRUB_MOD_FINI (afs)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
grub_fs_unregister (&grub_afs_fs);
|
|
||||||
}
|
|
||||||
|
|
|
@ -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
|
@ -26,18 +26,31 @@
|
||||||
#include <grub/types.h>
|
#include <grub/types.h>
|
||||||
#include <grub/lib/crc.h>
|
#include <grub/lib/crc.h>
|
||||||
#include <grub/deflate.h>
|
#include <grub/deflate.h>
|
||||||
|
#include <minilzo.h>
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
#define GRUB_BTRFS_SIGNATURE "_BHRfS_M"
|
#define GRUB_BTRFS_SIGNATURE "_BHRfS_M"
|
||||||
|
|
||||||
|
/* From http://www.oberhumer.com/opensource/lzo/lzofaq.php
|
||||||
|
* LZO will expand incompressible data by a little amount. I still haven't
|
||||||
|
* computed the exact values, but I suggest using these formulas for
|
||||||
|
* a worst-case expansion calculation:
|
||||||
|
*
|
||||||
|
* output_block_size = input_block_size + (input_block_size / 16) + 64 + 3
|
||||||
|
* */
|
||||||
|
#define GRUB_BTRFS_LZO_BLOCK_SIZE 4096
|
||||||
|
#define GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE (GRUB_BTRFS_LZO_BLOCK_SIZE + \
|
||||||
|
(GRUB_BTRFS_LZO_BLOCK_SIZE / 16) + 64 + 3)
|
||||||
|
|
||||||
typedef grub_uint8_t grub_btrfs_checksum_t[0x20];
|
typedef grub_uint8_t grub_btrfs_checksum_t[0x20];
|
||||||
typedef grub_uint16_t grub_btrfs_uuid_t[8];
|
typedef grub_uint16_t grub_btrfs_uuid_t[8];
|
||||||
|
|
||||||
struct grub_btrfs_device
|
struct grub_btrfs_device
|
||||||
{
|
{
|
||||||
grub_uint64_t device_id;
|
grub_uint64_t device_id;
|
||||||
grub_uint8_t dummy[0x62 - 8];
|
grub_uint64_t size;
|
||||||
|
grub_uint8_t dummy[0x62 - 0x10];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct grub_btrfs_superblock
|
struct grub_btrfs_superblock
|
||||||
|
@ -160,7 +173,8 @@ struct grub_btrfs_leaf_descriptor
|
||||||
{
|
{
|
||||||
unsigned depth;
|
unsigned depth;
|
||||||
unsigned allocated;
|
unsigned allocated;
|
||||||
struct {
|
struct
|
||||||
|
{
|
||||||
grub_disk_addr_t addr;
|
grub_disk_addr_t addr;
|
||||||
unsigned iter;
|
unsigned iter;
|
||||||
unsigned maxiter;
|
unsigned maxiter;
|
||||||
|
@ -179,7 +193,7 @@ struct grub_btrfs_time
|
||||||
{
|
{
|
||||||
grub_int64_t sec;
|
grub_int64_t sec;
|
||||||
grub_uint32_t nanosec;
|
grub_uint32_t nanosec;
|
||||||
} __attribute__ ((aligned(4)));
|
} __attribute__ ((aligned (4)));
|
||||||
|
|
||||||
struct grub_btrfs_inode
|
struct grub_btrfs_inode
|
||||||
{
|
{
|
||||||
|
@ -215,12 +229,13 @@ struct grub_btrfs_extent_data
|
||||||
|
|
||||||
#define GRUB_BTRFS_COMPRESSION_NONE 0
|
#define GRUB_BTRFS_COMPRESSION_NONE 0
|
||||||
#define GRUB_BTRFS_COMPRESSION_ZLIB 1
|
#define GRUB_BTRFS_COMPRESSION_ZLIB 1
|
||||||
|
#define GRUB_BTRFS_COMPRESSION_LZO 2
|
||||||
|
|
||||||
#define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100
|
#define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100
|
||||||
|
|
||||||
static grub_disk_addr_t superblock_sectors[] = { 64 * 2, 64 * 1024 * 2,
|
static grub_disk_addr_t superblock_sectors[] = { 64 * 2, 64 * 1024 * 2,
|
||||||
256 * 1048576 * 2,
|
256 * 1048576 * 2, 1048576ULL * 1048576ULL * 2
|
||||||
1048576ULL * 1048576ULL * 2 };
|
};
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
||||||
|
@ -234,6 +249,10 @@ read_sblock (grub_disk_t disk, struct grub_btrfs_superblock *sb)
|
||||||
for (i = 0; i < ARRAY_SIZE (superblock_sectors); i++)
|
for (i = 0; i < ARRAY_SIZE (superblock_sectors); i++)
|
||||||
{
|
{
|
||||||
struct grub_btrfs_superblock sblock;
|
struct grub_btrfs_superblock sblock;
|
||||||
|
/* Don't try additional superblocks beyond device size. */
|
||||||
|
if (i && (grub_le_to_cpu64 (sblock.this_device.size)
|
||||||
|
>> GRUB_DISK_SECTOR_BITS) <= superblock_sectors[i])
|
||||||
|
break;
|
||||||
err = grub_disk_read (disk, superblock_sectors[i], 0,
|
err = grub_disk_read (disk, superblock_sectors[i], 0,
|
||||||
sizeof (sblock), &sblock);
|
sizeof (sblock), &sblock);
|
||||||
if (err == GRUB_ERR_OUT_OF_RANGE)
|
if (err == GRUB_ERR_OUT_OF_RANGE)
|
||||||
|
@ -307,7 +326,7 @@ save_ref (struct grub_btrfs_leaf_descriptor *desc,
|
||||||
static int
|
static int
|
||||||
next (struct grub_btrfs_data *data,
|
next (struct grub_btrfs_data *data,
|
||||||
struct grub_btrfs_leaf_descriptor *desc,
|
struct grub_btrfs_leaf_descriptor *desc,
|
||||||
grub_disk_addr_t *outaddr, grub_size_t *outsize,
|
grub_disk_addr_t * outaddr, grub_size_t * outsize,
|
||||||
struct grub_btrfs_key *key_out)
|
struct grub_btrfs_key *key_out)
|
||||||
{
|
{
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
@ -330,13 +349,13 @@ next (struct grub_btrfs_data *data,
|
||||||
err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter
|
err = grub_btrfs_read_logical (data, desc->data[desc->depth - 1].iter
|
||||||
* sizeof (node)
|
* sizeof (node)
|
||||||
+ sizeof (struct btrfs_header)
|
+ sizeof (struct btrfs_header)
|
||||||
+ desc->data[desc->depth - 1].addr, &node,
|
+ desc->data[desc->depth - 1].addr,
|
||||||
sizeof (node));
|
&node, sizeof (node));
|
||||||
if (err)
|
if (err)
|
||||||
return -err;
|
return -err;
|
||||||
|
|
||||||
err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr), &head,
|
err = grub_btrfs_read_logical (data, grub_le_to_cpu64 (node.addr),
|
||||||
sizeof (head));
|
&head, sizeof (head));
|
||||||
if (err)
|
if (err)
|
||||||
return -err;
|
return -err;
|
||||||
|
|
||||||
|
@ -410,7 +429,8 @@ lower_bound (struct grub_btrfs_data *data,
|
||||||
grub_dprintf ("btrfs",
|
grub_dprintf ("btrfs",
|
||||||
"internal node (depth %d) %" PRIxGRUB_UINT64_T
|
"internal node (depth %d) %" PRIxGRUB_UINT64_T
|
||||||
" %x %" PRIxGRUB_UINT64_T "\n", depth,
|
" %x %" PRIxGRUB_UINT64_T "\n", depth,
|
||||||
node.key.object_id, node.key.type, node.key.offset);
|
node.key.object_id, node.key.type,
|
||||||
|
node.key.offset);
|
||||||
|
|
||||||
if (key_cmp (&node.key, key_in) == 0)
|
if (key_cmp (&node.key, key_in) == 0)
|
||||||
{
|
{
|
||||||
|
@ -465,7 +485,7 @@ lower_bound (struct grub_btrfs_data *data,
|
||||||
|
|
||||||
if (key_cmp (&leaf.key, key_in) == 0)
|
if (key_cmp (&leaf.key, key_in) == 0)
|
||||||
{
|
{
|
||||||
grub_memcpy (key_out, &leaf.key, sizeof(*key_out));
|
grub_memcpy (key_out, &leaf.key, sizeof (*key_out));
|
||||||
*outsize = grub_le_to_cpu32 (leaf.size);
|
*outsize = grub_le_to_cpu32 (leaf.size);
|
||||||
*outaddr = addr + grub_le_to_cpu32 (leaf.offset);
|
*outaddr = addr + grub_le_to_cpu32 (leaf.offset);
|
||||||
if (desc)
|
if (desc)
|
||||||
|
@ -483,7 +503,7 @@ lower_bound (struct grub_btrfs_data *data,
|
||||||
|
|
||||||
if (have_last)
|
if (have_last)
|
||||||
{
|
{
|
||||||
grub_memcpy (key_out, &leaf_last.key, sizeof(*key_out));
|
grub_memcpy (key_out, &leaf_last.key, sizeof (*key_out));
|
||||||
*outsize = grub_le_to_cpu32 (leaf_last.size);
|
*outsize = grub_le_to_cpu32 (leaf_last.size);
|
||||||
*outaddr = addr + grub_le_to_cpu32 (leaf_last.offset);
|
*outaddr = addr + grub_le_to_cpu32 (leaf_last.offset);
|
||||||
if (desc)
|
if (desc)
|
||||||
|
@ -503,8 +523,7 @@ lower_bound (struct grub_btrfs_data *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_device_t
|
static grub_device_t
|
||||||
find_device (struct grub_btrfs_data *data, grub_uint64_t id,
|
find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan)
|
||||||
int do_rescan)
|
|
||||||
{
|
{
|
||||||
grub_device_t dev_found = NULL;
|
grub_device_t dev_found = NULL;
|
||||||
auto int hook (const char *name);
|
auto int hook (const char *name);
|
||||||
|
@ -579,8 +598,7 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id,
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||||
grub_disk_addr_t addr,
|
|
||||||
void *buf, grub_size_t size)
|
void *buf, grub_size_t size)
|
||||||
{
|
{
|
||||||
while (size > 0)
|
while (size > 0)
|
||||||
|
@ -602,14 +620,14 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
||||||
for (ptr = data->sblock.bootstrap_mapping;
|
for (ptr = data->sblock.bootstrap_mapping;
|
||||||
ptr < data->sblock.bootstrap_mapping
|
ptr < data->sblock.bootstrap_mapping
|
||||||
+ sizeof (data->sblock.bootstrap_mapping)
|
+ sizeof (data->sblock.bootstrap_mapping)
|
||||||
- sizeof (struct grub_btrfs_key);
|
- sizeof (struct grub_btrfs_key);)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
key = (struct grub_btrfs_key *) ptr;
|
key = (struct grub_btrfs_key *) ptr;
|
||||||
if (key->type != GRUB_BTRFS_ITEM_TYPE_CHUNK)
|
if (key->type != GRUB_BTRFS_ITEM_TYPE_CHUNK)
|
||||||
break;
|
break;
|
||||||
chunk = (struct grub_btrfs_chunk_item *) (key + 1);
|
chunk = (struct grub_btrfs_chunk_item *) (key + 1);
|
||||||
grub_dprintf ("btrfs", "%" PRIxGRUB_UINT64_T " %" PRIxGRUB_UINT64_T " \n",
|
grub_dprintf ("btrfs",
|
||||||
|
"%" PRIxGRUB_UINT64_T " %" PRIxGRUB_UINT64_T " \n",
|
||||||
grub_le_to_cpu64 (key->offset),
|
grub_le_to_cpu64 (key->offset),
|
||||||
grub_le_to_cpu64 (chunk->size));
|
grub_le_to_cpu64 (chunk->size));
|
||||||
if (grub_le_to_cpu64 (key->offset) <= addr
|
if (grub_le_to_cpu64 (key->offset) <= addr
|
||||||
|
@ -707,8 +725,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
||||||
|
|
||||||
high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes),
|
high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes),
|
||||||
&stripen);
|
&stripen);
|
||||||
stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length)
|
stripe_offset =
|
||||||
* high;
|
low + grub_le_to_cpu64 (chunk->stripe_length) * high;
|
||||||
csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
|
csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -721,12 +739,11 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
||||||
&low);
|
&low);
|
||||||
|
|
||||||
high = grub_divmod64 (middle,
|
high = grub_divmod64 (middle,
|
||||||
grub_le_to_cpu16 (chunk->nsubstripes),
|
grub_le_to_cpu16 (chunk->nstripes)
|
||||||
|
/ grub_le_to_cpu16 (chunk->nsubstripes),
|
||||||
&stripen);
|
&stripen);
|
||||||
stripen *= grub_le_to_cpu16 (chunk->nstripes)
|
stripen *= grub_le_to_cpu16 (chunk->nsubstripes);
|
||||||
/ grub_le_to_cpu16 (chunk->nsubstripes);
|
redundancy = grub_le_to_cpu16 (chunk->nsubstripes);
|
||||||
redundancy = grub_le_to_cpu16 (chunk->nstripes)
|
|
||||||
/ grub_le_to_cpu16 (chunk->nsubstripes);
|
|
||||||
stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length)
|
stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length)
|
||||||
* high;
|
* high;
|
||||||
csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
|
csize = grub_le_to_cpu64 (chunk->stripe_length) - low;
|
||||||
|
@ -759,7 +776,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
||||||
paddr = stripe->offset + stripe_offset;
|
paddr = stripe->offset + stripe_offset;
|
||||||
|
|
||||||
grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
|
grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
|
||||||
"+0x%" PRIxGRUB_UINT64_T " (%d stripes (%d substripes) of %"
|
"+0x%" PRIxGRUB_UINT64_T
|
||||||
|
" (%d stripes (%d substripes) of %"
|
||||||
PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT64_T
|
PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT64_T
|
||||||
" maps to 0x%" PRIxGRUB_UINT64_T "\n",
|
" maps to 0x%" PRIxGRUB_UINT64_T "\n",
|
||||||
grub_le_to_cpu64 (key->offset),
|
grub_le_to_cpu64 (key->offset),
|
||||||
|
@ -769,7 +787,7 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data,
|
||||||
grub_le_to_cpu64 (chunk->stripe_length),
|
grub_le_to_cpu64 (chunk->stripe_length),
|
||||||
stripen, stripe->offset);
|
stripen, stripe->offset);
|
||||||
grub_dprintf ("btrfs", "reading paddr 0x%" PRIxGRUB_UINT64_T
|
grub_dprintf ("btrfs", "reading paddr 0x%" PRIxGRUB_UINT64_T
|
||||||
" for laddr 0x%" PRIxGRUB_UINT64_T"\n", paddr,
|
" for laddr 0x%" PRIxGRUB_UINT64_T "\n", paddr,
|
||||||
addr);
|
addr);
|
||||||
|
|
||||||
dev = find_device (data, stripe->device_id, j);
|
dev = find_device (data, stripe->device_id, j);
|
||||||
|
@ -815,7 +833,7 @@ grub_btrfs_mount (grub_device_t dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
data = grub_zalloc (sizeof (*data));
|
data = grub_zalloc (sizeof (*data));
|
||||||
if (! data)
|
if (!data)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
err = read_sblock (dev->disk, &data->sblock);
|
err = read_sblock (dev->disk, &data->sblock);
|
||||||
|
@ -866,8 +884,7 @@ grub_btrfs_read_inode (struct grub_btrfs_data *data,
|
||||||
key_in.type = GRUB_BTRFS_ITEM_TYPE_INODE_ITEM;
|
key_in.type = GRUB_BTRFS_ITEM_TYPE_INODE_ITEM;
|
||||||
key_in.offset = 0;
|
key_in.offset = 0;
|
||||||
|
|
||||||
err = lower_bound (data, &key_in, &key_out, tree,
|
err = lower_bound (data, &key_in, &key_out, tree, &elemaddr, &elemsize, NULL);
|
||||||
&elemaddr, &elemsize, NULL);
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
if (num != key_out.object_id
|
if (num != key_out.object_id
|
||||||
|
@ -877,6 +894,80 @@ grub_btrfs_read_inode (struct grub_btrfs_data *data,
|
||||||
return grub_btrfs_read_logical (data, elemaddr, inode, sizeof (*inode));
|
return grub_btrfs_read_logical (data, elemaddr, inode, sizeof (*inode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static grub_ssize_t
|
||||||
|
grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off,
|
||||||
|
char *obuf, grub_size_t osize)
|
||||||
|
{
|
||||||
|
grub_uint32_t total_size, cblock_size, ret = 0;
|
||||||
|
unsigned char buf[GRUB_BTRFS_LZO_BLOCK_SIZE];
|
||||||
|
|
||||||
|
total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
|
||||||
|
ibuf += sizeof (total_size);
|
||||||
|
|
||||||
|
if (isize < total_size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Jump forward to first block with requested data. */
|
||||||
|
while (off >= GRUB_BTRFS_LZO_BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
|
||||||
|
ibuf += sizeof (cblock_size);
|
||||||
|
|
||||||
|
if (cblock_size > GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
off -= GRUB_BTRFS_LZO_BLOCK_SIZE;
|
||||||
|
ibuf += cblock_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (osize > 0)
|
||||||
|
{
|
||||||
|
lzo_uint usize = GRUB_BTRFS_LZO_BLOCK_SIZE;
|
||||||
|
|
||||||
|
cblock_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf));
|
||||||
|
ibuf += sizeof (cblock_size);
|
||||||
|
|
||||||
|
if (cblock_size > GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Block partially filled with requested data. */
|
||||||
|
if (off > 0 || osize < GRUB_BTRFS_LZO_BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
grub_size_t to_copy = GRUB_BTRFS_LZO_BLOCK_SIZE - off;
|
||||||
|
|
||||||
|
if (to_copy > osize)
|
||||||
|
to_copy = osize;
|
||||||
|
|
||||||
|
if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, buf, &usize,
|
||||||
|
NULL) != LZO_E_OK)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (to_copy > usize)
|
||||||
|
to_copy = usize;
|
||||||
|
grub_memcpy(obuf, buf + off, to_copy);
|
||||||
|
|
||||||
|
osize -= to_copy;
|
||||||
|
ret += to_copy;
|
||||||
|
obuf += to_copy;
|
||||||
|
ibuf += cblock_size;
|
||||||
|
off = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decompress whole block directly to output buffer. */
|
||||||
|
if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, (lzo_bytep)obuf,
|
||||||
|
&usize, NULL) != LZO_E_OK)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
osize -= usize;
|
||||||
|
ret += usize;
|
||||||
|
obuf += usize;
|
||||||
|
ibuf += cblock_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static grub_ssize_t
|
static grub_ssize_t
|
||||||
grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||||
grub_uint64_t ino, grub_uint64_t tree,
|
grub_uint64_t ino, grub_uint64_t tree,
|
||||||
|
@ -909,6 +1000,12 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||||
grub_error (GRUB_ERR_BAD_FS, "extent not found");
|
grub_error (GRUB_ERR_BAD_FS, "extent not found");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if ((grub_ssize_t) elemsize < ((char *) &data->extent->inl
|
||||||
|
- (char *) data->extent))
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_BAD_FS, "extent descriptor is too short");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
data->extstart = grub_le_to_cpu64 (key_out.offset);
|
data->extstart = grub_le_to_cpu64 (key_out.offset);
|
||||||
data->extsize = elemsize;
|
data->extsize = elemsize;
|
||||||
data->extent = grub_malloc (elemsize);
|
data->extent = grub_malloc (elemsize);
|
||||||
|
@ -917,26 +1014,22 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||||
if (!data->extent)
|
if (!data->extent)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
err = grub_btrfs_read_logical (data, elemaddr,
|
err = grub_btrfs_read_logical (data, elemaddr, data->extent,
|
||||||
data->extent, elemsize);
|
elemsize);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
data->extend = data->extstart
|
data->extend = data->extstart + grub_le_to_cpu64 (data->extent->size);
|
||||||
+ grub_le_to_cpu64 (data->extent->size);
|
|
||||||
if (data->extent->type == GRUB_BTRFS_EXTENT_REGULAR
|
if (data->extent->type == GRUB_BTRFS_EXTENT_REGULAR
|
||||||
&& (char *) &data->extent + elemsize
|
&& (char *) &data->extent + elemsize
|
||||||
>= (char *) &data->extent->filled
|
>= (char *) &data->extent->filled + sizeof (data->extent->filled))
|
||||||
+ sizeof (data->extent->filled))
|
data->extend =
|
||||||
data->extend = data->extstart
|
data->extstart + grub_le_to_cpu64 (data->extent->filled);
|
||||||
+ grub_le_to_cpu64 (data->extent->filled);
|
|
||||||
|
|
||||||
grub_dprintf ("btrfs", "extent 0x%" PRIxGRUB_UINT64_T "+0x%"
|
grub_dprintf ("btrfs", "regular extent 0x%" PRIxGRUB_UINT64_T "+0x%"
|
||||||
PRIxGRUB_UINT64_T " (0x%"
|
PRIxGRUB_UINT64_T "\n",
|
||||||
PRIxGRUB_UINT64_T ")\n",
|
|
||||||
grub_le_to_cpu64 (key_out.offset),
|
grub_le_to_cpu64 (key_out.offset),
|
||||||
grub_le_to_cpu64 (data->extent->size),
|
grub_le_to_cpu64 (data->extent->size));
|
||||||
grub_le_to_cpu64 (data->extent->filled));
|
|
||||||
if (data->extend <= pos)
|
if (data->extend <= pos)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_FS, "extent not found");
|
grub_error (GRUB_ERR_BAD_FS, "extent not found");
|
||||||
|
@ -956,7 +1049,8 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE
|
if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE
|
||||||
&& data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB)
|
&& data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB
|
||||||
|
&& data->extent->compression != GRUB_BTRFS_COMPRESSION_LZO)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
"compression type 0x%x not supported",
|
"compression type 0x%x not supported",
|
||||||
|
@ -966,8 +1060,7 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||||
|
|
||||||
if (data->extent->encoding)
|
if (data->extent->encoding)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "encoding not supported");
|
||||||
"encoding not supported");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -983,6 +1076,15 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||||
!= (grub_ssize_t) csize)
|
!= (grub_ssize_t) csize)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO)
|
||||||
|
{
|
||||||
|
if (grub_btrfs_lzo_decompress(data->extent->inl, data->extsize -
|
||||||
|
((grub_uint8_t *) data->extent->inl
|
||||||
|
- (grub_uint8_t *) data->extent),
|
||||||
|
extoff, buf, csize)
|
||||||
|
!= (grub_ssize_t) csize)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
grub_memcpy (buf, data->extent->inl + extoff, csize);
|
grub_memcpy (buf, data->extent->inl + extoff, csize);
|
||||||
break;
|
break;
|
||||||
|
@ -992,10 +1094,13 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||||
grub_memset (buf, 0, csize);
|
grub_memset (buf, 0, csize);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB)
|
|
||||||
|
if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE)
|
||||||
{
|
{
|
||||||
char *tmp;
|
char *tmp;
|
||||||
grub_uint64_t zsize;
|
grub_uint64_t zsize;
|
||||||
|
grub_ssize_t ret;
|
||||||
|
|
||||||
zsize = grub_le_to_cpu64 (data->extent->compressed_size);
|
zsize = grub_le_to_cpu64 (data->extent->compressed_size);
|
||||||
tmp = grub_malloc (zsize);
|
tmp = grub_malloc (zsize);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
|
@ -1008,21 +1113,29 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data,
|
||||||
grub_free (tmp);
|
grub_free (tmp);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (grub_zlib_decompress (tmp, zsize, extoff
|
|
||||||
|
if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZLIB)
|
||||||
|
ret = grub_zlib_decompress (tmp, zsize, extoff
|
||||||
+ grub_le_to_cpu64 (data->extent->offset),
|
+ grub_le_to_cpu64 (data->extent->offset),
|
||||||
buf, csize) != (grub_ssize_t) csize)
|
buf, csize);
|
||||||
{
|
else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO)
|
||||||
|
ret = grub_btrfs_lzo_decompress (tmp, zsize, extoff
|
||||||
|
+ grub_le_to_cpu64 (data->extent->offset),
|
||||||
|
buf, csize);
|
||||||
|
else
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
grub_free (tmp);
|
grub_free (tmp);
|
||||||
|
|
||||||
|
if (ret != (grub_ssize_t) csize)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
grub_free (tmp);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
err = grub_btrfs_read_logical (data,
|
err = grub_btrfs_read_logical (data,
|
||||||
grub_le_to_cpu64 (data->extent->laddr)
|
grub_le_to_cpu64 (data->extent->laddr)
|
||||||
+ grub_le_to_cpu64 (data->extent->offset)
|
+ grub_le_to_cpu64 (data->extent->offset)
|
||||||
+ extoff,
|
+ extoff, buf, csize);
|
||||||
buf, csize);
|
|
||||||
if (err)
|
if (err)
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
@ -1097,8 +1210,8 @@ find_path (struct grub_btrfs_data *data,
|
||||||
key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
|
key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM;
|
||||||
key->offset = grub_cpu_to_le64 (~grub_getcrc32c (1, ctoken, ctokenlen));
|
key->offset = grub_cpu_to_le64 (~grub_getcrc32c (1, ctoken, ctokenlen));
|
||||||
|
|
||||||
err = lower_bound (data, key, &key_out, *tree,
|
err = lower_bound (data, key, &key_out, *tree, &elemaddr, &elemsize,
|
||||||
&elemaddr, &elemsize, NULL);
|
NULL);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_free (direl);
|
grub_free (direl);
|
||||||
|
@ -1208,7 +1321,6 @@ find_path (struct grub_btrfs_data *data,
|
||||||
grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path,
|
grub_memcpy (tmp + grub_le_to_cpu64 (inode.size), path,
|
||||||
grub_strlen (path) + 1);
|
grub_strlen (path) + 1);
|
||||||
grub_free (path_alloc);
|
grub_free (path_alloc);
|
||||||
grub_free (origpath);
|
|
||||||
path = path_alloc = tmp;
|
path = path_alloc = tmp;
|
||||||
if (path[0] == '/')
|
if (path[0] == '/')
|
||||||
{
|
{
|
||||||
|
@ -1247,8 +1359,7 @@ find_path (struct grub_btrfs_data *data,
|
||||||
grub_free (origpath);
|
grub_free (origpath);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
err = grub_btrfs_read_logical (data, elemaddr,
|
err = grub_btrfs_read_logical (data, elemaddr, &ri, sizeof (ri));
|
||||||
&ri, sizeof (ri));
|
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_free (direl);
|
grub_free (direl);
|
||||||
|
@ -1285,6 +1396,8 @@ find_path (struct grub_btrfs_data *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_free (direl);
|
grub_free (direl);
|
||||||
|
grub_free (origpath);
|
||||||
|
grub_free (path_alloc);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1310,23 +1423,28 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
||||||
|
|
||||||
err = find_path (data, path, &key_in, &tree, &type);
|
err = find_path (data, path, &key_in, &tree, &type);
|
||||||
if (err)
|
if (err)
|
||||||
|
{
|
||||||
|
grub_btrfs_unmount (data);
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY)
|
if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY)
|
||||||
|
{
|
||||||
|
grub_btrfs_unmount (data);
|
||||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
|
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
|
||||||
|
}
|
||||||
|
|
||||||
err = lower_bound (data, &key_in, &key_out, tree,
|
err = lower_bound (data, &key_in, &key_out, tree, &elemaddr, &elemsize, &desc);
|
||||||
&elemaddr, &elemsize, &desc);
|
|
||||||
if (err)
|
if (err)
|
||||||
|
{
|
||||||
|
grub_btrfs_unmount (data);
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM
|
if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM
|
||||||
|| key_out.object_id != key_in.object_id)
|
|| key_out.object_id != key_in.object_id)
|
||||||
{
|
{
|
||||||
r = next (data, &desc, &elemaddr, &elemsize, &key_out);
|
r = next (data, &desc, &elemaddr, &elemsize, &key_out);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
{
|
goto out;
|
||||||
free_iterator (&desc);
|
|
||||||
return -r;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -1344,14 +1462,17 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
||||||
direl = grub_malloc (allocated + 1);
|
direl = grub_malloc (allocated + 1);
|
||||||
if (!direl)
|
if (!direl)
|
||||||
{
|
{
|
||||||
free_iterator (&desc);
|
r = -grub_errno;
|
||||||
return grub_errno;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize);
|
err = grub_btrfs_read_logical (data, elemaddr, direl, elemsize);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
{
|
||||||
|
r = -err;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (cdirel = direl;
|
for (cdirel = direl;
|
||||||
(grub_uint8_t *) cdirel - (grub_uint8_t *) direl
|
(grub_uint8_t *) cdirel - (grub_uint8_t *) direl
|
||||||
|
@ -1384,7 +1505,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
||||||
}
|
}
|
||||||
while (r > 0);
|
while (r > 0);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
grub_free (direl);
|
grub_free (direl);
|
||||||
|
|
||||||
free_iterator (&desc);
|
free_iterator (&desc);
|
||||||
|
@ -1456,7 +1577,7 @@ grub_btrfs_uuid (grub_device_t device, char **uuid)
|
||||||
*uuid = NULL;
|
*uuid = NULL;
|
||||||
|
|
||||||
data = grub_btrfs_mount (device);
|
data = grub_btrfs_mount (device);
|
||||||
if (! data)
|
if (!data)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
*uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
|
*uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
|
||||||
|
@ -1482,7 +1603,7 @@ grub_btrfs_label (grub_device_t device, char **label)
|
||||||
*label = NULL;
|
*label = NULL;
|
||||||
|
|
||||||
data = grub_btrfs_mount (device);
|
data = grub_btrfs_mount (device);
|
||||||
if (! data)
|
if (!data)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
*label = grub_strndup (data->sblock.label, sizeof (data->sblock.label));
|
*label = grub_strndup (data->sblock.label, sizeof (data->sblock.label));
|
||||||
|
@ -1492,8 +1613,36 @@ grub_btrfs_label (grub_device_t device, char **label)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct grub_fs grub_btrfs_fs =
|
#ifdef GRUB_UTIL
|
||||||
{
|
static grub_err_t
|
||||||
|
grub_btrfs_embed (grub_device_t device __attribute__ ((unused)),
|
||||||
|
unsigned int *nsectors,
|
||||||
|
grub_embed_type_t embed_type,
|
||||||
|
grub_disk_addr_t **sectors)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
if (embed_type != GRUB_EMBED_PCBIOS)
|
||||||
|
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
|
"BtrFS currently supports only PC-BIOS embedding");
|
||||||
|
|
||||||
|
if (64 * 2 - 1 < *nsectors)
|
||||||
|
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||||
|
"Your core.img is unusually large. "
|
||||||
|
"It won't fit in the embedding area.");
|
||||||
|
|
||||||
|
*nsectors = 64 * 2 - 1;
|
||||||
|
*sectors = grub_malloc (*nsectors * sizeof (**sectors));
|
||||||
|
if (!*sectors)
|
||||||
|
return grub_errno;
|
||||||
|
for (i = 0; i < *nsectors; i++)
|
||||||
|
(*sectors)[i] = i + 1;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct grub_fs grub_btrfs_fs = {
|
||||||
.name = "btrfs",
|
.name = "btrfs",
|
||||||
.dir = grub_btrfs_dir,
|
.dir = grub_btrfs_dir,
|
||||||
.open = grub_btrfs_open,
|
.open = grub_btrfs_open,
|
||||||
|
@ -1502,16 +1651,17 @@ static struct grub_fs grub_btrfs_fs =
|
||||||
.uuid = grub_btrfs_uuid,
|
.uuid = grub_btrfs_uuid,
|
||||||
.label = grub_btrfs_label,
|
.label = grub_btrfs_label,
|
||||||
#ifdef GRUB_UTIL
|
#ifdef GRUB_UTIL
|
||||||
|
.embed = grub_btrfs_embed,
|
||||||
.reserved_first_sector = 1,
|
.reserved_first_sector = 1,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
GRUB_MOD_INIT(btrfs)
|
GRUB_MOD_INIT (btrfs)
|
||||||
{
|
{
|
||||||
grub_fs_register (&grub_btrfs_fs);
|
grub_fs_register (&grub_btrfs_fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
GRUB_MOD_FINI(btrfs)
|
GRUB_MOD_FINI (btrfs)
|
||||||
{
|
{
|
||||||
grub_fs_unregister (&grub_btrfs_fs);
|
grub_fs_unregister (&grub_btrfs_fs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,28 +25,74 @@
|
||||||
|
|
||||||
GRUB_MOD_LICENSE ("GPLv3+");
|
GRUB_MOD_LICENSE ("GPLv3+");
|
||||||
|
|
||||||
#ifndef MODE_USTAR
|
#define ATTR_TYPE 0160000
|
||||||
/* cpio support */
|
#define ATTR_FILE 0100000
|
||||||
#define MAGIC_BCPIO 070707
|
#define ATTR_DIR 0040000
|
||||||
|
#define ATTR_LNK 0120000
|
||||||
|
|
||||||
|
#ifdef MODE_ODC
|
||||||
|
#define ALIGN_CPIO(x) x
|
||||||
|
#define MAGIC "070707"
|
||||||
struct head
|
struct head
|
||||||
{
|
{
|
||||||
grub_uint16_t magic;
|
char magic[6];
|
||||||
|
char dev[6];
|
||||||
|
char ino[6];
|
||||||
|
char mode[6];
|
||||||
|
char uid[6];
|
||||||
|
char gid[6];
|
||||||
|
char nlink[6];
|
||||||
|
char rdev[6];
|
||||||
|
char mtime[11];
|
||||||
|
char namesize[6];
|
||||||
|
char filesize[11];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
#elif defined (MODE_NEWC)
|
||||||
|
#define ALIGN_CPIO(x) (ALIGN_UP ((x), 4))
|
||||||
|
#define MAGIC "070701"
|
||||||
|
#define MAGIC2 "070702"
|
||||||
|
struct head
|
||||||
|
{
|
||||||
|
char magic[6];
|
||||||
|
char ino[8];
|
||||||
|
char mode[8];
|
||||||
|
char uid[8];
|
||||||
|
char gid[8];
|
||||||
|
char nlink[8];
|
||||||
|
char mtime[8];
|
||||||
|
char filesize[8];
|
||||||
|
char devmajor[8];
|
||||||
|
char devminor[8];
|
||||||
|
char rdevmajor[8];
|
||||||
|
char rdevminor[8];
|
||||||
|
char namesize[8];
|
||||||
|
char check[8];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
#elif !defined (MODE_USTAR)
|
||||||
|
/* cpio support */
|
||||||
|
#define ALIGN_CPIO(x) (ALIGN_UP ((x), 2))
|
||||||
|
#ifdef MODE_BIGENDIAN
|
||||||
|
#define MAGIC "\x71\xc7"
|
||||||
|
#else
|
||||||
|
#define MAGIC "\xc7\x71"
|
||||||
|
#endif
|
||||||
|
struct head
|
||||||
|
{
|
||||||
|
grub_uint16_t magic[1];
|
||||||
grub_uint16_t dev;
|
grub_uint16_t dev;
|
||||||
grub_uint16_t ino;
|
grub_uint16_t ino;
|
||||||
grub_uint16_t mode;
|
grub_uint16_t mode[1];
|
||||||
grub_uint16_t uid;
|
grub_uint16_t uid;
|
||||||
grub_uint16_t gid;
|
grub_uint16_t gid;
|
||||||
grub_uint16_t nlink;
|
grub_uint16_t nlink;
|
||||||
grub_uint16_t rdev;
|
grub_uint16_t rdev;
|
||||||
grub_uint16_t mtime_1;
|
grub_uint16_t mtime[2];
|
||||||
grub_uint16_t mtime_2;
|
grub_uint16_t namesize[1];
|
||||||
grub_uint16_t namesize;
|
grub_uint16_t filesize[2];
|
||||||
grub_uint16_t filesize_1;
|
|
||||||
grub_uint16_t filesize_2;
|
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
#else
|
#else
|
||||||
/* tar support */
|
/* tar support */
|
||||||
#define MAGIC_USTAR "ustar"
|
#define MAGIC "ustar"
|
||||||
struct head
|
struct head
|
||||||
{
|
{
|
||||||
char name[100];
|
char name[100];
|
||||||
|
@ -71,60 +117,140 @@ struct head
|
||||||
struct grub_cpio_data
|
struct grub_cpio_data
|
||||||
{
|
{
|
||||||
grub_disk_t disk;
|
grub_disk_t disk;
|
||||||
grub_uint32_t hofs;
|
grub_off_t hofs;
|
||||||
grub_uint32_t dofs;
|
grub_off_t dofs;
|
||||||
grub_uint32_t size;
|
grub_off_t size;
|
||||||
|
#ifdef MODE_USTAR
|
||||||
|
char *linkname;
|
||||||
|
grub_size_t linkname_alloc;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static grub_dl_t my_mod;
|
static grub_dl_t my_mod;
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
canonicalize (char *name)
|
||||||
|
{
|
||||||
|
char *iptr, *optr;
|
||||||
|
for (iptr = name, optr = name; *iptr; )
|
||||||
|
{
|
||||||
|
while (*iptr == '/')
|
||||||
|
iptr++;
|
||||||
|
if (iptr[0] == '.' && (iptr[1] == '/' || iptr[1] == 0))
|
||||||
|
{
|
||||||
|
iptr += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
while (*iptr && *iptr != '/')
|
||||||
|
*optr++ = *iptr++;
|
||||||
|
if (*iptr)
|
||||||
|
*optr++ = *iptr++;
|
||||||
|
}
|
||||||
|
*optr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined (MODE_ODC) || defined (MODE_USTAR)
|
||||||
|
static inline unsigned long long
|
||||||
|
read_number (const char *str, grub_size_t size)
|
||||||
|
{
|
||||||
|
unsigned long long ret = 0;
|
||||||
|
while (size-- && *str >= '0' && *str <= '7')
|
||||||
|
ret = (ret << 3) | (*str++ & 0xf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#elif defined (MODE_NEWC)
|
||||||
|
static inline unsigned long long
|
||||||
|
read_number (const char *str, grub_size_t size)
|
||||||
|
{
|
||||||
|
unsigned long long ret = 0;
|
||||||
|
while (size-- && grub_isxdigit (*str))
|
||||||
|
{
|
||||||
|
char dig = *str++;
|
||||||
|
if (dig >= '0' && dig <= '9')
|
||||||
|
dig &= 0xf;
|
||||||
|
else if (dig >= 'a' && dig <= 'f')
|
||||||
|
dig -= 'a' - 10;
|
||||||
|
else
|
||||||
|
dig -= 'A' - 10;
|
||||||
|
ret = (ret << 4) | (dig);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline unsigned long long
|
||||||
|
read_number (const grub_uint16_t *arr, grub_size_t size)
|
||||||
|
{
|
||||||
|
long long ret = 0;
|
||||||
|
#ifdef MODE_BIGENDIAN
|
||||||
|
while (size--)
|
||||||
|
ret = (ret << 16) | grub_be_to_cpu16 (*arr++);
|
||||||
|
#else
|
||||||
|
while (size--)
|
||||||
|
ret = (ret << 16) | grub_le_to_cpu16 (*arr++);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_cpio_find_file (struct grub_cpio_data *data, char **name,
|
grub_cpio_find_file (struct grub_cpio_data *data, char **name,
|
||||||
grub_int32_t *mtime, grub_uint32_t * ofs)
|
grub_int32_t *mtime, grub_disk_addr_t *ofs,
|
||||||
|
grub_uint32_t *mode)
|
||||||
{
|
{
|
||||||
#ifndef MODE_USTAR
|
#ifndef MODE_USTAR
|
||||||
struct head hd;
|
struct head hd;
|
||||||
|
grub_size_t namesize;
|
||||||
|
grub_uint32_t modeval;
|
||||||
|
|
||||||
if (grub_disk_read
|
if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd))
|
||||||
(data->disk, 0, data->hofs, sizeof (hd), &hd))
|
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
if (hd.magic != MAGIC_BCPIO)
|
if (grub_memcmp (hd.magic, MAGIC, sizeof (hd.magic)) != 0
|
||||||
|
#ifdef MAGIC2
|
||||||
|
&& grub_memcmp (hd.magic, MAGIC2, sizeof (hd.magic)) != 0
|
||||||
|
#endif
|
||||||
|
)
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
|
return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive");
|
||||||
|
data->size = read_number (hd.filesize, ARRAY_SIZE (hd.filesize));
|
||||||
data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2;
|
|
||||||
if (mtime)
|
if (mtime)
|
||||||
*mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2;
|
*mtime = read_number (hd.mtime, ARRAY_SIZE (hd.mtime));
|
||||||
|
modeval = read_number (hd.mode, ARRAY_SIZE (hd.mode));
|
||||||
|
namesize = read_number (hd.namesize, ARRAY_SIZE (hd.namesize));
|
||||||
|
|
||||||
if (hd.namesize & 1)
|
if (mode)
|
||||||
hd.namesize++;
|
*mode = modeval;
|
||||||
|
|
||||||
if ((*name = grub_malloc (hd.namesize)) == NULL)
|
*name = grub_malloc (namesize + 1);
|
||||||
|
if (*name == NULL)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd),
|
if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd),
|
||||||
hd.namesize, *name))
|
namesize, *name))
|
||||||
{
|
{
|
||||||
grub_free (*name);
|
grub_free (*name);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
(*name)[namesize] = 0;
|
||||||
|
|
||||||
if (data->size == 0 && hd.mode == 0 && hd.namesize == 11 + 1
|
if (data->size == 0 && modeval == 0 && namesize == 11
|
||||||
&& ! grub_memcmp(*name, "TRAILER!!!", 11))
|
&& grub_memcmp(*name, "TRAILER!!!", 11) == 0)
|
||||||
{
|
{
|
||||||
*ofs = 0;
|
*ofs = 0;
|
||||||
|
grub_free (*name);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
data->dofs = data->hofs + sizeof (hd) + hd.namesize;
|
canonicalize (*name);
|
||||||
*ofs = data->dofs + data->size;
|
|
||||||
if (data->size & 1)
|
data->dofs = data->hofs + ALIGN_CPIO (sizeof (hd) + namesize);
|
||||||
(*ofs)++;
|
*ofs = data->dofs + ALIGN_CPIO (data->size);
|
||||||
#else
|
#else
|
||||||
struct head hd;
|
struct head hd;
|
||||||
|
int reread = 0, have_longname = 0, have_longlink = 0;
|
||||||
|
|
||||||
if (grub_disk_read
|
for (reread = 0; reread < 3; reread++)
|
||||||
(data->disk, 0, data->hofs, sizeof (hd), &hd))
|
{
|
||||||
|
if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd))
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
if (!hd.name[0])
|
if (!hd.name[0])
|
||||||
|
@ -133,18 +259,105 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name,
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1))
|
if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1))
|
||||||
return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive");
|
return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive");
|
||||||
|
|
||||||
if ((*name = grub_strdup (hd.name)) == NULL)
|
if (hd.typeflag == 'L')
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
grub_size_t namesize = read_number (hd.size, sizeof (hd.size));
|
||||||
|
*name = grub_malloc (namesize + 1);
|
||||||
|
if (*name == NULL)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
err = grub_disk_read (data->disk, 0,
|
||||||
|
data->hofs + GRUB_DISK_SECTOR_SIZE, namesize,
|
||||||
|
*name);
|
||||||
|
(*name)[namesize] = 0;
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
data->hofs += GRUB_DISK_SECTOR_SIZE
|
||||||
|
+ ((namesize + GRUB_DISK_SECTOR_SIZE - 1) &
|
||||||
|
~(GRUB_DISK_SECTOR_SIZE - 1));
|
||||||
|
have_longname = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
data->size = grub_strtoul (hd.size, NULL, 8);
|
if (hd.typeflag == 'K')
|
||||||
|
{
|
||||||
|
grub_err_t err;
|
||||||
|
grub_size_t linksize = read_number (hd.size, sizeof (hd.size));
|
||||||
|
if (data->linkname_alloc < linksize + 1)
|
||||||
|
{
|
||||||
|
char *n;
|
||||||
|
n = grub_malloc (2 * (linksize + 1));
|
||||||
|
if (!n)
|
||||||
|
return grub_errno;
|
||||||
|
grub_free (data->linkname);
|
||||||
|
data->linkname = n;
|
||||||
|
data->linkname_alloc = 2 * (linksize + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = grub_disk_read (data->disk, 0,
|
||||||
|
data->hofs + GRUB_DISK_SECTOR_SIZE, linksize,
|
||||||
|
data->linkname);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
data->linkname[linksize] = 0;
|
||||||
|
data->hofs += GRUB_DISK_SECTOR_SIZE
|
||||||
|
+ ((linksize + GRUB_DISK_SECTOR_SIZE - 1) &
|
||||||
|
~(GRUB_DISK_SECTOR_SIZE - 1));
|
||||||
|
have_longlink = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!have_longname)
|
||||||
|
{
|
||||||
|
*name = grub_strndup (hd.name, sizeof (hd.name));
|
||||||
|
if (*name == NULL)
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->size = read_number (hd.size, sizeof (hd.size));
|
||||||
data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
|
data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE;
|
||||||
*ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
|
*ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) &
|
||||||
~(GRUB_DISK_SECTOR_SIZE - 1));
|
~(GRUB_DISK_SECTOR_SIZE - 1));
|
||||||
if (mtime)
|
if (mtime)
|
||||||
*mtime = grub_strtoul (hd.mtime, NULL, 8);
|
*mtime = read_number (hd.mtime, sizeof (hd.mtime));
|
||||||
|
if (mode)
|
||||||
|
{
|
||||||
|
*mode = read_number (hd.mode, sizeof (hd.mode));
|
||||||
|
switch (hd.typeflag)
|
||||||
|
{
|
||||||
|
case '2':
|
||||||
|
*mode |= ATTR_LNK;
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
*mode |= ATTR_FILE;
|
||||||
|
break;
|
||||||
|
case '5':
|
||||||
|
*mode |= ATTR_DIR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!have_longlink)
|
||||||
|
{
|
||||||
|
if (data->linkname_alloc < 101)
|
||||||
|
{
|
||||||
|
char *n;
|
||||||
|
n = grub_malloc (101);
|
||||||
|
if (!n)
|
||||||
|
return grub_errno;
|
||||||
|
grub_free (data->linkname);
|
||||||
|
data->linkname = n;
|
||||||
|
data->linkname_alloc = 101;
|
||||||
|
}
|
||||||
|
grub_memcpy (data->linkname, hd.linkname, sizeof (hd.linkname));
|
||||||
|
data->linkname[100] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
canonicalize (*name);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
@ -158,15 +371,14 @@ grub_cpio_mount (grub_disk_t disk)
|
||||||
if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd))
|
if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
#ifndef MODE_USTAR
|
if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1)
|
||||||
if (hd.magic != MAGIC_BCPIO)
|
#ifdef MAGIC2
|
||||||
#else
|
&& grub_memcmp (hd.magic, MAGIC2, sizeof (MAGIC2) - 1)
|
||||||
if (grub_memcmp (hd.magic, MAGIC_USTAR,
|
|
||||||
sizeof (MAGIC_USTAR) - 1))
|
|
||||||
#endif
|
#endif
|
||||||
|
)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
data = (struct grub_cpio_data *) grub_malloc (sizeof (*data));
|
data = (struct grub_cpio_data *) grub_zalloc (sizeof (*data));
|
||||||
if (!data)
|
if (!data)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
@ -186,15 +398,107 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_cpio_dir (grub_device_t device, const char *path,
|
handle_symlink (struct grub_cpio_data *data,
|
||||||
|
const char *fn, char **name,
|
||||||
|
grub_uint32_t mode, int *restart)
|
||||||
|
{
|
||||||
|
grub_size_t flen;
|
||||||
|
char *target;
|
||||||
|
#ifndef MODE_USTAR
|
||||||
|
grub_err_t err;
|
||||||
|
#endif
|
||||||
|
char *ptr;
|
||||||
|
char *lastslash;
|
||||||
|
grub_size_t prefixlen;
|
||||||
|
char *rest;
|
||||||
|
grub_size_t size;
|
||||||
|
|
||||||
|
*restart = 0;
|
||||||
|
|
||||||
|
if ((mode & ATTR_TYPE) != ATTR_LNK)
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
flen = grub_strlen (fn);
|
||||||
|
if (grub_memcmp (*name, fn, flen) != 0
|
||||||
|
|| ((*name)[flen] != 0 && (*name)[flen] != '/'))
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
rest = *name + flen;
|
||||||
|
lastslash = rest;
|
||||||
|
if (*rest)
|
||||||
|
rest++;
|
||||||
|
while (lastslash >= *name && *lastslash != '/')
|
||||||
|
lastslash--;
|
||||||
|
if (lastslash >= *name)
|
||||||
|
prefixlen = lastslash - *name;
|
||||||
|
else
|
||||||
|
prefixlen = 0;
|
||||||
|
|
||||||
|
if (prefixlen)
|
||||||
|
prefixlen++;
|
||||||
|
|
||||||
|
#ifdef MODE_USTAR
|
||||||
|
size = grub_strlen (data->linkname);
|
||||||
|
#else
|
||||||
|
size = data->size;
|
||||||
|
#endif
|
||||||
|
if (size == 0)
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
target = grub_malloc (size + grub_strlen (*name) + 2);
|
||||||
|
if (!target)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
#ifdef MODE_USTAR
|
||||||
|
grub_memcpy (target + prefixlen, data->linkname, size);
|
||||||
|
#else
|
||||||
|
err = grub_disk_read (data->disk, 0, data->dofs, data->size,
|
||||||
|
target + prefixlen);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
#endif
|
||||||
|
if (target[prefixlen] == '/')
|
||||||
|
{
|
||||||
|
grub_memmove (target, target + prefixlen, data->size - 1);
|
||||||
|
ptr = target + data->size - 1;
|
||||||
|
ptr = grub_stpcpy (ptr, rest);
|
||||||
|
*ptr = 0;
|
||||||
|
grub_dprintf ("cpio", "symlink redirected %s to %s\n",
|
||||||
|
*name, target);
|
||||||
|
grub_free (*name);
|
||||||
|
*name = target;
|
||||||
|
*restart = 1;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
if (prefixlen)
|
||||||
|
{
|
||||||
|
grub_memcpy (target, *name, prefixlen);
|
||||||
|
target[prefixlen-1] = '/';
|
||||||
|
}
|
||||||
|
ptr = target + prefixlen + size;
|
||||||
|
ptr = grub_stpcpy (ptr, rest);
|
||||||
|
*ptr = 0;
|
||||||
|
grub_dprintf ("cpio", "symlink redirected %s to %s\n",
|
||||||
|
*name, target);
|
||||||
|
grub_free (*name);
|
||||||
|
*name = target;
|
||||||
|
*restart = 1;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_cpio_dir (grub_device_t device, const char *path_in,
|
||||||
int (*hook) (const char *filename,
|
int (*hook) (const char *filename,
|
||||||
const struct grub_dirhook_info *info))
|
const struct grub_dirhook_info *info))
|
||||||
{
|
{
|
||||||
struct grub_cpio_data *data;
|
struct grub_cpio_data *data;
|
||||||
grub_uint32_t ofs;
|
grub_disk_addr_t ofs;
|
||||||
char *prev, *name;
|
char *prev, *name, *path, *ptr;
|
||||||
const char *np;
|
grub_size_t len;
|
||||||
int len;
|
int symlinknest = 0;
|
||||||
|
|
||||||
|
path = grub_strdup (path_in + 1);
|
||||||
|
if (!path)
|
||||||
|
return grub_errno;
|
||||||
|
for (ptr = path + grub_strlen (path) - 1; ptr >= path && *ptr == '/'; ptr--)
|
||||||
|
*ptr = 0;
|
||||||
|
|
||||||
grub_dl_ref (my_mod);
|
grub_dl_ref (my_mod);
|
||||||
|
|
||||||
|
@ -202,35 +506,39 @@ grub_cpio_dir (grub_device_t device, const char *path,
|
||||||
|
|
||||||
data = grub_cpio_mount (device->disk);
|
data = grub_cpio_mount (device->disk);
|
||||||
if (!data)
|
if (!data)
|
||||||
goto fail;
|
{
|
||||||
|
grub_free (path);
|
||||||
np = path + 1;
|
return grub_errno;
|
||||||
len = grub_strlen (path) - 1;
|
}
|
||||||
|
|
||||||
|
len = grub_strlen (path);
|
||||||
data->hofs = 0;
|
data->hofs = 0;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
grub_int32_t mtime;
|
grub_int32_t mtime;
|
||||||
|
grub_uint32_t mode;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
if (grub_cpio_find_file (data, &name, &mtime, &ofs))
|
if (grub_cpio_find_file (data, &name, &mtime, &ofs, &mode))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (!ofs)
|
if (!ofs)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (grub_memcmp (np, name, len) == 0)
|
if (grub_memcmp (path, name, len) == 0
|
||||||
|
&& (name[len] == 0 || name[len] == '/' || len == 0))
|
||||||
{
|
{
|
||||||
char *p, *n;
|
char *p, *n;
|
||||||
|
|
||||||
n = name + len;
|
n = name + len;
|
||||||
if (*n == '/')
|
while (*n == '/')
|
||||||
n++;
|
n++;
|
||||||
|
|
||||||
p = grub_strchr (name + len, '/');
|
p = grub_strchr (n, '/');
|
||||||
if (p)
|
if (p)
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
if ((!prev) || (grub_strcmp (prev, name) != 0))
|
if (((!prev) || (grub_strcmp (prev, n) != 0)) && *n != 0)
|
||||||
{
|
{
|
||||||
struct grub_dirhook_info info;
|
struct grub_dirhook_info info;
|
||||||
grub_memset (&info, 0, sizeof (info));
|
grub_memset (&info, 0, sizeof (info));
|
||||||
|
@ -238,19 +546,43 @@ grub_cpio_dir (grub_device_t device, const char *path,
|
||||||
info.mtime = mtime;
|
info.mtime = mtime;
|
||||||
info.mtimeset = 1;
|
info.mtimeset = 1;
|
||||||
|
|
||||||
hook (name + len, &info);
|
if (hook (n, &info))
|
||||||
|
goto fail;
|
||||||
grub_free (prev);
|
grub_free (prev);
|
||||||
prev = name;
|
prev = name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
int restart;
|
||||||
|
err = handle_symlink (data, name, &path, mode, &restart);
|
||||||
grub_free (name);
|
grub_free (name);
|
||||||
|
if (err)
|
||||||
|
goto fail;
|
||||||
|
if (restart)
|
||||||
|
{
|
||||||
|
len = grub_strlen (path);
|
||||||
|
if (++symlinknest == 8)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_SYMLINK_LOOP,
|
||||||
|
"too deep nesting of symlinks");
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
ofs = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
grub_free (name);
|
||||||
data->hofs = ofs;
|
data->hofs = ofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
||||||
|
grub_free (path);
|
||||||
grub_free (prev);
|
grub_free (prev);
|
||||||
|
#ifdef MODE_USTAR
|
||||||
|
grub_free (data->linkname);
|
||||||
|
#endif
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
|
|
||||||
grub_dl_unref (my_mod);
|
grub_dl_unref (my_mod);
|
||||||
|
@ -259,23 +591,33 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_cpio_open (grub_file_t file, const char *name)
|
grub_cpio_open (grub_file_t file, const char *name_in)
|
||||||
{
|
{
|
||||||
struct grub_cpio_data *data;
|
struct grub_cpio_data *data;
|
||||||
grub_uint32_t ofs;
|
grub_disk_addr_t ofs;
|
||||||
char *fn;
|
char *fn;
|
||||||
int i, j;
|
char *name = grub_strdup (name_in + 1);
|
||||||
|
int symlinknest = 0;
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
grub_dl_ref (my_mod);
|
grub_dl_ref (my_mod);
|
||||||
|
|
||||||
data = grub_cpio_mount (file->device->disk);
|
data = grub_cpio_mount (file->device->disk);
|
||||||
if (!data)
|
if (!data)
|
||||||
goto fail;
|
{
|
||||||
|
grub_free (name);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
|
||||||
data->hofs = 0;
|
data->hofs = 0;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (grub_cpio_find_file (data, &fn, NULL, &ofs))
|
grub_uint32_t mode;
|
||||||
|
int restart;
|
||||||
|
|
||||||
|
if (grub_cpio_find_file (data, &fn, NULL, &ofs, &mode))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (!ofs)
|
if (!ofs)
|
||||||
|
@ -284,33 +626,31 @@ grub_cpio_open (grub_file_t file, const char *name)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compare NAME and FN by hand in order to cope with duplicate
|
if (handle_symlink (data, fn, &name, mode, &restart))
|
||||||
slashes. */
|
|
||||||
i = 0;
|
|
||||||
j = 0;
|
|
||||||
while (name[i] == '/')
|
|
||||||
i++;
|
|
||||||
while (1)
|
|
||||||
{
|
{
|
||||||
if (name[i] != fn[j])
|
grub_free (fn);
|
||||||
goto no_match;
|
goto fail;
|
||||||
|
|
||||||
if (name[i] == '\0')
|
|
||||||
break;
|
|
||||||
|
|
||||||
while (name[i] == '/' && name[i+1] == '/')
|
|
||||||
i++;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
j++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name[i] != fn[j])
|
if (restart)
|
||||||
|
{
|
||||||
|
ofs = 0;
|
||||||
|
if (++symlinknest == 8)
|
||||||
|
{
|
||||||
|
grub_error (GRUB_ERR_SYMLINK_LOOP,
|
||||||
|
"too deep nesting of symlinks");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
goto no_match;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grub_strcmp (name, fn) != 0)
|
||||||
goto no_match;
|
goto no_match;
|
||||||
|
|
||||||
file->data = data;
|
file->data = data;
|
||||||
file->size = data->size;
|
file->size = data->size;
|
||||||
grub_free (fn);
|
grub_free (fn);
|
||||||
|
grub_free (name);
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
|
||||||
|
@ -321,8 +661,11 @@ grub_cpio_open (grub_file_t file, const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
#ifdef MODE_USTAR
|
||||||
|
grub_free (data->linkname);
|
||||||
|
#endif
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
|
grub_free (name);
|
||||||
|
|
||||||
grub_dl_unref (my_mod);
|
grub_dl_unref (my_mod);
|
||||||
|
|
||||||
|
@ -342,7 +685,13 @@ grub_cpio_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_cpio_close (grub_file_t file)
|
grub_cpio_close (grub_file_t file)
|
||||||
{
|
{
|
||||||
grub_free (file->data);
|
struct grub_cpio_data *data;
|
||||||
|
|
||||||
|
data = file->data;
|
||||||
|
#ifdef MODE_USTAR
|
||||||
|
grub_free (data->linkname);
|
||||||
|
#endif
|
||||||
|
grub_free (data);
|
||||||
|
|
||||||
grub_dl_unref (my_mod);
|
grub_dl_unref (my_mod);
|
||||||
|
|
||||||
|
@ -352,6 +701,10 @@ grub_cpio_close (grub_file_t file)
|
||||||
static struct grub_fs grub_cpio_fs = {
|
static struct grub_fs grub_cpio_fs = {
|
||||||
#ifdef MODE_USTAR
|
#ifdef MODE_USTAR
|
||||||
.name = "tarfs",
|
.name = "tarfs",
|
||||||
|
#elif defined (MODE_ODC)
|
||||||
|
.name = "odc",
|
||||||
|
#elif defined (MODE_NEWC)
|
||||||
|
.name = "newc",
|
||||||
#else
|
#else
|
||||||
.name = "cpiofs",
|
.name = "cpiofs",
|
||||||
#endif
|
#endif
|
||||||
|
@ -366,6 +719,12 @@ static struct grub_fs grub_cpio_fs = {
|
||||||
|
|
||||||
#ifdef MODE_USTAR
|
#ifdef MODE_USTAR
|
||||||
GRUB_MOD_INIT (tar)
|
GRUB_MOD_INIT (tar)
|
||||||
|
#elif defined (MODE_ODC)
|
||||||
|
GRUB_MOD_INIT (odc)
|
||||||
|
#elif defined (MODE_NEWC)
|
||||||
|
GRUB_MOD_INIT (newc)
|
||||||
|
#elif defined (MODE_BIGENDIAN)
|
||||||
|
GRUB_MOD_INIT (cpio_be)
|
||||||
#else
|
#else
|
||||||
GRUB_MOD_INIT (cpio)
|
GRUB_MOD_INIT (cpio)
|
||||||
#endif
|
#endif
|
||||||
|
@ -376,6 +735,12 @@ GRUB_MOD_INIT (cpio)
|
||||||
|
|
||||||
#ifdef MODE_USTAR
|
#ifdef MODE_USTAR
|
||||||
GRUB_MOD_FINI (tar)
|
GRUB_MOD_FINI (tar)
|
||||||
|
#elif defined (MODE_ODC)
|
||||||
|
GRUB_MOD_FINI (odc)
|
||||||
|
#elif defined (MODE_NEWC)
|
||||||
|
GRUB_MOD_FINI (newc)
|
||||||
|
#elif defined (MODE_BIGENDIAN)
|
||||||
|
GRUB_MOD_FINI (cpio_be)
|
||||||
#else
|
#else
|
||||||
GRUB_MOD_FINI (cpio)
|
GRUB_MOD_FINI (cpio)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
#define MODE_BIGENDIAN 1
|
#define MODE_BIGENDIAN 1
|
||||||
#include "afs.c"
|
#include "cpio.c"
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue