merge mainline into gdb
This commit is contained in:
commit
515e8007fc
465 changed files with 26882 additions and 11400 deletions
|
@ -101,8 +101,7 @@ CLEANFILES += widthspec.h
|
|||
# Install config.h into platformdir
|
||||
platform_HEADERS = config.h
|
||||
|
||||
pkglib_DATA += grub-mkconfig_lib
|
||||
pkglib_DATA += update-grub_lib
|
||||
pkgdata_DATA += grub-mkconfig_lib
|
||||
|
||||
|
||||
if COND_i386_coreboot
|
||||
|
@ -305,7 +304,7 @@ endif
|
|||
|
||||
BOOTCHECKS += bootcheck-kfreebsd-aout
|
||||
|
||||
BOOTCHECKS += bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64
|
||||
#BOOTCHECKS += bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64
|
||||
|
||||
BOOTCHECKS += bootcheck-multiboot bootcheck-multiboot2
|
||||
|
||||
|
|
|
@ -29,12 +29,15 @@ library = {
|
|||
common = grub-core/lib/pbkdf2.c;
|
||||
common = grub-core/commands/extcmd.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 = {
|
||||
name = libgrubmods.a;
|
||||
cflags = '$(CFLAGS_POSIX) -Wno-undef';
|
||||
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(top_srcdir)/grub-core/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
|
||||
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.yy.c;
|
||||
|
@ -53,12 +56,14 @@ library = {
|
|||
common = grub-core/disk/mdraid1x_linux.c;
|
||||
common = grub-core/disk/raid5_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/afs.c;
|
||||
common = grub-core/fs/bfs.c;
|
||||
common = grub-core/fs/btrfs.c;
|
||||
common = grub-core/fs/cpio.c;
|
||||
common = grub-core/fs/cpio_be.c;
|
||||
common = grub-core/fs/odc.c;
|
||||
common = grub-core/fs/newc.c;
|
||||
common = grub-core/fs/ext2.c;
|
||||
common = grub-core/fs/fat.c;
|
||||
common = grub-core/fs/exfat.c;
|
||||
|
@ -100,7 +105,6 @@ library = {
|
|||
common = grub-core/partmap/acorn.c;
|
||||
common = grub-core/partmap/amiga.c;
|
||||
common = grub-core/partmap/apple.c;
|
||||
common = grub-core/partmap/gpt.c;
|
||||
common = grub-core/partmap/msdos.c;
|
||||
common = grub-core/partmap/sun.c;
|
||||
common = grub-core/partmap/plan.c;
|
||||
|
@ -116,6 +120,9 @@ library = {
|
|||
common = grub-core/io/lzopio.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 = {
|
||||
|
@ -135,6 +142,8 @@ program = {
|
|||
|
||||
common = util/grub-mkimage.c;
|
||||
common = util/resolve.c;
|
||||
common = util/argp_common.c;
|
||||
|
||||
extra_dist = util/grub-mkimagexx.c;
|
||||
|
||||
ldadd = libgrubmods.a;
|
||||
|
@ -151,6 +160,7 @@ program = {
|
|||
mansection = 1;
|
||||
|
||||
common = util/grub-mkrelpath.c;
|
||||
common = util/argp_common.c;
|
||||
|
||||
ldadd = libgrubmods.a;
|
||||
ldadd = libgrubgcry.a;
|
||||
|
@ -164,6 +174,7 @@ program = {
|
|||
mansection = 1;
|
||||
|
||||
common = util/grub-script-check.c;
|
||||
common = util/argp_common.c;
|
||||
|
||||
ldadd = libgrubmods.a;
|
||||
ldadd = libgrubgcry.a;
|
||||
|
@ -190,6 +201,7 @@ program = {
|
|||
mansection = 1;
|
||||
|
||||
common = util/grub-mkpasswd-pbkdf2.c;
|
||||
common = util/argp_common.c;
|
||||
|
||||
ldadd = libgrubmods.a;
|
||||
ldadd = libgrubgcry.a;
|
||||
|
@ -259,6 +271,7 @@ program = {
|
|||
mansection = 1;
|
||||
common = util/grub-mkfont.c;
|
||||
common = grub-core/unidata.c;
|
||||
common = util/argp_common.c;
|
||||
|
||||
cflags = '$(freetype_cflags)';
|
||||
|
||||
|
@ -271,30 +284,13 @@ program = {
|
|||
condition = COND_GRUB_MKFONT;
|
||||
};
|
||||
|
||||
program = {
|
||||
name = grub-mkdevicemap;
|
||||
installdir = sbin;
|
||||
mansection = 8;
|
||||
|
||||
common = util/grub-mkdevicemap.c;
|
||||
common = util/deviceiter.c;
|
||||
nosparc64 = util/devicemap.c;
|
||||
|
||||
sparc64_ieee1275 = util/ieee1275/ofpath.c;
|
||||
sparc64_ieee1275 = util/ieee1275/devicemap.c;
|
||||
|
||||
ldadd = libgrubmods.a;
|
||||
ldadd = libgrubgcry.a;
|
||||
ldadd = libgrubkern.a;
|
||||
ldadd = grub-core/gnulib/libgnu.a;
|
||||
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
|
||||
};
|
||||
|
||||
program = {
|
||||
name = grub-probe;
|
||||
installdir = sbin;
|
||||
mansection = 8;
|
||||
common = util/grub-probe.c;
|
||||
common = util/ieee1275/ofpath.c;
|
||||
common = util/argp_common.c;
|
||||
|
||||
ldadd = libgrubmods.a;
|
||||
ldadd = libgrubgcry.a;
|
||||
|
@ -309,6 +305,7 @@ program = {
|
|||
mansection = 8;
|
||||
common = util/grub-setup.c;
|
||||
common = util/lvm.c;
|
||||
common = util/argp_common.c;
|
||||
common = grub-core/lib/reed_solomon.c;
|
||||
|
||||
sparc64_ieee1275 = util/ieee1275/ofpath.c;
|
||||
|
@ -344,6 +341,7 @@ program = {
|
|||
mansection = 1;
|
||||
|
||||
common = util/grub-mklayout.c;
|
||||
common = util/argp_common.c;
|
||||
|
||||
ldadd = libgrubmods.a;
|
||||
ldadd = libgrubgcry.a;
|
||||
|
@ -494,15 +492,10 @@ script = {
|
|||
installdir = noinst;
|
||||
};
|
||||
|
||||
script = {
|
||||
name = update-grub_lib;
|
||||
common = util/update-grub_lib.in;
|
||||
installdir = noinst;
|
||||
};
|
||||
|
||||
script = {
|
||||
name = grub-kbdcomp;
|
||||
common = util/grub-kbdcomp.in;
|
||||
mansection = 1;
|
||||
};
|
||||
|
||||
script = {
|
||||
|
|
|
@ -105,7 +105,7 @@ platformdir = $(pkglibrootdir)/$(target_cpu)-$(platform)
|
|||
CFLAGS_GCRY = -Wno-error -Wno-missing-field-initializers
|
||||
CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap
|
||||
|
||||
CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter
|
||||
CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion -Wno-old-style-definition
|
||||
CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/gnulib -I$(top_srcdir)/grub-core/gnulib
|
||||
|
||||
CFLAGS_POSIX = -fno-builtin
|
||||
|
@ -137,7 +137,7 @@ KERNEL_HEADER_FILES =
|
|||
|
||||
man_MANS =
|
||||
noinst_DATA =
|
||||
pkglib_DATA =
|
||||
pkgdata_DATA =
|
||||
bin_SCRIPTS =
|
||||
sbin_SCRIPTS =
|
||||
bin_PROGRAMS =
|
||||
|
@ -147,11 +147,12 @@ check_SCRIPTS =
|
|||
grubconf_DATA =
|
||||
check_PROGRAMS =
|
||||
noinst_SCRIPTS =
|
||||
pkglib_SCRIPTS =
|
||||
noinst_PROGRAMS =
|
||||
grubconf_SCRIPTS =
|
||||
noinst_LIBRARIES =
|
||||
dist_noinst_DATA =
|
||||
platform_SCRIPTS =
|
||||
platform_PROGRAMS =
|
||||
|
||||
TESTS =
|
||||
EXTRA_DIST =
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
#undef _FILE_OFFSET_BITS
|
||||
#define _LARGEFILE_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#if defined(__PPC__) && !defined(__powerpc__)
|
||||
#define __powerpc__ 1
|
||||
#endif
|
||||
#if defined (GRUB_UTIL) || !defined (GRUB_MACHINE)
|
||||
#include <config-util.h>
|
||||
#define NESTED_FUNC_ATTR
|
||||
|
@ -39,6 +42,11 @@
|
|||
/* Define to 1 to enable disk cache statistics. */
|
||||
#define DISK_CACHE_STATS @DISK_CACHE_STATS@
|
||||
|
||||
#define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@"
|
||||
#define GRUB_PLATFORM "@GRUB_PLATFORM@"
|
||||
|
||||
#define RE_ENABLE_I18N 1
|
||||
|
||||
#if defined(__i386__)
|
||||
#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1)))
|
||||
#else
|
||||
|
|
84
configure.ac
84
configure.ac
|
@ -177,7 +177,7 @@ esac
|
|||
if test x${target_cpu} = xmipsel ; then
|
||||
machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo mips_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`"
|
||||
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
|
||||
|
||||
HOST_CPPFLAGS="$HOST_CPPFLAGS $machine_CPPFLAGS"
|
||||
|
@ -234,7 +234,7 @@ for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do
|
|||
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])
|
||||
fi
|
||||
|
||||
|
@ -298,7 +298,7 @@ fi
|
|||
|
||||
# Check for functions and headers.
|
||||
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
|
||||
#include <sys/param.h>
|
||||
|
@ -373,7 +373,9 @@ LDFLAGS="$TARGET_LDFLAGS"
|
|||
LIBS=""
|
||||
|
||||
# debug flags.
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -Wall -W -Wshadow -Wpointer-arith -Wmissing-prototypes -Wundef -Wstrict-prototypes -g"
|
||||
WARN_FLAGS="-Wall -W -Wshadow -Wold-style-declaration -Wold-style-definition -Wpointer-arith -Wundef -Wextra -Waddress -Warray-bounds -Wattributes -Wbuiltin-macro-redefined -Wcast-align -Wchar-subscripts -Wclobbered -Wcomment -Wcoverage-mismatch -Wdeprecated -Wdeprecated-declarations -Wdisabled-optimization -Wdiv-by-zero -Wempty-body -Wendif-labels -Wfloat-equal -Wformat-contains-nul -Wformat-extra-args -Wformat-security -Wformat-y2k -Wignored-qualifiers -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Winit-self -Wint-to-pointer-cast -Winvalid-pch -Wunsafe-loop-optimizations -Wlogical-op -Wmain -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-noreturn -Wmudflap -Wmultichar -Wnonnull -Woverflow -Wpacked-bitfield-compat -Wparentheses -Wpointer-arith -Wpointer-to-int-cast -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wstack-protector -Wstrict-aliasing -Wswitch -Wsync-nand -Wtrigraphs -Wtype-limits -Wundef -Wuninitialized -Wunknown-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-result -Wunused-value -Wunused-variable -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings -Wmissing-declarations -Wmissing-parameter-type -Wmissing-prototypes -Wnested-externs -Wstrict-prototypes -Wpointer-sign"
|
||||
HOST_CFLAGS="$HOST_CFLAGS $WARN_FLAGS"
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS $WARN_FLAGS -g -Wredundant-decls -Wmissing-prototypes"
|
||||
TARGET_CCASFLAGS="$TARGET_CCASFLAGS -g"
|
||||
|
||||
# Force no alignment to save space on i386.
|
||||
|
@ -477,6 +479,40 @@ case "${host_os}" in
|
|||
esac
|
||||
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
|
||||
# Force 32-bit mode.
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -m32"
|
||||
|
@ -558,11 +594,18 @@ AC_ARG_ENABLE([werror],
|
|||
[do not use -Werror when building GRUB])])
|
||||
if test x"$enable_werror" != xno ; then
|
||||
TARGET_CFLAGS="$TARGET_CFLAGS -Werror"
|
||||
HOST_CFLAGS="$HOST_CFLAGS -Werror"
|
||||
fi
|
||||
|
||||
TARGET_CPP="$TARGET_CC -E"
|
||||
TARGET_CCAS=$TARGET_CC
|
||||
|
||||
GRUB_TARGET_CPU="${target_cpu}"
|
||||
GRUB_PLATFORM="${platform}"
|
||||
|
||||
AC_SUBST(GRUB_TARGET_CPU)
|
||||
AC_SUBST(GRUB_PLATFORM)
|
||||
|
||||
AC_SUBST(OBJCONV)
|
||||
AC_SUBST(TARGET_CPP)
|
||||
AC_SUBST(TARGET_CCAS)
|
||||
|
@ -636,39 +679,6 @@ if test "x$target_cpu" = xi386; then
|
|||
grub_I386_ASM_ADDR32
|
||||
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
|
||||
AC_CACHE_CHECK([whether -nostdinc -isystem works], [grub_cv_cc_isystem], [
|
||||
SAVED_CPPFLAGS="$CPPFLAGS"
|
||||
|
|
|
@ -77,6 +77,7 @@ This edition documents version @value{VERSION}.
|
|||
* Finding your way around::
|
||||
* Coding style::
|
||||
* Contributing Changes::
|
||||
* Porting::
|
||||
* Error Handling::
|
||||
* CIA::
|
||||
* 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
|
||||
(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
|
||||
@chapter Error Handling
|
||||
|
||||
|
|
380
docs/grub.texi
380
docs/grub.texi
|
@ -20,7 +20,7 @@
|
|||
This manual is for GNU GRUB (version @value{VERSION},
|
||||
@value{UPDATED}).
|
||||
|
||||
Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008,2009,2010 Free Software Foundation, Inc.
|
||||
Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008,2009,2010,2011,2012 Free Software Foundation, Inc.
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
|
@ -89,7 +89,10 @@ This edition documents version @value{VERSION}.
|
|||
* Interface:: The menu and the command-line
|
||||
* Environment:: GRUB environment variables
|
||||
* Commands:: The list of available builtin commands
|
||||
* Internationalisation:: Topics relating to language support
|
||||
* Security:: Authentication and authorisation
|
||||
* Platform limitations:: The list of platform-specific limitations
|
||||
* Platform-specific operations:: Platform-specific operations
|
||||
* Supported kernels:: The list of supported kernels
|
||||
* Troubleshooting:: Error messages produced by GRUB
|
||||
* 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
|
||||
Support multiple filesystem types transparently, plus a useful explicit
|
||||
blocklist notation. The currently supported filesystem types are @dfn{Amiga
|
||||
Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS}, @dfn{cpio}, @dfn{Linux
|
||||
ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{HFS}, @dfn{HFS+},
|
||||
@dfn{ISO9660}, @dfn{JFS}, @dfn{Minix fs}, @dfn{nilfs2}, @dfn{NTFS},
|
||||
@dfn{ReiserFS}, @dfn{Amiga Smart FileSystem (SFS)}, @dfn{tar}, @dfn{UDF},
|
||||
@dfn{BSD UFS/UFS2}, and @dfn{XFS}. @xref{Filesystem}, for more information.
|
||||
Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS},
|
||||
@dfn{BtrFS} (including raid0, raid1, raid10, gzip and lzo),
|
||||
@dfn{cpio} (little- and big-endian bin, odc and newc variants),
|
||||
@dfn{Linux ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{exFAT}, @dfn{HFS},
|
||||
@dfn{HFS+}, @dfn{ISO9660} (including Joliet, Rock-ridge and multi-chunk files),
|
||||
@dfn{JFS}, @dfn{Minix fs} (versions 1, 2 and 3), @dfn{nilfs2},
|
||||
@dfn{NTFS} (including compression), @dfn{ReiserFS}, @dfn{ROMFS},
|
||||
@dfn{Amiga Smart FileSystem (SFS)}, @dfn{Squash4}, @dfn{tar}, @dfn{UDF},
|
||||
@dfn{BSD UFS/UFS2}, @dfn{XFS}, and @dfn{ZFS} (including lzjb, gzip,
|
||||
zle, mirror, stripe, raidz1/2/3 and encryption in AES-CCM and AES-GCM).
|
||||
@xref{Filesystem}, for more information.
|
||||
|
||||
@item Support automatic decompression
|
||||
Can decompress files which were compressed by @command{gzip} or
|
||||
|
@ -784,6 +793,7 @@ magic.
|
|||
|
||||
@menu
|
||||
* General boot methods:: How to boot OSes with GRUB generally
|
||||
* Loopback booting:: Notes on booting from loopbacks
|
||||
* OS-specific notes:: Notes on some operating systems
|
||||
@end menu
|
||||
|
||||
|
@ -855,6 +865,31 @@ required. @xref{DOS/Windows}.
|
|||
|
||||
Chain-loading is only supported on PC BIOS and EFI platforms.
|
||||
|
||||
@node Loopback booting
|
||||
@section Loopback booting
|
||||
GRUB is able to read from an image (be it one of CD or HDD) stored on
|
||||
any of its accessible storages (refer to @pxref{loopback} command).
|
||||
However the OS itself should be able to find its root. This usually
|
||||
involves running a userspace program running before the real root
|
||||
is discovered. This is achieved by GRUB loading a specially made
|
||||
small image and passing it as ramdisk to the kernel. This is achieved
|
||||
by commands @command{kfreebsd_module}, @command{knetbsd_module_elf},
|
||||
@command{kopenbsd_ramdisk}, @command{initrd} (@pxref{initrd}),
|
||||
@command{initrd16} (@pxref{initrd}), @command{multiboot_module},
|
||||
@command{multiboot2_module} or @command{xnu_ramdisk}
|
||||
depending on the loader. Note that for knetbsd the image must be put
|
||||
inside miniroot.kmod and the whole miniroot.kmod has to be loaded. In
|
||||
kopenbsd payload this is disabled by default. Aditionally behaviour of
|
||||
initial ramdisk depends on command line options. Several distributors provide
|
||||
the image for this purpose or it's integrated in their standard ramdisk and
|
||||
activated by special option. Consult your kernel and distribution manual for
|
||||
more details. Other loaders like appleloader, chainloader (BIOS, EFI, coreboot),
|
||||
freedos, ntldr and plan9 provide no possibility of loading initial ramdisk and
|
||||
as far as author is aware the payloads in question don't support either initial
|
||||
ramdisk or discovering loopback boot in other way and as such not bootable this
|
||||
way. Please consider alternative boot methods like copying all files
|
||||
from the image to actual partition. Consult your OS documentation for
|
||||
more details
|
||||
|
||||
@node OS-specific notes
|
||||
@section Some caveats on OS-specific issues
|
||||
|
@ -2203,42 +2238,67 @@ you see the files in a device or use the command @command{search}
|
|||
The device syntax is like this:
|
||||
|
||||
@example
|
||||
@code{(@var{device}[,@var{part-num}][,@var{bsd-subpart-letter}])}
|
||||
@code{(@var{device}[,@var{partmap-name1}@var{part-num1}[,@var{partmap-name2}@var{part-num2}[,...]]])}
|
||||
@end example
|
||||
|
||||
@samp{[]} means the parameter is optional. @var{device} should be
|
||||
either @samp{fd} or @samp{hd} followed by a digit, like @samp{fd0}.
|
||||
But you can also set @var{device} to a hexadecimal or a decimal number
|
||||
which is a BIOS drive number, so the following are equivalent:
|
||||
@samp{[]} means the parameter is optional. @var{device} depends on the disk
|
||||
driver in use. BIOS and EFI disks use either @samp{fd} or @samp{hd} followed
|
||||
by a digit, like @samp{fd0}, or @samp{cd}.
|
||||
AHCI, PATA (ata), crypto, USB use the name of driver followed by a number.
|
||||
Memdisk and host are limited to one disk and so it's refered just by driver
|
||||
name.
|
||||
RAID (md), ofdisk (ieee1275), LVM (lv) and arcdisk (arc) use intrinsic name
|
||||
of disk prefixed by driver name. Conflicts are solved by suffixing a number
|
||||
if necessarry. Commas need to be escaped.
|
||||
Loopback uses whatever name specified to @command{loopback} command.
|
||||
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
|
||||
(fd0)
|
||||
(hd0)
|
||||
(0x80)
|
||||
(128)
|
||||
(cd)
|
||||
(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
|
||||
|
||||
@var{part-num} represents the partition number of @var{device}, starting
|
||||
from one for primary partitions and from five for extended partitions,
|
||||
and @var{bsd-subpart-letter} represents the BSD disklabel subpartition,
|
||||
such as @samp{a} or @samp{e}.
|
||||
|
||||
A shortcut for specifying BSD subpartitions is
|
||||
@code{(@var{device},@var{bsd-subpart-letter})}, in this case, GRUB
|
||||
searches for the first PC partition containing a BSD disklabel, then
|
||||
finds the subpartition @var{bsd-subpart-letter}. Here is an example:
|
||||
|
||||
@example
|
||||
(hd0,a)
|
||||
@end example
|
||||
from one. @var{partname} is optional but is recommended since disk may have
|
||||
several top-level partmaps. Specifying third and later component you can access
|
||||
to subpartitions.
|
||||
|
||||
The syntax @samp{(hd0)} represents using the entire disk (or the
|
||||
MBR when installing GRUB), while the syntax @samp{(hd0,1)}
|
||||
represents using the first partition of the disk (or the boot sector
|
||||
of the partition when installing GRUB).
|
||||
|
||||
If you enabled the network support, the special drive @samp{(pxe)} is
|
||||
also available. Before using the network drive, you must initialize the
|
||||
network. @xref{Network}, for more information.
|
||||
@example
|
||||
(hd0,msdos1)
|
||||
(hd0,msdos1,msdos5)
|
||||
(hd0,msdos1,bsd3)
|
||||
(hd0,netbsd1)
|
||||
(hd0,gpt1)
|
||||
(hd0,1,3)
|
||||
@end example
|
||||
|
||||
If you enabled the network support, the special drives @samp{(tftp)},
|
||||
@samp{(http)} and so on ars also available.
|
||||
Before using the network drive, you must initialize the network.
|
||||
@xref{Network}, for more information.
|
||||
|
||||
If you boot GRUB from a CD-ROM, @samp{(cd)} is available. @xref{Making
|
||||
a GRUB bootable CD-ROM}, for details.
|
||||
|
@ -3867,6 +3927,102 @@ Unset the environment variable @var{envvar}.
|
|||
|
||||
This command is not yet implemented for GRUB 2, although it is planned.
|
||||
|
||||
@node Internationalisation
|
||||
@chapter Charset
|
||||
GRUB uses UTF-8 internally other than in rendering where some GRUB-specific
|
||||
appropriate representation is used. All text files (including config) are
|
||||
assumed to be encoded in UTF-8.
|
||||
|
||||
@chapter Filesystems
|
||||
NTFS, JFS, UDF, HFS+, exFAT, long 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)
|
||||
supports any key 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.
|
||||
Moreover all current input consumers are limited to ASCII.
|
||||
|
||||
@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
|
||||
Currently GRUB always uses YEAR-MONTH-DAY HOUR:MINUTE:SECOND [WEEKDAY] 24-hour
|
||||
datetime format but weekdays are translated.
|
||||
GRUB always uses the decimal number format with [0-9] as digits and . as
|
||||
descimal separator and no group separator.
|
||||
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.
|
||||
@command{test} tests <, >, <=, >=, -pgt and -plt compare the strings in the
|
||||
lexicographical order of unicode codepoints, replicating the behaviour of
|
||||
test from coreutils.
|
||||
environment variables and commands are listed in the same order.
|
||||
|
||||
@node Security
|
||||
@chapter Authentication and authorisation
|
||||
|
@ -3935,6 +4091,167 @@ adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2}
|
|||
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
|
||||
@chapter Supported boot targets
|
||||
|
||||
|
@ -3992,7 +4309,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
|
|||
@end multitable
|
||||
|
||||
@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 NTLDR @tab no (1) @tab no (1)
|
||||
@item Plan9 @tab no (1) @tab no (1)
|
||||
|
@ -4018,7 +4335,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
|
|||
@end multitable
|
||||
|
||||
@multitable @columnfractions .50 .22 .22
|
||||
@item @tab IEEE1275
|
||||
@item @tab ia32 IEEE1275
|
||||
@item BIOS chainloading @tab no (1)
|
||||
@item NTLDR @tab no (1)
|
||||
@item Plan9 @tab no (1)
|
||||
|
@ -4052,7 +4369,8 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel
|
|||
@item Requires ACPI
|
||||
@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
|
||||
|
||||
|
|
10
docs/man/grub-kbdcomp.h2m
Normal file
10
docs/man/grub-kbdcomp.h2m
Normal file
|
@ -0,0 +1,10 @@
|
|||
[NAME]
|
||||
grub-kbdcomp \- generate a GRUB keyboard layout file
|
||||
[DESCRIPTION]
|
||||
grub-kbdcomp processes a X keyboard layout description in
|
||||
.BR keymaps (5)
|
||||
format into a format that can be used by GRUB's
|
||||
.B keymap
|
||||
command.
|
||||
[SEE ALSO]
|
||||
.BR grub-mklayout (8)
|
24
gentpl.py
24
gentpl.py
|
@ -1,4 +1,19 @@
|
|||
#! /usr/bin/python
|
||||
# GRUB -- GRand Unified Bootloader
|
||||
# Copyright (C) 2010,2011 Free Software Foundation, Inc.
|
||||
#
|
||||
# GRUB is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# GRUB is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#
|
||||
# This is the python script used to generate Makefile.tpl
|
||||
|
@ -47,7 +62,6 @@ GROUPS["terminfomodule"] = GRUB_PLATFORMS[:];
|
|||
for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i)
|
||||
|
||||
# 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["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc")
|
||||
|
||||
|
@ -356,7 +370,7 @@ def first_time(snippet):
|
|||
def module(platform):
|
||||
r = set_canonical_name_suffix(".module")
|
||||
|
||||
r += gvar_add("noinst_PROGRAMS", "[+ name +].module")
|
||||
r += gvar_add("platform_PROGRAMS", "[+ name +].module")
|
||||
r += gvar_add("MODULE_FILES", "[+ name +].module$(EXEEXT)")
|
||||
|
||||
r += var_set(cname() + "_SOURCES", platform_sources(platform) + " ## platform sources")
|
||||
|
@ -384,7 +398,7 @@ def module(platform):
|
|||
|
||||
def kernel(platform):
|
||||
r = set_canonical_name_suffix(".exec")
|
||||
r += gvar_add("noinst_PROGRAMS", "[+ name +].exec")
|
||||
r += gvar_add("platform_PROGRAMS", "[+ name +].exec")
|
||||
r += var_set(cname() + "_SOURCES", platform_startup(platform))
|
||||
r += var_add(cname() + "_SOURCES", platform_sources(platform))
|
||||
r += var_set("nodist_" + cname() + "_SOURCES", platform_nodist_sources(platform) + " ## platform nodist sources")
|
||||
|
@ -409,7 +423,7 @@ def kernel(platform):
|
|||
|
||||
def image(platform):
|
||||
r = set_canonical_name_suffix(".image")
|
||||
r += gvar_add("noinst_PROGRAMS", "[+ name +].image")
|
||||
r += gvar_add("platform_PROGRAMS", "[+ name +].image")
|
||||
r += var_set(cname() + "_SOURCES", platform_sources(platform))
|
||||
r += var_set("nodist_" + cname() + "_SOURCES", platform_nodist_sources(platform) + "## platform nodist sources")
|
||||
r += var_set(cname() + "_LDADD", platform_ldadd(platform))
|
||||
|
@ -466,7 +480,7 @@ def manpage():
|
|||
r += gvar_add("man_MANS", "[+ name +].[+ mansection +]\n")
|
||||
r += rule("[+ name +].[+ mansection +]", "[+ name +]", """
|
||||
chmod a+x [+ name +]
|
||||
PATH=$(builddir):$$PATH $(HELP2MAN) --section=[+ mansection +] -i $(top_srcdir)/docs/man/[+ name +].h2m -o $@ [+ name +]
|
||||
PATH=$(builddir):$$PATH pkgdatadir=$(builddir) $(HELP2MAN) --section=[+ mansection +] -i $(top_srcdir)/docs/man/[+ name +].h2m -o $@ [+ name +]
|
||||
""")
|
||||
r += gvar_add("CLEANFILES", "[+ name +].[+ mansection +]")
|
||||
r += "endif\n"
|
||||
|
|
|
@ -19,13 +19,13 @@ script = {
|
|||
};
|
||||
|
||||
script = {
|
||||
installdir = noinst;
|
||||
installdir = platform;
|
||||
name = gmodule.pl;
|
||||
common = gmodule.pl.in;
|
||||
};
|
||||
|
||||
script = {
|
||||
installdir = noinst;
|
||||
installdir = platform;
|
||||
name = gdb_grub;
|
||||
common = gdb_grub.in;
|
||||
};
|
||||
|
@ -113,7 +113,7 @@ kernel = {
|
|||
ieee1275 = kern/ieee1275/ieee1275.c;
|
||||
ieee1275 = kern/ieee1275/mmap.c;
|
||||
ieee1275 = kern/ieee1275/openfw.c;
|
||||
ieee1275 = term/ieee1275/ofconsole.c;
|
||||
ieee1275 = term/ieee1275/console.c;
|
||||
ieee1275 = kern/ieee1275/init.c;
|
||||
|
||||
terminfoinkernel = term/terminfo.c;
|
||||
|
@ -207,7 +207,6 @@ kernel = {
|
|||
emu = gnulib/progname.c;
|
||||
emu = gnulib/error.c;
|
||||
emu = kern/emu/cache_s.S;
|
||||
emu = kern/emu/console.c;
|
||||
emu = kern/emu/hostdisk.c;
|
||||
emu = kern/emu/hostfs.c;
|
||||
emu = kern/emu/main.c;
|
||||
|
@ -215,6 +214,7 @@ kernel = {
|
|||
emu = kern/emu/mm.c;
|
||||
emu = kern/emu/time.c;
|
||||
emu = kern/emu/cache.c;
|
||||
emu = term/emu/console.c;
|
||||
|
||||
videoinkernel = term/gfxterm.c;
|
||||
videoinkernel = font/font.c;
|
||||
|
@ -348,7 +348,7 @@ image = {
|
|||
mips_qemu_mips_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000';
|
||||
mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x8bc00000';
|
||||
ldadd = '-lgcc';
|
||||
cflags = '-static-libgcc';
|
||||
cflags = '-Wno-unreachable-code -static-libgcc';
|
||||
enable = mips;
|
||||
};
|
||||
|
||||
|
@ -373,7 +373,7 @@ image = {
|
|||
i386_pc = boot/i386/pc/startup_raw.S;
|
||||
|
||||
objcopyflags = '-O binary';
|
||||
ldflags = '-Wl,-Ttext,0x8200';
|
||||
ldflags = '$(TARGET_IMG_LDFLAGS) -Wl,-Ttext,0x8200';
|
||||
enable = i386_pc;
|
||||
};
|
||||
|
||||
|
@ -462,6 +462,12 @@ module = {
|
|||
enable = pci;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = ehci;
|
||||
common = bus/usb/ehci.c;
|
||||
enable = pci;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = pci;
|
||||
common = bus/pci.c;
|
||||
|
@ -792,7 +798,7 @@ module = {
|
|||
module = {
|
||||
name = setpci;
|
||||
common = commands/setpci.c;
|
||||
enable = x86;
|
||||
enable = pci;
|
||||
};
|
||||
|
||||
module = {
|
||||
|
@ -874,6 +880,11 @@ module = {
|
|||
common = disk/lvm.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = ldm;
|
||||
common = disk/ldm.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = mdraid09;
|
||||
common = disk/mdraid_linux.c;
|
||||
|
@ -885,8 +896,8 @@ module = {
|
|||
};
|
||||
|
||||
module = {
|
||||
name = raid;
|
||||
common = disk/raid.c;
|
||||
name = diskfilter;
|
||||
common = disk/diskfilter.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
|
@ -1014,6 +1025,21 @@ module = {
|
|||
common = fs/cpio.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = cpio_be;
|
||||
common = fs/cpio_be.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = newc;
|
||||
common = fs/newc.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = odc;
|
||||
common = fs/odc.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = ext2;
|
||||
common = fs/ext2.c;
|
||||
|
@ -1102,6 +1128,8 @@ module = {
|
|||
module = {
|
||||
name = squash4;
|
||||
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 = {
|
||||
|
@ -1303,6 +1331,12 @@ module = {
|
|||
enable = i386_pc;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = pxechain;
|
||||
i386_pc = loader/i386/pc/pxechainloader.c;
|
||||
enable = i386_pc;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = multiboot2;
|
||||
cppflags = "-DGRUB_USE_MULTIBOOT2";
|
||||
|
@ -1418,7 +1452,7 @@ module = {
|
|||
extra_dist = script/yylex.l;
|
||||
extra_dist = script/parser.y;
|
||||
|
||||
cflags = '$(CFLAGS_POSIX)';
|
||||
cflags = '$(CFLAGS_POSIX) -Wno-redundant-decls';
|
||||
cppflags = '$(CPPFLAGS_POSIX)';
|
||||
};
|
||||
|
||||
|
@ -1642,9 +1676,13 @@ module = {
|
|||
module = {
|
||||
name = net;
|
||||
common = net/net.c;
|
||||
common = net/dns.c;
|
||||
common = net/bootp.c;
|
||||
common = net/ip.c;
|
||||
common = net/udp.c;
|
||||
common = net/tcp.c;
|
||||
common = net/icmp.c;
|
||||
common = net/icmp6.c;
|
||||
common = net/ethernet.c;
|
||||
common = net/arp.c;
|
||||
common = net/netbuff.c;
|
||||
|
@ -1655,6 +1693,11 @@ module = {
|
|||
common = net/tftp.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = http;
|
||||
common = net/http.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = ofnet;
|
||||
common = net/drivers/ieee1275/ofnet.c;
|
||||
|
@ -1694,13 +1737,14 @@ module = {
|
|||
common = lib/xzembed/xz_dec_lzma2.c;
|
||||
common = lib/xzembed/xz_dec_stream.c;
|
||||
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed';
|
||||
cflags='-Wno-unreachable-code';
|
||||
};
|
||||
|
||||
module = {
|
||||
name = lzopio;
|
||||
common = io/lzopio.c;
|
||||
common = lib/minilzo/minilzo.c;
|
||||
cflags = '$(CFLAGS_POSIX) -Wno-undef';
|
||||
cflags = '$(CFLAGS_POSIX) -Wno-undef -Wno-redundant-decls -Wno-error';
|
||||
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
|
||||
};
|
||||
|
||||
|
@ -1727,6 +1771,11 @@ module = {
|
|||
enable = videomodules;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = priority_queue;
|
||||
common = lib/priority_queue.c;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = time;
|
||||
common = commands/time.c;
|
||||
|
|
|
@ -177,20 +177,21 @@ real_code_2:
|
|||
pushw %es
|
||||
popw %ds
|
||||
|
||||
#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200
|
||||
movl $0x200, %ecx
|
||||
addl %ecx, %esi
|
||||
#else
|
||||
movl $(GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4), %ecx
|
||||
movl $0x1000, %ecx
|
||||
addl $0x200, %esi
|
||||
#endif
|
||||
movl $DATA_ADDR, %edi
|
||||
|
||||
call LOCAL(move_memory)
|
||||
|
||||
/* 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
|
||||
addl $4, %edi
|
||||
cmpl $(DATA_ADDR + 0x1000), %edi
|
||||
jne 3b
|
||||
|
||||
movl (ramdisk_image - start), %esi
|
||||
movl (ramdisk_size - start), %ecx
|
||||
|
@ -199,8 +200,9 @@ real_code_2:
|
|||
|
||||
1:
|
||||
|
||||
movl $(DATA_ADDR + 0x1000), %edi
|
||||
movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx
|
||||
addl $((0x9000 - 0x8200) - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx
|
||||
addl $GRUB_DECOMPRESSOR_I386_PC_MAX_DECOMPRESSOR_SIZE, %ecx
|
||||
|
||||
2:
|
||||
call LOCAL(move_memory)
|
||||
|
|
|
@ -60,11 +60,13 @@ LOCAL(uncompressed_size):
|
|||
. = _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):
|
||||
|
@ -99,94 +101,23 @@ LOCAL (codestart):
|
|||
.code32
|
||||
|
||||
incl %eax
|
||||
cld
|
||||
call grub_gate_a20
|
||||
|
||||
movl LOCAL(compressed_size), %edx
|
||||
addl $(LOCAL(decompressor_end) - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART - _start), %edx
|
||||
addl $(LOCAL(decompressor_end) - LOCAL(reed_solomon_part)), %edx
|
||||
movl reed_solomon_redundancy, %ecx
|
||||
leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax
|
||||
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
|
||||
|
||||
. = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART
|
||||
/*
|
||||
* Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself).
|
||||
* This uses the a.out kludge to load raw binary to the area starting at 1MB,
|
||||
* and relocates itself after loaded.
|
||||
*/
|
||||
.p2align 2 /* force 4-byte alignment */
|
||||
multiboot_header:
|
||||
/* magic */
|
||||
.long 0x1BADB002
|
||||
/* flags */
|
||||
.long (1 << 16)
|
||||
/* checksum */
|
||||
.long -0x1BADB002 - (1 << 16)
|
||||
/* header addr */
|
||||
.long multiboot_header - _start + 0x100000 + 0x200
|
||||
/* load addr */
|
||||
.long 0x100000
|
||||
/* load end addr */
|
||||
.long 0
|
||||
/* bss end addr */
|
||||
.long 0
|
||||
/* entry addr */
|
||||
.long multiboot_entry - _start + 0x100000 + 0x200
|
||||
|
||||
multiboot_entry:
|
||||
.code32
|
||||
/* obtain the boot device */
|
||||
movl 12(%ebx), %edx
|
||||
|
||||
movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp
|
||||
movl %ebp, %esp
|
||||
|
||||
/* relocate the code */
|
||||
movl $(LOCAL(decompressor_end) + 0x200), %ecx
|
||||
addl LOCAL(compressed_size) - _start + 0x100000 + 0x200, %ecx
|
||||
movl $0x100000, %esi
|
||||
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi
|
||||
cld
|
||||
rep
|
||||
movsb
|
||||
/* jump to the real address */
|
||||
movl $multiboot_trampoline, %eax
|
||||
jmp *%eax
|
||||
|
||||
multiboot_trampoline:
|
||||
/* fill the boot information */
|
||||
movl %edx, LOCAL(boot_dev)
|
||||
shrl $24, %edx
|
||||
/* enter the usual booting */
|
||||
call prot_to_real
|
||||
.code16
|
||||
jmp LOCAL (codestart)
|
||||
.code32
|
||||
|
||||
post_reed_solomon:
|
||||
|
||||
#ifdef ENABLE_LZMA
|
||||
movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi
|
||||
movl $LOCAL(decompressor_end), %esi
|
||||
pushl %edi
|
||||
movl LOCAL (uncompressed_size), %ecx
|
||||
leal (%edi, %ecx), %ebx
|
||||
call _LzmaDecodeA
|
||||
/* _LzmaDecodeA clears DF, so no need to run cld */
|
||||
popl %esi
|
||||
#endif
|
||||
|
||||
movl LOCAL(boot_dev), %edx
|
||||
movl $prot_to_real, %edi
|
||||
movl $real_to_prot, %ecx
|
||||
jmp *%esi
|
||||
|
||||
#include "../../../kern/i386/realmode.S"
|
||||
|
||||
/*
|
||||
* grub_gate_a20(int on)
|
||||
*
|
||||
|
@ -337,10 +268,87 @@ gate_a20_check_state:
|
|||
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 2
|
||||
.p2align 4
|
||||
|
||||
LOCAL(decompressor_end):
|
||||
|
|
|
@ -97,8 +97,6 @@ grub_cs5536_smbus_wait (grub_port_t smbbase)
|
|||
if (grub_get_time_ms () > start + 40)
|
||||
return grub_error (GRUB_ERR_IO, "SM stalled");
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
|
|
|
@ -36,6 +36,16 @@ grub_memalign_dma32 (grub_size_t align, grub_size_t size)
|
|||
align = 64;
|
||||
size = ALIGN_UP (size, align);
|
||||
ret = grub_memalign (align, size);
|
||||
#if GRUB_CPU_SIZEOF_VOID_P == 8
|
||||
if ((grub_addr_t) ret >> 32)
|
||||
{
|
||||
/* Shouldn't happend since the only platform in this case is
|
||||
x86_64-efi and it skips any regions > 4GiB because
|
||||
of EFI bugs anyway. */
|
||||
grub_error (GRUB_ERR_BUG, "allocation outside 32-bit range");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (!ret)
|
||||
return 0;
|
||||
grub_arch_sync_dma_caches (ret, size);
|
||||
|
|
1856
grub-core/bus/usb/ehci.c
Normal file
1856
grub-core/bus/usb/ehci.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -294,13 +294,15 @@ grub_ohci_pci_iter (grub_pci_device_t dev,
|
|||
o->hcca_chunk, o->hcca, o->hcca_addr);
|
||||
|
||||
/* Reserve memory for ctrl EDs. */
|
||||
o->ed_ctrl_chunk = grub_memalign_dma32 (16, sizeof(struct grub_ohci_ed)*GRUB_OHCI_CTRL_EDS);
|
||||
o->ed_ctrl_chunk = grub_memalign_dma32 (16, sizeof(struct grub_ohci_ed)
|
||||
* GRUB_OHCI_CTRL_EDS);
|
||||
if (! o->ed_ctrl_chunk)
|
||||
goto fail;
|
||||
o->ed_ctrl = grub_dma_get_virt (o->ed_ctrl_chunk);
|
||||
o->ed_ctrl_addr = grub_dma_get_phys (o->ed_ctrl_chunk);
|
||||
/* Preset EDs */
|
||||
grub_memset ((void*)o->ed_ctrl, 0, sizeof(struct grub_ohci_ed) * GRUB_OHCI_CTRL_EDS);
|
||||
grub_memset ((void *) o->ed_ctrl, 0, sizeof (struct grub_ohci_ed)
|
||||
* GRUB_OHCI_CTRL_EDS);
|
||||
for (j=0; j < GRUB_OHCI_CTRL_EDS; j++)
|
||||
o->ed_ctrl[j].target = grub_cpu_to_le32 (1 << 14); /* skip */
|
||||
|
||||
|
@ -308,7 +310,8 @@ grub_ohci_pci_iter (grub_pci_device_t dev,
|
|||
o->ed_ctrl_chunk, o->ed_ctrl, o->ed_ctrl_addr);
|
||||
|
||||
/* Reserve memory for bulk EDs. */
|
||||
o->ed_bulk_chunk = grub_memalign_dma32 (16, sizeof(struct grub_ohci_ed)*GRUB_OHCI_BULK_EDS);
|
||||
o->ed_bulk_chunk = grub_memalign_dma32 (16, sizeof (struct grub_ohci_ed)
|
||||
* GRUB_OHCI_BULK_EDS);
|
||||
if (! o->ed_bulk_chunk)
|
||||
goto fail;
|
||||
o->ed_bulk = grub_dma_get_virt (o->ed_bulk_chunk);
|
||||
|
@ -1152,8 +1155,8 @@ grub_ohci_check_transfer (grub_usb_controller_t dev,
|
|||
return parse_halt (dev, transfer, actual);
|
||||
|
||||
/* Finished ED detection */
|
||||
if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf) ==
|
||||
(grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf) ) /* Empty ED */
|
||||
if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xfU) ==
|
||||
(grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xfU) ) /* Empty ED */
|
||||
{
|
||||
/* Check the HALT bit */
|
||||
/* It looks like nonsense - it was tested previously...
|
||||
|
@ -1426,7 +1429,7 @@ static struct grub_usb_controller_dev usb_controller =
|
|||
.detect_dev = grub_ohci_detect_dev
|
||||
};
|
||||
|
||||
static void *fini_hnd;
|
||||
static struct grub_preboot *fini_hnd;
|
||||
|
||||
GRUB_MOD_INIT(ohci)
|
||||
{
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/usb.h>
|
||||
#include <grub/usbserial.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -137,19 +138,23 @@ ftdi_hw_configure (struct grub_serial_port *port,
|
|||
|
||||
divisor = get_divisor (config->speed);
|
||||
if (divisor == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("unsupported serial port speed"));
|
||||
|
||||
if (config->parity != GRUB_SERIAL_PARITY_NONE
|
||||
&& config->parity != GRUB_SERIAL_PARITY_ODD
|
||||
&& config->parity != GRUB_SERIAL_PARITY_EVEN)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported parity");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("unsupported serial port parity"));
|
||||
|
||||
if (config->stop_bits != GRUB_SERIAL_STOP_BITS_1
|
||||
&& config->stop_bits != GRUB_SERIAL_STOP_BITS_2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported stop bits");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("unsupported serial port stop bits number"));
|
||||
|
||||
if (config->word_len < 5 || config->word_len > 8)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported word length");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("unsupported serial port word length"));
|
||||
|
||||
port->config = *config;
|
||||
port->configured = 0;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/usb.h>
|
||||
#include <grub/usbserial.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -150,19 +151,23 @@ pl2303_hw_configure (struct grub_serial_port *port,
|
|||
struct grub_serial_config *config)
|
||||
{
|
||||
if (!is_speed_supported (config->speed))
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("unsupported serial port speed"));
|
||||
|
||||
if (config->parity != GRUB_SERIAL_PARITY_NONE
|
||||
&& config->parity != GRUB_SERIAL_PARITY_ODD
|
||||
&& config->parity != GRUB_SERIAL_PARITY_EVEN)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported parity");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("unsupported serial port parity"));
|
||||
|
||||
if (config->stop_bits != GRUB_SERIAL_STOP_BITS_1
|
||||
&& config->stop_bits != GRUB_SERIAL_STOP_BITS_2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported stop bits");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("unsupported serial port stop bits number"));
|
||||
|
||||
if (config->word_len < 5 || config->word_len > 8)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported word length");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("unsupported serial port word length"));
|
||||
|
||||
port->config = *config;
|
||||
port->configured = 0;
|
||||
|
|
|
@ -23,8 +23,9 @@
|
|||
#include <grub/usb.h>
|
||||
#include <grub/usbtrans.h>
|
||||
#include <grub/pci.h>
|
||||
#include <grub/i386/io.h>
|
||||
#include <grub/cpu/io.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/cpu/pci.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -125,13 +126,19 @@ typedef volatile struct grub_uhci_qh *grub_uhci_qh_t;
|
|||
struct grub_uhci
|
||||
{
|
||||
int iobase;
|
||||
grub_uint32_t *framelist;
|
||||
volatile grub_uint32_t *framelist_virt;
|
||||
grub_uint32_t framelist_phys;
|
||||
struct grub_pci_dma_chunk *framelist_chunk;
|
||||
|
||||
/* N_QH Queue Heads. */
|
||||
grub_uhci_qh_t qh;
|
||||
struct grub_pci_dma_chunk *qh_chunk;
|
||||
volatile grub_uhci_qh_t qh_virt;
|
||||
grub_uint32_t qh_phys;
|
||||
|
||||
/* N_TD Transfer Descriptors. */
|
||||
grub_uhci_td_t td;
|
||||
struct grub_pci_dma_chunk *td_chunk;
|
||||
volatile grub_uhci_td_t td_virt;
|
||||
grub_uint32_t td_phys;
|
||||
|
||||
/* Free Transfer Descriptors. */
|
||||
grub_uhci_td_t tdfree;
|
||||
|
@ -236,90 +243,71 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
|||
grub_uhci_readreg16(u, GRUB_UHCI_REG_USBCMD);
|
||||
|
||||
/* Reserve a page for the frame list. */
|
||||
u->framelist = grub_memalign (4096, 4096);
|
||||
if (! u->framelist)
|
||||
u->framelist_chunk = grub_memalign_dma32 (4096, 4096);
|
||||
if (! u->framelist_chunk)
|
||||
goto fail;
|
||||
u->framelist_virt = grub_dma_get_virt (u->framelist_chunk);
|
||||
u->framelist_phys = grub_dma_get_phys (u->framelist_chunk);
|
||||
|
||||
grub_dprintf ("uhci", "class=0x%02x 0x%02x interface 0x%02x base=0x%x framelist=%p\n",
|
||||
class, subclass, interf, u->iobase, u->framelist);
|
||||
|
||||
/* The framelist pointer of UHCI is only 32 bits, make sure this
|
||||
code works on on 64 bits architectures. */
|
||||
#if GRUB_CPU_SIZEOF_VOID_P == 8
|
||||
if ((grub_uint64_t) u->framelist >> 32)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"allocated frame list memory not <4GB");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
grub_dprintf ("uhci",
|
||||
"class=0x%02x 0x%02x interface 0x%02x base=0x%x framelist=%p\n",
|
||||
class, subclass, interf, u->iobase, u->framelist_virt);
|
||||
|
||||
/* The QH pointer of UHCI is only 32 bits, make sure this
|
||||
code works on on 64 bits architectures. */
|
||||
u->qh = (grub_uhci_qh_t) grub_memalign (4096, sizeof(struct grub_uhci_qh)*N_QH);
|
||||
if (! u->qh)
|
||||
u->qh_chunk = grub_memalign_dma32 (4096, sizeof(struct grub_uhci_qh) * N_QH);
|
||||
if (! u->qh_chunk)
|
||||
goto fail;
|
||||
|
||||
#if GRUB_CPU_SIZEOF_VOID_P == 8
|
||||
if ((grub_uint64_t) u->qh >> 32)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, "allocated QH memory not <4GB");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
u->qh_virt = grub_dma_get_virt (u->qh_chunk);
|
||||
u->qh_phys = grub_dma_get_phys (u->qh_chunk);
|
||||
|
||||
/* The TD pointer of UHCI is only 32 bits, make sure this
|
||||
code works on on 64 bits architectures. */
|
||||
u->td = (grub_uhci_td_t) grub_memalign (4096, sizeof(struct grub_uhci_td)*N_TD);
|
||||
if (! u->td)
|
||||
u->td_chunk = grub_memalign_dma32 (4096, sizeof(struct grub_uhci_td) * N_TD);
|
||||
if (! u->td_chunk)
|
||||
goto fail;
|
||||
|
||||
#if GRUB_CPU_SIZEOF_VOID_P == 8
|
||||
if ((grub_uint64_t) u->td >> 32)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, "allocated TD memory not <4GB");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
u->td_virt = grub_dma_get_virt (u->td_chunk);
|
||||
u->td_phys = grub_dma_get_phys (u->td_chunk);
|
||||
|
||||
grub_dprintf ("uhci", "QH=%p, TD=%p\n",
|
||||
u->qh, u->td);
|
||||
u->qh_virt, u->td_virt);
|
||||
|
||||
/* Link all Transfer Descriptors in a list of available Transfer
|
||||
Descriptors. */
|
||||
for (i = 0; i < N_TD; i++)
|
||||
u->td[i].linkptr = (grub_uint32_t) (grub_addr_t) &u->td[i + 1];
|
||||
u->td[N_TD - 2].linkptr = 0;
|
||||
u->tdfree = u->td;
|
||||
u->td_virt[i].linkptr = u->td_phys + (i + 1) * sizeof(struct grub_uhci_td);
|
||||
u->td_virt[N_TD - 2].linkptr = 0;
|
||||
u->tdfree = u->td_virt;
|
||||
|
||||
/* Setup the frame list pointers. Since no isochronous transfers
|
||||
are and will be supported, they all point to the (same!) queue
|
||||
head. */
|
||||
fp = (grub_uint32_t) (grub_addr_t) u->qh & (~15);
|
||||
fp = u->qh_phys & (~15);
|
||||
/* Mark this as a queue head. */
|
||||
fp |= 2;
|
||||
for (i = 0; i < 1024; i++)
|
||||
u->framelist[i] = fp;
|
||||
u->framelist_virt[i] = fp;
|
||||
/* Program the framelist address into the UHCI controller. */
|
||||
grub_uhci_writereg32 (u, GRUB_UHCI_REG_FLBASEADD,
|
||||
(grub_uint32_t) (grub_addr_t) u->framelist);
|
||||
grub_uhci_writereg32 (u, GRUB_UHCI_REG_FLBASEADD, u->framelist_phys);
|
||||
|
||||
/* Make the Queue Heads point to each other. */
|
||||
for (i = 0; i < N_QH; i++)
|
||||
{
|
||||
/* Point to the next QH. */
|
||||
u->qh[i].linkptr = (grub_uint32_t) (grub_addr_t) (&u->qh[i + 1]) & (~15);
|
||||
u->qh_virt[i].linkptr = ((u->qh_phys
|
||||
+ (i + 1) * sizeof(struct grub_uhci_qh))
|
||||
& (~15));
|
||||
|
||||
/* This is a QH. */
|
||||
u->qh[i].linkptr |= GRUB_UHCI_LINK_QUEUE_HEAD;
|
||||
u->qh_virt[i].linkptr |= GRUB_UHCI_LINK_QUEUE_HEAD;
|
||||
|
||||
/* For the moment, do not point to a Transfer Descriptor. These
|
||||
are set at transfer time, so just terminate it. */
|
||||
u->qh[i].elinkptr = 1;
|
||||
u->qh_virt[i].elinkptr = 1;
|
||||
}
|
||||
|
||||
/* The last Queue Head should terminate. */
|
||||
u->qh[N_QH - 1].linkptr = 1;
|
||||
u->qh_virt[N_QH - 1].linkptr = 1;
|
||||
|
||||
/* Enable UHCI again. */
|
||||
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD,
|
||||
|
@ -352,8 +340,8 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
|||
fail:
|
||||
if (u)
|
||||
{
|
||||
grub_free ((void *) u->qh);
|
||||
grub_free (u->framelist);
|
||||
grub_dma_free (u->qh_chunk);
|
||||
grub_dma_free (u->framelist_chunk);
|
||||
}
|
||||
grub_free (u);
|
||||
|
||||
|
@ -376,7 +364,7 @@ grub_alloc_td (struct grub_uhci *u)
|
|||
return NULL;
|
||||
|
||||
ret = u->tdfree;
|
||||
u->tdfree = (grub_uhci_td_t) (grub_addr_t) u->tdfree->linkptr;
|
||||
u->tdfree = grub_dma_phys2virt (u->tdfree->linkptr, u->td_chunk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -384,7 +372,7 @@ grub_alloc_td (struct grub_uhci *u)
|
|||
static void
|
||||
grub_free_td (struct grub_uhci *u, grub_uhci_td_t td)
|
||||
{
|
||||
td->linkptr = (grub_uint32_t) (grub_addr_t) u->tdfree;
|
||||
td->linkptr = grub_dma_virt2phys (u->tdfree, u->td_chunk);
|
||||
u->tdfree = td;
|
||||
}
|
||||
|
||||
|
@ -394,7 +382,7 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td,
|
|||
{
|
||||
int i; /* Index of TD in transfer */
|
||||
|
||||
u->qh_busy[qh - u->qh] = 0;
|
||||
u->qh_busy[qh - u->qh_virt] = 0;
|
||||
|
||||
*actual = 0;
|
||||
|
||||
|
@ -411,7 +399,7 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td,
|
|||
|
||||
/* Unlink the queue. */
|
||||
tdprev = td;
|
||||
td = (grub_uhci_td_t) (grub_addr_t) td->linkptr2;
|
||||
td = grub_dma_phys2virt (td->linkptr2, u->td_chunk);
|
||||
|
||||
/* Free the TD. */
|
||||
grub_free_td (u, tdprev);
|
||||
|
@ -439,7 +427,7 @@ grub_alloc_qh (struct grub_uhci *u,
|
|||
if (!u->qh_busy[i])
|
||||
break;
|
||||
}
|
||||
qh = &u->qh[i];
|
||||
qh = &u->qh_virt[i];
|
||||
if (i == N_QH)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
|
@ -447,7 +435,7 @@ grub_alloc_qh (struct grub_uhci *u,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
u->qh_busy[qh - u->qh] = 1;
|
||||
u->qh_busy[qh - u->qh_virt] = 1;
|
||||
|
||||
return qh;
|
||||
}
|
||||
|
@ -561,8 +549,8 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev,
|
|||
cdata->td_first = td;
|
||||
else
|
||||
{
|
||||
td_prev->linkptr2 = (grub_uint32_t) (grub_addr_t) td;
|
||||
td_prev->linkptr = (grub_uint32_t) (grub_addr_t) td;
|
||||
td_prev->linkptr2 = grub_dma_virt2phys (td, u->td_chunk);
|
||||
td_prev->linkptr = grub_dma_virt2phys (td, u->td_chunk);
|
||||
td_prev->linkptr |= 4;
|
||||
}
|
||||
td_prev = td;
|
||||
|
@ -574,7 +562,7 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev,
|
|||
|
||||
/* Link it into the queue and terminate. Now the transaction can
|
||||
take place. */
|
||||
cdata->qh->elinkptr = (grub_uint32_t) (grub_addr_t) cdata->td_first;
|
||||
cdata->qh->elinkptr = grub_dma_virt2phys (cdata->td_first, u->td_chunk);
|
||||
|
||||
grub_dprintf ("uhci", "initiate transaction\n");
|
||||
|
||||
|
@ -594,7 +582,7 @@ grub_uhci_check_transfer (grub_usb_controller_t dev,
|
|||
|
||||
*actual = 0;
|
||||
|
||||
errtd = (grub_uhci_td_t) (grub_addr_t) (cdata->qh->elinkptr & ~0x0f);
|
||||
errtd = grub_dma_phys2virt (cdata->qh->elinkptr & ~0x0f, u->qh_chunk);
|
||||
|
||||
grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n",
|
||||
errtd->ctrl_status, errtd->buffer & (~15), errtd);
|
||||
|
|
|
@ -340,7 +340,7 @@ grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc)
|
|||
void
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -44,7 +44,9 @@ static struct grub_usb_hub *hubs;
|
|||
/* Add a device that currently has device number 0 and resides on
|
||||
CONTROLLER, the Hub reported that the device speed is SPEED. */
|
||||
static grub_usb_device_t
|
||||
grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed)
|
||||
grub_usb_hub_add_dev (grub_usb_controller_t controller,
|
||||
grub_usb_speed_t speed,
|
||||
int port, int hubaddr)
|
||||
{
|
||||
grub_usb_device_t dev;
|
||||
int i;
|
||||
|
@ -56,6 +58,8 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed)
|
|||
|
||||
dev->controller = *controller;
|
||||
dev->speed = speed;
|
||||
dev->port = port;
|
||||
dev->hubaddr = hubaddr;
|
||||
|
||||
err = grub_usb_device_initialize (dev);
|
||||
if (err)
|
||||
|
@ -97,6 +101,11 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed)
|
|||
dev->initialized = 1;
|
||||
grub_usb_devs[i] = dev;
|
||||
|
||||
grub_dprintf ("usb", "Added new usb device: %p, addr=%d\n",
|
||||
dev, i);
|
||||
grub_dprintf ("usb", "speed=%d, port=%d, hubaddr=%d\n",
|
||||
speed, port, hubaddr);
|
||||
|
||||
/* Wait "recovery interval", spec. says 2ms */
|
||||
grub_millisleep (2);
|
||||
|
||||
|
@ -158,11 +167,13 @@ grub_usb_add_hub (grub_usb_device_t dev)
|
|||
if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp)
|
||||
== GRUB_USB_EP_INTERRUPT)
|
||||
{
|
||||
grub_size_t len;
|
||||
dev->hub_endpoint = endp;
|
||||
len = endp->maxpacket;
|
||||
if (len > sizeof (dev->statuschange))
|
||||
len = sizeof (dev->statuschange);
|
||||
dev->hub_transfer
|
||||
= grub_usb_bulk_read_background (dev, endp->endp_addr,
|
||||
grub_min (endp->maxpacket,
|
||||
sizeof (dev->statuschange)),
|
||||
= grub_usb_bulk_read_background (dev, endp->endp_addr, len,
|
||||
(char *) &dev->statuschange);
|
||||
break;
|
||||
}
|
||||
|
@ -218,7 +229,7 @@ attach_root_port (struct grub_usb_hub *hub, int portno,
|
|||
grub_millisleep (10);
|
||||
|
||||
/* Enable the port and create a device. */
|
||||
dev = grub_usb_hub_add_dev (hub->controller, speed);
|
||||
dev = grub_usb_hub_add_dev (hub->controller, speed, portno, 0);
|
||||
hub->controller->dev->pending_reset = 0;
|
||||
if (! dev)
|
||||
return;
|
||||
|
@ -314,7 +325,7 @@ poll_nonroot_hub (grub_usb_device_t dev)
|
|||
grub_usb_err_t err;
|
||||
unsigned i;
|
||||
grub_uint8_t changed;
|
||||
grub_size_t actual;
|
||||
grub_size_t actual, len;
|
||||
int j, total;
|
||||
|
||||
if (!dev->hub_transfer)
|
||||
|
@ -327,10 +338,11 @@ poll_nonroot_hub (grub_usb_device_t dev)
|
|||
|
||||
changed = dev->statuschange;
|
||||
|
||||
len = dev->hub_endpoint->maxpacket;
|
||||
if (len > sizeof (dev->statuschange))
|
||||
len = sizeof (dev->statuschange);
|
||||
dev->hub_transfer
|
||||
= grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr,
|
||||
grub_min (dev->hub_endpoint->maxpacket,
|
||||
sizeof (dev->statuschange)),
|
||||
= grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr, len,
|
||||
(char *) &dev->statuschange);
|
||||
|
||||
if (err || actual == 0 || changed == 0)
|
||||
|
@ -353,7 +365,7 @@ poll_nonroot_hub (grub_usb_device_t dev)
|
|||
0, i, sizeof (status), (char *) &status);
|
||||
|
||||
grub_dprintf ("usb", "dev = %p, i = %d, status = %08x\n",
|
||||
dev, i, status);
|
||||
dev, i, status);
|
||||
|
||||
if (err)
|
||||
continue;
|
||||
|
@ -472,7 +484,7 @@ poll_nonroot_hub (grub_usb_device_t dev)
|
|||
grub_millisleep (10);
|
||||
|
||||
/* Add the device and assign a device address to it. */
|
||||
next_dev = grub_usb_hub_add_dev (&dev->controller, speed);
|
||||
next_dev = grub_usb_hub_add_dev (&dev->controller, speed, i, dev->addr);
|
||||
dev->controller.dev->pending_reset = 0;
|
||||
if (! next_dev)
|
||||
continue;
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include <grub/efi/api.h>
|
||||
#endif
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
|
@ -41,8 +43,8 @@ static const struct grub_arg_option options[] = {
|
|||
0, ARG_TYPE_STRING},
|
||||
{"load-only", 'n', 0,
|
||||
N_("Load only tables specified by comma-separated list."), 0, ARG_TYPE_STRING},
|
||||
{"v1", '1', 0, N_("Expose v1 tables."), 0, ARG_TYPE_NONE},
|
||||
{"v2", '2', 0, N_("Expose v2 and v3 tables."), 0, ARG_TYPE_NONE},
|
||||
{"v1", '1', 0, N_("Export version 1 tables to the OS."), 0, ARG_TYPE_NONE},
|
||||
{"v2", '2', 0, N_("Export version 2 and version 3 tables to the OS."), 0, ARG_TYPE_NONE},
|
||||
{"oemid", 'o', 0, N_("Set OEMID of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING},
|
||||
{"oemtable", 't', 0,
|
||||
N_("Set OEMTABLE ID of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING},
|
||||
|
@ -138,6 +140,7 @@ iszero (grub_uint8_t *reg, int size)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#if defined (__i386__) || defined (__x86_64__)
|
||||
grub_err_t
|
||||
grub_acpi_create_ebda (void)
|
||||
{
|
||||
|
@ -165,7 +168,7 @@ grub_acpi_create_ebda (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ebda = (grub_uint8_t *) UINT_TO_PTR ((*((grub_uint16_t *)0x40e)) << 4);
|
||||
ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4);
|
||||
ebda_kb_len = *(grub_uint16_t *) ebda;
|
||||
if (! ebda || ebda_kb_len > 16)
|
||||
ebda_kb_len = 0;
|
||||
|
@ -173,14 +176,14 @@ grub_acpi_create_ebda (void)
|
|||
|
||||
/* FIXME: use low-memory mm allocation once it's available. */
|
||||
grub_mmap_iterate (find_hook);
|
||||
targetebda = (grub_uint8_t *) UINT_TO_PTR (highestlow);
|
||||
targetebda = (grub_uint8_t *) (grub_addr_t) highestlow;
|
||||
grub_dprintf ("acpi", "creating ebda @%llx\n",
|
||||
(unsigned long long) highestlow);
|
||||
if (! highestlow)
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't find space for the new EBDA");
|
||||
|
||||
mmapregion = grub_mmap_register (PTR_TO_UINT64 (targetebda), ebda_len,
|
||||
mmapregion = grub_mmap_register ((grub_addr_t) targetebda, ebda_len,
|
||||
GRUB_MEMORY_RESERVED);
|
||||
if (! mmapregion)
|
||||
return grub_errno;
|
||||
|
@ -297,6 +300,7 @@ grub_acpi_create_ebda (void)
|
|||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create tables common to ACPIv1 and ACPIv2+ */
|
||||
static void
|
||||
|
@ -328,13 +332,13 @@ setup_common_tables (void)
|
|||
if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE,
|
||||
sizeof (fadt->hdr.signature)) == 0)
|
||||
{
|
||||
fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt);
|
||||
fadt->dsdt_addr = (grub_addr_t) table_dsdt;
|
||||
fadt->facs_addr = facs_addr;
|
||||
|
||||
/* Does a revision 2 exist at all? */
|
||||
if (fadt->hdr.revision >= 3)
|
||||
{
|
||||
fadt->dsdt_xaddr = PTR_TO_UINT64 (table_dsdt);
|
||||
fadt->dsdt_xaddr = (grub_addr_t) table_dsdt;
|
||||
fadt->facs_xaddr = facs_addr;
|
||||
}
|
||||
|
||||
|
@ -365,7 +369,7 @@ setup_common_tables (void)
|
|||
rsdt->creator_rev = root_creator_rev;
|
||||
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
*(rsdt_entry++) = PTR_TO_UINT32 (cur->addr);
|
||||
*(rsdt_entry++) = (grub_addr_t) cur->addr;
|
||||
|
||||
/* Recompute checksum. */
|
||||
rsdt->checksum = 0;
|
||||
|
@ -383,7 +387,7 @@ setv1table (void)
|
|||
sizeof (rsdpv1_new->signature));
|
||||
grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid));
|
||||
rsdpv1_new->revision = 0;
|
||||
rsdpv1_new->rsdt_addr = PTR_TO_UINT32 (rsdt_addr);
|
||||
rsdpv1_new->rsdt_addr = (grub_addr_t) rsdt_addr;
|
||||
rsdpv1_new->checksum = 0;
|
||||
rsdpv1_new->checksum = 1 + ~grub_byte_checksum (rsdpv1_new,
|
||||
sizeof (*rsdpv1_new));
|
||||
|
@ -408,7 +412,7 @@ setv2table (void)
|
|||
|
||||
xsdt_entry = (grub_uint64_t *)(xsdt + 1);
|
||||
for (cur = acpi_tables; cur; cur = cur->next)
|
||||
*(xsdt_entry++) = PTR_TO_UINT64 (cur->addr);
|
||||
*(xsdt_entry++) = (grub_addr_t) cur->addr;
|
||||
grub_memcpy (&(xsdt->signature), "XSDT", 4);
|
||||
xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables;
|
||||
xsdt->revision = 1;
|
||||
|
@ -428,12 +432,12 @@ setv2table (void)
|
|||
grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid,
|
||||
sizeof (rsdpv2_new->rsdpv1.oemid));
|
||||
rsdpv2_new->rsdpv1.revision = rev2;
|
||||
rsdpv2_new->rsdpv1.rsdt_addr = PTR_TO_UINT32 (rsdt_addr);
|
||||
rsdpv2_new->rsdpv1.rsdt_addr = (grub_addr_t) rsdt_addr;
|
||||
rsdpv2_new->rsdpv1.checksum = 0;
|
||||
rsdpv2_new->rsdpv1.checksum = 1 + ~grub_byte_checksum
|
||||
(&(rsdpv2_new->rsdpv1), sizeof (rsdpv2_new->rsdpv1));
|
||||
rsdpv2_new->length = sizeof (*rsdpv2_new);
|
||||
rsdpv2_new->xsdt_addr = PTR_TO_UINT64 (xsdt);
|
||||
rsdpv2_new->xsdt_addr = (grub_addr_t) xsdt;
|
||||
rsdpv2_new->checksum = 0;
|
||||
rsdpv2_new->checksum = 1 + ~grub_byte_checksum (rsdpv2_new,
|
||||
rsdpv2_new->length);
|
||||
|
@ -463,7 +467,6 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
struct grub_arg_list *state = ctxt->state;
|
||||
struct grub_acpi_rsdp_v10 *rsdp;
|
||||
struct efiemu_acpi_table *cur, *t;
|
||||
grub_err_t err;
|
||||
int i, mmapregion;
|
||||
int numoftables;
|
||||
|
||||
|
@ -506,7 +509,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
/* Set revision variables to replicate the same version as host. */
|
||||
rev1 = ! rsdp->revision;
|
||||
rev2 = rsdp->revision;
|
||||
rsdt = (struct grub_acpi_table_header *) UINT_TO_PTR (rsdp->rsdt_addr);
|
||||
rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr;
|
||||
/* Load host tables. */
|
||||
for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
|
||||
entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
|
||||
|
@ -516,7 +519,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
char signature[5];
|
||||
struct efiemu_acpi_table *table;
|
||||
struct grub_acpi_table_header *curtable
|
||||
= (struct grub_acpi_table_header *) UINT_TO_PTR (*entry_ptr);
|
||||
= (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr;
|
||||
signature[4] = 0;
|
||||
for (i = 0; i < 4;i++)
|
||||
signature[i] = grub_tolower (curtable->signature[i]);
|
||||
|
@ -540,7 +543,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
|
||||
/* Load DSDT if not excluded. */
|
||||
dsdt = (struct grub_acpi_table_header *)
|
||||
UINT_TO_PTR (fadt->dsdt_addr);
|
||||
(grub_addr_t) fadt->dsdt_addr;
|
||||
if (dsdt && (! exclude || ! grub_strword (exclude, "dsdt"))
|
||||
&& (! load_only || grub_strword (load_only, "dsdt"))
|
||||
&& dsdt->length >= sizeof (*dsdt))
|
||||
|
@ -552,8 +555,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
free_tables ();
|
||||
grub_free (exclude);
|
||||
grub_free (load_only);
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't allocate table");
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (table_dsdt, dsdt, dsdt->length);
|
||||
}
|
||||
|
@ -579,8 +581,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
free_tables ();
|
||||
grub_free (exclude);
|
||||
grub_free (load_only);
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't allocate table structure");
|
||||
return grub_errno;
|
||||
}
|
||||
table->size = curtable->length;
|
||||
table->addr = grub_malloc (table->size);
|
||||
|
@ -588,8 +589,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
if (! table->addr)
|
||||
{
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't allocate table");
|
||||
return grub_errno;
|
||||
}
|
||||
table->next = acpi_tables;
|
||||
acpi_tables = table;
|
||||
|
@ -632,7 +632,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
if (! file)
|
||||
{
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't open file %s", args[i]);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
size = grub_file_size (file);
|
||||
|
@ -640,7 +640,8 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
{
|
||||
grub_file_close (file);
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_BAD_OS, "file %s is too small", args[i]);
|
||||
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
args[i]);
|
||||
}
|
||||
|
||||
buf = (char *) grub_malloc (size);
|
||||
|
@ -648,15 +649,17 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
{
|
||||
grub_file_close (file);
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't read file %s", args[i]);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (grub_file_read (file, buf, size) != (int) size)
|
||||
{
|
||||
grub_file_close (file);
|
||||
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);
|
||||
|
||||
|
@ -675,8 +678,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
if (! table)
|
||||
{
|
||||
free_tables ();
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"couldn't allocate table structure");
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
table->size = size;
|
||||
|
@ -732,13 +734,20 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
}
|
||||
acpi_tables = 0;
|
||||
|
||||
if (! state[9].set && (err = grub_acpi_create_ebda ()))
|
||||
#if defined (__i386__) || defined (__x86_64__)
|
||||
if (! state[9].set)
|
||||
{
|
||||
rsdpv1_new = 0;
|
||||
rsdpv2_new = 0;
|
||||
grub_mmap_free_and_unregister (mmapregion);
|
||||
return err;
|
||||
grub_err_t err;
|
||||
err = grub_acpi_create_ebda ();
|
||||
if (err)
|
||||
{
|
||||
rsdpv1_new = 0;
|
||||
rsdpv2_new = 0;
|
||||
grub_mmap_free_and_unregister (mmapregion);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
{
|
||||
|
@ -761,7 +770,7 @@ GRUB_MOD_INIT(acpi)
|
|||
{
|
||||
cmd = grub_register_extcmd ("acpi", grub_cmd_acpi, 0,
|
||||
N_("[-1|-2] [--exclude=TABLE1,TABLE2|"
|
||||
"--load-only=table1,table2] FILE1"
|
||||
"--load-only=TABLE1,TABLE2] FILE1"
|
||||
" [FILE2] [...]"),
|
||||
N_("Load host ACPI tables and tables "
|
||||
"specified by arguments."),
|
||||
|
|
|
@ -82,7 +82,7 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
|
|||
}
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (args[0]);
|
||||
|
|
|
@ -31,17 +31,17 @@ static grub_err_t (*grub_loader_boot_func) (void);
|
|||
static grub_err_t (*grub_loader_unload_func) (void);
|
||||
static int grub_loader_noreturn;
|
||||
|
||||
struct grub_preboot_t
|
||||
struct grub_preboot
|
||||
{
|
||||
grub_err_t (*preboot_func) (int);
|
||||
grub_err_t (*preboot_rest_func) (void);
|
||||
grub_loader_preboot_hook_prio_t prio;
|
||||
struct grub_preboot_t *next;
|
||||
struct grub_preboot_t *prev;
|
||||
struct grub_preboot *next;
|
||||
struct grub_preboot *prev;
|
||||
};
|
||||
|
||||
static int grub_loader_loaded;
|
||||
static struct grub_preboot_t *preboots_head = 0,
|
||||
static struct grub_preboot *preboots_head = 0,
|
||||
*preboots_tail = 0;
|
||||
|
||||
int
|
||||
|
@ -51,23 +51,20 @@ grub_loader_is_loaded (void)
|
|||
}
|
||||
|
||||
/* Register a preboot hook. */
|
||||
void *
|
||||
struct grub_preboot *
|
||||
grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
|
||||
grub_err_t (*preboot_rest_func) (void),
|
||||
grub_loader_preboot_hook_prio_t prio)
|
||||
{
|
||||
struct grub_preboot_t *cur, *new_preboot;
|
||||
struct grub_preboot *cur, *new_preboot;
|
||||
|
||||
if (! preboot_func && ! preboot_rest_func)
|
||||
return 0;
|
||||
|
||||
new_preboot = (struct grub_preboot_t *)
|
||||
grub_malloc (sizeof (struct grub_preboot_t));
|
||||
new_preboot = (struct grub_preboot *)
|
||||
grub_malloc (sizeof (struct grub_preboot));
|
||||
if (! new_preboot)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY, "hook not added");
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
new_preboot->preboot_func = preboot_func;
|
||||
new_preboot->preboot_rest_func = preboot_rest_func;
|
||||
|
@ -96,9 +93,9 @@ grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn),
|
|||
}
|
||||
|
||||
void
|
||||
grub_loader_unregister_preboot_hook (void *hnd)
|
||||
grub_loader_unregister_preboot_hook (struct grub_preboot *hnd)
|
||||
{
|
||||
struct grub_preboot_t *preb = hnd;
|
||||
struct grub_preboot *preb = hnd;
|
||||
|
||||
if (preb->next)
|
||||
preb->next->prev = preb->prev;
|
||||
|
@ -143,10 +140,11 @@ grub_err_t
|
|||
grub_loader_boot (void)
|
||||
{
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
struct grub_preboot_t *cur;
|
||||
struct grub_preboot *cur;
|
||||
|
||||
if (! grub_loader_loaded)
|
||||
return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel");
|
||||
return grub_error (GRUB_ERR_NO_KERNEL,
|
||||
N_("you need to load the kernel first"));
|
||||
|
||||
if (grub_loader_noreturn)
|
||||
grub_machine_fini ();
|
||||
|
|
|
@ -31,14 +31,16 @@ grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)),
|
|||
unsigned long hits, misses;
|
||||
|
||||
grub_disk_cache_get_performance (&hits, &misses);
|
||||
grub_printf_ (N_("Disk cache: hits = %lu, misses = %lu "), hits, misses);
|
||||
if (hits + misses)
|
||||
{
|
||||
unsigned long ratio = hits * 10000 / (hits + misses);
|
||||
grub_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100);
|
||||
grub_printf_ (N_("Disk cache statistics: hits = %lu (%lu.%02lu%%),"
|
||||
" misses = %lu\n"), ratio / 100, ratio % 100,
|
||||
hits, misses);
|
||||
}
|
||||
else
|
||||
grub_puts_ (N_("(N/A)"));
|
||||
grub_printf ("%s\n", _("No disk cache statistics available\n"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -41,13 +41,13 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
grub_file_t file;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
||||
grub_ssize_t size;
|
||||
int key = 0;
|
||||
int key = GRUB_TERM_NO_KEY;
|
||||
|
||||
if (state[0].set)
|
||||
dos = 1;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
file = grub_file_open (args[0]);
|
||||
if (! file)
|
||||
|
@ -77,8 +77,7 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
}
|
||||
}
|
||||
|
||||
while (grub_checkkey () >= 0 &&
|
||||
(key = grub_getkey ()) != GRUB_TERM_ESC)
|
||||
while ((key = grub_getkey_noblock ()) != GRUB_TERM_ESC)
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
|
|||
char *buf2 = 0;
|
||||
|
||||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
|
||||
|
||||
grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0],
|
||||
args[1]);
|
||||
|
|
|
@ -32,7 +32,7 @@ grub_cmd_source (grub_command_t cmd, int argc, char **args)
|
|||
int new_env, extractor;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
extractor = (cmd->name[0] == 'e');
|
||||
new_env = (cmd->name[extractor ? sizeof ("extract_entries_") - 1 : 0] == 'c');
|
||||
|
|
|
@ -165,7 +165,7 @@ grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)),
|
|||
int size;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no ROM image specified");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
|
@ -206,7 +206,9 @@ static grub_command_t cmd_fakebios, cmd_loadbios;
|
|||
GRUB_MOD_INIT(loadbios)
|
||||
{
|
||||
cmd_fakebios = grub_register_command ("fakebios", grub_cmd_fakebios,
|
||||
0, N_("Fake BIOS."));
|
||||
0, N_("Create BIOS-like structures for"
|
||||
" backward compatibility with"
|
||||
" existing OS."));
|
||||
|
||||
cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
|
||||
N_("BIOS_DUMP [INT10_DUMP]"),
|
||||
|
|
|
@ -133,7 +133,8 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (! partition)
|
||||
{
|
||||
grub_device_close (dev);
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such partition");
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
|
||||
N_("no such partition"));
|
||||
}
|
||||
|
||||
if (partition->start + partition->len > 0xffffffff)
|
||||
|
|
|
@ -24,13 +24,12 @@
|
|||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
static grub_err_t __attribute__ ((noreturn))
|
||||
grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
grub_halt ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
|
|
@ -30,8 +30,9 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
|||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"hash", 'h', 0, N_("Specify hash to use."), N_("HASH"), ARG_TYPE_STRING},
|
||||
{"check", 'c', 0, N_("Check hash list file."), N_("FILE"), ARG_TYPE_STRING},
|
||||
{"prefix", 'p', 0, N_("Base directory for hash list."), N_("DIRECTORY"),
|
||||
{"check", 'c', 0, N_("Check hashes of files with hash list FILE."),
|
||||
N_("FILE"), ARG_TYPE_STRING},
|
||||
{"prefix", 'p', 0, N_("Base directory for hash list."), N_("DIR"),
|
||||
ARG_TYPE_STRING},
|
||||
{"keep-going", 'k', 0, N_("Don't stop after first error."), 0, 0},
|
||||
{"uncompress", 'u', 0, N_("Uncompress file before checksumming."), 0, 0},
|
||||
|
|
|
@ -47,7 +47,7 @@ static const struct grub_arg_option options[] = {
|
|||
{"sleep", 'Y', 0, N_("Set drive to sleep mode."), 0, ARG_TYPE_NONE},
|
||||
{"identify", 'i', 0, N_("Print drive identity and settings."),
|
||||
0, ARG_TYPE_NONE},
|
||||
{"dumpid", 'I', 0, N_("Dump contents of ATA IDENTIFY sector."),
|
||||
{"dumpid", 'I', 0, N_("Show raw contents of ATA IDENTIFY sector."),
|
||||
0, ARG_TYPE_NONE},
|
||||
{"smart", -1, 0, N_("Disable/enable SMART (0/1)."), 0, ARG_TYPE_INT},
|
||||
{"quiet", 'q', 0, N_("Do not print messages."), 0, ARG_TYPE_NONE},
|
||||
|
@ -165,22 +165,20 @@ grub_hdparm_set_val_cmd (const char * msg, int val,
|
|||
}
|
||||
|
||||
static const char *
|
||||
le16_to_char (char *dest, const grub_uint16_t * src16, unsigned bytes)
|
||||
le16_to_char (grub_uint16_t *dest, const grub_uint16_t * src16, unsigned bytes)
|
||||
{
|
||||
grub_uint16_t * dest16 = (grub_uint16_t *) dest;
|
||||
unsigned i;
|
||||
for (i = 0; i < bytes / 2; i++)
|
||||
dest16[i] = grub_be_to_cpu16 (src16[i]);
|
||||
return dest;
|
||||
dest[i] = grub_be_to_cpu16 (src16[i]);
|
||||
dest[i] = 0;
|
||||
return (char *) dest;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_hdparm_print_identify (const char * idbuf)
|
||||
grub_hdparm_print_identify (const grub_uint16_t * idw)
|
||||
{
|
||||
const grub_uint16_t * idw = (const grub_uint16_t *) idbuf;
|
||||
|
||||
/* Print identity strings. */
|
||||
char tmp[40];
|
||||
grub_uint16_t tmp[21];
|
||||
grub_printf ("Model: \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40));
|
||||
grub_printf ("Firmware: \"%.8s\"\n", le16_to_char (tmp, &idw[23], 8));
|
||||
grub_printf ("Serial: \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20));
|
||||
|
@ -277,19 +275,25 @@ static int get_int_arg (const struct grub_arg_list *state)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
||||
grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
struct grub_ata *ata;
|
||||
const char *diskname;
|
||||
|
||||
/* Check command line. */
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing device name argument");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
|
||||
grub_size_t len = grub_strlen (args[0]);
|
||||
if (! (args[0][0] == '(' && args[0][len - 1] == ')'))
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "argument is not a device name");
|
||||
args[0][len - 1] = 0;
|
||||
if (args[0][0] == '(')
|
||||
{
|
||||
grub_size_t len = grub_strlen (args[0]);
|
||||
if (args[0][len - 1] == ')')
|
||||
args[0][len - 1] = 0;
|
||||
diskname = &args[0][1];
|
||||
}
|
||||
else
|
||||
diskname = &args[0][0];
|
||||
|
||||
int i = 0;
|
||||
int apm = get_int_arg (&state[i++]);
|
||||
|
@ -306,16 +310,10 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
|||
quiet = state[i++].set;
|
||||
|
||||
/* Open disk. */
|
||||
grub_disk_t disk = grub_disk_open (&args[0][1]);
|
||||
grub_disk_t disk = grub_disk_open (diskname);
|
||||
if (! disk)
|
||||
return grub_errno;
|
||||
|
||||
if (disk->partition)
|
||||
{
|
||||
grub_disk_close (disk);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "partition not allowed");
|
||||
}
|
||||
|
||||
switch (disk->dev->id)
|
||||
{
|
||||
case GRUB_DISK_DEVICE_ATA_ID:
|
||||
|
@ -377,7 +375,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
|||
/* Print/dump IDENTIFY. */
|
||||
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,
|
||||
0, 0, buf, sizeof (buf)))
|
||||
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)
|
||||
grub_hdparm_print_identify (buf);
|
||||
if (dumpid)
|
||||
hexdump (0, buf, sizeof (buf));
|
||||
hexdump (0, (char *) buf, sizeof (buf));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc,
|
|||
char *command_help;
|
||||
grub_uint32_t *unicode_command_help;
|
||||
grub_uint32_t *unicode_last_position;
|
||||
|
||||
|
||||
command_help = grub_xasprintf ("%s %s", cmd->name, summary_translated);
|
||||
if (!command_help)
|
||||
break;
|
||||
|
@ -99,28 +99,37 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc,
|
|||
else
|
||||
{
|
||||
int i;
|
||||
grub_command_t cmd;
|
||||
grub_command_t cmd_iter, cmd;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
currarg = args[i];
|
||||
FOR_COMMANDS(cmd)
|
||||
FOR_COMMANDS(cmd_iter)
|
||||
{
|
||||
if (cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE)
|
||||
{
|
||||
if (! grub_strncmp (cmd->name, currarg, grub_strlen (currarg)))
|
||||
{
|
||||
if (cnt++ > 0)
|
||||
grub_printf ("\n\n");
|
||||
if (!(cmd_iter->prio & GRUB_PRIO_LIST_FLAG_ACTIVE))
|
||||
continue;
|
||||
|
||||
if ((cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) &&
|
||||
! (cmd->flags & GRUB_COMMAND_FLAG_DYNCMD))
|
||||
grub_arg_show_help ((grub_extcmd_t) cmd->data);
|
||||
else
|
||||
grub_printf ("%s %s %s\n%s\n", _("Usage:"), cmd->name, _(cmd->summary),
|
||||
_(cmd->description));
|
||||
}
|
||||
if (grub_strncmp (cmd_iter->name, currarg,
|
||||
grub_strlen (currarg)) != 0)
|
||||
continue;
|
||||
if (cmd_iter->flags & GRUB_COMMAND_FLAG_DYNCMD)
|
||||
cmd = grub_dyncmd_get_cmd (cmd_iter);
|
||||
else
|
||||
cmd = cmd_iter;
|
||||
if (!cmd)
|
||||
{
|
||||
grub_print_error ();
|
||||
continue;
|
||||
}
|
||||
if (cnt++ > 0)
|
||||
grub_printf ("\n\n");
|
||||
|
||||
if ((cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) &&
|
||||
! (cmd->flags & GRUB_COMMAND_FLAG_DYNCMD))
|
||||
grub_arg_show_help ((grub_extcmd_t) cmd->data);
|
||||
else
|
||||
grub_printf ("%s %s %s\n%s\n", _("Usage:"), cmd->name,
|
||||
_(cmd->summary), _(cmd->description));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
int namelen;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
namelen = grub_strlen (args[0]);
|
||||
skip = (state[0].set) ? grub_strtoull (state[0].arg, 0, 0) : 0;
|
||||
|
@ -123,7 +123,7 @@ GRUB_MOD_INIT (hexdump)
|
|||
{
|
||||
cmd = grub_register_extcmd ("hexdump", grub_cmd_hexdump, 0,
|
||||
N_("[OPTIONS] FILE_OR_DEVICE"),
|
||||
N_("Dump the contents of a file or memory."),
|
||||
N_("Show raw contents of a file or memory."),
|
||||
options);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,11 +30,11 @@ parse_args (int argc, char *argv[], int *byte, int *bit)
|
|||
char *rest;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required.");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "address required");
|
||||
|
||||
*byte = grub_strtoul (argv[0], &rest, 0);
|
||||
if (*rest != ':')
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required.");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "address required");
|
||||
|
||||
*bit = grub_strtoul (rest + 1, 0, 0);
|
||||
|
||||
|
@ -60,7 +60,7 @@ grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)),
|
|||
if (value & (1 << bit))
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
|
|
@ -50,7 +50,9 @@ grub_cmd_cpuid (grub_extcmd_context_t ctxt __attribute__ ((unused)),
|
|||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
return grub_cpuid_has_longmode ? GRUB_ERR_NONE
|
||||
: grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
/* TRANSLATORS: it's a standalone boolean value,
|
||||
opposite of "true". */
|
||||
: grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */
|
||||
static grub_uint32_t *const int13slot = UINT_TO_PTR (4 * 0x13);
|
||||
static grub_uint32_t *const int13slot = (grub_uint32_t *) (4 * 0x13);
|
||||
|
||||
/* Remember to update enum opt_idxs accordingly. */
|
||||
static const struct grub_arg_option options[] = {
|
||||
|
@ -107,8 +107,7 @@ drivemap_set (grub_uint8_t newdrive, grub_uint8_t redirto)
|
|||
{
|
||||
mapping = grub_malloc (sizeof (drivemap_node_t));
|
||||
if (! mapping)
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"cannot allocate map entry, not enough memory");
|
||||
return grub_errno;
|
||||
mapping->newdrive = newdrive;
|
||||
mapping->redirto = redirto;
|
||||
mapping->next = map_head;
|
||||
|
@ -230,7 +229,7 @@ grub_cmd_drivemap (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
grub_err_t err;
|
||||
|
||||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
|
||||
|
||||
err = tryparse_diskstring (args[0], &mapfrom);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
|
|
|
@ -72,9 +72,9 @@ grub_cmd_lsapm (grub_command_t cmd __attribute__ ((unused)),
|
|||
{
|
||||
struct grub_apm_info info;
|
||||
if (!grub_apm_get_info (&info))
|
||||
return grub_error (GRUB_ERR_IO, "no APM found");
|
||||
return grub_error (GRUB_ERR_IO, N_("no APM found"));
|
||||
|
||||
grub_printf_ (N_("Vesion %u.%u\n"
|
||||
grub_printf_ (N_("Version %u.%u\n"
|
||||
"32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n"
|
||||
"16-bit CS = 0x%x, len = 0x%x\n"
|
||||
"DS = 0x%x, len = 0x%x\n"),
|
||||
|
|
|
@ -151,7 +151,7 @@ play (unsigned tempo, struct note *note)
|
|||
{
|
||||
unsigned int to;
|
||||
|
||||
if (note->pitch == T_FINE || grub_checkkey () >= 0)
|
||||
if (note->pitch == T_FINE || grub_getkey_noblock () != GRUB_TERM_NO_KEY)
|
||||
return 1;
|
||||
|
||||
grub_dprintf ("play", "pitch = %d, duration = %d\n", note->pitch,
|
||||
|
@ -169,7 +169,8 @@ play (unsigned tempo, struct note *note)
|
|||
}
|
||||
|
||||
to = grub_get_rtc () + BASE_TEMPO * note->duration / tempo;
|
||||
while (((unsigned int) grub_get_rtc () <= to) && (grub_checkkey () < 0))
|
||||
while (((unsigned int) grub_get_rtc () <= to)
|
||||
&& (grub_getkey_noblock () == GRUB_TERM_NO_KEY))
|
||||
;
|
||||
|
||||
return 0;
|
||||
|
@ -181,7 +182,8 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
|
|||
{
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name or tempo and notes required");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("filename or tempo and notes expected"));
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
|
@ -192,13 +194,15 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
|
|||
file = grub_file_open (args[0]);
|
||||
|
||||
if (! file)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]);
|
||||
return grub_errno;
|
||||
|
||||
if (grub_file_read (file, &tempo, sizeof (tempo)) != sizeof (tempo))
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_error (GRUB_ERR_FILE_READ_ERROR,
|
||||
"file doesn't even contains a full tempo record");
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
|
||||
args[0]);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
tempo = grub_le_to_cpu32 (tempo);
|
||||
|
@ -227,23 +231,27 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
if (*end)
|
||||
/* Was not a number either, assume it was supposed to be a file name. */
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]);
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), args[0]);
|
||||
|
||||
grub_dprintf ("play","tempo = %d\n", tempo);
|
||||
|
||||
for (i = 1; i + 1 < argc; i += 2)
|
||||
{
|
||||
note.pitch = grub_strtoul (args[i], &end, 0);
|
||||
if (grub_errno)
|
||||
break;
|
||||
if (*end)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_NUMBER, "bogus pitch number");
|
||||
grub_error (GRUB_ERR_BAD_NUMBER, N_("unrecognized number"));
|
||||
break;
|
||||
}
|
||||
|
||||
note.duration = grub_strtoul (args[i + 1], &end, 0);
|
||||
if (grub_errno)
|
||||
break;
|
||||
if (*end)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_NUMBER, "bogus duration number");
|
||||
grub_error (GRUB_ERR_BAD_NUMBER, N_("unrecognized number"));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -254,9 +262,6 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
beep_off ();
|
||||
|
||||
while (grub_checkkey () > 0)
|
||||
grub_getkey ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,8 +63,8 @@ static grub_uint32_t andmask = 0xffffffff, ormask = 0;
|
|||
struct
|
||||
keysym
|
||||
{
|
||||
char *unshifted_name; /* the name in unshifted state */
|
||||
char *shifted_name; /* the name in shifted state */
|
||||
const char *unshifted_name; /* the name in unshifted state */
|
||||
const char *shifted_name; /* the name in shifted state */
|
||||
unsigned char unshifted_ascii; /* the ascii code in unshifted state */
|
||||
unsigned char shifted_ascii; /* the ascii code in shifted state */
|
||||
unsigned char keycode; /* keyboard scancode */
|
||||
|
@ -365,7 +365,7 @@ grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
static void *preboot_hook;
|
||||
static struct grub_preboot *preboot_hook;
|
||||
|
||||
GRUB_MOD_INIT (sendkey)
|
||||
{
|
||||
|
|
|
@ -42,7 +42,7 @@ static grub_command_t cmd;
|
|||
GRUB_MOD_INIT(ieee1275_suspend)
|
||||
{
|
||||
cmd = grub_register_command ("suspend", grub_cmd_suspend,
|
||||
0, N_("Return to Open Firmware prompt."));
|
||||
0, N_("Return to IEEE1275 prompt."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(ieee1275_suspend)
|
||||
|
|
|
@ -44,7 +44,7 @@ grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv)
|
|||
grub_uint32_t value = 0;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
|
||||
addr = grub_strtoul (argv[0], 0, 0);
|
||||
switch (ctxt->extcmd->cmd->name[sizeof ("in") - 1])
|
||||
|
@ -82,7 +82,7 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv)
|
|||
grub_uint32_t mask = 0xffffffff;
|
||||
|
||||
if (argc != 2 && argc != 3)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
|
||||
|
||||
addr = grub_strtoul (argv[0], 0, 0);
|
||||
value = grub_strtoul (argv[1], 0, 0);
|
||||
|
@ -120,25 +120,28 @@ GRUB_MOD_INIT(memrw)
|
|||
{
|
||||
cmd_read_byte =
|
||||
grub_register_extcmd ("inb", grub_cmd_read, 0,
|
||||
N_("PORT"), N_("Read byte from PORT."), options);
|
||||
N_("PORT"), N_("Read 8-bit value from PORT."),
|
||||
options);
|
||||
cmd_read_word =
|
||||
grub_register_extcmd ("inw", grub_cmd_read, 0,
|
||||
N_("PORT"), N_("Read word from PORT."), options);
|
||||
N_("PORT"), N_("Read 16-bit value from PORT."),
|
||||
options);
|
||||
cmd_read_dword =
|
||||
grub_register_extcmd ("inl", grub_cmd_read, 0,
|
||||
N_("PORT"), N_("Read dword from PORT."), options);
|
||||
N_("PORT"), N_("Read 32-bit value from PORT."),
|
||||
options);
|
||||
cmd_write_byte =
|
||||
grub_register_command ("outb", grub_cmd_write,
|
||||
N_("PORT VALUE [MASK]"),
|
||||
N_("Write byte VALUE to PORT."));
|
||||
N_("Write 8-bit VALUE to PORT."));
|
||||
cmd_write_word =
|
||||
grub_register_command ("outw", grub_cmd_write,
|
||||
N_("PORT VALUE [MASK]"),
|
||||
N_("Write word VALUE to PORT."));
|
||||
N_("Write 16-bit VALUE to PORT."));
|
||||
cmd_write_dword =
|
||||
grub_register_command ("outl", grub_cmd_write,
|
||||
N_("ADDR VALUE [MASK]"),
|
||||
N_("Write dword VALUE to PORT."));
|
||||
N_("Write 32-bit VALUE to PORT."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(memrw)
|
||||
|
|
|
@ -207,7 +207,7 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)),
|
|||
{
|
||||
const char *prefix = grub_env_get ("prefix");
|
||||
if (!prefix)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "No prefix set");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("variable `%s' isn't set"), "prefix");
|
||||
filename = grub_xasprintf ("%s/layouts/%s.gkb", prefix, argv[0]);
|
||||
if (!filename)
|
||||
return grub_errno;
|
||||
|
@ -222,7 +222,8 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)),
|
|||
if (grub_file_read (file, magic, sizeof (magic)) != sizeof (magic))
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short");
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("premature end of file %s"),
|
||||
filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -236,7 +237,8 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)),
|
|||
if (grub_file_read (file, &version, sizeof (version)) != sizeof (version))
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short");
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("premature end of file %s"),
|
||||
filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -253,7 +255,8 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)),
|
|||
if (grub_file_read (file, newmap, sizeof (*newmap)) != sizeof (*newmap))
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short");
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("premature end of file %s"),
|
||||
filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,11 +78,11 @@ grub_cmd_keystatus (grub_extcmd_context_t ctxt,
|
|||
|
||||
FOR_ACTIVE_TERM_INPUTS (term)
|
||||
if (!term->getkeystatus)
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
|
||||
else
|
||||
nterms++;
|
||||
if (!nterms)
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ grub_cmd_keystatus (grub_extcmd_context_t ctxt,
|
|||
if (mods >= 0 && (mods & expect_mods) != 0)
|
||||
return 0;
|
||||
else
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
@ -99,7 +99,7 @@ static grub_extcmd_t cmd;
|
|||
GRUB_MOD_INIT(keystatus)
|
||||
{
|
||||
cmd = grub_register_extcmd ("keystatus", grub_cmd_keystatus, 0,
|
||||
N_("[--shift] [--ctrl] [--alt]"),
|
||||
"[--shift] [--ctrl] [--alt]",
|
||||
N_("Check key modifier status."),
|
||||
options);
|
||||
}
|
||||
|
|
|
@ -194,7 +194,7 @@ grub_cmd_legacy_source (struct grub_command *cmd,
|
|||
grub_err_t ret;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
extractor = (cmd->name[0] == 'e');
|
||||
new_env = (cmd->name[extractor ? (sizeof ("extract_legacy_entries_") - 1)
|
||||
|
@ -299,7 +299,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
|||
}
|
||||
|
||||
if (argc < 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename required");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1));
|
||||
cutargc = argc - 1;
|
||||
|
@ -411,10 +411,11 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
|||
}
|
||||
else
|
||||
{
|
||||
char rbuf[3] = "-r";
|
||||
bsdargc = cutargc + 2;
|
||||
bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
|
||||
grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0]));
|
||||
bsdargs[argc] = "-r";
|
||||
bsdargs[argc] = rbuf;
|
||||
bsdargs[argc + 1] = bsddevname;
|
||||
grub_snprintf (bsddevname, sizeof (bsddevname),
|
||||
"wd%d%c", bsd_device,
|
||||
|
@ -453,7 +454,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
|||
}
|
||||
while (0);
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s\n",
|
||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s",
|
||||
args[0]);
|
||||
}
|
||||
|
||||
|
@ -467,7 +468,8 @@ grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)),
|
|||
{
|
||||
cmd = grub_command_find ("initrd16");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"initrd16");
|
||||
|
||||
return cmd->func (cmd, argc, args);
|
||||
}
|
||||
|
@ -475,13 +477,14 @@ grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)),
|
|||
{
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"module");
|
||||
|
||||
return cmd->func (cmd, argc, args);
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"no kernel with module support is loaded in legacy way");
|
||||
N_("you need to load the kernel first"));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
@ -494,7 +497,8 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused
|
|||
{
|
||||
cmd = grub_command_find ("initrd16");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"initrd16");
|
||||
|
||||
return cmd->func (cmd, argc, args);
|
||||
}
|
||||
|
@ -502,14 +506,16 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused
|
|||
{
|
||||
char **newargs;
|
||||
grub_err_t err;
|
||||
char nounzipbuf[10] = "--nounzip";
|
||||
newargs = grub_malloc ((argc + 1) * sizeof (newargs[0]));
|
||||
if (!newargs)
|
||||
return grub_errno;
|
||||
grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0]));
|
||||
newargs[0] = "--nounzip";
|
||||
newargs[0] = nounzipbuf;
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
|
||||
"module");
|
||||
|
||||
err = cmd->func (cmd, argc + 1, newargs);
|
||||
grub_free (newargs);
|
||||
|
@ -517,7 +523,7 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused
|
|||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"no kernel with module support is loaded in legacy way");
|
||||
N_("you need to load the kernel first"));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
@ -696,7 +702,7 @@ grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)),
|
|||
struct legacy_md5_password *pw = NULL;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
if (args[0][0] != '-' || args[0][1] != '-')
|
||||
return grub_normal_set_password ("legacy", args[0]);
|
||||
|
||||
|
@ -722,7 +728,7 @@ grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unuse
|
|||
char entered[GRUB_AUTH_MAX_PASSLEN];
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
grub_puts_ (N_("Enter password: "));
|
||||
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
@ -781,26 +787,26 @@ GRUB_MOD_INIT(legacycfg)
|
|||
cmd_kernel = grub_register_command ("legacy_kernel",
|
||||
grub_cmd_legacy_kernel,
|
||||
N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"),
|
||||
N_("Simulate grub-legacy kernel command"));
|
||||
N_("Simulate grub-legacy `kernel' command"));
|
||||
|
||||
cmd_initrd = grub_register_command ("legacy_initrd",
|
||||
grub_cmd_legacy_initrd,
|
||||
N_("FILE [ARG ...]"),
|
||||
N_("Simulate grub-legacy initrd command"));
|
||||
N_("Simulate grub-legacy `initrd' command"));
|
||||
cmd_initrdnounzip = grub_register_command ("legacy_initrd_nounzip",
|
||||
grub_cmd_legacy_initrdnounzip,
|
||||
N_("FILE [ARG ...]"),
|
||||
N_("Simulate grub-legacy modulenounzip command"));
|
||||
N_("Simulate grub-legacy `modulenounzip' command"));
|
||||
|
||||
cmd_password = grub_register_command ("legacy_password",
|
||||
grub_cmd_legacy_password,
|
||||
N_("[--md5] PASSWD [FILE]"),
|
||||
N_("Simulate grub-legacy password command"));
|
||||
N_("Simulate grub-legacy `password' command"));
|
||||
|
||||
cmd_check_password = grub_register_command ("legacy_check_password",
|
||||
grub_cmd_legacy_check_password,
|
||||
N_("[--md5] PASSWD [FILE]"),
|
||||
N_("Simulate grub-legacy password command in menuentry mode"));
|
||||
N_("Simulate grub-legacy `password' command in menuentry mode"));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ open_envblk_file (char *filename)
|
|||
}
|
||||
else
|
||||
{
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, "prefix is not found");
|
||||
grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -93,8 +93,6 @@ read_envblk_file (grub_file_t file)
|
|||
ret = grub_file_read (file, buf + offset, size);
|
||||
if (ret <= 0)
|
||||
{
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
grub_error (GRUB_ERR_FILE_READ_ERROR, "cannot read");
|
||||
grub_free (buf);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
|||
grub_free (pathname);
|
||||
}
|
||||
else
|
||||
grub_printf ("%-12s", "DIR");
|
||||
grub_printf ("%-12s", _("DIR"));
|
||||
|
||||
if (info->mtimeset)
|
||||
{
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <grub/i18n.h>
|
||||
#include <grub/dl.h>
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static void
|
||||
|
@ -132,11 +134,13 @@ disp_acpi_xsdt_table (struct grub_acpi_table_header *t)
|
|||
desc = (grub_uint64_t *) (t + 1);
|
||||
for (; len > 0; desc++, len -= sizeof (*desc))
|
||||
{
|
||||
if (sizeof (grub_addr_t) == 4 && *desc >= (1ULL << 32))
|
||||
#if GRUB_CPU_SIZEOF_VOID_P == 4
|
||||
if (*desc >= (1ULL << 32))
|
||||
{
|
||||
grub_printf ("Unreachable table\n");
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
t = (struct grub_acpi_table_header *) (grub_addr_t) *desc;
|
||||
|
||||
if (t == NULL)
|
||||
|
@ -222,9 +226,11 @@ grub_cmd_lsacpi (struct grub_extcmd_context *ctxt,
|
|||
grub_printf ("No RSDPv2\n");
|
||||
else
|
||||
{
|
||||
if (sizeof (grub_addr_t) == 4 && rsdp2->xsdt_addr >= (1ULL << 32))
|
||||
grub_printf ("Unreachable RSDPv2\n");
|
||||
#if GRUB_CPU_SIZEOF_VOID_P == 4
|
||||
if (rsdp2->xsdt_addr >= (1ULL << 32))
|
||||
grub_printf ("Unreachable RSDPv2\n");
|
||||
else
|
||||
#endif
|
||||
{
|
||||
grub_printf ("RSDPv2 signature:");
|
||||
disp_acpi_rsdpv2 (rsdp2);
|
||||
|
@ -240,7 +246,7 @@ static grub_extcmd_t cmd;
|
|||
|
||||
GRUB_MOD_INIT(lsapi)
|
||||
{
|
||||
cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, 0, N_("[-1|-2]"),
|
||||
cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, 0, "[-1|-2]",
|
||||
N_("Show ACPI information."), options);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,13 +26,13 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
|||
|
||||
static const char *names[] =
|
||||
{
|
||||
[GRUB_MEMORY_AVAILABLE] = N_("available"),
|
||||
[GRUB_MEMORY_RESERVED] = N_("reserved"),
|
||||
[GRUB_MEMORY_ACPI] = N_("ACPI reclamaible"),
|
||||
[GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage"),
|
||||
[GRUB_MEMORY_BADRAM] = N_("BadRAM"),
|
||||
[GRUB_MEMORY_CODE] = N_("firmware code"),
|
||||
[GRUB_MEMORY_HOLE] = N_("hole")
|
||||
[GRUB_MEMORY_AVAILABLE] = N_("available RAM"),
|
||||
[GRUB_MEMORY_RESERVED] = N_("reserved RAM"),
|
||||
[GRUB_MEMORY_ACPI] = N_("ACPI reclaimable RAM"),
|
||||
[GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage RAM"),
|
||||
[GRUB_MEMORY_BADRAM] = N_("faulty RAM (BadRAM)"),
|
||||
[GRUB_MEMORY_CODE] = N_("RAM holding firmware code"),
|
||||
[GRUB_MEMORY_HOLE] = N_("Address range not associated with RAM")
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
|
|
|
@ -29,7 +29,7 @@ struct grub_pci_classname
|
|||
{
|
||||
int class;
|
||||
int subclass;
|
||||
char *desc;
|
||||
const char *desc;
|
||||
};
|
||||
|
||||
static const struct grub_pci_classname grub_pci_classes[] =
|
||||
|
|
|
@ -44,7 +44,7 @@ grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv)
|
|||
char buf[sizeof ("XXXXXXXX")];
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid number of arguments");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
|
||||
addr = grub_strtoul (argv[0], 0, 0);
|
||||
switch (ctxt->extcmd->cmd->name[sizeof ("read_") - 1])
|
||||
|
@ -81,7 +81,7 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv)
|
|||
grub_uint32_t mask = 0xffffffff;
|
||||
|
||||
if (argc != 2 && argc != 3)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid number of arguments");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
|
||||
|
||||
addr = grub_strtoul (argv[0], 0, 0);
|
||||
value = grub_strtoul (argv[1], 0, 0);
|
||||
|
@ -122,22 +122,28 @@ GRUB_MOD_INIT(memrw)
|
|||
{
|
||||
cmd_read_byte =
|
||||
grub_register_extcmd ("read_byte", grub_cmd_read, 0,
|
||||
N_("ADDR"), N_("Read byte from ADDR."), options);
|
||||
N_("ADDR"), N_("Read 8-bit value from ADDR."),
|
||||
options);
|
||||
cmd_read_word =
|
||||
grub_register_extcmd ("read_word", grub_cmd_read, 0,
|
||||
N_("ADDR"), N_("Read word from ADDR."), options);
|
||||
N_("ADDR"), N_("Read 16-bit value from ADDR."),
|
||||
options);
|
||||
cmd_read_dword =
|
||||
grub_register_extcmd ("read_dword", grub_cmd_read, 0,
|
||||
N_("ADDR"), N_("Read dword from ADDR."), options);
|
||||
N_("ADDR"), N_("Read 32-bit value from ADDR."),
|
||||
options);
|
||||
cmd_write_byte =
|
||||
grub_register_command ("write_byte", grub_cmd_write,
|
||||
N_("ADDR VALUE [MASK]"), N_("Write byte VALUE to ADDR."));
|
||||
N_("ADDR VALUE [MASK]"),
|
||||
N_("Write 8-bit VALUE to ADDR."));
|
||||
cmd_write_word =
|
||||
grub_register_command ("write_word", grub_cmd_write,
|
||||
N_("ADDR VALUE [MASK]"), N_("Write word VALUE to ADDR."));
|
||||
N_("ADDR VALUE [MASK]"),
|
||||
N_("Write 16-bit VALUE to ADDR."));
|
||||
cmd_write_dword =
|
||||
grub_register_command ("write_dword", grub_cmd_write,
|
||||
N_("ADDR VALUE [MASK]"), N_("Write dword VALUE to ADDR."));
|
||||
N_("ADDR VALUE [MASK]"),
|
||||
N_("Write 32-bit VALUE to ADDR."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(memrw)
|
||||
|
|
|
@ -30,17 +30,18 @@ static const struct grub_arg_option options[] =
|
|||
{"class", 1, GRUB_ARG_OPTION_REPEATABLE,
|
||||
N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING},
|
||||
{"users", 2, 0,
|
||||
N_("Users allowed to boot this entry."), N_("USERNAME"), ARG_TYPE_STRING},
|
||||
N_("List of users allowed to boot this entry."), N_("USERNAME[,USERNAME]"),
|
||||
ARG_TYPE_STRING},
|
||||
{"hotkey", 3, 0,
|
||||
N_("Keyboard key for this entry."), N_("KEY"), ARG_TYPE_STRING},
|
||||
N_("Keyboard key to quickly boot this entry."), N_("KEYBOARD_KEY"), ARG_TYPE_STRING},
|
||||
{"source", 4, 0,
|
||||
N_("Menu entry definition as a string."), N_("STRING"), ARG_TYPE_STRING},
|
||||
N_("Use STRING as menu entry body."), N_("STRING"), ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
char *name;
|
||||
const char *name;
|
||||
int key;
|
||||
} hotkey_aliases[] =
|
||||
{
|
||||
|
|
|
@ -41,7 +41,7 @@ grub_mini_cmd_cat (struct grub_command *cmd __attribute__ ((unused)),
|
|||
grub_ssize_t size;
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
|
@ -165,13 +165,13 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
|
|||
}
|
||||
|
||||
/* exit */
|
||||
static grub_err_t
|
||||
static grub_err_t __attribute__ ((noreturn))
|
||||
grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
grub_exit ();
|
||||
return 0;
|
||||
/* Not reached. */
|
||||
}
|
||||
|
||||
static grub_command_t cmd_cat, cmd_help;
|
||||
|
@ -187,7 +187,7 @@ GRUB_MOD_INIT(minicmd)
|
|||
0, N_("Show this message."));
|
||||
cmd_dump =
|
||||
grub_register_command ("dump", grub_mini_cmd_dump,
|
||||
N_("ADDR"), N_("Dump memory."));
|
||||
N_("ADDR [SIZE]"), N_("Show memory contents."));
|
||||
cmd_rmmod =
|
||||
grub_register_command ("rmmod", grub_mini_cmd_rmmod,
|
||||
N_("MODULE"), N_("Remove a module."));
|
||||
|
|
|
@ -49,14 +49,15 @@ grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
grub_printf_ (N_("SMB base = 0x%x\n"), smbbase);
|
||||
grub_printf_ (N_("System management bus controller I/O space is at 0x%x\n"),
|
||||
smbbase);
|
||||
|
||||
for (i = GRUB_SMB_RAM_START_ADDR;
|
||||
i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++)
|
||||
{
|
||||
struct grub_smbus_spd spd;
|
||||
grub_memset (&spd, 0, sizeof (spd));
|
||||
grub_printf_ (N_("Device %d\n"), i);
|
||||
grub_printf_ (N_("RAM slot number %d\n"), i);
|
||||
err = grub_cs5536_read_spd (smbbase, i, &spd);
|
||||
if (err)
|
||||
{
|
||||
|
|
|
@ -185,7 +185,8 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
|
|||
{
|
||||
char *filename;
|
||||
|
||||
filename = grub_xasprintf ("%s/parttool.lst", prefix);
|
||||
filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM
|
||||
"/parttool.lst", prefix);
|
||||
if (filename)
|
||||
{
|
||||
grub_file_t file;
|
||||
|
@ -268,7 +269,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
|
|||
break;
|
||||
}
|
||||
if (! cur)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unrecognised argument %s",
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"),
|
||||
args[i]);
|
||||
ptool = cur;
|
||||
pargs = (struct grub_parttool_args *)
|
||||
|
|
|
@ -72,7 +72,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
|
|||
int argc, char **args)
|
||||
{
|
||||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments expected");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
|
||||
return grub_normal_set_password (args[0], args[1]);
|
||||
}
|
||||
|
||||
|
|
|
@ -90,11 +90,11 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
|
|||
struct pbkdf2_password *pass;
|
||||
|
||||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Two arguments expected.");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
|
||||
|
||||
if (grub_memcmp (args[1], "grub.pbkdf2.sha512.",
|
||||
sizeof ("grub.pbkdf2.sha512.") - 1) != 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password.");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid PBKDF2 password"));
|
||||
|
||||
ptr = args[1] + sizeof ("grub.pbkdf2.sha512.") - 1;
|
||||
|
||||
|
@ -103,10 +103,12 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
|
|||
return grub_errno;
|
||||
|
||||
pass->c = grub_strtoul (ptr, &ptr, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (*ptr != '.')
|
||||
{
|
||||
grub_free (pass);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password.");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid PBKDF2 password"));
|
||||
}
|
||||
ptr++;
|
||||
|
||||
|
@ -114,7 +116,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (!ptr2 || ((ptr2 - ptr) & 1) || grub_strlen (ptr2 + 1) & 1)
|
||||
{
|
||||
grub_free (pass);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password.");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid PBKDF2 password"));
|
||||
}
|
||||
|
||||
pass->saltlen = (ptr2 - ptr) >> 1;
|
||||
|
@ -137,7 +139,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
|
|||
grub_free (pass->salt);
|
||||
grub_free (pass);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Incorrect PBKDF2 password.");
|
||||
N_("invalid PBKDF2 password"));
|
||||
}
|
||||
|
||||
*ptro = (hex1 << 4) | hex2;
|
||||
|
@ -166,7 +168,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
|
|||
grub_free (pass->salt);
|
||||
grub_free (pass);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Incorrect PBKDF2 password.");
|
||||
N_("invalid PBKDF2 password"));
|
||||
}
|
||||
|
||||
*ptro = (hex1 << 4) | hex2;
|
||||
|
|
|
@ -68,7 +68,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
else
|
||||
dev = grub_device_open (args[0]);
|
||||
if (! dev)
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "couldn't open device");
|
||||
return grub_errno;
|
||||
|
||||
if (state[1].set)
|
||||
{
|
||||
|
@ -96,7 +96,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
}
|
||||
fs = grub_fs_probe (dev);
|
||||
if (! fs)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_FS, "unrecognised fs");
|
||||
return grub_errno;
|
||||
if (state[3].set)
|
||||
{
|
||||
if (state[0].set)
|
||||
|
|
|
@ -24,13 +24,12 @@
|
|||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
static grub_err_t __attribute__ ((noreturn))
|
||||
grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
grub_reboot ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
|
|
@ -32,7 +32,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
|||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{ "set", 's', GRUB_ARG_OPTION_REPEATABLE,
|
||||
N_("Variable names to update with matches."),
|
||||
N_("Store matched component NUMBER in VARNAME."),
|
||||
N_("[NUMBER:]VARNAME"), ARG_TYPE_STRING },
|
||||
{ 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
@ -42,7 +42,6 @@ set_matches (char **varnames, char *str, grub_size_t nmatches,
|
|||
regmatch_t *matches)
|
||||
{
|
||||
int i;
|
||||
char ch;
|
||||
char *p;
|
||||
char *q;
|
||||
grub_err_t err;
|
||||
|
@ -51,6 +50,7 @@ set_matches (char **varnames, char *str, grub_size_t nmatches,
|
|||
auto void setvar (char *v, regmatch_t *m);
|
||||
void setvar (char *v, regmatch_t *m)
|
||||
{
|
||||
char ch;
|
||||
ch = str[m->rm_eo];
|
||||
str[m->rm_eo] = '\0';
|
||||
err = grub_env_set (v, str + m->rm_so);
|
||||
|
@ -59,7 +59,8 @@ set_matches (char **varnames, char *str, grub_size_t nmatches,
|
|||
|
||||
for (i = 0; varnames && varnames[i]; i++)
|
||||
{
|
||||
if (! (p = grub_strchr (varnames[i], ':')))
|
||||
p = grub_strchr (varnames[i], ':');
|
||||
if (! p)
|
||||
{
|
||||
/* varname w/o index defaults to 1 */
|
||||
if (nmatches < 2 || matches[1].rm_so == -1)
|
||||
|
@ -97,7 +98,7 @@ grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
regmatch_t *matches = 0;
|
||||
|
||||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "2 arguments expected");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
|
||||
|
||||
ret = regcomp (®ex, args[0], REG_EXTENDED);
|
||||
if (ret)
|
||||
|
|
|
@ -33,11 +33,21 @@
|
|||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
struct cache_entry
|
||||
{
|
||||
struct cache_entry *next;
|
||||
char *key;
|
||||
char *value;
|
||||
};
|
||||
|
||||
static struct cache_entry *cache;
|
||||
|
||||
void
|
||||
FUNC_NAME (const char *key, const char *var, int no_floppy,
|
||||
char **hints, unsigned nhints)
|
||||
{
|
||||
int count = 0;
|
||||
int is_cache = 0;
|
||||
grub_fs_autoload_hook_t saved_autoload;
|
||||
|
||||
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')
|
||||
return 0;
|
||||
|
||||
#ifdef DO_SEARCH_FS_UUID
|
||||
#define compare_fn grub_strcasecmp
|
||||
#else
|
||||
#define compare_fn grub_strcmp
|
||||
#endif
|
||||
|
||||
#ifdef DO_SEARCH_FILE
|
||||
{
|
||||
char *buf;
|
||||
|
@ -81,10 +97,8 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
|
|||
fs = grub_fs_probe (dev);
|
||||
|
||||
#ifdef DO_SEARCH_FS_UUID
|
||||
#define compare_fn grub_strcasecmp
|
||||
#define read_fn uuid
|
||||
#else
|
||||
#define compare_fn grub_strcmp
|
||||
#define read_fn label
|
||||
#endif
|
||||
|
||||
|
@ -106,6 +120,31 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
|
|||
}
|
||||
#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)
|
||||
{
|
||||
count++;
|
||||
|
@ -143,6 +182,32 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
|
|||
void try (void)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
char *end;
|
||||
|
@ -164,17 +229,20 @@ FUNC_NAME (const char *key, const char *var, int no_floppy,
|
|||
dev = grub_device_open (hints[i]);
|
||||
if (!dev)
|
||||
{
|
||||
*end = ',';
|
||||
if (!*end)
|
||||
*end = ',';
|
||||
continue;
|
||||
}
|
||||
if (!dev->disk)
|
||||
{
|
||||
grub_device_close (dev);
|
||||
*end = ',';
|
||||
if (!*end)
|
||||
*end = ',';
|
||||
continue;
|
||||
}
|
||||
ret = grub_partition_iterate (dev->disk, part_hook);
|
||||
*end = ',';
|
||||
if (!*end)
|
||||
*end = ',';
|
||||
grub_device_close (dev);
|
||||
if (ret)
|
||||
return;
|
||||
|
@ -209,7 +277,7 @@ grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc,
|
|||
char **args)
|
||||
{
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
|
||||
FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (args + 2),
|
||||
argc > 2 ? argc - 2 : 0);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#define DO_SEARCH_FILE 1
|
||||
#define FUNC_NAME grub_search_fs_file
|
||||
#define COMMAND_NAME "search.file"
|
||||
#define SEARCH_TARGET "file"
|
||||
#define HELP_MESSAGE N_("Search devices by file. If VARIABLE is specified, the first device found is set to a variable.")
|
||||
#include "search.c"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#define DO_SEARCH_FS_LABEL 1
|
||||
#define FUNC_NAME grub_search_label
|
||||
#define COMMAND_NAME "search.fs_label"
|
||||
#define SEARCH_TARGET "filesystem label"
|
||||
#define HELP_MESSAGE N_("Search devices by label. If VARIABLE is specified, the first device found is set to a variable.")
|
||||
#include "search.c"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#define DO_SEARCH_FS_UUID 1
|
||||
#define FUNC_NAME grub_search_fs_uuid
|
||||
#define COMMAND_NAME "search.fs_uuid"
|
||||
#define SEARCH_TARGET "filesystem UUID"
|
||||
#define HELP_MESSAGE N_("Search devices by UUID. If VARIABLE is specified, the first device found is set to a variable.")
|
||||
#include "search.c"
|
||||
|
|
|
@ -42,6 +42,21 @@ static const struct grub_arg_option options[] =
|
|||
{"hint", 'h', GRUB_ARG_OPTION_REPEATABLE,
|
||||
N_("First try the device HINT. If HINT ends in comma, "
|
||||
"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}
|
||||
};
|
||||
|
||||
|
@ -52,7 +67,12 @@ enum options
|
|||
SEARCH_FS_UUID,
|
||||
SEARCH_SET,
|
||||
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
|
||||
|
@ -60,27 +80,98 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
const char *var = 0;
|
||||
int nhints = 0;
|
||||
int i = 0, j = 0, nhints = 0;
|
||||
char **hints = NULL;
|
||||
|
||||
if (state[SEARCH_HINT].set)
|
||||
while (state[SEARCH_HINT].args[nhints])
|
||||
for (i = 0; state[SEARCH_HINT].args[i]; i++)
|
||||
nhints++;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified");
|
||||
#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, N_("one argument expected"));
|
||||
|
||||
if (state[SEARCH_SET].set)
|
||||
var = state[SEARCH_SET].arg ? state[SEARCH_SET].arg : "root";
|
||||
|
||||
if (state[SEARCH_LABEL].set)
|
||||
grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set,
|
||||
state[SEARCH_HINT].args, nhints);
|
||||
grub_search_label (args[j], var, state[SEARCH_NO_FLOPPY].set,
|
||||
hints, nhints);
|
||||
else if (state[SEARCH_FS_UUID].set)
|
||||
grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set,
|
||||
state[SEARCH_HINT].args, nhints);
|
||||
grub_search_fs_uuid (args[j], var, state[SEARCH_NO_FLOPPY].set,
|
||||
hints, nhints);
|
||||
else if (state[SEARCH_FILE].set)
|
||||
grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set,
|
||||
state[SEARCH_HINT].args, nhints);
|
||||
grub_search_fs_file (args[j], var, state[SEARCH_NO_FLOPPY].set,
|
||||
hints, nhints);
|
||||
else
|
||||
return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type");
|
||||
|
||||
|
@ -92,7 +183,8 @@ static grub_extcmd_t cmd;
|
|||
GRUB_MOD_INIT(search)
|
||||
{
|
||||
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] ...]"
|
||||
" NAME"),
|
||||
N_("Search devices by file, filesystem label"
|
||||
|
|
|
@ -128,7 +128,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid)
|
|||
|
||||
if (!write_mask)
|
||||
{
|
||||
grub_printf (N_("Register %x of %d:%d.%d is %x\n"), regaddr,
|
||||
grub_printf (_("Register %x of %d:%d.%d is %x\n"), regaddr,
|
||||
grub_pci_get_bus (dev),
|
||||
grub_pci_get_device (dev),
|
||||
grub_pci_get_function (dev),
|
||||
|
@ -179,7 +179,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
|
|||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (*ptr != ':')
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Colon expected.");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':');
|
||||
ptr++;
|
||||
pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff)
|
||||
<< 16;
|
||||
|
@ -210,7 +210,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
|
|||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (*ptr != ':')
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Colon expected.");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':');
|
||||
ptr++;
|
||||
optr = ptr;
|
||||
device = grub_strtoul (ptr, (char **) &ptr, 16);
|
||||
|
@ -238,11 +238,8 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
|
|||
|
||||
write_mask = 0;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Command expected.");
|
||||
|
||||
if (argc > 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Only one command is supported.");
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
|
||||
ptr = argv[0];
|
||||
|
||||
|
@ -257,7 +254,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
|
|||
regsize = 0;
|
||||
regaddr = grub_strtoul (ptr, (char **) &ptr, 16);
|
||||
if (grub_errno)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown register");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown register");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -298,7 +295,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
|
|||
|
||||
if (!regsize)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Unknown register size.");
|
||||
"unknown register size");
|
||||
|
||||
write_mask = 0;
|
||||
if (*ptr == '=')
|
||||
|
@ -321,7 +318,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
|
|||
|
||||
if (write_mask && varname)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"Option -v isn't valid for writes.");
|
||||
"option -v isn't valid for writes");
|
||||
|
||||
grub_pci_iterate (grub_setpci_iter);
|
||||
return GRUB_ERR_NONE;
|
||||
|
|
|
@ -54,7 +54,7 @@ grub_interruptible_millisleep (grub_uint32_t ms)
|
|||
start = grub_get_time_ms ();
|
||||
|
||||
while (grub_get_time_ms () - start < ms)
|
||||
if (grub_checkkey () >= 0 && grub_getkey () == GRUB_TERM_ESC)
|
||||
if (grub_getkey_noblock () == GRUB_TERM_ESC)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -67,7 +67,7 @@ grub_cmd_sleep (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
int n;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing operand");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected"));
|
||||
|
||||
n = grub_strtoul (args[0], 0, 10);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ struct grub_term_autoload *grub_term_output_autoload = NULL;
|
|||
struct abstract_terminal
|
||||
{
|
||||
struct abstract_terminal *next;
|
||||
struct abstract_terminal *prev;
|
||||
const char *name;
|
||||
grub_err_t (*init) (struct abstract_terminal *term);
|
||||
grub_err_t (*fini) (struct abstract_terminal *term);
|
||||
|
@ -94,19 +95,26 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
|||
while (1)
|
||||
{
|
||||
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;
|
||||
if (term == 0)
|
||||
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;
|
||||
if (term)
|
||||
break;
|
||||
if (again)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("terminal `%s' isn't found"),
|
||||
args[i]);
|
||||
for (aut = autoloads; aut; aut = aut->next)
|
||||
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] == '*'
|
||||
&& grub_memcmp (args[i], aut->name,
|
||||
grub_strlen (aut->name) - 1) == 0))
|
||||
|
@ -119,7 +127,8 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
|||
break;
|
||||
}
|
||||
if (!aut)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("terminal `%s' isn't found"),
|
||||
args[i]);
|
||||
again = 1;
|
||||
}
|
||||
|
@ -130,14 +139,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
|||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
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;
|
||||
if (term)
|
||||
{
|
||||
if (term->init && term->init (term) != GRUB_ERR_NONE)
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -149,14 +160,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
|||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
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;
|
||||
if (term)
|
||||
{
|
||||
if (!term->next && term == *enabled)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"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)
|
||||
term->fini (term);
|
||||
grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
|
||||
|
@ -167,14 +180,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
|||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
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;
|
||||
if (term)
|
||||
{
|
||||
if (term->init && term->init (term) != GRUB_ERR_NONE)
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -185,14 +200,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled,
|
|||
{
|
||||
next = term->next;
|
||||
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;
|
||||
if (i == argc)
|
||||
{
|
||||
if (!term->next && term == *enabled)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"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)
|
||||
term->fini (term);
|
||||
grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term));
|
||||
|
@ -208,6 +225,7 @@ grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)),
|
|||
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 *, prev);
|
||||
(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 *, fini);
|
||||
|
@ -224,6 +242,7 @@ grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)),
|
|||
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 *, prev);
|
||||
(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 *, fini);
|
||||
|
|
|
@ -416,7 +416,7 @@ grub_cmd_test (grub_command_t cmd __attribute__ ((unused)),
|
|||
argc--;
|
||||
|
||||
return test_parse (args, &argn, argc) ? GRUB_ERR_NONE
|
||||
: grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
: grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
|
||||
}
|
||||
|
||||
static grub_command_t cmd_1, cmd_2;
|
||||
|
|
|
@ -50,7 +50,7 @@ grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)),
|
|||
}
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
file = grub_file_open (argv[0]);
|
||||
if (! file)
|
||||
|
|
|
@ -35,12 +35,12 @@ grub_cmd_time (grub_command_t ctxt __attribute__ ((unused)),
|
|||
grub_uint32_t end;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "command expected");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("no command is specified"));
|
||||
|
||||
cmd = grub_command_find (args[0]);
|
||||
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_COMMAND, "Unknown command `%s'\n",
|
||||
return grub_error (GRUB_ERR_UNKNOWN_COMMAND, N_("can't find command `%s'"),
|
||||
args[0]);
|
||||
|
||||
start = grub_get_time_ms ();
|
||||
|
|
|
@ -36,7 +36,7 @@ grub_cmd_false (struct grub_command *cmd __attribute__ ((unused)),
|
|||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, N_("false"));
|
||||
}
|
||||
|
||||
static grub_command_t cmd_true, cmd_false;
|
||||
|
@ -46,9 +46,13 @@ GRUB_MOD_INIT(true)
|
|||
{
|
||||
cmd_true =
|
||||
grub_register_command ("true", grub_cmd_true,
|
||||
/* TRANSLATORS: it's imperative, not
|
||||
infinitive. */
|
||||
0, N_("Do nothing, successfully."));
|
||||
cmd_false =
|
||||
grub_register_command ("false", grub_cmd_false,
|
||||
/* TRANSLATORS: it's imperative, not
|
||||
infinitive. */
|
||||
0, N_("Do nothing, unsuccessfully."));
|
||||
}
|
||||
|
||||
|
|
|
@ -126,7 +126,9 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (*ptr != 'x')
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid mode specification");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("invalid video mode specification `%s'"),
|
||||
args[0]);
|
||||
ptr++;
|
||||
height = grub_strtoul (ptr, &ptr, 0);
|
||||
if (grub_errno)
|
||||
|
@ -178,7 +180,7 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
|
|||
{
|
||||
if (adapter->init ())
|
||||
{
|
||||
grub_puts_ (N_(" Failed"));
|
||||
grub_puts_ (N_(" Failed to initialize video adapter"));
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -74,6 +74,8 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
|
|||
grub_video_create_render_target (&text_layer, width, height,
|
||||
GRUB_VIDEO_MODE_TYPE_RGB
|
||||
| GRUB_VIDEO_MODE_TYPE_ALPHA);
|
||||
if (!text_layer)
|
||||
goto fail;
|
||||
|
||||
grub_video_set_active_render_target (text_layer);
|
||||
|
||||
|
@ -114,13 +116,13 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
|
|||
U+03C4 Greek tau CF 84
|
||||
U+00E4 lowercase letter a with umlaut C3 A4
|
||||
U+2124 set 'Z' symbol (integers) E2 84 A4
|
||||
U+2287 subset symbol E2 8A 87
|
||||
U+2286 subset symbol E2 8A 86
|
||||
U+211D set 'R' symbol (real numbers) E2 84 9D */
|
||||
|
||||
str =
|
||||
"Unicode test: happy\xE2\x98\xBA \xC2\xA3 5.00"
|
||||
" \xC2\xA1\xCF\x84\xC3\xA4u! "
|
||||
" \xE2\x84\xA4\xE2\x8A\x87\xE2\x84\x9D";
|
||||
" \xE2\x84\xA4\xE2\x8A\x86\xE2\x84\x9D";
|
||||
color = grub_video_map_rgb (128, 128, 255);
|
||||
|
||||
/* All characters in the string exist in the 'Fixed 20' (10x20) font. */
|
||||
|
@ -191,6 +193,11 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return grub_errno;
|
||||
|
||||
fail:
|
||||
grub_video_delete_render_target (text_layer);
|
||||
grub_video_restore ();
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
@ -201,7 +208,7 @@ static grub_command_t cmd_vbe;
|
|||
GRUB_MOD_INIT(videotest)
|
||||
{
|
||||
cmd = grub_register_command ("videotest", grub_cmd_videotest,
|
||||
"[WxH]",
|
||||
N_("[WxH]"),
|
||||
N_("Test video subsystem in mode WxH."));
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
cmd_vbe = grub_register_command ("vbetest", grub_cmd_videotest,
|
||||
|
|
|
@ -326,10 +326,15 @@ match_files (const char *prefix, const char *suffix, const char *end,
|
|||
if (! fs)
|
||||
goto fail;
|
||||
|
||||
path = grub_strchr (dir, ')');
|
||||
if (! path)
|
||||
goto fail;
|
||||
path++;
|
||||
if (dir[0] == '(')
|
||||
{
|
||||
path = grub_strchr (dir, ')');
|
||||
if (!path)
|
||||
goto fail;
|
||||
path++;
|
||||
}
|
||||
else
|
||||
path = dir;
|
||||
|
||||
if (fs->dir (dev, path, match))
|
||||
goto fail;
|
||||
|
@ -431,25 +436,8 @@ wildcard_expand (const char *s, char ***strs)
|
|||
if (start == noregexop) /* device part has regexop */
|
||||
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);
|
||||
|
||||
else if (*start == '/') /* no device part */
|
||||
{
|
||||
const 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
|
||||
{
|
||||
|
|
|
@ -121,6 +121,7 @@ enum
|
|||
struct grub_ahci_device
|
||||
{
|
||||
struct grub_ahci_device *next;
|
||||
struct grub_ahci_device **prev;
|
||||
volatile struct grub_ahci_hba *hba;
|
||||
int port;
|
||||
int num;
|
||||
|
@ -305,7 +306,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
|
|||
else
|
||||
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");
|
||||
else
|
||||
grub_dprintf ("ahci", "AHCI is in AHCI mode.\n");
|
||||
|
@ -542,10 +543,10 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
|||
(unsigned long long) parms->cmdsize);
|
||||
|
||||
if (parms->cmdsize != 0 && parms->cmdsize != 12 && parms->cmdsize != 16)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "incorrect ATAPI command size");
|
||||
return grub_error (GRUB_ERR_BUG, "incorrect ATAPI command size");
|
||||
|
||||
if (parms->size > GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too big data buffer");
|
||||
return grub_error (GRUB_ERR_BUG, "too big data buffer");
|
||||
|
||||
bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1));
|
||||
|
||||
|
@ -625,7 +626,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
|||
dev->hba->ports[dev->port].command_issue,
|
||||
dev->hba->ports[dev->port].intstatus,
|
||||
dev->hba->ports[dev->port].task_file_data);
|
||||
err = grub_error (GRUB_ERR_IO, "AHCI transfer timeouted");
|
||||
err = grub_error (GRUB_ERR_IO, "AHCI transfer timed out");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -692,6 +693,7 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata)
|
|||
|
||||
ata->data = dev;
|
||||
ata->dma = 1;
|
||||
ata->maxbuffer = GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH;
|
||||
ata->present = &dev->present;
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -21,9 +21,11 @@
|
|||
#include <grub/disk.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/arc/arc.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_arc_fileno_t last_handle = 0;
|
||||
static char *last_path = NULL;
|
||||
static int handle_writable = 0;
|
||||
|
||||
static int lnum = 0;
|
||||
|
||||
|
@ -100,11 +102,12 @@ grub_arcdisk_iterate (int (*hook_in) (const char *name),
|
|||
#define RAW_SUFFIX "partition(10)"
|
||||
|
||||
static grub_err_t
|
||||
reopen (const char *name)
|
||||
reopen (const char *name, int writable)
|
||||
{
|
||||
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);
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -115,12 +118,16 @@ reopen (const char *name)
|
|||
grub_free (last_path);
|
||||
last_path = NULL;
|
||||
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);
|
||||
return grub_error (GRUB_ERR_IO, "couldn't open %s", name);
|
||||
}
|
||||
handle_writable = writable;
|
||||
last_path = grub_strdup (name);
|
||||
if (!last_path)
|
||||
return grub_errno;
|
||||
|
@ -180,7 +187,7 @@ grub_arcdisk_open (const char *name, grub_disk_t disk)
|
|||
if (!hash)
|
||||
return grub_errno;
|
||||
|
||||
err = reopen (fullname);
|
||||
err = reopen (fullname, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -234,7 +241,7 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
grub_uint64_t totl = size << 9;
|
||||
grub_arc_err_t r;
|
||||
|
||||
err = reopen (disk->data);
|
||||
err = reopen (disk->data, 0);
|
||||
if (err)
|
||||
return err;
|
||||
r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0);
|
||||
|
@ -249,7 +256,11 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
{
|
||||
if (GRUB_ARC_FIRMWARE_VECTOR->read (last_handle, buf,
|
||||
totl, &count))
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "read failed");
|
||||
return grub_error (GRUB_ERR_READ_ERROR,
|
||||
N_("failure reading sector 0x%llx "
|
||||
"from `%s'"),
|
||||
(unsigned long long) sector,
|
||||
disk->name);
|
||||
totl -= count;
|
||||
buf += count;
|
||||
}
|
||||
|
@ -258,12 +269,39 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_arcdisk_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)))
|
||||
grub_arcdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_size_t size, const char *buf)
|
||||
{
|
||||
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, N_("failure writing sector 0x%llx "
|
||||
"to `%s'"),
|
||||
(unsigned long long) sector,
|
||||
disk->name);
|
||||
totl -= count;
|
||||
buf += count;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
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. */
|
||||
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;
|
||||
|
||||
for (i = 0; i < len / 2; i++)
|
||||
*(dst16++) = grub_be_to_cpu16 (*(src16++));
|
||||
dst[len] = '\0';
|
||||
dst16[i] = 0;
|
||||
}
|
||||
|
||||
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. */
|
||||
grub_ata_strncpy (text, info + 20, 20);
|
||||
grub_dprintf ("ata", "Serial: %s\n", text);
|
||||
grub_ata_strncpy (text, info + 46, 8);
|
||||
grub_dprintf ("ata", "Firmware: %s\n", text);
|
||||
grub_ata_strncpy (text, info + 54, 40);
|
||||
grub_dprintf ("ata", "Model: %s\n", text);
|
||||
grub_ata_strncpy (text, info + 10, 20);
|
||||
grub_dprintf ("ata", "Serial: %s\n", (char *) text);
|
||||
grub_ata_strncpy (text, info + 23, 8);
|
||||
grub_dprintf ("ata", "Firmware: %s\n", (char *) text);
|
||||
grub_ata_strncpy (text, info + 27, 40);
|
||||
grub_dprintf ("ata", "Model: %s\n", (char *) text);
|
||||
|
||||
if (! dev->atapi)
|
||||
{
|
||||
|
@ -65,7 +63,7 @@ static grub_err_t
|
|||
grub_atapi_identify (struct grub_ata *dev)
|
||||
{
|
||||
struct grub_disk_ata_pass_through_parms parms;
|
||||
char *info;
|
||||
grub_uint16_t *info;
|
||||
grub_err_t err;
|
||||
|
||||
info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
|
||||
|
@ -105,17 +103,19 @@ static grub_err_t
|
|||
grub_ata_identify (struct grub_ata *dev)
|
||||
{
|
||||
struct grub_disk_ata_pass_through_parms parms;
|
||||
char *info;
|
||||
grub_uint64_t *info64;
|
||||
grub_uint32_t *info32;
|
||||
grub_uint16_t *info16;
|
||||
grub_err_t err;
|
||||
|
||||
info = grub_malloc (GRUB_DISK_SECTOR_SIZE);
|
||||
if (! info)
|
||||
info64 = grub_malloc (GRUB_DISK_SECTOR_SIZE);
|
||||
info32 = (grub_uint32_t *) info64;
|
||||
info16 = (grub_uint16_t *) info64;
|
||||
if (! info16)
|
||||
return grub_errno;
|
||||
|
||||
info16 = (grub_uint16_t *) info;
|
||||
grub_memset (&parms, 0, sizeof (parms));
|
||||
parms.buffer = info;
|
||||
parms.buffer = info16;
|
||||
parms.size = GRUB_DISK_SECTOR_SIZE;
|
||||
parms.taskfile.disk = 0xE0;
|
||||
|
||||
|
@ -126,7 +126,7 @@ grub_ata_identify (struct grub_ata *dev)
|
|||
if (err || parms.size != GRUB_DISK_SECTOR_SIZE)
|
||||
{
|
||||
grub_uint8_t sts = parms.taskfile.status;
|
||||
grub_free (info);
|
||||
grub_free (info16);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ
|
||||
| GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR
|
||||
|
@ -167,14 +167,14 @@ grub_ata_identify (struct grub_ata *dev)
|
|||
|
||||
/* Determine the amount of sectors. */
|
||||
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
|
||||
dev->size = grub_le_to_cpu64(*((grub_uint64_t *) &info16[100]));
|
||||
dev->size = grub_le_to_cpu64 (info64[25]);
|
||||
|
||||
if (info16[106] & (1 << 12))
|
||||
{
|
||||
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
|
||||
|| secsize > 1048576)
|
||||
secsize = 256;
|
||||
|
@ -191,9 +191,9 @@ grub_ata_identify (struct grub_ata *dev)
|
|||
dev->heads = info16[3];
|
||||
dev->sectors_per_track = info16[6];
|
||||
|
||||
grub_ata_dumpinfo (dev, info);
|
||||
grub_ata_dumpinfo (dev, info16);
|
||||
|
||||
grub_free(info);
|
||||
grub_free (info16);
|
||||
|
||||
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_size_t batch;
|
||||
int cmd, cmd_write;
|
||||
grub_size_t nsectors = 0;
|
||||
|
||||
grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n",
|
||||
(unsigned long long) size, rw);
|
||||
|
@ -314,9 +315,11 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
cmd = GRUB_ATA_CMD_READ_SECTORS;
|
||||
cmd_write = GRUB_ATA_CMD_WRITE_SECTORS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (batch > (ata->maxbuffer >> ata->log_sector_size))
|
||||
batch = (ata->maxbuffer >> ata->log_sector_size);
|
||||
|
||||
grub_size_t nsectors = 0;
|
||||
while (nsectors < size)
|
||||
{
|
||||
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)),
|
||||
char *cmd __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.
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ATAPI write not implemented");
|
||||
|
|
|
@ -41,7 +41,7 @@ static const struct grub_arg_option options[] =
|
|||
{
|
||||
{"uuid", 'u', 0, N_("Mount by UUID."), 0, 0},
|
||||
{"all", 'a', 0, N_("Mount all."), 0, 0},
|
||||
{"boot", 'b', 0, N_("Mount all volumes marked as boot."), 0, 0},
|
||||
{"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -128,6 +128,29 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
|
|||
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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
gcry_err_code_t
|
||||
grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
||||
grub_uint8_t * data, grub_size_t len,
|
||||
grub_disk_addr_t sector)
|
||||
static gcry_err_code_t
|
||||
grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev,
|
||||
grub_uint8_t * data, grub_size_t len,
|
||||
grub_disk_addr_t sector, int do_encrypt)
|
||||
{
|
||||
grub_size_t i;
|
||||
gcry_err_code_t err;
|
||||
|
||||
/* The only mode without IV. */
|
||||
if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey)
|
||||
return grub_crypto_ecb_decrypt (dev->cipher, data, data, len);
|
||||
return (do_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))
|
||||
{
|
||||
|
@ -269,15 +293,23 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
|||
switch (dev->mode)
|
||||
{
|
||||
case GRUB_CRYPTODISK_MODE_CBC:
|
||||
err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
|
||||
(1U << dev->log_sector_size), iv);
|
||||
if (do_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,
|
||||
(1U << dev->log_sector_size), iv);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
||||
case GRUB_CRYPTODISK_MODE_PCBC:
|
||||
err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
|
||||
(1U << dev->log_sector_size), iv);
|
||||
if (do_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,
|
||||
(1U << dev->log_sector_size), iv);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
@ -294,9 +326,14 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
|||
{
|
||||
grub_crypto_xor (data + i + j, data + i + j, iv,
|
||||
dev->cipher->cipher->blocksize);
|
||||
err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j,
|
||||
data + i + j,
|
||||
dev->cipher->cipher->blocksize);
|
||||
if (do_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,
|
||||
data + i + j,
|
||||
dev->cipher->cipher->blocksize);
|
||||
if (err)
|
||||
return err;
|
||||
grub_crypto_xor (data + i + j, data + i + j, iv,
|
||||
|
@ -312,17 +349,26 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
|||
generate_lrw_sector (&sec, dev, (grub_uint8_t *) iv);
|
||||
lrw_xor (&sec, dev, data + i);
|
||||
|
||||
err = grub_crypto_ecb_decrypt (dev->cipher, data + i,
|
||||
data + i,
|
||||
(1U << dev->log_sector_size));
|
||||
if (do_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,
|
||||
data + i,
|
||||
(1U << dev->log_sector_size));
|
||||
if (err)
|
||||
return err;
|
||||
lrw_xor (&sec, dev, data + i);
|
||||
}
|
||||
break;
|
||||
case GRUB_CRYPTODISK_MODE_ECB:
|
||||
grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
|
||||
(1U << dev->log_sector_size));
|
||||
if (do_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,
|
||||
(1U << dev->log_sector_size));
|
||||
break;
|
||||
default:
|
||||
return GPG_ERR_NOT_IMPLEMENTED;
|
||||
|
@ -332,6 +378,14 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
|||
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
|
||||
grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t keysize)
|
||||
{
|
||||
|
@ -447,7 +501,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk)
|
|||
if (dev->cheat_fd == -1)
|
||||
dev->cheat_fd = open (dev->cheat, O_RDONLY);
|
||||
if (dev->cheat_fd == -1)
|
||||
return grub_error (GRUB_ERR_IO, "couldn't open %s: %s",
|
||||
return grub_error (GRUB_ERR_IO, N_("cannot open `%s': %s"),
|
||||
dev->cheat, strerror (errno));
|
||||
}
|
||||
#endif
|
||||
|
@ -506,8 +560,8 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
return err;
|
||||
if (grub_util_fd_read (dev->cheat_fd, buf, size << disk->log_sector_size)
|
||||
!= (ssize_t) (size << disk->log_sector_size))
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'",
|
||||
dev->cheat);
|
||||
return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"),
|
||||
dev->cheat, strerror (errno));
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
#endif
|
||||
|
@ -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);
|
||||
return err;
|
||||
}
|
||||
gcry_err = grub_cryptodisk_decrypt (dev, (grub_uint8_t *) buf,
|
||||
size << disk->log_sector_size,
|
||||
sector);
|
||||
gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf,
|
||||
size << disk->log_sector_size,
|
||||
sector, 0);
|
||||
return grub_crypto_gcry_error (gcry_err);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cryptodisk_write (grub_disk_t disk __attribute ((unused)),
|
||||
grub_disk_addr_t sector __attribute ((unused)),
|
||||
grub_size_t size __attribute ((unused)),
|
||||
const char *buf __attribute ((unused)))
|
||||
grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_size_t size, const char *buf)
|
||||
{
|
||||
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, N_("cannot read `%s': %s"),
|
||||
dev->cheat, strerror (errno));
|
||||
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
|
||||
|
@ -562,6 +658,7 @@ grub_cryptodisk_memberlist (grub_disk_t disk)
|
|||
static void
|
||||
cryptodisk_cleanup (void)
|
||||
{
|
||||
#if 0
|
||||
grub_cryptodisk_t dev = cryptodisk_list;
|
||||
grub_cryptodisk_t tmp;
|
||||
|
||||
|
@ -575,6 +672,7 @@ cryptodisk_cleanup (void)
|
|||
grub_free (dev);
|
||||
dev = tmp;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
|
|
1116
grub-core/disk/diskfilter.c
Normal file
1116
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/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/raid.h>
|
||||
#include <grub/diskfilter.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -90,70 +90,91 @@ struct grub_nv_super
|
|||
struct grub_nv_array array; /* Array information */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static grub_err_t
|
||||
grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array,
|
||||
grub_disk_addr_t *start_sector)
|
||||
static struct grub_diskfilter_vg *
|
||||
grub_dmraid_nv_detect (grub_disk_t disk,
|
||||
struct grub_diskfilter_pv_id *id,
|
||||
grub_disk_addr_t *start_sector)
|
||||
{
|
||||
grub_disk_addr_t sector;
|
||||
struct grub_nv_super sb;
|
||||
int level;
|
||||
int layout;
|
||||
grub_uint64_t disk_size;
|
||||
char *uuid;
|
||||
|
||||
if (disk->partition)
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "skip partition");
|
||||
|
||||
sector = grub_disk_get_size (disk) - 2;
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_RANGE, "skip partition");
|
||||
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))
|
||||
return grub_errno;
|
||||
return NULL;
|
||||
|
||||
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)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unknown version: %d.%d", sb.version);
|
||||
{
|
||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unknown version: %d.%d", sb.version);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (sb.array.raid_level)
|
||||
{
|
||||
case NV_LEVEL_0:
|
||||
array->level = 0;
|
||||
array->disk_size = sb.capacity / sb.array.total_volumes;
|
||||
level = 0;
|
||||
disk_size = sb.capacity / sb.array.total_volumes;
|
||||
break;
|
||||
|
||||
case NV_LEVEL_1:
|
||||
array->level = 1;
|
||||
array->disk_size = sb.capacity;
|
||||
level = 1;
|
||||
disk_size = sb.capacity;
|
||||
break;
|
||||
|
||||
case NV_LEVEL_5:
|
||||
array->level = 5;
|
||||
array->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
|
||||
array->disk_size = sb.capacity / (sb.array.total_volumes - 1);
|
||||
level = 5;
|
||||
layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC;
|
||||
disk_size = sb.capacity / (sb.array.total_volumes - 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unsupported RAID level: %d", sb.array.raid_level);
|
||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unsupported RAID level: %d", sb.array.raid_level);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
array->name = NULL;
|
||||
array->number = 0;
|
||||
array->total_devs = sb.array.total_volumes;
|
||||
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;
|
||||
uuid = grub_malloc (sizeof (sb.array.signature));
|
||||
if (! uuid)
|
||||
return NULL;
|
||||
|
||||
grub_memcpy (array->uuid, (char *) &sb.array.signature,
|
||||
grub_memcpy (uuid, (char *) &sb.array.signature,
|
||||
sizeof (sb.array.signature));
|
||||
|
||||
id->uuidlen = 0;
|
||||
id->id = sb.unit_number;
|
||||
|
||||
*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",
|
||||
.detect = grub_dmraid_nv_detect,
|
||||
|
@ -162,10 +183,10 @@ static struct grub_raid grub_dmraid_nv_dev =
|
|||
|
||||
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_raid_unregister (&grub_dmraid_nv_dev);
|
||||
grub_diskfilter_unregister (&grub_dmraid_nv_dev);
|
||||
}
|
||||
|
|
|
@ -533,7 +533,10 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector,
|
|||
(grub_efi_uintn_t) size << disk->log_sector_size,
|
||||
buf);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error");
|
||||
return grub_error (GRUB_ERR_READ_ERROR,
|
||||
N_("failure reading sector 0x%llx from `%s'"),
|
||||
(unsigned long long) sector,
|
||||
disk->name);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
@ -559,7 +562,9 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector,
|
|||
(grub_efi_uintn_t) size << disk->log_sector_size,
|
||||
(void *) buf);
|
||||
if (status != GRUB_EFI_SUCCESS)
|
||||
return grub_error (GRUB_ERR_WRITE_ERROR, "efidisk write error");
|
||||
return grub_error (GRUB_ERR_WRITE_ERROR,
|
||||
N_("failure writing sector 0x%llx to `%s'"),
|
||||
(unsigned long long) sector, disk->name);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
@ -664,38 +669,52 @@ grub_efidisk_get_device_handle (grub_disk_t disk)
|
|||
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 *
|
||||
grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
||||
{
|
||||
grub_efi_device_path_t *dp, *ldp, *sdp;
|
||||
/* This is a hard disk partition. */
|
||||
grub_disk_t parent = 0;
|
||||
auto int find_parent_disk (const char *name);
|
||||
|
||||
/* Find the disk which is the parent of a given hard disk partition. */
|
||||
int find_parent_disk (const char *name)
|
||||
{
|
||||
grub_disk_t disk;
|
||||
|
||||
disk = grub_disk_open (name);
|
||||
if (! disk)
|
||||
return 1;
|
||||
|
||||
if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID)
|
||||
{
|
||||
struct grub_efidisk_data *d;
|
||||
|
||||
d = disk->data;
|
||||
if (grub_efi_compare_device_paths (d->device_path, sdp) == 0)
|
||||
{
|
||||
parent = disk;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
grub_disk_close (disk);
|
||||
return 0;
|
||||
}
|
||||
grub_efi_device_path_t *dp, *ldp;
|
||||
char device_name[NEEDED_BUFLEN];
|
||||
|
||||
dp = grub_efi_get_device_path (handle);
|
||||
if (! dp)
|
||||
|
@ -710,9 +729,11 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
|||
== GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))
|
||||
{
|
||||
char *partition_name = NULL;
|
||||
char *device_name;
|
||||
char *dev_name;
|
||||
grub_efi_device_path_t *dup_dp, *dup_ldp;
|
||||
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);
|
||||
|
||||
/* Find the identical partition. */
|
||||
|
@ -741,11 +762,9 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
|||
dup_ldp->length[0] = sizeof (*dup_ldp);
|
||||
dup_ldp->length[1] = 0;
|
||||
|
||||
sdp = dup_dp;
|
||||
|
||||
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_NONE);
|
||||
if (!parent)
|
||||
grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_REMOVABLE);
|
||||
if (!get_diskname_from_path (dup_dp, device_name))
|
||||
return 0;
|
||||
parent = grub_disk_open (device_name);
|
||||
grub_free (dup_dp);
|
||||
|
||||
if (! parent)
|
||||
|
@ -756,7 +775,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
|||
if (hd.partition_start == 0
|
||||
&& hd.partition_size == grub_disk_get_size (parent))
|
||||
{
|
||||
device_name = grub_strdup (parent->name);
|
||||
dev_name = grub_strdup (parent->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -768,29 +787,18 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
|
|||
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_disk_close (parent);
|
||||
|
||||
return device_name;
|
||||
return dev_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This should be an entire disk. */
|
||||
char *device_name = 0;
|
||||
|
||||
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;
|
||||
if (!get_diskname_from_path (dp, device_name))
|
||||
return 0;
|
||||
return grub_strdup (device_name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ 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");
|
||||
grub_util_error ("%s", _("Coulnd't load sha256"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ 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");
|
||||
grub_util_error ("%s", _("Coulnd't load sha512"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -221,12 +221,12 @@ grub_util_get_geli_uuid (const char *dev)
|
|||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
s = grub_util_get_fd_sectors (fd, &log_secsize);
|
||||
s = grub_util_get_fd_sectors (fd, dev, &log_secsize);
|
||||
grub_util_fd_seek (fd, dev, (s << log_secsize) - 512);
|
||||
|
||||
uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1);
|
||||
if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0)
|
||||
grub_util_error (_("couldn't read ELI metadata"));
|
||||
grub_util_error ("%s", _("couldn't read ELI metadata"));
|
||||
|
||||
COMPILE_TIME_ASSERT (sizeof (header) <= 512);
|
||||
header = (void *) &hdr;
|
||||
|
@ -235,7 +235,7 @@ grub_util_get_geli_uuid (const char *dev)
|
|||
if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC))
|
||||
|| grub_le_to_cpu32 (header->version) > 5
|
||||
|| grub_le_to_cpu32 (header->version) < 1)
|
||||
grub_util_error (_("wrong ELI magic or version"));
|
||||
grub_util_error ("%s", _("wrong ELI magic or version"));
|
||||
|
||||
err = make_uuid ((void *) &hdr, uuid);
|
||||
if (err)
|
||||
|
@ -408,7 +408,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
|
|||
|
||||
sector = grub_disk_get_size (source);
|
||||
if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not a geli");
|
||||
return grub_error (GRUB_ERR_BUG, "not a geli");
|
||||
|
||||
/* Read the GELI header. */
|
||||
err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header);
|
||||
|
|
|
@ -465,14 +465,17 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
|
|||
int i;
|
||||
|
||||
if (cmd)
|
||||
return grub_error (GRUB_ERR_WRITE_ERROR, "can\'t write to cdrom");
|
||||
return grub_error (GRUB_ERR_WRITE_ERROR, N_("cannot write to cdrom"));
|
||||
|
||||
for (i = 0; i < GRUB_BIOSDISK_CDROM_RETRY_COUNT; i++)
|
||||
if (! grub_biosdisk_rw_int13_extensions (0x42, data->drive, dap))
|
||||
break;
|
||||
|
||||
if (i == GRUB_BIOSDISK_CDROM_RETRY_COUNT)
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "cdrom read error");
|
||||
return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx "
|
||||
"from `%s'"),
|
||||
(unsigned long long) sector,
|
||||
disk->name);
|
||||
}
|
||||
else
|
||||
if (grub_biosdisk_rw_int13_extensions (cmd + 0x42, data->drive, dap))
|
||||
|
@ -494,7 +497,9 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
|
|||
1024 /* cylinders */ *
|
||||
256 /* heads */ *
|
||||
63 /* spt */)
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "%s out of disk", disk->name);
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
N_("attempt to read or write outside of disk `%s'"),
|
||||
disk->name);
|
||||
|
||||
soff = ((grub_uint32_t) sector) % data->sectors + 1;
|
||||
head = ((grub_uint32_t) sector) / data->sectors;
|
||||
|
@ -502,7 +507,9 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
|
|||
coff = head / data->heads;
|
||||
|
||||
if (coff >= data->cylinders)
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "%s out of disk", disk->name);
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
N_("attempt to read or write outside of disk `%s'"),
|
||||
disk->name);
|
||||
|
||||
if (grub_biosdisk_rw_standard (cmd + 0x02, data->drive,
|
||||
coff, hoff, soff, size, segment))
|
||||
|
@ -510,9 +517,15 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk,
|
|||
switch (cmd)
|
||||
{
|
||||
case GRUB_BIOSDISK_READ:
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "%s read error", disk->name);
|
||||
return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx "
|
||||
"from `%s'"),
|
||||
(unsigned long long) sector,
|
||||
disk->name);
|
||||
case GRUB_BIOSDISK_WRITE:
|
||||
return grub_error (GRUB_ERR_WRITE_ERROR, "%s write error", disk->name);
|
||||
return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx "
|
||||
"to `%s'"),
|
||||
(unsigned long long) sector,
|
||||
disk->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -576,7 +589,7 @@ grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
struct grub_biosdisk_data *data = disk->data;
|
||||
|
||||
if (data->flags & GRUB_BIOSDISK_FLAG_CDROM)
|
||||
return grub_error (GRUB_ERR_IO, "can't write to CDROM");
|
||||
return grub_error (GRUB_ERR_IO, N_("cannot write to cdrom"));
|
||||
|
||||
while (size)
|
||||
{
|
||||
|
@ -627,7 +640,8 @@ GRUB_MOD_INIT(biosdisk)
|
|||
|
||||
if (grub_disk_firmware_is_tainted)
|
||||
{
|
||||
grub_puts_ (N_("Firmware is marked as tainted, refusing to initialize."));
|
||||
grub_puts_ (N_("Native disk drivers are in use. "
|
||||
"Refusing to use firmware disk interface."));
|
||||
return;
|
||||
}
|
||||
grub_disk_firmware_fini = grub_disk_biosdisk_fini;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/ieee1275/ieee1275.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -177,7 +178,10 @@ grub_nand_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
args.result = 1;
|
||||
|
||||
if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.result))
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "read error");
|
||||
return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx "
|
||||
"from `%s'"),
|
||||
(unsigned long long) sector,
|
||||
disk->name);
|
||||
|
||||
ofs = 0;
|
||||
size -= len;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/ieee1275/ieee1275.h>
|
||||
#include <grub/ieee1275/ofdisk.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static char *last_devpath;
|
||||
static grub_ieee1275_ihandle_t last_ihandle;
|
||||
|
@ -198,8 +199,14 @@ grub_ofdisk_iterate (int (*hook) (const char *name),
|
|||
if (grub_strncmp (ent->shortest, "cdrom", 5) == 0)
|
||||
continue;
|
||||
|
||||
if (hook (ent->shortest))
|
||||
return 1;
|
||||
{
|
||||
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 0;
|
||||
|
@ -241,7 +248,10 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
|
|||
char prop[64];
|
||||
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)
|
||||
return grub_errno;
|
||||
|
||||
|
@ -264,7 +274,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
|
|||
if (grub_strcmp (prop, "block"))
|
||||
{
|
||||
grub_free (devpath);
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device");
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device");
|
||||
}
|
||||
|
||||
/* XXX: There is no property to read the number of blocks. There
|
||||
|
@ -302,10 +312,9 @@ grub_ofdisk_close (grub_disk_t disk)
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_size_t size, char *buf)
|
||||
grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector)
|
||||
{
|
||||
grub_ssize_t status, actual;
|
||||
grub_ssize_t status;
|
||||
unsigned long long pos;
|
||||
|
||||
if (disk->data != last_devpath)
|
||||
|
@ -334,28 +343,54 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
last_devpath = disk->data;
|
||||
}
|
||||
|
||||
pos = sector * 512UL;
|
||||
pos = sector << GRUB_DISK_SECTOR_BITS;
|
||||
|
||||
grub_ieee1275_seek (last_ihandle, pos, &status);
|
||||
if (status < 0)
|
||||
return grub_error (GRUB_ERR_READ_ERROR,
|
||||
"seek error, can't seek block %llu",
|
||||
(long long) sector);
|
||||
grub_ieee1275_read (last_ihandle, buf, size * 512UL, &actual);
|
||||
if (actual != (grub_ssize_t) (size * 512UL))
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu",
|
||||
(long long) sector);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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, N_("failure reading sector 0x%llx "
|
||||
"from `%s'"),
|
||||
(unsigned long long) sector,
|
||||
disk->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_ofdisk_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)))
|
||||
grub_ofdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_size_t size, const char *buf)
|
||||
{
|
||||
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, N_("failure writing sector 0x%llx "
|
||||
"to `%s'"),
|
||||
(unsigned long long) sector,
|
||||
disk->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct grub_disk_dev grub_ofdisk_dev =
|
||||
|
|
996
grub-core/disk/ldm.c
Normal file
996
grub-core/disk/ldm.c
Normal file
|
@ -0,0 +1,996 @@
|
|||
/*
|
||||
* 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>
|
||||
#include <grub/i18n.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;
|
||||
|
||||
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,
|
||||
"LDM curently supports only PC-BIOS embedding");
|
||||
if (disk->partition)
|
||||
return grub_error (GRUB_ERR_BUG, "disk isn't LDM");
|
||||
pv = grub_diskfilter_get_pv_from_disk (disk, &vg);
|
||||
if (!pv)
|
||||
return grub_error (GRUB_ERR_BUG, "disk isn't LDM");
|
||||
for (lv = vg->lvs; lv; lv = lv->next)
|
||||
{
|
||||
struct grub_diskfilter_lv *comp;
|
||||
|
||||
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,
|
||||
N_("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,
|
||||
N_("this LDM has 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);
|
||||
}
|
|
@ -38,7 +38,7 @@ static struct grub_loopback *loopback_list;
|
|||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"delete", 'd', 0, N_("Delete the loopback device entry."), 0, 0},
|
||||
{"delete", 'd', 0, N_("Delete the specified loopback drive."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -86,7 +86,7 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
return delete_loopback (args[0]);
|
||||
|
||||
if (argc < 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
|
||||
file = grub_file_open (args[1]);
|
||||
if (! file)
|
||||
|
@ -224,7 +224,7 @@ GRUB_MOD_INIT(loopback)
|
|||
{
|
||||
cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, 0,
|
||||
N_("[-d] DEVICENAME FILE."),
|
||||
N_("Make a device of a file."), options);
|
||||
N_("Make a virtual drive from a file."), options);
|
||||
grub_disk_dev_register (&grub_loopback_dev);
|
||||
}
|
||||
|
||||
|
|
1585
grub-core/disk/lvm.c
1585
grub-core/disk/lvm.c
File diff suppressed because it is too large
Load diff
|
@ -22,7 +22,7 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/raid.h>
|
||||
#include <grub/diskfilter.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -103,8 +103,9 @@ struct grub_raid_super_1x
|
|||
|
||||
#define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */
|
||||
|
||||
static grub_err_t
|
||||
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
||||
static struct grub_diskfilter_vg *
|
||||
grub_mdraid_detect (grub_disk_t disk,
|
||||
struct grub_diskfilter_pv_id *id,
|
||||
grub_disk_addr_t *start_sector)
|
||||
{
|
||||
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),
|
||||
&sb))
|
||||
return grub_errno;
|
||||
return NULL;
|
||||
|
||||
if (grub_le_to_cpu32 (sb.magic) != SB_MAGIC
|
||||
|| 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;
|
||||
|
||||
if (grub_le_to_cpu32 (sb.major_version) != 1)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"Unsupported RAID version: %d",
|
||||
grub_le_to_cpu32 (sb.major_version));
|
||||
{
|
||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"Unsupported RAID version: %d",
|
||||
grub_le_to_cpu32 (sb.major_version));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 &&
|
||||
level != 5 && level != 6 && level != 10)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"Unsupported RAID level: %d", sb.level);
|
||||
{
|
||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"Unsupported RAID level: %d", sb.level);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
@ -175,62 +182,68 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
|||
+ 2 * grub_le_to_cpu32 (sb.max_dev);
|
||||
real_sb = grub_malloc (sb_size);
|
||||
if (! real_sb)
|
||||
return grub_errno;
|
||||
return NULL;
|
||||
|
||||
if (grub_disk_read (disk, sector, 0, sb_size, real_sb))
|
||||
{
|
||||
grub_free (real_sb);
|
||||
return grub_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
array->name = grub_strdup (real_sb->set_name);
|
||||
if (! array->name)
|
||||
{
|
||||
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);
|
||||
struct grub_diskfilter_vg *array;
|
||||
char *uuid;
|
||||
|
||||
if (grub_le_to_cpu32 (real_sb->dev_number) >=
|
||||
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);
|
||||
return grub_errno;
|
||||
grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
"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);
|
||||
|
||||
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);
|
||||
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",
|
||||
.detect = grub_mdraid_detect,
|
||||
.next = 0
|
||||
|
@ -238,10 +251,10 @@ static struct grub_raid grub_mdraid_dev = {
|
|||
|
||||
GRUB_MOD_INIT (mdraid1x)
|
||||
{
|
||||
grub_raid_register (&grub_mdraid_dev);
|
||||
grub_diskfilter_register (&grub_mdraid_dev);
|
||||
}
|
||||
|
||||
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/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/raid.h>
|
||||
#include <grub/diskfilter.h>
|
||||
|
||||
/* Linux RAID on disk structures and constants,
|
||||
copied from include/linux/raid/md_p.h. */
|
||||
|
@ -161,8 +161,9 @@ struct grub_raid_super_09
|
|||
struct grub_raid_disk_09 this_disk;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static grub_err_t
|
||||
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
||||
static struct grub_diskfilter_vg *
|
||||
grub_mdraid_detect (grub_disk_t disk,
|
||||
struct grub_diskfilter_pv_id *id,
|
||||
grub_disk_addr_t *start_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. */
|
||||
size = grub_disk_get_size (disk);
|
||||
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);
|
||||
|
||||
if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb))
|
||||
return grub_errno;
|
||||
return NULL;
|
||||
|
||||
/* Look whether there is a mdraid 0.90 superblock. */
|
||||
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
|
||||
|| grub_le_to_cpu32 (sb.minor_version) != 90)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unsupported RAID version: %d.%d",
|
||||
grub_le_to_cpu32 (sb.major_version),
|
||||
grub_le_to_cpu32 (sb.minor_version));
|
||||
{
|
||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unsupported RAID version: %d.%d",
|
||||
grub_le_to_cpu32 (sb.major_version),
|
||||
grub_le_to_cpu32 (sb.minor_version));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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 &&
|
||||
level != 5 && level != 6 && level != 10)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unsupported RAID level: %d", level);
|
||||
{
|
||||
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"unsupported RAID level: %d", level);
|
||||
return NULL;
|
||||
}
|
||||
if (grub_le_to_cpu32 (sb.this_disk.number) == 0xffff
|
||||
|| grub_le_to_cpu32 (sb.this_disk.number) == 0xfffe)
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
"spares aren't implemented");
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
"spares aren't implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
array->name = NULL;
|
||||
array->number = grub_le_to_cpu32 (sb.md_minor);
|
||||
array->level = level;
|
||||
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_malloc (16);
|
||||
if (!uuid)
|
||||
return NULL;
|
||||
|
||||
uuid = (grub_uint32_t *) array->uuid;
|
||||
uuid[0] = grub_swap_bytes32 (sb.set_uuid0);
|
||||
uuid[1] = grub_swap_bytes32 (sb.set_uuid1);
|
||||
uuid[2] = grub_swap_bytes32 (sb.set_uuid2);
|
||||
|
@ -228,10 +234,21 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
|
|||
|
||||
*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",
|
||||
.detect = grub_mdraid_detect,
|
||||
.next = 0
|
||||
|
@ -239,10 +256,10 @@ static struct grub_raid grub_mdraid_dev = {
|
|||
|
||||
GRUB_MOD_INIT (mdraid09)
|
||||
{
|
||||
grub_raid_register (&grub_mdraid_dev);
|
||||
grub_diskfilter_register (&grub_mdraid_dev);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (mdraid09)
|
||||
{
|
||||
grub_raid_unregister (&grub_mdraid_dev);
|
||||
grub_diskfilter_unregister (&grub_mdraid_dev);
|
||||
}
|
||||
|
|
|
@ -116,12 +116,13 @@ grub_pata_wait (void)
|
|||
static void
|
||||
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;
|
||||
|
||||
/* Read in the data, word by word. */
|
||||
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)
|
||||
buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress
|
||||
+ 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
|
||||
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;
|
||||
|
||||
/* Write the data, word by word. */
|
||||
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. */
|
||||
|
@ -484,6 +484,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata)
|
|||
|
||||
ata->data = devfnd;
|
||||
ata->dma = 0;
|
||||
ata->maxbuffer = 256 * 512;
|
||||
ata->present = &devfnd->present;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
|
|
@ -1,939 +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>
|
||||
#include <grub/partition.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_partition_get_start (m->device->partition)
|
||||
== grub_partition_get_start (disk->partition)
|
||||
&& grub_disk_get_size (m->device)
|
||||
== grub_disk_get_size (disk))
|
||||
{
|
||||
grub_disk_close (disk);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((disk->total_sectors != GRUB_ULONG_MAX) &&
|
||||
(! raid->detect (disk, &array, &start_sector)) &&
|
||||
(! insert_array (disk, &array, start_sector, raid->name,
|
||||
raid)))
|
||||
return 0;
|
||||
|
||||
/* This error usually means it's not raid, no need to display
|
||||
it. */
|
||||
if (grub_errno != GRUB_ERR_OUT_OF_RANGE)
|
||||
grub_print_error ();
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
grub_disk_close (disk);
|
||||
|
||||
if (arname && find_array (arname))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (scan_depth)
|
||||
return;
|
||||
|
||||
scan_depth++;
|
||||
for (raid = grub_raid_list; raid; raid = raid->next)
|
||||
grub_device_iterate (&hook);
|
||||
scan_depth--;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_raid_iterate (int (*hook) (const char *name),
|
||||
grub_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/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/raid.h>
|
||||
#include <grub/diskfilter.h>
|
||||
#include <grub/crypto.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
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 *buf2;
|
||||
|
@ -40,16 +41,15 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr,
|
|||
|
||||
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;
|
||||
|
||||
if (i == disknr)
|
||||
continue;
|
||||
|
||||
err = grub_disk_read (array->members[i].device,
|
||||
array->members[i].start_sector + sector,
|
||||
0, size, buf2);
|
||||
err = grub_diskfilter_read_node (&array->nodes[i], sector,
|
||||
size >> GRUB_DISK_SECTOR_BITS, buf2);
|
||||
|
||||
if (err)
|
||||
{
|
||||
|
@ -57,7 +57,7 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr,
|
|||
return err;
|
||||
}
|
||||
|
||||
grub_raid_block_xor (buf, buf2, size);
|
||||
grub_crypto_xor (buf, buf, buf2, size);
|
||||
}
|
||||
|
||||
grub_free (buf2);
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/raid.h>
|
||||
#include <grub/diskfilter.h>
|
||||
#include <grub/crypto.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -63,7 +64,7 @@ grub_raid6_init_table (void)
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int i, q, pos;
|
||||
|
@ -80,27 +81,30 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
|
|||
goto quit;
|
||||
|
||||
q = p + 1;
|
||||
if (q == (int) array->total_devs)
|
||||
if (q == (int) array->node_count)
|
||||
q = 0;
|
||||
|
||||
pos = q + 1;
|
||||
if (pos == (int) array->total_devs)
|
||||
if (pos == (int) array->node_count)
|
||||
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)
|
||||
bad1 = i;
|
||||
bad1 = c;
|
||||
else
|
||||
{
|
||||
if ((array->members[pos].device) &&
|
||||
(! grub_disk_read (array->members[pos].device,
|
||||
array->members[pos].start_sector + sector,
|
||||
0, size, buf)))
|
||||
if (! grub_diskfilter_read_node (&array->nodes[pos], sector,
|
||||
size >> GRUB_DISK_SECTOR_BITS, buf))
|
||||
{
|
||||
grub_raid_block_xor (pbuf, buf, size);
|
||||
grub_raid_block_mulx (i, buf, size);
|
||||
grub_raid_block_xor (qbuf, buf, size);
|
||||
grub_crypto_xor (pbuf, pbuf, buf, size);
|
||||
grub_raid_block_mulx (c, buf, size);
|
||||
grub_crypto_xor (qbuf, qbuf, buf, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -108,13 +112,13 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
|
|||
if (bad2 >= 0)
|
||||
goto quit;
|
||||
|
||||
bad2 = i;
|
||||
bad2 = c;
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
pos++;
|
||||
if (pos == (int) array->total_devs)
|
||||
if (pos == (int) array->node_count)
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
|
@ -125,27 +129,19 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
|
|||
if (bad2 < 0)
|
||||
{
|
||||
/* One bad device */
|
||||
if ((array->members[p].device) &&
|
||||
(! grub_disk_read (array->members[p].device,
|
||||
array->members[p].start_sector + sector,
|
||||
0, size, buf)))
|
||||
if ((! grub_diskfilter_read_node (&array->nodes[p], sector,
|
||||
size >> GRUB_DISK_SECTOR_BITS, buf)))
|
||||
{
|
||||
grub_raid_block_xor (buf, pbuf, size);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (! array->members[q].device)
|
||||
{
|
||||
grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore");
|
||||
grub_crypto_xor (buf, buf, pbuf, size);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
if (grub_disk_read (array->members[q].device,
|
||||
array->members[q].start_sector + sector, 0, size, buf))
|
||||
if (grub_diskfilter_read_node (&array->nodes[q], sector,
|
||||
size >> GRUB_DISK_SECTOR_BITS, buf))
|
||||
goto quit;
|
||||
|
||||
grub_raid_block_xor (buf, qbuf, size);
|
||||
grub_crypto_xor (buf, buf, qbuf, size);
|
||||
grub_raid_block_mulx (255 - bad1, buf,
|
||||
size);
|
||||
}
|
||||
|
@ -154,25 +150,17 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
|
|||
/* Two bad devices */
|
||||
int c;
|
||||
|
||||
if ((! array->members[p].device) || (! array->members[q].device))
|
||||
{
|
||||
grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore");
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (grub_disk_read (array->members[p].device,
|
||||
array->members[p].start_sector + sector,
|
||||
0, size, buf))
|
||||
if (grub_diskfilter_read_node (&array->nodes[p], sector,
|
||||
size >> GRUB_DISK_SECTOR_BITS, buf))
|
||||
goto quit;
|
||||
|
||||
grub_raid_block_xor (pbuf, buf, size);
|
||||
grub_crypto_xor (pbuf, pbuf, buf, size);
|
||||
|
||||
if (grub_disk_read (array->members[q].device,
|
||||
array->members[q].start_sector + sector,
|
||||
0, size, buf))
|
||||
if (grub_diskfilter_read_node (&array->nodes[q], sector,
|
||||
size >> GRUB_DISK_SECTOR_BITS, buf))
|
||||
goto quit;
|
||||
|
||||
grub_raid_block_xor (qbuf, buf, size);
|
||||
grub_crypto_xor (qbuf, qbuf, buf, size);
|
||||
|
||||
c = (255 - bad1 + (255 - powx_inv[(powx[bad2 - bad1 + 255] ^ 1)])) % 255;
|
||||
grub_raid_block_mulx (c, qbuf, size);
|
||||
|
@ -180,7 +168,7 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
|
|||
c = (bad2 + c) % 255;
|
||||
grub_raid_block_mulx (c, pbuf, size);
|
||||
|
||||
grub_raid_block_xor (pbuf, qbuf, size);
|
||||
grub_crypto_xor (pbuf, pbuf, qbuf, size);
|
||||
grub_memcpy (buf, pbuf, size);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <grub/scsi.h>
|
||||
#include <grub/scsicmd.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
@ -153,14 +154,14 @@ grub_scsi_inquiry (grub_scsi_t scsi)
|
|||
|
||||
/* Read the capacity and block size of SCSI. */
|
||||
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_capacity_data rcd;
|
||||
struct grub_scsi_read_capacity10 rc;
|
||||
struct grub_scsi_read_capacity10_data rcd;
|
||||
grub_err_t err;
|
||||
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.logical_block_addr = 0;
|
||||
rc.reserved1 = 0;
|
||||
|
@ -182,7 +183,42 @@ grub_scsi_read_capacity (grub_scsi_t scsi)
|
|||
if (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);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -253,12 +289,43 @@ grub_scsi_read12 (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
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
|
||||
sectors starting with SECTOR. */
|
||||
static grub_err_t
|
||||
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;
|
||||
struct grub_scsi_write10 wr;
|
||||
|
@ -287,6 +354,8 @@ grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
return err;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/* Send a SCSI request for DISK: write the data stored in BUF to SIZE
|
||||
sectors starting with SECTOR. */
|
||||
static grub_err_t
|
||||
|
@ -320,6 +389,39 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
}
|
||||
#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
|
||||
grub_scsi_iterate (int (*hook) (const char *name),
|
||||
|
@ -475,15 +577,26 @@ grub_scsi_open (const char *name, grub_disk_t disk)
|
|||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
/* Read capacity of media */
|
||||
err = grub_scsi_read_capacity (scsi);
|
||||
err = grub_scsi_read_capacity10 (scsi);
|
||||
if (err)
|
||||
{
|
||||
grub_free (scsi);
|
||||
grub_dprintf ("scsi", "READ CAPACITY failed\n");
|
||||
grub_dprintf ("scsi", "READ CAPACITY10 failed\n");
|
||||
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)
|
||||
{
|
||||
grub_free (scsi);
|
||||
|
@ -491,11 +604,11 @@ grub_scsi_open (const char *name, grub_disk_t disk)
|
|||
scsi->blocksize);
|
||||
}
|
||||
for (disk->log_sector_size = 0;
|
||||
(1 << disk->log_sector_size) < scsi->blocksize;
|
||||
(1U << disk->log_sector_size) < scsi->blocksize;
|
||||
disk->log_sector_size++);
|
||||
|
||||
grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n",
|
||||
scsi->size, scsi->blocksize);
|
||||
grub_dprintf ("scsi", "last_block=%" PRIuGRUB_UINT64_T ", blocksize=%u\n",
|
||||
scsi->last_block, scsi->blocksize);
|
||||
grub_dprintf ("scsi", "Disk total sectors = %llu\n",
|
||||
(unsigned long long) disk->total_sectors);
|
||||
|
||||
|
@ -539,13 +652,19 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
switch (scsi->devtype)
|
||||
{
|
||||
case grub_scsi_devtype_direct:
|
||||
err = grub_scsi_read10 (disk, sector, len, buf);
|
||||
if (sector >> 32)
|
||||
err = grub_scsi_read16 (disk, sector, len, buf);
|
||||
else
|
||||
err = grub_scsi_read10 (disk, sector, len, buf);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
||||
case grub_scsi_devtype_cdrom:
|
||||
err = grub_scsi_read12 (disk, sector, len, buf);
|
||||
if (sector >> 32)
|
||||
err = grub_scsi_read16 (disk, sector, len, buf);
|
||||
else
|
||||
err = grub_scsi_read12 (disk, sector, len, buf);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
@ -595,13 +714,41 @@ grub_scsi_write (grub_disk_t disk __attribute((unused)),
|
|||
grub_size_t size __attribute((unused)),
|
||||
const char *buf __attribute((unused)))
|
||||
{
|
||||
#if 0
|
||||
/* XXX: Not tested yet! */
|
||||
grub_scsi_t scsi;
|
||||
|
||||
/* XXX: This should depend on the device type? */
|
||||
return grub_scsi_write10 (disk, sector, size, buf);
|
||||
#endif
|
||||
return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
||||
scsi = disk->data;
|
||||
|
||||
if (scsi->devtype == grub_scsi_devtype_cdrom)
|
||||
return grub_error (GRUB_ERR_IO, N_("cannot write to cdrom"));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,6 +28,12 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
|||
|
||||
#define GRUB_USBMS_DIRECTION_BIT 7
|
||||
|
||||
/* Length of CBI command should be always 12 bytes */
|
||||
#define GRUB_USBMS_CBI_CMD_SIZE 12
|
||||
/* CBI class-specific USB request ADSC - it sends CBI (scsi) command to
|
||||
* device in DATA stage */
|
||||
#define GRUB_USBMS_CBI_ADSC_REQ 0x00
|
||||
|
||||
/* The USB Mass Storage Command Block Wrapper. */
|
||||
struct grub_usbms_cbw
|
||||
{
|
||||
|
@ -59,8 +65,9 @@ struct grub_usbms_dev
|
|||
struct grub_usb_desc_endp *in;
|
||||
struct grub_usb_desc_endp *out;
|
||||
|
||||
int in_maxsz;
|
||||
int out_maxsz;
|
||||
int subclass;
|
||||
int protocol;
|
||||
struct grub_usb_desc_endp *intrpt;
|
||||
};
|
||||
typedef struct grub_usbms_dev *grub_usbms_dev_t;
|
||||
|
||||
|
@ -70,7 +77,39 @@ static grub_usbms_dev_t grub_usbms_devices[MAX_USBMS_DEVICES];
|
|||
static int first_available_slot = 0;
|
||||
|
||||
static grub_err_t
|
||||
grub_usbms_reset (grub_usb_device_t dev, int interface)
|
||||
grub_usbms_cbi_cmd (grub_usb_device_t dev, int interface,
|
||||
grub_uint8_t *cbicb)
|
||||
{
|
||||
return grub_usb_control_msg (dev,
|
||||
GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT,
|
||||
GRUB_USBMS_CBI_ADSC_REQ, 0, interface,
|
||||
GRUB_USBMS_CBI_CMD_SIZE, (char*)cbicb);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_usbms_cbi_reset (grub_usb_device_t dev, int interface)
|
||||
{
|
||||
/* Prepare array with Command Block Reset (=CBR) */
|
||||
/* CBI specific communication reset command should be send to device
|
||||
* via CBI USB class specific request ADCS */
|
||||
struct grub_cbi_reset
|
||||
{
|
||||
grub_uint8_t opcode; /* 0x1d = SEND DIAGNOSTIC */
|
||||
grub_uint8_t lun; /* 7-5 LUN, 4-0 flags - for CBR always = 0x04 */
|
||||
grub_uint8_t pad[10];
|
||||
/* XXX: There is collision between CBI and UFI specifications:
|
||||
* CBI says 0xff, UFI says 0x00 ... probably it does
|
||||
* not matter ... (?) */
|
||||
} cbicb = { 0x1d, 0x04,
|
||||
{ 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff }
|
||||
};
|
||||
|
||||
return grub_usbms_cbi_cmd (dev, interface, (grub_uint8_t *)&cbicb);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_usbms_bo_reset (grub_usb_device_t dev, int interface)
|
||||
{
|
||||
grub_usb_err_t u;
|
||||
u = grub_usb_control_msg (dev, 0x21, 255, 0, interface, 0, 0);
|
||||
|
@ -79,6 +118,15 @@ grub_usbms_reset (grub_usb_device_t dev, int interface)
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_usbms_reset (grub_usbms_dev_t dev)
|
||||
{
|
||||
if (dev->protocol == GRUB_USBMS_PROTOCOL_BULK)
|
||||
return grub_usbms_bo_reset (dev->dev, dev->interface);
|
||||
else
|
||||
return grub_usbms_cbi_reset (dev->dev, dev->interface);
|
||||
}
|
||||
|
||||
static void
|
||||
grub_usbms_detach (grub_usb_device_t usbdev, int config, int interface)
|
||||
{
|
||||
|
@ -101,7 +149,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
|||
int j;
|
||||
grub_uint8_t luns = 0;
|
||||
unsigned curnum;
|
||||
grub_usb_err_t err;
|
||||
grub_usb_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
if (first_available_slot == ARRAY_SIZE (grub_usbms_devices))
|
||||
return 0;
|
||||
|
@ -117,7 +165,9 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
|||
&& interf->subclass != GRUB_USBMS_SUBCLASS_MMC2
|
||||
&& interf->subclass != GRUB_USBMS_SUBCLASS_UFI
|
||||
&& interf->subclass != GRUB_USBMS_SUBCLASS_SFF8070 )
|
||||
|| interf->protocol != GRUB_USBMS_PROTOCOL_BULK)
|
||||
|| (interf->protocol != GRUB_USBMS_PROTOCOL_BULK
|
||||
&& interf->protocol != GRUB_USBMS_PROTOCOL_CBI
|
||||
&& interf->protocol != GRUB_USBMS_PROTOCOL_CB))
|
||||
return 0;
|
||||
|
||||
grub_usbms_devices[curnum] = grub_zalloc (sizeof (struct grub_usbms_dev));
|
||||
|
@ -126,6 +176,8 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
|||
|
||||
grub_usbms_devices[curnum]->dev = usbdev;
|
||||
grub_usbms_devices[curnum]->interface = interfno;
|
||||
grub_usbms_devices[curnum]->subclass = interf->subclass;
|
||||
grub_usbms_devices[curnum]->protocol = interf->protocol;
|
||||
|
||||
grub_dprintf ("usbms", "alive\n");
|
||||
|
||||
|
@ -137,24 +189,19 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
|||
endp = &usbdev->config[0].interf[interfno].descendp[j];
|
||||
|
||||
if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2)
|
||||
{
|
||||
/* Bulk IN endpoint. */
|
||||
grub_usbms_devices[curnum]->in = endp;
|
||||
/* Clear Halt is not possible yet! */
|
||||
/* grub_usb_clear_halt (usbdev, endp->endp_addr); */
|
||||
grub_usbms_devices[curnum]->in_maxsz = endp->maxpacket;
|
||||
}
|
||||
/* Bulk IN endpoint. */
|
||||
grub_usbms_devices[curnum]->in = endp;
|
||||
else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2)
|
||||
{
|
||||
/* Bulk OUT endpoint. */
|
||||
grub_usbms_devices[curnum]->out = endp;
|
||||
/* Clear Halt is not possible yet! */
|
||||
/* grub_usb_clear_halt (usbdev, endp->endp_addr); */
|
||||
grub_usbms_devices[curnum]->out_maxsz = endp->maxpacket;
|
||||
}
|
||||
/* Bulk OUT endpoint. */
|
||||
grub_usbms_devices[curnum]->out = endp;
|
||||
else if ((endp->endp_addr & 128) && (endp->attrib & 3) == 3)
|
||||
/* Interrupt (IN) endpoint. */
|
||||
grub_usbms_devices[curnum]->intrpt = endp;
|
||||
}
|
||||
|
||||
if (!grub_usbms_devices[curnum]->in || !grub_usbms_devices[curnum]->out)
|
||||
if (!grub_usbms_devices[curnum]->in || !grub_usbms_devices[curnum]->out
|
||||
|| ((grub_usbms_devices[curnum]->protocol == GRUB_USBMS_PROTOCOL_CBI)
|
||||
&& !grub_usbms_devices[curnum]->intrpt))
|
||||
{
|
||||
grub_free (grub_usbms_devices[curnum]);
|
||||
grub_usbms_devices[curnum] = 0;
|
||||
|
@ -167,27 +214,34 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
|||
grub_usb_set_configuration (usbdev, 1);
|
||||
|
||||
/* Query the amount of LUNs. */
|
||||
err = grub_usb_control_msg (usbdev, 0xA1, 254, 0, interfno, 1, (char *) &luns);
|
||||
|
||||
if (err)
|
||||
{
|
||||
/* In case of a stall, clear the stall. */
|
||||
if (err == GRUB_USB_ERR_STALL)
|
||||
{
|
||||
grub_usb_clear_halt (usbdev, grub_usbms_devices[curnum]->in->endp_addr);
|
||||
grub_usb_clear_halt (usbdev, grub_usbms_devices[curnum]->out->endp_addr);
|
||||
}
|
||||
/* Just set the amount of LUNs to one. */
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
grub_usbms_devices[curnum]->luns = 1;
|
||||
if (grub_usbms_devices[curnum]->protocol == GRUB_USBMS_PROTOCOL_BULK)
|
||||
{ /* Only Bulk only devices support Get Max LUN command */
|
||||
err = grub_usb_control_msg (usbdev, 0xA1, 254, 0, interfno, 1, (char *) &luns);
|
||||
|
||||
if (err)
|
||||
{
|
||||
/* In case of a stall, clear the stall. */
|
||||
if (err == GRUB_USB_ERR_STALL)
|
||||
{
|
||||
grub_usb_clear_halt (usbdev, grub_usbms_devices[curnum]->in->endp_addr);
|
||||
grub_usb_clear_halt (usbdev, grub_usbms_devices[curnum]->out->endp_addr);
|
||||
}
|
||||
/* Just set the amount of LUNs to one. */
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
grub_usbms_devices[curnum]->luns = 1;
|
||||
}
|
||||
else
|
||||
/* luns = 0 means one LUN with ID 0 present ! */
|
||||
/* We get from device not number of LUNs but highest
|
||||
* LUN number. LUNs are numbered from 0,
|
||||
* i.e. number of LUNs is luns+1 ! */
|
||||
grub_usbms_devices[curnum]->luns = luns + 1;
|
||||
}
|
||||
else
|
||||
/* luns = 0 means one LUN with ID 0 present ! */
|
||||
/* We get from device not number of LUNs but highest
|
||||
* LUN number. LUNs are numbered from 0,
|
||||
* i.e. number of LUNs is luns+1 ! */
|
||||
grub_usbms_devices[curnum]->luns = luns + 1;
|
||||
|
||||
/* XXX: Does CBI devices support multiple LUNs ?
|
||||
* I.e., should we detect number of device's LUNs ? (How?) */
|
||||
grub_usbms_devices[curnum]->luns = 1;
|
||||
|
||||
grub_dprintf ("usbms", "alive\n");
|
||||
|
||||
usbdev->config[configno].interf[interfno].detach_hook = grub_usbms_detach;
|
||||
|
@ -232,8 +286,8 @@ grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns),
|
|||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||
grub_size_t size, char *buf, int read_write)
|
||||
grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||
grub_size_t size, char *buf, int read_write)
|
||||
{
|
||||
struct grub_usbms_cbw cbw;
|
||||
grub_usbms_dev_t dev = (grub_usbms_dev_t) scsi->data;
|
||||
|
@ -242,7 +296,7 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
|||
grub_usb_err_t err = GRUB_USB_ERR_NONE;
|
||||
grub_usb_err_t errCSW = GRUB_USB_ERR_NONE;
|
||||
int retrycnt = 3 + 1;
|
||||
|
||||
|
||||
retry:
|
||||
retrycnt--;
|
||||
if (retrycnt == 0)
|
||||
|
@ -343,7 +397,7 @@ CheckCSW:
|
|||
if (errCSW)
|
||||
{ /* Bulk-only reset device. */
|
||||
grub_dprintf ("usb", "Bulk-only reset device - errCSW\n");
|
||||
grub_usbms_reset (dev->dev, dev->interface);
|
||||
grub_usbms_reset (dev);
|
||||
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
||||
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
||||
goto retry;
|
||||
|
@ -360,7 +414,7 @@ CheckCSW:
|
|||
(status.signature != grub_cpu_to_le32(0x53425355)))
|
||||
{ /* Bulk-only reset device. */
|
||||
grub_dprintf ("usb", "Bulk-only reset device - bad status\n");
|
||||
grub_usbms_reset (dev->dev, dev->interface);
|
||||
grub_usbms_reset (dev);
|
||||
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
||||
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
||||
|
||||
|
@ -378,6 +432,158 @@ CheckCSW:
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||
grub_size_t size, char *buf, int read_write)
|
||||
{
|
||||
grub_usbms_dev_t dev = (grub_usbms_dev_t) scsi->data;
|
||||
int retrycnt = 3 + 1;
|
||||
grub_usb_err_t err = GRUB_USB_ERR_NONE;
|
||||
grub_uint8_t cbicb[GRUB_USBMS_CBI_CMD_SIZE];
|
||||
grub_uint16_t status;
|
||||
|
||||
retry:
|
||||
retrycnt--;
|
||||
if (retrycnt == 0)
|
||||
return grub_error (GRUB_ERR_IO, "USB Mass Storage CBI failed");
|
||||
|
||||
/* Setup the request. */
|
||||
grub_memset (cbicb, 0, sizeof (cbicb));
|
||||
grub_memcpy (cbicb, cmd,
|
||||
cmdsize >= GRUB_USBMS_CBI_CMD_SIZE
|
||||
? GRUB_USBMS_CBI_CMD_SIZE
|
||||
: cmdsize);
|
||||
|
||||
/* Debug print of CBIcb content. */
|
||||
grub_dprintf ("usb", "cbicb:\n %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
cbicb[ 0], cbicb[ 1], cbicb[ 2], cbicb[ 3],
|
||||
cbicb[ 4], cbicb[ 5], cbicb[ 6], cbicb[ 7],
|
||||
cbicb[ 8], cbicb[ 9], cbicb[10], cbicb[11]);
|
||||
|
||||
/* Write the request.
|
||||
* XXX: Error recovery is maybe not correct. */
|
||||
err = grub_usbms_cbi_cmd (dev->dev, dev->interface, cbicb);
|
||||
if (err)
|
||||
{
|
||||
grub_dprintf ("usb", "CBI cmdcb setup err=%d\n", err);
|
||||
if (err == GRUB_USB_ERR_STALL)
|
||||
{
|
||||
/* Stall in this place probably means bad or unsupported
|
||||
* command, so we will not try it again. */
|
||||
return grub_error (GRUB_ERR_IO, "USB Mass Storage CBI request failed");
|
||||
}
|
||||
else if (dev->protocol == GRUB_USBMS_PROTOCOL_CBI)
|
||||
{
|
||||
/* Try to get status from interrupt pipe */
|
||||
err = grub_usb_bulk_read (dev->dev, dev->intrpt->endp_addr,
|
||||
2, (char*)&status);
|
||||
grub_dprintf ("usb", "CBI cmdcb setup status: err=%d, status=0x%x\n", err, status);
|
||||
}
|
||||
/* Any other error could be transport problem, try it again */
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* Read/write the data, (maybe) according to specification. */
|
||||
if (size && (read_write == 0))
|
||||
{
|
||||
err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, size, buf);
|
||||
grub_dprintf ("usb", "read: %d\n", err);
|
||||
if (err)
|
||||
{
|
||||
if (err == GRUB_USB_ERR_STALL)
|
||||
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
else if (size)
|
||||
{
|
||||
err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf);
|
||||
grub_dprintf ("usb", "write: %d\n", err);
|
||||
if (err)
|
||||
{
|
||||
if (err == GRUB_USB_ERR_STALL)
|
||||
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: It is not clear to me yet, how to check status of CBI
|
||||
* data transfer on devices without interrupt pipe.
|
||||
* AFAIK there is probably no status phase to indicate possibly
|
||||
* bad transported data.
|
||||
* Maybe we should do check on higher level, i.e. issue RequestSense
|
||||
* command (we do it already in scsi.c) and check returned values
|
||||
* (we do not it yet) - ? */
|
||||
if (dev->protocol == GRUB_USBMS_PROTOCOL_CBI)
|
||||
{ /* Check status in interrupt pipe */
|
||||
err = grub_usb_bulk_read (dev->dev, dev->intrpt->endp_addr,
|
||||
2, (char*)&status);
|
||||
grub_dprintf ("usb", "read status: %d\n", err);
|
||||
if (err)
|
||||
{
|
||||
/* Try to reset device, because it is probably not standard
|
||||
* situation */
|
||||
grub_usbms_reset (dev);
|
||||
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
||||
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
||||
grub_usb_clear_halt (dev->dev, dev->intrpt->endp_addr);
|
||||
goto retry;
|
||||
}
|
||||
if (dev->subclass == GRUB_USBMS_SUBCLASS_UFI)
|
||||
{
|
||||
/* These devices should return bASC and bASCQ */
|
||||
if (status != 0)
|
||||
/* Some error, currently we don't care what it is... */
|
||||
goto retry;
|
||||
}
|
||||
else if (dev->subclass == GRUB_USBMS_SUBCLASS_RBC)
|
||||
{
|
||||
/* XXX: I don't understand what returns RBC subclass devices,
|
||||
* so I don't check it - maybe somebody helps ? */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Any other device should return bType = 0 and some bValue */
|
||||
if (status & 0xff)
|
||||
return grub_error (GRUB_ERR_IO, "USB Mass Storage CBI status type != 0");
|
||||
status = (status & 0x0300) >> 8;
|
||||
switch (status)
|
||||
{
|
||||
case 0 : /* OK */
|
||||
break;
|
||||
case 1 : /* Fail */
|
||||
goto retry;
|
||||
break;
|
||||
case 2 : /* Phase error */
|
||||
case 3 : /* Persistent Failure */
|
||||
grub_dprintf ("usb", "CBI reset device - phase error or persistent failure\n");
|
||||
grub_usbms_reset (dev);
|
||||
grub_usb_clear_halt (dev->dev, dev->in->endp_addr);
|
||||
grub_usb_clear_halt (dev->dev, dev->out->endp_addr);
|
||||
grub_usb_clear_halt (dev->dev, dev->intrpt->endp_addr);
|
||||
goto retry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static grub_err_t
|
||||
grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||
grub_size_t size, char *buf, int read_write)
|
||||
{
|
||||
grub_usbms_dev_t dev = (grub_usbms_dev_t) scsi->data;
|
||||
|
||||
if (dev->protocol == GRUB_USBMS_PROTOCOL_BULK)
|
||||
return grub_usbms_transfer_bo (scsi, cmdsize, cmd, size, buf,
|
||||
read_write);
|
||||
else
|
||||
return grub_usbms_transfer_cbi (scsi, cmdsize, cmd, size, buf,
|
||||
read_write);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_usbms_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
||||
|
@ -388,9 +594,9 @@ grub_usbms_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
|
|||
|
||||
static grub_err_t
|
||||
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
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#define bit_LM (1 << 29)
|
||||
|
||||
char *
|
||||
const char *
|
||||
grub_efiemu_get_default_core_name (void)
|
||||
{
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue