merge mainline into gdb

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2012-02-18 21:00:13 +01:00
commit 515e8007fc
465 changed files with 26882 additions and 11400 deletions

3062
ChangeLog

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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 = {

View file

@ -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 =

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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
View 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)

View file

@ -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"

View file

@ -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;

View file

@ -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)

View file

@ -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):

View file

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

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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)
{

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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));
}

View file

@ -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;

View file

@ -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."),

View file

@ -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]);

View file

@ -31,17 +31,17 @@ static grub_err_t (*grub_loader_boot_func) (void);
static grub_err_t (*grub_loader_unload_func) (void);
static int grub_loader_noreturn;
struct grub_preboot_t
struct grub_preboot
{
grub_err_t (*preboot_func) (int);
grub_err_t (*preboot_rest_func) (void);
grub_loader_preboot_hook_prio_t prio;
struct grub_preboot_t *next;
struct grub_preboot_t *prev;
struct grub_preboot *next;
struct grub_preboot *prev;
};
static int grub_loader_loaded;
static struct grub_preboot_t *preboots_head = 0,
static struct grub_preboot *preboots_head = 0,
*preboots_tail = 0;
int
@ -51,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 ();

View file

@ -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;
}

View file

@ -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)
;
}

View file

@ -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]);

View file

@ -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');

View file

@ -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]"),

View file

@ -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)

View file

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

View file

@ -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},

View file

@ -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));
}
}

View file

@ -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));
}
}
}

View file

@ -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);
}

View file

@ -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

View file

@ -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;

View file

@ -32,7 +32,7 @@
GRUB_MOD_LICENSE ("GPLv3+");
/* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */
static grub_uint32_t *const int13slot = UINT_TO_PTR (4 * 0x13);
static grub_uint32_t *const int13slot = (grub_uint32_t *) (4 * 0x13);
/* Remember to update enum opt_idxs accordingly. */
static const struct grub_arg_option options[] = {
@ -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)

View file

@ -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"),

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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)

View file

@ -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)

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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"));
}

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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);
}

View file

@ -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

View file

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

View file

@ -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)

View file

@ -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[] =
{

View file

@ -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."));

View file

@ -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)
{

View file

@ -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 *)

View file

@ -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]);
}

View file

@ -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;

View file

@ -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)

View file

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

View file

@ -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 (&regex, args[0], REG_EXTENDED);
if (ret)

View file

@ -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);

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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)

View 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 ();

View file

@ -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."));
}

View file

@ -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;
}

View file

@ -74,6 +74,8 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
grub_video_create_render_target (&text_layer, width, height,
GRUB_VIDEO_MODE_TYPE_RGB
| GRUB_VIDEO_MODE_TYPE_ALPHA);
if (!text_layer)
goto fail;
grub_video_set_active_render_target (text_layer);
@ -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,

View file

@ -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 (&regexp, *start != '(');
else if (*start == '(') /* device part explicit wo regexop */
else /* device part explicit wo regexop */
paths = match_files ("", start, noregexop, &regexp);
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, &regexp);
grub_free (prefix);
}
}
else
{

View file

@ -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)
{

View file

@ -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 =

View file

@ -29,29 +29,27 @@ static grub_ata_dev_t grub_ata_dev_list;
/* Byteorder has to be changed before strings can be read. */
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");

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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
View 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);
}

View file

@ -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);
}

File diff suppressed because it is too large Load diff

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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 ();
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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

View file

@ -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