merge mainline into backtrace
This commit is contained in:
commit
245f4582f9
871 changed files with 102908 additions and 16407 deletions
|
@ -1,4 +1,4 @@
|
|||
AUTOMAKE_OPTIONS = subdir-objects
|
||||
AUTOMAKE_OPTIONS = subdir-objects -Wno-portability
|
||||
|
||||
DEPDIR=.deps-core
|
||||
|
||||
|
@ -30,7 +30,7 @@ CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM)
|
|||
|
||||
# gentrigtables
|
||||
gentrigtables: gentrigtables.c
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(CPPFLAGS) -lm $<
|
||||
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(CPPFLAGS) $< -lm
|
||||
CLEANFILES += gentrigtables
|
||||
|
||||
# trigtables.c
|
||||
|
@ -48,10 +48,15 @@ CLEANFILES += grub_script.tab.c grub_script.tab.h
|
|||
grub_script.yy.h: script/yylex.l
|
||||
$(LEX) -o grub_script.yy.c --header-file=grub_script.yy.h $<
|
||||
grub_script.yy.c: grub_script.yy.h
|
||||
|
||||
rs_decoder.S: $(srcdir)/lib/reed_solomon.c
|
||||
$(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Os -I$(top_builddir) -S -DSTANDALONE -o $@ $< -g0 -mregparm=3
|
||||
|
||||
kern/i386/pc/startup.S: $(builddir)/rs_decoder.S
|
||||
|
||||
CLEANFILES += grub_script.yy.c grub_script.yy.h
|
||||
|
||||
include $(srcdir)/Makefile.core.am
|
||||
include $(srcdir)/Makefile.gcry.am
|
||||
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cache.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h
|
||||
|
@ -73,12 +78,11 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
|
|||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
|
||||
|
||||
if COND_i386_pc
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loader.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h
|
||||
|
@ -93,25 +97,25 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
|
|||
endif
|
||||
|
||||
if COND_i386_coreboot
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h
|
||||
endif
|
||||
|
||||
if COND_i386_multiboot
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h
|
||||
endif
|
||||
|
||||
if COND_i386_qemu
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
|
||||
endif
|
||||
|
||||
if COND_i386_ieee1275
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
|
||||
endif
|
||||
|
||||
|
@ -122,9 +126,41 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
|||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
|
||||
endif
|
||||
|
||||
if COND_mips_yeeloong
|
||||
if COND_ia64_efi
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/time.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
|
||||
endif
|
||||
|
||||
if COND_mips
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/kernel.h
|
||||
endif
|
||||
|
||||
if COND_mips_arc
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arc/arc.h
|
||||
endif
|
||||
|
||||
if COND_mips_qemu_mips
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
endif
|
||||
|
||||
if COND_mips_loongson
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h
|
||||
|
@ -135,21 +171,37 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
|
|||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cs5536.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pci.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/serial.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
endif
|
||||
|
||||
if COND_mips_qemu_mips
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
|
||||
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
|
||||
endif
|
||||
|
||||
if COND_powerpc_ieee1275
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
endif
|
||||
|
||||
if COND_sparc64_ieee1275
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h
|
||||
endif
|
||||
|
||||
if COND_emu
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/export.h
|
||||
if COND_GRUB_EMU_SDL
|
||||
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
|
||||
endif
|
||||
|
@ -176,13 +228,19 @@ symlist.c: symlist.h gensymlist.sh
|
|||
CLEANFILES += symlist.c
|
||||
BUILT_SOURCES += symlist.c
|
||||
|
||||
if COND_HAVE_ASM_USCORE
|
||||
ASM_PREFIX=_
|
||||
else
|
||||
ASM_PREFIX=
|
||||
endif
|
||||
|
||||
noinst_DATA += kernel_syms.lst
|
||||
|
||||
kernel_syms.lst: $(KERNEL_HEADER_FILES) $(top_builddir)/config.h
|
||||
$(TARGET_CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) $(CPPFLAGS) $(CFLAGS) -DGRUB_SYMBOL_GENERATOR=1 $^ >kernel_syms.input
|
||||
if grep "^#define HAVE_ASM_USCORE" $(top_builddir)/config.h; then u="_"; else u=""; fi; \
|
||||
cat kernel_syms.input | grep -v '^#' | sed -n \
|
||||
-e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/'"$$u"'\1 kernel/;p;}' \
|
||||
-e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/'"$$u"'\1 kernel/;p;}' \
|
||||
-e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/defined kernel '"$(ASM_PREFIX)"'\1/;p;}' \
|
||||
-e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/defined kernel '"$(ASM_PREFIX)"'\1/;p;}' \
|
||||
| sort -u >$@
|
||||
rm -f kernel_syms.input
|
||||
CLEANFILES += kernel_syms.lst
|
||||
|
@ -202,61 +260,92 @@ grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MOD_FILES)
|
|||
CLEANFILES += grub_emu_init.c
|
||||
endif
|
||||
|
||||
# .lst files
|
||||
platform_DATA += moddep.lst
|
||||
platform_DATA += fs.lst
|
||||
platform_DATA += command.lst
|
||||
platform_DATA += partmap.lst
|
||||
platform_DATA += handler.lst
|
||||
platform_DATA += terminal.lst
|
||||
platform_DATA += parttool.lst
|
||||
platform_DATA += video.lst
|
||||
platform_DATA += crypto.lst
|
||||
CLEANFILES += moddep.lst
|
||||
CLEANFILES += handler.lst
|
||||
CLEANFILES += terminal.lst
|
||||
CLEANFILES += parttool.lst
|
||||
CLEANFILES += video.lst
|
||||
CLEANFILES += crypto.lst
|
||||
# List files
|
||||
|
||||
fs.lst: $(FS_FILES)
|
||||
cat $^ /dev/null | sort | uniq > $@
|
||||
fs.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
if grep 'FS_LIST_MARKER' $$pp >/dev/null 2>&1; then \
|
||||
echo $$b; \
|
||||
fi; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += fs.lst
|
||||
CLEANFILES += fs.lst
|
||||
|
||||
command.lst: $(COMMAND_FILES)
|
||||
cat $^ /dev/null | sort | uniq > $@
|
||||
command.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
sed -n \
|
||||
-e "/EXTCOMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
|
||||
-e "/P1COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
|
||||
-e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += command.lst
|
||||
CLEANFILES += command.lst
|
||||
|
||||
partmap.lst: $(PARTMAP_FILES)
|
||||
cat $^ /dev/null | sort | uniq > $@
|
||||
partmap.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
if grep 'PARTMAP_LIST_MARKER' $$pp >/dev/null 2>&1; then \
|
||||
echo $$b; \
|
||||
fi; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += partmap.lst
|
||||
CLEANFILES += partmap.lst
|
||||
|
||||
handler.lst: $(HANDLER_FILES)
|
||||
cat $^ /dev/null | sort | uniq > $@
|
||||
CLEANFILES += handler.lst
|
||||
|
||||
terminal.lst: $(TERMINAL_FILES)
|
||||
cat $^ /dev/null | sort | uniq > $@
|
||||
terminal.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
sed -n \
|
||||
-e "/INPUT_TERMINAL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $$b/;p;}" \
|
||||
-e "/OUTPUT_TERMINAL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $$b/;p;}" $$pp; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += terminal.lst
|
||||
CLEANFILES += terminal.lst
|
||||
|
||||
parttool.lst: $(PARTTOOL_FILES)
|
||||
cat $^ /dev/null | sort | uniq > $@
|
||||
parttool.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
sed -n \
|
||||
-e "/PARTTOOL_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += parttool.lst
|
||||
CLEANFILES += parttool.lst
|
||||
|
||||
video.lst: $(VIDEO_FILES)
|
||||
cat $^ /dev/null | sort | uniq > $@
|
||||
video.lst: $(MARKER_FILES)
|
||||
(for pp in $^; do \
|
||||
b=`basename $$pp .marker`; \
|
||||
if grep 'VIDEO_LIST_MARKER' $$pp >/dev/null 2>&1; then \
|
||||
echo $$b; \
|
||||
fi; \
|
||||
done) | sort -u > $@
|
||||
platform_DATA += video.lst
|
||||
CLEANFILES += video.lst
|
||||
|
||||
# but, crypto.lst is simply copied
|
||||
crypto.lst: $(srcdir)/lib/libgcrypt-grub/cipher/crypto.lst
|
||||
cp $^ $@
|
||||
platform_DATA += crypto.lst
|
||||
CLEANFILES += crypto.lst
|
||||
|
||||
syminfo.lst: gensyminfo.sh kernel_syms.lst $(MODULE_FILES)
|
||||
cat kernel_syms.lst > $@.new
|
||||
for m in $(MODULE_FILES); do \
|
||||
sh $< $$m >> $@.new || exit 1; \
|
||||
done
|
||||
mv $@.new $@
|
||||
|
||||
# generate global module dependencies list
|
||||
moddep.lst: kernel_syms.lst genmoddep.awk $(DEF_FILES) $(UND_FILES)
|
||||
cat $(DEF_FILES) kernel_syms.lst /dev/null \
|
||||
| $(AWK) -f $(srcdir)/genmoddep.awk $(UND_FILES) > $@ \
|
||||
|| (rm -f $@; exit 1)
|
||||
moddep.lst: syminfo.lst genmoddep.awk
|
||||
cat $< | sort | awk -f $(srcdir)/genmoddep.awk > $@ || (rm -f $@; exit 1)
|
||||
platform_DATA += moddep.lst
|
||||
CLEANFILES += config.log syminfo.lst moddep.lst
|
||||
|
||||
$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT)
|
||||
TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@
|
||||
platform_DATA += $(MOD_FILES)
|
||||
platform_DATA += modinfo.sh
|
||||
CLEANFILES += $(MOD_FILES)
|
||||
|
||||
if COND_ENABLE_EFIEMU
|
||||
efiemu32.o: efiemu/runtime/efiemu.c $(TARGET_OBJ2ELF)
|
||||
|
|
File diff suppressed because it is too large
Load diff
102
grub-core/boot/decompressor/minilib.c
Normal file
102
grub-core/boot/decompressor/minilib.c
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 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/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/decompressor.h>
|
||||
|
||||
void *
|
||||
memset (void *s, int c, grub_size_t len)
|
||||
{
|
||||
grub_uint8_t *ptr;
|
||||
for (ptr = s; len; ptr++, len--)
|
||||
*ptr = c;
|
||||
return s;
|
||||
}
|
||||
|
||||
void *
|
||||
grub_memmove (void *dest, const void *src, grub_size_t n)
|
||||
{
|
||||
char *d = (char *) dest;
|
||||
const char *s = (const char *) src;
|
||||
|
||||
if (d < s)
|
||||
while (n--)
|
||||
*d++ = *s++;
|
||||
else
|
||||
{
|
||||
d += n;
|
||||
s += n;
|
||||
|
||||
while (n--)
|
||||
*--d = *--s;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
int
|
||||
grub_memcmp (const void *s1, const void *s2, grub_size_t n)
|
||||
{
|
||||
const char *t1 = s1;
|
||||
const char *t2 = s2;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
if (*t1 != *t2)
|
||||
return (int) *t1 - (int) *t2;
|
||||
|
||||
t1++;
|
||||
t2++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int memcmp (const void *s1, const void *s2, grub_size_t n)
|
||||
__attribute__ ((alias ("grub_memcmp")));
|
||||
|
||||
void *memmove (void *dest, const void *src, grub_size_t n)
|
||||
__attribute__ ((alias ("grub_memmove")));
|
||||
|
||||
void *memcpy (void *dest, const void *src, grub_size_t n)
|
||||
__attribute__ ((alias ("grub_memmove")));
|
||||
|
||||
void *grub_decompressor_scratch;
|
||||
|
||||
void
|
||||
find_scratch (void *src, void *dst, unsigned long srcsize,
|
||||
unsigned long dstsize)
|
||||
{
|
||||
#ifdef _mips
|
||||
/* Decoding from ROM. */
|
||||
if (((grub_addr_t) src & 0x10000000))
|
||||
{
|
||||
grub_decompressor_scratch = (void *) ALIGN_UP((grub_addr_t) dst + dstsize,
|
||||
256);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if ((char *) src + srcsize > (char *) dst + dstsize)
|
||||
grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) src + srcsize,
|
||||
256);
|
||||
else
|
||||
grub_decompressor_scratch = (void *) ALIGN_UP ((grub_addr_t) dst + dstsize,
|
||||
256);
|
||||
return;
|
||||
}
|
42
grub-core/boot/decompressor/none.c
Normal file
42
grub-core/boot/decompressor/none.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 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/decompressor.h>
|
||||
|
||||
void
|
||||
grub_decompress_core (void *src, void *dest, unsigned long n,
|
||||
unsigned long dstsize __attribute__ ((unused)))
|
||||
{
|
||||
char *d = (char *) dest;
|
||||
const char *s = (const char *) src;
|
||||
|
||||
if (d == s)
|
||||
return;
|
||||
|
||||
if (d < s)
|
||||
while (n--)
|
||||
*d++ = *s++;
|
||||
else
|
||||
{
|
||||
d += n;
|
||||
s += n;
|
||||
|
||||
while (n--)
|
||||
*--d = *--s;
|
||||
}
|
||||
}
|
60
grub-core/boot/decompressor/xz.c
Normal file
60
grub-core/boot/decompressor/xz.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 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/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/decompressor.h>
|
||||
|
||||
#include "xz.h"
|
||||
#include "xz_stream.h"
|
||||
|
||||
void
|
||||
grub_decompress_core (void *src, void *dst, unsigned long srcsize,
|
||||
unsigned long dstsize)
|
||||
{
|
||||
struct xz_dec *dec;
|
||||
struct xz_buf buf;
|
||||
|
||||
find_scratch (src, dst, srcsize, dstsize);
|
||||
|
||||
dec = xz_dec_init (GRUB_DECOMPRESSOR_DICT_SIZE);
|
||||
|
||||
buf.in = src;
|
||||
buf.in_pos = 0;
|
||||
buf.in_size = srcsize;
|
||||
buf.out = dst;
|
||||
buf.out_pos = 0;
|
||||
buf.out_size = dstsize;
|
||||
|
||||
while (buf.in_pos != buf.in_size)
|
||||
{
|
||||
enum xz_ret xzret;
|
||||
xzret = xz_dec_run (dec, &buf);
|
||||
switch (xzret)
|
||||
{
|
||||
case XZ_MEMLIMIT_ERROR:
|
||||
case XZ_FORMAT_ERROR:
|
||||
case XZ_OPTIONS_ERROR:
|
||||
case XZ_DATA_ERROR:
|
||||
case XZ_BUF_ERROR:
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/boot.h>
|
||||
#include <grub/machine/boot.h>
|
||||
|
||||
/*
|
||||
|
@ -112,12 +111,16 @@ LOCAL(after_BPB):
|
|||
*/
|
||||
. = _start + GRUB_BOOT_MACHINE_DRIVE_CHECK
|
||||
boot_drive_check:
|
||||
jmp 1f /* grub-setup may overwrite this jump */
|
||||
jmp 3f /* grub-setup may overwrite this jump */
|
||||
testb $0x80, %dl
|
||||
jnz 1f
|
||||
jz 2f
|
||||
3:
|
||||
/* Ignore %dl different from 0-0x0f and 0x80-0x8f. */
|
||||
testb $0x70, %dl
|
||||
jz 1f
|
||||
2:
|
||||
movb $0x80, %dl
|
||||
1:
|
||||
|
||||
/*
|
||||
* ljmp to the next instruction because some bogus BIOSes
|
||||
* jump to 07C0:0000 instead of 0000:7C00.
|
||||
|
@ -455,6 +458,8 @@ fd_probe_error_string: .asciz "Floppy"
|
|||
1:
|
||||
/* perform read */
|
||||
movw $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx
|
||||
movw %bx, %es
|
||||
xorw %bx, %bx
|
||||
movw $0x201, %ax
|
||||
movb $0, %ch
|
||||
movb $0, %dh
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/boot.h>
|
||||
#include <grub/machine/boot.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <multiboot.h>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#include <config.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/boot.h>
|
||||
#include <grub/machine/boot.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <multiboot.h>
|
||||
|
@ -178,14 +177,19 @@ 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
|
||||
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_MULTIBOOT_SIGNATURE)
|
||||
cmpl $MULTIBOOT_HEADER_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART)
|
||||
jz 1f
|
||||
|
||||
movl (ramdisk_image - start), %esi
|
||||
|
@ -195,17 +199,12 @@ real_code_2:
|
|||
|
||||
1:
|
||||
|
||||
movl %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE), %ecx
|
||||
addl $(GRUB_KERNEL_MACHINE_RAW_SIZE - 0x200), %ecx
|
||||
movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx
|
||||
addl $((0x9000 - 0x8200) - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx
|
||||
|
||||
2:
|
||||
call LOCAL(move_memory)
|
||||
|
||||
movsbl %dh, %eax
|
||||
movl %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART)
|
||||
movsbl (reg_edx + 2 - start), %eax
|
||||
movl %eax, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART)
|
||||
|
||||
movb $0xFF, %dh
|
||||
|
||||
ljmp $(DATA_ADDR >> 4), $0
|
||||
|
|
|
@ -77,69 +77,6 @@
|
|||
#define RepLenCoder (LenCoder + kNumLenProbs)
|
||||
#define Literal (RepLenCoder + kNumLenProbs)
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
DbgOut:
|
||||
pushf
|
||||
pushl %ebp
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %edx
|
||||
pushl %ecx
|
||||
pushl %ebx
|
||||
pushl %eax
|
||||
|
||||
call _DebugPrint
|
||||
|
||||
popl %eax
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
popf
|
||||
|
||||
ret
|
||||
|
||||
|
||||
/*
|
||||
* int LzmaDecodeProperties(CLzmaProperties *propsRes,
|
||||
* const unsigned char *propsData,
|
||||
* int size);
|
||||
*/
|
||||
|
||||
_LzmaDecodePropertiesA:
|
||||
movb (%edx), %dl
|
||||
|
||||
xorl %ecx, %ecx
|
||||
1:
|
||||
cmpb $45, %dl
|
||||
jb 2f
|
||||
incl %ecx
|
||||
subb $45, %dl
|
||||
jmp 1b
|
||||
2:
|
||||
movl %ecx, 8(%eax) /* pb */
|
||||
xorl %ecx, %ecx
|
||||
1:
|
||||
cmpb $9, %dl
|
||||
jb 2f
|
||||
incl %ecx
|
||||
subb $9, %dl
|
||||
2:
|
||||
movl %ecx, 4(%eax) /* lp */
|
||||
movb %dl, %cl
|
||||
movl %ecx, (%eax) /* lc */
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef ASM_FILE
|
||||
xorl %eax, %eax
|
||||
#endif
|
||||
ret
|
||||
|
||||
#define out_size 8(%ebp)
|
||||
|
||||
#define now_pos -4(%ebp)
|
346
grub-core/boot/i386/pc/startup_raw.S
Normal file
346
grub-core/boot/i386/pc/startup_raw.S
Normal file
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2008,2009,2011 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/offsets.h>
|
||||
#include <grub/machine/boot.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
|
||||
#define ABS(x) ((x) - LOCAL (base) + GRUB_BOOT_MACHINE_KERNEL_ADDR + 0x200)
|
||||
|
||||
.file "startup_raw.S"
|
||||
|
||||
.text
|
||||
|
||||
/* Tell GAS to generate 16-bit instructions so that this code works
|
||||
in real mode. */
|
||||
.code16
|
||||
|
||||
.globl start, _start
|
||||
start:
|
||||
_start:
|
||||
LOCAL (base):
|
||||
/*
|
||||
* Guarantee that "main" is loaded at 0x0:0x8200.
|
||||
*/
|
||||
#ifdef __APPLE__
|
||||
ljmp $0, $(ABS(LOCAL (codestart)) - 0x10000)
|
||||
#else
|
||||
ljmp $0, $ABS(LOCAL (codestart))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is a special data area.
|
||||
*/
|
||||
|
||||
. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
|
||||
LOCAL(compressed_size):
|
||||
.long 0
|
||||
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
|
||||
LOCAL(uncompressed_size):
|
||||
.long 0
|
||||
|
||||
. = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY
|
||||
reed_solomon_redundancy:
|
||||
.long 0
|
||||
|
||||
/*
|
||||
* This is the area for all of the special variables.
|
||||
*/
|
||||
|
||||
LOCAL(boot_dev):
|
||||
.byte 0xFF, 0xFF, 0xFF
|
||||
LOCAL(boot_drive):
|
||||
.byte 0x00
|
||||
|
||||
/* the real mode code continues... */
|
||||
LOCAL (codestart):
|
||||
cli /* we're not safe here! */
|
||||
|
||||
/* set up %ds, %ss, and %es */
|
||||
xorw %ax, %ax
|
||||
movw %ax, %ds
|
||||
movw %ax, %ss
|
||||
movw %ax, %es
|
||||
|
||||
/* set up the real mode/BIOS stack */
|
||||
movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp
|
||||
movl %ebp, %esp
|
||||
|
||||
sti /* we're safe again */
|
||||
|
||||
/* save the boot drive */
|
||||
ADDR32 movb %dl, LOCAL(boot_drive)
|
||||
|
||||
/* reset disk system (%ah = 0) */
|
||||
int $0x13
|
||||
|
||||
/* transition to protected mode */
|
||||
DATA32 call real_to_prot
|
||||
|
||||
/* The ".code32" directive takes GAS out of 16-bit mode. */
|
||||
.code32
|
||||
|
||||
incl %eax
|
||||
call grub_gate_a20
|
||||
|
||||
movl LOCAL(compressed_size), %edx
|
||||
addl $(LOCAL(decompressor_end) - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART - _start), %edx
|
||||
movl reed_solomon_redundancy, %ecx
|
||||
leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax
|
||||
call EXT_C (grub_reed_solomon_recover)
|
||||
jmp post_reed_solomon
|
||||
|
||||
#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)
|
||||
*
|
||||
* Gate address-line 20 for high memory.
|
||||
*
|
||||
* This routine is probably overconservative in what it does, but so what?
|
||||
*
|
||||
* It also eats any keystrokes in the keyboard buffer. :-(
|
||||
*/
|
||||
|
||||
grub_gate_a20:
|
||||
movl %eax, %edx
|
||||
|
||||
gate_a20_test_current_state:
|
||||
/* first of all, test if already in a good state */
|
||||
call gate_a20_check_state
|
||||
cmpb %al, %dl
|
||||
jnz gate_a20_try_bios
|
||||
ret
|
||||
|
||||
gate_a20_try_bios:
|
||||
/* second, try a BIOS call */
|
||||
pushl %ebp
|
||||
call prot_to_real
|
||||
|
||||
.code16
|
||||
movw $0x2400, %ax
|
||||
testb %dl, %dl
|
||||
jz 1f
|
||||
incw %ax
|
||||
1: int $0x15
|
||||
|
||||
DATA32 call real_to_prot
|
||||
.code32
|
||||
|
||||
popl %ebp
|
||||
call gate_a20_check_state
|
||||
cmpb %al, %dl
|
||||
jnz gate_a20_try_system_control_port_a
|
||||
ret
|
||||
|
||||
gate_a20_try_system_control_port_a:
|
||||
/*
|
||||
* In macbook, the keyboard test would hang the machine, so we move
|
||||
* this forward.
|
||||
*/
|
||||
/* fourth, try the system control port A */
|
||||
inb $0x92
|
||||
andb $(~0x03), %al
|
||||
testb %dl, %dl
|
||||
jz 6f
|
||||
orb $0x02, %al
|
||||
6: outb $0x92
|
||||
|
||||
/* When turning off Gate A20, do not check the state strictly,
|
||||
because a failure is not fatal usually, and Gate A20 is always
|
||||
on some modern machines. */
|
||||
testb %dl, %dl
|
||||
jz 7f
|
||||
call gate_a20_check_state
|
||||
cmpb %al, %dl
|
||||
jnz gate_a20_try_keyboard_controller
|
||||
7: ret
|
||||
|
||||
gate_a20_flush_keyboard_buffer:
|
||||
inb $0x64
|
||||
andb $0x02, %al
|
||||
jnz gate_a20_flush_keyboard_buffer
|
||||
2:
|
||||
inb $0x64
|
||||
andb $0x01, %al
|
||||
jz 3f
|
||||
inb $0x60
|
||||
jmp 2b
|
||||
3:
|
||||
ret
|
||||
|
||||
gate_a20_try_keyboard_controller:
|
||||
/* third, try the keyboard controller */
|
||||
call gate_a20_flush_keyboard_buffer
|
||||
|
||||
movb $0xd1, %al
|
||||
outb $0x64
|
||||
4:
|
||||
inb $0x64
|
||||
andb $0x02, %al
|
||||
jnz 4b
|
||||
|
||||
movb $0xdd, %al
|
||||
testb %dl, %dl
|
||||
jz 5f
|
||||
orb $0x02, %al
|
||||
5: outb $0x60
|
||||
call gate_a20_flush_keyboard_buffer
|
||||
|
||||
/* output a dummy command (USB keyboard hack) */
|
||||
movb $0xff, %al
|
||||
outb $0x64
|
||||
call gate_a20_flush_keyboard_buffer
|
||||
|
||||
call gate_a20_check_state
|
||||
cmpb %al, %dl
|
||||
/* everything failed, so restart from the beginning */
|
||||
jnz gate_a20_try_bios
|
||||
ret
|
||||
|
||||
gate_a20_check_state:
|
||||
/* iterate the checking for a while */
|
||||
movl $100, %ecx
|
||||
1:
|
||||
call 3f
|
||||
cmpb %al, %dl
|
||||
jz 2f
|
||||
loop 1b
|
||||
2:
|
||||
ret
|
||||
3:
|
||||
pushl %ebx
|
||||
pushl %ecx
|
||||
xorl %eax, %eax
|
||||
/* compare the byte at 0x8000 with that at 0x108000 */
|
||||
movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %ebx
|
||||
pushl %ebx
|
||||
/* save the original byte in CL */
|
||||
movb (%ebx), %cl
|
||||
/* store the value at 0x108000 in AL */
|
||||
addl $0x100000, %ebx
|
||||
movb (%ebx), %al
|
||||
/* try to set one less value at 0x8000 */
|
||||
popl %ebx
|
||||
movb %al, %ch
|
||||
decb %ch
|
||||
movb %ch, (%ebx)
|
||||
/* serialize */
|
||||
outb %al, $0x80
|
||||
outb %al, $0x80
|
||||
/* obtain the value at 0x108000 in CH */
|
||||
pushl %ebx
|
||||
addl $0x100000, %ebx
|
||||
movb (%ebx), %ch
|
||||
/* this result is 1 if A20 is on or 0 if it is off */
|
||||
subb %ch, %al
|
||||
xorb $1, %al
|
||||
/* restore the original */
|
||||
popl %ebx
|
||||
movb %cl, (%ebx)
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
ret
|
||||
|
||||
#ifdef ENABLE_LZMA
|
||||
#include "lzma_decode.S"
|
||||
#endif
|
||||
|
||||
.p2align 2
|
||||
|
||||
LOCAL(decompressor_end):
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <config.h>
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/i386/pc/memory.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/boot.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
|
|
2
grub-core/boot/mips/loongson/fuloong2f.S
Normal file
2
grub-core/boot/mips/loongson/fuloong2f.S
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define FULOONG2F 1
|
||||
#include "fwstart.S"
|
|
@ -16,51 +16,73 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/mips/yeeloong/serial.h>
|
||||
#include <grub/mips/yeeloong/pci.h>
|
||||
#include <grub/mips/loongson/serial.h>
|
||||
#include <grub/mips/loongson/pci.h>
|
||||
#include <grub/mips/loongson.h>
|
||||
#include <grub/pci.h>
|
||||
#include <grub/machine/serial.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/ns8250.h>
|
||||
#include <grub/cs5536.h>
|
||||
#include <grub/smbus.h>
|
||||
|
||||
#ifdef FULOONG2F
|
||||
#define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT2
|
||||
#define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200
|
||||
#else
|
||||
#define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT0
|
||||
#define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT0_DIVISOR_115200
|
||||
#endif
|
||||
|
||||
.set noreorder
|
||||
.set noat
|
||||
.set nomacro
|
||||
.set mips3
|
||||
|
||||
.global start,_start,__start
|
||||
start:
|
||||
_start:
|
||||
__start:
|
||||
/* Put serial init as soon as possible. But on Fuloong2f serial is past
|
||||
Geode, so on Fuloong2f we need Geode first.
|
||||
*/
|
||||
#ifndef FULOONG2F
|
||||
bal serial_hw_init
|
||||
nop
|
||||
#endif
|
||||
|
||||
/* Find CS5536 controller. */
|
||||
/* $t4 chooses device in priority encoding. */
|
||||
/* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG.
|
||||
This way we don't need to sacrifice a register for it. */
|
||||
retry_cs5536:
|
||||
/* We have only one bus (0). Function is 0. */
|
||||
lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR)
|
||||
lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE)
|
||||
lui $t3, %hi(GRUB_CS5536_PCIID)
|
||||
addiu $t3, $t3, %lo(GRUB_CS5536_PCIID)
|
||||
ori $t4, $zero, 1
|
||||
lui $a0, %hi(no_cs5536)
|
||||
1:
|
||||
andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1)
|
||||
beql $t4, $zero, fatal
|
||||
addiu $a0, $a0, %lo(no_cs5536)
|
||||
/* In case of failure try again. CS5536 may be slow to come up. */
|
||||
beql $t4, $zero, retry_cs5536
|
||||
nop
|
||||
sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
|
||||
lw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1)
|
||||
bnel $t2, $t3, 1b
|
||||
sll $t4, $t4, 1
|
||||
|
||||
#ifndef FULOONG2F
|
||||
bal message
|
||||
addiu $a0, $a0, %lo(cs5536_found)
|
||||
bal printhex
|
||||
move $a0, $t4
|
||||
#endif
|
||||
|
||||
/* Initialise SMBus controller. */
|
||||
lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE)
|
||||
li $t1, GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED
|
||||
sw $t1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_CONFIG) ($t0)
|
||||
|
||||
/* Set GPIO LBAR. */
|
||||
lui $a0, %hi(GRUB_CS5536_MSR_GPIO_BAR)
|
||||
addiu $a0, $a0, %lo(GRUB_CS5536_MSR_GPIO_BAR)
|
||||
|
@ -70,6 +92,15 @@ __start:
|
|||
ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \
|
||||
| GRUB_CS5536_LBAR_ENABLE) >> 32)
|
||||
|
||||
bal gpio_init
|
||||
nop
|
||||
|
||||
#ifdef FULOONG2F
|
||||
bal serial_hw_init
|
||||
nop
|
||||
#endif
|
||||
|
||||
/* Initialise SMBus controller. */
|
||||
/* Set SMBUS LBAR. */
|
||||
lui $a0, %hi(GRUB_CS5536_MSR_SMB_BAR)
|
||||
addiu $a0, $a0, %lo(GRUB_CS5536_MSR_SMB_BAR)
|
||||
|
@ -83,14 +114,6 @@ __start:
|
|||
bal message
|
||||
addiu $a0, $a0, %lo(smbus_enabled)
|
||||
|
||||
/* Enable SMBus controller pins. */
|
||||
lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO)
|
||||
ori $t1, $zero, GRUB_GPIO_SMBUS_PINS
|
||||
sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_OUT_EN) ($t0)
|
||||
sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_OUT_AUX1) ($t0)
|
||||
sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_IN_EN) ($t0)
|
||||
sw $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO + GRUB_GPIO_REG_IN_AUX1) ($t0)
|
||||
|
||||
lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS)
|
||||
|
||||
/* Disable SMB. */
|
||||
|
@ -107,7 +130,7 @@ __start:
|
|||
sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0)
|
||||
sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0)
|
||||
|
||||
/* Yeeloong has only one memory slot. */
|
||||
/* Yeeloong and Fuloong2f have only one memory slot. */
|
||||
/* Output first byte on serial for debugging. */
|
||||
ori $a1, $zero, GRUB_SMB_RAM_START_ADDR
|
||||
bal read_spd
|
||||
|
@ -120,7 +143,7 @@ __start:
|
|||
ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2
|
||||
lui $a0, %hi(unimplemented_memory_type)
|
||||
bne $t0, $v0, fatal
|
||||
addiu $a0, $a0, %hi(unimplemented_memory_type)
|
||||
addiu $a0, $a0, %lo(unimplemented_memory_type)
|
||||
|
||||
/* And here is our goal: DDR2 controller initialisation. */
|
||||
lui $t0, %hi(GRUB_CPU_LOONGSON_CORECFG)
|
||||
|
@ -206,10 +229,54 @@ other_exception:
|
|||
b fatal
|
||||
addiu $a0, $a0, %lo(unhandled_exception)
|
||||
|
||||
gpio_init:
|
||||
lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO)
|
||||
addiu $t0, $t0, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO)
|
||||
lui $t1, %hi (gpio_dump)
|
||||
addiu $t1, $t1, %lo (gpio_dump)
|
||||
|
||||
1:
|
||||
lw $t2, 0($t1)
|
||||
sw $t2, 0($t0)
|
||||
addiu $t0, $t0, 4
|
||||
addiu $t1, $t1, 4
|
||||
lui $t2, %hi (gpio_dump_end)
|
||||
addiu $t2, $t2, %lo (gpio_dump_end)
|
||||
bne $t1, $t2, 1b
|
||||
nop
|
||||
jr $ra
|
||||
nop
|
||||
|
||||
/* Same as similarly named C function but in asm since
|
||||
we need it early. */
|
||||
/* In: none. Out: none. Clobbered: $t0, $t1, $a0. */
|
||||
/* In: none. Out: none. Clobbered: $t0, $t1, $t2, $a0, $a1, $a2. */
|
||||
serial_hw_init:
|
||||
move $t2, $ra
|
||||
#ifdef FULOONG2F
|
||||
lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_LEG_IO)
|
||||
addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_LEG_IO)
|
||||
lui $a1, %hi (GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3 \
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP \
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 \
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1)
|
||||
ori $a1, $a1, (GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 \
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1)
|
||||
bal wrmsr
|
||||
move $a2, $zero
|
||||
|
||||
lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_UART1_CONF)
|
||||
addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_UART1_CONF)
|
||||
li $a1, 2
|
||||
bal wrmsr
|
||||
move $a2, $zero
|
||||
|
||||
lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_UART2_CONF)
|
||||
addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_UART2_CONF)
|
||||
li $a1, 2
|
||||
bal wrmsr
|
||||
move $a2, $zero
|
||||
#endif
|
||||
|
||||
lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
|
||||
|
||||
/* Turn off the interrupt. */
|
||||
|
@ -239,6 +306,7 @@ serial_hw_init:
|
|||
/* Let message return to original caller. */
|
||||
lui $a0, %hi(notification_string)
|
||||
addiu $a0, $a0, %lo(notification_string)
|
||||
move $ra, $t2
|
||||
|
||||
/* Print message on serial console. */
|
||||
/* In: $a0 = asciiz message. Out: none. Clobbered: $t0, $t1, $a0. */
|
||||
|
@ -379,7 +447,6 @@ read_spd_fail:
|
|||
ori $v0, $v0, 0x100
|
||||
|
||||
notification_string: .asciz "GRUB "
|
||||
no_cs5536: .asciz "No CS5536 found.\n\r"
|
||||
cs5536_found: .asciz "CS5536 at "
|
||||
sm_failed: .asciz "SM transaction failed.\n\r"
|
||||
unhandled_tlb_refill: .asciz "Unhandled TLB refill.\n\r"
|
||||
|
@ -404,14 +471,22 @@ regdump:
|
|||
.quad 0x0100020200010101 /* 4 */
|
||||
.quad 0x0a04030603050203 /* 6 */
|
||||
.quad 0x0f0e040000010a0b /* 7 */
|
||||
#ifdef FULOONG2F
|
||||
.quad 0x0000000100000001 /* 8 */
|
||||
#else
|
||||
.quad 0x0000010200000102 /* 8 */
|
||||
#endif
|
||||
.quad 0x0000060c00000000 /* 9 */
|
||||
.quad 0x2323233f3f1f0200 /* a */
|
||||
.quad 0x5f7f232323232323 /* b */
|
||||
.quad 0x002a3c0615000000 /* c */
|
||||
.quad 0x002a002a002a002a /* d */
|
||||
.quad 0x002a002a002a002a /* e */
|
||||
#ifdef FULOONG2F
|
||||
.quad 0x00b40020005b0004 /* f */
|
||||
#else
|
||||
.quad 0x00b40020006d0004 /* f */
|
||||
#endif
|
||||
.quad 0x070007ff00000087 /* 10 */
|
||||
.quad 0x000000000016101f /* 11 */
|
||||
.quad 0x001c000000000000 /* 12 */
|
||||
|
@ -426,6 +501,45 @@ regdump:
|
|||
.quad 0 /* 1b */
|
||||
.quad 0 /* 1c */
|
||||
|
||||
/* Dump of GPIO connections. FIXME: Remove useless and macroify. */
|
||||
gpio_dump:
|
||||
#ifdef FULOONG2F
|
||||
.long 0xffff0000, 0x2eefd110, 0xffff0000, 0xffff0000
|
||||
.long 0x2eefd110, 0xffff0000, 0x1000efff, 0xefff1000
|
||||
.long 0x3df3c20c, 0xffff0000, 0xffff0000, 0xffff0000
|
||||
.long 0x7df3820c, 0x3df3c20c, 0xffff0000, 0x00000000
|
||||
.long 0xffff0000, 0xffff0000, 0x3de3c21c, 0x3d83c27c
|
||||
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
.long 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000
|
||||
.long 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000
|
||||
.long 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000
|
||||
.long 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000
|
||||
.long 0xffff0000, 0xffff0000, 0xefff1000, 0xefff1000
|
||||
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
#else
|
||||
.long 0xffff0000, 0x2ffdd002, 0xffff0000, 0xffff0000
|
||||
.long 0x2fffd000, 0xffff0000, 0x1000efff, 0xefff1000
|
||||
.long 0x3ffbc004, 0xffff0000, 0xffff0000, 0xffff0000
|
||||
.long 0x3ffbc004, 0x3ffbc004, 0xffff0000, 0x00000000
|
||||
.long 0xffff0000, 0xffff0000, 0x3ffbc004, 0x3f9bc064
|
||||
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
.long 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000
|
||||
.long 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000
|
||||
.long 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000
|
||||
.long 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000
|
||||
.long 0xffff0000, 0xffff0000, 0xefff1000, 0xffff0000
|
||||
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
.long 0x00000000, 0x00000000, 0x00000000, 0x00000000
|
||||
.long 0x00000000, 0x50000000, 0x00000000, 0x00000000
|
||||
#endif
|
||||
gpio_dump_end:
|
||||
|
||||
.p2align
|
||||
|
||||
write_dumpreg:
|
||||
|
@ -626,6 +740,10 @@ continue:
|
|||
lui $t0, %hi(cached_continue - 0x20000000)
|
||||
addiu $t0, $t0, %lo(cached_continue - 0x20000000)
|
||||
jr $t0
|
||||
addiu $a2, $zero, -1
|
||||
#ifdef FULOONG2F
|
||||
addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_FULOONG2F)
|
||||
#else
|
||||
addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_YEELOONG)
|
||||
#endif
|
||||
|
||||
cached_continue:
|
||||
cached_continue:
|
269
grub-core/boot/mips/startup_raw.S
Normal file
269
grub-core/boot/mips/startup_raw.S
Normal file
|
@ -0,0 +1,269 @@
|
|||
/* startup.S - Startup code for the MIPS. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/symbol.h>
|
||||
#include <grub/offsets.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/kernel.h>
|
||||
#include <grub/offsets.h>
|
||||
|
||||
#define BASE_ADDR 8
|
||||
|
||||
.extern __bss_start
|
||||
.extern _end
|
||||
|
||||
.globl __start, _start, start
|
||||
.set noreorder
|
||||
.set nomacro
|
||||
__start:
|
||||
_start:
|
||||
start:
|
||||
|
||||
bal codestart
|
||||
nop
|
||||
base:
|
||||
. = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE
|
||||
compressed_size:
|
||||
.long 0
|
||||
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE
|
||||
uncompressed_size:
|
||||
.long 0
|
||||
. = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR
|
||||
uncompressed_addr:
|
||||
.long 0
|
||||
codestart:
|
||||
/* Save our base. */
|
||||
move $s0, $ra
|
||||
|
||||
/* Parse arguments. Has to be done before relocation.
|
||||
So need to do it in asm. */
|
||||
#ifdef GRUB_MACHINE_MIPS_QEMU_MIPS
|
||||
lui $t0, %hi (((16 << 20) - 264 + 4) | 0x80000000)
|
||||
lw $t1, %lo (((16 << 20) - 264 + 4) | 0x80000000) ($t0)
|
||||
|
||||
lui $t2, 0x1234
|
||||
ori $t2, 0x5678
|
||||
|
||||
bne $t1, $t2, 1f
|
||||
nop
|
||||
|
||||
lui $t0, %hi (((16 << 20) - 264) | 0x80000000)
|
||||
b 2f
|
||||
lw $s4, %lo (((16 << 20) - 264) | 0x80000000) ($t0)
|
||||
|
||||
1:
|
||||
li $s4, 0
|
||||
2:
|
||||
#endif
|
||||
|
||||
#ifdef GRUB_MACHINE_MIPS_LOONGSON
|
||||
move $s2, $zero
|
||||
move $s3, $zero
|
||||
move $s4, $zero
|
||||
move $s5, $zero
|
||||
move $s7, $zero
|
||||
|
||||
/* $a2 has the environment. */
|
||||
addiu $t0, $zero, -0x10
|
||||
and $t1, $a2, $t0
|
||||
beq $t0, $t1, argfw
|
||||
nop
|
||||
move $t0, $a2
|
||||
argcont:
|
||||
lw $t1, 0($t0)
|
||||
beq $t1, $zero, argdone
|
||||
nop
|
||||
#define DO_PARSE(str, reg) \
|
||||
addiu $t2, $s0, (str-base);\
|
||||
bal parsestr;\
|
||||
nop ;\
|
||||
beq $v0, $zero, 1f;\
|
||||
nop ;\
|
||||
b 2f;\
|
||||
move reg, $v0; \
|
||||
1:
|
||||
#define DO_CHECKT1(str, val) \
|
||||
move $t6, $t1 ;\
|
||||
addiu $t7, $s0, (str - base);\
|
||||
bal do_check ;\
|
||||
li $t2, val
|
||||
|
||||
DO_PARSE (busclockstr, $s2)
|
||||
DO_PARSE (cpuclockstr, $s3)
|
||||
DO_PARSE (memsizestr, $s4)
|
||||
DO_PARSE (highmemsizestr, $s5)
|
||||
DO_CHECKT1 (pmon_yeeloong_verstr, GRUB_ARCH_MACHINE_YEELOONG)
|
||||
DO_CHECKT1 (pmon_fuloong2f_verstr, GRUB_ARCH_MACHINE_FULOONG2F)
|
||||
2:
|
||||
b argcont
|
||||
addiu $t0, $t0, 4
|
||||
parsestr:
|
||||
move $v0, $zero
|
||||
move $t3, $t1
|
||||
3:
|
||||
lb $t4, 0($t2)
|
||||
lb $t5, 0($t3)
|
||||
addiu $t2, $t2, 1
|
||||
addiu $t3, $t3, 1
|
||||
beq $t5, $zero, 1f
|
||||
nop
|
||||
beq $t5, $t4, 3b
|
||||
nop
|
||||
bne $t4, $zero, 1f
|
||||
nop
|
||||
|
||||
addiu $t3, $t3, 0xffff
|
||||
digcont:
|
||||
lb $t5, 0($t3)
|
||||
/* Substract '0' from digit. */
|
||||
addiu $t5, $t5, 0xffd0
|
||||
bltz $t5, 1f
|
||||
nop
|
||||
addiu $t4, $t5, 0xfff7
|
||||
bgtz $t4, 1f
|
||||
nop
|
||||
/* Multiply $v0 by 10 with bitshifts. */
|
||||
sll $v0, $v0, 1
|
||||
sll $t4, $v0, 2
|
||||
addu $v0, $v0, $t4
|
||||
addu $v0, $v0, $t5
|
||||
addiu $t3, $t3, 1
|
||||
b digcont
|
||||
nop
|
||||
1:
|
||||
jr $ra
|
||||
nop
|
||||
busclockstr: .asciiz "busclock="
|
||||
cpuclockstr: .asciiz "cpuclock="
|
||||
memsizestr: .asciiz "memsize="
|
||||
highmemsizestr: .asciiz "highmemsize="
|
||||
machtype_yeeloong_str1: .asciiz "machtype=8.9"
|
||||
machtype_yeeloong_str2: .asciiz "machtype=lemote-yeeloong-"
|
||||
machtype_fuloong2f_str: .asciiz "machtype=lemote-fuloong-2f"
|
||||
machtype_fuloong2e_str: .asciiz "machtype=lemote-fuloong-2e"
|
||||
pmon_yeeloong_str: .asciiz "PMON_VER=LM8"
|
||||
pmon_fuloong2f_str: .asciiz "PMON_VER=LM6"
|
||||
pmon_yeeloong_verstr: .asciiz "Version=LM8"
|
||||
pmon_fuloong2f_verstr: .asciiz "Version=LM6"
|
||||
.p2align 2
|
||||
|
||||
argdone:
|
||||
beq $a0, $zero, cmdlinedone
|
||||
nop
|
||||
#define DO_CHECKA1(str, val) \
|
||||
lw $t6, 0($a1) ;\
|
||||
addiu $t7, $s0, (str - base);\
|
||||
bal do_check ;\
|
||||
li $t2, val
|
||||
DO_CHECKA1 (machtype_yeeloong_str1, GRUB_ARCH_MACHINE_YEELOONG)
|
||||
DO_CHECKA1 (machtype_yeeloong_str2, GRUB_ARCH_MACHINE_YEELOONG)
|
||||
DO_CHECKA1 (pmon_yeeloong_str, GRUB_ARCH_MACHINE_YEELOONG)
|
||||
DO_CHECKA1 (machtype_fuloong2f_str, GRUB_ARCH_MACHINE_FULOONG2F)
|
||||
DO_CHECKA1 (machtype_fuloong2e_str, GRUB_ARCH_MACHINE_FULOONG2E)
|
||||
DO_CHECKA1 (pmon_fuloong2f_str, GRUB_ARCH_MACHINE_FULOONG2F)
|
||||
addiu $a0, $a0, -1
|
||||
b argdone
|
||||
addiu $a1, $a1, 4
|
||||
do_check:
|
||||
lb $t4, 0($t7)
|
||||
beq $t4, $zero, 1f
|
||||
lb $t3, 0($t6)
|
||||
bne $t3, $t4, 2f
|
||||
addiu $t6, $t6, 1
|
||||
b do_check
|
||||
addiu $t7, $t7, 1
|
||||
1:
|
||||
move $s7, $t2
|
||||
2:
|
||||
jr $ra
|
||||
nop
|
||||
argfw:
|
||||
not $s7, $a2
|
||||
cmdlinedone:
|
||||
#endif
|
||||
/* Copy the decompressor. */
|
||||
lui $t1, %hi(base)
|
||||
addiu $t1, $t1, %lo(base)
|
||||
lui $t3, %hi(__bss_start)
|
||||
addiu $t3, $t3, %lo(__bss_start)
|
||||
move $t2, $s0
|
||||
|
||||
1:
|
||||
beq $t1, $t3, 2f
|
||||
lb $t4, 0($t2)
|
||||
sb $t4, 0($t1)
|
||||
addiu $t1, $t1, 1
|
||||
b 1b
|
||||
addiu $t2, $t2, 1
|
||||
2:
|
||||
/* Clean out its BSS. */
|
||||
lui $t1, %hi(__bss_start)
|
||||
addiu $t1, $t1, %lo(__bss_start)
|
||||
lui $t2, %hi(_end)
|
||||
addiu $t2, $t2, %lo(_end)
|
||||
1:
|
||||
beq $t1, $t2, 2f
|
||||
nop
|
||||
sb $zero, 0($t1)
|
||||
b 1b
|
||||
addiu $t1, $t1, 1
|
||||
2:
|
||||
lui $a0, %hi(base)
|
||||
addiu $a0, $a0, %lo(base)
|
||||
lui $a1, %hi(_end)
|
||||
addiu $a1, %lo(_end)
|
||||
subu $a1,$a1,$a0
|
||||
|
||||
#include "../../kern/mips/cache_flush.S"
|
||||
|
||||
/* Decompress the payload. */
|
||||
lui $a0, %hi(__bss_start)
|
||||
addiu $a0, $a0, %lo(__bss_start)
|
||||
lui $t0, %hi(base)
|
||||
addiu $t0, $t0, %lo(base)
|
||||
subu $a0, $a0, $t0
|
||||
addu $a0, $a0, $s0
|
||||
|
||||
lw $a1, (GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR - BASE_ADDR)($s0)
|
||||
lw $a2, (GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE - BASE_ADDR)($s0)
|
||||
lw $a3, (GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE - BASE_ADDR)($s0)
|
||||
move $s1, $a1
|
||||
|
||||
/* $a0 contains source compressed address, $a1 is destination,
|
||||
$a2 is compressed size, $a3 is uncompressed size.
|
||||
*/
|
||||
move $s6, $a3
|
||||
|
||||
lui $t0, %hi(EXT_C(grub_decompress_core))
|
||||
addiu $t0, $t0, %lo(EXT_C(grub_decompress_core))
|
||||
|
||||
lui $sp, %hi(_start - 256)
|
||||
jalr $t0
|
||||
addiu $sp, $sp, %lo(_start - 256)
|
||||
|
||||
move $a0, $s1
|
||||
move $a1, $s6
|
||||
|
||||
#include "../../kern/mips/cache_flush.S"
|
||||
|
||||
lui $t1, %hi(GRUB_MACHINE_LINK_ADDR)
|
||||
addiu $t1, %lo(GRUB_MACHINE_LINK_ADDR)
|
||||
|
||||
jr $t1
|
||||
nop
|
|
@ -17,7 +17,6 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/boot.h>
|
||||
#include <grub/machine/boot.h>
|
||||
|
||||
.text
|
||||
|
@ -29,9 +28,6 @@ pic_base:
|
|||
call boot_continue
|
||||
mov %o4, CIF_REG
|
||||
|
||||
. = _start + GRUB_BOOT_MACHINE_VER_MAJ
|
||||
boot_version: .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
|
||||
|
||||
/* The offsets to these locations are defined by the
|
||||
* GRUB_BOOT_MACHINE_foo macros in include/grub/sparc/ieee1275/boot.h,
|
||||
* and grub-setup uses this to patch these next three values as needed.
|
||||
|
@ -44,6 +40,7 @@ boot_version: .byte GRUB_BOOT_VERSION_MAJOR, GRUB_BOOT_VERSION_MINOR
|
|||
* After loading in that block we will execute it by jumping to the
|
||||
* load address plus the size of the prepended A.OUT header (32 bytes).
|
||||
*/
|
||||
. = _start + GRUB_BOOT_MACHINE_BOOT_DEVPATH
|
||||
boot_path:
|
||||
. = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE
|
||||
boot_path_end:
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/boot.h>
|
||||
#include <grub/machine/boot.h>
|
||||
#include <grub/offsets.h>
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ write_bases (void)
|
|||
for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++)
|
||||
reg |= (((base_win[i] >> GRUB_MACHINE_PCI_WIN_SHIFT)
|
||||
& GRUB_MACHINE_PCI_WIN_MASK)
|
||||
>> (i * GRUB_MACHINE_PCI_WIN_MASK_SIZE));
|
||||
<< (i * GRUB_MACHINE_PCI_WIN_MASK_SIZE));
|
||||
GRUB_MACHINE_PCI_IO_CTRL_REG = reg;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,13 @@
|
|||
#include <grub/pci.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/ata.h>
|
||||
#ifdef GRUB_MACHINE_MIPS_LOONGSON
|
||||
#include <grub/machine/kernel.h>
|
||||
#endif
|
||||
|
||||
#include <grub/dl.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
int
|
||||
grub_cs5536_find (grub_pci_device_t *devp)
|
||||
|
@ -213,26 +220,6 @@ grub_cs5536_read_spd (grub_port_t smbbase, grub_uint8_t dev,
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Dump of GPIO connections. FIXME: Remove useless and macroify. */
|
||||
static grub_uint32_t gpiodump[] = {
|
||||
0xffff0000, 0x2ffdd002, 0xffff0000, 0xffff0000,
|
||||
0x2fffd000, 0xffff0000, 0x1000efff, 0xefff1000,
|
||||
0x3ffbc004, 0xffff0000, 0xffff0000, 0xffff0000,
|
||||
0x3ffbc004, 0x3ffbc004, 0xffff0000, 0x00000000,
|
||||
0xffff0000, 0xffff0000, 0x3ffbc004, 0x3f9bc064,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000,
|
||||
0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000,
|
||||
0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000,
|
||||
0xefff1000, 0xefff1000, 0xffff0000, 0x00000000,
|
||||
0xffff0000, 0xffff0000, 0xefff1000, 0xffff0000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x50000000, 0x00000000, 0x00000000,
|
||||
};
|
||||
|
||||
static inline void
|
||||
set_io_space (grub_pci_device_t dev, int num, grub_uint16_t start,
|
||||
grub_uint16_t len)
|
||||
|
@ -273,17 +260,6 @@ set_p2d (grub_pci_device_t dev, int num, int dest, grub_uint32_t start)
|
|||
void
|
||||
grub_cs5536_init_geode (grub_pci_device_t dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Make sure GPIO is where we expect it to be. */
|
||||
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_GPIO_BAR,
|
||||
GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_GPIO);
|
||||
|
||||
/* Setup GPIO. */
|
||||
for (i = 0; i < (int) ARRAY_SIZE (gpiodump); i++)
|
||||
((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_IO_BASE
|
||||
+ GRUB_CS5536_LBAR_GPIO)) [i] = gpiodump[i];
|
||||
|
||||
/* Enable more BARs. */
|
||||
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_IRQ_MAP_BAR,
|
||||
GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_IRQ_MAP);
|
||||
|
@ -295,11 +271,27 @@ grub_cs5536_init_geode (grub_pci_device_t dev)
|
|||
GRUB_CS5536_LBAR_TURN_ON | GRUB_CS5536_LBAR_PM);
|
||||
|
||||
/* Setup DIVIL. */
|
||||
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LEG_IO,
|
||||
GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1);
|
||||
#ifdef GRUB_MACHINE_MIPS_LOONGSON
|
||||
switch (grub_arch_machine)
|
||||
{
|
||||
case GRUB_ARCH_MACHINE_YEELOONG:
|
||||
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LEG_IO,
|
||||
GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1);
|
||||
break;
|
||||
case GRUB_ARCH_MACHINE_FULOONG2F:
|
||||
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_LEG_IO,
|
||||
GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0
|
||||
| GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK,
|
||||
(~GRUB_CS5536_DIVIL_LPC_INTERRUPTS) & 0xffff);
|
||||
grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK,
|
||||
|
|
|
@ -20,23 +20,39 @@
|
|||
#include <grub/dl.h>
|
||||
#include <grub/pci.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm_private.h>
|
||||
#include <grub/cache.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/* FIXME: correctly support 64-bit architectures. */
|
||||
/* #if GRUB_TARGET_SIZEOF_VOID_P == 4 */
|
||||
struct grub_pci_dma_chunk *
|
||||
grub_memalign_dma32 (grub_size_t align, grub_size_t size)
|
||||
{
|
||||
return grub_memalign (align, size);
|
||||
void *ret;
|
||||
if (align < 64)
|
||||
align = 64;
|
||||
size = ALIGN_UP (size, align);
|
||||
ret = grub_memalign (align, size);
|
||||
if (!ret)
|
||||
return 0;
|
||||
grub_arch_sync_dma_caches (ret, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* FIXME: evil. */
|
||||
void
|
||||
grub_dma_free (struct grub_pci_dma_chunk *ch)
|
||||
{
|
||||
grub_size_t size = (((struct grub_mm_header *) ch) - 1)->size * GRUB_MM_ALIGN;
|
||||
grub_arch_sync_dma_caches (ch, size);
|
||||
grub_free (ch);
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
#ifdef GRUB_MACHINE_MIPS_YEELOONG
|
||||
#ifdef GRUB_MACHINE_MIPS_LOONGSON
|
||||
volatile void *
|
||||
grub_dma_get_virt (struct grub_pci_dma_chunk *ch)
|
||||
{
|
||||
|
@ -90,17 +106,14 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook)
|
|||
|
||||
/* Check if there is a device present. */
|
||||
if (id >> 16 == 0xFFFF)
|
||||
continue;
|
||||
|
||||
#ifdef GRUB_MACHINE_MIPS_YEELOONG
|
||||
/* Skip ghosts. */
|
||||
if (id == GRUB_YEELOONG_OHCI_PCIID
|
||||
&& dev.function == GRUB_YEELOONG_OHCI_GHOST_FUNCTION)
|
||||
continue;
|
||||
if (id == GRUB_YEELOONG_EHCI_PCIID
|
||||
&& dev.function == GRUB_YEELOONG_EHCI_GHOST_FUNCTION)
|
||||
continue;
|
||||
#endif
|
||||
{
|
||||
if (dev.function == 0)
|
||||
/* Devices are required to implement function 0, so if
|
||||
it's missing then there is no device here. */
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hook (dev, id))
|
||||
return;
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <grub/usb.h>
|
||||
#include <grub/dl.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
||||
static struct grub_usb_controller_dev usb_controller =
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,6 +18,9 @@
|
|||
|
||||
#include <grub/serial.h>
|
||||
#include <grub/usbserial.h>
|
||||
#include <grub/dl.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
void
|
||||
grub_usbserial_fini (struct grub_serial_port *port)
|
||||
|
@ -44,6 +47,7 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno,
|
|||
struct grub_serial_port *port;
|
||||
int j;
|
||||
struct grub_usb_desc_if *interf;
|
||||
grub_usb_err_t err = GRUB_USB_ERR_NONE;
|
||||
|
||||
interf = usbdev->config[configno].interf[interfno].descif;
|
||||
|
||||
|
@ -80,7 +84,12 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno,
|
|||
port->out_endp = endp;
|
||||
}
|
||||
}
|
||||
if (!port->out_endp || !port->in_endp)
|
||||
|
||||
/* Configure device */
|
||||
if (port->out_endp && port->in_endp)
|
||||
err = grub_usb_set_configuration (usbdev, configno + 1);
|
||||
|
||||
if (!port->out_endp || !port->in_endp || err)
|
||||
{
|
||||
grub_free (port->name);
|
||||
grub_free (port);
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <grub/usb.h>
|
||||
#include <grub/usbserial.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_FTDI_MODEM_CTRL = 0x01,
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <grub/usb.h>
|
||||
#include <grub/usbserial.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/* Convert speed to divisor. */
|
||||
static grub_uint32_t
|
||||
is_speed_supported (unsigned int speed)
|
||||
|
|
|
@ -26,19 +26,59 @@
|
|||
#include <grub/i386/io.h>
|
||||
#include <grub/time.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define GRUB_UHCI_IOMASK (0x7FF << 5)
|
||||
|
||||
#define N_QH 256
|
||||
#define N_TD 640
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GRUB_UHCI_REG_USBCMD = 0x00,
|
||||
GRUB_UHCI_REG_USBINTR = 0x04,
|
||||
GRUB_UHCI_REG_FLBASEADD = 0x08,
|
||||
GRUB_UHCI_REG_PORTSC1 = 0x10,
|
||||
GRUB_UHCI_REG_PORTSC2 = 0x12
|
||||
GRUB_UHCI_REG_PORTSC2 = 0x12,
|
||||
GRUB_UHCI_REG_USBLEGSUP = 0xc0
|
||||
} grub_uhci_reg_t;
|
||||
|
||||
/* R/WC legacy support bits */
|
||||
#define GRUB_UHCI_LEGSUP_END_A20GATE (1 << 15)
|
||||
#define GRUB_UHCI_TRAP_BY_64H_WSTAT (1 << 11)
|
||||
#define GRUB_UHCI_TRAP_BY_64H_RSTAT (1 << 10)
|
||||
#define GRUB_UHCI_TRAP_BY_60H_WSTAT (1 << 9)
|
||||
#define GRUB_UHCI_TRAP_BY_60H_RSTAT (1 << 8)
|
||||
|
||||
/* Reset all legacy support - clear all R/WC bits and all R/W bits */
|
||||
#define GRUB_UHCI_RESET_LEGSUP_SMI ( GRUB_UHCI_LEGSUP_END_A20GATE \
|
||||
| GRUB_UHCI_TRAP_BY_64H_WSTAT \
|
||||
| GRUB_UHCI_TRAP_BY_64H_RSTAT \
|
||||
| GRUB_UHCI_TRAP_BY_60H_WSTAT \
|
||||
| GRUB_UHCI_TRAP_BY_60H_RSTAT )
|
||||
|
||||
/* Some UHCI commands */
|
||||
#define GRUB_UHCI_CMD_RUN_STOP (1 << 0)
|
||||
#define GRUB_UHCI_CMD_HCRESET (1 << 1)
|
||||
#define GRUB_UHCI_CMD_MAXP (1 << 7)
|
||||
|
||||
/* Important bits in structures */
|
||||
#define GRUB_UHCI_LINK_TERMINATE 1
|
||||
#define GRUB_UHCI_LINK_QUEUE_HEAD 2
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED = 0x0002,
|
||||
GRUB_UHCI_REG_PORTSC_PORT_ENABLED = 0x0004,
|
||||
GRUB_UHCI_REG_PORTSC_RESUME = 0x0040,
|
||||
GRUB_UHCI_REG_PORTSC_RESET = 0x0200,
|
||||
GRUB_UHCI_REG_PORTSC_SUSPEND = 0x1000,
|
||||
GRUB_UHCI_REG_PORTSC_RW = GRUB_UHCI_REG_PORTSC_PORT_ENABLED
|
||||
| GRUB_UHCI_REG_PORTSC_RESUME | GRUB_UHCI_REG_PORTSC_RESET
|
||||
| GRUB_UHCI_REG_PORTSC_SUSPEND,
|
||||
/* These bits should not be written as 1 unless we really need it */
|
||||
GRUB_UHCI_PORTSC_RWC = ((1 << 1) | (1 << 3) | (1 << 11) | (3 << 13))
|
||||
};
|
||||
|
||||
/* UHCI Queue Head. */
|
||||
struct grub_uhci_qh
|
||||
|
@ -87,15 +127,17 @@ struct grub_uhci
|
|||
int iobase;
|
||||
grub_uint32_t *framelist;
|
||||
|
||||
/* 256 Queue Heads. */
|
||||
/* N_QH Queue Heads. */
|
||||
grub_uhci_qh_t qh;
|
||||
|
||||
/* 256 Transfer Descriptors. */
|
||||
/* N_TD Transfer Descriptors. */
|
||||
grub_uhci_td_t td;
|
||||
|
||||
/* Free Transfer Descriptors. */
|
||||
grub_uhci_td_t tdfree;
|
||||
|
||||
int qh_busy[N_QH];
|
||||
|
||||
struct grub_uhci *next;
|
||||
};
|
||||
|
||||
|
@ -161,6 +203,11 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
|||
if (class != 0x0c || subclass != 0x03 || interf != 0x00)
|
||||
return 0;
|
||||
|
||||
/* Set bus master - needed for coreboot or broken BIOSes */
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND);
|
||||
grub_pci_write_word(addr,
|
||||
GRUB_PCI_COMMAND_BUS_MASTER | grub_pci_read_word(addr));
|
||||
|
||||
/* Determine IO base address. */
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG4);
|
||||
base = grub_pci_read (addr);
|
||||
|
@ -175,6 +222,19 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
|||
|
||||
u->iobase = base & GRUB_UHCI_IOMASK;
|
||||
|
||||
/* Reset PIRQ and SMI */
|
||||
addr = grub_pci_make_address (dev, GRUB_UHCI_REG_USBLEGSUP);
|
||||
grub_pci_write_word(addr, GRUB_UHCI_RESET_LEGSUP_SMI);
|
||||
/* Reset the HC */
|
||||
grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, GRUB_UHCI_CMD_HCRESET);
|
||||
grub_millisleep(5);
|
||||
/* Disable interrupts and commands (just to be safe) */
|
||||
grub_uhci_writereg16(u, GRUB_UHCI_REG_USBINTR, 0);
|
||||
/* Finish HC reset, HC remains disabled */
|
||||
grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, 0);
|
||||
/* Read back to be sure PCI write is done */
|
||||
grub_uhci_readreg16(u, GRUB_UHCI_REG_USBCMD);
|
||||
|
||||
/* Reserve a page for the frame list. */
|
||||
u->framelist = grub_memalign (4096, 4096);
|
||||
if (! u->framelist)
|
||||
|
@ -196,7 +256,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
|||
|
||||
/* 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, 4096);
|
||||
u->qh = (grub_uhci_qh_t) grub_memalign (4096, sizeof(struct grub_uhci_qh)*N_QH);
|
||||
if (! u->qh)
|
||||
goto fail;
|
||||
|
||||
|
@ -210,7 +270,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
|||
|
||||
/* 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, 4096*2);
|
||||
u->td = (grub_uhci_td_t) grub_memalign (4096, sizeof(struct grub_uhci_td)*N_TD);
|
||||
if (! u->td)
|
||||
goto fail;
|
||||
|
||||
|
@ -227,14 +287,11 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
|||
|
||||
/* Link all Transfer Descriptors in a list of available Transfer
|
||||
Descriptors. */
|
||||
for (i = 0; i < 256; i++)
|
||||
for (i = 0; i < N_TD; i++)
|
||||
u->td[i].linkptr = (grub_uint32_t) (grub_addr_t) &u->td[i + 1];
|
||||
u->td[255 - 1].linkptr = 0;
|
||||
u->td[N_TD - 2].linkptr = 0;
|
||||
u->tdfree = u->td;
|
||||
|
||||
/* Make sure UHCI is disabled! */
|
||||
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 0);
|
||||
|
||||
/* Setup the frame list pointers. Since no isochronous transfers
|
||||
are and will be supported, they all point to the (same!) queue
|
||||
head. */
|
||||
|
@ -248,7 +305,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
|||
(grub_uint32_t) (grub_addr_t) u->framelist);
|
||||
|
||||
/* Make the Queue Heads point to each other. */
|
||||
for (i = 0; i < 256; i++)
|
||||
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);
|
||||
|
@ -261,12 +318,12 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
|
|||
u->qh[i].elinkptr = 1;
|
||||
}
|
||||
|
||||
/* The last Queue Head should terminate. 256 are too many QHs so
|
||||
just use 50. */
|
||||
u->qh[50 - 1].linkptr = 1;
|
||||
/* The last Queue Head should terminate. */
|
||||
u->qh[N_QH - 1].linkptr = 1;
|
||||
|
||||
/* Enable UHCI again. */
|
||||
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 1 | (1 << 7));
|
||||
grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD,
|
||||
GRUB_UHCI_CMD_RUN_STOP | GRUB_UHCI_CMD_MAXP);
|
||||
|
||||
/* UHCI is initialized and ready for transfers. */
|
||||
grub_dprintf ("uhci", "UHCI initialized\n");
|
||||
|
@ -332,11 +389,13 @@ grub_free_td (struct grub_uhci *u, grub_uhci_td_t td)
|
|||
}
|
||||
|
||||
static void
|
||||
grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td,
|
||||
grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td,
|
||||
grub_usb_transfer_t transfer, grub_size_t *actual)
|
||||
{
|
||||
int i; /* Index of TD in transfer */
|
||||
|
||||
u->qh_busy[qh - u->qh] = 0;
|
||||
|
||||
*actual = 0;
|
||||
|
||||
/* Free the TDs in this queue and set last_trans. */
|
||||
|
@ -375,19 +434,21 @@ grub_alloc_qh (struct grub_uhci *u,
|
|||
#endif
|
||||
i = 1;
|
||||
|
||||
for (; i < 255; i++)
|
||||
for (; i < N_QH; i++)
|
||||
{
|
||||
if (u->qh[i].elinkptr & 1)
|
||||
if (!u->qh_busy[i])
|
||||
break;
|
||||
}
|
||||
qh = &u->qh[i];
|
||||
if (! (qh->elinkptr & 1))
|
||||
if (i == N_QH)
|
||||
{
|
||||
grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"no free queue heads available");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u->qh_busy[qh - u->qh] = 1;
|
||||
|
||||
return qh;
|
||||
}
|
||||
|
||||
|
@ -395,7 +456,7 @@ static grub_uhci_td_t
|
|||
grub_uhci_transaction (struct grub_uhci *u, unsigned int endp,
|
||||
grub_transfer_type_t type, unsigned int addr,
|
||||
unsigned int toggle, grub_size_t size,
|
||||
grub_uint32_t data)
|
||||
grub_uint32_t data, grub_usb_speed_t speed)
|
||||
{
|
||||
grub_uhci_td_t td;
|
||||
static const unsigned int tf[] = { 0x69, 0xE1, 0x2D };
|
||||
|
@ -420,7 +481,8 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp,
|
|||
td->linkptr = 1;
|
||||
|
||||
/* Active! Only retry a transfer 3 times. */
|
||||
td->ctrl_status = (1 << 23) | (3 << 27);
|
||||
td->ctrl_status = (1 << 23) | (3 << 27) |
|
||||
((speed == GRUB_USB_SPEED_LOW) ? (1 << 26) : 0);
|
||||
|
||||
/* If zero bytes are transmitted, size is 0x7FF. Otherwise size is
|
||||
size-1. */
|
||||
|
@ -438,26 +500,35 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp,
|
|||
return td;
|
||||
}
|
||||
|
||||
struct grub_uhci_transfer_controller_data
|
||||
{
|
||||
grub_uhci_qh_t qh;
|
||||
grub_uhci_td_t td_first;
|
||||
};
|
||||
|
||||
static grub_usb_err_t
|
||||
grub_uhci_transfer (grub_usb_controller_t dev,
|
||||
grub_usb_transfer_t transfer,
|
||||
int timeout, grub_size_t *actual)
|
||||
grub_uhci_setup_transfer (grub_usb_controller_t dev,
|
||||
grub_usb_transfer_t transfer)
|
||||
{
|
||||
struct grub_uhci *u = (struct grub_uhci *) dev->data;
|
||||
grub_uhci_qh_t qh;
|
||||
grub_uhci_td_t td;
|
||||
grub_uhci_td_t td_first = NULL;
|
||||
grub_uhci_td_t td_prev = NULL;
|
||||
grub_usb_err_t err = GRUB_USB_ERR_NONE;
|
||||
int i;
|
||||
grub_uint64_t endtime;
|
||||
struct grub_uhci_transfer_controller_data *cdata;
|
||||
|
||||
*actual = 0;
|
||||
cdata = grub_malloc (sizeof (*cdata));
|
||||
if (!cdata)
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
|
||||
cdata->td_first = NULL;
|
||||
|
||||
/* Allocate a queue head for the transfer queue. */
|
||||
qh = grub_alloc_qh (u, GRUB_USB_TRANSACTION_TYPE_CONTROL);
|
||||
if (! qh)
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
cdata->qh = grub_alloc_qh (u, GRUB_USB_TRANSACTION_TYPE_CONTROL);
|
||||
if (! cdata->qh)
|
||||
{
|
||||
grub_free (cdata);
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
grub_dprintf ("uhci", "transfer, iobase:%08x\n", u->iobase);
|
||||
|
||||
|
@ -465,23 +536,29 @@ grub_uhci_transfer (grub_usb_controller_t dev,
|
|||
{
|
||||
grub_usb_transaction_t tr = &transfer->transactions[i];
|
||||
|
||||
td = grub_uhci_transaction (u, transfer->endpoint, tr->pid,
|
||||
td = grub_uhci_transaction (u, transfer->endpoint & 15, tr->pid,
|
||||
transfer->devaddr, tr->toggle,
|
||||
tr->size, tr->data);
|
||||
tr->size, tr->data,
|
||||
transfer->dev->speed);
|
||||
if (! td)
|
||||
{
|
||||
grub_size_t actual = 0;
|
||||
/* Terminate and free. */
|
||||
td_prev->linkptr2 = 0;
|
||||
td_prev->linkptr = 1;
|
||||
if (td_prev)
|
||||
{
|
||||
td_prev->linkptr2 = 0;
|
||||
td_prev->linkptr = 1;
|
||||
}
|
||||
|
||||
if (td_first)
|
||||
grub_free_queue (u, td_first, NULL, actual);
|
||||
if (cdata->td_first)
|
||||
grub_free_queue (u, cdata->qh, cdata->td_first, NULL, &actual);
|
||||
|
||||
grub_free (cdata);
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
if (! td_first)
|
||||
td_first = td;
|
||||
if (! cdata->td_first)
|
||||
cdata->td_first = td;
|
||||
else
|
||||
{
|
||||
td_prev->linkptr2 = (grub_uint32_t) (grub_addr_t) td;
|
||||
|
@ -497,81 +574,112 @@ grub_uhci_transfer (grub_usb_controller_t dev,
|
|||
|
||||
/* Link it into the queue and terminate. Now the transaction can
|
||||
take place. */
|
||||
qh->elinkptr = (grub_uint32_t) (grub_addr_t) td_first;
|
||||
cdata->qh->elinkptr = (grub_uint32_t) (grub_addr_t) cdata->td_first;
|
||||
|
||||
grub_dprintf ("uhci", "initiate transaction\n");
|
||||
|
||||
/* Wait until either the transaction completed or an error
|
||||
occurred. */
|
||||
endtime = grub_get_time_ms () + timeout;
|
||||
for (;;)
|
||||
transfer->controller_data = cdata;
|
||||
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_usb_err_t
|
||||
grub_uhci_check_transfer (grub_usb_controller_t dev,
|
||||
grub_usb_transfer_t transfer,
|
||||
grub_size_t *actual)
|
||||
{
|
||||
struct grub_uhci *u = (struct grub_uhci *) dev->data;
|
||||
grub_uhci_td_t errtd;
|
||||
struct grub_uhci_transfer_controller_data *cdata = transfer->controller_data;
|
||||
|
||||
*actual = 0;
|
||||
|
||||
errtd = (grub_uhci_td_t) (grub_addr_t) (cdata->qh->elinkptr & ~0x0f);
|
||||
|
||||
grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n",
|
||||
errtd->ctrl_status, errtd->buffer & (~15), errtd);
|
||||
|
||||
/* Check if the transaction completed. */
|
||||
if (cdata->qh->elinkptr & 1)
|
||||
{
|
||||
grub_uhci_td_t errtd;
|
||||
grub_dprintf ("uhci", "transaction complete\n");
|
||||
|
||||
errtd = (grub_uhci_td_t) (grub_addr_t) (qh->elinkptr & ~0x0f);
|
||||
/* Place the QH back in the free list and deallocate the associated
|
||||
TDs. */
|
||||
cdata->qh->elinkptr = 1;
|
||||
grub_free_queue (u, cdata->qh, cdata->td_first, transfer, actual);
|
||||
grub_free (cdata);
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n",
|
||||
errtd->ctrl_status, errtd->buffer & (~15), errtd);
|
||||
grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status);
|
||||
|
||||
/* Check if the transaction completed. */
|
||||
if (qh->elinkptr & 1)
|
||||
break;
|
||||
|
||||
grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status);
|
||||
if (!(errtd->ctrl_status & (1 << 23)))
|
||||
{
|
||||
grub_usb_err_t err = GRUB_USB_ERR_NONE;
|
||||
|
||||
/* Check if the endpoint is stalled. */
|
||||
if (errtd->ctrl_status & (1 << 22))
|
||||
err = GRUB_USB_ERR_STALL;
|
||||
|
||||
|
||||
/* Check if an error related to the data buffer occurred. */
|
||||
if (errtd->ctrl_status & (1 << 21))
|
||||
else if (errtd->ctrl_status & (1 << 21))
|
||||
err = GRUB_USB_ERR_DATA;
|
||||
|
||||
|
||||
/* Check if a babble error occurred. */
|
||||
if (errtd->ctrl_status & (1 << 20))
|
||||
else if (errtd->ctrl_status & (1 << 20))
|
||||
err = GRUB_USB_ERR_BABBLE;
|
||||
|
||||
|
||||
/* Check if a NAK occurred. */
|
||||
if (errtd->ctrl_status & (1 << 19))
|
||||
else if (errtd->ctrl_status & (1 << 19))
|
||||
err = GRUB_USB_ERR_NAK;
|
||||
|
||||
|
||||
/* Check if a timeout occurred. */
|
||||
if (errtd->ctrl_status & (1 << 18))
|
||||
else if (errtd->ctrl_status & (1 << 18))
|
||||
err = GRUB_USB_ERR_TIMEOUT;
|
||||
|
||||
|
||||
/* Check if a bitstuff error occurred. */
|
||||
if (errtd->ctrl_status & (1 << 17))
|
||||
else if (errtd->ctrl_status & (1 << 17))
|
||||
err = GRUB_USB_ERR_BITSTUFF;
|
||||
|
||||
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
/* Fall through, no errors occurred, so the QH might be
|
||||
updated. */
|
||||
grub_dprintf ("uhci", "transaction fallthrough\n");
|
||||
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
err = GRUB_USB_ERR_STALL;
|
||||
grub_dprintf ("uhci", "transaction timed out\n");
|
||||
goto fail;
|
||||
grub_dprintf ("uhci", "transaction failed\n");
|
||||
|
||||
/* Place the QH back in the free list and deallocate the associated
|
||||
TDs. */
|
||||
cdata->qh->elinkptr = 1;
|
||||
grub_free_queue (u, cdata->qh, cdata->td_first, transfer, actual);
|
||||
grub_free (cdata);
|
||||
|
||||
return err;
|
||||
}
|
||||
grub_cpu_idle ();
|
||||
}
|
||||
|
||||
grub_dprintf ("uhci", "transaction complete\n");
|
||||
/* Fall through, no errors occurred, so the QH might be
|
||||
updated. */
|
||||
grub_dprintf ("uhci", "transaction fallthrough\n");
|
||||
|
||||
fail:
|
||||
return GRUB_USB_ERR_WAIT;
|
||||
}
|
||||
|
||||
if (err != GRUB_USB_ERR_NONE)
|
||||
grub_dprintf ("uhci", "transaction failed\n");
|
||||
static grub_usb_err_t
|
||||
grub_uhci_cancel_transfer (grub_usb_controller_t dev,
|
||||
grub_usb_transfer_t transfer)
|
||||
{
|
||||
struct grub_uhci *u = (struct grub_uhci *) dev->data;
|
||||
grub_size_t actual;
|
||||
struct grub_uhci_transfer_controller_data *cdata = transfer->controller_data;
|
||||
|
||||
grub_dprintf ("uhci", "transaction cancel\n");
|
||||
|
||||
/* Place the QH back in the free list and deallocate the associated
|
||||
TDs. */
|
||||
qh->elinkptr = 1;
|
||||
grub_free_queue (u, td_first, transfer, actual);
|
||||
cdata->qh->elinkptr = 1;
|
||||
grub_free_queue (u, cdata->qh, cdata->td_first, transfer, &actual);
|
||||
grub_free (cdata);
|
||||
|
||||
return err;
|
||||
return GRUB_USB_ERR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -622,7 +730,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev,
|
|||
endtime = grub_get_time_ms () + 1000;
|
||||
while ((grub_uhci_readreg16 (u, reg) & (1 << 2)))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
return grub_error (GRUB_ERR_IO, "UHCI Timed out");
|
||||
return grub_error (GRUB_ERR_IO, "UHCI Timed out - disable");
|
||||
|
||||
status = grub_uhci_readreg16 (u, reg);
|
||||
grub_dprintf ("uhci", ">3detect=0x%02x\n", status);
|
||||
|
@ -630,28 +738,37 @@ grub_uhci_portstatus (grub_usb_controller_t dev,
|
|||
}
|
||||
|
||||
/* Reset the port. */
|
||||
grub_uhci_writereg16 (u, reg, 1 << 9);
|
||||
status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC;
|
||||
grub_uhci_writereg16 (u, reg, status | (1 << 9));
|
||||
grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */
|
||||
|
||||
/* Wait for the reset to complete. XXX: How long exactly? */
|
||||
grub_millisleep (50); /* For root hub should be nominaly 50ms */
|
||||
status = grub_uhci_readreg16 (u, reg);
|
||||
status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC;
|
||||
grub_uhci_writereg16 (u, reg, status & ~(1 << 9));
|
||||
grub_dprintf ("uhci", "reset completed\n");
|
||||
grub_millisleep (10);
|
||||
grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */
|
||||
|
||||
/* Note: some debug prints were removed because they affected reset/enable timing. */
|
||||
|
||||
grub_millisleep (1); /* Probably not needed at all or only few microsecs. */
|
||||
|
||||
/* Reset bits Connect & Enable Status Change */
|
||||
status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC;
|
||||
grub_uhci_writereg16 (u, reg, status | (1 << 3) | GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED);
|
||||
grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */
|
||||
|
||||
/* Enable the port. */
|
||||
grub_uhci_writereg16 (u, reg, 1 << 2);
|
||||
grub_millisleep (10);
|
||||
|
||||
grub_dprintf ("uhci", "waiting for the port to be enabled\n");
|
||||
status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC;
|
||||
grub_uhci_writereg16 (u, reg, status | (1 << 2));
|
||||
grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */
|
||||
|
||||
endtime = grub_get_time_ms () + 1000;
|
||||
while (! ((status = grub_uhci_readreg16 (u, reg)) & (1 << 2)))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
return grub_error (GRUB_ERR_IO, "UHCI Timed out");
|
||||
return grub_error (GRUB_ERR_IO, "UHCI Timed out - enable");
|
||||
|
||||
/* Reset bit Connect Status Change */
|
||||
grub_uhci_writereg16 (u, reg, status | (1 << 1));
|
||||
/* Reset recovery time */
|
||||
grub_millisleep (10);
|
||||
|
||||
/* Read final port status */
|
||||
status = grub_uhci_readreg16 (u, reg);
|
||||
|
@ -675,15 +792,22 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
|
|||
else if (port == 1)
|
||||
reg = GRUB_UHCI_REG_PORTSC2;
|
||||
else
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
"UHCI Root Hub port does not exist");
|
||||
return GRUB_USB_SPEED_NONE;
|
||||
|
||||
status = grub_uhci_readreg16 (u, reg);
|
||||
|
||||
grub_dprintf ("uhci", "detect=0x%02x port=%d\n", status, port);
|
||||
|
||||
/* Connect Status Change bit - it detects change of connection */
|
||||
*changed = ((status & (1 << 1)) != 0);
|
||||
if (status & (1 << 1))
|
||||
{
|
||||
*changed = 1;
|
||||
/* Reset bit Connect Status Change */
|
||||
grub_uhci_writereg16 (u, reg, (status & GRUB_UHCI_REG_PORTSC_RW)
|
||||
| GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED);
|
||||
}
|
||||
else
|
||||
*changed = 0;
|
||||
|
||||
if (! (status & 1))
|
||||
return GRUB_USB_SPEED_NONE;
|
||||
|
@ -705,7 +829,9 @@ static struct grub_usb_controller_dev usb_controller =
|
|||
{
|
||||
.name = "uhci",
|
||||
.iterate = grub_uhci_iterate,
|
||||
.transfer = grub_uhci_transfer,
|
||||
.setup_transfer = grub_uhci_setup_transfer,
|
||||
.check_transfer = grub_uhci_check_transfer,
|
||||
.cancel_transfer = grub_uhci_cancel_transfer,
|
||||
.hubports = grub_uhci_hubports,
|
||||
.portstatus = grub_uhci_portstatus,
|
||||
.detect_dev = grub_uhci_detect_dev
|
||||
|
|
|
@ -24,8 +24,10 @@
|
|||
#include <grub/list.h>
|
||||
#include <grub/term.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_usb_controller_dev_t grub_usb_list;
|
||||
struct grub_usb_attach_desc *attach_hooks;
|
||||
static struct grub_usb_attach_desc *attach_hooks;
|
||||
|
||||
void
|
||||
grub_usb_controller_dev_register (grub_usb_controller_dev_t usb)
|
||||
|
@ -183,6 +185,12 @@ grub_usb_device_initialize (grub_usb_device_t dev)
|
|||
for (i = 0; i < 8; i++)
|
||||
dev->config[i].descconf = NULL;
|
||||
|
||||
if (descdev->configcnt == 0)
|
||||
{
|
||||
err = GRUB_USB_ERR_BADDEVICE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < descdev->configcnt; i++)
|
||||
{
|
||||
int pos;
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
/* USB Supports 127 devices, with device 0 as special case. */
|
||||
static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES];
|
||||
|
||||
static int rescan = 0;
|
||||
|
||||
struct grub_usb_hub
|
||||
{
|
||||
struct grub_usb_hub *next;
|
||||
|
@ -37,7 +39,7 @@ struct grub_usb_hub
|
|||
grub_usb_device_t dev;
|
||||
};
|
||||
|
||||
struct grub_usb_hub *hubs;
|
||||
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. */
|
||||
|
@ -108,11 +110,8 @@ static grub_usb_err_t
|
|||
grub_usb_add_hub (grub_usb_device_t dev)
|
||||
{
|
||||
struct grub_usb_usb_hubdesc hubdesc;
|
||||
grub_err_t err;
|
||||
grub_usb_err_t err;
|
||||
int i;
|
||||
grub_uint64_t timeout;
|
||||
grub_usb_device_t next_dev;
|
||||
grub_usb_device_t *attached_devices;
|
||||
|
||||
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
|
@ -131,11 +130,9 @@ grub_usb_add_hub (grub_usb_device_t dev)
|
|||
grub_dprintf ("usb", "Hub set configuration\n");
|
||||
grub_usb_set_configuration (dev, 1);
|
||||
|
||||
attached_devices = grub_zalloc (hubdesc.portcnt
|
||||
* sizeof (attached_devices[0]));
|
||||
if (!attached_devices)
|
||||
dev->children = grub_zalloc (hubdesc.portcnt * sizeof (dev->children[0]));
|
||||
if (!dev->children)
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
dev->children = attached_devices;
|
||||
dev->nports = hubdesc.portcnt;
|
||||
|
||||
/* Power on all Hub ports. */
|
||||
|
@ -143,115 +140,36 @@ grub_usb_add_hub (grub_usb_device_t dev)
|
|||
{
|
||||
grub_dprintf ("usb", "Power on - port %d\n", i);
|
||||
/* Power on the port and wait for possible device connect */
|
||||
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_SET_FEATURE,
|
||||
GRUB_USB_HUB_FEATURE_PORT_POWER,
|
||||
i, 0, NULL);
|
||||
/* Just ignore the device if some error happened */
|
||||
if (err)
|
||||
continue;
|
||||
grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_SET_FEATURE,
|
||||
GRUB_USB_HUB_FEATURE_PORT_POWER,
|
||||
i, 0, NULL);
|
||||
}
|
||||
/* Wait for port power-on */
|
||||
if (hubdesc.pwdgood >= 50)
|
||||
grub_millisleep (hubdesc.pwdgood * 2);
|
||||
else
|
||||
grub_millisleep (100);
|
||||
|
||||
/* Iterate over the Hub ports. */
|
||||
for (i = 1; i <= hubdesc.portcnt; i++)
|
||||
|
||||
/* Rest will be done on next usb poll. */
|
||||
for (i = 0; i < dev->config[0].interf[0].descif->endpointcnt;
|
||||
i++)
|
||||
{
|
||||
grub_uint32_t status;
|
||||
struct grub_usb_desc_endp *endp = NULL;
|
||||
endp = &dev->config[0].interf[0].descendp[i];
|
||||
|
||||
/* Get the port status. */
|
||||
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_GET_STATUS,
|
||||
0, i, sizeof (status), (char *) &status);
|
||||
/* Just ignore the device if the Hub does not report the
|
||||
status. */
|
||||
if (err)
|
||||
continue;
|
||||
grub_dprintf ("usb", "Hub port %d status: 0x%02x\n", i, status);
|
||||
|
||||
/* If connected, reset and enable the port. */
|
||||
if (status & GRUB_USB_HUB_STATUS_CONNECTED)
|
||||
if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp)
|
||||
== GRUB_USB_EP_INTERRUPT)
|
||||
{
|
||||
grub_usb_speed_t speed;
|
||||
|
||||
/* Determine the device speed. */
|
||||
if (status & GRUB_USB_HUB_STATUS_LOWSPEED)
|
||||
speed = GRUB_USB_SPEED_LOW;
|
||||
else
|
||||
{
|
||||
if (status & GRUB_USB_HUB_STATUS_HIGHSPEED)
|
||||
speed = GRUB_USB_SPEED_HIGH;
|
||||
else
|
||||
speed = GRUB_USB_SPEED_FULL;
|
||||
}
|
||||
|
||||
/* A device is actually connected to this port.
|
||||
* Now do reset of port. */
|
||||
grub_dprintf ("usb", "Reset hub port - port %d\n", i);
|
||||
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_SET_FEATURE,
|
||||
GRUB_USB_HUB_FEATURE_PORT_RESET,
|
||||
i, 0, 0);
|
||||
/* If the Hub does not cooperate for this port, just skip
|
||||
the port. */
|
||||
if (err)
|
||||
continue;
|
||||
|
||||
/* Wait for reset procedure done */
|
||||
timeout = grub_get_time_ms () + 1000;
|
||||
do
|
||||
{
|
||||
/* Get the port status. */
|
||||
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_GET_STATUS,
|
||||
0, i, sizeof (status), (char *) &status);
|
||||
}
|
||||
while (!err &&
|
||||
!(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) &&
|
||||
(grub_get_time_ms() < timeout) );
|
||||
if (err || !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) )
|
||||
continue;
|
||||
|
||||
/* Wait a recovery time after reset, spec. says 10ms */
|
||||
grub_millisleep (10);
|
||||
|
||||
/* Do reset of connection change bit */
|
||||
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_CLEAR_FEATURE,
|
||||
GRUB_USB_HUB_FEATURE_C_CONNECTED,
|
||||
i, 0, 0);
|
||||
/* Just ignore the device if the Hub reports some error */
|
||||
if (err)
|
||||
continue;
|
||||
grub_dprintf ("usb", "Hub port - cleared connection change\n");
|
||||
|
||||
/* Add the device and assign a device address to it. */
|
||||
grub_dprintf ("usb", "Call hub_add_dev - port %d\n", i);
|
||||
next_dev = grub_usb_hub_add_dev (&dev->controller, speed);
|
||||
if (! next_dev)
|
||||
continue;
|
||||
|
||||
attached_devices[i - 1] = next_dev;
|
||||
|
||||
/* If the device is a Hub, scan it for more devices. */
|
||||
if (next_dev->descdev.class == 0x09)
|
||||
grub_usb_add_hub (next_dev);
|
||||
dev->hub_endpoint = endp;
|
||||
dev->hub_transfer
|
||||
= grub_usb_bulk_read_background (dev, endp->endp_addr,
|
||||
grub_min (endp->maxpacket,
|
||||
sizeof (dev->statuschange)),
|
||||
(char *) &dev->statuschange);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rescan = 1;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -261,19 +179,47 @@ attach_root_port (struct grub_usb_hub *hub, int portno,
|
|||
{
|
||||
grub_usb_device_t dev;
|
||||
grub_err_t err;
|
||||
int total, i;
|
||||
grub_usb_speed_t current_speed = GRUB_USB_SPEED_NONE;
|
||||
int changed=0;
|
||||
|
||||
#if 0
|
||||
/* Specification does not say about disabling of port when device
|
||||
* connected. If disabling is really necessary for some devices,
|
||||
* delete this #if 0 and related #endif */
|
||||
/* Disable the port. XXX: Why? */
|
||||
err = hub->controller->dev->portstatus (hub->controller, portno, 0);
|
||||
if (err)
|
||||
return;
|
||||
#endif
|
||||
/* Wait for completion of insertion and stable power (USB spec.)
|
||||
* Should be at least 100ms, some devices requires more...
|
||||
* There is also another thing - some devices have worse contacts
|
||||
* and connected signal is unstable for some time - we should handle
|
||||
* it - but prevent deadlock in case when device is too faulty... */
|
||||
for (total = i = 0; (i < 250) && (total < 2000); i++, total++)
|
||||
{
|
||||
grub_millisleep (1);
|
||||
current_speed = hub->controller->dev->detect_dev
|
||||
(hub->controller, portno, &changed);
|
||||
if (current_speed == GRUB_USB_SPEED_NONE)
|
||||
i = 0;
|
||||
}
|
||||
grub_dprintf ("usb", "total=%d\n", total);
|
||||
if (total >= 2000)
|
||||
return;
|
||||
|
||||
/* Enable the port. */
|
||||
err = hub->controller->dev->portstatus (hub->controller, portno, 1);
|
||||
if (err)
|
||||
return;
|
||||
hub->controller->dev->pending_reset = grub_get_time_ms () + 5000;
|
||||
|
||||
grub_millisleep (10);
|
||||
|
||||
/* Enable the port and create a device. */
|
||||
dev = grub_usb_hub_add_dev (hub->controller, speed);
|
||||
hub->controller->dev->pending_reset = 0;
|
||||
if (! dev)
|
||||
return;
|
||||
|
||||
|
@ -320,11 +266,14 @@ grub_usb_root_hub (grub_usb_controller_t controller)
|
|||
for (i = 0; i < hub->nports; i++)
|
||||
{
|
||||
grub_usb_speed_t speed;
|
||||
speed = controller->dev->detect_dev (hub->controller, i,
|
||||
&changed);
|
||||
if (!controller->dev->pending_reset)
|
||||
{
|
||||
speed = controller->dev->detect_dev (hub->controller, i,
|
||||
&changed);
|
||||
|
||||
if (speed != GRUB_USB_SPEED_NONE)
|
||||
attach_root_port (hub, i, speed);
|
||||
if (speed != GRUB_USB_SPEED_NONE)
|
||||
attach_root_port (hub, i, speed);
|
||||
}
|
||||
}
|
||||
|
||||
return GRUB_USB_ERR_NONE;
|
||||
|
@ -341,6 +290,9 @@ detach_device (grub_usb_device_t dev)
|
|||
return;
|
||||
if (dev->descdev.class == GRUB_USB_CLASS_HUB)
|
||||
{
|
||||
if (dev->hub_transfer)
|
||||
grub_usb_cancel_transfer (dev->hub_transfer);
|
||||
|
||||
for (i = 0; i < dev->nports; i++)
|
||||
detach_device (dev->children[i]);
|
||||
grub_free (dev->children);
|
||||
|
@ -359,16 +311,39 @@ detach_device (grub_usb_device_t dev)
|
|||
static void
|
||||
poll_nonroot_hub (grub_usb_device_t dev)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_usb_err_t err;
|
||||
unsigned i;
|
||||
grub_uint64_t timeout;
|
||||
grub_usb_device_t next_dev;
|
||||
grub_usb_device_t *attached_devices = dev->children;
|
||||
|
||||
grub_uint8_t changed;
|
||||
grub_size_t actual;
|
||||
int j, total;
|
||||
|
||||
if (!dev->hub_transfer)
|
||||
return;
|
||||
|
||||
err = grub_usb_check_transfer (dev->hub_transfer, &actual);
|
||||
|
||||
if (err == GRUB_USB_ERR_WAIT)
|
||||
return;
|
||||
|
||||
changed = 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)),
|
||||
(char *) &dev->statuschange);
|
||||
|
||||
if (err || actual == 0 || changed == 0)
|
||||
return;
|
||||
|
||||
/* Iterate over the Hub ports. */
|
||||
for (i = 1; i <= dev->nports; i++)
|
||||
{
|
||||
grub_uint32_t status;
|
||||
grub_uint32_t current_status = 0;
|
||||
|
||||
if (!(changed & (1 << i)))
|
||||
continue;
|
||||
|
||||
/* Get the port status. */
|
||||
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
|
||||
|
@ -376,92 +351,140 @@ poll_nonroot_hub (grub_usb_device_t dev)
|
|||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_GET_STATUS,
|
||||
0, i, sizeof (status), (char *) &status);
|
||||
/* Just ignore the device if the Hub does not report the
|
||||
status. */
|
||||
|
||||
grub_dprintf ("usb", "dev = %p, i = %d, status = %08x\n",
|
||||
dev, i, status);
|
||||
|
||||
if (err)
|
||||
continue;
|
||||
|
||||
if (status & GRUB_USB_HUB_STATUS_C_CONNECTED)
|
||||
/* FIXME: properly handle these conditions. */
|
||||
if (status & GRUB_USB_HUB_STATUS_C_PORT_ENABLED)
|
||||
grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_CLEAR_FEATURE,
|
||||
GRUB_USB_HUB_FEATURE_C_PORT_ENABLED, i, 0, 0);
|
||||
|
||||
if (status & GRUB_USB_HUB_STATUS_C_PORT_SUSPEND)
|
||||
grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_CLEAR_FEATURE,
|
||||
GRUB_USB_HUB_FEATURE_C_PORT_SUSPEND, i, 0, 0);
|
||||
|
||||
if (status & GRUB_USB_HUB_STATUS_C_PORT_OVERCURRENT)
|
||||
grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_CLEAR_FEATURE,
|
||||
GRUB_USB_HUB_FEATURE_C_PORT_OVERCURRENT, i, 0, 0);
|
||||
|
||||
if (!dev->controller.dev->pending_reset &&
|
||||
(status & GRUB_USB_HUB_STATUS_C_PORT_CONNECTED))
|
||||
{
|
||||
detach_device (attached_devices[i-1]);
|
||||
attached_devices[i - 1] = NULL;
|
||||
}
|
||||
grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_CLEAR_FEATURE,
|
||||
GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED, i, 0, 0);
|
||||
|
||||
detach_device (dev->children[i - 1]);
|
||||
dev->children[i - 1] = NULL;
|
||||
|
||||
/* Connected and status of connection changed ? */
|
||||
if ((status & GRUB_USB_HUB_STATUS_CONNECTED)
|
||||
&& (status & GRUB_USB_HUB_STATUS_C_CONNECTED))
|
||||
{
|
||||
grub_usb_speed_t speed;
|
||||
|
||||
/* Determine the device speed. */
|
||||
if (status & GRUB_USB_HUB_STATUS_LOWSPEED)
|
||||
speed = GRUB_USB_SPEED_LOW;
|
||||
else
|
||||
/* Connected and status of connection changed ? */
|
||||
if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)
|
||||
{
|
||||
if (status & GRUB_USB_HUB_STATUS_HIGHSPEED)
|
||||
speed = GRUB_USB_SPEED_HIGH;
|
||||
else
|
||||
speed = GRUB_USB_SPEED_FULL;
|
||||
/* A device is actually connected to this port. */
|
||||
/* Wait for completion of insertion and stable power (USB spec.)
|
||||
* Should be at least 100ms, some devices requires more...
|
||||
* There is also another thing - some devices have worse contacts
|
||||
* and connected signal is unstable for some time - we should handle
|
||||
* it - but prevent deadlock in case when device is too faulty... */
|
||||
for (total = j = 0; (j < 250) && (total < 2000); j++, total++)
|
||||
{
|
||||
grub_millisleep (1);
|
||||
/* Get the port status. */
|
||||
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_GET_STATUS,
|
||||
0, i,
|
||||
sizeof (current_status),
|
||||
(char *) ¤t_status);
|
||||
if (err)
|
||||
{
|
||||
total = 2000;
|
||||
break;
|
||||
}
|
||||
if (!(current_status & GRUB_USB_HUB_STATUS_PORT_CONNECTED))
|
||||
j = 0;
|
||||
}
|
||||
grub_dprintf ("usb", "(non-root) total=%d\n", total);
|
||||
if (total >= 2000)
|
||||
continue;
|
||||
|
||||
/* Now do reset of port. */
|
||||
grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_SET_FEATURE,
|
||||
GRUB_USB_HUB_FEATURE_PORT_RESET,
|
||||
i, 0, 0);
|
||||
rescan = 1;
|
||||
/* We cannot reset more than one device at the same time !
|
||||
* Resetting more devices together results in very bad
|
||||
* situation: more than one device has default address 0
|
||||
* at the same time !!!
|
||||
* Additionaly, we cannot perform another reset
|
||||
* anywhere on the same OHCI controller until
|
||||
* we will finish addressing of reseted device ! */
|
||||
dev->controller.dev->pending_reset = grub_get_time_ms () + 5000;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* A device is actually connected to this port.
|
||||
* Now do reset of port. */
|
||||
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_SET_FEATURE,
|
||||
GRUB_USB_HUB_FEATURE_PORT_RESET,
|
||||
i, 0, 0);
|
||||
/* If the Hub does not cooperate for this port, just skip
|
||||
the port. */
|
||||
if (err)
|
||||
continue;
|
||||
if (status & GRUB_USB_HUB_STATUS_C_PORT_RESET)
|
||||
{
|
||||
grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_CLEAR_FEATURE,
|
||||
GRUB_USB_HUB_FEATURE_C_PORT_RESET, i, 0, 0);
|
||||
|
||||
/* Wait for reset procedure done */
|
||||
timeout = grub_get_time_ms () + 1000;
|
||||
do
|
||||
{
|
||||
/* Get the port status. */
|
||||
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_GET_STATUS,
|
||||
0, i, sizeof (status), (char *) &status);
|
||||
}
|
||||
while (!err &&
|
||||
!(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) &&
|
||||
(grub_get_time_ms() < timeout) );
|
||||
if (err || !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) )
|
||||
continue;
|
||||
if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)
|
||||
{
|
||||
grub_usb_speed_t speed;
|
||||
grub_usb_device_t next_dev;
|
||||
|
||||
/* Wait a recovery time after reset, spec. says 10ms */
|
||||
grub_millisleep (10);
|
||||
/* Determine the device speed. */
|
||||
if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED)
|
||||
speed = GRUB_USB_SPEED_LOW;
|
||||
else
|
||||
{
|
||||
if (status & GRUB_USB_HUB_STATUS_PORT_HIGHSPEED)
|
||||
speed = GRUB_USB_SPEED_HIGH;
|
||||
else
|
||||
speed = GRUB_USB_SPEED_FULL;
|
||||
}
|
||||
|
||||
/* Do reset of connection change bit */
|
||||
err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT
|
||||
| GRUB_USB_REQTYPE_CLASS
|
||||
| GRUB_USB_REQTYPE_TARGET_OTHER),
|
||||
GRUB_USB_REQ_CLEAR_FEATURE,
|
||||
GRUB_USB_HUB_FEATURE_C_CONNECTED,
|
||||
i, 0, 0);
|
||||
/* Just ignore the device if the Hub reports some error */
|
||||
if (err)
|
||||
continue;
|
||||
/* Wait a recovery time after reset, spec. says 10ms */
|
||||
grub_millisleep (10);
|
||||
|
||||
/* Add the device and assign a device address to it. */
|
||||
next_dev = grub_usb_hub_add_dev (&dev->controller, speed);
|
||||
if (! next_dev)
|
||||
continue;
|
||||
/* Add the device and assign a device address to it. */
|
||||
next_dev = grub_usb_hub_add_dev (&dev->controller, speed);
|
||||
dev->controller.dev->pending_reset = 0;
|
||||
if (! next_dev)
|
||||
continue;
|
||||
|
||||
attached_devices[i - 1] = next_dev;
|
||||
dev->children[i - 1] = next_dev;
|
||||
|
||||
/* If the device is a Hub, scan it for more devices. */
|
||||
if (next_dev->descdev.class == 0x09)
|
||||
grub_usb_add_hub (next_dev);
|
||||
/* If the device is a Hub, scan it for more devices. */
|
||||
if (next_dev->descdev.class == 0x09)
|
||||
grub_usb_add_hub (next_dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -476,12 +499,21 @@ grub_usb_poll_devices (void)
|
|||
/* No, it should be never changed, it should be constant. */
|
||||
for (i = 0; i < hub->nports; i++)
|
||||
{
|
||||
grub_usb_speed_t speed;
|
||||
grub_usb_speed_t speed = GRUB_USB_SPEED_NONE;
|
||||
int changed = 0;
|
||||
|
||||
speed = hub->controller->dev->detect_dev (hub->controller, i,
|
||||
&changed);
|
||||
|
||||
if (!hub->controller->dev->pending_reset)
|
||||
{
|
||||
/* Check for possible timeout */
|
||||
if (grub_get_time_ms () > hub->controller->dev->pending_reset)
|
||||
{
|
||||
/* Something went wrong, reset device was not
|
||||
* addressed properly, timeout happened */
|
||||
hub->controller->dev->pending_reset = 0;
|
||||
speed = hub->controller->dev->detect_dev (hub->controller,
|
||||
i, &changed);
|
||||
}
|
||||
}
|
||||
if (changed)
|
||||
{
|
||||
detach_device (hub->devices[i]);
|
||||
|
@ -492,13 +524,21 @@ grub_usb_poll_devices (void)
|
|||
}
|
||||
}
|
||||
|
||||
/* We should check changes of non-root hubs too. */
|
||||
for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++)
|
||||
while (1)
|
||||
{
|
||||
grub_usb_device_t dev = grub_usb_devs[i];
|
||||
|
||||
if (dev && dev->descdev.class == 0x09)
|
||||
poll_nonroot_hub (dev);
|
||||
rescan = 0;
|
||||
|
||||
/* We should check changes of non-root hubs too. */
|
||||
for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++)
|
||||
{
|
||||
grub_usb_device_t dev = grub_usb_devs[i];
|
||||
|
||||
if (dev && dev->descdev.class == 0x09)
|
||||
poll_nonroot_hub (dev);
|
||||
}
|
||||
if (!rescan)
|
||||
break;
|
||||
grub_millisleep (50);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,6 +23,41 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/usb.h>
|
||||
#include <grub/usbtrans.h>
|
||||
#include <grub/time.h>
|
||||
|
||||
static grub_usb_err_t
|
||||
grub_usb_execute_and_wait_transfer (grub_usb_device_t dev,
|
||||
grub_usb_transfer_t transfer,
|
||||
int timeout, grub_size_t *actual)
|
||||
{
|
||||
grub_usb_err_t err;
|
||||
grub_uint64_t endtime;
|
||||
|
||||
err = dev->controller.dev->setup_transfer (&dev->controller, transfer);
|
||||
if (err)
|
||||
return err;
|
||||
/* endtime moved behind setup transfer to prevent false timeouts
|
||||
* while debugging... */
|
||||
endtime = grub_get_time_ms () + timeout;
|
||||
while (1)
|
||||
{
|
||||
err = dev->controller.dev->check_transfer (&dev->controller, transfer,
|
||||
actual);
|
||||
if (!err)
|
||||
return GRUB_USB_ERR_NONE;
|
||||
if (err != GRUB_USB_ERR_WAIT)
|
||||
return err;
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
err = dev->controller.dev->cancel_transfer (&dev->controller,
|
||||
transfer);
|
||||
if (err)
|
||||
return err;
|
||||
return GRUB_USB_ERR_TIMEOUT;
|
||||
}
|
||||
grub_cpu_idle ();
|
||||
}
|
||||
}
|
||||
|
||||
grub_usb_err_t
|
||||
grub_usb_control_msg (grub_usb_device_t dev,
|
||||
|
@ -62,7 +97,7 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
|||
if (! transfer)
|
||||
{
|
||||
grub_dma_free (data_chunk);
|
||||
return grub_errno;
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
setupdata_chunk = grub_memalign_dma32 (32, sizeof (*setupdata));
|
||||
|
@ -70,7 +105,7 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
|||
{
|
||||
grub_free (transfer);
|
||||
grub_dma_free (data_chunk);
|
||||
return grub_errno;
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
setupdata = grub_dma_get_virt (setupdata_chunk);
|
||||
|
@ -104,7 +139,7 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
|||
grub_free (transfer);
|
||||
grub_dma_free (setupdata_chunk);
|
||||
grub_dma_free (data_chunk);
|
||||
return grub_errno;
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
/* Build a Setup packet. XXX: Endianness. */
|
||||
|
@ -147,8 +182,8 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
|||
|
||||
transfer->transactions[datablocks + 1].toggle = 1;
|
||||
|
||||
err = dev->controller.dev->transfer (&dev->controller, transfer,
|
||||
1000, &actual);
|
||||
err = grub_usb_execute_and_wait_transfer (dev, transfer, 1000, &actual);
|
||||
|
||||
grub_dprintf ("usb", "control: err=%d\n", err);
|
||||
|
||||
grub_free (transfer->transactions);
|
||||
|
@ -162,22 +197,20 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
|||
return err;
|
||||
}
|
||||
|
||||
static grub_usb_err_t
|
||||
grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||
int endpoint, grub_size_t size0, char *data_in,
|
||||
grub_transfer_type_t type, int timeout,
|
||||
grub_size_t *actual)
|
||||
static grub_usb_transfer_t
|
||||
grub_usb_bulk_setup_readwrite (grub_usb_device_t dev,
|
||||
int endpoint, grub_size_t size0, char *data_in,
|
||||
grub_transfer_type_t type)
|
||||
{
|
||||
int i;
|
||||
grub_usb_transfer_t transfer;
|
||||
int datablocks;
|
||||
unsigned int max;
|
||||
grub_usb_err_t err;
|
||||
int toggle = dev->toggle[endpoint];
|
||||
volatile char *data;
|
||||
grub_uint32_t data_addr;
|
||||
struct grub_pci_dma_chunk *data_chunk;
|
||||
grub_size_t size = size0;
|
||||
int toggle = dev->toggle[endpoint];
|
||||
|
||||
grub_dprintf ("usb", "bulk: size=0x%02lx type=%d\n", (unsigned long) size,
|
||||
type);
|
||||
|
@ -185,7 +218,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
|||
/* FIXME: avoid allocation any kind of buffer in a first place. */
|
||||
data_chunk = grub_memalign_dma32 (128, size);
|
||||
if (!data_chunk)
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
return NULL;
|
||||
data = grub_dma_get_virt (data_chunk);
|
||||
data_addr = grub_dma_get_phys (data_chunk);
|
||||
if (type == GRUB_USB_TRANSFER_TYPE_OUT)
|
||||
|
@ -195,7 +228,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
|||
if (dev->initialized)
|
||||
{
|
||||
struct grub_usb_desc_endp *endpdesc;
|
||||
endpdesc = grub_usb_get_endpdescriptor (dev, 0);
|
||||
endpdesc = grub_usb_get_endpdescriptor (dev, endpoint);
|
||||
|
||||
if (endpdesc)
|
||||
max = endpdesc->maxpacket;
|
||||
|
@ -210,18 +243,21 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
|||
if (! transfer)
|
||||
{
|
||||
grub_dma_free (data_chunk);
|
||||
return grub_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
datablocks = ((size + max - 1) / max);
|
||||
transfer->transcnt = datablocks;
|
||||
transfer->size = size - 1;
|
||||
transfer->endpoint = endpoint & 15;
|
||||
transfer->endpoint = endpoint;
|
||||
transfer->devaddr = dev->addr;
|
||||
transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK;
|
||||
transfer->dir = type;
|
||||
transfer->max = max;
|
||||
transfer->dev = dev;
|
||||
transfer->last_trans = -1; /* Reset index of last processed transaction (TD) */
|
||||
transfer->data_chunk = data_chunk;
|
||||
transfer->data = data_in;
|
||||
|
||||
/* Allocate an array of transfer data structures. */
|
||||
transfer->transactions = grub_malloc (transfer->transcnt
|
||||
|
@ -230,7 +266,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
|||
{
|
||||
grub_free (transfer);
|
||||
grub_dma_free (data_chunk);
|
||||
return grub_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set up all transfers. */
|
||||
|
@ -248,25 +284,51 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
|||
tr->preceding = i * max;
|
||||
size -= tr->size;
|
||||
}
|
||||
return transfer;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer)
|
||||
{
|
||||
grub_usb_device_t dev = transfer->dev;
|
||||
int toggle = dev->toggle[transfer->endpoint];
|
||||
|
||||
err = dev->controller.dev->transfer (&dev->controller, transfer, timeout,
|
||||
actual);
|
||||
/* We must remember proper toggle value even if some transactions
|
||||
* were not processed - correct value should be inversion of last
|
||||
* processed transaction (TD). */
|
||||
if (transfer->last_trans >= 0)
|
||||
toggle = transfer->transactions[transfer->last_trans].toggle ? 0 : 1;
|
||||
else
|
||||
toggle = dev->toggle[endpoint]; /* Nothing done, take original */
|
||||
grub_dprintf ("usb", "bulk: err=%d, toggle=%d\n", err, toggle);
|
||||
dev->toggle[endpoint] = toggle;
|
||||
toggle = dev->toggle[transfer->endpoint]; /* Nothing done, take original */
|
||||
grub_dprintf ("usb", "bulk: toggle=%d\n", toggle);
|
||||
dev->toggle[transfer->endpoint] = toggle;
|
||||
|
||||
if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN)
|
||||
grub_memcpy (transfer->data, (void *)
|
||||
grub_dma_get_virt (transfer->data_chunk),
|
||||
transfer->size + 1);
|
||||
|
||||
grub_free (transfer->transactions);
|
||||
grub_free (transfer);
|
||||
grub_dma_free (data_chunk);
|
||||
grub_dma_free (transfer->data_chunk);
|
||||
}
|
||||
|
||||
if (type == GRUB_USB_TRANSFER_TYPE_IN)
|
||||
grub_memcpy (data_in, (char *) data, size0);
|
||||
static grub_usb_err_t
|
||||
grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||
int endpoint, grub_size_t size0, char *data_in,
|
||||
grub_transfer_type_t type, int timeout,
|
||||
grub_size_t *actual)
|
||||
{
|
||||
grub_usb_err_t err;
|
||||
grub_usb_transfer_t transfer;
|
||||
|
||||
transfer = grub_usb_bulk_setup_readwrite (dev, endpoint, size0,
|
||||
data_in, type);
|
||||
if (!transfer)
|
||||
return GRUB_USB_ERR_INTERNAL;
|
||||
err = grub_usb_execute_and_wait_transfer (dev, transfer, timeout, actual);
|
||||
|
||||
grub_usb_bulk_finish_readwrite (transfer);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -298,6 +360,49 @@ grub_usb_bulk_read (grub_usb_device_t dev,
|
|||
return err;
|
||||
}
|
||||
|
||||
grub_usb_err_t
|
||||
grub_usb_check_transfer (grub_usb_transfer_t transfer, grub_size_t *actual)
|
||||
{
|
||||
grub_usb_err_t err;
|
||||
grub_usb_device_t dev = transfer->dev;
|
||||
|
||||
err = dev->controller.dev->check_transfer (&dev->controller, transfer,
|
||||
actual);
|
||||
if (err == GRUB_USB_ERR_WAIT)
|
||||
return err;
|
||||
|
||||
grub_usb_bulk_finish_readwrite (transfer);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
grub_usb_transfer_t
|
||||
grub_usb_bulk_read_background (grub_usb_device_t dev,
|
||||
int endpoint, grub_size_t size, void *data)
|
||||
{
|
||||
grub_usb_err_t err;
|
||||
grub_usb_transfer_t transfer;
|
||||
|
||||
transfer = grub_usb_bulk_setup_readwrite (dev, endpoint, size,
|
||||
data, GRUB_USB_TRANSFER_TYPE_IN);
|
||||
if (!transfer)
|
||||
return NULL;
|
||||
|
||||
err = dev->controller.dev->setup_transfer (&dev->controller, transfer);
|
||||
if (err)
|
||||
return NULL;
|
||||
|
||||
return transfer;
|
||||
}
|
||||
|
||||
void
|
||||
grub_usb_cancel_transfer (grub_usb_transfer_t transfer)
|
||||
{
|
||||
grub_usb_device_t dev = transfer->dev;
|
||||
dev->controller.dev->cancel_transfer (&dev->controller, transfer);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_usb_err_t
|
||||
grub_usb_bulk_read_extended (grub_usb_device_t dev,
|
||||
int endpoint, grub_size_t size, char *data,
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/acpi.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/memory.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
|
@ -34,6 +33,8 @@
|
|||
#include <grub/efi/api.h>
|
||||
#endif
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"exclude", 'x', 0,
|
||||
N_("Don't load host tables specified by comma-separated list."),
|
||||
|
@ -151,10 +152,10 @@ grub_acpi_create_ebda (void)
|
|||
auto int NESTED_FUNC_ATTR find_hook (grub_uint64_t, grub_uint64_t,
|
||||
grub_uint32_t);
|
||||
int NESTED_FUNC_ATTR find_hook (grub_uint64_t start, grub_uint64_t size,
|
||||
grub_uint32_t type)
|
||||
grub_memory_type_t type)
|
||||
{
|
||||
grub_uint64_t end = start + size;
|
||||
if (type != GRUB_MACHINE_MEMORY_AVAILABLE)
|
||||
if (type != GRUB_MEMORY_AVAILABLE)
|
||||
return 0;
|
||||
if (end > 0x100000)
|
||||
end = 0x100000;
|
||||
|
@ -180,7 +181,7 @@ grub_acpi_create_ebda (void)
|
|||
"couldn't find space for the new EBDA");
|
||||
|
||||
mmapregion = grub_mmap_register (PTR_TO_UINT64 (targetebda), ebda_len,
|
||||
GRUB_MACHINE_MEMORY_RESERVED);
|
||||
GRUB_MEMORY_RESERVED);
|
||||
if (! mmapregion)
|
||||
return grub_errno;
|
||||
|
||||
|
@ -704,7 +705,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
|
|||
|
||||
playground = playground_ptr
|
||||
= grub_mmap_malign_and_register (1, playground_size, &mmapregion,
|
||||
GRUB_MACHINE_MEMORY_ACPI, 0);
|
||||
GRUB_MEMORY_ACPI, 0);
|
||||
|
||||
if (! playground)
|
||||
{
|
||||
|
|
|
@ -16,9 +16,30 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef GRUB_DSDT_TEST
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define grub_dprintf(cond, args...) printf ( args )
|
||||
#define grub_printf printf
|
||||
typedef uint64_t grub_uint64_t;
|
||||
typedef uint32_t grub_uint32_t;
|
||||
typedef uint16_t grub_uint16_t;
|
||||
typedef uint8_t grub_uint8_t;
|
||||
|
||||
#endif
|
||||
|
||||
#include <grub/acpi.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
#ifndef GRUB_DSDT_TEST
|
||||
#include <grub/misc.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/cpu/io.h>
|
||||
#endif
|
||||
|
||||
static inline grub_uint32_t
|
||||
decode_length (const grub_uint8_t *ptr, int *numlen)
|
||||
|
@ -123,6 +144,7 @@ skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end)
|
|||
return 0;
|
||||
break;
|
||||
case GRUB_ACPI_EXTOPCODE_FIELD_OP:
|
||||
case GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP:
|
||||
ptr++;
|
||||
ptr += decode_length (ptr, 0);
|
||||
break;
|
||||
|
@ -136,7 +158,7 @@ skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end)
|
|||
static int
|
||||
get_sleep_type (grub_uint8_t *table, grub_uint8_t *end)
|
||||
{
|
||||
grub_uint8_t *ptr, *prev;
|
||||
grub_uint8_t *ptr, *prev = table;
|
||||
int sleep_type = -1;
|
||||
|
||||
ptr = table + sizeof (struct grub_acpi_table_header);
|
||||
|
@ -156,11 +178,12 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *end)
|
|||
break;
|
||||
case GRUB_ACPI_OPCODE_NAME:
|
||||
ptr++;
|
||||
if (memcmp (ptr, "_S5_", 4) == 0)
|
||||
if (memcmp (ptr, "_S5_", 4) == 0 || memcmp (ptr, "\\_S5_", 4) == 0)
|
||||
{
|
||||
int ll;
|
||||
grub_uint8_t *ptr2 = ptr;
|
||||
ptr2 += 4;
|
||||
grub_dprintf ("acpi", "S5 found\n");
|
||||
ptr2 += skip_name_string (ptr, end);
|
||||
if (*ptr2 != 0x12)
|
||||
{
|
||||
grub_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2);
|
||||
|
@ -208,6 +231,47 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *end)
|
|||
return sleep_type;
|
||||
}
|
||||
|
||||
#ifdef GRUB_DSDT_TEST
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
FILE *f;
|
||||
size_t len;
|
||||
unsigned char *buf;
|
||||
if (argc < 2)
|
||||
printf ("Usage: %s FILE\n", argv[0]);
|
||||
f = fopen (argv[1], "rb");
|
||||
if (!f)
|
||||
{
|
||||
printf ("Couldn't open file\n");
|
||||
return 1;
|
||||
}
|
||||
fseek (f, 0, SEEK_END);
|
||||
len = ftell (f);
|
||||
fseek (f, 0, SEEK_SET);
|
||||
buf = malloc (len);
|
||||
if (!buf)
|
||||
{
|
||||
printf ("Couldn't malloc buffer\n");
|
||||
fclose (f);
|
||||
return 2;
|
||||
}
|
||||
if (fread (buf, 1, len, f) != len)
|
||||
{
|
||||
printf ("Read failed\n");
|
||||
free (buf);
|
||||
fclose (f);
|
||||
return 2;
|
||||
}
|
||||
|
||||
printf ("Sleep type = %d\n", get_sleep_type (buf, buf + len));
|
||||
free (buf);
|
||||
fclose (f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
grub_acpi_halt (void)
|
||||
{
|
||||
|
@ -262,5 +326,8 @@ grub_acpi_halt (void)
|
|||
}
|
||||
}
|
||||
|
||||
grub_printf ("ACPI shutdown failed\n");
|
||||
grub_millisleep (1500);
|
||||
|
||||
grub_puts_ (N_("ACPI shutdown failed"));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/* pxe.c - command to control the pxe driver */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,35 +17,37 @@
|
|||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/machine/pxe.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/arc/arc.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_pxe_unload (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
grub_cmd_lsdev (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
if (! grub_pxe_pxenv)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no pxe environment");
|
||||
|
||||
grub_pxe_unload ();
|
||||
|
||||
auto int hook (const char *name, const struct grub_arc_component *comp);
|
||||
int hook (const char *name, const struct grub_arc_component *comp __attribute__ ((unused)))
|
||||
{
|
||||
grub_printf ("%s\n", name);
|
||||
return 0;
|
||||
}
|
||||
grub_arc_iterate_devs (hook, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(pxecmd)
|
||||
GRUB_MOD_INIT(lsdev)
|
||||
{
|
||||
cmd = grub_register_command ("pxe_unload", grub_cmd_pxe_unload,
|
||||
0,
|
||||
N_("Unload PXE environment."));
|
||||
cmd = grub_register_command ("lsdev", grub_cmd_lsdev, "",
|
||||
N_("List devices."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(pxecmd)
|
||||
GRUB_MOD_FINI(lsdev)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
|
@ -26,6 +26,8 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t (*grub_loader_boot_func) (void);
|
||||
static grub_err_t (*grub_loader_unload_func) (void);
|
||||
static int grub_loader_noreturn;
|
||||
|
|
58
grub-core/commands/cacheinfo.c
Normal file
58
grub-core/commands/cacheinfo.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* cacheinfo.c - disk cache statistics */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/disk.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char *argv[] __attribute__ ((unused)))
|
||||
{
|
||||
unsigned long hits, misses;
|
||||
|
||||
grub_disk_cache_get_performance (&hits, &misses);
|
||||
grub_printf_ (N_("Disk cache: hits = %lu, misses = %lu "), hits, misses);
|
||||
if (hits + misses)
|
||||
{
|
||||
unsigned long ratio = hits * 10000 / (hits + misses);
|
||||
grub_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100);
|
||||
}
|
||||
else
|
||||
grub_puts_ (N_("(N/A)"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_cacheinfo;
|
||||
|
||||
GRUB_MOD_INIT(cacheinfo)
|
||||
{
|
||||
cmd_cacheinfo =
|
||||
grub_register_command ("cacheinfo", grub_rescue_cmd_info,
|
||||
0, N_("Get disk cache info."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(cacheinfo)
|
||||
{
|
||||
grub_unregister_command (cmd_cacheinfo);
|
||||
}
|
|
@ -25,6 +25,8 @@
|
|||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"dos", -1, 0, N_("Accept DOS-style CR/NL line endings."), 0, 0},
|
||||
|
@ -76,7 +78,7 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
}
|
||||
|
||||
while (grub_checkkey () >= 0 &&
|
||||
(key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != GRUB_TERM_ESC)
|
||||
(key = grub_getkey ()) != GRUB_TERM_ESC)
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define BUFFER_SIZE 512
|
||||
|
||||
static grub_err_t
|
||||
|
@ -40,8 +42,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
|
|||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required");
|
||||
|
||||
grub_printf ("Compare file `%s' with `%s':\n", args[0],
|
||||
args[1]);
|
||||
grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0],
|
||||
args[1]);
|
||||
|
||||
file1 = grub_file_open (args[0]);
|
||||
file2 = grub_file_open (args[1]);
|
||||
|
@ -49,9 +51,9 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
|
|||
goto cleanup;
|
||||
|
||||
if (grub_file_size (file1) != grub_file_size (file2))
|
||||
grub_printf ("Files differ in size: %llu [%s], %llu [%s]\n",
|
||||
(unsigned long long) grub_file_size (file1), args[0],
|
||||
(unsigned long long) grub_file_size (file2), args[1]);
|
||||
grub_printf_ (N_("Files differ in size: %llu [%s], %llu [%s]\n"),
|
||||
(unsigned long long) grub_file_size (file1), args[0],
|
||||
(unsigned long long) grub_file_size (file2), args[1]);
|
||||
else
|
||||
{
|
||||
pos = 0;
|
||||
|
@ -76,9 +78,9 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
|
|||
{
|
||||
if (buf1[i] != buf2[i])
|
||||
{
|
||||
grub_printf ("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n",
|
||||
(unsigned long long) (i + pos), buf1[i], args[0],
|
||||
buf2[i], args[1]);
|
||||
grub_printf_ (N_("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n"),
|
||||
(unsigned long long) (i + pos), buf1[i],
|
||||
args[0], buf2[i], args[1]);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
@ -87,15 +89,14 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
|
|||
}
|
||||
while (rd2);
|
||||
|
||||
grub_printf ("The files are identical.\n");
|
||||
/* TRANSLATORS: it's always exactly 2 files. */
|
||||
grub_printf_ (N_("The files are identical.\n"));
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
if (buf1)
|
||||
grub_free (buf1);
|
||||
if (buf2)
|
||||
grub_free (buf2);
|
||||
grub_free (buf1);
|
||||
grub_free (buf2);
|
||||
if (file1)
|
||||
grub_file_close (file1);
|
||||
if (file2)
|
||||
|
|
|
@ -24,31 +24,39 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_source (grub_command_t cmd, int argc, char **args)
|
||||
{
|
||||
int new_env;
|
||||
int new_env, extractor;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
new_env = (cmd->name[0] == 'c');
|
||||
extractor = (cmd->name[0] == 'e');
|
||||
new_env = (cmd->name[extractor ? sizeof ("extract_entries_") - 1 : 0] == 'c');
|
||||
|
||||
if (new_env)
|
||||
{
|
||||
grub_cls ();
|
||||
grub_env_context_open (1);
|
||||
}
|
||||
grub_cls ();
|
||||
|
||||
if (new_env && !extractor)
|
||||
grub_env_context_open ();
|
||||
if (extractor)
|
||||
grub_env_extractor_open (!new_env);
|
||||
|
||||
grub_normal_execute (args[0], 1, ! new_env);
|
||||
|
||||
if (new_env)
|
||||
if (new_env && !extractor)
|
||||
grub_env_context_close ();
|
||||
if (extractor)
|
||||
grub_env_extractor_close (!new_env);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_configfile, cmd_source, cmd_dot;
|
||||
static grub_command_t cmd_extractor_source, cmd_extractor_configfile;
|
||||
|
||||
GRUB_MOD_INIT(configfile)
|
||||
{
|
||||
|
@ -60,6 +68,19 @@ GRUB_MOD_INIT(configfile)
|
|||
N_("FILE"),
|
||||
N_("Load another config file without changing context.")
|
||||
);
|
||||
|
||||
cmd_extractor_source =
|
||||
grub_register_command ("extract_entries_source", grub_cmd_source,
|
||||
N_("FILE"),
|
||||
N_("Load another config file without changing context but take only menuentries.")
|
||||
);
|
||||
|
||||
cmd_extractor_configfile =
|
||||
grub_register_command ("extract_entries_configfile", grub_cmd_source,
|
||||
N_("FILE"),
|
||||
N_("Load another config file without changing context but take only menuentries.")
|
||||
);
|
||||
|
||||
cmd_dot =
|
||||
grub_register_command (".", grub_cmd_source,
|
||||
N_("FILE"),
|
||||
|
@ -71,5 +92,7 @@ GRUB_MOD_FINI(configfile)
|
|||
{
|
||||
grub_unregister_command (cmd_configfile);
|
||||
grub_unregister_command (cmd_source);
|
||||
grub_unregister_command (cmd_extractor_configfile);
|
||||
grub_unregister_command (cmd_extractor_source);
|
||||
grub_unregister_command (cmd_dot);
|
||||
}
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
/* crc.c - command to calculate the crc32 checksum of a file */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008,2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/lib/crc.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_crc (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
|
||||
{
|
||||
grub_file_t file;
|
||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
||||
grub_ssize_t size;
|
||||
grub_uint32_t crc;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
grub_file_filter_disable_compression ();
|
||||
file = grub_file_open (args[0]);
|
||||
if (! file)
|
||||
return 0;
|
||||
|
||||
crc = 0;
|
||||
while ((size = grub_file_read (file, buf, sizeof (buf))) > 0)
|
||||
crc = grub_getcrc32 (crc, buf, size);
|
||||
|
||||
if (grub_errno)
|
||||
goto fail;
|
||||
|
||||
grub_printf ("%08x\n", crc);
|
||||
|
||||
fail:
|
||||
grub_file_close (file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(crc)
|
||||
{
|
||||
cmd = grub_register_command ("crc", grub_cmd_crc,
|
||||
N_("FILE"),
|
||||
N_("Calculate the crc32 checksum of a file."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(crc)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
|
@ -24,6 +24,8 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define GRUB_DATETIME_SET_YEAR 1
|
||||
#define GRUB_DATETIME_SET_MONTH 2
|
||||
#define GRUB_DATETIME_SET_DAY 4
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* echo.c - Command to display a line of text */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2006,2007 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2006,2007,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
|
||||
|
@ -21,6 +21,9 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/term.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
|
@ -43,8 +46,14 @@ grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
char *arg = *args;
|
||||
/* Unescaping results in a string no longer than the original. */
|
||||
char *unescaped = grub_malloc (grub_strlen (arg) + 1);
|
||||
char *p = unescaped;
|
||||
args++;
|
||||
|
||||
if (!unescaped)
|
||||
return grub_errno;
|
||||
|
||||
while (*arg)
|
||||
{
|
||||
/* In case `-e' is used, parse backslashes. */
|
||||
|
@ -57,11 +66,11 @@ grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
switch (*arg)
|
||||
{
|
||||
case '\\':
|
||||
grub_printf ("\\");
|
||||
*p++ = '\\';
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
grub_printf ("\a");
|
||||
*p++ = '\a';
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
|
@ -69,23 +78,23 @@ grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
break;
|
||||
|
||||
case 'f':
|
||||
grub_printf ("\f");
|
||||
*p++ = '\f';
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
grub_printf ("\n");
|
||||
*p++ = '\n';
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
grub_printf ("\r");
|
||||
*p++ = '\r';
|
||||
break;
|
||||
|
||||
case 't':
|
||||
grub_printf ("\t");
|
||||
*p++ = '\t';
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
grub_printf ("\v");
|
||||
*p++ = '\v';
|
||||
break;
|
||||
}
|
||||
arg++;
|
||||
|
@ -94,10 +103,14 @@ grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
|
||||
/* This was not an escaped character, or escaping is not
|
||||
enabled. */
|
||||
grub_printf ("%c", *arg);
|
||||
*p++ = *arg;
|
||||
arg++;
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
grub_xputs (unescaped);
|
||||
grub_free (unescaped);
|
||||
|
||||
/* If another argument follows, insert a space. */
|
||||
if (i != argc - 1)
|
||||
grub_printf (" " );
|
||||
|
@ -106,6 +119,8 @@ grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
if (newline)
|
||||
grub_printf ("\n");
|
||||
|
||||
grub_refresh ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static struct grub_video_patch
|
||||
{
|
||||
const char *name;
|
||||
|
@ -54,24 +56,24 @@ scan_card (grub_pci_device_t dev, grub_pci_id_t pciid)
|
|||
{
|
||||
grub_target_addr_t base;
|
||||
|
||||
grub_printf ("Found graphic card: %s\n", p->name);
|
||||
grub_dprintf ("fixvideo", "Found graphic card: %s\n", p->name);
|
||||
addr += 8 + p->mmio_bar * 4;
|
||||
base = grub_pci_read (addr);
|
||||
if ((! base) || (base & GRUB_PCI_ADDR_SPACE_IO) ||
|
||||
(base & GRUB_PCI_ADDR_MEM_PREFETCH))
|
||||
grub_printf ("Invalid MMIO bar %d\n", p->mmio_bar);
|
||||
grub_dprintf ("fixvideo", "Invalid MMIO bar %d\n", p->mmio_bar);
|
||||
else
|
||||
{
|
||||
base &= GRUB_PCI_ADDR_MEM_MASK;
|
||||
base += p->mmio_reg;
|
||||
|
||||
if (*((volatile grub_uint32_t *) base) != p->mmio_old)
|
||||
grub_printf ("Old value don't match\n");
|
||||
grub_dprintf ("fixvideo", "Old value doesn't match\n");
|
||||
else
|
||||
{
|
||||
*((volatile grub_uint32_t *) base) = 0;
|
||||
if (*((volatile grub_uint32_t *) base))
|
||||
grub_printf ("Set MMIO fails\n");
|
||||
grub_dprintf ("fixvideo", "Setting MMIO fails\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +82,7 @@ scan_card (grub_pci_device_t dev, grub_pci_id_t pciid)
|
|||
p++;
|
||||
}
|
||||
|
||||
grub_printf ("Unknown graphic card: %x\n", pciid);
|
||||
grub_dprintf ("fixvideo", "Unknown graphic card: %x\n", pciid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID;
|
||||
static grub_efi_guid_t acpi2_guid = GRUB_EFI_ACPI_20_TABLE_GUID;
|
||||
static grub_efi_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID;
|
||||
|
@ -47,7 +49,7 @@ enable_rom_area (void)
|
|||
rom_ptr = (grub_uint32_t *) VBIOS_ADDR;
|
||||
if (*rom_ptr != BLANK_MEM)
|
||||
{
|
||||
grub_printf ("ROM image is present.\n");
|
||||
grub_puts_ (N_("ROM image is present."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -65,7 +67,7 @@ enable_rom_area (void)
|
|||
*rom_ptr = 0;
|
||||
if (*rom_ptr != 0)
|
||||
{
|
||||
grub_printf ("Can\'t enable ROM area.\n");
|
||||
grub_puts_ (N_("Can\'t enable ROM area."));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -207,7 +209,7 @@ GRUB_MOD_INIT(loadbios)
|
|||
0, N_("Fake BIOS."));
|
||||
|
||||
cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios,
|
||||
"BIOS_DUMP [INT10_DUMP]",
|
||||
N_("BIOS_DUMP [INT10_DUMP]"),
|
||||
N_("Load BIOS dump."));
|
||||
}
|
||||
|
||||
|
|
145
grub-core/commands/efi/lsefimmap.c
Normal file
145
grub-core/commands/efi/lsefimmap.c
Normal file
|
@ -0,0 +1,145 @@
|
|||
/* lsefimemmap.c - Display memory map. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 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/types.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/efi/api.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/command.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define ADD_MEMORY_DESCRIPTOR(desc, size) \
|
||||
((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
grub_efi_uintn_t map_size;
|
||||
grub_efi_memory_descriptor_t *memory_map;
|
||||
grub_efi_memory_descriptor_t *memory_map_end;
|
||||
grub_efi_memory_descriptor_t *desc;
|
||||
grub_efi_uintn_t desc_size;
|
||||
|
||||
map_size = 0;
|
||||
if (grub_efi_get_memory_map (&map_size, NULL, NULL, &desc_size, 0) < 0)
|
||||
return 0;
|
||||
|
||||
memory_map = grub_malloc (map_size);
|
||||
if (memory_map == NULL)
|
||||
return grub_errno;
|
||||
if (grub_efi_get_memory_map (&map_size, memory_map, NULL, &desc_size, 0) <= 0)
|
||||
goto fail;
|
||||
|
||||
grub_printf
|
||||
("Type Physical start - end #Pages "
|
||||
" Size Attributes\n");
|
||||
memory_map_end = ADD_MEMORY_DESCRIPTOR (memory_map, map_size);
|
||||
for (desc = memory_map;
|
||||
desc < memory_map_end;
|
||||
desc = ADD_MEMORY_DESCRIPTOR (desc, desc_size))
|
||||
{
|
||||
grub_efi_uint64_t size;
|
||||
grub_efi_uint64_t attr;
|
||||
static const char types_str[][9] =
|
||||
{
|
||||
"reserved",
|
||||
"ldr-code",
|
||||
"ldr-data",
|
||||
"BS-code ",
|
||||
"BS-data ",
|
||||
"RT-code ",
|
||||
"RT-data ",
|
||||
"conv-mem",
|
||||
"unusable",
|
||||
"ACPI-rec",
|
||||
"ACPI-nvs",
|
||||
"MMIO ",
|
||||
"IO-ports",
|
||||
"PAL-code"
|
||||
};
|
||||
if (desc->type < ARRAY_SIZE (types_str))
|
||||
grub_printf ("%s ", types_str[desc->type]);
|
||||
else
|
||||
grub_printf ("Unk %02x ", desc->type);
|
||||
|
||||
grub_printf (" %016" PRIxGRUB_UINT64_T "-%016" PRIxGRUB_UINT64_T
|
||||
" %08" PRIxGRUB_UINT64_T,
|
||||
desc->physical_start,
|
||||
desc->physical_start + (desc->num_pages << 12) - 1,
|
||||
desc->num_pages);
|
||||
|
||||
size = desc->num_pages;
|
||||
size <<= (12 - 10);
|
||||
if (size < 1024)
|
||||
grub_printf (" %4" PRIuGRUB_UINT64_T "KB", size);
|
||||
else
|
||||
{
|
||||
size /= 1024;
|
||||
if (size < 1024)
|
||||
grub_printf (" %4" PRIuGRUB_UINT64_T "MB", size);
|
||||
else
|
||||
{
|
||||
size /= 1024;
|
||||
grub_printf (" %4" PRIuGRUB_UINT64_T "GB", size);
|
||||
}
|
||||
}
|
||||
|
||||
attr = desc->attribute;
|
||||
if (attr & GRUB_EFI_MEMORY_RUNTIME)
|
||||
grub_printf (" RT");
|
||||
if (attr & GRUB_EFI_MEMORY_UC)
|
||||
grub_printf (" UC");
|
||||
if (attr & GRUB_EFI_MEMORY_WC)
|
||||
grub_printf (" WC");
|
||||
if (attr & GRUB_EFI_MEMORY_WT)
|
||||
grub_printf (" WT");
|
||||
if (attr & GRUB_EFI_MEMORY_WB)
|
||||
grub_printf (" WB");
|
||||
if (attr & GRUB_EFI_MEMORY_UCE)
|
||||
grub_printf (" UCE");
|
||||
if (attr & GRUB_EFI_MEMORY_WP)
|
||||
grub_printf (" WP");
|
||||
if (attr & GRUB_EFI_MEMORY_RP)
|
||||
grub_printf (" RP");
|
||||
if (attr & GRUB_EFI_MEMORY_XP)
|
||||
grub_printf (" XP");
|
||||
|
||||
grub_printf ("\n");
|
||||
}
|
||||
|
||||
fail:
|
||||
grub_free (memory_map);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(lsefimmap)
|
||||
{
|
||||
cmd = grub_register_command ("lsefimmap", grub_cmd_lsefimmap,
|
||||
"", "Display EFI memory map.");
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(lsefimmap)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* systab.c - Display EFI systab. */
|
||||
/* lsefisystab.c - Display EFI systab. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
@ -18,12 +18,15 @@
|
|||
*/
|
||||
#include <grub/types.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/charset.h>
|
||||
#include <grub/efi/api.h>
|
||||
#include <grub/efi/efi.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
struct guid_mapping
|
||||
{
|
||||
grub_efi_guid_t guid;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* systab.c - Display EFI systab. */
|
||||
/* lssal.c - Display EFI SAL systab. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
|
@ -23,6 +23,9 @@
|
|||
#include <grub/charset.h>
|
||||
#include <grub/efi/api.h>
|
||||
#include <grub/efi/efi.h>
|
||||
#include <grub/dl.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static void
|
||||
disp_sal (void *table)
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/script_sh.h>
|
||||
#include <grub/dl.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
grub_err_t
|
||||
grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args,
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include <grub/fs.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/* Convert a LBA address to a CHS address in the INT 13 format. */
|
||||
/* Taken from grub1. */
|
||||
/* XXX: use hardcoded geometry of C = 1024, H = 255, S = 63.
|
||||
|
@ -229,7 +231,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)),
|
|||
return grub_errno;
|
||||
}
|
||||
|
||||
grub_printf ("New MBR is written to '%s'\n", args[0]);
|
||||
grub_printf_ (N_("New MBR is written to '%s'\n"), args[0]);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <grub/normal.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
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},
|
||||
|
@ -36,11 +38,13 @@ static const struct grub_arg_option options[] = {
|
|||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
struct { const char *name; const char *hashname; } aliases[] =
|
||||
static struct { const char *name; const char *hashname; } aliases[] =
|
||||
{
|
||||
{"sha256sum", "sha256"},
|
||||
{"sha512sum", "sha512"},
|
||||
{"sha1sum", "sha1"},
|
||||
{"md5sum", "md5"},
|
||||
{"crc", "crc32"},
|
||||
};
|
||||
|
||||
static inline int
|
||||
|
@ -137,7 +141,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
|
|||
grub_file_close (file);
|
||||
if (err)
|
||||
{
|
||||
grub_printf ("%s: READ ERROR\n", p);
|
||||
grub_printf_ (N_("%s: READ ERROR\n"), p);
|
||||
if (!keep)
|
||||
{
|
||||
grub_file_close (hashlist);
|
||||
|
@ -151,7 +155,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
|
|||
}
|
||||
if (grub_crypto_memcmp (expected, actual, hash->mdlen) != 0)
|
||||
{
|
||||
grub_printf ("%s: HASH MISMATCH\n", p);
|
||||
grub_printf_ (N_("%s: HASH MISMATCH\n"), p);
|
||||
if (!keep)
|
||||
{
|
||||
grub_file_close (hashlist);
|
||||
|
@ -162,7 +166,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
|
|||
mismatch++;
|
||||
continue;
|
||||
}
|
||||
grub_printf ("%s: OK\n", p);
|
||||
grub_printf_ (N_("%s: OK\n"), p);
|
||||
}
|
||||
if (mismatch || unread)
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE,
|
||||
|
@ -248,36 +252,49 @@ grub_cmd_hashsum (struct grub_extcmd_context *ctxt,
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd, cmd_md5, cmd_sha256, cmd_sha512;
|
||||
static grub_extcmd_t cmd, cmd_md5, cmd_sha1, cmd_sha256, cmd_sha512, cmd_crc;
|
||||
|
||||
GRUB_MOD_INIT(hashsum)
|
||||
{
|
||||
cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0,
|
||||
"hashsum -h HASH [-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]",
|
||||
"Compute or check hash checksum.",
|
||||
N_("-h HASH [-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, 0,
|
||||
N_("[-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
cmd_sha1 = grub_register_extcmd ("sha1sum", grub_cmd_hashsum, 0,
|
||||
N_("[-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
cmd_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum, 0,
|
||||
N_("[-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
"Compute or check hash checksum.",
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
cmd_sha512 = grub_register_extcmd ("sha512sum", grub_cmd_hashsum, 0,
|
||||
N_("[-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
|
||||
cmd_crc = grub_register_extcmd ("crc", grub_cmd_hashsum, 0,
|
||||
N_("[-c FILE [-p PREFIX]] "
|
||||
"[FILE1 [FILE2 ...]]"),
|
||||
N_("Compute or check hash checksum."),
|
||||
options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(hashsum)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
grub_unregister_extcmd (cmd_md5);
|
||||
grub_unregister_extcmd (cmd_sha1);
|
||||
grub_unregister_extcmd (cmd_sha256);
|
||||
grub_unregister_extcmd (cmd_sha512);
|
||||
grub_unregister_extcmd (cmd_crc);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <grub/ata.h>
|
||||
#include <grub/scsi.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
|
@ -26,6 +27,8 @@
|
|||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"apm", 'B', 0, N_("Set Advanced Power Management\n"
|
||||
"(1=low, ..., 254=high, 255=off)."),
|
||||
|
@ -61,60 +64,64 @@ enum grub_ata_smart_commands
|
|||
static int quiet = 0;
|
||||
|
||||
static grub_err_t
|
||||
grub_hdparm_do_ata_cmd (grub_disk_t disk, grub_uint8_t cmd,
|
||||
grub_hdparm_do_ata_cmd (grub_ata_t ata, grub_uint8_t cmd,
|
||||
grub_uint8_t features, grub_uint8_t sectors,
|
||||
void * buffer, int size)
|
||||
{
|
||||
struct grub_disk_ata_pass_through_parms apt;
|
||||
grub_memset (&apt, 0, sizeof (apt));
|
||||
|
||||
apt.taskfile[GRUB_ATA_REG_CMD] = cmd;
|
||||
apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
|
||||
apt.taskfile[GRUB_ATA_REG_SECTORS] = sectors;
|
||||
apt.taskfile.cmd = cmd;
|
||||
apt.taskfile.features = features;
|
||||
apt.taskfile.sectors = sectors;
|
||||
apt.taskfile.disk = 0xE0;
|
||||
|
||||
apt.buffer = buffer;
|
||||
apt.size = size;
|
||||
|
||||
if (grub_disk_ata_pass_through (disk, &apt))
|
||||
if (ata->dev->readwrite (ata, &apt, 0))
|
||||
return grub_errno;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_hdparm_do_check_powermode_cmd (grub_disk_t disk)
|
||||
grub_hdparm_do_check_powermode_cmd (grub_ata_t ata)
|
||||
{
|
||||
struct grub_disk_ata_pass_through_parms apt;
|
||||
grub_memset (&apt, 0, sizeof (apt));
|
||||
|
||||
apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_CHECK_POWER_MODE;
|
||||
apt.taskfile.cmd = GRUB_ATA_CMD_CHECK_POWER_MODE;
|
||||
apt.taskfile.disk = 0xE0;
|
||||
|
||||
if (grub_disk_ata_pass_through (disk, &apt))
|
||||
if (ata->dev->readwrite (ata, &apt, 0))
|
||||
return -1;
|
||||
|
||||
return apt.taskfile[GRUB_ATA_REG_SECTORS];
|
||||
return apt.taskfile.sectors;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features)
|
||||
grub_hdparm_do_smart_cmd (grub_ata_t ata, grub_uint8_t features)
|
||||
{
|
||||
struct grub_disk_ata_pass_through_parms apt;
|
||||
grub_memset (&apt, 0, sizeof (apt));
|
||||
|
||||
apt.taskfile[GRUB_ATA_REG_CMD] = GRUB_ATA_CMD_SMART;
|
||||
apt.taskfile[GRUB_ATA_REG_FEATURES] = features;
|
||||
apt.taskfile[GRUB_ATA_REG_LBAMID] = 0x4f;
|
||||
apt.taskfile[GRUB_ATA_REG_LBAHIGH] = 0xc2;
|
||||
apt.taskfile.cmd = GRUB_ATA_CMD_SMART;
|
||||
apt.taskfile.features = features;
|
||||
apt.taskfile.lba_mid = 0x4f;
|
||||
apt.taskfile.lba_high = 0xc2;
|
||||
apt.taskfile.disk = 0xE0;
|
||||
|
||||
if (grub_disk_ata_pass_through (disk, &apt))
|
||||
if (ata->dev->readwrite (ata, &apt, 0))
|
||||
return -1;
|
||||
|
||||
if (features == GRUB_ATA_FEAT_SMART_STATUS)
|
||||
{
|
||||
if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0x4f
|
||||
&& apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0xc2)
|
||||
if ( apt.taskfile.lba_mid == 0x4f
|
||||
&& apt.taskfile.lba_high == 0xc2)
|
||||
return 0; /* Good SMART status. */
|
||||
else if ( apt.taskfile[GRUB_ATA_REG_LBAMID] == 0xf4
|
||||
&& apt.taskfile[GRUB_ATA_REG_LBAHIGH] == 0x2c)
|
||||
else if ( apt.taskfile.lba_mid == 0xf4
|
||||
&& apt.taskfile.lba_high == 0x2c)
|
||||
return 1; /* Bad SMART status. */
|
||||
else
|
||||
return -1;
|
||||
|
@ -124,12 +131,12 @@ grub_hdparm_do_smart_cmd (grub_disk_t disk, grub_uint8_t features)
|
|||
|
||||
static grub_err_t
|
||||
grub_hdparm_simple_cmd (const char * msg,
|
||||
grub_disk_t disk, grub_uint8_t cmd)
|
||||
grub_ata_t ata, grub_uint8_t cmd)
|
||||
{
|
||||
if (! quiet && msg)
|
||||
grub_printf ("%s", msg);
|
||||
|
||||
grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, 0, 0, NULL, 0);
|
||||
grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, 0, 0, NULL, 0);
|
||||
|
||||
if (! quiet && msg)
|
||||
grub_printf ("%s\n", ! err ? "" : ": not supported");
|
||||
|
@ -138,7 +145,7 @@ grub_hdparm_simple_cmd (const char * msg,
|
|||
|
||||
static grub_err_t
|
||||
grub_hdparm_set_val_cmd (const char * msg, int val,
|
||||
grub_disk_t disk, grub_uint8_t cmd,
|
||||
grub_ata_t ata, grub_uint8_t cmd,
|
||||
grub_uint8_t features, grub_uint8_t sectors)
|
||||
{
|
||||
if (! quiet && msg && *msg)
|
||||
|
@ -149,7 +156,7 @@ grub_hdparm_set_val_cmd (const char * msg, int val,
|
|||
grub_printf ("Disable %s", msg);
|
||||
}
|
||||
|
||||
grub_err_t err = grub_hdparm_do_ata_cmd (disk, cmd, features, sectors,
|
||||
grub_err_t err = grub_hdparm_do_ata_cmd (ata, cmd, features, sectors,
|
||||
NULL, 0);
|
||||
|
||||
if (! quiet && msg)
|
||||
|
@ -273,6 +280,7 @@ static grub_err_t
|
|||
grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
struct grub_ata *ata;
|
||||
|
||||
/* Check command line. */
|
||||
if (argc != 1)
|
||||
|
@ -283,9 +291,6 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
|||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "argument is not a device name");
|
||||
args[0][len - 1] = 0;
|
||||
|
||||
if (! grub_disk_ata_pass_through)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "ATA pass through not available");
|
||||
|
||||
int i = 0;
|
||||
int apm = get_int_arg (&state[i++]);
|
||||
int power = state[i++].set;
|
||||
|
@ -311,15 +316,37 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
|||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "partition not allowed");
|
||||
}
|
||||
|
||||
switch (disk->dev->id)
|
||||
{
|
||||
case GRUB_DISK_DEVICE_ATA_ID:
|
||||
ata = disk->data;
|
||||
break;
|
||||
case GRUB_DISK_DEVICE_SCSI_ID:
|
||||
if (((disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF)
|
||||
== GRUB_SCSI_SUBSYSTEM_PATA
|
||||
|| (((disk->id >> GRUB_SCSI_ID_SUBSYSTEM_SHIFT) & 0xFF)
|
||||
== GRUB_SCSI_SUBSYSTEM_AHCI))
|
||||
{
|
||||
ata = ((struct grub_scsi *) disk->data)->data;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return grub_error (GRUB_ERR_IO, "not an ATA device");
|
||||
}
|
||||
|
||||
|
||||
/* Change settings. */
|
||||
if (aam >= 0)
|
||||
grub_hdparm_set_val_cmd ("Automatic Acoustic Management", (aam ? aam : -1),
|
||||
disk, GRUB_ATA_CMD_SET_FEATURES, (aam ? 0x42 : 0xc2), aam);
|
||||
ata, GRUB_ATA_CMD_SET_FEATURES,
|
||||
(aam ? 0x42 : 0xc2), aam);
|
||||
|
||||
if (apm >= 0)
|
||||
grub_hdparm_set_val_cmd ("Advanced Power Management",
|
||||
(apm != 255 ? apm : -1), disk, GRUB_ATA_CMD_SET_FEATURES,
|
||||
(apm != 255 ? 0x05 : 0x85), (apm != 255 ? apm : 0));
|
||||
(apm != 255 ? apm : -1), ata,
|
||||
GRUB_ATA_CMD_SET_FEATURES,
|
||||
(apm != 255 ? 0x05 : 0x85),
|
||||
(apm != 255 ? apm : 0));
|
||||
|
||||
if (standby_tout >= 0)
|
||||
{
|
||||
|
@ -330,28 +357,28 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
|||
grub_printf (")");
|
||||
}
|
||||
/* The IDLE cmd sets disk to idle mode and configures standby timer. */
|
||||
grub_hdparm_set_val_cmd ("", -1, disk, GRUB_ATA_CMD_IDLE, 0, standby_tout);
|
||||
grub_hdparm_set_val_cmd ("", -1, ata, GRUB_ATA_CMD_IDLE, 0, standby_tout);
|
||||
}
|
||||
|
||||
if (enable_smart >= 0)
|
||||
{
|
||||
if (! quiet)
|
||||
grub_printf ("%sable SMART operations", (enable_smart ? "En" : "Dis"));
|
||||
int err = grub_hdparm_do_smart_cmd (disk, (enable_smart ?
|
||||
int err = grub_hdparm_do_smart_cmd (ata, (enable_smart ?
|
||||
GRUB_ATA_FEAT_SMART_ENABLE : GRUB_ATA_FEAT_SMART_DISABLE));
|
||||
if (! quiet)
|
||||
grub_printf ("%s\n", err ? ": not supported" : "");
|
||||
}
|
||||
|
||||
if (sec_freeze)
|
||||
grub_hdparm_simple_cmd ("Freeze security settings", disk,
|
||||
grub_hdparm_simple_cmd ("Freeze security settings", ata,
|
||||
GRUB_ATA_CMD_SECURITY_FREEZE_LOCK);
|
||||
|
||||
/* Print/dump IDENTIFY. */
|
||||
if (ident || dumpid)
|
||||
{
|
||||
char buf[GRUB_DISK_SECTOR_SIZE];
|
||||
if (grub_hdparm_do_ata_cmd (disk, GRUB_ATA_CMD_IDENTIFY_DEVICE,
|
||||
if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE,
|
||||
0, 0, buf, sizeof (buf)))
|
||||
grub_printf ("Cannot read ATA IDENTIFY data\n");
|
||||
else
|
||||
|
@ -367,7 +394,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
|||
if (power)
|
||||
{
|
||||
grub_printf ("Disk power mode is: ");
|
||||
int mode = grub_hdparm_do_check_powermode_cmd (disk);
|
||||
int mode = grub_hdparm_do_check_powermode_cmd (ata);
|
||||
if (mode < 0)
|
||||
grub_printf ("unknown\n");
|
||||
else
|
||||
|
@ -383,7 +410,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
|||
{
|
||||
if (! quiet)
|
||||
grub_printf ("SMART status is: ");
|
||||
int err = grub_hdparm_do_smart_cmd (disk, GRUB_ATA_FEAT_SMART_STATUS);
|
||||
int err = grub_hdparm_do_smart_cmd (ata, GRUB_ATA_FEAT_SMART_STATUS);
|
||||
if (! quiet)
|
||||
grub_printf ("%s\n", (err < 0 ? "unknown" :
|
||||
err == 0 ? "OK" : "*BAD*"));
|
||||
|
@ -392,11 +419,11 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
|
|||
|
||||
/* Change power mode. */
|
||||
if (standby_now)
|
||||
grub_hdparm_simple_cmd ("Set disk to standby mode", disk,
|
||||
grub_hdparm_simple_cmd ("Set disk to standby mode", ata,
|
||||
GRUB_ATA_CMD_STANDBY_IMMEDIATE);
|
||||
|
||||
if (sleep_now)
|
||||
grub_hdparm_simple_cmd ("Set disk to sleep mode", disk,
|
||||
grub_hdparm_simple_cmd ("Set disk to sleep mode", ata,
|
||||
GRUB_ATA_CMD_SLEEP);
|
||||
|
||||
grub_disk_close (disk);
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <grub/normal.h>
|
||||
#include <grub/charset.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc,
|
||||
char **args)
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] = {
|
||||
{"skip", 's', 0, N_("Skip offset bytes from the beginning of file."), 0,
|
||||
ARG_TYPE_INT},
|
||||
|
|
|
@ -20,40 +20,82 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/cmos.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
parse_args (int argc, char *argv[], int *byte, int *bit)
|
||||
{
|
||||
char *rest;
|
||||
|
||||
if (argc != 1)
|
||||
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.");
|
||||
|
||||
*bit = grub_strtoul (rest + 1, 0, 0);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int byte, bit;
|
||||
char *rest;
|
||||
grub_err_t err;
|
||||
grub_uint8_t value;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required.");
|
||||
err = parse_args (argc, argv, &byte, &bit);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
byte = grub_strtoul (argv[0], &rest, 0);
|
||||
if (*rest != ':')
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required.");
|
||||
err = grub_cmos_read (byte, &value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
bit = grub_strtoul (rest + 1, 0, 0);
|
||||
|
||||
if (grub_cmos_read (byte) & (1 << bit))
|
||||
if (value & (1 << bit))
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
static grub_err_t
|
||||
grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
int byte, bit;
|
||||
grub_err_t err;
|
||||
grub_uint8_t value;
|
||||
|
||||
err = parse_args (argc, argv, &byte, &bit);
|
||||
if (err)
|
||||
return err;
|
||||
err = grub_cmos_read (byte, &value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return grub_cmos_write (byte, value & (~(1 << bit)));
|
||||
}
|
||||
|
||||
static grub_command_t cmd, cmd_clean;
|
||||
|
||||
|
||||
GRUB_MOD_INIT(cmostest)
|
||||
{
|
||||
cmd = grub_register_command ("cmostest", grub_cmd_cmostest,
|
||||
"cmostest BYTE:BIT",
|
||||
"Test bit at BYTE:BIT in CMOS.");
|
||||
N_("BYTE:BIT"),
|
||||
N_("Test bit at BYTE:BIT in CMOS."));
|
||||
cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean,
|
||||
N_("BYTE:BIT"),
|
||||
N_("Clean bit at BYTE:BIT in CMOS."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(cmostest)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
grub_unregister_command (cmd_clean);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <grub/i386/cpuid.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define cpuid(num,a,b,c,d) \
|
||||
asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
|
||||
: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
|
||||
|
|
|
@ -24,10 +24,12 @@
|
|||
#include <grub/disk.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/machine/memory.h>
|
||||
#include <grub/machine/biosnum.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/memory.h>
|
||||
#include <grub/machine/memory.h>
|
||||
|
||||
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);
|
||||
|
@ -176,11 +178,11 @@ list_mappings (void)
|
|||
/* Show: list mappings. */
|
||||
if (! map_head)
|
||||
{
|
||||
grub_printf ("No drives have been remapped\n");
|
||||
grub_puts_ (N_("No drives have been remapped"));
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_printf ("OS disk #num ------> GRUB/BIOS device\n");
|
||||
grub_puts_ (N_("OS disk #num ------> GRUB/BIOS device"));
|
||||
drivemap_node_t *curnode = map_head;
|
||||
while (curnode)
|
||||
{
|
||||
|
@ -306,7 +308,7 @@ install_int13_handler (int noret __attribute__ ((unused)))
|
|||
grub_dprintf ("drivemap", "Payload is %u bytes long\n", total_size);
|
||||
handler_base = grub_mmap_malign_and_register (16, total_size,
|
||||
&drivemap_mmap,
|
||||
GRUB_MACHINE_MEMORY_RESERVED,
|
||||
GRUB_MEMORY_RESERVED,
|
||||
GRUB_MMAP_MALLOC_LOW);
|
||||
if (! handler_base)
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't reserve "
|
||||
|
@ -361,7 +363,7 @@ uninstall_int13_handler (void)
|
|||
static int
|
||||
grub_get_root_biosnumber_drivemap (void)
|
||||
{
|
||||
char *biosnum;
|
||||
const char *biosnum;
|
||||
int ret = -1;
|
||||
grub_device_t dev;
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <grub/machine/int.h>
|
||||
#include <grub/acpi.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"no-apm", 'n', 0, N_("Do not use APM to halt the computer."), 0, 0},
|
||||
|
|
115
grub-core/commands/i386/pc/lsapm.c
Normal file
115
grub-core/commands/i386/pc/lsapm.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 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/machine/int.h>
|
||||
#include <grub/machine/apm.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
int
|
||||
grub_apm_get_info (struct grub_apm_info *info)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
|
||||
/* detect APM */
|
||||
regs.eax = 0x5300;
|
||||
regs.ebx = 0;
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
grub_bios_interrupt (0x15, ®s);
|
||||
|
||||
if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
|
||||
return 0;
|
||||
info->version = regs.eax & 0xffff;
|
||||
info->flags = regs.ecx & 0xffff;
|
||||
|
||||
/* disconnect APM first */
|
||||
regs.eax = 0x5304;
|
||||
regs.ebx = 0;
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
grub_bios_interrupt (0x15, ®s);
|
||||
|
||||
/* connect APM */
|
||||
regs.eax = 0x5303;
|
||||
regs.ebx = 0;
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
grub_bios_interrupt (0x15, ®s);
|
||||
|
||||
if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
|
||||
return 0;
|
||||
|
||||
info->cseg = regs.eax & 0xffff;
|
||||
info->offset = regs.ebx;
|
||||
info->cseg_16 = regs.ecx & 0xffff;
|
||||
info->dseg = regs.edx & 0xffff;
|
||||
info->cseg_len = regs.esi >> 16;
|
||||
info->cseg_16_len = regs.esi & 0xffff;
|
||||
info->dseg_len = regs.edi;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_lsapm (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)), char **args __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_apm_info info;
|
||||
if (!grub_apm_get_info (&info))
|
||||
return grub_error (GRUB_ERR_IO, "no APM found");
|
||||
|
||||
grub_printf_ (N_("Vesion %u.%u\n"
|
||||
"32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n"
|
||||
"16-bit CS = 0x%x, len = 0x%x\n"
|
||||
"DS = 0x%x, len = 0x%x\n"),
|
||||
info.version >> 8, info.version & 0xff,
|
||||
info.cseg, info.cseg_len, info.offset,
|
||||
info.cseg_16, info.cseg_16_len,
|
||||
info.dseg, info.dseg_len);
|
||||
grub_xputs (info.flags & GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED
|
||||
? _("16-bit protected interface supported\n")
|
||||
: _("16-bit protected interface unsupported\n"));
|
||||
grub_xputs (info.flags & GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED
|
||||
? _("32-bit protected interface supported\n")
|
||||
: _("32-bit protected interface unsupported\n"));
|
||||
grub_xputs (info.flags & GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN
|
||||
? _("CPU Idle slows down processor\n")
|
||||
: _("CPU Idle doesn't slow down processor\n"));
|
||||
grub_xputs (info.flags & GRUB_APM_FLAGS_DISABLED
|
||||
? _("APM disabled\n") : _("APM enabled\n"));
|
||||
grub_xputs (info.flags & GRUB_APM_FLAGS_DISENGAGED
|
||||
? _("APM disengaged\n") : _("APM engaged\n"));
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(lsapm)
|
||||
{
|
||||
cmd = grub_register_command ("lsapm", grub_cmd_lsapm, 0,
|
||||
N_("Show APM information."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(lsapm)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
||||
|
||||
|
|
@ -29,6 +29,8 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define BASE_TEMPO (60 * GRUB_TICKS_PER_SECOND)
|
||||
|
||||
/* The speaker port. */
|
||||
|
@ -190,7 +192,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
|
|||
file = grub_file_open (args[0]);
|
||||
|
||||
if (! file)
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]);
|
||||
|
||||
if (grub_file_read (file, &tempo, sizeof (tempo)) != sizeof (tempo))
|
||||
{
|
||||
|
@ -225,7 +227,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
if (*end)
|
||||
/* Was not a number either, assume it was supposed to be a file name. */
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
|
||||
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]);
|
||||
|
||||
grub_dprintf ("play","tempo = %d\n", tempo);
|
||||
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#include <grub/extcmd.h>
|
||||
#include <grub/cpu/io.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv2+");
|
||||
|
||||
static char sendkey[0x20];
|
||||
/* Length of sendkey. */
|
||||
|
@ -33,23 +36,23 @@ static int keylen = 0;
|
|||
static int noled = 0;
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"num", 'n', 0, "set numlock mode", "[on|off]", ARG_TYPE_STRING},
|
||||
{"caps", 'c', 0, "set capslock mode", "[on|off]", ARG_TYPE_STRING},
|
||||
{"scroll", 's', 0, "set scrolllock mode", "[on|off]", ARG_TYPE_STRING},
|
||||
{"insert", 0, 0, "set insert mode", "[on|off]", ARG_TYPE_STRING},
|
||||
{"pause", 0, 0, "set pause mode", "[on|off]", ARG_TYPE_STRING},
|
||||
{"left-shift", 0, 0, "press left shift", "[on|off]", ARG_TYPE_STRING},
|
||||
{"right-shift", 0, 0, "press right shift", "[on|off]", ARG_TYPE_STRING},
|
||||
{"sysrq", 0, 0, "press SysRq", "[on|off]", ARG_TYPE_STRING},
|
||||
{"numkey", 0, 0, "press NumLock key", "[on|off]", ARG_TYPE_STRING},
|
||||
{"capskey", 0, 0, "press CapsLock key", "[on|off]", ARG_TYPE_STRING},
|
||||
{"scrollkey", 0, 0, "press ScrollLock key", "[on|off]", ARG_TYPE_STRING},
|
||||
{"insertkey", 0, 0, "press Insert key", "[on|off]", ARG_TYPE_STRING},
|
||||
{"left-alt", 0, 0, "press left alt", "[on|off]", ARG_TYPE_STRING},
|
||||
{"right-alt", 0, 0, "press right alt", "[on|off]", ARG_TYPE_STRING},
|
||||
{"left-ctrl", 0, 0, "press left ctrl", "[on|off]", ARG_TYPE_STRING},
|
||||
{"right-ctrl", 0, 0, "press right ctrl", "[on|off]", ARG_TYPE_STRING},
|
||||
{"no-led", 0, 0, "don't update LED state", 0, 0},
|
||||
{"num", 'n', 0, N_("set numlock mode"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"caps", 'c', 0, N_("set capslock mode"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"scroll", 's', 0, N_("set scrolllock mode"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"insert", 0, 0, N_("set insert mode"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"pause", 0, 0, N_("set pause mode"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"left-shift", 0, 0, N_("press left shift"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"right-shift", 0, 0, N_("press right shift"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"sysrq", 0, 0, N_("press SysRq"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"numkey", 0, 0, N_("press NumLock key"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"capskey", 0, 0, N_("press CapsLock key"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"scrollkey", 0, 0, N_("press ScrollLock key"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"insertkey", 0, 0, N_("press Insert key"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"left-alt", 0, 0, N_("press left alt"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"right-alt", 0, 0, N_("press right alt"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"left-ctrl", 0, 0, N_("press left ctrl"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"right-ctrl", 0, 0, N_("press right ctrl"), "[on|off]", ARG_TYPE_STRING},
|
||||
{"no-led", 0, 0, N_("don't update LED state"), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
static int simple_flag_offsets[]
|
||||
|
@ -367,8 +370,8 @@ static void *preboot_hook;
|
|||
GRUB_MOD_INIT (sendkey)
|
||||
{
|
||||
cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, 0,
|
||||
"sendkey [KEYSTROKE1] [KEYSTROKE2] ...",
|
||||
"Emulate a keystroke", options);
|
||||
N_("[KEYSTROKE1] [KEYSTROKE2] ..."),
|
||||
N_("Emulate a keystroke"), options);
|
||||
|
||||
preboot_hook
|
||||
= grub_loader_register_preboot_hook (grub_sendkey_preboot,
|
||||
|
|
|
@ -24,12 +24,14 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_suspend (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
{
|
||||
grub_printf ("Run 'go' to resume GRUB.\n");
|
||||
grub_puts_ (N_("Run 'go' to resume GRUB."));
|
||||
grub_ieee1275_enter ();
|
||||
grub_cls ();
|
||||
return 0;
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <grub/cpu/io.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_extcmd_t cmd_read_byte, cmd_read_word, cmd_read_dword;
|
||||
static grub_command_t cmd_write_byte, cmd_write_word, cmd_write_dword;
|
||||
|
||||
|
|
299
grub-core/commands/keylayouts.c
Normal file
299
grub-core/commands/keylayouts.c
Normal file
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2002,2003,2005,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/term.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/keyboard_layouts.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/file.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static struct grub_keyboard_layout layout_us = {
|
||||
.keyboard_map = {
|
||||
/* Keyboard errors. Handled by driver. */
|
||||
/* 0x00 */ 0, 0, 0, 0,
|
||||
|
||||
/* 0x04 */ 'a', 'b', 'c', 'd',
|
||||
/* 0x08 */ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
||||
/* 0x10 */ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
|
||||
/* 0x18 */ 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
|
||||
/* 0x20 */ '3', '4', '5', '6', '7', '8', '9', '0',
|
||||
/* 0x28 */ '\n', '\e', '\b', '\t', ' ', '-', '=', '[',
|
||||
/* According to usage table 0x31 should be mapped to '/'
|
||||
but testing with real keyboard shows that 0x32 is remapped to '/'.
|
||||
Map 0x31 to 0.
|
||||
*/
|
||||
/* 0x30 */ ']', 0, '\\', ';', '\'', '`', ',', '.',
|
||||
/* 0x39 is CapsLock. Handled by driver. */
|
||||
/* 0x38 */ '/', 0, GRUB_TERM_KEY_F1, GRUB_TERM_KEY_F2,
|
||||
/* 0x3c */ GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4,
|
||||
/* 0x3e */ GRUB_TERM_KEY_F5, GRUB_TERM_KEY_F6,
|
||||
/* 0x40 */ GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8,
|
||||
/* 0x42 */ GRUB_TERM_KEY_F9, GRUB_TERM_KEY_F10,
|
||||
/* 0x44 */ GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12,
|
||||
/* PrtScr and ScrollLock. Not handled yet. */
|
||||
/* 0x46 */ 0, 0,
|
||||
/* 0x48 is Pause. Not handled yet. */
|
||||
/* 0x48 */ 0, GRUB_TERM_KEY_INSERT,
|
||||
/* 0x4a */ GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_PPAGE,
|
||||
/* 0x4c */ GRUB_TERM_KEY_DC, GRUB_TERM_KEY_END,
|
||||
/* 0x4e */ GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_RIGHT,
|
||||
/* 0x50 */ GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_DOWN,
|
||||
/* 0x53 is NumLock. Handled by driver. */
|
||||
/* 0x52 */ GRUB_TERM_KEY_UP, 0,
|
||||
/* 0x54 */ '/', '*',
|
||||
/* 0x56 */ '-', '+',
|
||||
/* 0x58 */ '\n', GRUB_TERM_KEY_END,
|
||||
/* 0x5a */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_NPAGE,
|
||||
/* 0x5c */ GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_CENTER,
|
||||
/* 0x5e */ GRUB_TERM_KEY_RIGHT, GRUB_TERM_KEY_HOME,
|
||||
/* 0x60 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_PPAGE,
|
||||
/* 0x62 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC,
|
||||
/* 0x64 */ '\\'
|
||||
},
|
||||
.keyboard_map_shift = {
|
||||
/* Keyboard errors. Handled by driver. */
|
||||
/* 0x00 */ 0, 0, 0, 0,
|
||||
|
||||
/* 0x04 */ 'A', 'B', 'C', 'D',
|
||||
/* 0x08 */ 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
|
||||
/* 0x10 */ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
|
||||
/* 0x18 */ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@',
|
||||
/* 0x20 */ '#', '$', '%', '^', '&', '*', '(', ')',
|
||||
/* 0x28 */ '\n' | GRUB_TERM_SHIFT, '\e' | GRUB_TERM_SHIFT,
|
||||
/* 0x2a */ '\b' | GRUB_TERM_SHIFT, '\t' | GRUB_TERM_SHIFT,
|
||||
/* 0x2c */ ' ' | GRUB_TERM_SHIFT, '_', '+', '{',
|
||||
/* According to usage table 0x31 should be mapped to '/'
|
||||
but testing with real keyboard shows that 0x32 is remapped to '/'.
|
||||
Map 0x31 to 0.
|
||||
*/
|
||||
/* 0x30 */ '}', 0, '|', ':', '"', '~', '<', '>',
|
||||
/* 0x39 is CapsLock. Handled by driver. */
|
||||
/* 0x38 */ '?', 0,
|
||||
/* 0x3a */ GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT,
|
||||
/* 0x3b */ GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT,
|
||||
/* 0x3c */ GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT,
|
||||
/* 0x3d */ GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT,
|
||||
/* 0x3e */ GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT,
|
||||
/* 0x3f */ GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT,
|
||||
/* 0x40 */ GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT,
|
||||
/* 0x41 */ GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT,
|
||||
/* 0x42 */ GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT,
|
||||
/* 0x43 */ GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT,
|
||||
/* 0x44 */ GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT,
|
||||
/* 0x45 */ GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT,
|
||||
/* PrtScr and ScrollLock. Not handled yet. */
|
||||
/* 0x46 */ 0, 0,
|
||||
/* 0x48 is Pause. Not handled yet. */
|
||||
/* 0x48 */ 0, GRUB_TERM_KEY_INSERT | GRUB_TERM_SHIFT,
|
||||
/* 0x4a */ GRUB_TERM_KEY_HOME | GRUB_TERM_SHIFT,
|
||||
/* 0x4b */ GRUB_TERM_KEY_PPAGE | GRUB_TERM_SHIFT,
|
||||
/* 0x4c */ GRUB_TERM_KEY_DC | GRUB_TERM_SHIFT,
|
||||
/* 0x4d */ GRUB_TERM_KEY_END | GRUB_TERM_SHIFT,
|
||||
/* 0x4e */ GRUB_TERM_KEY_NPAGE | GRUB_TERM_SHIFT,
|
||||
/* 0x4f */ GRUB_TERM_KEY_RIGHT | GRUB_TERM_SHIFT,
|
||||
/* 0x50 */ GRUB_TERM_KEY_LEFT | GRUB_TERM_SHIFT,
|
||||
/* 0x51 */ GRUB_TERM_KEY_DOWN | GRUB_TERM_SHIFT,
|
||||
/* 0x53 is NumLock. Handled by driver. */
|
||||
/* 0x52 */ GRUB_TERM_KEY_UP | GRUB_TERM_SHIFT, 0,
|
||||
/* 0x54 */ '/', '*',
|
||||
/* 0x56 */ '-', '+',
|
||||
/* 0x58 */ '\n' | GRUB_TERM_SHIFT, '1', '2', '3', '4', '5','6', '7',
|
||||
/* 0x60 */ '8', '9', '0', '.', '|'
|
||||
}
|
||||
};
|
||||
|
||||
static struct grub_keyboard_layout *grub_current_layout = &layout_us;
|
||||
|
||||
static int
|
||||
map_key_core (int code, int status, int *alt_gr_consumed)
|
||||
{
|
||||
*alt_gr_consumed = 0;
|
||||
|
||||
if (status & GRUB_TERM_STATUS_RALT)
|
||||
{
|
||||
if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT))
|
||||
{
|
||||
if (grub_current_layout->keyboard_map_shift_l3[code])
|
||||
{
|
||||
*alt_gr_consumed = 1;
|
||||
return grub_current_layout->keyboard_map_shift_l3[code];
|
||||
}
|
||||
}
|
||||
else if (grub_current_layout->keyboard_map_l3[code])
|
||||
{
|
||||
*alt_gr_consumed = 1;
|
||||
return grub_current_layout->keyboard_map_l3[code];
|
||||
}
|
||||
}
|
||||
if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT))
|
||||
return grub_current_layout->keyboard_map_shift[code];
|
||||
else
|
||||
return grub_current_layout->keyboard_map[code];
|
||||
}
|
||||
|
||||
unsigned
|
||||
grub_term_map_key (grub_keyboard_key_t code, int status)
|
||||
{
|
||||
int alt_gr_consumed = 0;
|
||||
int key;
|
||||
|
||||
if (code >= 0x59 && code <= 0x63 && (status & GRUB_TERM_STATUS_NUM))
|
||||
{
|
||||
if (status & (GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT))
|
||||
status &= ~(GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT);
|
||||
else
|
||||
status |= GRUB_TERM_STATUS_RSHIFT;
|
||||
}
|
||||
|
||||
key = map_key_core (code, status, &alt_gr_consumed);
|
||||
|
||||
if (key == 0 || key == GRUB_TERM_SHIFT)
|
||||
grub_printf ("Unknown key 0x%x detected\n", code);
|
||||
|
||||
if (status & GRUB_TERM_STATUS_CAPS)
|
||||
{
|
||||
if ((key >= 'a') && (key <= 'z'))
|
||||
key += 'A' - 'a';
|
||||
else if ((key >= 'A') && (key <= 'Z'))
|
||||
key += 'a' - 'A';
|
||||
}
|
||||
|
||||
if ((status & GRUB_TERM_STATUS_LALT) ||
|
||||
((status & GRUB_TERM_STATUS_RALT) && !alt_gr_consumed))
|
||||
key |= GRUB_TERM_ALT;
|
||||
if (status & (GRUB_TERM_STATUS_LCTRL | GRUB_TERM_STATUS_RCTRL))
|
||||
key |= GRUB_TERM_CTRL;
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
char *filename;
|
||||
grub_file_t file;
|
||||
grub_uint32_t version;
|
||||
grub_uint8_t magic[GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE];
|
||||
struct grub_keyboard_layout *newmap = NULL;
|
||||
unsigned i;
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file or layout name required");
|
||||
if (argv[0][0] != '(' && argv[0][0] != '/' && argv[0][0] != '+')
|
||||
{
|
||||
const char *prefix = grub_env_get ("prefix");
|
||||
if (!prefix)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "No prefix set");
|
||||
filename = grub_xasprintf ("%s/layouts/%s.gkb", prefix, argv[0]);
|
||||
if (!filename)
|
||||
return grub_errno;
|
||||
}
|
||||
else
|
||||
filename = argv[0];
|
||||
|
||||
file = grub_file_open (filename);
|
||||
if (! file)
|
||||
goto fail;
|
||||
|
||||
if (grub_file_read (file, magic, sizeof (magic)) != sizeof (magic))
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (grub_memcmp (magic, GRUB_KEYBOARD_LAYOUTS_FILEMAGIC,
|
||||
GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE) != 0)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid magic");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (grub_file_read (file, &version, sizeof (version)) != sizeof (version))
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (grub_le_to_cpu32 (version) != GRUB_KEYBOARD_LAYOUTS_VERSION)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid version");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
newmap = grub_malloc (sizeof (*newmap));
|
||||
if (!newmap)
|
||||
goto fail;
|
||||
|
||||
if (grub_file_read (file, newmap, sizeof (*newmap)) != sizeof (*newmap))
|
||||
{
|
||||
if (!grub_errno)
|
||||
grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map); i++)
|
||||
newmap->keyboard_map[i] = grub_le_to_cpu32(newmap->keyboard_map[i]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_shift); i++)
|
||||
newmap->keyboard_map_shift[i]
|
||||
= grub_le_to_cpu32(newmap->keyboard_map_shift[i]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_l3); i++)
|
||||
newmap->keyboard_map_l3[i]
|
||||
= grub_le_to_cpu32(newmap->keyboard_map_l3[i]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_shift_l3); i++)
|
||||
newmap->keyboard_map_shift_l3[i]
|
||||
= grub_le_to_cpu32(newmap->keyboard_map_shift_l3[i]);
|
||||
|
||||
grub_current_layout = newmap;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
fail:
|
||||
if (filename != argv[0])
|
||||
grub_free (filename);
|
||||
grub_free (newmap);
|
||||
if (file)
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(keylayouts)
|
||||
{
|
||||
cmd = grub_register_command ("keymap", grub_cmd_keymap,
|
||||
0, N_("Load a keyboard layout."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(keylayouts)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
|
@ -23,6 +23,8 @@
|
|||
#include <grub/term.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"shift", 's', 0, N_("Check Shift key."), 0, 0},
|
||||
|
@ -31,7 +33,23 @@ static const struct grub_arg_option options[] =
|
|||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#define grub_cur_term_input grub_term_get_current_input ()
|
||||
static int
|
||||
grub_getkeystatus (void)
|
||||
{
|
||||
int status = 0;
|
||||
grub_term_input_t term;
|
||||
|
||||
if (grub_term_poll_usb)
|
||||
grub_term_poll_usb ();
|
||||
|
||||
FOR_ACTIVE_TERM_INPUTS(term)
|
||||
{
|
||||
if (term->getkeystatus)
|
||||
status |= term->getkeystatus (term);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_keystatus (grub_extcmd_context_t ctxt,
|
||||
|
@ -43,11 +61,11 @@ grub_cmd_keystatus (grub_extcmd_context_t ctxt,
|
|||
int mods;
|
||||
|
||||
if (state[0].set)
|
||||
expect_mods |= GRUB_TERM_STATUS_SHIFT;
|
||||
expect_mods |= (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT);
|
||||
if (state[1].set)
|
||||
expect_mods |= GRUB_TERM_STATUS_CTRL;
|
||||
expect_mods |= (GRUB_TERM_STATUS_LCTRL | GRUB_TERM_STATUS_RCTRL);
|
||||
if (state[2].set)
|
||||
expect_mods |= GRUB_TERM_STATUS_ALT;
|
||||
expect_mods |= (GRUB_TERM_STATUS_LALT | GRUB_TERM_STATUS_RALT);
|
||||
|
||||
grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods);
|
||||
|
||||
|
|
820
grub-core/commands/legacycfg.c
Normal file
820
grub-core/commands/legacycfg.c
Normal file
|
@ -0,0 +1,820 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2000, 2001, 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/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/normal.h>
|
||||
#include <grub/script_sh.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/term.h>
|
||||
#include <grub/legacy_parse.h>
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/auth.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/partition.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
legacy_file (const char *filename)
|
||||
{
|
||||
grub_file_t file;
|
||||
char *entryname = NULL, *entrysrc = NULL;
|
||||
grub_menu_t menu;
|
||||
char *suffix = grub_strdup ("");
|
||||
|
||||
auto grub_err_t getline (char **line, int cont);
|
||||
grub_err_t getline (char **line,
|
||||
int cont __attribute__ ((unused)))
|
||||
{
|
||||
*line = 0;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (!suffix)
|
||||
return grub_errno;
|
||||
|
||||
file = grub_file_open (filename);
|
||||
if (! file)
|
||||
return grub_errno;
|
||||
|
||||
menu = grub_env_get_menu ();
|
||||
if (! menu)
|
||||
{
|
||||
menu = grub_zalloc (sizeof (*menu));
|
||||
if (! menu)
|
||||
return grub_errno;
|
||||
|
||||
grub_env_set_menu (menu);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
char *buf = grub_file_getline (file);
|
||||
char *parsed = NULL;
|
||||
|
||||
if (!buf && grub_errno)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
if (!buf)
|
||||
break;
|
||||
|
||||
{
|
||||
char *oldname = NULL;
|
||||
char *newsuffix;
|
||||
char *ptr;
|
||||
|
||||
for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++);
|
||||
|
||||
oldname = entryname;
|
||||
parsed = grub_legacy_parse (ptr, &entryname, &newsuffix);
|
||||
grub_free (buf);
|
||||
buf = NULL;
|
||||
if (newsuffix)
|
||||
{
|
||||
char *t;
|
||||
|
||||
t = suffix;
|
||||
suffix = grub_realloc (suffix, grub_strlen (suffix)
|
||||
+ grub_strlen (newsuffix) + 1);
|
||||
if (!suffix)
|
||||
{
|
||||
grub_free (t);
|
||||
grub_free (entrysrc);
|
||||
grub_free (parsed);
|
||||
grub_free (newsuffix);
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (suffix + grub_strlen (suffix), newsuffix,
|
||||
grub_strlen (newsuffix) + 1);
|
||||
grub_free (newsuffix);
|
||||
newsuffix = NULL;
|
||||
}
|
||||
if (oldname != entryname && oldname)
|
||||
{
|
||||
const char **args = grub_malloc (sizeof (args[0]));
|
||||
if (!args)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
args[0] = oldname;
|
||||
grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL,
|
||||
entrysrc, 0);
|
||||
grub_free (args);
|
||||
entrysrc[0] = 0;
|
||||
grub_free (oldname);
|
||||
}
|
||||
}
|
||||
|
||||
if (parsed && !entryname)
|
||||
{
|
||||
grub_normal_parse_line (parsed, getline);
|
||||
grub_print_error ();
|
||||
grub_free (parsed);
|
||||
parsed = NULL;
|
||||
}
|
||||
else if (parsed)
|
||||
{
|
||||
if (!entrysrc)
|
||||
entrysrc = parsed;
|
||||
else
|
||||
{
|
||||
char *t;
|
||||
|
||||
t = entrysrc;
|
||||
entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc)
|
||||
+ grub_strlen (parsed) + 1);
|
||||
if (!entrysrc)
|
||||
{
|
||||
grub_free (t);
|
||||
grub_free (parsed);
|
||||
grub_free (suffix);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed,
|
||||
grub_strlen (parsed) + 1);
|
||||
grub_free (parsed);
|
||||
parsed = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
grub_file_close (file);
|
||||
|
||||
if (entryname)
|
||||
{
|
||||
const char **args = grub_malloc (sizeof (args[0]));
|
||||
if (!args)
|
||||
{
|
||||
grub_file_close (file);
|
||||
return grub_errno;
|
||||
}
|
||||
args[0] = entryname;
|
||||
grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, entrysrc, 0);
|
||||
grub_free (args);
|
||||
}
|
||||
|
||||
grub_normal_parse_line (suffix, getline);
|
||||
grub_print_error ();
|
||||
grub_free (suffix);
|
||||
grub_free (entrysrc);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_source (struct grub_command *cmd,
|
||||
int argc, char **args)
|
||||
{
|
||||
int new_env, extractor;
|
||||
grub_err_t ret;
|
||||
|
||||
if (argc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
|
||||
|
||||
extractor = (cmd->name[0] == 'e');
|
||||
new_env = (cmd->name[extractor ? (sizeof ("extract_legacy_entries_") - 1)
|
||||
: (sizeof ("legacy_") - 1)] == 'c');
|
||||
|
||||
if (new_env)
|
||||
grub_cls ();
|
||||
|
||||
if (new_env && !extractor)
|
||||
grub_env_context_open ();
|
||||
if (extractor)
|
||||
grub_env_extractor_open (!new_env);
|
||||
|
||||
ret = legacy_file (args[0]);
|
||||
|
||||
if (new_env)
|
||||
{
|
||||
grub_menu_t menu;
|
||||
menu = grub_env_get_menu ();
|
||||
if (menu && menu->size)
|
||||
grub_show_menu (menu, 1, 0);
|
||||
if (!extractor)
|
||||
grub_env_context_close ();
|
||||
}
|
||||
if (extractor)
|
||||
grub_env_extractor_close (!new_env);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum
|
||||
{
|
||||
GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD
|
||||
} kernel_type;
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
int i;
|
||||
#ifdef TODO
|
||||
int no_mem_option = 0;
|
||||
#endif
|
||||
struct grub_command *cmd;
|
||||
char **cutargs;
|
||||
int cutargc;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
/* FIXME: really support this. */
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--no-mem-option") == 0)
|
||||
{
|
||||
#ifdef TODO
|
||||
no_mem_option = 1;
|
||||
#endif
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* linux16 handles both zImages and bzImages. */
|
||||
if (argc >= 1 && (grub_strcmp (args[0], "--type=linux") == 0
|
||||
|| grub_strcmp (args[0], "--type=biglinux") == 0))
|
||||
{
|
||||
kernel_type = LINUX;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=multiboot") == 0)
|
||||
{
|
||||
kernel_type = MULTIBOOT;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=freebsd") == 0)
|
||||
{
|
||||
kernel_type = KFREEBSD;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=openbsd") == 0)
|
||||
{
|
||||
kernel_type = KOPENBSD;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argc >= 1 && grub_strcmp (args[0], "--type=netbsd") == 0)
|
||||
{
|
||||
kernel_type = KNETBSD;
|
||||
argc--;
|
||||
args++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename required");
|
||||
|
||||
cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1));
|
||||
cutargc = argc - 1;
|
||||
grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2));
|
||||
cutargs[0] = args[0];
|
||||
|
||||
do
|
||||
{
|
||||
/* First try Linux. */
|
||||
if (kernel_type == GUESS_IT || kernel_type == LINUX)
|
||||
{
|
||||
cmd = grub_command_find ("linux16");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, cutargc, cutargs))
|
||||
{
|
||||
kernel_type = LINUX;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Then multiboot. */
|
||||
if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT)
|
||||
{
|
||||
cmd = grub_command_find ("multiboot");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, argc, args))
|
||||
{
|
||||
kernel_type = MULTIBOOT;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
{
|
||||
int bsd_device = -1;
|
||||
int bsd_slice = -1;
|
||||
int bsd_part = -1;
|
||||
{
|
||||
grub_device_t dev;
|
||||
const char *hdbiasstr;
|
||||
int hdbias = 0;
|
||||
hdbiasstr = grub_env_get ("legacy_hdbias");
|
||||
if (hdbiasstr)
|
||||
{
|
||||
hdbias = grub_strtoul (hdbiasstr, 0, 0);
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
dev = grub_device_open (0);
|
||||
if (dev && dev->disk
|
||||
&& dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID
|
||||
&& dev->disk->dev->id >= 0x80 && dev->disk->dev->id <= 0x90)
|
||||
{
|
||||
struct grub_partition *part = dev->disk->partition;
|
||||
bsd_device = dev->disk->id - 0x80 - hdbias;
|
||||
if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0
|
||||
|| grub_strcmp (part->partmap->name, "openbsd") == 0
|
||||
|| grub_strcmp (part->partmap->name, "bsd") == 0))
|
||||
{
|
||||
bsd_part = part->number;
|
||||
part = part->parent;
|
||||
}
|
||||
if (part && grub_strcmp (part->partmap->name, "msdos") == 0)
|
||||
bsd_slice = part->number;
|
||||
}
|
||||
}
|
||||
|
||||
/* k*BSD didn't really work well with grub-legacy. */
|
||||
if (kernel_type == GUESS_IT || kernel_type == KFREEBSD)
|
||||
{
|
||||
char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")];
|
||||
if (bsd_device != -1)
|
||||
{
|
||||
if (bsd_slice != -1 && bsd_part != -1)
|
||||
grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device,
|
||||
bsd_slice, 'a' + bsd_part);
|
||||
else if (bsd_slice != -1)
|
||||
grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device,
|
||||
bsd_slice);
|
||||
else
|
||||
grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device);
|
||||
grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf);
|
||||
}
|
||||
else
|
||||
grub_env_unset ("kFreeBSD.vfs.root.mountfrom");
|
||||
cmd = grub_command_find ("kfreebsd");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, cutargc, cutargs))
|
||||
{
|
||||
kernel_type = KFREEBSD;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
{
|
||||
char **bsdargs;
|
||||
int bsdargc;
|
||||
char bsddevname[sizeof ("wdXXXXXXXXXXXXY")];
|
||||
if (bsd_device == -1)
|
||||
{
|
||||
bsdargs = cutargs;
|
||||
bsdargc = cutargc;
|
||||
}
|
||||
else
|
||||
{
|
||||
bsdargc = cutargc + 2;
|
||||
bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
|
||||
grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0]));
|
||||
bsdargs[argc] = "-r";
|
||||
bsdargs[argc + 1] = bsddevname;
|
||||
grub_snprintf (bsddevname, sizeof (bsddevname),
|
||||
"wd%d%c", bsd_device,
|
||||
bsd_part != -1 ? bsd_part + 'a' : 'c');
|
||||
}
|
||||
if (kernel_type == GUESS_IT || kernel_type == KNETBSD)
|
||||
{
|
||||
cmd = grub_command_find ("knetbsd");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, bsdargc, bsdargs))
|
||||
{
|
||||
kernel_type = KNETBSD;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
if (kernel_type == GUESS_IT || kernel_type == KOPENBSD)
|
||||
{
|
||||
cmd = grub_command_find ("kopenbsd");
|
||||
if (cmd)
|
||||
{
|
||||
if (!(cmd->func) (cmd, bsdargc, bsdargs))
|
||||
{
|
||||
kernel_type = KOPENBSD;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
if (bsdargs != cutargs)
|
||||
grub_free (bsdargs);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s\n",
|
||||
args[0]);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_command *cmd;
|
||||
|
||||
if (kernel_type == LINUX)
|
||||
{
|
||||
cmd = grub_command_find ("initrd16");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found");
|
||||
|
||||
return cmd->func (cmd, argc, args);
|
||||
}
|
||||
if (kernel_type == MULTIBOOT)
|
||||
{
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found");
|
||||
|
||||
return cmd->func (cmd, argc, args);
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"no kernel with module support is loaded in legacy way");
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_command *cmd;
|
||||
|
||||
if (kernel_type == LINUX)
|
||||
{
|
||||
cmd = grub_command_find ("initrd16");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found");
|
||||
|
||||
return cmd->func (cmd, argc, args);
|
||||
}
|
||||
if (kernel_type == MULTIBOOT)
|
||||
{
|
||||
char **newargs;
|
||||
grub_err_t err;
|
||||
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";
|
||||
cmd = grub_command_find ("module");
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found");
|
||||
|
||||
err = cmd->func (cmd, argc + 1, newargs);
|
||||
grub_free (newargs);
|
||||
return err;
|
||||
}
|
||||
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"no kernel with module support is loaded in legacy way");
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_password_deny (const char *user __attribute__ ((unused)),
|
||||
const char *entered __attribute__ ((unused)),
|
||||
void *password __attribute__ ((unused)))
|
||||
{
|
||||
return GRUB_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
#define MD5_HASHLEN 16
|
||||
|
||||
struct legacy_md5_password
|
||||
{
|
||||
grub_uint8_t *salt;
|
||||
int saltlen;
|
||||
grub_uint8_t hash[MD5_HASHLEN];
|
||||
};
|
||||
|
||||
static int
|
||||
check_password_md5_real (const char *entered,
|
||||
struct legacy_md5_password *pw)
|
||||
{
|
||||
int enteredlen = grub_strlen (entered);
|
||||
unsigned char alt_result[MD5_HASHLEN];
|
||||
unsigned char *digest;
|
||||
grub_uint8_t ctx[GRUB_MD_MD5->contextsize];
|
||||
int i;
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
memcpy (alt_result, digest, MD5_HASHLEN);
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */
|
||||
for (i = enteredlen; i > 16; i -= 16)
|
||||
GRUB_MD_MD5->write (ctx, alt_result, 16);
|
||||
GRUB_MD_MD5->write (ctx, alt_result, i);
|
||||
|
||||
for (i = enteredlen; i > 0; i >>= 1)
|
||||
GRUB_MD_MD5->write (ctx, entered + ((i & 1) ? enteredlen : 0), 1);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
|
||||
for (i = 0; i < 1000; i++)
|
||||
{
|
||||
memcpy (alt_result, digest, 16);
|
||||
|
||||
GRUB_MD_MD5->init (ctx);
|
||||
if ((i & 1) != 0)
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
else
|
||||
GRUB_MD_MD5->write (ctx, alt_result, 16);
|
||||
|
||||
if (i % 3 != 0)
|
||||
GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3);
|
||||
|
||||
if (i % 7 != 0)
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
|
||||
if ((i & 1) != 0)
|
||||
GRUB_MD_MD5->write (ctx, alt_result, 16);
|
||||
else
|
||||
GRUB_MD_MD5->write (ctx, entered, enteredlen);
|
||||
digest = GRUB_MD_MD5->read (ctx);
|
||||
GRUB_MD_MD5->final (ctx);
|
||||
}
|
||||
|
||||
return (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
check_password_md5 (const char *user,
|
||||
const char *entered,
|
||||
void *password)
|
||||
{
|
||||
if (!check_password_md5_real (entered, password))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
grub_auth_authenticate (user);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ib64t (char c)
|
||||
{
|
||||
if (c == '.')
|
||||
return 0;
|
||||
if (c == '/')
|
||||
return 1;
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0' + 2;
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
return c - 'A' + 12;
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return c - 'a' + 38;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct legacy_md5_password *
|
||||
parse_legacy_md5 (int argc, char **args)
|
||||
{
|
||||
const char *salt, *saltend;
|
||||
struct legacy_md5_password *pw = NULL;
|
||||
int i;
|
||||
const char *p;
|
||||
|
||||
if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0)
|
||||
goto fail;
|
||||
if (argc == 1)
|
||||
goto fail;
|
||||
if (grub_strlen(args[1]) <= 3)
|
||||
goto fail;
|
||||
salt = args[1];
|
||||
saltend = grub_strchr (salt + 3, '$');
|
||||
if (!saltend)
|
||||
goto fail;
|
||||
pw = grub_malloc (sizeof (*pw));
|
||||
if (!pw)
|
||||
goto fail;
|
||||
|
||||
p = saltend + 1;
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
int n;
|
||||
grub_uint32_t w = 0;
|
||||
|
||||
for (n = 0; n < 4; n++)
|
||||
{
|
||||
int ww = ib64t(*p++);
|
||||
if (ww == -1)
|
||||
goto fail;
|
||||
w |= ww << (n * 6);
|
||||
}
|
||||
pw->hash[i == 4 ? 5 : 12+i] = w & 0xff;
|
||||
pw->hash[6+i] = (w >> 8) & 0xff;
|
||||
pw->hash[i] = (w >> 16) & 0xff;
|
||||
}
|
||||
{
|
||||
int n;
|
||||
grub_uint32_t w = 0;
|
||||
for (n = 0; n < 2; n++)
|
||||
{
|
||||
int ww = ib64t(*p++);
|
||||
if (ww == -1)
|
||||
goto fail;
|
||||
w |= ww << (6 * n);
|
||||
}
|
||||
if (w >= 0x100)
|
||||
goto fail;
|
||||
pw->hash[11] = w;
|
||||
}
|
||||
|
||||
pw->saltlen = saltend - salt;
|
||||
pw->salt = (grub_uint8_t *) grub_strndup (salt, pw->saltlen);
|
||||
if (!pw->salt)
|
||||
goto fail;
|
||||
|
||||
return pw;
|
||||
|
||||
fail:
|
||||
grub_free (pw);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct legacy_md5_password *pw = NULL;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected");
|
||||
if (args[0][0] != '-' || args[0][1] != '-')
|
||||
return grub_normal_set_password ("legacy", args[0]);
|
||||
|
||||
pw = parse_legacy_md5 (argc, args);
|
||||
|
||||
if (pw)
|
||||
return grub_auth_register_authentication ("legacy", check_password_md5, pw);
|
||||
else
|
||||
/* This is to imitate minor difference between grub-legacy in GRUB2.
|
||||
If 2 password commands are executed in a row and second one fails
|
||||
on GRUB2 the password of first one is used, whereas in grub-legacy
|
||||
authenthication is denied. In case of no password command was executed
|
||||
early both versions deny any access. */
|
||||
return grub_auth_register_authentication ("legacy", check_password_deny,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct legacy_md5_password *pw = NULL;
|
||||
char entered[GRUB_AUTH_MAX_PASSLEN];
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected");
|
||||
grub_puts_ (N_("Enter password: "));
|
||||
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
if (args[0][0] != '-' || args[0][1] != '-')
|
||||
{
|
||||
char correct[GRUB_AUTH_MAX_PASSLEN];
|
||||
|
||||
grub_memset (correct, 0, sizeof (correct));
|
||||
grub_strncpy (correct, args[0], sizeof (correct));
|
||||
|
||||
if (grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) != 0)
|
||||
return GRUB_ACCESS_DENIED;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
pw = parse_legacy_md5 (argc, args);
|
||||
|
||||
if (!pw)
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
if (!check_password_md5_real (entered, pw))
|
||||
return GRUB_ACCESS_DENIED;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_command_t cmd_source, cmd_configfile;
|
||||
static grub_command_t cmd_source_extract, cmd_configfile_extract;
|
||||
static grub_command_t cmd_kernel, cmd_initrd, cmd_initrdnounzip;
|
||||
static grub_command_t cmd_password, cmd_check_password;
|
||||
|
||||
GRUB_MOD_INIT(legacycfg)
|
||||
{
|
||||
cmd_source
|
||||
= grub_register_command ("legacy_source",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in same context"));
|
||||
cmd_configfile
|
||||
= grub_register_command ("legacy_configfile",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in new context"));
|
||||
cmd_source_extract
|
||||
= grub_register_command ("extract_legacy_entries_source",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in same context taking only menu entries"));
|
||||
cmd_configfile_extract
|
||||
= grub_register_command ("extract_legacy_entries_configfile",
|
||||
grub_cmd_legacy_source,
|
||||
N_("FILE"),
|
||||
N_("Parse legacy config in new context taking only menu entries"));
|
||||
|
||||
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"));
|
||||
|
||||
cmd_initrd = grub_register_command ("legacy_initrd",
|
||||
grub_cmd_legacy_initrd,
|
||||
N_("FILE [ARG ...]"),
|
||||
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"));
|
||||
|
||||
cmd_password = grub_register_command ("legacy_password",
|
||||
grub_cmd_legacy_password,
|
||||
N_("[--md5] PASSWD [FILE]"),
|
||||
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"));
|
||||
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(legacycfg)
|
||||
{
|
||||
grub_unregister_command (cmd_source);
|
||||
grub_unregister_command (cmd_configfile);
|
||||
grub_unregister_command (cmd_source_extract);
|
||||
grub_unregister_command (cmd_configfile_extract);
|
||||
|
||||
grub_unregister_command (cmd_kernel);
|
||||
grub_unregister_command (cmd_initrd);
|
||||
grub_unregister_command (cmd_initrdnounzip);
|
||||
|
||||
grub_unregister_command (cmd_password);
|
||||
grub_unregister_command (cmd_check_password);
|
||||
}
|
|
@ -28,6 +28,8 @@
|
|||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"file", 'f', 0, N_("Specify filename."), 0, ARG_TYPE_PATHNAME},
|
||||
|
@ -41,7 +43,7 @@ open_envblk_file (char *filename)
|
|||
|
||||
if (! filename)
|
||||
{
|
||||
char *prefix;
|
||||
const char *prefix;
|
||||
|
||||
prefix = grub_env_get ("prefix");
|
||||
if (prefix)
|
||||
|
@ -344,7 +346,7 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
|
||||
while (argc)
|
||||
{
|
||||
char *value;
|
||||
const char *value;
|
||||
|
||||
value = grub_env_get (args[0]);
|
||||
if (value)
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#include <grub/extcmd.h>
|
||||
#include <grub/datetime.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/net.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
|
@ -58,6 +61,22 @@ grub_ls_list_devices (int longlist)
|
|||
|
||||
grub_device_iterate (grub_ls_print_devices);
|
||||
grub_xputs ("\n");
|
||||
|
||||
#ifndef GRUB_UTIL
|
||||
{
|
||||
grub_net_app_level_t proto;
|
||||
int first = 1;
|
||||
FOR_NET_APP_LEVEL (proto)
|
||||
{
|
||||
if (first)
|
||||
grub_puts_ (N_ ("Network protocols:"));
|
||||
first = 0;
|
||||
grub_printf ("%s ", proto->name);
|
||||
}
|
||||
grub_xputs ("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
grub_refresh ();
|
||||
|
||||
return 0;
|
||||
|
@ -132,11 +151,12 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
|
|||
|
||||
if (units)
|
||||
{
|
||||
grub_uint32_t whole, fraction;
|
||||
grub_uint64_t whole, fraction;
|
||||
|
||||
whole = grub_divmod64 (fsize, 100, &fraction);
|
||||
grub_snprintf (buf, sizeof (buf),
|
||||
"%u.%02u%c", whole, fraction,
|
||||
"%" PRIuGRUB_UINT64_T
|
||||
".%02" PRIuGRUB_UINT64_T "%c", whole, fraction,
|
||||
grub_human_sizes[units]);
|
||||
grub_printf ("%-12s", buf);
|
||||
}
|
||||
|
@ -270,7 +290,7 @@ static grub_extcmd_t cmd;
|
|||
GRUB_MOD_INIT(ls)
|
||||
{
|
||||
cmd = grub_register_extcmd ("ls", grub_cmd_ls, 0,
|
||||
N_("[-l|-h|-a] [FILE]"),
|
||||
N_("[-l|-h|-a] [FILE ...]"),
|
||||
N_("List devices and files."), options);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <grub/i18n.h>
|
||||
#include <grub/dl.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static void
|
||||
print_strn (grub_uint8_t *str, grub_size_t len)
|
||||
{
|
||||
|
|
|
@ -16,24 +16,41 @@
|
|||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRUB_MACHINE_EMU
|
||||
#include <grub/machine/memory.h>
|
||||
#endif
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/memory.h>
|
||||
|
||||
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")
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_lsmmap (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)), char **args __attribute__ ((unused)))
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
|
||||
{
|
||||
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
|
||||
int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type)
|
||||
auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_memory_type_t);
|
||||
int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size,
|
||||
grub_memory_type_t type)
|
||||
{
|
||||
grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n",
|
||||
(long long) addr, (long long) size, type);
|
||||
if (type < ARRAY_SIZE (names) && names[type])
|
||||
grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, %s\n"),
|
||||
(long long) addr, (long long) size, _(names[type]));
|
||||
else
|
||||
grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n"),
|
||||
(long long) addr, (long long) size, type);
|
||||
return 0;
|
||||
}
|
||||
#ifndef GRUB_MACHINE_EMU
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
struct grub_pci_classname
|
||||
{
|
||||
int class;
|
||||
|
|
|
@ -23,13 +23,15 @@
|
|||
#include <grub/env.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_extcmd_t cmd_read_byte, cmd_read_word, cmd_read_dword;
|
||||
static grub_command_t cmd_write_byte, cmd_write_word, cmd_write_dword;
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{0, 'v', 0, N_("Save read value into variable VARNAME."),
|
||||
"VARNAME", ARG_TYPE_STRING},
|
||||
N_("VARNAME"), ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
|
|
@ -28,13 +28,13 @@
|
|||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"class", 1, GRUB_ARG_OPTION_REPEATABLE,
|
||||
N_("Menu entry type."), "STRING", ARG_TYPE_STRING},
|
||||
N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING},
|
||||
{"users", 2, 0,
|
||||
N_("Users allowed to boot this entry."), "USERNAME", ARG_TYPE_STRING},
|
||||
N_("Users allowed to boot this entry."), N_("USERNAME"), ARG_TYPE_STRING},
|
||||
{"hotkey", 3, 0,
|
||||
N_("Keyboard key for this entry."), "KEY", ARG_TYPE_STRING},
|
||||
N_("Keyboard key for this entry."), N_("KEY"), ARG_TYPE_STRING},
|
||||
{"source", 4, 0,
|
||||
N_("Menu entry definition as a string."), "STRING", ARG_TYPE_STRING},
|
||||
N_("Menu entry definition as a string."), N_("STRING"), ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -46,18 +46,31 @@ static struct
|
|||
{
|
||||
{"backspace", '\b'},
|
||||
{"tab", '\t'},
|
||||
{"delete", GRUB_TERM_DC}
|
||||
{"delete", GRUB_TERM_KEY_DC},
|
||||
{"insert", GRUB_TERM_KEY_INSERT},
|
||||
{"f1", GRUB_TERM_KEY_F1},
|
||||
{"f2", GRUB_TERM_KEY_F2},
|
||||
{"f3", GRUB_TERM_KEY_F3},
|
||||
{"f4", GRUB_TERM_KEY_F4},
|
||||
{"f5", GRUB_TERM_KEY_F5},
|
||||
{"f6", GRUB_TERM_KEY_F6},
|
||||
{"f7", GRUB_TERM_KEY_F7},
|
||||
{"f8", GRUB_TERM_KEY_F8},
|
||||
{"f9", GRUB_TERM_KEY_F9},
|
||||
{"f10", GRUB_TERM_KEY_F10},
|
||||
{"f11", GRUB_TERM_KEY_F11},
|
||||
{"f12", GRUB_TERM_KEY_F12},
|
||||
};
|
||||
|
||||
/* Add a menu entry to the current menu context (as given by the environment
|
||||
variable data slot `menu'). As the configuration file is read, the script
|
||||
parser calls this when a menu entry is to be created. */
|
||||
static grub_err_t
|
||||
append_menu_entry (int argc, const char **args, char **classes,
|
||||
const char *users, const char *hotkey,
|
||||
const char *prefix, const char *sourcecode)
|
||||
grub_err_t
|
||||
grub_normal_add_menu_entry (int argc, const char **args, char **classes,
|
||||
const char *users, const char *hotkey,
|
||||
const char *prefix, const char *sourcecode,
|
||||
int submenu)
|
||||
{
|
||||
unsigned i;
|
||||
int menu_hotkey = 0;
|
||||
char **menu_args = NULL;
|
||||
char *menu_users = NULL;
|
||||
|
@ -78,8 +91,9 @@ append_menu_entry (int argc, const char **args, char **classes,
|
|||
if (! menu_sourcecode)
|
||||
return grub_errno;
|
||||
|
||||
if (classes)
|
||||
if (classes && classes[0])
|
||||
{
|
||||
int i;
|
||||
for (i = 0; classes[i]; i++); /* count # of menuentry classes */
|
||||
menu_classes = grub_zalloc (sizeof (struct grub_menu_entry_class) * i);
|
||||
if (! menu_classes)
|
||||
|
@ -103,6 +117,7 @@ append_menu_entry (int argc, const char **args, char **classes,
|
|||
|
||||
if (hotkey)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
|
||||
if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
|
||||
{
|
||||
|
@ -128,13 +143,16 @@ append_menu_entry (int argc, const char **args, char **classes,
|
|||
if (! menu_args)
|
||||
goto fail;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
menu_args[i] = grub_strdup (args[i]);
|
||||
if (! menu_args[i])
|
||||
goto fail;
|
||||
}
|
||||
menu_args[argc] = NULL;
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
menu_args[i] = grub_strdup (args[i]);
|
||||
if (! menu_args[i])
|
||||
goto fail;
|
||||
}
|
||||
menu_args[argc] = NULL;
|
||||
}
|
||||
|
||||
/* Add the menu entry at the end of the list. */
|
||||
while (*last)
|
||||
|
@ -153,6 +171,7 @@ append_menu_entry (int argc, const char **args, char **classes,
|
|||
(*last)->argc = argc;
|
||||
(*last)->args = menu_args;
|
||||
(*last)->sourcecode = menu_sourcecode;
|
||||
(*last)->submenu = submenu;
|
||||
|
||||
menu->size++;
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -160,13 +179,19 @@ append_menu_entry (int argc, const char **args, char **classes,
|
|||
fail:
|
||||
|
||||
grub_free (menu_sourcecode);
|
||||
for (i = 0; menu_classes && menu_classes[i].name; i++)
|
||||
grub_free (menu_classes[i].name);
|
||||
grub_free (menu_classes);
|
||||
{
|
||||
int i;
|
||||
for (i = 0; menu_classes && menu_classes[i].name; i++)
|
||||
grub_free (menu_classes[i].name);
|
||||
grub_free (menu_classes);
|
||||
}
|
||||
|
||||
for (i = 0; menu_args && menu_args[i]; i++)
|
||||
grub_free (menu_args[i]);
|
||||
grub_free (menu_args);
|
||||
{
|
||||
int i;
|
||||
for (i = 0; menu_args && menu_args[i]; i++)
|
||||
grub_free (menu_args[i]);
|
||||
grub_free (menu_args);
|
||||
}
|
||||
|
||||
grub_free (menu_users);
|
||||
grub_free (menu_title);
|
||||
|
@ -181,20 +206,6 @@ setparams_prefix (int argc, char **args)
|
|||
char *p;
|
||||
char *result;
|
||||
grub_size_t len = 10;
|
||||
static const char *escape_characters = "\"\\";
|
||||
|
||||
auto char *strescpy (char *, const char *, const char *);
|
||||
char * strescpy (char *d, const char *s, const char *escapes)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
if (grub_strchr (escapes, *s))
|
||||
*d++ = '\\';
|
||||
*d++ = *s++;
|
||||
}
|
||||
*d = '\0';
|
||||
return d;
|
||||
}
|
||||
|
||||
/* Count resulting string length */
|
||||
for (i = 0; i < argc; i++)
|
||||
|
@ -202,7 +213,7 @@ setparams_prefix (int argc, char **args)
|
|||
len += 3; /* 3 = 1 space + 2 quotes */
|
||||
p = args[i];
|
||||
while (*p)
|
||||
len += grub_strchr (escape_characters, *p++) ? 2 : 1;
|
||||
len += (*p++ == '\'' ? 3 : 1);
|
||||
}
|
||||
|
||||
result = grub_malloc (len + 2);
|
||||
|
@ -210,17 +221,17 @@ setparams_prefix (int argc, char **args)
|
|||
return 0;
|
||||
|
||||
grub_strcpy (result, "setparams");
|
||||
i = 9;
|
||||
p = result + 9;
|
||||
|
||||
for (j = 0; j < argc; j++)
|
||||
{
|
||||
result[i++] = ' ';
|
||||
result[i++] = '"';
|
||||
i = strescpy (result + i, args[j], escape_characters) - result;
|
||||
result[i++] = '"';
|
||||
*p++ = ' ';
|
||||
*p++ = '\'';
|
||||
p = grub_strchrsub (p, args[j], '\'', "'\\''");
|
||||
*p++ = '\'';
|
||||
}
|
||||
result[i++] = '\n';
|
||||
result[i] = '\0';
|
||||
*p++ = '\n';
|
||||
*p = '\0';
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -243,9 +254,12 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition");
|
||||
|
||||
if (! ctxt->script)
|
||||
return append_menu_entry (argc, (const char **) args,
|
||||
ctxt->state[0].args, ctxt->state[1].arg,
|
||||
ctxt->state[2].arg, 0, ctxt->state[3].arg);
|
||||
return grub_normal_add_menu_entry (argc, (const char **) args,
|
||||
(ctxt->state[0].set ? ctxt->state[0].args
|
||||
: NULL), ctxt->state[1].arg,
|
||||
ctxt->state[2].arg, 0,
|
||||
ctxt->state[3].arg,
|
||||
ctxt->extcmd->cmd->name[0] == 's');
|
||||
|
||||
src = args[argc - 1];
|
||||
args[argc - 1] = NULL;
|
||||
|
@ -258,9 +272,10 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
if (! prefix)
|
||||
return grub_errno;
|
||||
|
||||
r = append_menu_entry (argc - 1, (const char **) args,
|
||||
ctxt->state[0].args, ctxt->state[1].arg,
|
||||
ctxt->state[2].arg, prefix, src + 1);
|
||||
r = grub_normal_add_menu_entry (argc - 1, (const char **) args,
|
||||
ctxt->state[0].args, ctxt->state[1].arg,
|
||||
ctxt->state[2].arg, prefix, src + 1,
|
||||
ctxt->extcmd->cmd->name[0] == 's');
|
||||
|
||||
src[len - 1] = ch;
|
||||
args[argc - 1] = src;
|
||||
|
@ -268,18 +283,25 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
return r;
|
||||
}
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
static grub_extcmd_t cmd, cmd_sub;
|
||||
|
||||
void
|
||||
grub_menu_init (void)
|
||||
{
|
||||
cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
|
||||
GRUB_COMMAND_FLAG_BLOCKS,
|
||||
GRUB_COMMAND_FLAG_BLOCKS
|
||||
| GRUB_COMMAND_FLAG_EXTRACTOR,
|
||||
N_("BLOCK"), N_("Define a menuentry."), options);
|
||||
cmd_sub = grub_register_extcmd ("submenu", grub_cmd_menuentry,
|
||||
GRUB_COMMAND_FLAG_BLOCKS
|
||||
| GRUB_COMMAND_FLAG_EXTRACTOR,
|
||||
N_("BLOCK"), N_("Define a submenu."),
|
||||
options);
|
||||
}
|
||||
|
||||
void
|
||||
grub_menu_fini (void)
|
||||
{
|
||||
grub_unregister_extcmd (cmd);
|
||||
grub_unregister_extcmd (cmd_sub);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/* cat FILE */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_cat (struct grub_command *cmd __attribute__ ((unused)),
|
||||
|
@ -88,26 +90,6 @@ grub_mini_cmd_help (struct grub_command *cmd __attribute__ ((unused)),
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
grub_rescue_cmd_info (void)
|
||||
{
|
||||
extern void grub_disk_cache_get_performance (unsigned long *,
|
||||
unsigned long *);
|
||||
unsigned long hits, misses;
|
||||
|
||||
grub_disk_cache_get_performance (&hits, &misses);
|
||||
grub_printf ("Disk cache: hits = %u, misses = %u ", hits, misses);
|
||||
if (hits + misses)
|
||||
{
|
||||
unsigned long ratio = hits * 10000 / (hits + misses);
|
||||
grub_printf ("(%u.%u%%)\n", ratio / 100, ratio % 100);
|
||||
}
|
||||
else
|
||||
grub_printf ("(N/A)\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* dump ADDRESS [SIZE] */
|
||||
static grub_err_t
|
||||
grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)),
|
||||
|
@ -163,7 +145,7 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)),
|
|||
{
|
||||
grub_dl_t mod;
|
||||
|
||||
grub_printf ("Name\tRef Count\tDependencies\n");
|
||||
grub_printf_ (N_("Name\tRef Count\tDependencies\n"));
|
||||
FOR_DL_MODULES (mod)
|
||||
{
|
||||
grub_dl_dep_t dep;
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include <grub/dl.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/cs5536.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
@ -36,43 +39,44 @@ grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
if (!grub_cs5536_find (&dev))
|
||||
{
|
||||
grub_printf ("No CS5536 found\n");
|
||||
grub_puts_ (N_("No CS5536 found"));
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
grub_printf ("CS5536 at %d:%d.%d\n", grub_pci_get_bus (dev),
|
||||
grub_pci_get_device (dev), grub_pci_get_function (dev));
|
||||
grub_printf_ (N_("CS5536 at %d:%d.%d\n"), grub_pci_get_bus (dev),
|
||||
grub_pci_get_device (dev), grub_pci_get_function (dev));
|
||||
|
||||
err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
grub_printf ("SMB base = 0x%x\n", smbbase);
|
||||
grub_printf_ (N_("SMB base = 0x%x\n"), smbbase);
|
||||
|
||||
for (i = GRUB_SMB_RAM_START_ADDR;
|
||||
i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++)
|
||||
{
|
||||
struct grub_smbus_spd spd;
|
||||
grub_memset (&spd, 0, sizeof (spd));
|
||||
grub_printf ("Device %d\n", i);
|
||||
grub_printf_ (N_("Device %d\n"), i);
|
||||
err = grub_cs5536_read_spd (smbbase, i, &spd);
|
||||
if (err)
|
||||
{
|
||||
grub_print_error ();
|
||||
continue;
|
||||
}
|
||||
grub_printf ("Written SPD bytes: %d B.\n", spd.written_size);
|
||||
grub_printf ("Total flash size: %d B.\n", 1 << spd.log_total_flash_size);
|
||||
grub_printf_ (N_("Written SPD bytes: %d B.\n"), spd.written_size);
|
||||
grub_printf_ (N_("Total flash size: %d B.\n"),
|
||||
1 << spd.log_total_flash_size);
|
||||
if (spd.memory_type == GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2)
|
||||
{
|
||||
char str[sizeof (spd.ddr2.part_number) + 1];
|
||||
grub_printf ("Memory type: DDR2.\n");
|
||||
grub_puts_ (N_("Memory type: DDR2."));
|
||||
grub_memcpy (str, spd.ddr2.part_number,
|
||||
sizeof (spd.ddr2.part_number));
|
||||
str[sizeof (spd.ddr2.part_number)] = 0;
|
||||
grub_printf ("Part no: %s.\n", str);
|
||||
grub_printf_ (N_("Part no: %s.\n"), str);
|
||||
}
|
||||
else
|
||||
grub_printf ("Memory type: Unknown.\n");
|
||||
grub_puts_ (N_("Memory type: Unknown."));
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -83,7 +87,7 @@ static grub_command_t cmd;
|
|||
GRUB_MOD_INIT(lsspd)
|
||||
{
|
||||
cmd = grub_register_command ("lsspd", grub_cmd_lsspd, 0,
|
||||
"Print Memory information.");
|
||||
N_("Print Memory information."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(lsspd)
|
|
@ -31,13 +31,15 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv2+");
|
||||
|
||||
static struct grub_parttool *parts = 0;
|
||||
static int curhandle = 0;
|
||||
static grub_dl_t mymod;
|
||||
static char helpmsg[] =
|
||||
"Perform COMMANDS on partition.\n"
|
||||
"Use \"parttool PARTITION help\" for the list "
|
||||
"of available commands.";
|
||||
N_("Perform COMMANDS on partition.\n"
|
||||
"Use \"parttool PARTITION help\" for the list "
|
||||
"of available commands.");
|
||||
|
||||
int
|
||||
grub_parttool_register(const char *part_name,
|
||||
|
@ -126,7 +128,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
|
|||
break;
|
||||
|
||||
case GRUB_PARTTOOL_ARG_VAL:
|
||||
grub_printf ("=VAL");
|
||||
grub_xputs (_("=VAL"));
|
||||
spacing -= 4;
|
||||
break;
|
||||
|
||||
|
@ -135,18 +137,18 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
|
|||
}
|
||||
while (spacing-- > 0)
|
||||
grub_printf (" ");
|
||||
grub_printf ("%s\n", curarg->desc);
|
||||
grub_puts_ (curarg->desc);
|
||||
}
|
||||
}
|
||||
if (! found)
|
||||
grub_printf ("Sorry no parttool is available for %s\n",
|
||||
grub_printf_ (N_("Sorry no parttool is available for %s\n"),
|
||||
dev->disk->partition->partmap->name);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
grub_printf ("%s\n", helpmsg);
|
||||
grub_puts_ (helpmsg);
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments");
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <grub/dl.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_dl_t my_mod;
|
||||
|
||||
static grub_err_t
|
||||
|
@ -40,26 +42,22 @@ check_password (const char *user, const char *entered,
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
grub_err_t
|
||||
grub_normal_set_password (const char *user, const char *password)
|
||||
{
|
||||
grub_err_t err;
|
||||
char *pass;
|
||||
int copylen;
|
||||
|
||||
if (argc != 2)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments expected");
|
||||
|
||||
pass = grub_zalloc (GRUB_AUTH_MAX_PASSLEN);
|
||||
if (!pass)
|
||||
return grub_errno;
|
||||
copylen = grub_strlen (args[1]);
|
||||
copylen = grub_strlen (password);
|
||||
if (copylen >= GRUB_AUTH_MAX_PASSLEN)
|
||||
copylen = GRUB_AUTH_MAX_PASSLEN - 1;
|
||||
grub_memcpy (pass, args[1], copylen);
|
||||
grub_memcpy (pass, password, copylen);
|
||||
|
||||
err = grub_auth_register_authentication (args[0], check_password, pass);
|
||||
err = grub_auth_register_authentication (user, check_password, pass);
|
||||
if (err)
|
||||
{
|
||||
grub_free (pass);
|
||||
|
@ -69,6 +67,15 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
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_normal_set_password (args[0], args[1]);
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(password)
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <grub/dl.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_dl_t my_mod;
|
||||
|
||||
struct pbkdf2_password
|
||||
|
|
|
@ -32,9 +32,11 @@
|
|||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"set", 's', GRUB_ARG_OPTION_OPTIONAL,
|
||||
{"set", 's', 0,
|
||||
N_("Set a variable to return value."), "VAR", ARG_TYPE_STRING},
|
||||
{"driver", 'd', 0, N_("Determine driver."), 0, 0},
|
||||
{"partmap", 'p', 0, N_("Determine partition map type."), 0, 0},
|
||||
|
@ -72,7 +74,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
{
|
||||
const char *val = "none";
|
||||
if (dev->net)
|
||||
val = dev->net->dev->name;
|
||||
val = dev->net->protocol->name;
|
||||
if (dev->disk)
|
||||
val = dev->disk->dev->name;
|
||||
if (state[0].set)
|
||||
|
@ -134,7 +136,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
|
|||
return err;
|
||||
if (! label)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"uuid for this FS isn't supported yet");
|
||||
"label for this FS isn't supported yet");
|
||||
|
||||
if (state[0].set)
|
||||
grub_env_set (state[0].arg, label);
|
||||
|
@ -150,7 +152,7 @@ static grub_extcmd_t cmd;
|
|||
|
||||
GRUB_MOD_INIT (probe)
|
||||
{
|
||||
cmd = grub_register_extcmd ("probe", grub_cmd_probe, 0, N_("[DEVICE]"),
|
||||
cmd = grub_register_extcmd ("probe", grub_cmd_probe, 0, N_("DEVICE"),
|
||||
N_("Retrieve device info."), options);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static char *
|
||||
grub_getline (void)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include <grub/misc.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <grub/script_sh.h>
|
||||
#include <regex.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{ "set", 's', GRUB_ARG_OPTION_REPEATABLE,
|
||||
|
@ -87,7 +89,6 @@ set_matches (char **varnames, char *str, grub_size_t nmatches,
|
|||
static grub_err_t
|
||||
grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
int argn = 0;
|
||||
regex_t regex;
|
||||
int ret;
|
||||
grub_size_t s;
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include <grub/disk.h>
|
||||
#include <grub/partition.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
void
|
||||
FUNC_NAME (const char *key, const char *var, int no_floppy,
|
||||
char **hints, unsigned nhints)
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <grub/search.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"file", 'f', 0, N_("Search devices by a file."), 0, 0},
|
||||
|
@ -90,7 +92,7 @@ static grub_extcmd_t cmd;
|
|||
GRUB_MOD_INIT(search)
|
||||
{
|
||||
cmd =
|
||||
grub_register_extcmd ("search", grub_cmd_search, 0,
|
||||
grub_register_extcmd ("search", grub_cmd_search, GRUB_COMMAND_FLAG_EXTRACTOR,
|
||||
N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]"
|
||||
" NAME"),
|
||||
N_("Search devices by file, filesystem label"
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <grub/mm.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
struct pci_register
|
||||
{
|
||||
const char *name;
|
||||
|
@ -32,7 +34,7 @@ struct pci_register
|
|||
unsigned size;
|
||||
};
|
||||
|
||||
struct pci_register pci_registers[] =
|
||||
static struct pci_register pci_registers[] =
|
||||
{
|
||||
{"VENDOR_ID", GRUB_PCI_REG_VENDOR , 2},
|
||||
{"DEVICE_ID", GRUB_PCI_REG_DEVICE , 2},
|
||||
|
@ -64,12 +66,12 @@ struct pci_register pci_registers[] =
|
|||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{0, 'd', 0, "Select device by vendor and device IDs.",
|
||||
"[vendor]:[device]", ARG_TYPE_STRING},
|
||||
{0, 's', 0, "Select device by its position on the bus.",
|
||||
"[bus]:[slot][.func]", ARG_TYPE_STRING},
|
||||
{0, 'v', 0, "Save read value into variable VARNAME.",
|
||||
"VARNAME", ARG_TYPE_STRING},
|
||||
{0, 'd', 0, N_("Select device by vendor and device IDs."),
|
||||
N_("[vendor]:[device]"), ARG_TYPE_STRING},
|
||||
{0, 's', 0, N_("Select device by its position on the bus."),
|
||||
N_("[bus]:[slot][.func]"), ARG_TYPE_STRING},
|
||||
{0, 'v', 0, N_("Save read value into variable VARNAME."),
|
||||
N_("VARNAME"), ARG_TYPE_STRING},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -126,7 +128,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid)
|
|||
|
||||
if (!write_mask)
|
||||
{
|
||||
grub_printf ("Register %x of %d:%d.%d is %x\n", regaddr,
|
||||
grub_printf (N_("Register %x of %d:%d.%d is %x\n"), regaddr,
|
||||
grub_pci_get_bus (dev),
|
||||
grub_pci_get_device (dev),
|
||||
grub_pci_get_function (dev),
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"verbose", 'v', 0, N_("Verbose countdown."), 0, 0},
|
||||
|
@ -52,8 +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_TERM_ASCII_CHAR (grub_getkey ()) == GRUB_TERM_ESC)
|
||||
if (grub_checkkey () >= 0 && grub_getkey () == GRUB_TERM_ESC)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include <grub/i18n.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
struct grub_term_autoload *grub_term_input_autoload = NULL;
|
||||
struct grub_term_autoload *grub_term_output_autoload = NULL;
|
||||
|
||||
|
@ -210,11 +212,11 @@ grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)),
|
|||
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, init);
|
||||
(void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, fini);
|
||||
return handle_command (argc, args,
|
||||
(struct abstract_terminal **) &grub_term_inputs,
|
||||
(struct abstract_terminal **) &grub_term_inputs_disabled,
|
||||
grub_term_input_autoload,
|
||||
N_ ("Active input terminals:"),
|
||||
N_ ("Available input terminals:"));
|
||||
(struct abstract_terminal **) (void *) &grub_term_inputs,
|
||||
(struct abstract_terminal **) (void *) &grub_term_inputs_disabled,
|
||||
grub_term_input_autoload,
|
||||
N_ ("Active input terminals:"),
|
||||
N_ ("Available input terminals:"));
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
@ -225,11 +227,12 @@ grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)),
|
|||
(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);
|
||||
return handle_command (argc, args, (struct abstract_terminal **) &grub_term_outputs,
|
||||
(struct abstract_terminal **) &grub_term_outputs_disabled,
|
||||
grub_term_output_autoload,
|
||||
N_ ("Active output terminals:"),
|
||||
N_ ("Available output terminals:"));
|
||||
return handle_command (argc, args,
|
||||
(struct abstract_terminal **) (void *) &grub_term_outputs,
|
||||
(struct abstract_terminal **) (void *) &grub_term_outputs_disabled,
|
||||
grub_term_output_autoload,
|
||||
N_ ("Active output terminals:"),
|
||||
N_ ("Available output terminals:"));
|
||||
}
|
||||
|
||||
static grub_command_t cmd_terminal_input, cmd_terminal_output;
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/* A simple implementation for signed numbers. */
|
||||
static int
|
||||
grub_strtosl (char *arg, char **end, int base)
|
||||
|
@ -423,8 +425,10 @@ GRUB_MOD_INIT(test)
|
|||
{
|
||||
cmd_1 = grub_register_command ("[", grub_cmd_test,
|
||||
N_("EXPRESSION ]"), N_("Evaluate an expression."));
|
||||
cmd_1->flags |= GRUB_COMMAND_FLAG_EXTRACTOR;
|
||||
cmd_2 = grub_register_command ("test", grub_cmd_test,
|
||||
N_("EXPRESSION"), N_("Evaluate an expression."));
|
||||
cmd_2->flags |= GRUB_COMMAND_FLAG_EXTRACTOR;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(test)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* minicmd.c - commands for the rescue mode */
|
||||
/* testload.c - load the same file in multiple ways */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2005,2006,2007,2009,2010 Free Software Foundation, Inc.
|
||||
|
@ -29,6 +29,8 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
|
|
68
grub-core/commands/time.c
Normal file
68
grub-core/commands/time.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/* echo.c - Command to display a line of text */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/time.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_time (grub_command_t ctxt __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_command_t cmd;
|
||||
grub_uint32_t start;
|
||||
grub_uint32_t end;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "command expected");
|
||||
|
||||
cmd = grub_command_find (args[0]);
|
||||
|
||||
if (!cmd)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_COMMAND, "Unknown command `%s'\n",
|
||||
args[0]);
|
||||
|
||||
start = grub_get_time_ms ();
|
||||
(cmd->func) (cmd, argc - 1, &args[1]);
|
||||
end = grub_get_time_ms ();
|
||||
|
||||
grub_printf_ (N_("Elapsed time: %d.%03d seconds \n"), (end - start) / 1000,
|
||||
(end - start) % 1000);
|
||||
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_command_t cmd;
|
||||
|
||||
GRUB_MOD_INIT(time)
|
||||
{
|
||||
cmd = grub_register_command ("time", grub_cmd_time,
|
||||
N_("COMMAND [ARGS]"),
|
||||
N_("Measure time used by COMMAND"));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(time)
|
||||
{
|
||||
grub_unregister_command (cmd);
|
||||
}
|
|
@ -21,6 +21,8 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_true (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static const char *usb_classes[] =
|
||||
{
|
||||
"Unknown",
|
||||
|
|
|
@ -25,58 +25,121 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static unsigned height, width, depth;
|
||||
static struct grub_video_mode_info *current_mode;
|
||||
|
||||
static int
|
||||
hook (const struct grub_video_mode_info *info)
|
||||
{
|
||||
if (height && width && (info->width != width || info->height != height))
|
||||
return 0;
|
||||
|
||||
if (depth && info->bpp != depth)
|
||||
return 0;
|
||||
|
||||
if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID)
|
||||
grub_printf (" ");
|
||||
else
|
||||
grub_printf (" 0x%03x ", info->mode_number);
|
||||
{
|
||||
if (current_mode && info->mode_number == current_mode->mode_number)
|
||||
grub_printf ("*");
|
||||
else
|
||||
grub_printf (" ");
|
||||
grub_printf (" 0x%03x ", info->mode_number);
|
||||
}
|
||||
grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp);
|
||||
|
||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
|
||||
grub_printf ("Text-only ");
|
||||
grub_xputs (_("Text-only "));
|
||||
/* Show mask and position details for direct color modes. */
|
||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB)
|
||||
grub_printf ("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d",
|
||||
info->red_mask_size,
|
||||
info->green_mask_size,
|
||||
info->blue_mask_size,
|
||||
info->reserved_mask_size,
|
||||
info->red_field_pos,
|
||||
info->green_field_pos,
|
||||
info->blue_field_pos,
|
||||
info->reserved_field_pos);
|
||||
grub_printf_ (N_("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d"),
|
||||
info->red_mask_size,
|
||||
info->green_mask_size,
|
||||
info->blue_mask_size,
|
||||
info->reserved_mask_size,
|
||||
info->red_field_pos,
|
||||
info->green_field_pos,
|
||||
info->blue_field_pos,
|
||||
info->reserved_field_pos);
|
||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
|
||||
grub_printf ("Packed ");
|
||||
grub_xputs (_("Packed "));
|
||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV)
|
||||
grub_printf ("YUV ");
|
||||
grub_xputs (_("YUV "));
|
||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR)
|
||||
grub_printf ("Planar ");
|
||||
grub_xputs (_("Planar "));
|
||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES)
|
||||
grub_printf ("Hercules ");
|
||||
grub_xputs (_("Hercules "));
|
||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA)
|
||||
grub_printf ("CGA ");
|
||||
grub_xputs (_("CGA "));
|
||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_NONCHAIN4)
|
||||
grub_printf ("Non-chain 4 ");
|
||||
grub_xputs (_("Non-chain 4 "));
|
||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP)
|
||||
grub_printf ("Monochrome ");
|
||||
grub_xputs (_("Monochrome "));
|
||||
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN)
|
||||
grub_printf ("Unknown ");
|
||||
grub_xputs (_("Unknown "));
|
||||
|
||||
grub_printf ("\n");
|
||||
grub_xputs ("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
print_edid (struct grub_video_edid_info *edid_info)
|
||||
{
|
||||
unsigned int edid_width, edid_height;
|
||||
|
||||
if (grub_video_edid_checksum (edid_info))
|
||||
{
|
||||
grub_puts_ (N_(" EDID checksum invalid"));
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
grub_printf_ (N_(" EDID version: %u.%u\n"),
|
||||
edid_info->version, edid_info->revision);
|
||||
if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height)
|
||||
== GRUB_ERR_NONE)
|
||||
grub_printf_ (N_(" Preferred mode: %ux%u\n"), edid_width, edid_height);
|
||||
else
|
||||
{
|
||||
grub_printf_ (N_(" No preferred mode available\n"));
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc __attribute__ ((unused)),
|
||||
char **args __attribute__ ((unused)))
|
||||
int argc, char **args)
|
||||
{
|
||||
grub_video_adapter_t adapter;
|
||||
grub_video_driver_id_t id;
|
||||
|
||||
height = width = depth = 0;
|
||||
if (argc)
|
||||
{
|
||||
char *ptr;
|
||||
ptr = args[0];
|
||||
width = grub_strtoul (ptr, &ptr, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (*ptr != 'x')
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid mode specification");
|
||||
ptr++;
|
||||
height = grub_strtoul (ptr, &ptr, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (*ptr == 'x')
|
||||
{
|
||||
ptr++;
|
||||
depth = grub_strtoul (ptr, &ptr, 0);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
if (grub_strcmp (cmd->name, "vbeinfo") == 0)
|
||||
grub_dl_load ("vbe");
|
||||
|
@ -84,25 +147,38 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
id = grub_video_get_driver_id ();
|
||||
|
||||
grub_printf ("List of supported video modes:\n");
|
||||
grub_printf ("Legend: P=Packed pixel, D=Direct color, "
|
||||
"mask/pos=R/G/B/reserved\n");
|
||||
grub_puts_ (N_("List of supported video modes:"));
|
||||
grub_puts_ (N_("Legend: P=Packed pixel, D=Direct color, "
|
||||
"mask/pos=R/G/B/reserved"));
|
||||
|
||||
FOR_VIDEO_ADAPTERS (adapter)
|
||||
{
|
||||
grub_printf ("Adapter '%s':\n", adapter->name);
|
||||
struct grub_video_mode_info info;
|
||||
struct grub_video_edid_info edid_info;
|
||||
|
||||
grub_printf_ (N_("Adapter '%s':\n"), adapter->name);
|
||||
|
||||
if (!adapter->iterate)
|
||||
{
|
||||
grub_printf (" No info available\n");
|
||||
grub_puts_ (N_(" No info available"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (adapter->id != id)
|
||||
current_mode = NULL;
|
||||
|
||||
if (adapter->id == id)
|
||||
{
|
||||
if (grub_video_get_info (&info) == GRUB_ERR_NONE)
|
||||
current_mode = &info;
|
||||
else
|
||||
/* Don't worry about errors. */
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (adapter->init ())
|
||||
{
|
||||
grub_printf (" Failed\n");
|
||||
grub_puts_ (N_(" Failed"));
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
continue;
|
||||
}
|
||||
|
@ -113,6 +189,13 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
|
|||
|
||||
adapter->iterate (hook);
|
||||
|
||||
if (adapter->get_edid && adapter->get_edid (&edid_info) == GRUB_ERR_NONE)
|
||||
print_edid (&edid_info);
|
||||
else
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
|
||||
current_mode = NULL;
|
||||
|
||||
if (adapter->id != id)
|
||||
{
|
||||
if (adapter->fini ())
|
||||
|
@ -132,11 +215,16 @@ static grub_command_t cmd_vbe;
|
|||
|
||||
GRUB_MOD_INIT(videoinfo)
|
||||
{
|
||||
cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, 0,
|
||||
N_("List available video modes."));
|
||||
cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, N_("[WxH[xD]]"),
|
||||
N_("List available video modes. If "
|
||||
"resolution is given show only modes"
|
||||
" matching it."));
|
||||
#ifdef GRUB_MACHINE_PCBIOS
|
||||
cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo, 0,
|
||||
N_("List available video modes."));
|
||||
cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo,
|
||||
N_("[WxH[xD]]"),
|
||||
N_("List available video modes. If "
|
||||
"resolution is given show only modes"
|
||||
" matching it."));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <grub/gfxmenu_view.h>
|
||||
#include <grub/env.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
|
|
|
@ -139,6 +139,7 @@ make_regex (const char *start, const char *end, regex_t *regexp)
|
|||
case '.':
|
||||
case '(':
|
||||
case ')':
|
||||
case '@':
|
||||
buffer[i++] = '\\';
|
||||
buffer[i++] = ch;
|
||||
break;
|
||||
|
@ -255,8 +256,7 @@ match_devices (const regex_t *regexp, int noparts)
|
|||
for (i = 0; devs && devs[i]; i++)
|
||||
grub_free (devs[i]);
|
||||
|
||||
if (devs)
|
||||
grub_free (devs);
|
||||
grub_free (devs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -266,7 +266,6 @@ match_files (const char *prefix, const char *suffix, const char *end,
|
|||
const regex_t *regexp)
|
||||
{
|
||||
int i;
|
||||
int error;
|
||||
char **files;
|
||||
unsigned nfile;
|
||||
char *dir;
|
||||
|
@ -289,6 +288,8 @@ match_files (const char *prefix, const char *suffix, const char *end,
|
|||
if (regexec (regexp, name, 0, 0, 0))
|
||||
return 0;
|
||||
|
||||
grub_dprintf ("expand", "matched\n");
|
||||
|
||||
buffer = grub_xasprintf ("%s%s", dir, name);
|
||||
if (! buffer)
|
||||
return 1;
|
||||
|
@ -341,20 +342,17 @@ match_files (const char *prefix, const char *suffix, const char *end,
|
|||
|
||||
fail:
|
||||
|
||||
if (dir)
|
||||
grub_free (dir);
|
||||
grub_free (dir);
|
||||
|
||||
for (i = 0; files && files[i]; i++)
|
||||
grub_free (files[i]);
|
||||
|
||||
if (files)
|
||||
grub_free (files);
|
||||
grub_free (files);
|
||||
|
||||
if (dev)
|
||||
grub_device_close (dev);
|
||||
|
||||
if (device_name)
|
||||
grub_free (device_name);
|
||||
grub_free (device_name);
|
||||
|
||||
grub_error_pop ();
|
||||
return 0;
|
||||
|
@ -424,8 +422,6 @@ wildcard_expand (const char *s, char ***strs)
|
|||
while (*start)
|
||||
{
|
||||
split_path (start, &noregexop, ®exop);
|
||||
if (noregexop >= regexop) /* no more wildcards */
|
||||
break;
|
||||
|
||||
if (make_regex (noregexop, regexop, ®exp))
|
||||
goto fail;
|
||||
|
@ -440,9 +436,7 @@ wildcard_expand (const char *s, char ***strs)
|
|||
|
||||
else if (*start == '/') /* no device part */
|
||||
{
|
||||
char **r;
|
||||
unsigned n;
|
||||
char *root;
|
||||
const char *root;
|
||||
char *prefix;
|
||||
|
||||
root = grub_env_get ("root");
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include <grub/i18n.h>
|
||||
#include <grub/crypto.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
/* This prefix is used by xnu and boot-132 to hash
|
||||
together with volume serial. */
|
||||
static grub_uint8_t hash_prefix[16]
|
||||
|
@ -49,10 +51,18 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
|
|||
char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
|
||||
char *ptr;
|
||||
grub_uint8_t ctx[GRUB_MD_MD5->contextsize];
|
||||
int low = 0;
|
||||
|
||||
if (argc < 1)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required");
|
||||
|
||||
if (argc > 1 && grub_strcmp (args[0], "-l") == 0)
|
||||
{
|
||||
low = 1;
|
||||
argc--;
|
||||
args++;
|
||||
}
|
||||
|
||||
serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16));
|
||||
|
||||
GRUB_MD_MD5->init (&ctx);
|
||||
|
@ -73,10 +83,11 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
|
|||
(unsigned int) xnu_uuid[10], (unsigned int) xnu_uuid[11],
|
||||
(unsigned int) xnu_uuid[12], (unsigned int) xnu_uuid[13],
|
||||
(unsigned int) xnu_uuid[14], (unsigned int) xnu_uuid[15]);
|
||||
for (ptr = uuid_string; *ptr; ptr++)
|
||||
*ptr = grub_toupper (*ptr);
|
||||
if (!low)
|
||||
for (ptr = uuid_string; *ptr; ptr++)
|
||||
*ptr = grub_toupper (*ptr);
|
||||
if (argc == 1)
|
||||
grub_printf ("%s", uuid_string);
|
||||
grub_printf ("%s\n", uuid_string);
|
||||
if (argc > 1)
|
||||
grub_env_set (args[1], uuid_string);
|
||||
|
||||
|
@ -89,9 +100,10 @@ static grub_command_t cmd;
|
|||
GRUB_MOD_INIT (xnu_uuid)
|
||||
{
|
||||
cmd = grub_register_command ("xnu_uuid", grub_cmd_xnu_uuid,
|
||||
N_("GRUBUUID [VARNAME]"),
|
||||
N_("[-l] GRUBUUID [VARNAME]"),
|
||||
N_("Transform 64-bit UUID to format "
|
||||
"suitable for XNU."));
|
||||
"suitable for XNU. If -l is given keep "
|
||||
"it lowercase as done by blkid."));
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (xnu_uuid)
|
||||
|
|
89
grub-core/disk/AFSplitter.c
Normal file
89
grub-core/disk/AFSplitter.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* AFsplitter - Anti forensic information splitter
|
||||
* Copyright 2004, Clemens Fruhwirth <clemens@endorphin.org>
|
||||
*
|
||||
* AFsplitter diffuses information over a large stripe of data,
|
||||
* therefor supporting secure data destruction.
|
||||
*
|
||||
* This program is grub_free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the grub_free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the grub_free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <grub/crypto.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
|
||||
gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src,
|
||||
grub_uint8_t * dst, grub_size_t blocksize,
|
||||
grub_size_t blocknumbers);
|
||||
|
||||
static void
|
||||
diffuse (const gcry_md_spec_t * hash, grub_uint8_t * src,
|
||||
grub_uint8_t * dst, grub_size_t size)
|
||||
{
|
||||
grub_size_t i;
|
||||
grub_uint32_t IV; /* host byte order independend hash IV */
|
||||
|
||||
grub_size_t fullblocks = size / hash->mdlen;
|
||||
int padding = size % hash->mdlen;
|
||||
grub_uint8_t final[hash->mdlen];
|
||||
grub_uint8_t temp[sizeof (IV) + hash->mdlen];
|
||||
|
||||
/* hash block the whole data set with different IVs to produce
|
||||
* more than just a single data block
|
||||
*/
|
||||
for (i = 0; i < fullblocks; i++)
|
||||
{
|
||||
IV = grub_cpu_to_be32 (i);
|
||||
grub_memcpy (temp, &IV, sizeof (IV));
|
||||
grub_memcpy (temp + sizeof (IV), src + hash->mdlen * i, hash->mdlen);
|
||||
grub_crypto_hash (hash, dst + hash->mdlen * i, temp,
|
||||
sizeof (IV) + hash->mdlen);
|
||||
}
|
||||
|
||||
if (padding)
|
||||
{
|
||||
IV = grub_cpu_to_be32 (i);
|
||||
grub_memcpy (temp, &IV, sizeof (IV));
|
||||
grub_memcpy (temp + sizeof (IV), src + hash->mdlen * i, padding);
|
||||
grub_crypto_hash (hash, final, temp, sizeof (IV) + padding);
|
||||
grub_memcpy (dst + hash->mdlen * i, final, padding);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the splitted master key stored on disk into the original key
|
||||
*/
|
||||
gcry_err_code_t
|
||||
AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst,
|
||||
grub_size_t blocksize, grub_size_t blocknumbers)
|
||||
{
|
||||
grub_size_t i;
|
||||
grub_uint8_t *bufblock;
|
||||
|
||||
bufblock = grub_zalloc (blocksize);
|
||||
if (bufblock == NULL)
|
||||
return GPG_ERR_OUT_OF_MEMORY;
|
||||
|
||||
grub_memset (bufblock, 0, blocksize);
|
||||
for (i = 0; i < blocknumbers - 1; i++)
|
||||
{
|
||||
grub_crypto_xor (bufblock, src + (blocksize * i), bufblock, blocksize);
|
||||
diffuse (hash, bufblock, bufblock, blocksize);
|
||||
}
|
||||
grub_crypto_xor (dst, src + (i * blocksize), bufblock, blocksize);
|
||||
|
||||
grub_free (bufblock);
|
||||
return GPG_ERR_NO_ERROR;
|
||||
}
|
738
grub-core/disk/ahci.c
Normal file
738
grub-core/disk/ahci.c
Normal file
|
@ -0,0 +1,738 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/dl.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/pci.h>
|
||||
#include <grub/ata.h>
|
||||
#include <grub/scsi.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/list.h>
|
||||
#include <grub/loader.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
struct grub_ahci_cmd_head
|
||||
{
|
||||
grub_uint32_t config;
|
||||
grub_uint32_t transfered;
|
||||
grub_uint64_t command_table_base;
|
||||
grub_uint32_t unused[4];
|
||||
};
|
||||
|
||||
struct grub_ahci_prdt_entry
|
||||
{
|
||||
grub_uint64_t data_base;
|
||||
grub_uint32_t unused;
|
||||
grub_uint32_t size;
|
||||
};
|
||||
|
||||
struct grub_ahci_cmd_table
|
||||
{
|
||||
grub_uint8_t cfis[0x40];
|
||||
grub_uint8_t command[0x10];
|
||||
grub_uint8_t reserved[0x30];
|
||||
struct grub_ahci_prdt_entry prdt[1];
|
||||
};
|
||||
|
||||
struct grub_ahci_hba_port
|
||||
{
|
||||
grub_uint64_t command_list_base;
|
||||
grub_uint64_t fis_base;
|
||||
grub_uint32_t intstatus;
|
||||
grub_uint32_t inten;
|
||||
grub_uint32_t command;
|
||||
grub_uint32_t unused1;
|
||||
grub_uint32_t task_file_data;
|
||||
grub_uint32_t sig;
|
||||
grub_uint32_t status;
|
||||
grub_uint32_t unused2;
|
||||
grub_uint32_t sata_error;
|
||||
grub_uint32_t sata_active;
|
||||
grub_uint32_t command_issue;
|
||||
grub_uint32_t unused3;
|
||||
grub_uint32_t fbs;
|
||||
grub_uint32_t unused4[15];
|
||||
};
|
||||
|
||||
enum grub_ahci_hba_port_command
|
||||
{
|
||||
GRUB_AHCI_HBA_PORT_CMD_ST = 0x01,
|
||||
GRUB_AHCI_HBA_PORT_CMD_FRE = 0x10,
|
||||
GRUB_AHCI_HBA_PORT_CMD_CR = 0x8000,
|
||||
GRUB_AHCI_HBA_PORT_CMD_FR = 0x4000,
|
||||
};
|
||||
|
||||
struct grub_ahci_hba
|
||||
{
|
||||
grub_uint32_t cap;
|
||||
grub_uint32_t global_control;
|
||||
grub_uint32_t intr_status;
|
||||
grub_uint32_t ports_implemented;
|
||||
grub_uint32_t unused1[6];
|
||||
grub_uint32_t bios_handoff;
|
||||
grub_uint32_t unused2[53];
|
||||
struct grub_ahci_hba_port ports[32];
|
||||
};
|
||||
|
||||
struct grub_ahci_received_fis
|
||||
{
|
||||
char raw[4096];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_AHCI_HBA_CAP_NPORTS_MASK = 0x1f
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_AHCI_HBA_GLOBAL_CONTROL_RESET = 0x00000001,
|
||||
GRUB_AHCI_HBA_GLOBAL_CONTROL_INTR_EN = 0x00000002,
|
||||
GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN = 0x80000000,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED = 1,
|
||||
GRUB_AHCI_BIOS_HANDOFF_OS_OWNED = 2,
|
||||
GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED = 8,
|
||||
GRUB_AHCI_BIOS_HANDOFF_RWC = 8
|
||||
};
|
||||
|
||||
|
||||
struct grub_ahci_device
|
||||
{
|
||||
struct grub_ahci_device *next;
|
||||
volatile struct grub_ahci_hba *hba;
|
||||
int port;
|
||||
int num;
|
||||
struct grub_pci_dma_chunk *command_list_chunk;
|
||||
volatile struct grub_ahci_cmd_head *command_list;
|
||||
struct grub_pci_dma_chunk *command_table_chunk;
|
||||
volatile struct grub_ahci_cmd_table *command_table;
|
||||
struct grub_pci_dma_chunk *rfis;
|
||||
int present;
|
||||
};
|
||||
|
||||
static grub_err_t
|
||||
grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||
struct grub_disk_ata_pass_through_parms *parms,
|
||||
int spinup);
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_AHCI_CONFIG_READ = 0,
|
||||
GRUB_AHCI_CONFIG_CFIS_LENGTH_MASK = 0x1f,
|
||||
GRUB_AHCI_CONFIG_ATAPI = 0x20,
|
||||
GRUB_AHCI_CONFIG_WRITE = 0x40,
|
||||
GRUB_AHCI_CONFIG_PREFETCH = 0x80,
|
||||
GRUB_AHCI_CONFIG_RESET = 0x100,
|
||||
GRUB_AHCI_CONFIG_BIST = 0x200,
|
||||
GRUB_AHCI_CONFIG_CLEAR_R_OK = 0x400,
|
||||
GRUB_AHCI_CONFIG_PMP_MASK = 0xf000,
|
||||
GRUB_AHCI_CONFIG_PRDT_LENGTH_MASK = 0xffff0000,
|
||||
};
|
||||
#define GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT 0
|
||||
#define GRUB_AHCI_CONFIG_PMP_SHIFT 12
|
||||
#define GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT 16
|
||||
#define GRUB_AHCI_INTERRUPT_ON_COMPLETE 0x80000000
|
||||
|
||||
#define GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH 0x200000
|
||||
|
||||
static struct grub_ahci_device *grub_ahci_devices;
|
||||
static int numdevs;
|
||||
|
||||
static int
|
||||
init_port (struct grub_ahci_device *dev)
|
||||
{
|
||||
struct grub_pci_dma_chunk *command_list;
|
||||
struct grub_pci_dma_chunk *command_table;
|
||||
grub_uint64_t endtime;
|
||||
|
||||
command_list = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head));
|
||||
if (!command_list)
|
||||
return 1;
|
||||
|
||||
command_table = grub_memalign_dma32 (1024,
|
||||
sizeof (struct grub_ahci_cmd_table));
|
||||
if (!command_table)
|
||||
{
|
||||
grub_dma_free (command_list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_dprintf ("ahci", "found device ahci%d (port %d)\n", dev->num, dev->port);
|
||||
|
||||
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
|
||||
endtime = grub_get_time_ms () + 1000;
|
||||
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
grub_dprintf ("ahci", "couldn't stop FR\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
|
||||
endtime = grub_get_time_ms () + 1000;
|
||||
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
grub_dprintf ("ahci", "couldn't stop CR\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev->hba->ports[dev->port].fbs = 2;
|
||||
|
||||
dev->rfis = grub_memalign_dma32 (4096,
|
||||
sizeof (struct grub_ahci_received_fis));
|
||||
grub_memset ((char *) grub_dma_get_virt (dev->rfis), 0,
|
||||
sizeof (struct grub_ahci_received_fis));
|
||||
dev->hba->ports[dev->port].fis_base = grub_dma_get_phys (dev->rfis);
|
||||
dev->hba->ports[dev->port].command_list_base
|
||||
= grub_dma_get_phys (command_list);
|
||||
dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_FRE;
|
||||
while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
grub_dprintf ("ahci", "couldn't start FR\n");
|
||||
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
|
||||
goto out;
|
||||
}
|
||||
dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST;
|
||||
while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
grub_dprintf ("ahci", "couldn't start CR\n");
|
||||
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_CR;
|
||||
goto out_stop_fr;
|
||||
}
|
||||
|
||||
dev->hba->ports[dev->port].command
|
||||
= (dev->hba->ports[dev->port].command & 0x0fffffff) | (1 << 28) | 2 | 4;
|
||||
|
||||
dev->command_list_chunk = command_list;
|
||||
dev->command_list = grub_dma_get_virt (command_list);
|
||||
dev->command_table_chunk = command_table;
|
||||
dev->command_table = grub_dma_get_virt (command_table);
|
||||
dev->command_list->command_table_base
|
||||
= grub_dma_get_phys (command_table);
|
||||
|
||||
return 0;
|
||||
out_stop_fr:
|
||||
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
|
||||
endtime = grub_get_time_ms () + 1000;
|
||||
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
grub_dprintf ("ahci", "couldn't stop FR\n");
|
||||
break;
|
||||
}
|
||||
out:
|
||||
grub_dma_free (command_list);
|
||||
grub_dma_free (command_table);
|
||||
grub_dma_free (dev->rfis);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int NESTED_FUNC_ATTR
|
||||
grub_ahci_pciinit (grub_pci_device_t dev,
|
||||
grub_pci_id_t pciid __attribute__ ((unused)))
|
||||
{
|
||||
grub_pci_address_t addr;
|
||||
grub_uint32_t class;
|
||||
grub_uint32_t bar;
|
||||
unsigned i, nports;
|
||||
volatile struct grub_ahci_hba *hba;
|
||||
|
||||
/* Read class. */
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
|
||||
class = grub_pci_read (addr);
|
||||
|
||||
/* Check if this class ID matches that of a PCI IDE Controller. */
|
||||
if (class >> 8 != 0x010601)
|
||||
return 0;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG5);
|
||||
bar = grub_pci_read (addr);
|
||||
|
||||
if ((bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK
|
||||
| GRUB_PCI_ADDR_MEM_PREFETCH))
|
||||
!= (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32))
|
||||
return 0;
|
||||
|
||||
hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK,
|
||||
sizeof (hba));
|
||||
|
||||
if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED))
|
||||
{
|
||||
grub_uint64_t endtime;
|
||||
|
||||
grub_dprintf ("ahci", "Requesting AHCI ownership\n");
|
||||
hba->bios_handoff = (hba->bios_handoff & ~GRUB_AHCI_BIOS_HANDOFF_RWC)
|
||||
| GRUB_AHCI_BIOS_HANDOFF_OS_OWNED;
|
||||
grub_dprintf ("ahci", "Waiting for BIOS to give up ownership\n");
|
||||
endtime = grub_get_time_ms () + 1000;
|
||||
while ((hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED)
|
||||
&& grub_get_time_ms () < endtime);
|
||||
if (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED)
|
||||
{
|
||||
grub_dprintf ("ahci", "Forcibly taking ownership\n");
|
||||
hba->bios_handoff = GRUB_AHCI_BIOS_HANDOFF_OS_OWNED;
|
||||
hba->bios_handoff |= GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED;
|
||||
}
|
||||
else
|
||||
grub_dprintf ("ahci", "AHCI ownership obtained\n");
|
||||
}
|
||||
else
|
||||
grub_dprintf ("ahci", "AHCI is already in OS mode\n");
|
||||
|
||||
if (~(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN))
|
||||
grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n");
|
||||
else
|
||||
grub_dprintf ("ahci", "AHCI is in AHCI mode.\n");
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN;
|
||||
grub_millisleep (1);
|
||||
if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)
|
||||
break;
|
||||
}
|
||||
if (i == 5)
|
||||
{
|
||||
grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
grub_uint64_t endtime;
|
||||
hba->global_control |= 1;
|
||||
endtime = grub_get_time_ms () + 1000;
|
||||
while (hba->global_control & 1)
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
grub_dprintf ("ahci", "couldn't reset AHCI\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN;
|
||||
grub_millisleep (1);
|
||||
if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)
|
||||
break;
|
||||
}
|
||||
if (i == 5)
|
||||
{
|
||||
grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n");
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1;
|
||||
|
||||
grub_dprintf ("ahci", "%d AHCI ports\n", nports);
|
||||
|
||||
for (i = 0; i < nports; i++)
|
||||
{
|
||||
struct grub_ahci_device *adev;
|
||||
grub_uint32_t st;
|
||||
|
||||
if (!(hba->ports_implemented & (1 << i)))
|
||||
continue;
|
||||
|
||||
grub_dprintf ("ahci", "status %d:%x\n", i, hba->ports[i].status);
|
||||
/* FIXME: support hotplugging. */
|
||||
st = hba->ports[i].status;
|
||||
if ((st & 0xf) != 0x3 && (st & 0xf) != 0x1)
|
||||
continue;
|
||||
|
||||
adev = grub_malloc (sizeof (*adev));
|
||||
if (!adev)
|
||||
return 1;
|
||||
|
||||
adev->hba = hba;
|
||||
adev->port = i;
|
||||
adev->present = 1;
|
||||
adev->num = numdevs++;
|
||||
|
||||
if (init_port (adev))
|
||||
{
|
||||
grub_free (adev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices),
|
||||
GRUB_AS_LIST (adev));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_ahci_initialize (void)
|
||||
{
|
||||
grub_pci_iterate (grub_ahci_pciinit);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_ahci_fini_hw (int noreturn __attribute__ ((unused)))
|
||||
{
|
||||
struct grub_ahci_device *dev;
|
||||
|
||||
for (dev = grub_ahci_devices; dev; dev = dev->next)
|
||||
{
|
||||
grub_uint64_t endtime;
|
||||
|
||||
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE;
|
||||
endtime = grub_get_time_ms () + 1000;
|
||||
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
grub_dprintf ("ahci", "couldn't stop FR\n");
|
||||
break;
|
||||
}
|
||||
|
||||
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
|
||||
endtime = grub_get_time_ms () + 1000;
|
||||
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
grub_dprintf ("ahci", "couldn't stop CR\n");
|
||||
break;
|
||||
}
|
||||
grub_dma_free (dev->command_list_chunk);
|
||||
grub_dma_free (dev->command_table_chunk);
|
||||
grub_dma_free (dev->rfis);
|
||||
dev->command_list_chunk = NULL;
|
||||
dev->command_table_chunk = NULL;
|
||||
dev->rfis = NULL;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_ahci_restore_hw (void)
|
||||
{
|
||||
struct grub_ahci_device **pdev;
|
||||
|
||||
for (pdev = &grub_ahci_devices; *pdev; pdev = &((*pdev)->next))
|
||||
if (init_port (*pdev))
|
||||
{
|
||||
struct grub_ahci_device *odev;
|
||||
odev = *pdev;
|
||||
*pdev = (*pdev)->next;
|
||||
grub_free (odev);
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
grub_ahci_iterate (int (*hook) (int id, int bus),
|
||||
grub_disk_pull_t pull)
|
||||
{
|
||||
struct grub_ahci_device *dev;
|
||||
|
||||
if (pull != GRUB_DISK_PULL_NONE)
|
||||
return 0;
|
||||
|
||||
FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
|
||||
if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
find_free_cmd_slot (struct grub_ahci_device *dev)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
if (dev->hda->ports[dev->port].command_issue & (1 << i))
|
||||
continue;
|
||||
if (dev->hda->ports[dev->port].sata_active & (1 << i))
|
||||
continue;
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_AHCI_FIS_REG_H2D = 0x27
|
||||
};
|
||||
|
||||
static const int register_map[11] = { 3 /* Features */,
|
||||
12 /* Sectors */,
|
||||
4 /* LBA low */,
|
||||
5 /* LBA mid */,
|
||||
6 /* LBA high */,
|
||||
7 /* Device */,
|
||||
2 /* CMD register */,
|
||||
13 /* Sectors 48 */,
|
||||
8 /* LBA48 low */,
|
||||
9 /* LBA48 mid */,
|
||||
10 /* LBA48 high */ };
|
||||
|
||||
static grub_err_t
|
||||
grub_ahci_readwrite_real (struct grub_ahci_device *dev,
|
||||
struct grub_disk_ata_pass_through_parms *parms,
|
||||
int spinup)
|
||||
{
|
||||
struct grub_pci_dma_chunk *bufc;
|
||||
grub_uint64_t endtime;
|
||||
unsigned i;
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
grub_dprintf ("ahci", "AHCI tfd = %x\n",
|
||||
dev->hba->ports[dev->port].task_file_data);
|
||||
|
||||
if ((dev->hba->ports[dev->port].task_file_data & 0x80))
|
||||
{
|
||||
dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST;
|
||||
endtime = grub_get_time_ms () + 1000;
|
||||
while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
grub_dprintf ("ahci", "couldn't stop CR\n");
|
||||
break;
|
||||
}
|
||||
dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST;
|
||||
endtime = grub_get_time_ms () + (spinup ? 10000 : 1000);
|
||||
while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
grub_dprintf ("ahci", "couldn't start CR\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error;
|
||||
|
||||
grub_dprintf("ahci", "grub_ahci_read (size=%llu, cmdsize = %llu)\n",
|
||||
(unsigned long long) parms->size,
|
||||
(unsigned long long) parms->cmdsize);
|
||||
|
||||
if (parms->cmdsize != 0 && parms->cmdsize != 12 && parms->cmdsize != 16)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "incorrect ATAPI command size");
|
||||
|
||||
if (parms->size > GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "too big data buffer");
|
||||
|
||||
bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1));
|
||||
|
||||
dev->hba->ports[dev->port].command |= 8;
|
||||
|
||||
grub_dprintf ("ahci", "AHCI tfd = %x\n",
|
||||
dev->hba->ports[dev->port].task_file_data);
|
||||
/* FIXME: support port multipliers. */
|
||||
dev->command_list[0].config
|
||||
= (5 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT)
|
||||
// | GRUB_AHCI_CONFIG_CLEAR_R_OK
|
||||
| (0 << GRUB_AHCI_CONFIG_PMP_SHIFT)
|
||||
| (1 << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT)
|
||||
| (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0)
|
||||
| (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ)
|
||||
| (parms->taskfile.cmd == 8 ? (1 << 8) : 0);
|
||||
dev->command_list[0].transfered = 0;
|
||||
dev->command_list[0].command_table_base
|
||||
= grub_dma_get_phys (dev->command_table_chunk);
|
||||
grub_memset ((char *) dev->command_list[0].unused, 0,
|
||||
sizeof (dev->command_list[0].unused));
|
||||
grub_memset ((char *) &dev->command_table[0], 0,
|
||||
sizeof (dev->command_table[0]));
|
||||
if (parms->cmdsize)
|
||||
grub_memcpy ((char *) dev->command_table[0].command, parms->cmd,
|
||||
parms->cmdsize);
|
||||
|
||||
dev->command_table[0].cfis[0] = GRUB_AHCI_FIS_REG_H2D;
|
||||
dev->command_table[0].cfis[1] = 0x80;
|
||||
for (i = 0; i < sizeof (parms->taskfile.raw); i++)
|
||||
dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i];
|
||||
|
||||
grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
dev->command_table[0].cfis[0], dev->command_table[0].cfis[1],
|
||||
dev->command_table[0].cfis[2], dev->command_table[0].cfis[3],
|
||||
dev->command_table[0].cfis[4], dev->command_table[0].cfis[5],
|
||||
dev->command_table[0].cfis[6], dev->command_table[0].cfis[7]);
|
||||
grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
dev->command_table[0].cfis[8], dev->command_table[0].cfis[9],
|
||||
dev->command_table[0].cfis[10], dev->command_table[0].cfis[11],
|
||||
dev->command_table[0].cfis[12], dev->command_table[0].cfis[13],
|
||||
dev->command_table[0].cfis[14], dev->command_table[0].cfis[15]);
|
||||
|
||||
dev->command_table[0].prdt[0].data_base = grub_dma_get_phys (bufc);
|
||||
dev->command_table[0].prdt[0].unused = 0;
|
||||
dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1)
|
||||
| GRUB_AHCI_INTERRUPT_ON_COMPLETE;
|
||||
|
||||
grub_dprintf ("ahci", "PRDT = %" PRIxGRUB_UINT64_T ", %x, %x (%"
|
||||
PRIuGRUB_SIZE ")\n",
|
||||
dev->command_table[0].prdt[0].data_base,
|
||||
dev->command_table[0].prdt[0].unused,
|
||||
dev->command_table[0].prdt[0].size,
|
||||
(char *) &dev->command_table[0].prdt[0]
|
||||
- (char *) &dev->command_table[0]);
|
||||
|
||||
if (parms->write)
|
||||
grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size);
|
||||
|
||||
grub_dprintf ("ahci", "AHCI command schedulded\n");
|
||||
grub_dprintf ("ahci", "AHCI tfd = %x\n",
|
||||
dev->hba->ports[dev->port].task_file_data);
|
||||
dev->hba->ports[dev->port].inten = 0xffffffff;//(1 << 2) | (1 << 5);
|
||||
dev->hba->ports[dev->port].intstatus = 0xffffffff;//(1 << 2) | (1 << 5);
|
||||
grub_dprintf ("ahci", "AHCI tfd = %x\n",
|
||||
dev->hba->ports[dev->port].task_file_data);
|
||||
dev->hba->ports[dev->port].command_issue |= 1;
|
||||
grub_dprintf ("ahci", "AHCI sig = %x\n", dev->hba->ports[dev->port].sig);
|
||||
grub_dprintf ("ahci", "AHCI tfd = %x\n",
|
||||
dev->hba->ports[dev->port].task_file_data);
|
||||
|
||||
endtime = grub_get_time_ms () + (spinup ? 10000 : 1000);
|
||||
while ((dev->hba->ports[dev->port].command_issue & 1))
|
||||
if (grub_get_time_ms () > endtime)
|
||||
{
|
||||
grub_dprintf ("ahci", "AHCI status <%x %x %x>\n",
|
||||
dev->hba->ports[dev->port].command_issue,
|
||||
dev->hba->ports[dev->port].intstatus,
|
||||
dev->hba->ports[dev->port].task_file_data);
|
||||
err = grub_error (GRUB_ERR_IO, "AHCI transfer timeouted");
|
||||
break;
|
||||
}
|
||||
|
||||
grub_dprintf ("ahci", "AHCI command completed <%x %x %x %x %x, %x %x>\n",
|
||||
dev->hba->ports[dev->port].command_issue,
|
||||
dev->hba->ports[dev->port].intstatus,
|
||||
dev->hba->ports[dev->port].task_file_data,
|
||||
dev->command_list[0].transfered,
|
||||
dev->hba->ports[dev->port].sata_error,
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x00],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x18]);
|
||||
grub_dprintf ("ahci",
|
||||
"last PIO FIS %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x08],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x09],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0a],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0b],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0c],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0d],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0e],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x0f]);
|
||||
grub_dprintf ("ahci",
|
||||
"last REG FIS %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x10],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x11],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x12],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x13],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x14],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x15],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x16],
|
||||
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x17]);
|
||||
|
||||
if (!parms->write)
|
||||
grub_memcpy (parms->buffer, (char *) grub_dma_get_virt (bufc), parms->size);
|
||||
grub_dma_free (bufc);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_ahci_readwrite (grub_ata_t disk,
|
||||
struct grub_disk_ata_pass_through_parms *parms,
|
||||
int spinup)
|
||||
{
|
||||
return grub_ahci_readwrite_real (disk->data, parms, spinup);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_ahci_open (int id, int devnum, struct grub_ata *ata)
|
||||
{
|
||||
struct grub_ahci_device *dev;
|
||||
|
||||
if (id != GRUB_SCSI_SUBSYSTEM_AHCI)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an AHCI device");
|
||||
|
||||
FOR_LIST_ELEMENTS(dev, grub_ahci_devices)
|
||||
if (dev->num == devnum)
|
||||
break;
|
||||
|
||||
if (! dev)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such AHCI device");
|
||||
|
||||
grub_dprintf ("ahci", "opening AHCI dev `ahci%d'\n", dev->num);
|
||||
|
||||
ata->data = dev;
|
||||
ata->dma = 1;
|
||||
ata->present = &dev->present;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static struct grub_ata_dev grub_ahci_dev =
|
||||
{
|
||||
.iterate = grub_ahci_iterate,
|
||||
.open = grub_ahci_open,
|
||||
.readwrite = grub_ahci_readwrite,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void *fini_hnd;
|
||||
|
||||
GRUB_MOD_INIT(ahci)
|
||||
{
|
||||
/* To prevent two drivers operating on the same disks. */
|
||||
grub_disk_firmware_is_tainted = 1;
|
||||
if (grub_disk_firmware_fini)
|
||||
{
|
||||
grub_disk_firmware_fini ();
|
||||
grub_disk_firmware_fini = NULL;
|
||||
}
|
||||
|
||||
/* AHCI initialization. */
|
||||
grub_ahci_initialize ();
|
||||
|
||||
/* AHCI devices are handled by scsi.mod. */
|
||||
grub_ata_dev_register (&grub_ahci_dev);
|
||||
|
||||
fini_hnd = grub_loader_register_preboot_hook (grub_ahci_fini_hw,
|
||||
grub_ahci_restore_hw,
|
||||
GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(ahci)
|
||||
{
|
||||
grub_ahci_fini_hw (0);
|
||||
grub_loader_unregister_preboot_hook (fini_hnd);
|
||||
|
||||
grub_ata_dev_unregister (&grub_ahci_dev);
|
||||
}
|
299
grub-core/disk/arc/arcdisk.c
Normal file
299
grub-core/disk/arc/arcdisk.c
Normal file
|
@ -0,0 +1,299 @@
|
|||
/* ofdisk.c - Open Firmware disk access. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2004,2006,2007,2008,2009,2011 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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/misc.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/arc/arc.h>
|
||||
|
||||
static grub_arc_fileno_t last_handle = 0;
|
||||
static char *last_path = NULL;
|
||||
|
||||
static int lnum = 0;
|
||||
|
||||
struct arcdisk_hash_ent
|
||||
{
|
||||
char *devpath;
|
||||
int num;
|
||||
struct arcdisk_hash_ent *next;
|
||||
};
|
||||
|
||||
#define ARCDISK_HASH_SZ 8
|
||||
static struct arcdisk_hash_ent *arcdisk_hash[ARCDISK_HASH_SZ];
|
||||
|
||||
static int
|
||||
arcdisk_hash_fn (const char *devpath)
|
||||
{
|
||||
int hash = 0;
|
||||
while (*devpath)
|
||||
hash ^= *devpath++;
|
||||
return (hash & (ARCDISK_HASH_SZ - 1));
|
||||
}
|
||||
|
||||
static struct arcdisk_hash_ent *
|
||||
arcdisk_hash_find (const char *devpath)
|
||||
{
|
||||
struct arcdisk_hash_ent *p = arcdisk_hash[arcdisk_hash_fn (devpath)];
|
||||
|
||||
while (p)
|
||||
{
|
||||
if (!grub_strcmp (p->devpath, devpath))
|
||||
break;
|
||||
p = p->next;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static struct arcdisk_hash_ent *
|
||||
arcdisk_hash_add (char *devpath)
|
||||
{
|
||||
struct arcdisk_hash_ent *p;
|
||||
struct arcdisk_hash_ent **head = &arcdisk_hash[arcdisk_hash_fn(devpath)];
|
||||
|
||||
p = grub_malloc (sizeof (*p));
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
p->devpath = devpath;
|
||||
p->next = *head;
|
||||
p->num = lnum++;
|
||||
*head = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
grub_arcdisk_iterate (int (*hook_in) (const char *name),
|
||||
grub_disk_pull_t pull)
|
||||
{
|
||||
auto int hook (const char *name, const struct grub_arc_component *comp);
|
||||
int hook (const char *name, const struct grub_arc_component *comp)
|
||||
{
|
||||
if (!(comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
|
||||
|| comp->type == GRUB_ARC_COMPONENT_TYPE_DISK
|
||||
|| comp->type == GRUB_ARC_COMPONENT_TYPE_TAPE))
|
||||
return 0;
|
||||
return hook_in (name);
|
||||
}
|
||||
if (pull != GRUB_DISK_PULL_NONE)
|
||||
return 0;
|
||||
|
||||
return grub_arc_iterate_devs (hook, 1);
|
||||
}
|
||||
|
||||
#define RAW_SUFFIX "partition(10)"
|
||||
|
||||
static grub_err_t
|
||||
reopen (const char *name)
|
||||
{
|
||||
grub_arc_fileno_t handle;
|
||||
|
||||
if (last_path && grub_strcmp (last_path, name) == 0)
|
||||
{
|
||||
grub_dprintf ("arcdisk", "using already opened %s\n", name);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
if (last_path)
|
||||
{
|
||||
GRUB_ARC_FIRMWARE_VECTOR->close (last_handle);
|
||||
grub_free (last_path);
|
||||
last_path = NULL;
|
||||
last_handle = 0;
|
||||
}
|
||||
if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle))
|
||||
{
|
||||
grub_dprintf ("arcdisk", "couldn't open %s\n", name);
|
||||
return grub_error (GRUB_ERR_IO, "couldn't open %s", name);
|
||||
}
|
||||
last_path = grub_strdup (name);
|
||||
if (!last_path)
|
||||
return grub_errno;
|
||||
last_handle = handle;
|
||||
grub_dprintf ("arcdisk", "opened %s\n", name);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_arcdisk_open (const char *name, grub_disk_t disk)
|
||||
{
|
||||
char *fullname, *optr;
|
||||
const char *iptr;
|
||||
int state = 0;
|
||||
grub_err_t err;
|
||||
grub_arc_err_t r;
|
||||
struct grub_arc_fileinfo info;
|
||||
struct arcdisk_hash_ent *hash;
|
||||
|
||||
if (grub_memcmp (name, "arc/", 4) != 0)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not arc device");
|
||||
fullname = grub_malloc (2 * grub_strlen (name) + sizeof (RAW_SUFFIX));
|
||||
if (!fullname)
|
||||
return grub_errno;
|
||||
optr = fullname;
|
||||
for (iptr = name + 4; *iptr; iptr++)
|
||||
if (state == 0)
|
||||
{
|
||||
if (!grub_isdigit (*iptr))
|
||||
*optr++ = *iptr;
|
||||
else
|
||||
{
|
||||
*optr++ = '(';
|
||||
*optr++ = *iptr;
|
||||
state = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (grub_isdigit (*iptr))
|
||||
*optr++ = *iptr;
|
||||
else
|
||||
{
|
||||
*optr++ = ')';
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
if (state)
|
||||
*optr++ = ')';
|
||||
grub_memcpy (optr, RAW_SUFFIX, sizeof (RAW_SUFFIX));
|
||||
disk->data = fullname;
|
||||
grub_dprintf ("arcdisk", "opening %s\n", fullname);
|
||||
|
||||
hash = arcdisk_hash_find (fullname);
|
||||
if (!hash)
|
||||
hash = arcdisk_hash_add (fullname);
|
||||
if (!hash)
|
||||
return grub_errno;
|
||||
|
||||
err = reopen (fullname);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
r = GRUB_ARC_FIRMWARE_VECTOR->getfileinformation (last_handle, &info);
|
||||
if (r)
|
||||
{
|
||||
grub_uint64_t res = 0;
|
||||
int i;
|
||||
|
||||
grub_dprintf ("arcdisk", "couldn't retrieve size: %ld\n", r);
|
||||
for (i = 40; i >= 9; i--)
|
||||
{
|
||||
grub_uint64_t pos = res | (1ULL << i);
|
||||
char buf[512];
|
||||
long unsigned count = 0;
|
||||
grub_dprintf ("arcdisk",
|
||||
"seek to 0x%" PRIxGRUB_UINT64_T "\n", pos);
|
||||
if (GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0))
|
||||
continue;
|
||||
if (GRUB_ARC_FIRMWARE_VECTOR->read (last_handle, buf,
|
||||
0x200, &count))
|
||||
continue;
|
||||
if (count == 0)
|
||||
continue;
|
||||
res |= (1ULL << i);
|
||||
}
|
||||
grub_dprintf ("arcdisk",
|
||||
"determined disk size 0x%" PRIxGRUB_UINT64_T "\n", res);
|
||||
disk->total_sectors = (res + 0x200) >> 9;
|
||||
}
|
||||
else
|
||||
disk->total_sectors = (info.end >> 9);
|
||||
|
||||
disk->id = hash->num;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_arcdisk_close (grub_disk_t disk)
|
||||
{
|
||||
grub_free (disk->data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_size_t size, char *buf)
|
||||
{
|
||||
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);
|
||||
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->read (last_handle, buf,
|
||||
totl, &count))
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "read failed");
|
||||
totl -= count;
|
||||
buf += count;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
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)))
|
||||
{
|
||||
return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
||||
}
|
||||
|
||||
static struct grub_disk_dev grub_arcdisk_dev =
|
||||
{
|
||||
.name = "arcdisk",
|
||||
.id = GRUB_DISK_DEVICE_ARCDISK_ID,
|
||||
.iterate = grub_arcdisk_iterate,
|
||||
.open = grub_arcdisk_open,
|
||||
.close = grub_arcdisk_close,
|
||||
.read = grub_arcdisk_read,
|
||||
.write = grub_arcdisk_write,
|
||||
.next = 0
|
||||
};
|
||||
|
||||
void
|
||||
grub_arcdisk_init (void)
|
||||
{
|
||||
grub_disk_dev_register (&grub_arcdisk_dev);
|
||||
}
|
||||
|
||||
void
|
||||
grub_arcdisk_fini (void)
|
||||
{
|
||||
if (last_path)
|
||||
{
|
||||
GRUB_ARC_FIRMWARE_VECTOR->close (last_handle);
|
||||
grub_free (last_path);
|
||||
last_path = NULL;
|
||||
last_handle = 0;
|
||||
}
|
||||
|
||||
grub_disk_dev_unregister (&grub_arcdisk_dev);
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,107 +0,0 @@
|
|||
/* ata_pthru.c - ATA pass through for ata.mod. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/ata.h>
|
||||
#include <grub/disk.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/mm.h>
|
||||
|
||||
|
||||
/* ATA pass through support, used by hdparm.mod. */
|
||||
static grub_err_t
|
||||
grub_ata_pass_through (grub_disk_t disk,
|
||||
struct grub_disk_ata_pass_through_parms *parms)
|
||||
{
|
||||
if (disk->dev->id != GRUB_DISK_DEVICE_ATA_ID)
|
||||
return grub_error (GRUB_ERR_BAD_DEVICE,
|
||||
"device not accessed via ata.mod");
|
||||
|
||||
struct grub_ata_device *dev = (struct grub_ata_device *) disk->data;
|
||||
|
||||
if (! (parms->size == 0 || parms->size == GRUB_DISK_SECTOR_SIZE))
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"ATA multi-sector read and DATA OUT not implemented");
|
||||
|
||||
grub_dprintf ("ata", "ata_pass_through: cmd=0x%x, features=0x%x, sectors=0x%x\n",
|
||||
parms->taskfile[GRUB_ATA_REG_CMD],
|
||||
parms->taskfile[GRUB_ATA_REG_FEATURES],
|
||||
parms->taskfile[GRUB_ATA_REG_SECTORS]);
|
||||
grub_dprintf ("ata", "lba_high=0x%x, lba_mid=0x%x, lba_low=0x%x, size=%d\n",
|
||||
parms->taskfile[GRUB_ATA_REG_LBAHIGH],
|
||||
parms->taskfile[GRUB_ATA_REG_LBAMID],
|
||||
parms->taskfile[GRUB_ATA_REG_LBALOW], parms->size);
|
||||
|
||||
/* Set registers. */
|
||||
grub_ata_regset (dev, GRUB_ATA_REG_DISK, 0xE0 | dev->device << 4
|
||||
| (parms->taskfile[GRUB_ATA_REG_DISK] & 0xf));
|
||||
if (grub_ata_check_ready (dev))
|
||||
return grub_errno;
|
||||
|
||||
int i;
|
||||
for (i = GRUB_ATA_REG_FEATURES; i <= GRUB_ATA_REG_LBAHIGH; i++)
|
||||
grub_ata_regset (dev, i, parms->taskfile[i]);
|
||||
|
||||
/* Start command. */
|
||||
grub_ata_regset (dev, GRUB_ATA_REG_CMD, parms->taskfile[GRUB_ATA_REG_CMD]);
|
||||
|
||||
/* Wait for !BSY. */
|
||||
if (grub_ata_wait_not_busy (dev, GRUB_ATA_TOUT_DATA))
|
||||
return grub_errno;
|
||||
|
||||
/* Check status. */
|
||||
grub_int8_t sts = grub_ata_regget (dev, GRUB_ATA_REG_STATUS);
|
||||
grub_dprintf ("ata", "status=0x%x\n", sts);
|
||||
|
||||
/* Transfer data. */
|
||||
if ((sts & (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_DRQ)
|
||||
{
|
||||
if (parms->size != GRUB_DISK_SECTOR_SIZE)
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "DRQ unexpected");
|
||||
grub_ata_pio_read (dev, parms->buffer, GRUB_DISK_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
/* Return registers. */
|
||||
for (i = GRUB_ATA_REG_ERROR; i <= GRUB_ATA_REG_STATUS; i++)
|
||||
parms->taskfile[i] = grub_ata_regget (dev, i);
|
||||
|
||||
grub_dprintf ("ata", "status=0x%x, error=0x%x, sectors=0x%x\n",
|
||||
parms->taskfile[GRUB_ATA_REG_STATUS],
|
||||
parms->taskfile[GRUB_ATA_REG_ERROR],
|
||||
parms->taskfile[GRUB_ATA_REG_SECTORS]);
|
||||
|
||||
if (parms->taskfile[GRUB_ATA_REG_STATUS]
|
||||
& (GRUB_ATA_STATUS_DRQ | GRUB_ATA_STATUS_ERR))
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "ATA passthrough failed");
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GRUB_MOD_INIT(ata_pthru)
|
||||
{
|
||||
/* Register ATA pass through function. */
|
||||
grub_disk_ata_pass_through = grub_ata_pass_through;
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(ata_pthru)
|
||||
{
|
||||
if (grub_disk_ata_pass_through == grub_ata_pass_through)
|
||||
grub_disk_ata_pass_through = NULL;
|
||||
}
|
883
grub-core/disk/cryptodisk.c
Normal file
883
grub-core/disk/cryptodisk.c
Normal file
|
@ -0,0 +1,883 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2007,2010,2011 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/cryptodisk.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/extcmd.h>
|
||||
#include <grub/i18n.h>
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <grub/emu/hostdisk.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
grub_cryptodisk_dev_t grub_cryptodisk_list;
|
||||
|
||||
static const struct grub_arg_option options[] =
|
||||
{
|
||||
{"uuid", 'u', 0, N_("Mount by UUID."), 0, 0},
|
||||
{"all", 'a', 0, N_("Mount all."), 0, 0},
|
||||
{"boot", 'b', 0, N_("Mount all volumes marked as boot."), 0, 0},
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */
|
||||
#define GF_POLYNOM 0x87
|
||||
static inline int GF_PER_SECTOR (const struct grub_cryptodisk *dev)
|
||||
{
|
||||
return 1U << (dev->log_sector_size - GRUB_CRYPTODISK_GF_LOG_BYTES);
|
||||
}
|
||||
|
||||
static grub_cryptodisk_t cryptodisk_list = NULL;
|
||||
static grub_uint8_t n = 0;
|
||||
|
||||
static void
|
||||
gf_mul_x (grub_uint8_t *g)
|
||||
{
|
||||
int over = 0, over2 = 0;
|
||||
unsigned j;
|
||||
|
||||
for (j = 0; j < GRUB_CRYPTODISK_GF_BYTES; j++)
|
||||
{
|
||||
over2 = !!(g[j] & 0x80);
|
||||
g[j] <<= 1;
|
||||
g[j] |= over;
|
||||
over = over2;
|
||||
}
|
||||
if (over)
|
||||
g[0] ^= GF_POLYNOM;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gf_mul_x_be (grub_uint8_t *g)
|
||||
{
|
||||
int over = 0, over2 = 0;
|
||||
int j;
|
||||
|
||||
for (j = (int) GRUB_CRYPTODISK_GF_BYTES - 1; j >= 0; j--)
|
||||
{
|
||||
over2 = !!(g[j] & 0x80);
|
||||
g[j] <<= 1;
|
||||
g[j] |= over;
|
||||
over = over2;
|
||||
}
|
||||
if (over)
|
||||
g[GRUB_CRYPTODISK_GF_BYTES - 1] ^= GF_POLYNOM;
|
||||
}
|
||||
|
||||
static void
|
||||
gf_mul_be (grub_uint8_t *o, const grub_uint8_t *a, const grub_uint8_t *b)
|
||||
{
|
||||
unsigned i;
|
||||
grub_uint8_t t[GRUB_CRYPTODISK_GF_BYTES];
|
||||
grub_memset (o, 0, GRUB_CRYPTODISK_GF_BYTES);
|
||||
grub_memcpy (t, b, GRUB_CRYPTODISK_GF_BYTES);
|
||||
for (i = 0; i < GRUB_CRYPTODISK_GF_SIZE; i++)
|
||||
{
|
||||
if (((a[GRUB_CRYPTODISK_GF_BYTES - i / 8 - 1] >> (i % 8))) & 1)
|
||||
grub_crypto_xor (o, o, t, GRUB_CRYPTODISK_GF_BYTES);
|
||||
gf_mul_x_be (t);
|
||||
}
|
||||
}
|
||||
|
||||
static gcry_err_code_t
|
||||
grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher,
|
||||
void *out, void *in, grub_size_t size,
|
||||
void *iv)
|
||||
{
|
||||
grub_uint8_t *inptr, *outptr, *end;
|
||||
grub_uint8_t ivt[cipher->cipher->blocksize];
|
||||
if (!cipher->cipher->decrypt)
|
||||
return GPG_ERR_NOT_SUPPORTED;
|
||||
if (size % cipher->cipher->blocksize != 0)
|
||||
return GPG_ERR_INV_ARG;
|
||||
end = (grub_uint8_t *) in + size;
|
||||
for (inptr = in, outptr = out; inptr < end;
|
||||
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
|
||||
{
|
||||
grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
|
||||
cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
|
||||
grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
|
||||
grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize);
|
||||
}
|
||||
return GPG_ERR_NO_ERROR;
|
||||
}
|
||||
|
||||
struct lrw_sector
|
||||
{
|
||||
grub_uint8_t low[GRUB_CRYPTODISK_GF_BYTES];
|
||||
grub_uint8_t high[GRUB_CRYPTODISK_GF_BYTES];
|
||||
grub_uint8_t low_byte, low_byte_c;
|
||||
};
|
||||
|
||||
static void
|
||||
generate_lrw_sector (struct lrw_sector *sec,
|
||||
const struct grub_cryptodisk *dev,
|
||||
const grub_uint8_t *iv)
|
||||
{
|
||||
grub_uint8_t idx[GRUB_CRYPTODISK_GF_BYTES];
|
||||
grub_uint16_t c;
|
||||
int j;
|
||||
grub_memcpy (idx, iv, GRUB_CRYPTODISK_GF_BYTES);
|
||||
sec->low_byte = (idx[GRUB_CRYPTODISK_GF_BYTES - 1]
|
||||
& (GF_PER_SECTOR (dev) - 1));
|
||||
sec->low_byte_c = (((GF_PER_SECTOR (dev) - 1) & ~sec->low_byte) + 1);
|
||||
idx[GRUB_CRYPTODISK_GF_BYTES - 1] &= ~(GF_PER_SECTOR (dev) - 1);
|
||||
gf_mul_be (sec->low, dev->lrw_key, idx);
|
||||
if (!sec->low_byte)
|
||||
return;
|
||||
|
||||
c = idx[GRUB_CRYPTODISK_GF_BYTES - 1] + GF_PER_SECTOR (dev);
|
||||
if (c & 0x100)
|
||||
{
|
||||
for (j = GRUB_CRYPTODISK_GF_BYTES - 2; j >= 0; j--)
|
||||
{
|
||||
idx[j]++;
|
||||
if (idx[j] != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
idx[GRUB_CRYPTODISK_GF_BYTES - 1] = c;
|
||||
gf_mul_be (sec->high, dev->lrw_key, idx);
|
||||
}
|
||||
|
||||
static void __attribute__ ((unused))
|
||||
lrw_xor (const struct lrw_sector *sec,
|
||||
const struct grub_cryptodisk *dev,
|
||||
grub_uint8_t *b)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES;
|
||||
i += GRUB_CRYPTODISK_GF_BYTES)
|
||||
grub_crypto_xor (b + i, b + i, sec->low, GRUB_CRYPTODISK_GF_BYTES);
|
||||
grub_crypto_xor (b, b, dev->lrw_precalc + GRUB_CRYPTODISK_GF_BYTES * sec->low_byte,
|
||||
sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES);
|
||||
if (!sec->low_byte)
|
||||
return;
|
||||
|
||||
for (i = sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES;
|
||||
i < (1U << dev->log_sector_size); i += GRUB_CRYPTODISK_GF_BYTES)
|
||||
grub_crypto_xor (b + i, b + i, sec->high, GRUB_CRYPTODISK_GF_BYTES);
|
||||
grub_crypto_xor (b + sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES,
|
||||
b + sec->low_byte_c * GRUB_CRYPTODISK_GF_BYTES,
|
||||
dev->lrw_precalc, sec->low_byte * GRUB_CRYPTODISK_GF_BYTES);
|
||||
}
|
||||
|
||||
gcry_err_code_t
|
||||
grub_cryptodisk_decrypt (struct grub_cryptodisk *dev,
|
||||
grub_uint8_t * data, grub_size_t len,
|
||||
grub_disk_addr_t sector)
|
||||
{
|
||||
grub_size_t i;
|
||||
gcry_err_code_t err;
|
||||
|
||||
/* The only mode without IV. */
|
||||
if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey)
|
||||
return grub_crypto_ecb_decrypt (dev->cipher, data, data, len);
|
||||
|
||||
for (i = 0; i < len; i += (1U << dev->log_sector_size))
|
||||
{
|
||||
grub_size_t sz = ((dev->cipher->cipher->blocksize
|
||||
+ sizeof (grub_uint32_t) - 1)
|
||||
/ sizeof (grub_uint32_t));
|
||||
grub_uint32_t iv[sz];
|
||||
|
||||
if (dev->rekey)
|
||||
{
|
||||
grub_uint64_t zone = sector >> dev->rekey_shift;
|
||||
if (zone != dev->last_rekey)
|
||||
{
|
||||
err = dev->rekey (dev, zone);
|
||||
if (err)
|
||||
return err;
|
||||
dev->last_rekey = zone;
|
||||
}
|
||||
}
|
||||
|
||||
grub_memset (iv, 0, sz * sizeof (iv[0]));
|
||||
switch (dev->mode_iv)
|
||||
{
|
||||
case GRUB_CRYPTODISK_MODE_IV_NULL:
|
||||
break;
|
||||
case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH:
|
||||
{
|
||||
grub_uint64_t tmp;
|
||||
grub_uint64_t ctx[(dev->iv_hash->contextsize + 7) / 8];
|
||||
|
||||
grub_memset (ctx, 0, sizeof (ctx));
|
||||
|
||||
tmp = grub_cpu_to_le64 (sector << dev->log_sector_size);
|
||||
dev->iv_hash->init (ctx);
|
||||
dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len);
|
||||
dev->iv_hash->write (ctx, &tmp, sizeof (tmp));
|
||||
dev->iv_hash->final (ctx);
|
||||
|
||||
grub_memcpy (iv, dev->iv_hash->read (ctx), sizeof (iv));
|
||||
}
|
||||
break;
|
||||
case GRUB_CRYPTODISK_MODE_IV_PLAIN64:
|
||||
iv[1] = grub_cpu_to_le32 (sector >> 32);
|
||||
case GRUB_CRYPTODISK_MODE_IV_PLAIN:
|
||||
iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
|
||||
break;
|
||||
case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64:
|
||||
iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size));
|
||||
iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size)
|
||||
& 0xFFFFFFFF);
|
||||
break;
|
||||
case GRUB_CRYPTODISK_MODE_IV_BENBI:
|
||||
{
|
||||
grub_uint64_t num = (sector << dev->benbi_log) + 1;
|
||||
iv[sz - 2] = grub_cpu_to_be32 (num >> 32);
|
||||
iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF);
|
||||
}
|
||||
break;
|
||||
case GRUB_CRYPTODISK_MODE_IV_ESSIV:
|
||||
iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF);
|
||||
err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv,
|
||||
dev->cipher->cipher->blocksize);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
switch (dev->mode)
|
||||
{
|
||||
case GRUB_CRYPTODISK_MODE_CBC:
|
||||
err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i,
|
||||
(1U << dev->log_sector_size), iv);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
||||
case GRUB_CRYPTODISK_MODE_PCBC:
|
||||
err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i,
|
||||
(1U << dev->log_sector_size), iv);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
case GRUB_CRYPTODISK_MODE_XTS:
|
||||
{
|
||||
unsigned j;
|
||||
err = grub_crypto_ecb_encrypt (dev->secondary_cipher, iv, iv,
|
||||
dev->cipher->cipher->blocksize);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (j = 0; j < (1U << dev->log_sector_size);
|
||||
j += dev->cipher->cipher->blocksize)
|
||||
{
|
||||
grub_crypto_xor (data + i + j, data + i + j, iv,
|
||||
dev->cipher->cipher->blocksize);
|
||||
err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j,
|
||||
data + i + j,
|
||||
dev->cipher->cipher->blocksize);
|
||||
if (err)
|
||||
return err;
|
||||
grub_crypto_xor (data + i + j, data + i + j, iv,
|
||||
dev->cipher->cipher->blocksize);
|
||||
gf_mul_x ((grub_uint8_t *) iv);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GRUB_CRYPTODISK_MODE_LRW:
|
||||
{
|
||||
struct lrw_sector sec;
|
||||
|
||||
generate_lrw_sector (&sec, dev, (grub_uint8_t *) iv);
|
||||
lrw_xor (&sec, dev, data + i);
|
||||
|
||||
err = grub_crypto_ecb_decrypt (dev->cipher, data + i,
|
||||
data + i,
|
||||
(1U << dev->log_sector_size));
|
||||
if (err)
|
||||
return err;
|
||||
lrw_xor (&sec, dev, data + i);
|
||||
}
|
||||
break;
|
||||
case GRUB_CRYPTODISK_MODE_ECB:
|
||||
grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i,
|
||||
(1U << dev->log_sector_size));
|
||||
break;
|
||||
default:
|
||||
return GPG_ERR_NOT_IMPLEMENTED;
|
||||
}
|
||||
sector++;
|
||||
}
|
||||
return GPG_ERR_NO_ERROR;
|
||||
}
|
||||
|
||||
gcry_err_code_t
|
||||
grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t keysize)
|
||||
{
|
||||
gcry_err_code_t err;
|
||||
int real_keysize;
|
||||
|
||||
real_keysize = keysize;
|
||||
if (dev->mode == GRUB_CRYPTODISK_MODE_XTS)
|
||||
real_keysize /= 2;
|
||||
if (dev->mode == GRUB_CRYPTODISK_MODE_LRW)
|
||||
real_keysize -= dev->cipher->cipher->blocksize;
|
||||
|
||||
/* Set the PBKDF2 output as the cipher key. */
|
||||
err = grub_crypto_cipher_set_key (dev->cipher, key, real_keysize);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Configure ESSIV if necessary. */
|
||||
if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_ESSIV)
|
||||
{
|
||||
grub_size_t essiv_keysize = dev->essiv_hash->mdlen;
|
||||
grub_uint8_t hashed_key[essiv_keysize];
|
||||
|
||||
grub_crypto_hash (dev->essiv_hash, hashed_key, key, keysize);
|
||||
err = grub_crypto_cipher_set_key (dev->essiv_cipher,
|
||||
hashed_key, essiv_keysize);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (dev->mode == GRUB_CRYPTODISK_MODE_XTS)
|
||||
{
|
||||
err = grub_crypto_cipher_set_key (dev->secondary_cipher,
|
||||
key + real_keysize,
|
||||
keysize / 2);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (dev->mode == GRUB_CRYPTODISK_MODE_LRW)
|
||||
{
|
||||
unsigned i;
|
||||
grub_uint8_t idx[GRUB_CRYPTODISK_GF_BYTES];
|
||||
|
||||
grub_free (dev->lrw_precalc);
|
||||
grub_memcpy (dev->lrw_key, key + real_keysize,
|
||||
dev->cipher->cipher->blocksize);
|
||||
dev->lrw_precalc = grub_malloc ((1U << dev->log_sector_size));
|
||||
if (!dev->lrw_precalc)
|
||||
return GPG_ERR_OUT_OF_MEMORY;
|
||||
grub_memset (idx, 0, GRUB_CRYPTODISK_GF_BYTES);
|
||||
for (i = 0; i < (1U << dev->log_sector_size);
|
||||
i += GRUB_CRYPTODISK_GF_BYTES)
|
||||
{
|
||||
idx[GRUB_CRYPTODISK_GF_BYTES - 1] = i / GRUB_CRYPTODISK_GF_BYTES;
|
||||
gf_mul_be (dev->lrw_precalc + i, idx, dev->lrw_key);
|
||||
}
|
||||
}
|
||||
return GPG_ERR_NO_ERROR;
|
||||
}
|
||||
|
||||
static int
|
||||
grub_cryptodisk_iterate (int (*hook) (const char *name),
|
||||
grub_disk_pull_t pull)
|
||||
{
|
||||
grub_cryptodisk_t i;
|
||||
|
||||
if (pull != GRUB_DISK_PULL_NONE)
|
||||
return 0;
|
||||
|
||||
for (i = cryptodisk_list; i != NULL; i = i->next)
|
||||
{
|
||||
char buf[30];
|
||||
grub_snprintf (buf, sizeof (buf), "crypto%lu", i->id);
|
||||
if (hook (buf))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cryptodisk_open (const char *name, grub_disk_t disk)
|
||||
{
|
||||
grub_cryptodisk_t dev;
|
||||
|
||||
if (grub_memcmp (name, "crypto", sizeof ("crypto") - 1) != 0)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
|
||||
|
||||
if (grub_memcmp (name, "cryptouuid/", sizeof ("cryptouuid/") - 1) == 0)
|
||||
{
|
||||
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
|
||||
if (grub_strcasecmp (name + sizeof ("cryptouuid/") - 1, dev->uuid) == 0)
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long id = grub_strtoul (name + sizeof ("crypto") - 1, 0, 0);
|
||||
if (grub_errno)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
|
||||
/* Search for requested device in the list of CRYPTODISK devices. */
|
||||
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
|
||||
if (dev->id == id)
|
||||
break;
|
||||
}
|
||||
if (!dev)
|
||||
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device");
|
||||
|
||||
disk->log_sector_size = dev->log_sector_size;
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
if (dev->cheat)
|
||||
{
|
||||
if (dev->cheat_fd == -1)
|
||||
dev->cheat_fd = open (dev->cheat, O_RDONLY);
|
||||
if (dev->cheat_fd == -1)
|
||||
return grub_error (GRUB_ERR_IO, "couldn't open %s: %s",
|
||||
dev->cheat, strerror (errno));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!dev->source_disk)
|
||||
{
|
||||
grub_dprintf ("cryptodisk", "Opening device %s\n", name);
|
||||
/* Try to open the source disk and populate the requested disk. */
|
||||
dev->source_disk = grub_disk_open (dev->source);
|
||||
if (!dev->source_disk)
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
disk->data = dev;
|
||||
disk->total_sectors = dev->total_length;
|
||||
disk->id = dev->id;
|
||||
dev->ref++;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
grub_cryptodisk_close (grub_disk_t disk)
|
||||
{
|
||||
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
|
||||
grub_dprintf ("cryptodisk", "Closing disk\n");
|
||||
|
||||
dev->ref--;
|
||||
|
||||
if (dev->ref != 0)
|
||||
return;
|
||||
#ifdef GRUB_UTIL
|
||||
if (dev->cheat)
|
||||
{
|
||||
close (dev->cheat_fd);
|
||||
dev->cheat_fd = -1;
|
||||
}
|
||||
#endif
|
||||
grub_disk_close (dev->source_disk);
|
||||
dev->source_disk = NULL;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||
grub_size_t size, char *buf)
|
||||
{
|
||||
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
|
||||
grub_err_t err;
|
||||
gcry_err_code_t gcry_err;
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
if (dev->cheat)
|
||||
{
|
||||
err = grub_util_fd_seek (dev->cheat_fd, dev->cheat,
|
||||
sector << disk->log_sector_size);
|
||||
if (err)
|
||||
return err;
|
||||
if (grub_util_fd_read (dev->cheat_fd, buf, size << disk->log_sector_size)
|
||||
!= (ssize_t) (size << disk->log_sector_size))
|
||||
return grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'",
|
||||
dev->cheat);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
grub_dprintf ("cryptodisk",
|
||||
"Reading %" PRIuGRUB_SIZE " sectors from sector 0x%"
|
||||
PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n",
|
||||
size, sector, dev->offset);
|
||||
|
||||
err = grub_disk_read (dev->source_disk,
|
||||
(sector << (disk->log_sector_size
|
||||
- GRUB_DISK_SECTOR_BITS)) + dev->offset, 0,
|
||||
size << disk->log_sector_size, buf);
|
||||
if (err)
|
||||
{
|
||||
grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err);
|
||||
return err;
|
||||
}
|
||||
gcry_err = grub_cryptodisk_decrypt (dev, (grub_uint8_t *) buf,
|
||||
size << disk->log_sector_size,
|
||||
sector);
|
||||
return grub_crypto_gcry_error (gcry_err);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cryptodisk_write (grub_disk_t disk __attribute ((unused)),
|
||||
grub_disk_addr_t sector __attribute ((unused)),
|
||||
grub_size_t size __attribute ((unused)),
|
||||
const char *buf __attribute ((unused)))
|
||||
{
|
||||
return GRUB_ERR_NOT_IMPLEMENTED_YET;
|
||||
}
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
static grub_disk_memberlist_t
|
||||
grub_cryptodisk_memberlist (grub_disk_t disk)
|
||||
{
|
||||
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
|
||||
grub_disk_memberlist_t list = NULL;
|
||||
|
||||
list = grub_malloc (sizeof (*list));
|
||||
if (list)
|
||||
{
|
||||
list->disk = dev->source_disk;
|
||||
list->next = NULL;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
cryptodisk_cleanup (void)
|
||||
{
|
||||
grub_cryptodisk_t dev = cryptodisk_list;
|
||||
grub_cryptodisk_t tmp;
|
||||
|
||||
while (dev != NULL)
|
||||
{
|
||||
grub_free (dev->source);
|
||||
grub_free (dev->cipher);
|
||||
grub_free (dev->secondary_cipher);
|
||||
grub_free (dev->essiv_cipher);
|
||||
tmp = dev->next;
|
||||
grub_free (dev);
|
||||
dev = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
|
||||
grub_disk_t source)
|
||||
{
|
||||
newdev->source = grub_strdup (name);
|
||||
if (!newdev->source)
|
||||
{
|
||||
grub_free (newdev);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
newdev->id = n++;
|
||||
newdev->source_id = source->id;
|
||||
newdev->source_dev_id = source->dev->id;
|
||||
newdev->next = cryptodisk_list;
|
||||
cryptodisk_list = newdev;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_cryptodisk_t
|
||||
grub_cryptodisk_get_by_uuid (const char *uuid)
|
||||
{
|
||||
grub_cryptodisk_t dev;
|
||||
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
|
||||
if (grub_strcasecmp (dev->uuid, uuid) == 0)
|
||||
return dev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
grub_cryptodisk_t
|
||||
grub_cryptodisk_get_by_source_disk (grub_disk_t disk)
|
||||
{
|
||||
grub_cryptodisk_t dev;
|
||||
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
|
||||
if (dev->source_id == disk->id && dev->source_dev_id == disk->dev->id)
|
||||
return dev;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
grub_err_t
|
||||
grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name,
|
||||
grub_disk_t source, const char *cheat)
|
||||
{
|
||||
newdev->cheat = grub_strdup (cheat);
|
||||
newdev->source = grub_strdup (name);
|
||||
if (!newdev->source || !newdev->cheat)
|
||||
{
|
||||
grub_free (newdev->source);
|
||||
grub_free (newdev->cheat);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
newdev->cheat_fd = -1;
|
||||
newdev->source_id = source->id;
|
||||
newdev->source_dev_id = source->dev->id;
|
||||
newdev->id = n++;
|
||||
newdev->next = cryptodisk_list;
|
||||
cryptodisk_list = newdev;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
grub_util_cryptodisk_print_abstraction (grub_disk_t disk)
|
||||
{
|
||||
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
|
||||
|
||||
grub_printf ("cryptodisk %s ", dev->modname);
|
||||
|
||||
if (dev->cipher)
|
||||
grub_printf ("%s ", dev->cipher->cipher->modname);
|
||||
if (dev->secondary_cipher)
|
||||
grub_printf ("%s ", dev->secondary_cipher->cipher->modname);
|
||||
if (dev->essiv_cipher)
|
||||
grub_printf ("%s ", dev->essiv_cipher->cipher->modname);
|
||||
if (dev->hash)
|
||||
grub_printf ("%s ", dev->hash->modname);
|
||||
if (dev->essiv_hash)
|
||||
grub_printf ("%s ", dev->essiv_hash->modname);
|
||||
if (dev->iv_hash)
|
||||
grub_printf ("%s ", dev->iv_hash->modname);
|
||||
}
|
||||
|
||||
void
|
||||
grub_util_cryptodisk_print_uuid (grub_disk_t disk)
|
||||
{
|
||||
grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data;
|
||||
grub_printf ("%s ", dev->uuid);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int check_boot, have_it;
|
||||
static char *search_uuid;
|
||||
|
||||
static void
|
||||
cryptodisk_close (grub_cryptodisk_t dev)
|
||||
{
|
||||
grub_crypto_cipher_close (dev->cipher);
|
||||
grub_crypto_cipher_close (dev->secondary_cipher);
|
||||
grub_crypto_cipher_close (dev->essiv_cipher);
|
||||
grub_free (dev);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_cryptodisk_t dev;
|
||||
grub_cryptodisk_dev_t cr;
|
||||
|
||||
dev = grub_cryptodisk_get_by_source_disk (source);
|
||||
|
||||
if (dev)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
FOR_CRYPTODISK_DEVS (cr)
|
||||
{
|
||||
dev = cr->scan (source, search_uuid, check_boot);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (!dev)
|
||||
continue;
|
||||
|
||||
err = cr->recover_key (source, dev);
|
||||
if (err)
|
||||
{
|
||||
cryptodisk_close (dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
grub_cryptodisk_insert (dev, name, source);
|
||||
|
||||
have_it = 1;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
#include <grub/util/misc.h>
|
||||
grub_err_t
|
||||
grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_cryptodisk_t dev;
|
||||
grub_cryptodisk_dev_t cr;
|
||||
grub_disk_t source;
|
||||
|
||||
/* Try to open disk. */
|
||||
source = grub_disk_open (sourcedev);
|
||||
if (!source)
|
||||
return grub_errno;
|
||||
|
||||
dev = grub_cryptodisk_get_by_source_disk (source);
|
||||
|
||||
if (dev)
|
||||
{
|
||||
grub_disk_close (source);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
FOR_CRYPTODISK_DEVS (cr)
|
||||
{
|
||||
dev = cr->scan (source, search_uuid, check_boot);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
if (!dev)
|
||||
continue;
|
||||
|
||||
grub_util_info ("cheatmounted %s (%s) at %s", sourcedev, dev->modname,
|
||||
cheat);
|
||||
err = grub_cryptodisk_cheat_insert (dev, sourcedev, source, cheat);
|
||||
grub_disk_close (source);
|
||||
if (err)
|
||||
grub_free (dev);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_disk_close (source);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
grub_cryptodisk_scan_device (const char *name)
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_disk_t source;
|
||||
|
||||
/* Try to open disk. */
|
||||
source = grub_disk_open (name);
|
||||
if (!source)
|
||||
return grub_errno;
|
||||
|
||||
err = grub_cryptodisk_scan_device_real (name, source);
|
||||
|
||||
grub_disk_close (source);
|
||||
|
||||
if (err)
|
||||
grub_print_error ();
|
||||
return have_it && search_uuid ? 1 : 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
|
||||
{
|
||||
struct grub_arg_list *state = ctxt->state;
|
||||
|
||||
if (argc < 1 && !state[1].set && !state[2].set)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
|
||||
|
||||
have_it = 0;
|
||||
if (state[0].set)
|
||||
{
|
||||
grub_cryptodisk_t dev;
|
||||
|
||||
dev = grub_cryptodisk_get_by_uuid (args[0]);
|
||||
if (dev)
|
||||
{
|
||||
grub_dprintf ("cryptodisk",
|
||||
"already mounted as crypto%lu\n", dev->id);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
check_boot = state[2].set;
|
||||
search_uuid = args[0];
|
||||
grub_device_iterate (&grub_cryptodisk_scan_device);
|
||||
search_uuid = NULL;
|
||||
|
||||
if (!have_it)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found");
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
else if (state[1].set || (argc == 0 && state[2].set))
|
||||
{
|
||||
search_uuid = NULL;
|
||||
check_boot = state[2].set;
|
||||
grub_device_iterate (&grub_cryptodisk_scan_device);
|
||||
search_uuid = NULL;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
grub_err_t err;
|
||||
grub_disk_t disk;
|
||||
grub_cryptodisk_t dev;
|
||||
|
||||
search_uuid = NULL;
|
||||
check_boot = state[2].set;
|
||||
disk = grub_disk_open (args[0]);
|
||||
if (!disk)
|
||||
return grub_errno;
|
||||
|
||||
dev = grub_cryptodisk_get_by_source_disk (disk);
|
||||
if (dev)
|
||||
{
|
||||
grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id);
|
||||
grub_disk_close (disk);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
err = grub_cryptodisk_scan_device_real (args[0], disk);
|
||||
|
||||
grub_disk_close (disk);
|
||||
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
static struct grub_disk_dev grub_cryptodisk_dev = {
|
||||
.name = "cryptodisk",
|
||||
.id = GRUB_DISK_DEVICE_CRYPTODISK_ID,
|
||||
.iterate = grub_cryptodisk_iterate,
|
||||
.open = grub_cryptodisk_open,
|
||||
.close = grub_cryptodisk_close,
|
||||
.read = grub_cryptodisk_read,
|
||||
.write = grub_cryptodisk_write,
|
||||
#ifdef GRUB_UTIL
|
||||
.memberlist = grub_cryptodisk_memberlist,
|
||||
#endif
|
||||
.next = 0
|
||||
};
|
||||
|
||||
static grub_extcmd_t cmd;
|
||||
|
||||
GRUB_MOD_INIT (cryptodisk)
|
||||
{
|
||||
grub_disk_dev_register (&grub_cryptodisk_dev);
|
||||
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
|
||||
N_("SOURCE|-u UUID|-a|-b"),
|
||||
N_("Mount a crypto device."), options);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (cryptodisk)
|
||||
{
|
||||
grub_disk_dev_unregister (&grub_cryptodisk_dev);
|
||||
cryptodisk_cleanup ();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue