Merge mainline into net

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-09-22 20:13:00 +02:00
commit 760a7e5aed
521 changed files with 54590 additions and 8041 deletions

View file

@ -75,9 +75,10 @@ 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
@ -93,24 +94,20 @@ 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
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
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/i386/pit.h
endif
@ -123,8 +120,8 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
endif
if COND_mips_yeeloong
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
@ -133,19 +130,17 @@ 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/pci.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.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
endif
if COND_powerpc_ieee1275
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
endif
if COND_sparc64_ieee1275
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h
endif
@ -179,13 +174,19 @@ symlist.c: symlist.h gensymlist.sh
CLEANFILES += symlist.c
BUILT_SOURCES += symlist.c
if COND_HAVE_ASM_USCORE
ASM_PREFIX=1
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 '"$(ASM_PREFIX)"'kernel \1/;p;}' \
-e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/defined '"$(ASM_PREFIX)"' kernel \1/;p;}' \
| sort -u >$@
rm -f kernel_syms.input
CLEANFILES += kernel_syms.lst
@ -205,61 +206,91 @@ 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 "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" \
-e "/EXTCOMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \
-e "/P1COMMAND_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)
sh $^ $@
platform_DATA += $(MOD_FILES)
CLEANFILES += $(MOD_FILES)
if COND_ENABLE_EFIEMU
efiemu32.o: efiemu/runtime/efiemu.c $(TARGET_OBJ2ELF)

View file

@ -1,5 +1,17 @@
AutoGen definitions Makefile.tpl;
script = {
installdir = noinst;
name = gensyminfo.sh;
common = gensyminfo.sh.in;
};
script = {
installdir = noinst;
name = genmod.sh;
common = genmod.sh.in;
};
kernel = {
name = kernel;
@ -10,20 +22,20 @@ kernel = {
x86_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment';
i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),$(GRUB_KERNEL_MACHINE_LINK_ADDR)';
i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)';
i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),$(GRUB_KERNEL_MACHINE_LINK_ADDR)';
i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200';
i386_coreboot_ldflags = '-Wl,-Ttext=$(GRUB_KERNEL_MACHINE_LINK_ADDR)';
i386_multiboot_ldflags = '-Wl,-Ttext=$(GRUB_KERNEL_MACHINE_LINK_ADDR)';
i386_ieee1275_ldflags = '-Wl,-Ttext=$(GRUB_KERNEL_MACHINE_LINK_ADDR)';
mips_yeeloong_ldflags = '-Wl,-Ttext,$(GRUB_KERNEL_MACHINE_LINK_ADDR)';
powerpc_ieee1275_ldflags = '-Wl,-Ttext,$(GRUB_KERNEL_MACHINE_LINK_ADDR)';
i386_coreboot_ldflags = '-Wl,-Ttext=0x8200';
i386_multiboot_ldflags = '-Wl,-Ttext=0x8200';
i386_ieee1275_ldflags = '-Wl,-Ttext=0x10000';
mips_yeeloong_ldflags = '-Wl,-Ttext,0x80200000';
powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000';
sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400';
mips_yeeloong_cppflags = '-DUSE_ASCII_FAILBACK';
i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)';
i386_qemu_ccasflags = '-DGRUB_KERNEL_MACHINE_LINK_ADDR=$(GRUB_KERNEL_MACHINE_LINK_ADDR)';
emu_cflags = '$(CFLAGS_GNULIB)';
emu_cppflags = '$(CPPFLAGS_GNULIB)';
@ -137,6 +149,8 @@ kernel = {
mips_yeeloong = term/at_keyboard.c;
mips_yeeloong = term/serial.c;
mips_yeeloong = video/sm712.c;
extra_dist = video/sm712_init.c;
mips_yeeloong = commands/keylayouts.c;
powerpc_ieee1275 = kern/ieee1275/init.c;
powerpc_ieee1275 = kern/powerpc/cache.S;
@ -149,6 +163,7 @@ kernel = {
emu = disk/host.c;
emu = gnulib/progname.c;
emu = gnulib/error.c;
emu = kern/emu/console.c;
emu = kern/emu/getroot.c;
emu = kern/emu/hostdisk.c;
@ -172,6 +187,8 @@ kernel = {
videoinkernel = video/fb/video_fb.c;
videoinkernel = video/video.c;
videoinkernel = commands/boot.c;
extra_dist = kern/i386/realmode.S;
extra_dist = kern/i386/pc/lzma_decode.S;
extra_dist = kern/mips/cache_flush.S;
@ -186,7 +203,7 @@ program = {
ldadd = 'kernel.img$(EXEEXT)';
ldadd = '$(MODULE_FILES)';
ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER)';
ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
enable = emu;
};
@ -199,7 +216,7 @@ program = {
emu_nodist = symlist.c;
ldadd = 'kernel.img$(EXEEXT)';
ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER)';
ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)';
enable = emu;
};
@ -318,25 +335,19 @@ module = {
module = {
name = usbserial_common;
common = bus/usb/serial/common.c;
enable = emu;
enable = usb;
emu_condition = COND_GRUB_EMU_USB;
};
module = {
name = usbserial_pl2303;
common = bus/usb/serial/pl2303.c;
enable = emu;
enable = usb;
emu_condition = COND_GRUB_EMU_USB;
};
module = {
name = usbserial_ftdi;
common = bus/usb/serial/ftdi.c;
enable = emu;
enable = usb;
emu_condition = COND_GRUB_EMU_USB;
};
module = {
@ -369,12 +380,6 @@ module = {
library = {
name = libgnulib.a;
common = gnulib/regex.c;
extra_dist = gnulib/regcomp.c;
extra_dist = gnulib/regexec.c;
extra_dist = gnulib/fnmatch_loop.c;
extra_dist = gnulib/regex_internal.c;
cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)';
};
@ -394,6 +399,7 @@ module = {
module = {
name = regexp;
common = commands/regexp.c;
common = commands/wildcard.c;
ldadd = libgnulib.a;
cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)';
cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)';
@ -402,7 +408,7 @@ module = {
module = {
name = acpi;
x86 = commands/acpi.c;
common = commands/acpi.c;
x86_efi = commands/efi/acpi.c;
i386_pc = commands/i386/pc/acpi.c;
i386_coreboot = commands/i386/pc/acpi.c;
@ -414,6 +420,41 @@ module = {
enable = i386_multiboot;
};
module = {
name = lsacpi;
common = commands/lsacpi.c;
enable = x86_efi;
enable = i386_pc;
enable = i386_coreboot;
enable = i386_multiboot;
};
module = {
name = lsefisystab;
common = commands/efi/lsefisystab.c;
enable = x86_efi;
};
module = {
name = lssal;
common = commands/efi/lssal.c;
enable = x86_efi;
};
module = {
name = lsefimmap;
common = commands/efi/lsefimmap.c;
enable = x86_efi;
};
module = {
name = blocklist;
common = commands/blocklist.c;
@ -423,6 +464,7 @@ module = {
name = boot;
common = commands/boot.c;
i386_pc = lib/i386/pc/biosnum.c;
enable = videomodules;
};
module = {
@ -446,12 +488,6 @@ module = {
enable = x86;
};
module = {
name = crc;
common = commands/crc.c;
common = lib/crc.c;
};
module = {
name = date;
common = commands/date.c;
@ -491,6 +527,10 @@ module = {
name = halt;
nopc = commands/halt.c;
i386_pc = commands/i386/pc/halt.c;
i386_pc = commands/acpihalt.c;
i386_coreboot = commands/acpihalt.c;
i386_multiboot = commands/acpihalt.c;
x86_efi = commands/acpihalt.c;
i386_multiboot = lib/i386/halt.c;
i386_coreboot = lib/i386/halt.c;
i386_qemu = lib/i386/halt.c;
@ -671,15 +711,8 @@ module = {
};
module = {
name = vbeinfo;
i386_pc = commands/i386/pc/vbeinfo.c;
enable = i386_pc;
};
module = {
name = vbetest;
i386_pc = commands/i386/pc/vbetest.c;
enable = i386_pc;
name = videoinfo;
common = commands/videoinfo.c;
};
module = {
@ -708,10 +741,15 @@ module = {
};
module = {
name = mdraid;
name = mdraid09;
common = disk/mdraid_linux.c;
};
module = {
name = mdraid1x;
common = disk/mdraid1x_linux.c;
};
module = {
name = raid;
common = disk/raid.c;
@ -833,6 +871,11 @@ module = {
common = fs/befs_be.c;
};
module = {
name = btrfs;
common = fs/btrfs.c;
};
module = {
name = cpio;
common = fs/cpio.c;
@ -878,6 +921,11 @@ module = {
common = fs/minix.c;
};
module = {
name = minix2;
common = fs/minix2.c;
};
module = {
name = nilfs2;
common = fs/nilfs2.c;
@ -1009,6 +1057,9 @@ module = {
powerpc = lib/powerpc/relocator_asm.S;
powerpc = lib/powerpc/relocator.c;
extra_dist = lib/i386/relocator_common.S;
extra_dist = kern/powerpc/cache_flush.S;
enable = mips;
enable = powerpc;
enable = x86;
@ -1084,6 +1135,7 @@ module = {
module = {
name = linux;
x86 = loader/i386/linux.c;
i386_pc = lib/i386/pc/vesa_modes_table.c;
mips = loader/mips/linux.c;
powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c;
sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c;
@ -1160,6 +1212,8 @@ module = {
common = script/lexer.c;
common = script/argv.c;
common = commands/menuentry.c;
common = unidata.c;
common_nodist = grub_script.tab.c;
common_nodist = grub_script.yy.c;
@ -1404,3 +1458,43 @@ module = {
emu = net/drivers/emu/emunet.c;
enable = ieee1275;
};
module = {
name = legacycfg;
common = commands/legacycfg.c;
common = lib/legacy_parse.c;
emu = lib/i386/pc/vesa_modes_table.c;
enable = i386_pc;
enable = emu;
};
module = {
name = test_blockarg;
common = tests/test_blockarg.c;
};
module = {
name = xzio;
common = io/xzio.c;
common = lib/xzembed/xz_dec_bcj.c;
common = lib/xzembed/xz_dec_lzma2.c;
common = lib/xzembed/xz_dec_stream.c;
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed';
};
module = {
name = testload;
common = commands/testload.c;
};
module = {
name = lsapm;
common = commands/i386/pc/lsapm.c;
enable = i386_pc;
};
module = {
name = keylayouts;
common = commands/keylayouts.c;
enable = videomodules;
};

View file

@ -112,12 +112,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.

View file

@ -185,7 +185,7 @@ real_code_2:
call LOCAL(move_memory)
/* Check for multiboot signature. */
cmpl $MULTIBOOT_HEADER_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_MACHINE_DATA_END)
cmpl $MULTIBOOT_HEADER_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_I386_PC_MULTIBOOT_SIGNATURE)
jz 1f
movl (ramdisk_image - start), %esi

View file

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

View file

@ -98,7 +98,6 @@ struct grub_ohci
struct grub_pci_dma_chunk *td_chunk;
struct grub_ohci *next;
grub_ohci_td_t td_free; /* Pointer to first free TD */
int bad_OHCI;
};
static struct grub_ohci *ohci;
@ -149,8 +148,8 @@ typedef enum
#define GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE (1 << 4)
#define GRUB_OHCI_RESET_CONNECT_CHANGE (1 << 16)
#define GRUB_OHCI_CTRL_EDS 16
#define GRUB_OHCI_BULK_EDS 16
#define GRUB_OHCI_CTRL_EDS 256
#define GRUB_OHCI_BULK_EDS 510
#define GRUB_OHCI_TDS 256
#define GRUB_OHCI_ED_ADDR_MASK 0x7ff
@ -442,8 +441,10 @@ grub_ohci_pci_iter (grub_pci_device_t dev,
(grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA)
& ~GRUB_OHCI_RHUB_PORT_POWER_MASK)
| GRUB_OHCI_RHUB_PORT_ALL_POWERED);
#if 0 /* We don't need it at all, handled via hotplugging */
/* Now we have hot-plugging, we need to wait for stable power only */
grub_millisleep (100);
#endif
/* Link to ohci now that initialisation is successful. */
o->next = ohci;
@ -623,7 +624,8 @@ grub_ohci_transaction (grub_ohci_td_t td,
break;
}
/* Set the token (Always generate interrupt - bits 21-23 = 0). */
/* Set the token */
token |= ( 7 << 21); /* Never generate interrupt */
token |= toggle << 24;
token |= 1 << 25;
@ -652,36 +654,31 @@ grub_ohci_transaction (grub_ohci_td_t td,
td->next_td = 0;
}
struct grub_ohci_transfer_controller_data
{
grub_uint32_t tderr_phys;
grub_uint32_t td_last_phys;
grub_ohci_ed_t ed_virt;
grub_ohci_td_t td_current_virt;
grub_ohci_td_t td_head_virt;
};
static grub_usb_err_t
grub_ohci_transfer (grub_usb_controller_t dev,
grub_usb_transfer_t transfer, int timeout,
grub_size_t *actual)
grub_ohci_setup_transfer (grub_usb_controller_t dev,
grub_usb_transfer_t transfer)
{
struct grub_ohci *o = (struct grub_ohci *) dev->data;
grub_ohci_ed_t ed_virt;
int bulk = 0;
grub_ohci_td_t td_head_virt;
grub_ohci_td_t td_current_virt;
grub_ohci_td_t td_next_virt;
grub_ohci_td_t tderr_virt = NULL;
grub_uint32_t target;
grub_uint32_t td_head_phys;
grub_uint32_t td_tail_phys;
grub_uint32_t td_last_phys;
grub_uint32_t tderr_phys = 0;
grub_uint32_t status;
grub_uint32_t control;
grub_uint8_t errcode = 0;
grub_usb_err_t err = GRUB_USB_ERR_NONE;
int i;
grub_uint64_t maxtime;
grub_uint64_t bad_OHCI_delay = 0;
int err_halt = 0;
int err_timeout = 0;
int err_unrec = 0;
grub_uint32_t intstatus;
struct grub_ohci_transfer_controller_data *cdata;
*actual = 0;
cdata = grub_zalloc (sizeof (*cdata));
if (!cdata)
return GRUB_USB_ERR_INTERNAL;
/* Pre-set target for ED - we need it to find proper ED */
/* Set the device address. */
@ -703,21 +700,23 @@ grub_ohci_transfer (grub_usb_controller_t dev,
case GRUB_USB_TRANSACTION_TYPE_CONTROL:
break;
default :
default:
grub_free (cdata);
return GRUB_USB_ERR_INTERNAL;
}
/* Find proper ED or add new ED */
ed_virt = grub_ohci_find_ed (o, bulk, target);
if (!ed_virt)
cdata->ed_virt = grub_ohci_find_ed (o, bulk, target);
if (!cdata->ed_virt)
{
grub_dprintf ("ohci","Fatal: No free ED !\n");
grub_free (cdata);
return GRUB_USB_ERR_INTERNAL;
}
/* Take pointer to first TD from ED */
td_head_phys = grub_le_to_cpu32 (ed_virt->td_head) & ~0xf;
td_tail_phys = grub_le_to_cpu32 (ed_virt->td_tail) & ~0xf;
td_head_phys = grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf;
td_tail_phys = grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf;
/* Sanity check - td_head should be equal to td_tail */
if (td_head_phys != td_tail_phys) /* Should never happen ! */
@ -726,6 +725,7 @@ grub_ohci_transfer (grub_usb_controller_t dev,
grub_dprintf ("ohci", "HEAD = 0x%02x, TAIL = 0x%02x\n",
td_head_phys, td_tail_phys);
/* XXX: Fix: What to do ? */
grub_free (cdata);
return GRUB_USB_ERR_INTERNAL;
}
@ -733,65 +733,62 @@ grub_ohci_transfer (grub_usb_controller_t dev,
* we must allocate the first TD. */
if (!td_head_phys)
{
td_head_virt = grub_ohci_alloc_td (o);
if (!td_head_virt)
cdata->td_head_virt = grub_ohci_alloc_td (o);
if (!cdata->td_head_virt)
return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */
/* We can set td_head only when ED is not active, i.e.
* when it is newly allocated. */
ed_virt->td_head = grub_cpu_to_le32 ( grub_ohci_td_virt2phys (o,
td_head_virt) );
ed_virt->td_tail = ed_virt->td_head;
cdata->ed_virt->td_head
= grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, cdata->td_head_virt));
cdata->ed_virt->td_tail = cdata->ed_virt->td_head;
}
else
td_head_virt = grub_ohci_td_phys2virt ( o, td_head_phys );
cdata->td_head_virt = grub_ohci_td_phys2virt ( o, td_head_phys );
/* Set TDs */
td_last_phys = td_head_phys; /* initial value to make compiler happy... */
for (i = 0, td_current_virt = td_head_virt;
cdata->td_last_phys = td_head_phys; /* initial value to make compiler happy... */
for (i = 0, cdata->td_current_virt = cdata->td_head_virt;
i < transfer->transcnt; i++)
{
grub_usb_transaction_t tr = &transfer->transactions[i];
grub_ohci_transaction (td_current_virt, tr->pid, tr->toggle,
grub_ohci_transaction (cdata->td_current_virt, tr->pid, tr->toggle,
tr->size, tr->data);
/* Set index of TD in transfer */
td_current_virt->tr_index = (grub_uint32_t) i;
/* No IRQ request in TD if bad_OHCI set */
if (o->bad_OHCI)
td_current_virt->token |= grub_cpu_to_le32 ( 7 << 21);
cdata->td_current_virt->tr_index = (grub_uint32_t) i;
/* Remember last used (processed) TD phys. addr. */
td_last_phys = grub_ohci_td_virt2phys (o, td_current_virt);
cdata->td_last_phys = grub_ohci_td_virt2phys (o, cdata->td_current_virt);
/* Allocate next TD */
td_next_virt = grub_ohci_alloc_td (o);
if (!td_next_virt) /* No free TD, cancel transfer and free TDs except head TD */
{
if (i) /* if i==0 we have nothing to free... */
grub_ohci_free_tds (o,
grub_ohci_td_phys2virt(o,
grub_le_to_cpu32 (td_head_virt->next_td) ) );
grub_ohci_free_tds (o, grub_ohci_td_phys2virt(o,
grub_le_to_cpu32 (cdata->td_head_virt->next_td)));
/* Reset head TD */
grub_memset ( (void*)td_head_virt, 0,
grub_memset ( (void*)cdata->td_head_virt, 0,
sizeof(struct grub_ohci_td) );
grub_dprintf ("ohci", "Fatal: No free TD !");
grub_free (cdata);
return GRUB_USB_ERR_INTERNAL;
}
/* Chain TDs */
td_current_virt->link_td = td_next_virt;
td_current_virt->next_td = grub_cpu_to_le32 (
cdata->td_current_virt->link_td = td_next_virt;
cdata->td_current_virt->next_td = grub_cpu_to_le32 (
grub_ohci_td_virt2phys (o,
td_next_virt) );
td_next_virt->prev_td_phys = grub_ohci_td_virt2phys (o,
td_current_virt);
td_current_virt = td_next_virt;
cdata->td_current_virt);
cdata->td_current_virt = td_next_virt;
}
grub_dprintf ("ohci", "Tail TD (not processed) = %p\n",
td_current_virt);
cdata->td_current_virt);
/* Setup the Endpoint Descriptor for transfer. */
/* First set necessary fields in TARGET but keep (or set) skip bit */
@ -799,12 +796,12 @@ grub_ohci_transfer (grub_usb_controller_t dev,
* size never change after first allocation of ED.
* But unfortunately max. packet size may change during initial
* setup sequence and we must handle it. */
ed_virt->target = grub_cpu_to_le32 (target | (1 << 14));
cdata->ed_virt->target = grub_cpu_to_le32 (target | (1 << 14));
/* Set td_tail */
ed_virt->td_tail
= grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, td_current_virt));
cdata->ed_virt->td_tail
= grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, cdata->td_current_virt));
/* Now reset skip bit */
ed_virt->target = grub_cpu_to_le32 (target);
cdata->ed_virt->target = grub_cpu_to_le32 (target);
/* ed_virt->td_head = grub_cpu_to_le32 (td_head); Must not be changed, it is maintained by OHCI */
/* ed_virt->next_ed = grub_cpu_to_le32 (0); Handled by grub_ohci_find_ed, do not change ! */
@ -834,93 +831,21 @@ grub_ohci_transfer (grub_usb_controller_t dev,
}
}
/* Safety measure to avoid a hang. */
maxtime = grub_get_time_ms () + timeout;
/* Wait until the transfer is completed or STALLs. */
do
{
/* Check transfer status */
intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
if (!o->bad_OHCI && (intstatus & 0x2) != 0)
{
/* Remember last successful TD */
tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf;
/* Reset DoneHead */
o->hcca->donehead = 0;
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1));
/* Read back of register should ensure it is really written */
grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
/* if TD is last, finish */
if (tderr_phys == td_last_phys)
{
if (grub_le_to_cpu32 (ed_virt->td_head) & 1)
err_halt = 1;
break;
}
continue;
}
transfer->controller_data = cdata;
if ((intstatus & 0x10) != 0)
{ /* Unrecoverable error - only reset can help...! */
err_unrec = 1;
break;
}
return GRUB_USB_ERR_NONE;
}
/* Detected a HALT. */
if (err_halt || (grub_le_to_cpu32 (ed_virt->td_head) & 1))
{
err_halt = 1;
/* ED is halted, but donehead event can happened in the meantime */
intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
if (!o->bad_OHCI && (intstatus & 0x2) != 0)
/* Don't break loop now, first do donehead action(s) */
continue;
break;
}
/* bad OHCI handling */
if ( (grub_le_to_cpu32 (ed_virt->td_head) & ~0xf) ==
(grub_le_to_cpu32 (ed_virt->td_tail) & ~0xf) ) /* Empty ED */
{
if (o->bad_OHCI) /* Bad OHCI detected previously */
{
/* Try get last successful TD. */
tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf;
if (tderr_phys)/* Reset DoneHead if we were successful */
{
o->hcca->donehead = 0;
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1));
/* Read back of register should ensure it is really written */
grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
}
/* Check the HALT bit */
if (grub_le_to_cpu32 (ed_virt->td_head) & 1)
err_halt = 1;
break;
}
else /* Detection of bad OHCI */
/* We should wait short time (~2ms) before we say that
* it is bad OHCI to prevent some hazard -
* donehead can react in the meantime. This waiting is done
* only once per OHCI driver "live cycle". */
if (!bad_OHCI_delay) /* Set delay time */
bad_OHCI_delay = grub_get_time_ms () + 2;
else if (grub_get_time_ms () >= bad_OHCI_delay)
o->bad_OHCI = 1;
continue;
}
/* Timeout ? */
if (grub_get_time_ms () > maxtime)
{
err_timeout = 1;
break;
}
grub_cpu_idle ();
}
while (1);
static void
pre_finish_transfer (grub_usb_controller_t dev,
grub_usb_transfer_t transfer)
{
struct grub_ohci *o = dev->data;
struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data;
grub_uint32_t target;
grub_uint32_t status;
grub_uint32_t control;
grub_uint32_t intstatus;
/* There are many ways how the loop above can finish:
* - normally without any error via INTSTATUS WDH bit
@ -952,8 +877,8 @@ grub_ohci_transfer (grub_usb_controller_t dev,
/* Remember target for debug and set skip flag in ED */
/* It should be normaly not necessary but we need it at least
* in case of timeout */
target = grub_le_to_cpu32 ( ed_virt->target );
ed_virt->target = grub_cpu_to_le32 (target | (1 << 14));
target = grub_le_to_cpu32 ( cdata->ed_virt->target );
cdata->ed_virt->target = grub_cpu_to_le32 (target | (1 << 14));
/* Read registers for debug - they should be read now because
* debug prints case unwanted delays, so something can happen
* in the meantime... */
@ -963,253 +888,321 @@ grub_ohci_transfer (grub_usb_controller_t dev,
/* Now print debug values - to have full info what happened */
grub_dprintf ("ohci", "loop finished: control=0x%02x status=0x%02x\n",
control, status);
grub_dprintf ("ohci", "intstatus=0x%02x \n\t\t tderr_phys=0x%02x, td_last_phys=0x%02x\n",
intstatus, tderr_phys, td_last_phys);
grub_dprintf ("ohci", "err_unrec=%d, err_timeout=%d \n\t\t err_halt=%d, bad_OHCI=%d\n",
err_unrec, err_timeout, err_halt, o->bad_OHCI);
grub_dprintf ("ohci", "intstatus=0x%02x, td_last_phys=0x%02x\n",
intstatus, cdata->td_last_phys);
grub_dprintf ("ohci", "TARGET=0x%02x, HEAD=0x%02x, TAIL=0x%02x\n",
target,
grub_le_to_cpu32 (ed_virt->td_head),
grub_le_to_cpu32 (ed_virt->td_tail) );
grub_le_to_cpu32 (cdata->ed_virt->td_head),
grub_le_to_cpu32 (cdata->ed_virt->td_tail) );
if (!err_halt && !err_unrec && !err_timeout) /* normal finish */
{
/* Simple workaround if donehead is not working */
if (o->bad_OHCI &&
( !tderr_phys || (tderr_phys != td_last_phys) ) )
{
grub_dprintf ("ohci", "normal finish, but tderr_phys corrected\n");
tderr_phys = td_last_phys;
/* I hope we can do it as transfer (most probably) finished OK */
}
/* Prepare pointer to last processed TD */
tderr_virt = grub_ohci_td_phys2virt (o, tderr_phys);
/* Set index of last processed TD */
if (tderr_virt)
transfer->last_trans = tderr_virt->tr_index;
else
transfer->last_trans = -1;
*actual = transfer->size + 1;
}
}
else if (err_halt) /* error, ED is halted by OHCI, i.e. can be modified */
{
/* First we must get proper tderr_phys value */
if (o->bad_OHCI) /* In case of bad_OHCI tderr_phys can be wrong */
{
if ( tderr_phys ) /* check if tderr_phys points to TD with error */
errcode = grub_le_to_cpu32 ( grub_ohci_td_phys2virt (o,
tderr_phys)->token )
>> 28;
if ( !tderr_phys || !errcode ) /* tderr_phys not valid or points to wrong TD */
{ /* Retired TD with error should be previous TD to ED->td_head */
tderr_phys = grub_ohci_td_phys2virt (o,
grub_le_to_cpu32 ( ed_virt->td_head) & ~0xf )
->prev_td_phys;
}
}
/* Even if we have "good" OHCI, in some cases
* tderr_phys can be zero, check it */
else if ( !tderr_phys )
{ /* Retired TD with error should be previous TD to ED->td_head */
tderr_phys = grub_ohci_td_phys2virt (o,
grub_le_to_cpu32 ( ed_virt->td_head) & ~0xf )
->prev_td_phys;
}
/* Prepare pointer to last processed TD and get error code */
tderr_virt = grub_ohci_td_phys2virt (o, tderr_phys);
/* Set index of last processed TD */
if (tderr_virt)
{
errcode = grub_le_to_cpu32 ( tderr_virt->token ) >> 28;
transfer->last_trans = tderr_virt->tr_index;
}
else
transfer->last_trans = -1;
/* Evaluation of error code */
grub_dprintf ("ohci", "OHCI tderr_phys=0x%02x, errcode=0x%02x\n",
tderr_phys, errcode);
switch (errcode)
{
case 0:
/* XXX: Should not happen! */
grub_error (GRUB_ERR_IO, "OHCI failed without reporting the reason");
err = GRUB_USB_ERR_INTERNAL;
break;
case 1:
/* XXX: CRC error. */
err = GRUB_USB_ERR_TIMEOUT;
break;
case 2:
err = GRUB_USB_ERR_BITSTUFF;
break;
case 3:
/* XXX: Data Toggle error. */
err = GRUB_USB_ERR_DATA;
break;
case 4:
err = GRUB_USB_ERR_STALL;
break;
case 5:
/* XXX: Not responding. */
err = GRUB_USB_ERR_TIMEOUT;
break;
case 6:
/* XXX: PID Check bits failed. */
err = GRUB_USB_ERR_BABBLE;
break;
case 7:
/* XXX: PID unexpected failed. */
err = GRUB_USB_ERR_BABBLE;
break;
case 8:
/* XXX: Data overrun error. */
err = GRUB_USB_ERR_DATA;
grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n",
tderr_virt, tderr_virt->tr_index);
break;
case 9:
/* XXX: Data underrun error. */
grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n",
tderr_virt, tderr_virt->tr_index);
if (transfer->last_trans == -1)
break;
*actual = transfer->transactions[transfer->last_trans].size
- (grub_le_to_cpu32 (tderr_virt->buffer_end)
- grub_le_to_cpu32 (tderr_virt->buffer))
+ transfer->transactions[transfer->last_trans].preceding;
break;
case 10:
/* XXX: Reserved. */
err = GRUB_USB_ERR_NAK;
break;
case 11:
/* XXX: Reserved. */
err = GRUB_USB_ERR_NAK;
break;
case 12:
/* XXX: Buffer overrun. */
err = GRUB_USB_ERR_DATA;
break;
case 13:
/* XXX: Buffer underrun. */
err = GRUB_USB_ERR_DATA;
break;
default:
err = GRUB_USB_ERR_NAK;
break;
}
}
else if (err_unrec)
{
/* Don't try to get error code and last processed TD for proper
* toggle bit value - anything can be invalid */
err = GRUB_USB_ERR_UNRECOVERABLE;
grub_dprintf("ohci", "Unrecoverable error!");
/* Do OHCI reset in case of unrecoverable error - maybe we will need
* do more - re-enumerate bus etc. (?) */
/* Suspend the OHCI by issuing a reset. */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */
/* Read back of register should ensure it is really written */
grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
grub_millisleep (1);
grub_dprintf ("ohci", "Unrecoverable error - OHCI reset\n");
/* Misc. resets. */
o->hcca->donehead = 0;
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, o->ed_ctrl_addr);
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, o->ed_bulk_addr);
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
/* Read back of register should ensure it is really written */
grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
/* Enable the OHCI. */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL,
(2 << 6)
| GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE
| GRUB_OHCI_REG_CONTROL_BULK_ENABLE );
}
else if (err_timeout)
{
/* In case of timeout do not detect error from TD */
err = GRUB_ERR_TIMEOUT;
grub_dprintf("ohci", "Timeout !\n");
/* We should wait for next SOF to be sure that ED is unaccessed
* by OHCI */
/* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2));
/* Wait for new SOF */
while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0);
/* Now we must find last processed TD if bad_OHCI == TRUE */
if (o->bad_OHCI)
{ /* Retired TD with error should be previous TD to ED->td_head */
tderr_phys = grub_ohci_td_phys2virt (o,
grub_le_to_cpu32 ( ed_virt->td_head) & ~0xf)
->prev_td_phys;
}
tderr_virt = grub_ohci_td_phys2virt (o, tderr_phys);
if (tderr_virt)
transfer->last_trans = tderr_virt->tr_index;
else
transfer->last_trans = -1;
}
static void
finish_transfer (grub_usb_controller_t dev,
grub_usb_transfer_t transfer)
{
struct grub_ohci *o = dev->data;
struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data;
/* Set empty ED - set HEAD = TAIL = last (not processed) TD */
ed_virt->td_head = grub_cpu_to_le32 (grub_le_to_cpu32 (ed_virt->td_tail) & ~0xf);
cdata->ed_virt->td_head = grub_cpu_to_le32 (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf);
/* At this point always should be:
* ED has skip bit set and halted or empty or after next SOF,
* i.e. it is safe to free all TDs except last not processed
* ED HEAD == TAIL == phys. addr. of td_current_virt */
/* Reset DoneHead - sanity cleanup */
/* Un-chainig of last TD */
if (cdata->td_current_virt->prev_td_phys)
{
grub_ohci_td_t td_prev_virt
= grub_ohci_td_phys2virt (o, cdata->td_current_virt->prev_td_phys);
if (cdata->td_current_virt == (grub_ohci_td_t) td_prev_virt->link_td)
td_prev_virt->link_td = 0;
cdata->td_current_virt->prev_td_phys = 0;
}
grub_dprintf ("ohci", "OHCI finished, freeing\n");
grub_ohci_free_tds (o, cdata->td_head_virt);
grub_free (cdata);
}
static grub_usb_err_t
parse_halt (grub_usb_controller_t dev,
grub_usb_transfer_t transfer,
grub_size_t *actual)
{
struct grub_ohci *o = dev->data;
struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data;
grub_uint8_t errcode = 0;
grub_usb_err_t err = GRUB_USB_ERR_NAK;
grub_ohci_td_t tderr_virt = NULL;
*actual = 0;
pre_finish_transfer (dev, transfer);
/* First we must get proper tderr_phys value */
/* Retired TD with error should be previous TD to ED->td_head */
cdata->tderr_phys = grub_ohci_td_phys2virt (o,
grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf )
->prev_td_phys;
/* Prepare pointer to last processed TD and get error code */
tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys);
/* Set index of last processed TD */
if (tderr_virt)
{
errcode = grub_le_to_cpu32 (tderr_virt->token) >> 28;
transfer->last_trans = tderr_virt->tr_index;
}
else
transfer->last_trans = -1;
/* Evaluation of error code */
grub_dprintf ("ohci", "OHCI tderr_phys=0x%02x, errcode=0x%02x\n",
cdata->tderr_phys, errcode);
switch (errcode)
{
case 0:
/* XXX: Should not happen! */
grub_error (GRUB_ERR_IO, "OHCI failed without reporting the reason");
err = GRUB_USB_ERR_INTERNAL;
break;
case 1:
/* XXX: CRC error. */
err = GRUB_USB_ERR_TIMEOUT;
break;
case 2:
err = GRUB_USB_ERR_BITSTUFF;
break;
case 3:
/* XXX: Data Toggle error. */
err = GRUB_USB_ERR_DATA;
break;
case 4:
err = GRUB_USB_ERR_STALL;
break;
case 5:
/* XXX: Not responding. */
err = GRUB_USB_ERR_TIMEOUT;
break;
case 6:
/* XXX: PID Check bits failed. */
err = GRUB_USB_ERR_BABBLE;
break;
case 7:
/* XXX: PID unexpected failed. */
err = GRUB_USB_ERR_BABBLE;
break;
case 8:
/* XXX: Data overrun error. */
err = GRUB_USB_ERR_DATA;
grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n",
tderr_virt, tderr_virt->tr_index);
break;
case 9:
/* XXX: Data underrun error. */
grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n",
tderr_virt, tderr_virt->tr_index);
if (transfer->last_trans == -1)
break;
*actual = transfer->transactions[transfer->last_trans].size
- (grub_le_to_cpu32 (tderr_virt->buffer_end)
- grub_le_to_cpu32 (tderr_virt->buffer))
+ transfer->transactions[transfer->last_trans].preceding;
err = GRUB_USB_ERR_NONE;
break;
case 10:
/* XXX: Reserved. */
err = GRUB_USB_ERR_NAK;
break;
case 11:
/* XXX: Reserved. */
err = GRUB_USB_ERR_NAK;
break;
case 12:
/* XXX: Buffer overrun. */
err = GRUB_USB_ERR_DATA;
break;
case 13:
/* XXX: Buffer underrun. */
err = GRUB_USB_ERR_DATA;
break;
default:
err = GRUB_USB_ERR_NAK;
break;
}
finish_transfer (dev, transfer);
return err;
}
static grub_usb_err_t
parse_success (grub_usb_controller_t dev,
grub_usb_transfer_t transfer,
grub_size_t *actual)
{
struct grub_ohci *o = dev->data;
struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data;
grub_ohci_td_t tderr_virt = NULL;
pre_finish_transfer (dev, transfer);
/* I hope we can do it as transfer (most probably) finished OK */
cdata->tderr_phys = cdata->td_last_phys;
/* Prepare pointer to last processed TD */
tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys);
/* Set index of last processed TD */
if (tderr_virt)
transfer->last_trans = tderr_virt->tr_index;
else
transfer->last_trans = -1;
*actual = transfer->size + 1;
finish_transfer (dev, transfer);
return GRUB_USB_ERR_NONE;
}
static grub_usb_err_t
parse_unrec (grub_usb_controller_t dev,
grub_usb_transfer_t transfer,
grub_size_t *actual)
{
struct grub_ohci *o = dev->data;
*actual = 0;
pre_finish_transfer (dev, transfer);
/* Don't try to get error code and last processed TD for proper
* toggle bit value - anything can be invalid */
grub_dprintf("ohci", "Unrecoverable error!");
/* Do OHCI reset in case of unrecoverable error - maybe we will need
* do more - re-enumerate bus etc. (?) */
/* Suspend the OHCI by issuing a reset. */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */
/* Read back of register should ensure it is really written */
grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS);
grub_millisleep (1);
grub_dprintf ("ohci", "Unrecoverable error - OHCI reset\n");
/* Misc. resets. */
o->hcca->donehead = 0;
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1));
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, o->ed_ctrl_addr);
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0);
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, o->ed_bulk_addr);
grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0);
/* Read back of register should ensure it is really written */
grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
/* Un-chainig of last TD */
if (td_current_virt->prev_td_phys)
{
grub_ohci_td_t td_prev_virt
= grub_ohci_td_phys2virt (o, td_current_virt->prev_td_phys);
/* Enable the OHCI. */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL,
(2 << 6)
| GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE
| GRUB_OHCI_REG_CONTROL_BULK_ENABLE );
finish_transfer (dev, transfer);
td_next_virt = (grub_ohci_td_t) td_prev_virt->link_td;
if (td_current_virt == td_next_virt)
td_prev_virt->link_td = 0;
return GRUB_USB_ERR_UNRECOVERABLE;
}
static grub_usb_err_t
grub_ohci_check_transfer (grub_usb_controller_t dev,
grub_usb_transfer_t transfer,
grub_size_t *actual)
{
struct grub_ohci *o = dev->data;
struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data;
grub_uint32_t intstatus;
/* Check transfer status */
intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS);
if ((intstatus & 0x10) != 0)
/* Unrecoverable error - only reset can help...! */
return parse_unrec (dev, transfer, actual);
/* Detected a HALT. */
if ((grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1))
return parse_halt (dev, transfer, actual);
/* Finished ED detection */
if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf) ==
(grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf) ) /* Empty ED */
{
/* Check the HALT bit */
/* It looks like nonsense - it was tested previously...
* but it can change because OHCI is working
* simultaneously via DMA... */
if (grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1)
return parse_halt (dev, transfer, actual);
else
return parse_success (dev, transfer, actual);
}
grub_dprintf ("ohci", "OHCI finished, freeing, err=0x%02x, errcode=0x%02x\n",
err, errcode);
grub_ohci_free_tds (o, td_head_virt);
return GRUB_USB_ERR_WAIT;
}
return err;
static grub_usb_err_t
grub_ohci_cancel_transfer (grub_usb_controller_t dev,
grub_usb_transfer_t transfer)
{
struct grub_ohci *o = dev->data;
struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data;
grub_ohci_td_t tderr_virt = NULL;
pre_finish_transfer (dev, transfer);
grub_dprintf("ohci", "Timeout !\n");
/* We should wait for next SOF to be sure that ED is unaccessed
* by OHCI */
/* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2));
/* Wait for new SOF */
while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0);
/* Possible retired TD with error should be previous TD to ED->td_head */
cdata->tderr_phys
= grub_ohci_td_phys2virt (o, grub_le_to_cpu32 (cdata->ed_virt->td_head)
& ~0xf)->prev_td_phys;
tderr_virt = grub_ohci_td_phys2virt (o,cdata-> tderr_phys);
grub_dprintf ("ohci", "Cancel: tderr_phys=0x%x, tderr_virt=%p\n",
cdata->tderr_phys, tderr_virt);
if (tderr_virt)
transfer->last_trans = tderr_virt->tr_index;
else
transfer->last_trans = -1;
finish_transfer (dev, transfer);
return GRUB_USB_ERR_NONE;
}
static grub_err_t
@ -1218,6 +1211,7 @@ grub_ohci_portstatus (grub_usb_controller_t dev,
{
struct grub_ohci *o = (struct grub_ohci *) dev->data;
grub_uint64_t endtime;
int i;
grub_dprintf ("ohci", "begin of portstatus=0x%02x\n",
grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port));
@ -1238,31 +1232,47 @@ grub_ohci_portstatus (grub_usb_controller_t dev,
return GRUB_ERR_NONE;
}
/* Reset the port */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
GRUB_OHCI_SET_PORT_RESET);
grub_millisleep (50); /* For root hub should be nominaly 50ms */
/* End the reset signaling. */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE);
grub_millisleep (10);
/* OHCI does one reset signal 10ms long but USB spec.
* requests 50ms for root hub (no need to be continuous).
* So, we do reset 5 times... */
for (i = 0; i < 5; i++)
{
/* Reset the port - timing of reset is done by OHCI */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
GRUB_OHCI_SET_PORT_RESET);
/* Enable the port and wait for it. */
/* Wait for reset completion */
endtime = grub_get_time_ms () + 1000;
while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)
& GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE))
if (grub_get_time_ms () > endtime)
return grub_error (GRUB_ERR_IO, "OHCI Timed out - reset");
/* End the reset signaling - reset the reset status change */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE);
grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
}
/* Enable port */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
GRUB_OHCI_SET_PORT_ENABLE);
grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port);
/* Wait for signal enabled */
endtime = grub_get_time_ms () + 1000;
while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)
& (1 << 1)))
if (grub_get_time_ms () > endtime)
return grub_error (GRUB_ERR_IO, "OHCI Timed out - enable");
grub_millisleep (10);
/* Reset bit Connect Status Change */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
GRUB_OHCI_RESET_CONNECT_CHANGE);
/* "Reset recovery time" (USB spec.) */
grub_millisleep (10);
grub_dprintf ("ohci", "end of portstatus=0x%02x\n",
grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port));
@ -1279,8 +1289,16 @@ grub_ohci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
grub_dprintf ("ohci", "detect_dev status=0x%02x\n", status);
/* Connect Status Change bit - it detects change of connection */
*changed = ((status & GRUB_OHCI_RESET_CONNECT_CHANGE) != 0);
/* Connect Status Change bit - it detects change of connection */
if (status & GRUB_OHCI_RESET_CONNECT_CHANGE)
{
*changed = 1;
/* Reset bit Connect Status Change */
grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port,
GRUB_OHCI_RESET_CONNECT_CHANGE);
}
else
*changed = 0;
if (! (status & 1))
return GRUB_USB_SPEED_NONE;
@ -1398,7 +1416,9 @@ static struct grub_usb_controller_dev usb_controller =
{
.name = "ohci",
.iterate = grub_ohci_iterate,
.transfer = grub_ohci_transfer,
.setup_transfer = grub_ohci_setup_transfer,
.check_transfer = grub_ohci_check_transfer,
.cancel_transfer = grub_ohci_cancel_transfer,
.hubports = grub_ohci_hubports,
.portstatus = grub_ohci_portstatus,
.detect_dev = grub_ohci_detect_dev

View file

@ -44,6 +44,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 +81,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);

View file

@ -28,6 +28,8 @@
#define GRUB_UHCI_IOMASK (0x7FF << 5)
#define N_QH 256
typedef enum
{
GRUB_UHCI_REG_USBCMD = 0x00,
@ -39,6 +41,19 @@ typedef enum
#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,7 +102,7 @@ struct grub_uhci
int iobase;
grub_uint32_t *framelist;
/* 256 Queue Heads. */
/* N_QH Queue Heads. */
grub_uhci_qh_t qh;
/* 256 Transfer Descriptors. */
@ -96,6 +111,8 @@ struct grub_uhci
/* Free Transfer Descriptors. */
grub_uhci_td_t tdfree;
int qh_busy[N_QH];
struct grub_uhci *next;
};
@ -248,7 +265,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,9 +278,8 @@ 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));
@ -332,11 +348,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 +393,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 +415,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 +440,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 +459,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 +495,26 @@ 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_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 +530,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 +686,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 +694,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);
@ -683,7 +756,15 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
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 +786,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

View file

@ -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;
@ -110,9 +112,6 @@ grub_usb_add_hub (grub_usb_device_t dev)
struct grub_usb_usb_hubdesc hubdesc;
grub_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,45 @@ 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;
/* 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 +264,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 +288,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 +309,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 +349,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_printf ("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 *) &current_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 +497,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 +522,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);
}
}

View file

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

View file

@ -23,10 +23,8 @@
#include <grub/disk.h>
#include <grub/term.h>
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/acpi.h>
#include <grub/mm.h>
#include <grub/machine/memory.h>
#include <grub/memory.h>
#include <grub/i18n.h>
@ -152,10 +150,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;
@ -181,7 +179,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;
@ -325,7 +323,7 @@ setup_common_tables (void)
/* If it's FADT correct DSDT and FACS addresses. */
fadt = (struct grub_acpi_fadt *) cur->addr;
if (grub_memcmp (fadt->hdr.signature, "FACP",
if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE,
sizeof (fadt->hdr.signature)) == 0)
{
fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt);
@ -458,10 +456,9 @@ free_tables (void)
}
static grub_err_t
grub_cmd_acpi (struct grub_extcmd *cmd,
int argc, char **args)
grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
struct grub_acpi_rsdp_v10 *rsdp;
struct efiemu_acpi_table *cur, *t;
grub_err_t err;
@ -529,7 +526,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd,
struct grub_acpi_fadt *fadt = (struct grub_acpi_fadt *) curtable;
/* Set root header variables to the same values
as FACP by default. */
as FADT by default. */
grub_memcpy (&root_oemid, &(fadt->hdr.oemid),
sizeof (root_oemid));
grub_memcpy (&root_oemtable, &(fadt->hdr.oemtable),
@ -629,7 +626,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd,
grub_size_t size;
char *buf;
file = grub_gzfile_open (args[i], 1);
file = grub_file_open (args[i]);
if (! file)
{
free_tables ();
@ -706,7 +703,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd,
playground = playground_ptr
= grub_mmap_malign_and_register (1, playground_size, &mmapregion,
GRUB_MACHINE_MEMORY_ACPI, 0);
GRUB_MEMORY_ACPI, 0);
if (! playground)
{
@ -760,8 +757,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(acpi)
{
cmd = grub_register_extcmd ("acpi", grub_cmd_acpi,
GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("acpi", grub_cmd_acpi, 0,
N_("[-1|-2] [--exclude=TABLE1,TABLE2|"
"--load-only=table1,table2] FILE1"
" [FILE2] [...]"),

View file

@ -0,0 +1,266 @@
/*
* 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/acpi.h>
#include <grub/misc.h>
#include <grub/cpu/io.h>
static inline grub_uint32_t
decode_length (const grub_uint8_t *ptr, int *numlen)
{
int num_bytes, i;
grub_uint32_t ret;
if (*ptr < 64)
{
if (numlen)
*numlen = 1;
return *ptr;
}
num_bytes = *ptr >> 6;
if (numlen)
*numlen = num_bytes + 1;
ret = *ptr & 0xf;
ptr++;
for (i = 0; i < num_bytes; i++)
{
ret |= *ptr << (8 * i + 4);
ptr++;
}
return ret;
}
static inline grub_uint32_t
skip_name_string (const grub_uint8_t *ptr, const grub_uint8_t *end)
{
const grub_uint8_t *ptr0 = ptr;
while (ptr < end && (*ptr == '^' || *ptr == '\\'))
ptr++;
switch (*ptr)
{
case '.':
ptr++;
ptr += 8;
break;
case '/':
ptr++;
ptr += 1 + (*ptr) * 4;
break;
case 0:
ptr++;
break;
default:
ptr += 4;
break;
}
return ptr - ptr0;
}
static inline grub_uint32_t
skip_data_ref_object (const grub_uint8_t *ptr, const grub_uint8_t *end)
{
grub_dprintf ("acpi", "data type = 0x%x\n", *ptr);
switch (*ptr)
{
case GRUB_ACPI_OPCODE_PACKAGE:
return 1 + decode_length (ptr + 1, 0);
case GRUB_ACPI_OPCODE_ZERO:
case GRUB_ACPI_OPCODE_ONES:
case GRUB_ACPI_OPCODE_ONE:
return 1;
case GRUB_ACPI_OPCODE_BYTE_CONST:
return 2;
case GRUB_ACPI_OPCODE_WORD_CONST:
return 3;
case GRUB_ACPI_OPCODE_DWORD_CONST:
return 5;
default:
if (*ptr == '^' || *ptr == '\\' || *ptr == '_'
|| (*ptr >= 'A' && *ptr <= 'Z'))
return skip_name_string (ptr, end);
grub_printf ("Unknown opcode 0x%x\n", *ptr);
return 0;
}
}
static inline grub_uint32_t
skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end)
{
const grub_uint8_t *ptr0 = ptr;
int add;
grub_dprintf ("acpi", "Extended opcode: 0x%x\n", *ptr);
switch (*ptr)
{
case GRUB_ACPI_EXTOPCODE_MUTEX:
ptr++;
ptr += skip_name_string (ptr, end);
ptr++;
break;
case GRUB_ACPI_EXTOPCODE_OPERATION_REGION:
ptr++;
ptr += skip_name_string (ptr, end);
ptr++;
ptr += add = skip_data_ref_object (ptr, end);
if (!add)
return 0;
ptr += add = skip_data_ref_object (ptr, end);
if (!add)
return 0;
break;
case GRUB_ACPI_EXTOPCODE_FIELD_OP:
ptr++;
ptr += decode_length (ptr, 0);
break;
default:
grub_printf ("Unexpected extended opcode: 0x%x\n", *ptr);
return 0;
}
return ptr - ptr0;
}
static int
get_sleep_type (grub_uint8_t *table, grub_uint8_t *end)
{
grub_uint8_t *ptr, *prev;
int sleep_type = -1;
ptr = table + sizeof (struct grub_acpi_table_header);
while (ptr < end && prev < ptr)
{
int add;
prev = ptr;
grub_dprintf ("acpi", "Opcode 0x%x\n", *ptr);
grub_dprintf ("acpi", "Tell %x\n", (unsigned) (ptr - table));
switch (*ptr)
{
case GRUB_ACPI_OPCODE_EXTOP:
ptr++;
ptr += add = skip_ext_op (ptr, end);
if (!add)
return -1;
break;
case GRUB_ACPI_OPCODE_NAME:
ptr++;
if (memcmp (ptr, "_S5_", 4) == 0)
{
int ll;
grub_uint8_t *ptr2 = ptr;
ptr2 += 4;
if (*ptr2 != 0x12)
{
grub_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2);
return -1;
}
ptr2++;
decode_length (ptr2, &ll);
ptr2 += ll;
ptr2++;
switch (*ptr2)
{
case GRUB_ACPI_OPCODE_ZERO:
sleep_type = 0;
break;
case GRUB_ACPI_OPCODE_ONE:
sleep_type = 1;
break;
case GRUB_ACPI_OPCODE_BYTE_CONST:
sleep_type = ptr2[1];
break;
default:
grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2);
return -1;
}
}
ptr += add = skip_name_string (ptr, end);
if (!add)
return -1;
ptr += add = skip_data_ref_object (ptr, end);
if (!add)
return -1;
break;
case GRUB_ACPI_OPCODE_SCOPE:
case GRUB_ACPI_OPCODE_IF:
case GRUB_ACPI_OPCODE_METHOD:
{
ptr++;
ptr += decode_length (ptr, 0);
break;
}
}
}
grub_dprintf ("acpi", "TYP = %d\n", sleep_type);
return sleep_type;
}
void
grub_acpi_halt (void)
{
struct grub_acpi_rsdp_v20 *rsdp2;
struct grub_acpi_rsdp_v10 *rsdp1;
struct grub_acpi_table_header *rsdt;
grub_uint32_t *entry_ptr;
rsdp2 = grub_acpi_get_rsdpv2 ();
if (rsdp2)
rsdp1 = &(rsdp2->rsdpv1);
else
rsdp1 = grub_acpi_get_rsdpv1 ();
grub_dprintf ("acpi", "rsdp1=%p\n", rsdp1);
if (!rsdp1)
return;
rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp1->rsdt_addr;
for (entry_ptr = (grub_uint32_t *) (rsdt + 1);
entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt)
+ rsdt->length);
entry_ptr++)
{
if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "FACP", 4) == 0)
{
grub_uint32_t port;
struct grub_acpi_fadt *fadt
= ((struct grub_acpi_fadt *) (grub_addr_t) *entry_ptr);
struct grub_acpi_table_header *dsdt
= (struct grub_acpi_table_header *) (grub_addr_t) fadt->dsdt_addr;
int sleep_type = -1;
port = fadt->pm1a;
grub_dprintf ("acpi", "PM1a port=%x\n", port);
if (grub_memcmp (dsdt->signature, "DSDT",
sizeof (dsdt->signature)) != 0)
break;
sleep_type = get_sleep_type ((grub_uint8_t *) dsdt,
(grub_uint8_t *) dsdt + dsdt->length);
if (sleep_type < 0 || sleep_type >= 8)
break;
grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n",
sleep_type, port);
grub_outw (GRUB_ACPI_SLP_EN
| (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET), port & 0xffff);
}
}
grub_printf ("ACPI shutdown failed\n");
}

View file

@ -82,6 +82,7 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)),
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
grub_file_filter_disable_compression ();
file = grub_file_open (args[0]);
if (! file)
return grub_errno;

View file

@ -22,7 +22,6 @@
#include <grub/disk.h>
#include <grub/term.h>
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
@ -33,9 +32,9 @@ static const struct grub_arg_option options[] =
};
static grub_err_t
grub_cmd_cat (grub_extcmd_t cmd, int argc, char **args)
grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
int dos = 0;
grub_file_t file;
char buf[GRUB_DISK_SECTOR_SIZE];
@ -48,7 +47,7 @@ grub_cmd_cat (grub_extcmd_t cmd, int argc, char **args)
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
file = grub_gzfile_open (args[0], 1);
file = grub_file_open (args[0]);
if (! file)
return grub_errno;
@ -77,7 +76,7 @@ grub_cmd_cat (grub_extcmd_t cmd, int argc, char **args)
}
while (grub_checkkey () >= 0 &&
(key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != GRUB_TERM_ESC)
(key = grub_getkey ()) != GRUB_TERM_ESC)
;
}
@ -92,7 +91,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(cat)
{
cmd = grub_register_extcmd ("cat", grub_cmd_cat, GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("cat", grub_cmd_cat, 0,
N_("FILE"), N_("Show the contents of a file."),
options);
}

View file

@ -21,7 +21,6 @@
#include <grub/misc.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/gzio.h>
#include <grub/command.h>
#include <grub/i18n.h>
@ -44,8 +43,8 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)),
grub_printf ("Compare file `%s' with `%s':\n", args[0],
args[1]);
file1 = grub_gzfile_open (args[0], 1);
file2 = grub_gzfile_open (args[1], 1);
file1 = grub_file_open (args[0]);
file2 = grub_file_open (args[1]);
if (! file1 || ! file2)
goto cleanup;

View file

@ -27,28 +27,34 @@
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 +66,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 +90,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);
}

View file

@ -1,71 +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");
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);
}

View file

@ -30,9 +30,9 @@ static const struct grub_arg_option options[] =
};
static grub_err_t
grub_cmd_echo (grub_extcmd_t cmd, int argc, char **args)
grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
int newline = 1;
int i;
@ -113,7 +113,9 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(echo)
{
cmd = grub_register_extcmd ("echo", grub_cmd_echo, GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("echo", grub_cmd_echo,
GRUB_COMMAND_ACCEPT_DASH
| GRUB_COMMAND_OPTIONS_AT_START,
N_("[-e|-n] STRING"), N_("Display a line of text."),
options);
}

View file

@ -0,0 +1,143 @@
/* 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>
#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);
}

View file

@ -0,0 +1,107 @@
/* lsefisystab.c - Display EFI systab. */
/*
* 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/normal.h>
#include <grub/charset.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
struct guid_mapping
{
grub_efi_guid_t guid;
const char *name;
};
static const struct guid_mapping guid_mappings[] =
{
{ GRUB_EFI_ACPI_20_TABLE_GUID, "ACPI-2.0"},
{ GRUB_EFI_ACPI_TABLE_GUID, "ACPI-1.0"},
{ GRUB_EFI_SAL_TABLE_GUID, "SAL"},
{ GRUB_EFI_SMBIOS_TABLE_GUID, "SMBIOS"},
{ GRUB_EFI_MPS_TABLE_GUID, "MPS"},
{ GRUB_EFI_HCDP_TABLE_GUID, "HCDP"}
};
static grub_err_t
grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
const grub_efi_system_table_t *st = grub_efi_system_table;
grub_efi_configuration_table_t *t;
unsigned int i;
grub_printf ("Signature: %016" PRIxGRUB_UINT64_T " revision: %08x\n",
st->hdr.signature, st->hdr.revision);
{
char *vendor;
grub_uint16_t *vendor_utf16;
grub_printf ("Vendor: ");
for (vendor_utf16 = st->firmware_vendor; *vendor_utf16; vendor_utf16++);
vendor = grub_malloc (4 * (vendor_utf16 - st->firmware_vendor) + 1);
if (!vendor)
return grub_errno;
*grub_utf16_to_utf8 ((grub_uint8_t *) vendor, st->firmware_vendor,
vendor_utf16 - st->firmware_vendor) = 0;
grub_printf ("%s", vendor);
grub_free (vendor);
}
grub_printf (", Version=%x\n", st->firmware_revision);
grub_printf ("%ld tables:\n", st->num_table_entries);
t = st->configuration_table;
for (i = 0; i < st->num_table_entries; i++)
{
unsigned int j;
grub_printf ("%p ", t->vendor_table);
grub_printf ("%08x-%04x-%04x-",
t->vendor_guid.data1, t->vendor_guid.data2,
t->vendor_guid.data3);
for (j = 0; j < 8; j++)
grub_printf ("%02x", t->vendor_guid.data4[j]);
for (j = 0; j < ARRAY_SIZE (guid_mappings); j++)
if (grub_memcmp (&guid_mappings[j].guid, &t->vendor_guid,
sizeof (grub_efi_guid_t)) == 0)
grub_printf (" %s", guid_mappings[j].name);
grub_printf ("\n");
t++;
}
return GRUB_ERR_NONE;
}
static grub_command_t cmd;
GRUB_MOD_INIT(lsefisystab)
{
cmd = grub_register_command ("lsefisystab", grub_cmd_lsefisystab,
"", "Display EFI system tables.");
}
GRUB_MOD_FINI(lsefisystab)
{
grub_unregister_command (cmd);
}

View file

@ -0,0 +1,162 @@
/* lssal.c - Display EFI SAL systab. */
/*
* 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/normal.h>
#include <grub/charset.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
static void
disp_sal (void *table)
{
struct grub_efi_sal_system_table *t = table;
void *desc;
grub_uint32_t len, l;
grub_printf ("SAL rev: %02x, signature: %x, len:%x\n",
t->sal_rev, t->signature, t->total_table_len);
grub_printf ("nbr entry: %d, chksum: %02x, SAL version A: %02x B: %02x\n",
t->entry_count, t->checksum,
t->sal_a_version, t->sal_b_version);
grub_printf ("OEM-ID: %-32s\n", t->oem_id);
grub_printf ("Product-ID: %-32s\n", t->product_id);
desc = t->entries;
len = t->total_table_len - sizeof (struct grub_efi_sal_system_table);
while (len > 0)
{
switch (*(grub_uint8_t *) desc)
{
case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_ENTRYPOINT_DESCRIPTOR:
{
struct grub_efi_sal_system_table_entrypoint_descriptor *c = desc;
l = sizeof (*c);
grub_printf (" Entry point: PAL=%016" PRIxGRUB_UINT64_T
" SAL=%016" PRIxGRUB_UINT64_T " GP=%016"
PRIxGRUB_UINT64_T "\n",
c->pal_proc_addr, c->sal_proc_addr,
c->global_data_ptr);
}
break;
case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_MEMORY_DESCRIPTOR:
{
struct grub_efi_sal_system_table_memory_descriptor *c = desc;
l = sizeof (*c);
grub_printf (" Memory descriptor entry addr=%016" PRIxGRUB_UINT64_T
" len=%" PRIuGRUB_UINT64_T "KB\n",
c->addr, c->len * 4);
grub_printf (" sal_used=%d attr=%x AR=%x attr_mask=%x "
"type=%x usage=%x\n",
c->sal_used, c->attr, c->ar, c->attr_mask, c->mem_type,
c->usage);
}
break;
case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PLATFORM_FEATURES:
{
struct grub_efi_sal_system_table_platform_features *c = desc;
l = sizeof (*c);
grub_printf (" Platform features: %02x", c->flags);
if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_BUSLOCK)
grub_printf (" BusLock");
if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IRQREDIRECT)
grub_printf (" IrqRedirect");
if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IPIREDIRECT)
grub_printf (" IPIRedirect");
if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_ITCDRIFT)
grub_printf (" ITCDrift");
grub_printf ("\n");
}
break;
case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_TRANSLATION_REGISTER_DESCRIPTOR:
{
struct grub_efi_sal_system_table_translation_register_descriptor *c
= desc;
l = sizeof (*c);
grub_printf (" TR type=%d num=%d va=%016" PRIxGRUB_UINT64_T
" pte=%016" PRIxGRUB_UINT64_T "\n",
c->register_type, c->register_number,
c->addr, c->page_size);
}
break;
case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PURGE_TRANSLATION_COHERENCE:
{
struct grub_efi_sal_system_table_purge_translation_coherence *c
= desc;
l = sizeof (*c);
grub_printf (" PTC coherence nbr=%d addr=%016" PRIxGRUB_UINT64_T "\n",
c->ndomains, c->coherence);
}
break;
case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_AP_WAKEUP:
{
struct grub_efi_sal_system_table_ap_wakeup *c = desc;
l = sizeof (*c);
grub_printf (" AP wake-up: mec=%d vect=%" PRIxGRUB_UINT64_T "\n",
c->mechanism, c->vector);
}
break;
default:
grub_printf (" unknown entry 0x%x\n", *(grub_uint8_t *)desc);
return;
}
desc = (grub_uint8_t *)desc + l;
len -= l;
}
}
static grub_err_t
grub_cmd_lssal (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
const grub_efi_system_table_t *st = grub_efi_system_table;
grub_efi_configuration_table_t *t = st->configuration_table;
unsigned int i;
grub_efi_guid_t guid = GRUB_EFI_SAL_TABLE_GUID;
for (i = 0; i < st->num_table_entries; i++)
{
if (grub_memcmp (&guid, &t->vendor_guid,
sizeof (grub_efi_guid_t)) == 0)
{
disp_sal (t->vendor_table);
return GRUB_ERR_NONE;
}
t++;
}
grub_printf ("SAL not found\n");
return GRUB_ERR_NONE;
}
static grub_command_t cmd;
GRUB_MOD_INIT(lssal)
{
cmd = grub_register_command ("lssal", grub_cmd_lssal, "",
"Display SAL system table.");
}
GRUB_MOD_FINI(lssal)
{
grub_unregister_command (cmd);
}

View file

@ -21,46 +21,55 @@
#include <grub/list.h>
#include <grub/misc.h>
#include <grub/extcmd.h>
#include <grub/script_sh.h>
static grub_err_t
grub_extcmd_dispatcher (struct grub_command *cmd,
int argc, char **args)
grub_err_t
grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args,
struct grub_script *script)
{
int new_argc;
char **new_args;
struct grub_arg_option *parser;
struct grub_arg_list *state;
int maxargs = 0;
struct grub_extcmd_context context;
grub_err_t ret;
grub_extcmd_t ext;
grub_extcmd_t ext = cmd->data;
ext = cmd->data;
parser = (struct grub_arg_option *) ext->options;
while (parser && (parser++)->doc)
maxargs++;
context.state = 0;
context.extcmd = ext;
context.script = script;
/* Set up the option state. */
state = grub_zalloc (sizeof (struct grub_arg_list) * maxargs);
if (! ext->options)
{
ret = (ext->func) (&context, argc, args);
return ret;
}
state = grub_arg_list_alloc (ext, argc, args);
if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc))
{
ext->state = state;
ret = (ext->func) (ext, new_argc, new_args);
context.state = state;
ret = (ext->func) (&context, new_argc, new_args);
grub_free (new_args);
grub_free (state);
return ret;
}
else
ret = grub_errno;
grub_free (state);
return grub_errno;
}
return ret;
static grub_err_t
grub_extcmd_dispatch (struct grub_command *cmd, int argc, char **args)
{
return grub_extcmd_dispatcher (cmd, argc, args, 0);
}
grub_extcmd_t
grub_register_extcmd (const char *name, grub_extcmd_func_t func,
unsigned flags, const char *summary,
const char *description,
const struct grub_arg_option *parser)
grub_register_extcmd_prio (const char *name, grub_extcmd_func_t func,
grub_command_flags_t flags, const char *summary,
const char *description,
const struct grub_arg_option *parser,
int prio)
{
grub_extcmd_t ext;
grub_command_t cmd;
@ -69,8 +78,8 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func,
if (! ext)
return 0;
cmd = grub_register_command_prio (name, grub_extcmd_dispatcher,
summary, description, 1);
cmd = grub_register_command_prio (name, grub_extcmd_dispatch,
summary, description, prio);
if (! cmd)
{
grub_free (ext);
@ -88,6 +97,16 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func,
return ext;
}
grub_extcmd_t
grub_register_extcmd (const char *name, grub_extcmd_func_t func,
grub_command_flags_t flags, const char *summary,
const char *description,
const struct grub_arg_option *parser)
{
return grub_register_extcmd_prio (name, func, flags,
summary, description, parser, 1);
}
void
grub_unregister_extcmd (grub_extcmd_t ext)
{

View file

@ -32,6 +32,7 @@ static const struct grub_arg_option options[] = {
{"prefix", 'p', 0, N_("Base directory for hash list."), N_("DIRECTORY"),
ARG_TYPE_STRING},
{"keep-going", 'k', 0, N_("Don't stop after first error."), 0, 0},
{"uncompress", 'u', 0, N_("Uncompress file before checksumming."), 0, 0},
{0, 0, 0, 0, 0, 0}
};
@ -39,7 +40,9 @@ struct { const char *name; const char *hashname; } aliases[] =
{
{"sha256sum", "sha256"},
{"sha512sum", "sha512"},
{"sha1sum", "sha1"},
{"md5sum", "md5"},
{"crc", "crc32"},
};
static inline int
@ -80,7 +83,7 @@ hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result)
static grub_err_t
check_list (const gcry_md_spec_t *hash, const char *hashfilename,
const char *prefix, int keep)
const char *prefix, int keep, int uncompress)
{
grub_file_t hashlist, file;
char *buf = NULL;
@ -115,11 +118,17 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
filename = grub_xasprintf ("%s/%s", prefix, p);
if (!filename)
return grub_errno;
if (!uncompress)
grub_file_filter_disable_compression ();
file = grub_file_open (filename);
grub_free (filename);
}
else
file = grub_file_open (p);
{
if (!uncompress)
grub_file_filter_disable_compression ();
file = grub_file_open (p);
}
if (!file)
{
grub_file_close (hashlist);
@ -165,19 +174,20 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename,
}
static grub_err_t
grub_cmd_hashsum (struct grub_extcmd *cmd,
grub_cmd_hashsum (struct grub_extcmd_context *ctxt,
int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
const char *hashname = NULL;
const char *prefix = NULL;
const gcry_md_spec_t *hash;
unsigned i;
int keep = state[3].set;
int uncompress = state[4].set;
unsigned unread = 0;
for (i = 0; i < ARRAY_SIZE (aliases); i++)
if (grub_strcmp (cmd->cmd->name, aliases[i].name) == 0)
if (grub_strcmp (ctxt->extcmd->cmd->name, aliases[i].name) == 0)
hashname = aliases[i].hashname;
if (state[0].set)
hashname = state[0].arg;
@ -197,7 +207,7 @@ grub_cmd_hashsum (struct grub_extcmd *cmd,
if (argc != 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"--check is incompatible with file list");
return check_list (hash, state[1].arg, prefix, keep);
return check_list (hash, state[1].arg, prefix, keep, uncompress);
}
for (i = 0; i < (unsigned) argc; i++)
@ -206,6 +216,8 @@ grub_cmd_hashsum (struct grub_extcmd *cmd,
grub_file_t file;
grub_err_t err;
unsigned j;
if (!uncompress)
grub_file_filter_disable_compression ();
file = grub_file_open (args[i]);
if (!file)
{
@ -238,30 +250,37 @@ grub_cmd_hashsum (struct grub_extcmd *cmd,
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,
GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0,
"hashsum -h HASH [-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]",
"Compute or check hash checksum.",
N_("Compute or check hash checksum."),
options);
cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum,
GRUB_COMMAND_FLAG_BOTH,
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_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum,
GRUB_COMMAND_FLAG_BOTH,
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,
GRUB_COMMAND_FLAG_BOTH,
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."),
@ -272,6 +291,8 @@ 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);
}

View file

@ -270,9 +270,9 @@ static int get_int_arg (const struct grub_arg_list *state)
}
static grub_err_t
grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state????
grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state????
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
/* Check command line. */
if (argc != 1)
@ -409,8 +409,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(hdparm)
{
cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm,
GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm, 0,
N_("[OPTIONS] DISK"),
N_("Get/set ATA disk parameters."), options);
}

View file

@ -27,7 +27,7 @@
#include <grub/charset.h>
static grub_err_t
grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc,
grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc,
char **args)
{
int cnt = 0;
@ -38,8 +38,7 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc,
grub_command_t cmd;
FOR_COMMANDS(cmd)
{
if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) &&
(cmd->flags & GRUB_COMMAND_FLAG_CMDLINE))
if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE))
{
struct grub_term_output *term;
const char *summary_translated = _(cmd->summary);
@ -112,7 +111,8 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc,
if (cnt++ > 0)
grub_printf ("\n\n");
if (cmd->flags & GRUB_COMMAND_FLAG_EXTCMD)
if ((cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) &&
! (cmd->flags & GRUB_COMMAND_FLAG_DYNCMD))
grub_arg_show_help ((grub_extcmd_t) cmd->data);
else
grub_printf ("%s %s %s\n%s\n", _("Usage:"), cmd->name, _(cmd->summary),
@ -130,8 +130,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(help)
{
cmd = grub_register_extcmd ("help", grub_cmd_help,
GRUB_COMMAND_FLAG_CMDLINE,
cmd = grub_register_extcmd ("help", grub_cmd_help, 0,
N_("[PATTERN ...]"),
N_("Show a help message."), 0);
}

View file

@ -21,7 +21,6 @@
#include <grub/file.h>
#include <grub/disk.h>
#include <grub/misc.h>
#include <grub/gzio.h>
#include <grub/lib/hexdump.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
@ -34,9 +33,9 @@ static const struct grub_arg_option options[] = {
};
static grub_err_t
grub_cmd_hexdump (grub_extcmd_t cmd, int argc, char **args)
grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
char buf[GRUB_DISK_SECTOR_SIZE * 4];
grub_ssize_t size, length;
grub_disk_addr_t skip;
@ -89,7 +88,7 @@ grub_cmd_hexdump (grub_extcmd_t cmd, int argc, char **args)
{
grub_file_t file;
file = grub_gzfile_open (args[0], 1);
file = grub_file_open (args[0]);
if (! file)
return 0;
@ -120,8 +119,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT (hexdump)
{
cmd = grub_register_extcmd ("hexdump", grub_cmd_hexdump,
GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("hexdump", grub_cmd_hexdump, 0,
N_("[OPTIONS] FILE_OR_DEVICE"),
N_("Dump the contents of a file or memory."),
options);

View file

@ -22,20 +22,32 @@
#include <grub/cmos.h>
static grub_err_t
grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[])
parse_args (int argc, char *argv[], int *byte, int *bit)
{
int byte, bit;
char *rest;
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required.");
byte = grub_strtoul (argv[0], &rest, 0);
*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);
*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;
grub_err_t err;
err = parse_args (argc, argv, &byte, &bit);
if (err)
return err;
if (grub_cmos_read (byte) & (1 << bit))
return GRUB_ERR_NONE;
@ -43,7 +55,22 @@ grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)),
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;
err = parse_args (argc, argv, &byte, &bit);
if (err)
return err;
grub_cmos_write (byte, grub_cmos_read (byte) & (~(1 << bit)));
return GRUB_ERR_NONE;
}
static grub_command_t cmd, cmd_clean;
GRUB_MOD_INIT(cmostest)
@ -51,9 +78,13 @@ GRUB_MOD_INIT(cmostest)
cmd = grub_register_command ("cmostest", grub_cmd_cmostest,
"cmostest BYTE:BIT",
"Test bit at BYTE:BIT in CMOS.");
cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean,
"cmosclean BYTE:BIT",
"Clean bit at BYTE:BIT in CMOS.");
}
GRUB_MOD_FINI(cmostest)
{
grub_unregister_command (cmd);
grub_unregister_command (cmd_clean);
}

View file

@ -43,7 +43,7 @@ static const struct grub_arg_option options[] =
unsigned char grub_cpuid_has_longmode = 0;
static grub_err_t
grub_cmd_cpuid (grub_extcmd_t cmd __attribute__ ((unused)),
grub_cmd_cpuid (grub_extcmd_context_t ctxt __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
@ -88,7 +88,7 @@ GRUB_MOD_INIT(cpuid)
done:
#endif
cmd = grub_register_extcmd ("cpuid", grub_cmd_cpuid, GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("cpuid", grub_cmd_cpuid, 0,
"[-l]", N_("Check for CPU features."), options);
}

View file

@ -24,9 +24,10 @@
#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>
/* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */
@ -196,13 +197,13 @@ list_mappings (void)
}
static grub_err_t
grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args)
grub_cmd_drivemap (struct grub_extcmd_context *ctxt, int argc, char **args)
{
if (cmd->state[OPTIDX_LIST].set)
if (ctxt->state[OPTIDX_LIST].set)
{
return list_mappings ();
}
else if (cmd->state[OPTIDX_RESET].set)
else if (ctxt->state[OPTIDX_RESET].set)
{
/* Reset: just delete all mappings, freeing their memory. */
drivemap_node_t *curnode = map_head;
@ -216,7 +217,7 @@ grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args)
map_head = 0;
return GRUB_ERR_NONE;
}
else if (!cmd->state[OPTIDX_SWAP].set && argc == 0)
else if (!ctxt->state[OPTIDX_SWAP].set && argc == 0)
{
/* No arguments */
return list_mappings ();
@ -248,11 +249,11 @@ grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args)
}
/* Set the mapping for the disk (overwrites any existing mapping). */
grub_dprintf ("drivemap", "%s %s (%02x) = %s (%02x)\n",
cmd->state[OPTIDX_SWAP].set ? "Swapping" : "Mapping",
ctxt->state[OPTIDX_SWAP].set ? "Swapping" : "Mapping",
args[1], mapto, args[0], mapfrom);
err = drivemap_set (mapto, mapfrom);
/* If -s, perform the reverse mapping too (only if the first was OK). */
if (cmd->state[OPTIDX_SWAP].set && err == GRUB_ERR_NONE)
if (ctxt->state[OPTIDX_SWAP].set && err == GRUB_ERR_NONE)
err = drivemap_set (mapfrom, mapto);
return err;
}
@ -306,7 +307,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 "
@ -401,8 +402,7 @@ GRUB_MOD_INIT (drivemap)
{
grub_get_root_biosnumber_saved = grub_get_root_biosnumber;
grub_get_root_biosnumber = grub_get_root_biosnumber_drivemap;
cmd = grub_register_extcmd ("drivemap", grub_cmd_drivemap,
GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("drivemap", grub_cmd_drivemap, 0,
N_("-l | -r | [-s] grubdev osdisk."),
N_("Manage the BIOS drive mappings."),
options);

View file

@ -22,6 +22,7 @@
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/machine/int.h>
#include <grub/acpi.h>
static const struct grub_arg_option options[] =
{
@ -46,6 +47,8 @@ grub_halt (int no_apm)
{
struct grub_bios_int_registers regs;
grub_acpi_halt ();
if (no_apm)
stop ();
@ -93,13 +96,14 @@ grub_halt (int no_apm)
}
static grub_err_t
grub_cmd_halt (grub_extcmd_t cmd,
grub_cmd_halt (grub_extcmd_context_t ctxt,
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
int no_apm = 0;
if (state[0].set)
no_apm = 1;
grub_halt (no_apm);
@ -110,8 +114,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(halt)
{
cmd = grub_register_extcmd ("halt", grub_cmd_halt, GRUB_COMMAND_FLAG_BOTH,
"[-n]",
cmd = grub_register_extcmd ("halt", grub_cmd_halt, 0, "[-n]",
N_("Halt the system, if possible using APM."),
options);
}

View file

@ -0,0 +1,113 @@
/*
* 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>
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, &regs);
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, &regs);
/* connect APM */
regs.eax = 0x5303;
regs.ebx = 0;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x15, &regs);
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 ("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);
}

View file

@ -284,9 +284,9 @@ grub_sendkey_preboot (int noret __attribute__ ((unused)))
}
static grub_err_t
grub_cmd_sendkey (grub_extcmd_t cmd, int argc, char **args)
grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
auto int find_key_code (char *key);
auto int find_ascii_code (char *key);
@ -366,8 +366,7 @@ static void *preboot_hook;
GRUB_MOD_INIT (sendkey)
{
cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey,
GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, 0,
"sendkey [KEYSTROKE1] [KEYSTROKE2] ...",
"Emulate a keystroke", options);

View file

@ -1,185 +0,0 @@
/* vbeinfo.c - command to list compatible VBE video modes. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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/dl.h>
#include <grub/env.h>
#include <grub/misc.h>
#include <grub/machine/init.h>
#include <grub/machine/vbe.h>
#include <grub/mm.h>
#include <grub/command.h>
#include <grub/i18n.h>
static void *
real2pm (grub_vbe_farptr_t ptr)
{
return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL)
+ ((unsigned long) ptr & 0x0000FFFF));
}
static grub_err_t
grub_cmd_vbeinfo (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
struct grub_vbe_info_block controller_info;
struct grub_vbe_mode_info_block mode_info_tmp;
grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
grub_uint16_t *video_mode_list;
grub_uint16_t *p;
grub_uint16_t *saved_video_mode_list;
grub_size_t video_mode_list_size;
grub_err_t err;
char *modevar;
err = grub_vbe_probe (&controller_info);
if (err != GRUB_ERR_NONE)
return err;
grub_printf ("VBE info: version: %d.%d OEM software rev: %d.%d\n",
controller_info.version >> 8,
controller_info.version & 0xFF,
controller_info.oem_software_rev >> 8,
controller_info.oem_software_rev & 0xFF);
/* The total_memory field is in 64 KiB units. */
grub_printf (" total memory: %d KiB\n",
(controller_info.total_memory << 16) / 1024);
/* Because the information on video modes is stored in a temporary place,
it is better to copy it to somewhere safe. */
p = video_mode_list = real2pm (controller_info.video_mode_ptr);
while (*p++ != 0xFFFF)
;
video_mode_list_size = (grub_addr_t) p - (grub_addr_t) video_mode_list;
saved_video_mode_list = grub_malloc (video_mode_list_size);
if (! saved_video_mode_list)
return grub_errno;
grub_memcpy (saved_video_mode_list, video_mode_list, video_mode_list_size);
grub_printf ("List of compatible video modes:\n");
grub_printf ("Legend: P=Packed pixel, D=Direct color, "
"mask/pos=R/G/B/reserved\n");
/* Walk through all video modes listed. */
for (p = saved_video_mode_list; *p != 0xFFFF; p++)
{
const char *memory_model = 0;
grub_uint32_t mode = (grub_uint32_t) *p;
err = grub_vbe_get_video_mode_info (mode, &mode_info_tmp);
if (err != GRUB_ERR_NONE)
{
grub_errno = GRUB_ERR_NONE;
continue;
}
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_SUPPORTED) == 0)
/* If not available, skip it. */
continue;
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_RESERVED_1) == 0)
/* Not enough information. */
continue;
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_COLOR) == 0)
/* Monochrome is unusable. */
continue;
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_LFB_AVAIL) == 0)
/* We support only linear frame buffer modes. */
continue;
if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_GRAPHICS) == 0)
/* We allow only graphical modes. */
continue;
switch (mode_info_tmp.memory_model)
{
case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL:
memory_model = "Packed";
break;
case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR:
memory_model = "Direct";
break;
default:
break;
}
if (! memory_model)
continue;
grub_printf ("0x%03x: %4d x %4d x %2d %s",
mode,
mode_info_tmp.x_resolution,
mode_info_tmp.y_resolution,
mode_info_tmp.bits_per_pixel,
memory_model);
/* Show mask and position details for direct color modes. */
if (mode_info_tmp.memory_model == GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR)
grub_printf (", mask: %d/%d/%d/%d pos: %d/%d/%d/%d",
mode_info_tmp.red_mask_size,
mode_info_tmp.green_mask_size,
mode_info_tmp.blue_mask_size,
mode_info_tmp.rsvd_mask_size,
mode_info_tmp.red_field_position,
mode_info_tmp.green_field_position,
mode_info_tmp.blue_field_position,
mode_info_tmp.rsvd_field_position);
grub_printf ("\n");
}
grub_free (saved_video_mode_list);
/* Check existence of vbe_mode environment variable. */
modevar = grub_env_get ("vbe_mode");
if (modevar != 0)
{
unsigned long value;
value = grub_strtoul (modevar, 0, 0);
if (grub_errno == GRUB_ERR_NONE)
use_mode = value;
else
grub_errno = GRUB_ERR_NONE;
}
grub_printf ("Configured VBE mode (vbe_mode) = 0x%03x\n", use_mode);
return 0;
}
static grub_command_t cmd;
GRUB_MOD_INIT(vbeinfo)
{
cmd =
grub_register_command ("vbeinfo", grub_cmd_vbeinfo, 0,
N_("List compatible VESA BIOS extension video modes."));
}
GRUB_MOD_FINI(vbeinfo)
{
grub_unregister_command (cmd);
}

View file

@ -1,179 +0,0 @@
/* vbetest.c - command to test VESA BIOS Extension 2.0+ support. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,2007 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/normal.h>
#include <grub/dl.h>
#include <grub/env.h>
#include <grub/misc.h>
#include <grub/term.h>
#include <grub/machine/init.h>
#include <grub/machine/vbe.h>
#include <grub/video.h>
#include <grub/err.h>
#include <grub/i18n.h>
static grub_err_t
grub_cmd_vbetest (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
grub_err_t err;
char *modevar;
struct grub_vbe_mode_info_block mode_info;
struct grub_vbe_info_block controller_info;
grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE;
grub_uint32_t old_mode;
grub_uint8_t *framebuffer = 0;
grub_uint32_t bytes_per_scan_line = 0;
unsigned char *ptr;
int i;
grub_printf ("Probing for VESA BIOS Extension ... ");
/* Check if VESA BIOS exists. */
err = grub_vbe_probe (&controller_info);
if (err != GRUB_ERR_NONE)
return err;
grub_printf ("found!\n");
/* Dump out controller information. */
grub_printf ("VBE signature = %c%c%c%c\n",
controller_info.signature[0],
controller_info.signature[1],
controller_info.signature[2],
controller_info.signature[3]);
grub_printf ("VBE version = %d.%d\n",
controller_info.version >> 8,
controller_info.version & 0xFF);
grub_printf ("OEM string ptr = %08x\n",
controller_info.oem_string_ptr);
grub_printf ("Total memory = %d\n",
controller_info.total_memory);
err = grub_vbe_get_video_mode (&old_mode);
grub_printf ("Get video mode err = %04x\n", err);
if (err == GRUB_ERR_NONE)
grub_printf ("Old video mode = %04x\n", old_mode);
else
grub_errno = GRUB_ERR_NONE;
/* Check existence of vbe_mode environment variable. */
modevar = grub_env_get ("vbe_mode");
if (modevar != 0)
{
unsigned long value;
value = grub_strtoul (modevar, 0, 0);
if (grub_errno == GRUB_ERR_NONE)
use_mode = value;
else
grub_errno = GRUB_ERR_NONE;
}
err = grub_vbe_get_video_mode_info (use_mode, &mode_info);
if (err != GRUB_ERR_NONE)
return err;
/* Dump out details about the mode being tested. */
grub_printf ("mode: 0x%03x\n",
use_mode);
grub_printf ("width : %d\n",
mode_info.x_resolution);
grub_printf ("height: %d\n",
mode_info.y_resolution);
grub_printf ("memory model: %02x\n",
mode_info.memory_model);
grub_printf ("bytes/scanline: %d\n",
mode_info.bytes_per_scan_line);
grub_printf ("bytes/scanline (lin): %d\n",
mode_info.lin_bytes_per_scan_line);
grub_printf ("base address: %08x\n",
mode_info.phys_base_addr);
grub_printf ("red mask/pos: %d/%d\n",
mode_info.red_mask_size,
mode_info.red_field_position);
grub_printf ("green mask/pos: %d/%d\n",
mode_info.green_mask_size,
mode_info.green_field_position);
grub_printf ("blue mask/pos: %d/%d\n",
mode_info.blue_mask_size,
mode_info.blue_field_position);
grub_printf ("Press any key to continue.\n");
grub_getkey ();
/* Setup GFX mode. */
err = grub_vbe_set_video_mode (use_mode, &mode_info);
if (err != GRUB_ERR_NONE)
return err;
/* Determine framebuffer address and how many bytes are in scan line. */
framebuffer = (grub_uint8_t *) mode_info.phys_base_addr;
ptr = framebuffer;
if (controller_info.version >= 0x300)
{
bytes_per_scan_line = mode_info.lin_bytes_per_scan_line;
}
else
{
bytes_per_scan_line = mode_info.bytes_per_scan_line;
}
/* Draw some random data to screen. */
for (i = 0; i < 256 * 256; i++)
{
ptr[i] = i & 0x0F;
}
/* Draw white line to screen. */
for (i = 0; i < 100; i++)
{
ptr[mode_info.bytes_per_scan_line * 50 + i] = 0x0F;
}
/* Draw another white line to screen. */
grub_memset (ptr + bytes_per_scan_line * 51, 0x0f, bytes_per_scan_line);
grub_getkey ();
grub_video_restore ();
/* Restore old video mode. */
grub_vbe_set_video_mode (old_mode, 0);
return grub_errno;
}
static grub_command_t cmd;
GRUB_MOD_INIT(vbetest)
{
cmd = grub_register_command ("vbetest", grub_cmd_vbetest,
0, N_("Test VESA BIOS Extension 2.0+ support."));
}
GRUB_MOD_FINI(vbetest)
{
grub_unregister_command (cmd);
}

View file

@ -36,17 +36,16 @@ static const struct grub_arg_option options[] =
static grub_err_t
grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv)
grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv)
{
grub_target_addr_t addr;
grub_uint32_t value = 0;
char buf[sizeof ("XXXXXXXX")];
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments");
addr = grub_strtoul (argv[0], 0, 0);
switch (cmd->cmd->name[sizeof ("in") - 1])
switch (ctxt->extcmd->cmd->name[sizeof ("in") - 1])
{
case 'l':
value = grub_inl (addr);
@ -61,10 +60,11 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv)
break;
}
if (cmd->state[0].set)
if (ctxt->state[0].set)
{
char buf[sizeof ("XXXXXXXX")];
grub_snprintf (buf, sizeof (buf), "%x", value);
grub_env_set (cmd->state[0].arg, buf);
grub_env_set (ctxt->state[0].arg, buf);
}
else
grub_printf ("0x%x\n", value);
@ -117,13 +117,13 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv)
GRUB_MOD_INIT(memrw)
{
cmd_read_byte =
grub_register_extcmd ("inb", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH,
grub_register_extcmd ("inb", grub_cmd_read, 0,
N_("PORT"), N_("Read byte from PORT."), options);
cmd_read_word =
grub_register_extcmd ("inw", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH,
grub_register_extcmd ("inw", grub_cmd_read, 0,
N_("PORT"), N_("Read word from PORT."), options);
cmd_read_dword =
grub_register_extcmd ("inl", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH,
grub_register_extcmd ("inl", grub_cmd_read, 0,
N_("PORT"), N_("Read dword from PORT."), options);
cmd_write_byte =
grub_register_command ("outb", grub_cmd_write,

View file

@ -0,0 +1,297 @@
/*
* 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>
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);
}

View file

@ -31,23 +31,39 @@ 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_t cmd,
grub_cmd_keystatus (grub_extcmd_context_t ctxt,
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
int expect_mods = 0;
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);
@ -80,8 +96,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(keystatus)
{
cmd = grub_register_extcmd ("keystatus", grub_cmd_keystatus,
GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("keystatus", grub_cmd_keystatus, 0,
N_("[--shift] [--ctrl] [--alt]"),
N_("Check key modifier status."),
options);

View file

@ -0,0 +1,806 @@
/*
* 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>
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;
oldname = entryname;
parsed = grub_legacy_parse (buf, &entryname, &newsuffix);
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);
if (menu && menu->size)
grub_show_menu (menu, 1);
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 && !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;
int no_mem_option = 0;
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)
{
no_mem_option = 1;
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;
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_printf ("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 onl 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 onl 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);
}

View file

@ -56,6 +56,7 @@ open_envblk_file (char *filename)
grub_strcpy (filename, prefix);
filename[len] = '/';
grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG);
grub_file_filter_disable_compression ();
file = grub_file_open (filename);
grub_free (filename);
return file;
@ -67,6 +68,7 @@ open_envblk_file (char *filename)
}
}
grub_file_filter_disable_compression ();
return grub_file_open (filename);
}
@ -111,11 +113,11 @@ read_envblk_file (grub_file_t file)
}
static grub_err_t
grub_cmd_load_env (grub_extcmd_t cmd,
grub_cmd_load_env (grub_extcmd_context_t ctxt,
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
grub_file_t file;
grub_envblk_t envblk;
@ -143,11 +145,11 @@ grub_cmd_load_env (grub_extcmd_t cmd,
}
static grub_err_t
grub_cmd_list_env (grub_extcmd_t cmd,
grub_cmd_list_env (grub_extcmd_context_t ctxt,
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
grub_file_t file;
grub_envblk_t envblk;
@ -280,9 +282,9 @@ write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists,
}
static grub_err_t
grub_cmd_save_env (grub_extcmd_t cmd, int argc, char **args)
grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
grub_file_t file;
grub_envblk_t envblk;
struct blocklist *head = 0;
@ -373,20 +375,15 @@ static grub_extcmd_t cmd_load, cmd_list, cmd_save;
GRUB_MOD_INIT(loadenv)
{
cmd_load =
grub_register_extcmd ("load_env", grub_cmd_load_env,
GRUB_COMMAND_FLAG_BOTH,
N_("[-f FILE]"),
grub_register_extcmd ("load_env", grub_cmd_load_env, 0, N_("[-f FILE]"),
N_("Load variables from environment block file."),
options);
cmd_list =
grub_register_extcmd ("list_env", grub_cmd_list_env,
GRUB_COMMAND_FLAG_BOTH,
N_("[-f FILE]"),
grub_register_extcmd ("list_env", grub_cmd_list_env, 0, N_("[-f FILE]"),
N_("List variables from environment block file."),
options);
cmd_save =
grub_register_extcmd ("save_env", grub_cmd_save_env,
GRUB_COMMAND_FLAG_BOTH,
grub_register_extcmd ("save_env", grub_cmd_save_env, 0,
N_("[-f FILE] variable_name [...]"),
N_("Save variables to environment block file."),
options);

View file

@ -120,6 +120,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
/* XXX: For ext2fs symlinks are detected as files while they
should be reported as directories. */
grub_file_filter_disable_compression ();
file = grub_file_open (pathname);
if (! file)
{
@ -226,6 +227,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
struct grub_dirhook_info info;
grub_errno = 0;
grub_file_filter_disable_compression ();
file = grub_file_open (dirname);
if (! file)
goto fail;
@ -263,15 +265,17 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human)
}
static grub_err_t
grub_cmd_ls (grub_extcmd_t cmd, int argc, char **args)
grub_cmd_ls (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
int i;
if (argc == 0)
grub_ls_list_devices (state[0].set);
else
grub_ls_list_files (args[0], state[0].set, state[2].set,
state[1].set);
for (i = 0; i < argc; i++)
grub_ls_list_files (args[i], state[0].set, state[2].set,
state[1].set);
return 0;
}
@ -280,8 +284,8 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(ls)
{
cmd = grub_register_extcmd ("ls", grub_cmd_ls, GRUB_COMMAND_FLAG_BOTH,
N_("[-l|-h|-a] [FILE]"),
cmd = grub_register_extcmd ("ls", grub_cmd_ls, 0,
N_("[-l|-h|-a] [FILE ...]"),
N_("List devices and files."), options);
}

250
grub-core/commands/lsacpi.c Normal file
View file

@ -0,0 +1,250 @@
/* acpi.c - Display acpi tables. */
/*
* 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/normal.h>
#include <grub/acpi.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/dl.h>
static void
print_strn (grub_uint8_t *str, grub_size_t len)
{
for (; *str && len; str++, len--)
grub_printf ("%c", *str);
for (len++; len; len--)
grub_printf (" ");
}
#define print_field(x) print_strn(x, sizeof (x))
static void
disp_acpi_table (struct grub_acpi_table_header *t)
{
print_field (t->signature);
grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u OEM=", t->length, t->revision);
print_field (t->oemid);
print_field (t->oemtable);
grub_printf ("OEMrev=%08" PRIxGRUB_UINT32_T " ", t->oemrev);
print_field (t->creator_id);
grub_printf (" %08" PRIxGRUB_UINT32_T "\n", t->creator_rev);
}
static void
disp_madt_table (struct grub_acpi_madt *t)
{
struct grub_acpi_madt_entry_header *d;
grub_uint32_t len;
disp_acpi_table (&t->hdr);
grub_printf ("Local APIC=%08" PRIxGRUB_UINT32_T " Flags=%08"
PRIxGRUB_UINT32_T "\n",
t->lapic_addr, t->flags);
len = t->hdr.length - sizeof (struct grub_acpi_madt);
d = t->entries;
for (;len > 0; len -= d->len, d = (void *) ((grub_uint8_t *) d + d->len))
{
grub_printf (" type=%x l=%u ", d->type, d->len);
switch (d->type)
{
case GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE:
{
struct grub_acpi_madt_entry_interrupt_override *dt = (void *) d;
grub_printf ("Int Override bus=%x src=%x GSI=%08x Flags=%04x\n",
dt->bus, dt->source, dt->global_sys_interrupt,
dt->flags);
}
break;
case GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC:
{
struct grub_acpi_madt_entry_sapic *dt = (void *) d;
grub_printf ("IOSAPIC Id=%02x GSI=%08x Addr=%016" PRIxGRUB_UINT64_T
"\n",
dt->id, dt->global_sys_interrupt_base,
dt->addr);
}
break;
case GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC:
{
struct grub_acpi_madt_entry_lsapic *dt = (void *) d;
grub_printf ("LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x",
dt->cpu_id, dt->id, dt->eid, dt->flags);
if (dt->flags & GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED)
grub_printf (" Enabled\n");
else
grub_printf (" Disabled\n");
if (d->len > sizeof (struct grub_acpi_madt_entry_sapic))
grub_printf (" UID val=%08x, Str=%s\n", dt->cpu_uid,
dt->cpu_uid_str);
}
break;
case GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE:
{
struct grub_acpi_madt_entry_platform_int_source *dt = (void *) d;
static const char * const platint_type[] =
{"Nul", "PMI", "INIT", "CPEI"};
grub_printf ("Platform INT flags=%04x type=%02x (%s)"
" ID=%02x EID=%02x\n",
dt->flags, dt->inttype,
(dt->inttype < ARRAY_SIZE (platint_type))
? platint_type[dt->inttype] : "??", dt->cpu_id,
dt->cpu_eid);
grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x\n",
dt->sapic_vector, dt->global_sys_int, dt->src_flags);
}
break;
default:
grub_printf (" ??\n");
}
}
}
static void
disp_acpi_xsdt_table (struct grub_acpi_table_header *t)
{
grub_uint32_t len;
grub_uint64_t *desc;
disp_acpi_table (t);
len = t->length - sizeof (*t);
desc = (grub_uint64_t *) (t + 1);
for (; len > 0; desc++, len -= sizeof (*desc))
{
if (sizeof (grub_addr_t) == 4 && *desc >= (1ULL << 32))
{
grub_printf ("Unreachable table\n");
continue;
}
t = (struct grub_acpi_table_header *) (grub_addr_t) *desc;
if (t == NULL)
continue;
if (grub_memcmp (t->signature, GRUB_ACPI_MADT_SIGNATURE,
sizeof (t->signature)) == 0)
disp_madt_table ((struct grub_acpi_madt *) t);
else
disp_acpi_table (t);
}
}
static void
disp_acpi_rsdt_table (struct grub_acpi_table_header *t)
{
grub_uint32_t len;
grub_uint32_t *desc;
disp_acpi_table (t);
len = t->length - sizeof (*t);
desc = (grub_uint32_t *) (t + 1);
for (; len > 0; desc++, len -= sizeof (*desc))
{
t = (struct grub_acpi_table_header *) (grub_addr_t) *desc;
if (t == NULL)
continue;
if (grub_memcmp (t->signature, GRUB_ACPI_MADT_SIGNATURE,
sizeof (t->signature)) == 0)
disp_madt_table ((struct grub_acpi_madt *) t);
else
disp_acpi_table (t);
}
}
static void
disp_acpi_rsdpv1 (struct grub_acpi_rsdp_v10 *rsdp)
{
print_field (rsdp->signature);
grub_printf ("chksum:%02x, OEM-ID: ", rsdp->checksum);
print_field (rsdp->oemid);
grub_printf ("rev=%d\n", rsdp->revision);
grub_printf ("RSDT=%08" PRIxGRUB_UINT32_T "\n", rsdp->rsdt_addr);
}
static void
disp_acpi_rsdpv2 (struct grub_acpi_rsdp_v20 *rsdp)
{
disp_acpi_rsdpv1 (&rsdp->rsdpv1);
grub_printf ("len=%d XSDT=%016" PRIxGRUB_UINT64_T "\n", rsdp->length,
rsdp->xsdt_addr);
}
static const struct grub_arg_option options[] = {
{"v1", '1', 0, N_("Show v1 tables only."), 0, ARG_TYPE_NONE},
{"v2", '2', 0, N_("Show v2 and v3 tablesv only."), 0, ARG_TYPE_NONE}
};
static grub_err_t
grub_cmd_lsacpi (struct grub_extcmd_context *ctxt,
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
if (!ctxt->state[1].set)
{
struct grub_acpi_rsdp_v10 *rsdp1 = grub_acpi_get_rsdpv1 ();
if (!rsdp1)
grub_printf ("No RSDPv1\n");
else
{
grub_printf ("RSDPv1 signature:");
disp_acpi_rsdpv1 (rsdp1);
disp_acpi_rsdt_table ((void *) (grub_addr_t) rsdp1->rsdt_addr);
}
}
if (!ctxt->state[0].set)
{
struct grub_acpi_rsdp_v20 *rsdp2 = grub_acpi_get_rsdpv2 ();
if (!rsdp2)
grub_printf ("No RSDPv2\n");
else
{
if (sizeof (grub_addr_t) == 4 && rsdp2->xsdt_addr >= (1ULL << 32))
grub_printf ("Unreachable RSDPv2\n");
else
{
grub_printf ("RSDPv2 signature:");
disp_acpi_rsdpv2 (rsdp2);
disp_acpi_xsdt_table ((void *) (grub_addr_t) rsdp2->xsdt_addr);
grub_printf ("\n");
}
}
}
return GRUB_ERR_NONE;
}
static grub_extcmd_t cmd;
GRUB_MOD_INIT(lsapi)
{
cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, 0, N_("[-1|-2]"),
N_("Show ACPI information."), options);
}
GRUB_MOD_FINI(lsacpi)
{
grub_unregister_extcmd (cmd);
}

View file

@ -16,24 +16,39 @@
* 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>
static const char *names[] =
{
[GRUB_MEMORY_AVAILABLE] = "available",
[GRUB_MEMORY_RESERVED] = "reserved",
[GRUB_MEMORY_ACPI] = "ACPI reclamaible",
[GRUB_MEMORY_NVS] = "NVS",
[GRUB_MEMORY_BADRAM] = "BadRAM",
[GRUB_MEMORY_CODE] = "firmware code",
[GRUB_MEMORY_HOLE] = "hole"
};
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 ("base_addr = 0x%llx, length = 0x%llx, %s\n",
(long long) addr, (long long) size, names[type]);
else
grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n",
(long long) addr, (long long) size, type);
return 0;
}
#ifndef GRUB_MACHINE_EMU

View file

@ -211,11 +211,11 @@ grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid)
}
static grub_err_t
grub_cmd_lspci (grub_extcmd_t cmd,
grub_cmd_lspci (grub_extcmd_context_t ctxt,
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
{
iospace = cmd->state[0].set;
iospace = ctxt->state[0].set;
grub_pci_iterate (grub_lspci_iter);
return GRUB_ERR_NONE;
}
@ -224,8 +224,8 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(lspci)
{
cmd = grub_register_extcmd ("lspci", grub_cmd_lspci, GRUB_COMMAND_FLAG_BOTH,
"[-i]", N_("List PCI devices."), options);
cmd = grub_register_extcmd ("lspci", grub_cmd_lspci, 0, "[-i]",
N_("List PCI devices."), options);
}
GRUB_MOD_FINI(lspci)

View file

@ -35,7 +35,7 @@ static const struct grub_arg_option options[] =
static grub_err_t
grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv)
grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv)
{
grub_target_addr_t addr;
grub_uint32_t value = 0;
@ -45,7 +45,7 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid number of arguments");
addr = grub_strtoul (argv[0], 0, 0);
switch (cmd->cmd->name[sizeof ("read_") - 1])
switch (ctxt->extcmd->cmd->name[sizeof ("read_") - 1])
{
case 'd':
value = *((volatile grub_uint32_t *) addr);
@ -60,10 +60,10 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv)
break;
}
if (cmd->state[0].set)
if (ctxt->state[0].set)
{
grub_snprintf (buf, sizeof (buf), "%x", value);
grub_env_set (cmd->state[0].arg, buf);
grub_env_set (ctxt->state[0].arg, buf);
}
else
grub_printf ("0x%x\n", value);
@ -119,13 +119,13 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv)
GRUB_MOD_INIT(memrw)
{
cmd_read_byte =
grub_register_extcmd ("read_byte", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH,
grub_register_extcmd ("read_byte", grub_cmd_read, 0,
N_("ADDR"), N_("Read byte from ADDR."), options);
cmd_read_word =
grub_register_extcmd ("read_word", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH,
grub_register_extcmd ("read_word", grub_cmd_read, 0,
N_("ADDR"), N_("Read word from ADDR."), options);
cmd_read_dword =
grub_register_extcmd ("read_dword", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH,
grub_register_extcmd ("read_dword", grub_cmd_read, 0,
N_("ADDR"), N_("Read dword from ADDR."), options);
cmd_write_byte =
grub_register_command ("write_byte", grub_cmd_write,

View file

@ -0,0 +1,320 @@
/* menuentry.c - menuentry command */
/*
* 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/err.h>
#include <grub/dl.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/normal.h>
static const struct grub_arg_option options[] =
{
{"class", 1, GRUB_ARG_OPTION_REPEATABLE,
N_("Menu entry type."), "STRING", ARG_TYPE_STRING},
{"users", 2, 0,
N_("Users allowed to boot this entry."), "USERNAME", ARG_TYPE_STRING},
{"hotkey", 3, 0,
N_("Keyboard key for this entry."), "KEY", ARG_TYPE_STRING},
{"source", 4, 0,
N_("Menu entry definition as a string."), "STRING", ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
static struct
{
char *name;
int key;
} hotkey_aliases[] =
{
{"backspace", '\b'},
{"tab", '\t'},
{"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. */
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)
{
int menu_hotkey = 0;
char **menu_args = NULL;
char *menu_users = NULL;
char *menu_title = NULL;
char *menu_sourcecode = NULL;
struct grub_menu_entry_class *menu_classes = NULL;
grub_menu_t menu;
grub_menu_entry_t *last;
menu = grub_env_get_menu ();
if (! menu)
return grub_error (GRUB_ERR_MENU, "no menu context");
last = &menu->entry_list;
menu_sourcecode = grub_xasprintf ("%s%s", prefix ?: "", sourcecode);
if (! menu_sourcecode)
return grub_errno;
if (classes)
{
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)
goto fail;
for (i = 0; classes[i]; i++)
{
menu_classes[i].name = grub_strdup (classes[i]);
if (! menu_classes[i].name)
goto fail;
menu_classes[i].next = classes[i + 1] ? &menu_classes[i + 1] : NULL;
}
}
if (users)
{
menu_users = grub_strdup (users);
if (! menu_users)
goto fail;
}
if (hotkey)
{
unsigned i;
for (i = 0; i < ARRAY_SIZE (hotkey_aliases); i++)
if (grub_strcmp (hotkey, hotkey_aliases[i].name) == 0)
{
menu_hotkey = hotkey_aliases[i].key;
break;
}
if (i == ARRAY_SIZE (hotkey_aliases))
menu_hotkey = hotkey[0];
}
if (! argc)
{
grub_error (GRUB_ERR_MENU, "menuentry is missing title");
goto fail;
}
menu_title = grub_strdup (args[0]);
if (! menu_title)
goto fail;
/* Save argc, args to pass as parameters to block arg later. */
menu_args = grub_malloc (sizeof (char*) * (argc + 1));
if (! menu_args)
goto fail;
{
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)
last = &(*last)->next;
*last = grub_zalloc (sizeof (**last));
if (! *last)
goto fail;
(*last)->title = menu_title;
(*last)->hotkey = menu_hotkey;
(*last)->classes = menu_classes;
if (menu_users)
(*last)->restricted = 1;
(*last)->users = menu_users;
(*last)->argc = argc;
(*last)->args = menu_args;
(*last)->sourcecode = menu_sourcecode;
(*last)->submenu = submenu;
menu->size++;
return GRUB_ERR_NONE;
fail:
grub_free (menu_sourcecode);
{
int i;
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_args && menu_args[i]; i++)
grub_free (menu_args[i]);
grub_free (menu_args);
}
grub_free (menu_users);
grub_free (menu_title);
return grub_errno;
}
static char *
setparams_prefix (int argc, char **args)
{
int i;
int j;
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++)
{
len += 3; /* 3 = 1 space + 2 quotes */
p = args[i];
while (*p)
len += grub_strchr (escape_characters, *p++) ? 2 : 1;
}
result = grub_malloc (len + 2);
if (! result)
return 0;
grub_strcpy (result, "setparams");
i = 9;
for (j = 0; j < argc; j++)
{
result[i++] = ' ';
result[i++] = '"';
i = strescpy (result + i, args[j], escape_characters) - result;
result[i++] = '"';
}
result[i++] = '\n';
result[i] = '\0';
return result;
}
static grub_err_t
grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
{
char ch;
char *src;
char *prefix;
unsigned len;
grub_err_t r;
if (! argc)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments");
if (ctxt->state[3].set && ctxt->script)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple menuentry definitions");
if (! ctxt->state[3].set && ! ctxt->script)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition");
if (! ctxt->script)
return grub_normal_add_menu_entry (argc, (const char **) args,
ctxt->state[0].args, 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;
len = grub_strlen(src);
ch = src[len - 1];
src[len - 1] = '\0';
prefix = setparams_prefix (argc - 1, args);
if (! prefix)
return grub_errno;
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;
grub_free (prefix);
return r;
}
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_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);
}

View file

@ -108,146 +108,6 @@ grub_rescue_cmd_info (void)
}
#endif
/* root [DEVICE] */
static grub_err_t
grub_mini_cmd_root (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_device_t dev;
grub_fs_t fs;
if (argc > 0)
{
char *device_name = grub_file_get_device_name (argv[0]);
if (! device_name)
return grub_errno;
grub_env_set ("root", device_name);
grub_free (device_name);
}
dev = grub_device_open (0);
if (! dev)
return grub_errno;
fs = grub_fs_probe (dev);
if (grub_errno == GRUB_ERR_UNKNOWN_FS)
grub_errno = GRUB_ERR_NONE;
grub_printf ("(%s): Filesystem is %s.\n",
grub_env_get ("root"), fs ? fs->name : "unknown");
grub_device_close (dev);
return 0;
}
#if 0
static void
grub_rescue_cmd_testload (int argc, char *argv[])
{
grub_file_t file;
char *buf;
grub_ssize_t size;
grub_ssize_t pos;
auto void read_func (unsigned long sector, unsigned offset, unsigned len);
void read_func (unsigned long sector __attribute__ ((unused)),
unsigned offset __attribute__ ((unused)),
unsigned len __attribute__ ((unused)))
{
grub_putchar ('.');
grub_refresh ();
}
if (argc < 1)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
return;
}
file = grub_file_open (argv[0]);
if (! file)
return;
size = grub_file_size (file) & ~(GRUB_DISK_SECTOR_SIZE - 1);
if (size == 0)
{
grub_file_close (file);
return;
}
buf = grub_malloc (size);
if (! buf)
goto fail;
grub_printf ("Reading %s sequentially", argv[0]);
file->read_hook = read_func;
if (grub_file_read (file, buf, size) != size)
goto fail;
grub_printf (" Done.\n");
/* Read sequentially again. */
grub_printf ("Reading %s sequentially again", argv[0]);
if (grub_file_seek (file, 0) < 0)
goto fail;
for (pos = 0; pos < size; pos += GRUB_DISK_SECTOR_SIZE)
{
char sector[GRUB_DISK_SECTOR_SIZE];
if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE)
!= GRUB_DISK_SECTOR_SIZE)
goto fail;
if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0)
{
grub_printf ("\nDiffers in %d\n", pos);
goto fail;
}
}
grub_printf (" Done.\n");
/* Read backwards and compare. */
grub_printf ("Reading %s backwards", argv[0]);
pos = size;
while (pos > 0)
{
char sector[GRUB_DISK_SECTOR_SIZE];
pos -= GRUB_DISK_SECTOR_SIZE;
if (grub_file_seek (file, pos) < 0)
goto fail;
if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE)
!= GRUB_DISK_SECTOR_SIZE)
goto fail;
if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0)
{
int i;
grub_printf ("\nDiffers in %d\n", pos);
for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i++)
grub_putchar (buf[pos + i]);
if (i)
grub_refresh ();
goto fail;
}
}
grub_printf (" Done.\n");
fail:
grub_file_close (file);
grub_free (buf);
}
#endif
/* dump ADDRESS [SIZE] */
static grub_err_t
grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)),
@ -332,7 +192,7 @@ grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)),
return 0;
}
static grub_command_t cmd_cat, cmd_help, cmd_root;
static grub_command_t cmd_cat, cmd_help;
static grub_command_t cmd_dump, cmd_rmmod, cmd_lsmod, cmd_exit;
GRUB_MOD_INIT(minicmd)
@ -343,9 +203,6 @@ GRUB_MOD_INIT(minicmd)
cmd_help =
grub_register_command ("help", grub_mini_cmd_help,
0, N_("Show this message."));
cmd_root =
grub_register_command ("root", grub_mini_cmd_root,
N_("[DEVICE]"), N_("Set the root device."));
cmd_dump =
grub_register_command ("dump", grub_mini_cmd_dump,
N_("ADDR"), N_("Dump memory."));
@ -364,7 +221,6 @@ GRUB_MOD_FINI(minicmd)
{
grub_unregister_command (cmd_cat);
grub_unregister_command (cmd_help);
grub_unregister_command (cmd_root);
grub_unregister_command (cmd_dump);
grub_unregister_command (cmd_rmmod);
grub_unregister_command (cmd_lsmod);

View file

@ -275,7 +275,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
if (! parsed[j])
{
for (curarg = ptool->args; curarg->name; curarg++)
if (grub_strncmp (curarg->name, args[i],
if (grub_strncmp (curarg->name, args[j],
grub_strlen (curarg->name)) == 0
&& ((curarg->type == GRUB_PARTTOOL_ARG_BOOL
&& (args[j][grub_strlen (curarg->name)] == '+'

View file

@ -40,26 +40,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 +65,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)

View file

@ -45,9 +45,9 @@ static const struct grub_arg_option options[] =
};
static grub_err_t
grub_cmd_probe (grub_extcmd_t cmd, int argc, char **args)
grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
grub_device_t dev;
grub_fs_t fs;
char *ptr;
@ -150,8 +150,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT (probe)
{
cmd = grub_register_extcmd ("probe", grub_cmd_probe, GRUB_COMMAND_FLAG_BOTH,
N_("[DEVICE]"),
cmd = grub_register_extcmd ("probe", grub_cmd_probe, 0, N_("[DEVICE]"),
N_("Retrieve device info."), options);
}

View file

@ -20,37 +20,104 @@
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/command.h>
#include <grub/err.h>
#include <grub/env.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/script_sh.h>
#include <regex.h>
static const struct grub_arg_option options[] =
{
{ "set", 's', GRUB_ARG_OPTION_REPEATABLE,
N_("Variable names to update with matches."),
N_("[NUMBER:]VARNAME"), ARG_TYPE_STRING },
{ 0, 0, 0, 0, 0, 0 }
};
static grub_err_t
grub_cmd_regexp (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
set_matches (char **varnames, char *str, grub_size_t nmatches,
regmatch_t *matches)
{
int i;
char ch;
char *p;
char *q;
grub_err_t err;
unsigned long j;
auto void setvar (char *v, regmatch_t *m);
void setvar (char *v, regmatch_t *m)
{
ch = str[m->rm_eo];
str[m->rm_eo] = '\0';
err = grub_env_set (v, str + m->rm_so);
str[m->rm_eo] = ch;
}
for (i = 0; varnames && varnames[i]; i++)
{
if (! (p = grub_strchr (varnames[i], ':')))
{
/* varname w/o index defaults to 1 */
if (nmatches < 2 || matches[1].rm_so == -1)
grub_env_unset (varnames[i]);
else
setvar (varnames[i], &matches[1]);
}
else
{
j = grub_strtoul (varnames[i], &q, 10);
if (q != p)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"invalid variable name format %s", varnames[i]);
if (nmatches <= j || matches[j].rm_so == -1)
grub_env_unset (p + 1);
else
setvar (p + 1, &matches[j]);
}
if (err != GRUB_ERR_NONE)
return err;
}
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args)
{
int argn = 0;
int matches = 0;
regex_t regex;
int ret;
grub_size_t s;
char *comperr;
grub_err_t err;
regmatch_t *matches = 0;
if (argc != 2)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "2 arguments expected");
ret = regcomp (&regex, args[0], RE_SYNTAX_GNU_AWK);
ret = regcomp (&regex, args[0], REG_EXTENDED);
if (ret)
goto fail;
ret = regexec (&regex, args[1], 0, 0, 0);
matches = grub_zalloc (sizeof (*matches) * (regex.re_nsub + 1));
if (! matches)
goto fail;
ret = regexec (&regex, args[1], regex.re_nsub + 1, matches, 0);
if (!ret)
{
err = set_matches (ctxt->state[0].args, args[1],
regex.re_nsub + 1, matches);
regfree (&regex);
return GRUB_ERR_NONE;
grub_free (matches);
return err;
}
fail:
grub_free (matches);
s = regerror (ret, &regex, 0, 0);
comperr = grub_malloc (s);
if (!comperr)
@ -65,16 +132,19 @@ grub_cmd_regexp (grub_command_t cmd __attribute__ ((unused)),
return err;
}
static grub_command_t cmd;
static grub_extcmd_t cmd;
GRUB_MOD_INIT(regexp)
{
cmd = grub_register_command ("regexp", grub_cmd_regexp,
N_("REGEXP STRING"),
N_("Test if REGEXP matches STRING."));
cmd = grub_register_extcmd ("regexp", grub_cmd_regexp, 0, N_("REGEXP STRING"),
N_("Test if REGEXP matches STRING."), options);
/* Setup GRUB script wildcard translator. */
grub_wildcard_translator = &grub_filename_translator;
}
GRUB_MOD_FINI(regexp)
{
grub_unregister_command (cmd);
grub_unregister_extcmd (cmd);
grub_wildcard_translator = 0;
}

View file

@ -28,9 +28,12 @@
#include <grub/command.h>
#include <grub/search.h>
#include <grub/i18n.h>
#include <grub/disk.h>
#include <grub/partition.h>
void
FUNC_NAME (const char *key, const char *var, int no_floppy)
FUNC_NAME (const char *key, const char *var, int no_floppy,
char **hints, unsigned nhints)
{
int count = 0;
grub_fs_autoload_hook_t saved_autoload;
@ -54,6 +57,7 @@ FUNC_NAME (const char *key, const char *var, int no_floppy)
if (! buf)
return 1;
grub_file_filter_disable_compression ();
file = grub_file_open (buf);
if (file)
{
@ -113,22 +117,86 @@ FUNC_NAME (const char *key, const char *var, int no_floppy)
return (found && var);
}
auto int part_hook (grub_disk_t disk, const grub_partition_t partition);
int part_hook (grub_disk_t disk, const grub_partition_t partition)
{
char *partition_name, *devname;
int ret;
partition_name = grub_partition_get_name (partition);
if (! partition_name)
return 1;
devname = grub_xasprintf ("%s,%s", disk->name, partition_name);
grub_free (partition_name);
if (!devname)
return 1;
ret = iterate_device (devname);
grub_free (devname);
return ret;
}
auto void try (void);
void try (void)
{
unsigned i;
for (i = 0; i < nhints; i++)
{
char *end;
if (!hints[i][0])
continue;
end = hints[i] + grub_strlen (hints[i]) - 1;
if (*end == ',')
*end = 0;
if (iterate_device (hints[i]))
{
if (!*end)
*end = ',';
return;
}
if (!*end)
{
grub_device_t dev;
int ret;
dev = grub_device_open (hints[i]);
if (!dev)
{
*end = ',';
continue;
}
if (!dev->disk)
{
grub_device_close (dev);
*end = ',';
continue;
}
ret = grub_partition_iterate (dev->disk, part_hook);
*end = ',';
grub_device_close (dev);
if (ret)
return;
}
}
grub_device_iterate (iterate_device);
}
/* First try without autoloading if we're setting variable. */
if (var)
{
saved_autoload = grub_fs_autoload_hook;
grub_fs_autoload_hook = 0;
grub_device_iterate (iterate_device);
try ();
/* Restore autoload hook. */
grub_fs_autoload_hook = saved_autoload;
/* Retry with autoload if nothing found. */
if (grub_errno == GRUB_ERR_NONE && count == 0)
grub_device_iterate (iterate_device);
try ();
}
else
grub_device_iterate (iterate_device);
try ();
if (grub_errno == GRUB_ERR_NONE && count == 0)
grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key);
@ -141,7 +209,8 @@ grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc,
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified");
FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0);
FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (args + 2),
argc > 2 ? argc - 2 : 0);
return grub_errno;
}
@ -158,7 +227,7 @@ GRUB_MOD_INIT(search_label)
{
cmd =
grub_register_command (COMMAND_NAME, grub_cmd_do_search,
N_("NAME [VARIABLE]"),
N_("NAME [VARIABLE] [HINTS]"),
HELP_MESSAGE);
}

View file

@ -37,6 +37,9 @@ static const struct grub_arg_option options[] =
{"set", 's', GRUB_ARG_OPTION_OPTIONAL,
N_("Set a variable to the first device found."), "VAR", ARG_TYPE_STRING},
{"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0},
{"hint", 'h', GRUB_ARG_OPTION_REPEATABLE,
N_("First try the device HINT. If HINT ends in comma, "
"also try subpartitions"), N_("HINT"), ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
@ -47,13 +50,19 @@ enum options
SEARCH_FS_UUID,
SEARCH_SET,
SEARCH_NO_FLOPPY,
SEARCH_HINT
};
static grub_err_t
grub_cmd_search (grub_extcmd_t cmd, int argc, char **args)
grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
const char *var = 0;
int nhints = 0;
if (state[SEARCH_HINT].set)
while (state[SEARCH_HINT].args[nhints])
nhints++;
if (argc == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified");
@ -62,11 +71,14 @@ grub_cmd_search (grub_extcmd_t cmd, int argc, char **args)
var = state[SEARCH_SET].arg ? state[SEARCH_SET].arg : "root";
if (state[SEARCH_LABEL].set)
grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set);
grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set,
state[SEARCH_HINT].args, nhints);
else if (state[SEARCH_FS_UUID].set)
grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set);
grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set,
state[SEARCH_HINT].args, nhints);
else if (state[SEARCH_FILE].set)
grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set);
grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set,
state[SEARCH_HINT].args, nhints);
else
return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type");
@ -78,9 +90,9 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(search)
{
cmd =
grub_register_extcmd ("search", grub_cmd_search,
GRUB_COMMAND_FLAG_BOTH,
N_("search [-f|-l|-u|-s|-n] NAME"),
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"
" or filesystem UUID."
" If --set is specified, the first device found is"

View file

@ -155,7 +155,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid)
}
static grub_err_t
grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv)
grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv)
{
const char *ptr;
unsigned i;
@ -163,14 +163,14 @@ grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv)
pciid_check_value = 0;
pciid_check_mask = 0;
if (cmd->state[0].set)
if (ctxt->state[0].set)
{
ptr = cmd->state[0].arg;
ptr = ctxt->state[0].arg;
pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff);
if (grub_errno == GRUB_ERR_BAD_NUMBER)
{
grub_errno = GRUB_ERR_NONE;
ptr = cmd->state[0].arg;
ptr = ctxt->state[0].arg;
}
else
pciid_check_mask |= 0xffff;
@ -191,11 +191,11 @@ grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv)
check_bus = check_device = check_function = 0;
if (cmd->state[1].set)
if (ctxt->state[1].set)
{
const char *optr;
ptr = cmd->state[1].arg;
ptr = ctxt->state[1].arg;
optr = ptr;
bus = grub_strtoul (ptr, (char **) &ptr, 16);
if (grub_errno == GRUB_ERR_BAD_NUMBER)
@ -229,8 +229,8 @@ grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv)
}
}
if (cmd->state[2].set)
varname = cmd->state[2].arg;
if (ctxt->state[2].set)
varname = ctxt->state[2].arg;
else
varname = NULL;
@ -329,7 +329,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(setpci)
{
cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, 0,
N_("[-s POSITION] [-d DEVICE] [-v VAR] "
"[REGISTER][=VALUE[:MASK]]"),
N_("Manipulate PCI devices."), options);

View file

@ -52,17 +52,16 @@ 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;
}
static grub_err_t
grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args)
grub_cmd_sleep (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = cmd->state;
struct grub_arg_list *state = ctxt->state;
int n;
if (argc != 1)
@ -101,7 +100,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(sleep)
{
cmd = grub_register_extcmd ("sleep", grub_cmd_sleep, GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("sleep", grub_cmd_sleep, 0,
N_("NUMBER_OF_SECONDS"),
N_("Wait for a specified number of seconds."),
options);

View file

@ -334,6 +334,7 @@ test_parse (char **args, int *argn, int argc)
if (grub_strcmp (args[*argn], "-s") == 0)
{
grub_file_t file;
grub_file_filter_disable_compression ();
file = grub_file_open (args[*argn + 1]);
update_val (file && (grub_file_size (file) != 0));
if (file)
@ -422,8 +423,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)

View file

@ -0,0 +1,155 @@
/* 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.
*
* 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/mm.h>
#include <grub/err.h>
#include <grub/env.h>
#include <grub/misc.h>
#include <grub/file.h>
#include <grub/disk.h>
#include <grub/term.h>
#include <grub/loader.h>
#include <grub/command.h>
#include <grub/i18n.h>
static grub_err_t
grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t file;
char *buf;
grub_size_t size;
grub_off_t pos;
auto void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector, unsigned offset, unsigned len);
void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector __attribute__ ((unused)),
unsigned offset __attribute__ ((unused)),
unsigned len __attribute__ ((unused)))
{
grub_xputs (".");
grub_refresh ();
}
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified");
file = grub_file_open (argv[0]);
if (! file)
return grub_errno;
size = grub_file_size (file) & ~(GRUB_DISK_SECTOR_SIZE - 1);
if (size == 0)
{
grub_file_close (file);
return GRUB_ERR_NONE;
}
buf = grub_malloc (size);
if (! buf)
goto fail;
grub_printf ("Reading %s sequentially", argv[0]);
file->read_hook = read_func;
if (grub_file_read (file, buf, size) != (grub_ssize_t) size)
goto fail;
grub_printf (" Done.\n");
/* Read sequentially again. */
grub_printf ("Reading %s sequentially again", argv[0]);
grub_file_seek (file, 0);
for (pos = 0; pos < size; pos += GRUB_DISK_SECTOR_SIZE)
{
char sector[GRUB_DISK_SECTOR_SIZE];
if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE)
!= GRUB_DISK_SECTOR_SIZE)
goto fail;
if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0)
{
grub_printf ("\nDiffers in %lld\n", (unsigned long long) pos);
goto fail;
}
}
grub_printf (" Done.\n");
/* Read backwards and compare. */
grub_printf ("Reading %s backwards", argv[0]);
pos = size;
while (pos > 0)
{
char sector[GRUB_DISK_SECTOR_SIZE];
pos -= GRUB_DISK_SECTOR_SIZE;
grub_file_seek (file, pos);
if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE)
!= GRUB_DISK_SECTOR_SIZE)
goto fail;
if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0)
{
int i;
grub_printf ("\nDiffers in %lld\n", (unsigned long long) pos);
for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i++)
{
grub_printf ("%02x ", buf[pos + i]);
if ((i & 15) == 15)
grub_printf ("\n");
}
if (i)
grub_refresh ();
goto fail;
}
}
grub_printf (" Done.\n");
return GRUB_ERR_NONE;
fail:
grub_file_close (file);
grub_free (buf);
if (!grub_errno)
grub_error (GRUB_ERR_IO, "bad read");
return grub_errno;
}
static grub_command_t cmd;
GRUB_MOD_INIT(testload)
{
cmd =
grub_register_command ("testload", grub_cmd_testload,
N_("FILE"),
N_("Load the same file in multiple ways."));
}
GRUB_MOD_FINI(testload)
{
grub_unregister_command (cmd);
}

View file

@ -0,0 +1,184 @@
/* videoinfo.c - command to list video modes. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,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/video.h>
#include <grub/dl.h>
#include <grub/env.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/command.h>
#include <grub/i18n.h>
static unsigned height, width, depth;
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);
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 ");
/* 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);
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
grub_printf ("Packed ");
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV)
grub_printf ("YUV ");
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR)
grub_printf ("Planar ");
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES)
grub_printf ("Hercules ");
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA)
grub_printf ("CGA ");
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_NONCHAIN4)
grub_printf ("Non-chain 4 ");
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP)
grub_printf ("Monochrome ");
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN)
grub_printf ("Unknown ");
grub_printf ("\n");
return 0;
}
static grub_err_t
grub_cmd_videoinfo (grub_command_t cmd __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");
#endif
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");
FOR_VIDEO_ADAPTERS (adapter)
{
grub_printf ("Adapter '%s':\n", adapter->name);
if (!adapter->iterate)
{
grub_printf (" No info available\n");
continue;
}
if (adapter->id != id)
{
if (adapter->init ())
{
grub_printf (" Failed\n");
grub_errno = GRUB_ERR_NONE;
continue;
}
}
if (adapter->print_adapter_specific_info)
adapter->print_adapter_specific_info ();
adapter->iterate (hook);
if (adapter->id != id)
{
if (adapter->fini ())
{
grub_errno = GRUB_ERR_NONE;
continue;
}
}
}
return GRUB_ERR_NONE;
}
static grub_command_t cmd;
#ifdef GRUB_MACHINE_PCBIOS
static grub_command_t cmd_vbe;
#endif
GRUB_MOD_INIT(videoinfo)
{
cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, "[WxH[xD]]",
N_("List available video modes. If "
"resolution is given show only modes"
" matching it."));
#ifdef GRUB_MACHINE_PCBIOS
cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo, "[WxH[xD]]",
N_("List available video modes. If "
"resolution is given show only modes"
" matching it."));
#endif
}
GRUB_MOD_FINI(videoinfo)
{
grub_unregister_command (cmd);
#ifdef GRUB_MACHINE_PCBIOS
grub_unregister_command (cmd_vbe);
#endif
}

View file

@ -26,11 +26,11 @@
#include <grub/command.h>
#include <grub/i18n.h>
#include <grub/gfxmenu_view.h>
#include <grub/env.h>
static grub_err_t
grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char **args __attribute__ ((unused)))
int argc, char **args)
{
grub_err_t err;
grub_video_color_t color;
@ -41,8 +41,20 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
int i;
struct grub_video_render_target *text_layer;
grub_video_color_t palette[16];
const char *mode = NULL;
err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
#ifdef GRUB_MACHINE_PCBIOS
if (grub_strcmp (cmd->name, "vbetest") == 0)
grub_dl_load ("vbe");
#endif
mode = grub_env_get ("gfxmode");
if (argc)
mode = args[0];
if (!mode)
mode = "auto";
err = grub_video_set_mode (mode, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
if (err)
return err;
@ -180,14 +192,25 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
}
static grub_command_t cmd;
#ifdef GRUB_MACHINE_PCBIOS
static grub_command_t cmd_vbe;
#endif
GRUB_MOD_INIT(videotest)
{
cmd = grub_register_command ("videotest", grub_cmd_videotest,
"[WxH]",
N_("Test video subsystem in mode WxH."));
#ifdef GRUB_MACHINE_PCBIOS
cmd_vbe = grub_register_command ("vbetest", grub_cmd_videotest,
0, N_("Test video subsystem."));
#endif
}
GRUB_MOD_FINI(videotest)
{
grub_unregister_command (cmd);
#ifdef GRUB_MACHINE_PCBIOS
grub_unregister_command (cmd_vbe);
#endif
}

View file

@ -0,0 +1,498 @@
/* wildcard.c - Wildcard character expansion for GRUB script. */
/*
* 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/mm.h>
#include <grub/fs.h>
#include <grub/env.h>
#include <grub/file.h>
#include <grub/device.h>
#include <grub/script_sh.h>
#include <regex.h>
static inline int isregexop (char ch);
static char ** merge (char **lhs, char **rhs);
static char *make_dir (const char *prefix, const char *start, const char *end);
static int make_regex (const char *regex_start, const char *regex_end,
regex_t *regexp);
static void split_path (const char *path, const char **suffix_end, const char **regex_end);
static char ** match_devices (const regex_t *regexp, int noparts);
static char ** match_files (const char *prefix, const char *suffix_start,
const char *suffix_end, const regex_t *regexp);
static char* wildcard_escape (const char *s);
static char* wildcard_unescape (const char *s);
static grub_err_t wildcard_expand (const char *s, char ***strs);
struct grub_script_wildcard_translator grub_filename_translator = {
.expand = wildcard_expand,
.escape = wildcard_escape,
.unescape = wildcard_unescape
};
static char **
merge (char **dest, char **ps)
{
int i;
int j;
char **p;
if (! dest)
return ps;
if (! ps)
return dest;
for (i = 0; dest[i]; i++)
;
for (j = 0; ps[j]; j++)
;
p = grub_realloc (dest, sizeof (char*) * (i + j + 1));
if (! p)
{
grub_free (dest);
grub_free (ps);
return 0;
}
dest = p;
for (j = 0; ps[j]; j++)
dest[i++] = ps[j];
dest[i] = 0;
grub_free (ps);
return dest;
}
static inline int
isregexop (char ch)
{
return grub_strchr ("*.\\", ch) ? 1 : 0;
}
static char *
make_dir (const char *prefix, const char *start, const char *end)
{
char ch;
unsigned i;
unsigned n;
char *result;
i = grub_strlen (prefix);
n = i + end - start;
result = grub_malloc (n + 1);
if (! result)
return 0;
grub_strcpy (result, prefix);
while (start < end && (ch = *start++))
if (ch == '\\' && isregexop (*start))
result[i++] = *start++;
else
result[i++] = ch;
result[i] = '\0';
return result;
}
static int
make_regex (const char *start, const char *end, regex_t *regexp)
{
char ch;
int i = 0;
unsigned len = end - start;
char *buffer = grub_malloc (len * 2 + 2 + 1); /* worst case size. */
if (! buffer)
return 1;
buffer[i++] = '^';
while (start < end)
{
/* XXX Only * expansion for now. */
switch ((ch = *start++))
{
case '\\':
buffer[i++] = ch;
if (*start != '\0')
buffer[i++] = *start++;
break;
case '.':
case '(':
case ')':
buffer[i++] = '\\';
buffer[i++] = ch;
break;
case '*':
buffer[i++] = '.';
buffer[i++] = '*';
break;
default:
buffer[i++] = ch;
}
}
buffer[i++] = '$';
buffer[i] = '\0';
grub_dprintf ("expand", "Regexp is %s\n", buffer);
if (regcomp (regexp, buffer, RE_SYNTAX_GNU_AWK))
{
grub_free (buffer);
return 1;
}
grub_free (buffer);
return 0;
}
/* Split `str' into two parts: (1) dirname that is regexop free (2)
dirname that has a regexop. */
static void
split_path (const char *str, const char **noregexop, const char **regexop)
{
char ch = 0;
int regex = 0;
const char *end;
const char *split; /* points till the end of dirnaname that doesn't
need expansion. */
split = end = str;
while ((ch = *end))
{
if (ch == '\\' && end[1])
end++;
else if (isregexop (ch))
regex = 1;
else if (ch == '/' && ! regex)
split = end + 1; /* forward to next regexop-free dirname */
else if (ch == '/' && regex)
break; /* stop at the first dirname with a regexop */
end++;
}
*regexop = end;
if (! regex)
*noregexop = end;
else
*noregexop = split;
}
static char **
match_devices (const regex_t *regexp, int noparts)
{
int i;
int ndev;
char **devs;
auto int match (const char *name);
int match (const char *name)
{
char **t;
char *buffer;
/* skip partitions if asked to. */
if (noparts && grub_strchr(name, ','))
return 0;
buffer = grub_xasprintf ("(%s)", name);
if (! buffer)
return 1;
grub_dprintf ("expand", "matching: %s\n", buffer);
if (regexec (regexp, buffer, 0, 0, 0))
{
grub_dprintf ("expand", "not matched\n");
grub_free (buffer);
return 0;
}
t = grub_realloc (devs, sizeof (char*) * (ndev + 2));
if (! t)
return 1;
devs = t;
devs[ndev++] = buffer;
devs[ndev] = 0;
return 0;
}
ndev = 0;
devs = 0;
if (grub_device_iterate (match))
goto fail;
return devs;
fail:
for (i = 0; devs && devs[i]; i++)
grub_free (devs[i]);
if (devs)
grub_free (devs);
return 0;
}
static char **
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;
const char *path;
char *device_name;
grub_fs_t fs;
grub_device_t dev;
auto int match (const char *name, const struct grub_dirhook_info *info);
int match (const char *name, const struct grub_dirhook_info *info)
{
char **t;
char *buffer;
/* skip . and .. names */
if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0)
return 0;
grub_dprintf ("expand", "matching: %s in %s\n", name, dir);
if (regexec (regexp, name, 0, 0, 0))
return 0;
buffer = grub_xasprintf ("%s%s", dir, name);
if (! buffer)
return 1;
t = grub_realloc (files, sizeof (char*) * (nfile + 2));
if (! t)
{
grub_free (buffer);
return 1;
}
files = t;
files[nfile++] = buffer;
files[nfile] = 0;
return 0;
}
nfile = 0;
files = 0;
dev = 0;
device_name = 0;
grub_error_push ();
dir = make_dir (prefix, suffix, end);
if (! dir)
goto fail;
device_name = grub_file_get_device_name (dir);
dev = grub_device_open (device_name);
if (! dev)
goto fail;
fs = grub_fs_probe (dev);
if (! fs)
goto fail;
path = grub_strchr (dir, ')');
if (! path)
goto fail;
path++;
if (fs->dir (dev, path, match))
goto fail;
grub_free (dir);
grub_device_close (dev);
grub_free (device_name);
grub_error_pop ();
return files;
fail:
if (dir)
grub_free (dir);
for (i = 0; files && files[i]; i++)
grub_free (files[i]);
if (files)
grub_free (files);
if (dev)
grub_device_close (dev);
if (device_name)
grub_free (device_name);
grub_error_pop ();
return 0;
}
static char*
wildcard_escape (const char *s)
{
int i;
int len;
char ch;
char *p;
len = grub_strlen (s);
p = grub_malloc (len * 2 + 1);
if (! p)
return NULL;
i = 0;
while ((ch = *s++))
{
if (isregexop (ch))
p[i++] = '\\';
p[i++] = ch;
}
p[i] = '\0';
return p;
}
static char*
wildcard_unescape (const char *s)
{
int i;
int len;
char ch;
char *p;
len = grub_strlen (s);
p = grub_malloc (len + 1);
if (! p)
return NULL;
i = 0;
while ((ch = *s++))
{
if (ch == '\\' && isregexop (*s))
p[i++] = *s++;
else
p[i++] = ch;
}
p[i] = '\0';
return p;
}
static grub_err_t
wildcard_expand (const char *s, char ***strs)
{
const char *start;
const char *regexop;
const char *noregexop;
char **paths = 0;
unsigned i;
regex_t regexp;
start = s;
while (*start)
{
split_path (start, &noregexop, &regexop);
if (noregexop >= regexop) /* no more wildcards */
break;
if (make_regex (noregexop, regexop, &regexp))
goto fail;
if (paths == 0)
{
if (start == noregexop) /* device part has regexop */
paths = match_devices (&regexp, *start != '(');
else if (*start == '(') /* device part explicit wo regexop */
paths = match_files ("", start, noregexop, &regexp);
else if (*start == '/') /* no device part */
{
char **r;
unsigned n;
char *root;
char *prefix;
root = grub_env_get ("root");
if (! root)
goto fail;
prefix = grub_xasprintf ("(%s)", root);
if (! prefix)
goto fail;
paths = match_files (prefix, start, noregexop, &regexp);
grub_free (prefix);
}
}
else
{
char **r = 0;
for (i = 0; paths[i]; i++)
{
char **p;
p = match_files (paths[i], start, noregexop, &regexp);
if (! p)
continue;
r = merge (r, p);
if (! r)
goto fail;
}
paths = r;
}
regfree (&regexp);
if (! paths)
goto done;
start = regexop;
}
done:
*strs = paths;
return 0;
fail:
for (i = 0; paths && paths[i]; i++)
grub_free (paths[i]);
grub_free (paths);
regfree (&regexp);
return grub_errno;
}

View file

@ -723,7 +723,6 @@ grub_ata_open (const char *name, grub_disk_t disk)
disk->id = (unsigned long) dev;
disk->has_partitions = 1;
disk->data = dev;
return 0;

View file

@ -514,16 +514,12 @@ grub_efidisk_open (const char *name, struct grub_disk *disk)
switch (name[0])
{
case 'f':
disk->has_partitions = 0;
d = get_device (fd_devices, num);
break;
case 'c':
/* FIXME: a CDROM should have partitions, but not implemented yet. */
disk->has_partitions = 0;
d = get_device (cd_devices, num);
break;
case 'h':
disk->has_partitions = 1;
d = get_device (hd_devices, num);
break;
default:
@ -731,7 +727,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
{
/* This is a hard disk partition. */
grub_disk_t parent = 0;
char *partition_name = 0;
grub_partition_t tpart = NULL;
char *device_name;
grub_efi_device_path_t *dup_dp, *dup_ldp;
grub_efi_hard_drive_device_path_t hd;
@ -770,7 +766,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
if (grub_partition_get_start (part) == hd.partition_start
&& grub_partition_get_len (part) == hd.partition_size)
{
partition_name = grub_partition_get_name (part);
tpart = part;
return 1;
}
@ -799,14 +795,17 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle)
grub_memcpy (&hd, ldp, sizeof (hd));
grub_partition_iterate (parent, find_partition);
if (! partition_name)
if (! tpart)
{
grub_disk_close (parent);
return 0;
}
device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
grub_free (partition_name);
{
char *partition_name = grub_partition_get_name (tpart);
device_name = grub_xasprintf ("%s,%s", parent->name, partition_name);
grub_free (partition_name);
}
grub_disk_close (parent);
return device_name;

View file

@ -43,7 +43,6 @@ grub_host_open (const char *name, grub_disk_t disk)
disk->total_sectors = 0;
disk->id = (unsigned long) "host";
disk->has_partitions = 0;
disk->data = 0;
return GRUB_ERR_NONE;

View file

@ -17,8 +17,8 @@
*/
#include <grub/machine/biosdisk.h>
#include <grub/machine/memory.h>
#include <grub/machine/kernel.h>
#include <grub/machine/memory.h>
#include <grub/machine/int.h>
#include <grub/disk.h>
#include <grub/dl.h>
@ -248,6 +248,9 @@ grub_biosdisk_get_drive (const char *name)
{
unsigned long drive;
if (name[0] == 'c' && name[1] == 'd' && name[2] == 0 && cd_drive)
return cd_drive;
if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd')
goto fail;
@ -270,6 +273,9 @@ grub_biosdisk_call_hook (int (*hook) (const char *name), int drive)
{
char name[10];
if (cd_drive && drive == cd_drive)
return hook ("cd");
grub_snprintf (name, sizeof (name),
(drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
return hook (name);
@ -321,7 +327,6 @@ grub_biosdisk_open (const char *name, grub_disk_t disk)
if (drive < 0)
return grub_errno;
disk->has_partitions = 1;
disk->id = drive;
data = (struct grub_biosdisk_data *) grub_zalloc (sizeof (*data));

View file

@ -113,7 +113,6 @@ grub_nand_open (const char *name, grub_disk_t disk)
disk->id = dev_ihandle;
disk->has_partitions = 0;
disk->data = data;
return 0;

View file

@ -23,9 +23,15 @@
#include <grub/ieee1275/ieee1275.h>
#include <grub/ieee1275/ofdisk.h>
static char *last_devpath;
static grub_ieee1275_ihandle_t last_ihandle;
struct ofdisk_hash_ent
{
char *devpath;
/* Pointer to shortest available name on nodes representing canonical names,
otherwise NULL. */
const char *shortest;
struct ofdisk_hash_ent *next;
};
@ -59,60 +65,125 @@ static struct ofdisk_hash_ent *
ofdisk_hash_add (char *devpath)
{
struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)];
struct ofdisk_hash_ent *p = grub_malloc(sizeof (*p));
struct ofdisk_hash_ent *p, *pcan;
char *curcan;
if (p)
p = grub_malloc(sizeof (*p));
if (!p)
return NULL;
p->devpath = devpath;
p->next = *head;
p->shortest = 0;
*head = p;
curcan = grub_ieee1275_canonicalise_devname (devpath);
if (!curcan)
{
p->devpath = devpath;
p->next = *head;
*head = p;
grub_errno = GRUB_ERR_NONE;
return p;
}
pcan = ofdisk_hash_find (curcan);
if (!pcan)
pcan = ofdisk_hash_add (curcan);
else
grub_free (curcan);
if (!pcan)
grub_errno = GRUB_ERR_NONE;
else
{
if (!pcan->shortest
|| grub_strlen (pcan->shortest) > grub_strlen (devpath))
pcan->shortest = devpath;
}
return p;
}
static int
grub_ofdisk_iterate (int (*hook) (const char *name))
static void
scan (void)
{
auto int dev_iterate (struct grub_ieee1275_devalias *alias);
int dev_iterate (struct grub_ieee1275_devalias *alias)
{
int ret = 0;
struct ofdisk_hash_ent *op;
grub_dprintf ("disk", "device name = %s type = %s\n", alias->name,
alias->type);
if (grub_strcmp (alias->type, "block") != 0)
return 0;
grub_dprintf ("disk", "disk name = %s\n", alias->name);
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY))
op = ofdisk_hash_find (alias->path);
if (!op)
{
grub_ieee1275_phandle_t dev;
char tmp[8];
if (grub_ieee1275_finddevice (alias->path, &dev))
char *name = grub_strdup (alias->name);
if (!name)
{
grub_dprintf ("disk", "finddevice (%s) failed\n", alias->path);
return 0;
}
if (grub_ieee1275_get_property (dev, "iconname", tmp,
sizeof tmp, 0))
{
grub_dprintf ("disk", "get iconname failed\n");
return 0;
}
if (grub_strcmp (tmp, "sdmmc"))
{
grub_dprintf ("disk", "device is not an SD card\n");
grub_errno = GRUB_ERR_NONE;
return 0;
}
op = ofdisk_hash_add (name);
}
if (! grub_strcmp (alias->type, "block") &&
grub_strncmp (alias->name, "cdrom", 5))
ret = hook (alias->name);
return ret;
return 0;
}
return grub_devalias_iterate (dev_iterate);
grub_devalias_iterate (dev_iterate);
grub_ieee1275_devices_iterate (dev_iterate);
}
static int
grub_ofdisk_iterate (int (*hook) (const char *name))
{
unsigned i;
scan ();
for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++)
{
static struct ofdisk_hash_ent *ent;
for (ent = ofdisk_hash[i]; ent; ent = ent->next)
{
if (!ent->shortest)
continue;
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY))
{
grub_ieee1275_phandle_t dev;
char tmp[8];
if (grub_ieee1275_finddevice (ent->devpath, &dev))
{
grub_dprintf ("disk", "finddevice (%s) failed\n",
ent->devpath);
continue;
}
if (grub_ieee1275_get_property (dev, "iconname", tmp,
sizeof tmp, 0))
{
grub_dprintf ("disk", "get iconname failed\n");
continue;
}
if (grub_strcmp (tmp, "sdmmc") != 0)
{
grub_dprintf ("disk", "device is not an SD card\n");
continue;
}
}
if (grub_strncmp (ent->shortest, "cdrom", 5) == 0)
continue;
if (hook (ent->shortest))
return 1;
}
}
return 0;
}
static char *
@ -137,11 +208,6 @@ compute_dev_path (const char *name)
*p++ = c;
}
if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
{
*p++ = ':';
*p++ = '0';
}
*p++ = '\0';
return devpath;
@ -151,8 +217,6 @@ static grub_err_t
grub_ofdisk_open (const char *name, grub_disk_t disk)
{
grub_ieee1275_phandle_t dev;
grub_ieee1275_ihandle_t dev_ihandle = 0;
struct ofdisk_hash_ent *op;
char *devpath;
/* XXX: This should be large enough for any possible case. */
char prop[64];
@ -162,69 +226,50 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
if (! devpath)
return grub_errno;
op = ofdisk_hash_find (devpath);
if (!op)
op = ofdisk_hash_add (devpath);
grub_dprintf ("disk", "Opening `%s'.\n", devpath);
grub_free (devpath);
if (!op)
return grub_errno;
grub_dprintf ("disk", "Opening `%s'.\n", op->devpath);
if (grub_ieee1275_finddevice (op->devpath, &dev))
{
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties");
goto fail;
}
if (grub_ieee1275_finddevice (devpath, &dev))
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties");
if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop),
&actual))
{
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
goto fail;
}
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type");
if (grub_strcmp (prop, "block"))
{
grub_error (GRUB_ERR_BAD_DEVICE, "not a block device");
goto fail;
}
grub_ieee1275_open (op->devpath, &dev_ihandle);
if (! dev_ihandle)
{
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
goto fail;
}
grub_dprintf ("disk", "Opened `%s' as handle %p.\n", op->devpath,
(void *) (unsigned long) dev_ihandle);
return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device");
/* XXX: There is no property to read the number of blocks. There
should be a property `#blocks', but it is not there. Perhaps it
is possible to use seek for this. */
disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
disk->id = (unsigned long) op;
{
struct ofdisk_hash_ent *op;
op = ofdisk_hash_find (devpath);
if (!op)
op = ofdisk_hash_add (devpath);
else
grub_free (devpath);
if (!op)
return grub_errno;
disk->id = (unsigned long) op;
disk->data = op->devpath;
}
/* XXX: Read this, somehow. */
disk->has_partitions = 1;
disk->data = (void *) (unsigned long) dev_ihandle;
return 0;
fail:
if (dev_ihandle)
grub_ieee1275_close (dev_ihandle);
return grub_errno;
}
static void
grub_ofdisk_close (grub_disk_t disk)
{
grub_dprintf ("disk", "Closing handle %p.\n",
(void *) disk->data);
grub_ieee1275_close ((grub_ieee1275_ihandle_t) (unsigned long) disk->data);
if (disk->data == last_devpath)
{
if (last_ihandle)
grub_ieee1275_close (last_ihandle);
last_ihandle = 0;
last_devpath = NULL;
}
disk->data = 0;
}
static grub_err_t
@ -234,16 +279,40 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_ssize_t status, actual;
unsigned long long pos;
if (disk->data != last_devpath)
{
if (last_ihandle)
grub_ieee1275_close (last_ihandle);
last_ihandle = 0;
last_devpath = NULL;
if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0))
{
char name2[grub_strlen (disk->data) + 3];
char *p;
grub_strcpy (name2, disk->data);
p = name2 + grub_strlen (name2);
*p++ = ':';
*p++ = '0';
*p = 0;
grub_ieee1275_open (name2, &last_ihandle);
}
else
grub_ieee1275_open (disk->data, &last_ihandle);
if (! last_ihandle)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
last_devpath = disk->data;
}
pos = sector * 512UL;
grub_ieee1275_seek ((grub_ieee1275_ihandle_t) (unsigned long) disk->data,
pos, &status);
grub_ieee1275_seek (last_ihandle, pos, &status);
if (status < 0)
return grub_error (GRUB_ERR_READ_ERROR,
"seek error, can't seek block %llu",
(long long) sector);
grub_ieee1275_read ((grub_ieee1275_ihandle_t) (unsigned long) disk->data,
buf, size * 512UL, &actual);
grub_ieee1275_read (last_ihandle, buf, size * 512UL, &actual);
if (actual != (grub_ssize_t) (size * 512UL))
return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu",
(long long) sector);
@ -281,5 +350,10 @@ grub_ofdisk_init (void)
void
grub_ofdisk_fini (void)
{
if (last_ihandle)
grub_ieee1275_close (last_ihandle);
last_ihandle = 0;
last_devpath = NULL;
grub_disk_dev_unregister (&grub_ofdisk_dev);
}

View file

@ -29,7 +29,6 @@ struct grub_loopback
{
char *devname;
grub_file_t file;
int has_partitions;
struct grub_loopback *next;
};
@ -38,7 +37,6 @@ static struct grub_loopback *loopback_list;
static const struct grub_arg_option options[] =
{
{"delete", 'd', 0, N_("Delete the loopback device entry."), 0, 0},
{"partitions", 'p', 0, N_("Simulate a hard drive with partitions."), 0, 0},
{0, 0, 0, 0, 0, 0}
};
@ -71,9 +69,9 @@ delete_loopback (const char *name)
/* The command to add and remove loopback devices. */
static grub_err_t
grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = state = cmd->state;
struct grub_arg_list *state = ctxt->state;
grub_file_t file;
struct grub_loopback *newdev;
grub_err_t ret;
@ -106,9 +104,6 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
grub_file_close (newdev->file);
newdev->file = file;
/* Set has_partitions when `--partitions' was used. */
newdev->has_partitions = state[1].set;
return 0;
}
@ -126,9 +121,6 @@ grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args)
newdev->file = file;
/* Set has_partitions when `--partitions' was used. */
newdev->has_partitions = state[1].set;
/* Add the new entry to the list. */
newdev->next = loopback_list;
loopback_list = newdev;
@ -167,11 +159,13 @@ grub_loopback_open (const char *name, grub_disk_t disk)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device");
/* Use the filesize for the disk size, round up to a complete sector. */
disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
/ GRUB_DISK_SECTOR_SIZE);
if (dev->file->size != GRUB_FILE_SIZE_UNKNOWN)
disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
/ GRUB_DISK_SECTOR_SIZE);
else
disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
disk->id = (unsigned long) dev;
disk->has_partitions = dev->has_partitions;
disk->data = dev->file;
return 0;
@ -227,8 +221,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(loopback)
{
cmd = grub_register_extcmd ("loopback", grub_cmd_loopback,
GRUB_COMMAND_FLAG_BOTH,
cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, 0,
N_("[-d|-p] DEVICENAME FILE."),
N_("Make a device of a file."), options);
grub_disk_dev_register (&grub_loopback_dev);

View file

@ -150,7 +150,6 @@ grub_lvm_open (const char *name, grub_disk_t disk)
if (! lv)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown LVM device %s", name);
disk->has_partitions = 0;
disk->id = lv->number;
disk->data = lv;
disk->total_sectors = lv->size;
@ -274,9 +273,17 @@ grub_lvm_scan_device (const char *name)
struct grub_lvm_vg *vg;
struct grub_lvm_pv *pv;
#ifdef GRUB_UTIL
grub_util_info ("scanning %s for LVM", name);
#endif
disk = grub_disk_open (name);
if (!disk)
return 0;
{
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
grub_errno = GRUB_ERR_NONE;
return 0;
}
/* Search for label. */
for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++)
@ -294,7 +301,12 @@ grub_lvm_scan_device (const char *name)
/* Return if we didn't find a label. */
if (i == GRUB_LVM_LABEL_SCAN_SECTORS)
goto fail;
{
#ifdef GRUB_UTIL
grub_util_info ("no LVM signature found\n");
#endif
goto fail;
}
pvh = (struct grub_lvm_pv_header *) (buf + grub_le_to_cpu32(lh->offset_xl));
@ -318,6 +330,9 @@ grub_lvm_scan_device (const char *name)
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"we don't support multiple LVM data areas");
#ifdef GRUB_UTIL
grub_util_info ("we don't support multiple LVM data areas\n");
#endif
goto fail;
}
@ -344,6 +359,9 @@ grub_lvm_scan_device (const char *name)
{
grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unknown LVM metadata header");
#ifdef GRUB_UTIL
grub_util_info ("unknown LVM metadata header\n");
#endif
goto fail2;
}
@ -364,7 +382,12 @@ grub_lvm_scan_device (const char *name)
q++;
if (q == metadatabuf + mda_size)
goto fail2;
{
#ifdef GRUB_UTIL
grub_util_info ("error parsing metadata\n");
#endif
goto fail2;
}
vgname_len = q - p;
vgname = grub_malloc (vgname_len + 1);
@ -376,7 +399,12 @@ grub_lvm_scan_device (const char *name)
p = grub_strstr (q, "id = \"");
if (p == NULL)
goto fail3;
{
#ifdef GRUB_UTIL
grub_util_info ("couldn't find ID\n");
#endif
goto fail3;
}
p += sizeof ("id = \"") - 1;
grub_memcpy (vg_id, p, GRUB_LVM_ID_STRLEN);
vg_id[GRUB_LVM_ID_STRLEN] = '\0';
@ -399,7 +427,12 @@ grub_lvm_scan_device (const char *name)
vg->extent_size = grub_lvm_getvalue (&p, "extent_size = ");
if (p == NULL)
goto fail4;
{
#ifdef GRUB_UTIL
grub_util_info ("unknown extent size\n");
#endif
goto fail4;
}
vg->lvs = NULL;
vg->pvs = NULL;
@ -439,11 +472,21 @@ grub_lvm_scan_device (const char *name)
pv->start = grub_lvm_getvalue (&p, "pe_start = ");
if (p == NULL)
goto pvs_fail;
{
#ifdef GRUB_UTIL
grub_util_info ("unknown pe_start\n");
#endif
goto pvs_fail;
}
p = grub_strchr (p, '}');
if (p == NULL)
goto pvs_fail;
{
#ifdef GRUB_UTIL
grub_util_info ("error parsing pe_start\n");
#endif
goto pvs_fail;
}
p++;
pv->disk = NULL;
@ -500,7 +543,12 @@ grub_lvm_scan_device (const char *name)
lv->segment_count = grub_lvm_getvalue (&p, "segment_count = ");
if (p == NULL)
goto lvs_fail;
{
#ifdef GRUB_UTIL
grub_util_info ("unknown segment_count\n");
#endif
goto lvs_fail;
}
lv->segments = grub_malloc (sizeof (*seg) * lv->segment_count);
seg = lv->segments;
@ -510,14 +558,29 @@ grub_lvm_scan_device (const char *name)
p = grub_strstr (p, "segment");
if (p == NULL)
goto lvs_segment_fail;
{
#ifdef GRUB_UTIL
grub_util_info ("unknown segment\n");
#endif
goto lvs_segment_fail;
}
seg->start_extent = grub_lvm_getvalue (&p, "start_extent = ");
if (p == NULL)
goto lvs_segment_fail;
{
#ifdef GRUB_UTIL
grub_util_info ("unknown start_extent\n");
#endif
goto lvs_segment_fail;
}
seg->extent_count = grub_lvm_getvalue (&p, "extent_count = ");
if (p == NULL)
goto lvs_segment_fail;
{
#ifdef GRUB_UTIL
grub_util_info ("unknown extent_count\n");
#endif
goto lvs_segment_fail;
}
if (grub_lvm_checkvalue (&p, "type = ", "snapshot"))
{
@ -528,7 +591,12 @@ grub_lvm_scan_device (const char *name)
seg->stripe_count = grub_lvm_getvalue (&p, "stripe_count = ");
if (p == NULL)
goto lvs_segment_fail;
{
#ifdef GRUB_UTIL
grub_util_info ("unknown stripe_count\n");
#endif
goto lvs_segment_fail;
}
lv->size += seg->extent_count * vg->extent_size;
@ -541,7 +609,12 @@ grub_lvm_scan_device (const char *name)
p = grub_strstr (p, "stripes = [");
if (p == NULL)
goto lvs_segment_fail2;
{
#ifdef GRUB_UTIL
grub_util_info ("unknown stripes\n");
#endif
goto lvs_segment_fail2;
}
p += sizeof("stripes = [") - 1;
for (j = 0; j < seg->stripe_count; j++)
@ -655,6 +728,8 @@ grub_lvm_scan_device (const char *name)
grub_free (metadatabuf);
fail:
grub_disk_close (disk);
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
grub_errno = GRUB_ERR_NONE;
return 0;
}

View file

@ -0,0 +1,231 @@
/* mdraid_linux.c - module to handle Linux Software RAID. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009,2010 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/dl.h>
#include <grub/disk.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/raid.h>
/* Linux RAID on disk structures and constants,
copied from include/linux/raid/md_p.h. */
#define SB_MAGIC 0xa92b4efc
/*
* The version-1 superblock :
* All numeric fields are little-endian.
*
* Total size: 256 bytes plus 2 per device.
* 1K allows 384 devices.
*/
struct grub_raid_super_1x
{
/* Constant array information - 128 bytes. */
grub_uint32_t magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian. */
grub_uint32_t major_version; /* 1. */
grub_uint32_t feature_map; /* Bit 0 set if 'bitmap_offset' is meaningful. */
grub_uint32_t pad0; /* Always set to 0 when writing. */
grub_uint8_t set_uuid[16]; /* User-space generated. */
char set_name[32]; /* Set and interpreted by user-space. */
grub_uint64_t ctime; /* Lo 40 bits are seconds, top 24 are microseconds or 0. */
grub_uint32_t level; /* -4 (multipath), -1 (linear), 0,1,4,5. */
grub_uint32_t layout; /* only for raid5 and raid10 currently. */
grub_uint64_t size; /* Used size of component devices, in 512byte sectors. */
grub_uint32_t chunksize; /* In 512byte sectors. */
grub_uint32_t raid_disks;
grub_uint32_t bitmap_offset; /* Sectors after start of superblock that bitmap starts
* NOTE: signed, so bitmap can be before superblock
* only meaningful of feature_map[0] is set.
*/
/* These are only valid with feature bit '4'. */
grub_uint32_t new_level; /* New level we are reshaping to. */
grub_uint64_t reshape_position; /* Next address in array-space for reshape. */
grub_uint32_t delta_disks; /* Change in number of raid_disks. */
grub_uint32_t new_layout; /* New layout. */
grub_uint32_t new_chunk; /* New chunk size (512byte sectors). */
grub_uint8_t pad1[128 - 124]; /* Set to 0 when written. */
/* Constant this-device information - 64 bytes. */
grub_uint64_t data_offset; /* Sector start of data, often 0. */
grub_uint64_t data_size; /* Sectors in this device that can be used for data. */
grub_uint64_t super_offset; /* Sector start of this superblock. */
grub_uint64_t recovery_offset; /* Sectors before this offset (from data_offset) have been recovered. */
grub_uint32_t dev_number; /* Permanent identifier of this device - not role in raid. */
grub_uint32_t cnt_corrected_read; /* Number of read errors that were corrected by re-writing. */
grub_uint8_t device_uuid[16]; /* User-space setable, ignored by kernel. */
grub_uint8_t devflags; /* Per-device flags. Only one defined... */
grub_uint8_t pad2[64 - 57]; /* Set to 0 when writing. */
/* Array state information - 64 bytes. */
grub_uint64_t utime; /* 40 bits second, 24 btes microseconds. */
grub_uint64_t events; /* Incremented when superblock updated. */
grub_uint64_t resync_offset; /* Data before this offset (from data_offset) known to be in sync. */
grub_uint32_t sb_csum; /* Checksum upto devs[max_dev]. */
grub_uint32_t max_dev; /* Size of devs[] array to consider. */
grub_uint8_t pad3[64 - 32]; /* Set to 0 when writing. */
/* Device state information. Indexed by dev_number.
* 2 bytes per device.
* Note there are no per-device state flags. State information is rolled
* into the 'roles' value. If a device is spare or faulty, then it doesn't
* have a meaningful role.
*/
grub_uint16_t dev_roles[0]; /* Role in array, or 0xffff for a spare, or 0xfffe for faulty. */
};
/* Could be __attribute__ ((packed)), but since all members in this struct
are already appropriately aligned, we can omit this and avoid suboptimal
assembly in some cases. */
#define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */
static grub_err_t
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{
grub_disk_addr_t sector;
grub_uint64_t size;
struct grub_raid_super_1x sb;
grub_uint8_t minor_version;
/* The sector where the mdraid 0.90 superblock is stored, if available. */
size = grub_disk_get_size (disk);
/* Check for an 1.x superblock.
* It's always aligned to a 4K boundary
* and depending on the minor version it can be:
* 0: At least 8K, but less than 12K, from end of device
* 1: At start of device
* 2: 4K from start of device.
*/
for (minor_version = 0; minor_version < 3; ++minor_version)
{
switch (minor_version)
{
case 0:
sector = (size - 8 * 2) & ~(4 * 2 - 1);
break;
case 1:
sector = 0;
break;
case 2:
sector = 4 * 2;
break;
}
if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x),
&sb))
return grub_errno;
if (sb.magic != SB_MAGIC)
continue;
{
grub_uint64_t sb_size;
struct grub_raid_super_1x *real_sb;
if (sb.major_version != 1)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID version: %d",
sb.major_version);
/* Multipath. */
if ((int) sb.level == -4)
sb.level = 1;
if (sb.level != 0 && sb.level != 1 && sb.level != 4 &&
sb.level != 5 && sb.level != 6 && sb.level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID level: %d", sb.level);
/* 1.x superblocks don't have a fixed size on disk. So we have to
read it again now that we now the max device count. */
sb_size = sizeof (struct grub_raid_super_1x)
+ 2 * grub_le_to_cpu32 (sb.max_dev);
real_sb = grub_malloc (sb_size);
if (! real_sb)
return grub_errno;
if (grub_disk_read (disk, sector, 0, sb_size, real_sb))
{
grub_free (real_sb);
return grub_errno;
}
array->name = grub_strdup (real_sb->set_name);
if (! array->name)
{
grub_free (real_sb);
return grub_errno;
}
array->number = 0;
array->level = grub_le_to_cpu32 (real_sb->level);
array->layout = grub_le_to_cpu32 (real_sb->layout);
array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks);
array->disk_size = grub_le_to_cpu64 (real_sb->size);
array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);
if (grub_le_to_cpu32 (real_sb->dev_number) <
grub_le_to_cpu32 (real_sb->max_dev))
array->index = grub_le_to_cpu16
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
else
array->index = 0xffff; /* disk will be later not used! */
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)
{
grub_free (real_sb);
return grub_errno;
}
grub_memcpy (array->uuid, real_sb->set_uuid, 16);
*start_sector = real_sb->data_offset;
grub_free (real_sb);
return 0;
}
}
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 1.x raid");
}
static struct grub_raid grub_mdraid_dev = {
.name = "mdraid1x",
.detect = grub_mdraid_detect,
.next = 0
};
GRUB_MOD_INIT (mdraid1x)
{
grub_raid_register (&grub_mdraid_dev);
}
GRUB_MOD_FINI (mdraid1x)
{
grub_raid_unregister (&grub_mdraid_dev);
}

View file

@ -159,266 +159,78 @@ struct grub_raid_super_09
struct grub_raid_disk_09 this_disk;
} __attribute__ ((packed));
/*
* The version-1 superblock :
* All numeric fields are little-endian.
*
* Total size: 256 bytes plus 2 per device.
* 1K allows 384 devices.
*/
struct grub_raid_super_1x
{
/* Constant array information - 128 bytes. */
grub_uint32_t magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian. */
grub_uint32_t major_version; /* 1. */
grub_uint32_t feature_map; /* Bit 0 set if 'bitmap_offset' is meaningful. */
grub_uint32_t pad0; /* Always set to 0 when writing. */
grub_uint8_t set_uuid[16]; /* User-space generated. */
char set_name[32]; /* Set and interpreted by user-space. */
grub_uint64_t ctime; /* Lo 40 bits are seconds, top 24 are microseconds or 0. */
grub_uint32_t level; /* -4 (multipath), -1 (linear), 0,1,4,5. */
grub_uint32_t layout; /* only for raid5 and raid10 currently. */
grub_uint64_t size; /* Used size of component devices, in 512byte sectors. */
grub_uint32_t chunksize; /* In 512byte sectors. */
grub_uint32_t raid_disks;
grub_uint32_t bitmap_offset; /* Sectors after start of superblock that bitmap starts
* NOTE: signed, so bitmap can be before superblock
* only meaningful of feature_map[0] is set.
*/
/* These are only valid with feature bit '4'. */
grub_uint32_t new_level; /* New level we are reshaping to. */
grub_uint64_t reshape_position; /* Next address in array-space for reshape. */
grub_uint32_t delta_disks; /* Change in number of raid_disks. */
grub_uint32_t new_layout; /* New layout. */
grub_uint32_t new_chunk; /* New chunk size (512byte sectors). */
grub_uint8_t pad1[128 - 124]; /* Set to 0 when written. */
/* Constant this-device information - 64 bytes. */
grub_uint64_t data_offset; /* Sector start of data, often 0. */
grub_uint64_t data_size; /* Sectors in this device that can be used for data. */
grub_uint64_t super_offset; /* Sector start of this superblock. */
grub_uint64_t recovery_offset; /* Sectors before this offset (from data_offset) have been recovered. */
grub_uint32_t dev_number; /* Permanent identifier of this device - not role in raid. */
grub_uint32_t cnt_corrected_read; /* Number of read errors that were corrected by re-writing. */
grub_uint8_t device_uuid[16]; /* User-space setable, ignored by kernel. */
grub_uint8_t devflags; /* Per-device flags. Only one defined... */
grub_uint8_t pad2[64 - 57]; /* Set to 0 when writing. */
/* Array state information - 64 bytes. */
grub_uint64_t utime; /* 40 bits second, 24 btes microseconds. */
grub_uint64_t events; /* Incremented when superblock updated. */
grub_uint64_t resync_offset; /* Data before this offset (from data_offset) known to be in sync. */
grub_uint32_t sb_csum; /* Checksum upto devs[max_dev]. */
grub_uint32_t max_dev; /* Size of devs[] array to consider. */
grub_uint8_t pad3[64 - 32]; /* Set to 0 when writing. */
/* Device state information. Indexed by dev_number.
* 2 bytes per device.
* Note there are no per-device state flags. State information is rolled
* into the 'roles' value. If a device is spare or faulty, then it doesn't
* have a meaningful role.
*/
grub_uint16_t dev_roles[0]; /* Role in array, or 0xffff for a spare, or 0xfffe for faulty. */
};
/* Could be __attribute__ ((packed)), but since all members in this struct
are already appropriately aligned, we can omit this and avoid suboptimal
assembly in some cases. */
#define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */
static grub_err_t
grub_mdraid_detect_09 (grub_disk_addr_t sector,
struct grub_raid_super_09 *sb,
struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{
grub_uint32_t *uuid;
if (sb->major_version != 0 || sb->minor_version != 90)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID version: %d.%d",
sb->major_version, sb->minor_version);
/* FIXME: Check the checksum. */
/* Multipath. */
if ((int) sb->level == -4)
sb->level = 1;
if (sb->level != 0 && sb->level != 1 && sb->level != 4 &&
sb->level != 5 && sb->level != 6 && sb->level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID level: %d", sb->level);
array->name = NULL;
array->number = sb->md_minor;
array->level = sb->level;
array->layout = sb->layout;
array->total_devs = sb->raid_disks;
array->disk_size = (sb->size) ? sb->size * 2 : sector;
array->chunk_size = sb->chunk_size >> 9;
array->index = sb->this_disk.number;
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)
return grub_errno;
uuid = (grub_uint32_t *) array->uuid;
uuid[0] = sb->set_uuid0;
uuid[1] = sb->set_uuid1;
uuid[2] = sb->set_uuid2;
uuid[3] = sb->set_uuid3;
*start_sector = 0;
return 0;
}
static grub_err_t
grub_mdraid_detect_1x (grub_disk_t disk, grub_disk_addr_t sector,
struct grub_raid_super_1x *sb,
struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{
grub_uint64_t sb_size;
struct grub_raid_super_1x *real_sb;
if (sb->major_version != 1)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID version: %d",
sb->major_version);
/* Multipath. */
if ((int) sb->level == -4)
sb->level = 1;
if (sb->level != 0 && sb->level != 1 && sb->level != 4 &&
sb->level != 5 && sb->level != 6 && sb->level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID level: %d", sb->level);
/* 1.x superblocks don't have a fixed size on disk. So we have to
read it again now that we now the max device count. */
sb_size = sizeof (struct grub_raid_super_1x) + 2 * grub_le_to_cpu32 (sb->max_dev);
real_sb = grub_malloc (sb_size);
if (! real_sb)
return grub_errno;
if (grub_disk_read (disk, sector, 0, sb_size, real_sb))
{
grub_free (real_sb);
return grub_errno;
}
array->name = grub_strdup (real_sb->set_name);
if (! array->name)
{
grub_free (real_sb);
return grub_errno;
}
array->number = 0;
array->level = grub_le_to_cpu32 (real_sb->level);
array->layout = grub_le_to_cpu32 (real_sb->layout);
array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks);
array->disk_size = grub_le_to_cpu64 (real_sb->size);
array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);
if (grub_le_to_cpu32 (real_sb->dev_number) <
grub_le_to_cpu32 (real_sb->max_dev))
array->index = grub_le_to_cpu16
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
else
array->index = 0xffff; /* disk will be later not used! */
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)
{
grub_free (real_sb);
return grub_errno;
}
grub_memcpy (array->uuid, real_sb->set_uuid, 16);
*start_sector = real_sb->data_offset;
grub_free (real_sb);
return 0;
}
static grub_err_t
grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_disk_addr_t *start_sector)
{
grub_disk_addr_t sector;
grub_uint64_t size;
struct grub_raid_super_09 sb_09;
struct grub_raid_super_1x sb_1x;
grub_uint8_t minor_version;
struct grub_raid_super_09 sb;
grub_uint32_t *uuid;
/* The sector where the mdraid 0.90 superblock is stored, if available. */
size = grub_disk_get_size (disk);
sector = NEW_SIZE_SECTORS (size);
if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb_09))
if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb))
return grub_errno;
/* Look whether there is a mdraid 0.90 superblock. */
if (sb_09.md_magic == SB_MAGIC)
return grub_mdraid_detect_09 (sector, &sb_09, array, start_sector);
if (sb.md_magic != SB_MAGIC)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid");
/* Check for an 1.x superblock.
* It's always aligned to a 4K boundary
* and depending on the minor version it can be:
* 0: At least 8K, but less than 12K, from end of device
* 1: At start of device
* 2: 4K from start of device.
*/
if (sb.major_version != 0 || sb.minor_version != 90)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID version: %d.%d",
sb.major_version, sb.minor_version);
for (minor_version = 0; minor_version < 3; ++minor_version)
{
switch (minor_version)
{
case 0:
sector = (size - 8 * 2) & ~(4 * 2 - 1);
break;
case 1:
sector = 0;
break;
case 2:
sector = 4 * 2;
break;
}
/* FIXME: Check the checksum. */
if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x),
&sb_1x))
return grub_errno;
/* Multipath. */
if ((int) sb.level == -4)
sb.level = 1;
if (sb_1x.magic == SB_MAGIC)
return grub_mdraid_detect_1x (disk, sector, &sb_1x, array,
start_sector);
}
if (sb.level != 0 && sb.level != 1 && sb.level != 4 &&
sb.level != 5 && sb.level != 6 && sb.level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID level: %d", sb.level);
/* Neither 0.90 nor 1.x. */
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid");
array->name = NULL;
array->number = sb.md_minor;
array->level = sb.level;
array->layout = sb.layout;
array->total_devs = sb.raid_disks;
array->disk_size = (sb.size) ? sb.size * 2 : sector;
array->chunk_size = sb.chunk_size >> 9;
array->index = sb.this_disk.number;
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)
return grub_errno;
uuid = (grub_uint32_t *) array->uuid;
uuid[0] = sb.set_uuid0;
uuid[1] = sb.set_uuid1;
uuid[2] = sb.set_uuid2;
uuid[3] = sb.set_uuid3;
*start_sector = 0;
return 0;
}
static struct grub_raid grub_mdraid_dev = {
.name = "mdraid",
.name = "mdraid09",
.detect = grub_mdraid_detect,
.next = 0
};
GRUB_MOD_INIT (mdraid)
GRUB_MOD_INIT (mdraid09)
{
grub_raid_register (&grub_mdraid_dev);
}
GRUB_MOD_FINI (mdraid)
GRUB_MOD_FINI (mdraid09)
{
grub_raid_unregister (&grub_mdraid_dev);
}

View file

@ -41,7 +41,6 @@ grub_memdisk_open (const char *name, grub_disk_t disk)
disk->total_sectors = memdisk_size / GRUB_DISK_SECTOR_SIZE;
disk->id = (unsigned long) "mdsk";
disk->has_partitions = 0;
return GRUB_ERR_NONE;
}

View file

@ -126,7 +126,6 @@ grub_raid_open (const char *name, grub_disk_t disk)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s",
name);
disk->has_partitions = 1;
disk->id = array->number;
disk->data = array;

View file

@ -431,12 +431,6 @@ grub_scsi_open (const char *name, grub_disk_t disk)
"unknown SCSI device");
}
if (scsi->devtype == grub_scsi_devtype_cdrom)
disk->has_partitions = 0;
else
disk->has_partitions = 1;
/* According to USB MS tests specification, issue Test Unit Ready
* until OK */
maxtime = grub_get_time_ms () + 5000; /* It is safer value */

View file

@ -29,8 +29,8 @@
#include <grub/normal.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/machine/memory.h>
#include <grub/efiemu/efiemu.h>
#include <grub/memory.h>
struct grub_efiemu_memrequest
{
@ -269,10 +269,11 @@ static grub_err_t
grub_efiemu_mmap_init (void)
{
auto int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t, grub_uint64_t,
grub_uint32_t);
grub_memory_type_t);
int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t addr __attribute__ ((unused)),
grub_uint64_t size __attribute__ ((unused)),
grub_uint32_t type __attribute__ ((unused)))
grub_memory_type_t type
__attribute__ ((unused)))
{
mmap_reserved_size++;
return 0;
@ -382,32 +383,29 @@ grub_efiemu_mm_init (void)
static grub_err_t
grub_efiemu_mmap_fill (void)
{
auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t);
auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t,
grub_memory_type_t);
int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr,
grub_uint64_t size,
grub_uint32_t type)
grub_memory_type_t type)
{
switch (type)
{
case GRUB_MACHINE_MEMORY_AVAILABLE:
case GRUB_MEMORY_AVAILABLE:
return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_CONVENTIONAL_MEMORY);
#ifdef GRUB_MACHINE_MEMORY_ACPI
case GRUB_MACHINE_MEMORY_ACPI:
case GRUB_MEMORY_ACPI:
return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_ACPI_RECLAIM_MEMORY);
#endif
#ifdef GRUB_MACHINE_MEMORY_NVS
case GRUB_MACHINE_MEMORY_NVS:
case GRUB_MEMORY_NVS:
return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_ACPI_MEMORY_NVS);
#endif
default:
grub_printf ("Unknown memory type %d. Marking as unusable\n", type);
case GRUB_MACHINE_MEMORY_RESERVED:
grub_printf ("Unknown memory type %d. Assuming unusable\n", type);
case GRUB_MEMORY_RESERVED:
return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_UNUSABLE_MEMORY);
}
@ -421,9 +419,7 @@ grub_efiemu_mmap_fill (void)
}
grub_err_t
grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t,
grub_uint64_t,
grub_uint32_t))
grub_efiemu_mmap_iterate (grub_memory_hook_t hook)
{
unsigned i;
@ -432,18 +428,22 @@ grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t,
{
case GRUB_EFI_RUNTIME_SERVICES_CODE:
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
GRUB_EFIEMU_MEMORY_CODE);
GRUB_MEMORY_CODE);
break;
case GRUB_EFI_UNUSABLE_MEMORY:
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
GRUB_MEMORY_BADRAM);
break;
case GRUB_EFI_RESERVED_MEMORY_TYPE:
case GRUB_EFI_RUNTIME_SERVICES_DATA:
case GRUB_EFI_UNUSABLE_MEMORY:
case GRUB_EFI_MEMORY_MAPPED_IO:
case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:
case GRUB_EFI_PAL_CODE:
case GRUB_EFI_MAX_MEMORY_TYPE:
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
GRUB_EFIEMU_MEMORY_RESERVED);
GRUB_MEMORY_RESERVED);
break;
case GRUB_EFI_LOADER_CODE:
@ -452,17 +452,17 @@ grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t,
case GRUB_EFI_BOOT_SERVICES_DATA:
case GRUB_EFI_CONVENTIONAL_MEMORY:
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
GRUB_EFIEMU_MEMORY_AVAILABLE);
GRUB_MEMORY_AVAILABLE);
break;
case GRUB_EFI_ACPI_RECLAIM_MEMORY:
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
GRUB_EFIEMU_MEMORY_ACPI);
GRUB_MEMORY_ACPI);
break;
case GRUB_EFI_ACPI_MEMORY_NVS:
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
GRUB_EFIEMU_MEMORY_NVS);
GRUB_MEMORY_NVS);
break;
}

View file

@ -20,9 +20,9 @@
#include <grub/err.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/types.h>
#include <grub/efiemu/efiemu.h>
#include <grub/lib/crc.h>
#include <grub/crypto.h>
grub_err_t
SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks,
@ -123,6 +123,7 @@ SUFFIX (grub_efiemu_crc) (void)
int handle;
grub_off_t off;
struct SUFFIX (grub_efiemu_runtime_services) *runtime_services;
grub_uint8_t crc32_context[GRUB_MD_CRC32->contextsize];
/* compute CRC32 of runtime_services */
err = grub_efiemu_resolve_symbol ("efiemu_runtime_services",
@ -132,19 +133,25 @@ SUFFIX (grub_efiemu_crc) (void)
runtime_services = (struct SUFFIX (grub_efiemu_runtime_services) *)
((grub_uint8_t *) grub_efiemu_mm_obtain_request (handle) + off);
runtime_services->hdr.crc32 = 0;
runtime_services->hdr.crc32 = grub_getcrc32
(0, runtime_services, runtime_services->hdr.header_size);
GRUB_MD_CRC32->init(crc32_context);
GRUB_MD_CRC32->write(crc32_context, runtime_services, runtime_services->hdr.header_size);
GRUB_MD_CRC32->final(crc32_context);
runtime_services->hdr.crc32 =
grub_be_to_cpu32(*(grub_uint32_t*)GRUB_MD_CRC32->read(crc32_context));
err = grub_efiemu_resolve_symbol ("efiemu_system_table", &handle, &off);
if (err)
return err;
/* compute CRC32 of system table */
SUFFIX (grub_efiemu_system_table)->hdr.crc32 = 0;
SUFFIX (grub_efiemu_system_table)->hdr.crc32
= grub_getcrc32 (0, SUFFIX (grub_efiemu_system_table),
SUFFIX (grub_efiemu_system_table)->hdr.header_size);
GRUB_MD_CRC32->init(crc32_context);
GRUB_MD_CRC32->write(crc32_context, SUFFIX (grub_efiemu_system_table),
SUFFIX (grub_efiemu_system_table)->hdr.header_size);
GRUB_MD_CRC32->final(crc32_context);
SUFFIX (grub_efiemu_system_table)->hdr.crc32 =
grub_be_to_cpu32(*(grub_uint32_t*)GRUB_MD_CRC32->read(crc32_context));
grub_dprintf ("efiemu","system_table = %p, runtime_services = %p\n",
SUFFIX (grub_efiemu_system_table), runtime_services);

132
grub-core/fs/btrfs.c Normal file
View file

@ -0,0 +1,132 @@
/* btrfs.c - B-tree file system. */
/*
* 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/err.h>
#include <grub/file.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/disk.h>
#include <grub/dl.h>
#include <grub/types.h>
#define BTRFS_SIGNATURE "_BHRfS_M"
struct btrfs_superblock
{
grub_uint8_t dummy1[32];
grub_uint16_t uuid[8];
grub_uint8_t dummy2[16];
grub_uint8_t signature[sizeof (BTRFS_SIGNATURE) - 1];
} __attribute__ ((packed));
struct grub_btrfs_data
{
struct btrfs_superblock sblock;
};
static struct grub_btrfs_data *
grub_btrfs_mount (grub_disk_t disk)
{
struct grub_btrfs_data *data = grub_malloc (sizeof (*data));
if (! data)
return NULL;
if (grub_disk_read (disk, 128, 0, sizeof (data->sblock),
&data->sblock) != GRUB_ERR_NONE)
goto fail;
if (grub_strncmp ((char *) data->sblock.signature, BTRFS_SIGNATURE, sizeof (BTRFS_SIGNATURE) - 1))
{
grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem");
goto fail;
}
return data;
fail:
grub_free (data);
return NULL;
}
static grub_err_t
grub_btrfs_open (struct grub_file *file __attribute__ ((unused)),
const char *name __attribute__ ((unused)))
{
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "only detection is supported for Btrfs");
}
static grub_err_t
grub_btrfs_dir (grub_device_t device,
const char *path __attribute__ ((unused)),
int (*hook) (const char *filename,
const struct grub_dirhook_info *info)
__attribute__ ((unused)))
{
struct grub_btrfs_data *data = grub_btrfs_mount (device->disk);
if (grub_errno)
return grub_errno;
grub_free (data);
return GRUB_ERR_NONE;
}
static grub_err_t
grub_btrfs_uuid (grub_device_t device, char **uuid)
{
struct grub_btrfs_data *data;
*uuid = NULL;
data = grub_btrfs_mount (device->disk);
if (! data)
return grub_errno;
*uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
grub_be_to_cpu16 (data->sblock.uuid[0]),
grub_be_to_cpu16 (data->sblock.uuid[1]),
grub_be_to_cpu16 (data->sblock.uuid[2]),
grub_be_to_cpu16 (data->sblock.uuid[3]),
grub_be_to_cpu16 (data->sblock.uuid[4]),
grub_be_to_cpu16 (data->sblock.uuid[5]),
grub_be_to_cpu16 (data->sblock.uuid[6]),
grub_be_to_cpu16 (data->sblock.uuid[7]));
grub_free (data);
return grub_errno;
}
static struct grub_fs grub_btrfs_fs =
{
.name = "btrfs",
.dir = grub_btrfs_dir,
.open = grub_btrfs_open,
.uuid = grub_btrfs_uuid,
};
GRUB_MOD_INIT(btrfs)
{
grub_fs_register (&grub_btrfs_fs);
}
GRUB_MOD_FINI(btrfs)
{
grub_fs_unregister (&grub_btrfs_fs);
}

View file

@ -728,22 +728,27 @@ grub_ext2_open (struct grub_file *file, const char *name)
{
struct grub_ext2_data *data;
struct grub_fshelp_node *fdiro = 0;
grub_err_t err;
grub_dl_ref (my_mod);
data = grub_ext2_mount (file->device->disk);
if (! data)
goto fail;
{
err = grub_errno;
goto fail;
}
grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_ext2_iterate_dir,
grub_ext2_read_symlink, GRUB_FSHELP_REG);
if (grub_errno)
err = grub_fshelp_find_file (name, &data->diropen, &fdiro,
grub_ext2_iterate_dir,
grub_ext2_read_symlink, GRUB_FSHELP_REG);
if (err)
goto fail;
if (! fdiro->inode_read)
{
grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode);
if (grub_errno)
err = grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode);
if (err)
goto fail;
}
@ -763,7 +768,7 @@ grub_ext2_open (struct grub_file *file, const char *name)
grub_dl_unref (my_mod);
return grub_errno;
return err;
}
static grub_err_t

View file

@ -25,10 +25,13 @@
#include <grub/dl.h>
#include <grub/types.h>
#ifdef MODE_MINIX2
#define GRUB_MINIX_MAGIC 0x2468
#define GRUB_MINIX_MAGIC_30 0x2478
#else
#define GRUB_MINIX_MAGIC 0x137F
#define GRUB_MINIX2_MAGIC 0x2468
#define GRUB_MINIX_MAGIC_30 0x138F
#define GRUB_MINIX2_MAGIC_30 0x2478
#endif
#define GRUB_MINIX_BSIZE 1024U
#define GRUB_MINIX_LOG2_BSIZE 1
#define GRUB_MINIX_ROOT_INODE 1
@ -38,20 +41,25 @@
#define GRUB_MINIX_IFDIR 0040000U
#define GRUB_MINIX_IFLNK 0120000U
#define GRUB_MINIX_INODE(data,field) (data->version == 1 ? \
data->inode. field : data->inode2. field)
#define GRUB_MINIX_INODE_ENDIAN(data,field,bits1,bits2) (data->version == 1 ? \
grub_le_to_cpu##bits1 (data->inode.field) : \
grub_le_to_cpu##bits2 (data->inode2.field))
#define GRUB_MINIX_INODE_SIZE(data) GRUB_MINIX_INODE_ENDIAN (data,size,16,32)
#define GRUB_MINIX_INODE_MODE(data) GRUB_MINIX_INODE_ENDIAN (data,mode,16,16)
#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) GRUB_MINIX_INODE_ENDIAN \
(data,dir_zones[blk],16,32)
#define GRUB_MINIX_INODE_INDIR_ZONE(data) \
GRUB_MINIX_INODE_ENDIAN (data,indir_zone,16,32)
#define GRUB_MINIX_INODE_DINDIR_ZONE(data) \
GRUB_MINIX_INODE_ENDIAN (data,double_indir_zone,16,32)
#define GRUB_MINIX_INODE_BLKSZ(data) (data->version == 1 ? 2 : 4)
#ifdef MODE_MINIX2
typedef grub_uint32_t grub_minix_uintn_t;
#define grub_minix_le_to_cpu_n grub_le_to_cpu32
#else
typedef grub_uint16_t grub_minix_uintn_t;
#define grub_minix_le_to_cpu_n grub_le_to_cpu16
#endif
#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t)
#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size))
#define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode))
#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) (grub_minix_le_to_cpu_n \
(data->inode.dir_zones[blk]))
#define GRUB_MINIX_INODE_INDIR_ZONE(data) (grub_minix_le_to_cpu_n \
(data->inode.indir_zone))
#define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \
(data->inode.double_indir_zone))
#define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \
+ grub_le_to_cpu16 (sblock->log2_zone_size))
#define GRUB_MINIX_ZONESZ (GRUB_MINIX_BSIZE \
@ -69,6 +77,7 @@ struct grub_minix_sblock
grub_uint16_t magic;
};
#ifndef MODE_MINIX2
struct grub_minix_inode
{
grub_uint16_t mode;
@ -82,7 +91,9 @@ struct grub_minix_inode
grub_uint16_t double_indir_zone;
};
struct grub_minix2_inode
#else
struct grub_minix_inode
{
grub_uint16_t mode;
grub_uint16_t nlinks;
@ -99,16 +110,16 @@ struct grub_minix2_inode
};
#endif
/* Information about a "mounted" minix filesystem. */
struct grub_minix_data
{
struct grub_minix_sblock sblock;
struct grub_minix_inode inode;
struct grub_minix2_inode inode2;
int ino;
int linknest;
grub_disk_t disk;
int version;
int filename_size;
};
@ -128,24 +139,12 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk)
/* Read the block pointer in ZONE, on the offset NUM. */
int grub_get_indir (int zone, int num)
{
if (data->version == 1)
{
grub_uint16_t indir16;
grub_disk_read (data->disk,
zone << GRUB_MINIX_LOG2_ZONESZ,
sizeof (grub_uint16_t) * num,
sizeof (grub_uint16_t), (char *) &indir16);
return grub_le_to_cpu16 (indir16);
}
else
{
grub_uint32_t indir32;
grub_disk_read (data->disk,
zone << GRUB_MINIX_LOG2_ZONESZ,
sizeof (grub_uint32_t) * num,
sizeof (grub_uint32_t), (char *) &indir32);
return grub_le_to_cpu32 (indir32);
}
grub_minix_uintn_t indirn;
grub_disk_read (data->disk,
zone << GRUB_MINIX_LOG2_ZONESZ,
sizeof (grub_minix_uintn_t) * num,
sizeof (grub_minix_uintn_t), (char *) &indirn);
return grub_minix_le_to_cpu_n (indirn);
}
/* Direct block. */
@ -259,27 +258,13 @@ grub_minix_read_inode (struct grub_minix_data *data, int ino)
+ grub_le_to_cpu16 (sblock->zone_bmap_size))
<< GRUB_MINIX_LOG2_BSIZE);
if (data->version == 1)
{
block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
int offs = (ino % (GRUB_DISK_SECTOR_SIZE
/ sizeof (struct grub_minix_inode))
* sizeof (struct grub_minix_inode));
grub_disk_read (data->disk, block, offs,
sizeof (struct grub_minix_inode), &data->inode);
}
else
{
block += ino / (GRUB_DISK_SECTOR_SIZE
/ sizeof (struct grub_minix2_inode));
int offs = (ino
% (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix2_inode))
* sizeof (struct grub_minix2_inode));
grub_disk_read (data->disk, block, offs,
sizeof (struct grub_minix2_inode),&data->inode2);
}
block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode));
int offs = (ino % (GRUB_DISK_SECTOR_SIZE
/ sizeof (struct grub_minix_inode))
* sizeof (struct grub_minix_inode));
grub_disk_read (data->disk, block, offs,
sizeof (struct grub_minix_inode), &data->inode);
return GRUB_ERR_NONE;
}
@ -424,25 +409,9 @@ grub_minix_mount (grub_disk_t disk)
goto fail;
if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC)
{
data->version = 1;
data->filename_size = 14;
}
else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX2_MAGIC)
{
data->version = 2;
data->filename_size = 14;
}
data->filename_size = 14;
else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30)
{
data->version = 1;
data->filename_size = 30;
}
else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX2_MAGIC_30)
{
data->version = 2;
data->filename_size = 30;
}
data->filename_size = 30;
else
goto fail;
@ -453,7 +422,11 @@ grub_minix_mount (grub_disk_t disk)
fail:
grub_free (data);
#ifdef MODE_MINIX2
grub_error (GRUB_ERR_BAD_FS, "not a minix2 filesystem");
#else
grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem");
#endif
return 0;
}
@ -583,32 +556,36 @@ grub_minix_close (grub_file_t file)
}
static grub_err_t
grub_minix_label (grub_device_t device __attribute ((unused)),
char **label __attribute ((unused)))
{
return GRUB_ERR_NONE;
}
static struct grub_fs grub_minix_fs =
{
#ifdef MODE_MINIX2
.name = "minix2",
#else
.name = "minix",
#endif
.dir = grub_minix_dir,
.open = grub_minix_open,
.read = grub_minix_read,
.close = grub_minix_close,
.label = grub_minix_label,
.next = 0
};
#ifdef MODE_MINIX2
GRUB_MOD_INIT(minix2)
#else
GRUB_MOD_INIT(minix)
#endif
{
grub_fs_register (&grub_minix_fs);
my_mod = mod;
}
#ifdef MODE_MINIX2
GRUB_MOD_FINI(minix2)
#else
GRUB_MOD_FINI(minix)
#endif
{
grub_fs_unregister (&grub_minix_fs);
}

2
grub-core/fs/minix2.c Normal file
View file

@ -0,0 +1,2 @@
#define MODE_MINIX2 1
#include "minix.c"

View file

@ -1,22 +0,0 @@
#! /bin/sh
#
# Copyright (C) 2005,2009 Free Software Foundation, Inc.
#
# This gensymlist.sh is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# Read source code from stdin and detect command names.
module=$1
grep -v "^#" | sed -n \
-e "/grub_register_command *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $module/;p;}" \
-e "/grub_register_extcmd *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $module/;p;}" \
-e "/grub_register_command_p1 *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $module/;p;}"

View file

@ -1,26 +0,0 @@
#! /bin/sh
#
# Copyright (C) 2005,2008 Free Software Foundation, Inc.
#
# This gensymlist.sh is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# Read source code from stdin and detect fs names.
module=$1
# Ignore kernel.mod.
if test $module = kernel; then
exit
fi
# For now, this emits only a module name, if the module registers a filesystem.
if grep -v "^#" | grep '^ *grub_fs_register' >/dev/null 2>&1; then
echo $module
fi

View file

@ -1,19 +0,0 @@
#! /bin/sh
#
# Copyright (C) 2009 Free Software Foundation, Inc.
#
# This script is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# Read source code from stdin and detect command names.
module=$1
grep -v "^#" | sed -n \
-e "/grub_parser_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/parser.\1: $module/;p;}"

73
grub-core/genmod.sh.in Normal file
View file

@ -0,0 +1,73 @@
#! /bin/sh -e
#
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# This gensymlist.sh is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
#
# Example:
#
# genmod.sh moddep.lst normal.module normal.mod
#
moddep=$1
infile=$2
outfile=$3
tmpfile=${outfile}.tmp
modname=`echo $infile | sed -e 's@\.module.*$@@'`
if ! grep ^$modname: $moddep >/dev/null; then
echo "warning: moddep.lst has no dependencies for $modname" >&2
exit 0
fi
deps=`grep ^$modname: $moddep | sed s@^.*:@@`
# remove old files if any
rm -f $tmpfile $outfile
# stripout .modname and .moddeps sections from input module
objcopy -R .modname -R .moddeps $infile $tmpfile
# Attach .modname and .moddeps sections
t1=`mktemp`
printf "$modname\0" >$t1
t2=`mktemp`
for dep in $deps; do printf "$dep\0" >> $t2; done
if test -n "$deps"; then
objcopy --add-section .modname=$t1 --add-section .moddeps=$t2 $tmpfile
else
objcopy --add-section .modname=$t1 $tmpfile
fi
rm -f $t1 $t2
if test x@TARGET_APPLE_CC@ != x1; then
if ! test -z "@TARGET_OBJ2ELF@"; then
./@TARGET_OBJ2ELF@ $tmpfile || exit 1
fi
if test x@platform@ != xemu; then
@STRIP@ --strip-unneeded \
-K grub_mod_init -K grub_mod_fini \
-K _grub_mod_init -K _grub_mod_fini \
-R .note -R .comment $tmpfile || exit 1
fi
else
# XXX Test these Apple CC fixes
cp $tmpfile $tmpfile.bin
@OBJCONV@ -f@TARGET_MODULE_FORMAT@ \
-nr:_grub_mod_init:grub_mod_init \
-nr:_grub_mod_fini:grub_mod_fini \
-wd1106 -ew2030 -ew2050 -nu -nd $tmpfile.bin $tmpfile || exit 1
rm -f $name.bin
fi
mv $tmpfile $outfile

View file

@ -11,23 +11,28 @@
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# Read defined symbols from stdin.
# Read symbols' info from stdin.
BEGIN {
error = 0
lineno = 0;
while (getline <"/dev/stdin") {
symtab[$1] = $2
}
}
# The rest is undefined symbols.
{
module = $2
if ($1 in symtab) {
modtab[module] = modtab[module] " " symtab[$1];
}
else if ($1 != "__gnu_local_gp") {
printf "%s in %s is not defined\n", $1, module >"/dev/stderr";
error++;
lineno++;
if ($1 == "defined") {
symtab[$3] = $2;
modtab[$2] = "" modtab[$2]
} else if ($1 == "undefined") {
if ($3 in symtab)
modtab[$2] = modtab[$2] " " symtab[$3];
else if ($3 != "__gnu_local_gp") {
printf "%s in %s is not defined\n", $3, $2 >"/dev/stderr";
error++;
}
}
else {
printf "error: %u: unrecognized input format\n", lineno;
error++;
break;
}
}
}

View file

@ -1,47 +0,0 @@
#! /bin/sh
#
# Copyright (C) 2002,2007 Free Software Foundation, Inc.
#
# This genmodsrc.sh is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
set -e
mod_name="$1"
deps="$2"
cat <<EOF
/* This file is automatically generated by genmodsrc.sh. DO NOT EDIT! */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2007 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>
EOF
echo "GRUB_MOD_NAME(${mod_name});"
for mod in `grep "^${mod_name}:" ${deps} | sed 's/^[^:]*://'`; do
echo "GRUB_MOD_DEP(${mod});"
done

View file

@ -1,26 +0,0 @@
#! /bin/sh
#
# Copyright (C) 2005, 2008 Free Software Foundation, Inc.
#
# This script is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# Read source code from stdin and detect partmap names.
module=$1
# Ignore kernel.mod.
if test $module = kernel; then
exit
fi
# For now, this emits only a module name, if the module registers a partition map.
if grep -v "^#" | grep '^ *grub_partition_map_register' >/dev/null 2>&1; then
echo $module
fi

View file

@ -1,19 +0,0 @@
#! /bin/sh
#
# Copyright (C) 2009 Free Software Foundation, Inc.
#
# This gensymlist.sh is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# Read source code from stdin and detect parttool names.
module=$1
grep -v "^#" | sed -n \
-e "/grub_parttool_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $module/;p;}"

View file

@ -0,0 +1,34 @@
#! /bin/sh -e
#
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# This gensymlist.sh is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
#
# Example:
#
# gensyms.sh normal.module
#
module=$1
modname=`echo $module | sed -e 's@\.module.*$@@'`
# Print all symbols defined by module
if test x@TARGET_APPLE_CC@ = x1; then
@NM@ -g -P -p $module | \
grep -E '^[a-zA-Z0-9_]* [TDS]' | \
sed "s@^\([^ ]*\).*@defined $modname \1@g"
else
@NM@ -g --defined-only -P -p $module | \
sed "s@^\([^ ]*\).*@defined $modname \1@g"
fi
# Print all undefined symbols used by module
@NM@ -u -P -p $module | sed "s@^\([^ ]*\).*@undefined $modname \1@g"

View file

@ -1,20 +0,0 @@
#! /bin/sh
#
# Copyright (C) 2009,2010 Free Software Foundation, Inc.
#
# This script is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# Read source code from stdin and detect command names.
module=$1
grep -v "^#" | sed -n \
-e "/grub_term_register_input *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $module/;p;}" \
-e "/grub_term_register_output *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $module/;p;}" \

View file

@ -1,26 +0,0 @@
#! /bin/sh
#
# Copyright (C) 2005,2008,2009 Free Software Foundation, Inc.
#
# This script is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# Read source code from stdin and detect partmap names.
module=$1
# Ignore video.mod.
if test $module = video; then
exit
fi
# For now, this emits only a module name, if the module registers a partition map.
if grep -v "^#" | grep '^ *grub_video_register' >/dev/null 2>&1; then
echo $module
fi

View file

@ -26,7 +26,6 @@
#include <grub/normal.h>
#include <grub/file.h>
#include <grub/kernel.h>
#include <grub/gzio.h>
#include <grub/i18n.h>
/*
@ -219,7 +218,7 @@ grub_gettext_translate (const char *orig)
return ret;
}
/* This is similar to grub_gzfile_open. */
/* This is similar to grub_file_open. */
static grub_file_t
grub_mofile_open (const char *filename)
{
@ -229,7 +228,7 @@ grub_mofile_open (const char *filename)
/* Using fd_mo and not another variable because
it's needed for grub_gettext_get_info. */
fd_mo = grub_gzfile_open (filename, 1);
fd_mo = grub_file_open (filename);
grub_errno = GRUB_ERR_NONE;
if (!fd_mo)

1359
grub-core/gnulib/Makefile.am Normal file

File diff suppressed because it is too large Load diff

489
grub-core/gnulib/alloca.c Normal file
View file

@ -0,0 +1,489 @@
/* alloca.c -- allocate automatically reclaimed memory
(Mostly) portable public-domain implementation -- D A Gwyn
This implementation of the PWB library alloca function,
which is used to allocate space off the run-time stack so
that it is automatically reclaimed upon procedure exit,
was inspired by discussions with J. Q. Johnson of Cornell.
J.Otto Tennant <jot@cray.com> contributed the Cray support.
There are some preprocessor constants that can
be defined when compiling for your specific system, for
improved efficiency; however, the defaults should be okay.
The general concept of this implementation is to keep
track of all alloca-allocated blocks, and reclaim any
that are found to be deeper in the stack than the current
invocation. This heuristic does not reclaim storage as
soon as it becomes invalid, but it will do so eventually.
As a special case, alloca(0) reclaims storage without
allocating any. It is a good idea to use alloca(0) in
your main control loop, etc. to force garbage collection. */
#include <config.h>
#include <alloca.h>
#include <string.h>
#include <stdlib.h>
#ifdef emacs
# include "lisp.h"
# include "blockinput.h"
# ifdef EMACS_FREE
# undef free
# define free EMACS_FREE
# endif
#else
# define memory_full() abort ()
#endif
/* If compiling with GCC 2, this file's not needed. */
#if !defined (__GNUC__) || __GNUC__ < 2
/* If someone has defined alloca as a macro,
there must be some other way alloca is supposed to work. */
# ifndef alloca
# ifdef emacs
# ifdef static
/* actually, only want this if static is defined as ""
-- this is for usg, in which emacs must undefine static
in order to make unexec workable
*/
# ifndef STACK_DIRECTION
you
lose
-- must know STACK_DIRECTION at compile-time
/* Using #error here is not wise since this file should work for
old and obscure compilers. */
# endif /* STACK_DIRECTION undefined */
# endif /* static */
# endif /* emacs */
/* If your stack is a linked list of frames, you have to
provide an "address metric" ADDRESS_FUNCTION macro. */
# if defined (CRAY) && defined (CRAY_STACKSEG_END)
long i00afunc ();
# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
# else
# define ADDRESS_FUNCTION(arg) &(arg)
# endif
/* Define STACK_DIRECTION if you know the direction of stack
growth for your system; otherwise it will be automatically
deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
# ifndef STACK_DIRECTION
# define STACK_DIRECTION 0 /* Direction unknown. */
# endif
# if STACK_DIRECTION != 0
# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
# else /* STACK_DIRECTION == 0; need run-time code. */
static int stack_dir; /* 1 or -1 once known. */
# define STACK_DIR stack_dir
static void
find_stack_direction (void)
{
static char *addr = NULL; /* Address of first `dummy', once known. */
auto char dummy; /* To get stack address. */
if (addr == NULL)
{ /* Initial entry. */
addr = ADDRESS_FUNCTION (dummy);
find_stack_direction (); /* Recurse once. */
}
else
{
/* Second entry. */
if (ADDRESS_FUNCTION (dummy) > addr)
stack_dir = 1; /* Stack grew upward. */
else
stack_dir = -1; /* Stack grew downward. */
}
}
# endif /* STACK_DIRECTION == 0 */
/* An "alloca header" is used to:
(a) chain together all alloca'ed blocks;
(b) keep track of stack depth.
It is very important that sizeof(header) agree with malloc
alignment chunk size. The following default should work okay. */
# ifndef ALIGN_SIZE
# define ALIGN_SIZE sizeof(double)
# endif
typedef union hdr
{
char align[ALIGN_SIZE]; /* To force sizeof(header). */
struct
{
union hdr *next; /* For chaining headers. */
char *deep; /* For stack depth measure. */
} h;
} header;
static header *last_alloca_header = NULL; /* -> last alloca header. */
/* Return a pointer to at least SIZE bytes of storage,
which will be automatically reclaimed upon exit from
the procedure that called alloca. Originally, this space
was supposed to be taken from the current stack frame of the
caller, but that method cannot be made to work for some
implementations of C, for example under Gould's UTX/32. */
void *
alloca (size_t size)
{
auto char probe; /* Probes stack depth: */
register char *depth = ADDRESS_FUNCTION (probe);
# if STACK_DIRECTION == 0
if (STACK_DIR == 0) /* Unknown growth direction. */
find_stack_direction ();
# endif
/* Reclaim garbage, defined as all alloca'd storage that
was allocated from deeper in the stack than currently. */
{
register header *hp; /* Traverses linked list. */
# ifdef emacs
BLOCK_INPUT;
# endif
for (hp = last_alloca_header; hp != NULL;)
if ((STACK_DIR > 0 && hp->h.deep > depth)
|| (STACK_DIR < 0 && hp->h.deep < depth))
{
register header *np = hp->h.next;
free (hp); /* Collect garbage. */
hp = np; /* -> next header. */
}
else
break; /* Rest are not deeper. */
last_alloca_header = hp; /* -> last valid storage. */
# ifdef emacs
UNBLOCK_INPUT;
# endif
}
if (size == 0)
return NULL; /* No allocation required. */
/* Allocate combined header + user data storage. */
{
/* Address of header. */
register header *new;
size_t combined_size = sizeof (header) + size;
if (combined_size < sizeof (header))
memory_full ();
new = malloc (combined_size);
if (! new)
memory_full ();
new->h.next = last_alloca_header;
new->h.deep = depth;
last_alloca_header = new;
/* User storage begins just after header. */
return (void *) (new + 1);
}
}
# if defined (CRAY) && defined (CRAY_STACKSEG_END)
# ifdef DEBUG_I00AFUNC
# include <stdio.h>
# endif
# ifndef CRAY_STACK
# define CRAY_STACK
# ifndef CRAY2
/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
struct stack_control_header
{
long shgrow:32; /* Number of times stack has grown. */
long shaseg:32; /* Size of increments to stack. */
long shhwm:32; /* High water mark of stack. */
long shsize:32; /* Current size of stack (all segments). */
};
/* The stack segment linkage control information occurs at
the high-address end of a stack segment. (The stack
grows from low addresses to high addresses.) The initial
part of the stack segment linkage control information is
0200 (octal) words. This provides for register storage
for the routine which overflows the stack. */
struct stack_segment_linkage
{
long ss[0200]; /* 0200 overflow words. */
long sssize:32; /* Number of words in this segment. */
long ssbase:32; /* Offset to stack base. */
long:32;
long sspseg:32; /* Offset to linkage control of previous
segment of stack. */
long:32;
long sstcpt:32; /* Pointer to task common address block. */
long sscsnm; /* Private control structure number for
microtasking. */
long ssusr1; /* Reserved for user. */
long ssusr2; /* Reserved for user. */
long sstpid; /* Process ID for pid based multi-tasking. */
long ssgvup; /* Pointer to multitasking thread giveup. */
long sscray[7]; /* Reserved for Cray Research. */
long ssa0;
long ssa1;
long ssa2;
long ssa3;
long ssa4;
long ssa5;
long ssa6;
long ssa7;
long sss0;
long sss1;
long sss2;
long sss3;
long sss4;
long sss5;
long sss6;
long sss7;
};
# else /* CRAY2 */
/* The following structure defines the vector of words
returned by the STKSTAT library routine. */
struct stk_stat
{
long now; /* Current total stack size. */
long maxc; /* Amount of contiguous space which would
be required to satisfy the maximum
stack demand to date. */
long high_water; /* Stack high-water mark. */
long overflows; /* Number of stack overflow ($STKOFEN) calls. */
long hits; /* Number of internal buffer hits. */
long extends; /* Number of block extensions. */
long stko_mallocs; /* Block allocations by $STKOFEN. */
long underflows; /* Number of stack underflow calls ($STKRETN). */
long stko_free; /* Number of deallocations by $STKRETN. */
long stkm_free; /* Number of deallocations by $STKMRET. */
long segments; /* Current number of stack segments. */
long maxs; /* Maximum number of stack segments so far. */
long pad_size; /* Stack pad size. */
long current_address; /* Current stack segment address. */
long current_size; /* Current stack segment size. This
number is actually corrupted by STKSTAT to
include the fifteen word trailer area. */
long initial_address; /* Address of initial segment. */
long initial_size; /* Size of initial segment. */
};
/* The following structure describes the data structure which trails
any stack segment. I think that the description in 'asdef' is
out of date. I only describe the parts that I am sure about. */
struct stk_trailer
{
long this_address; /* Address of this block. */
long this_size; /* Size of this block (does not include
this trailer). */
long unknown2;
long unknown3;
long link; /* Address of trailer block of previous
segment. */
long unknown5;
long unknown6;
long unknown7;
long unknown8;
long unknown9;
long unknown10;
long unknown11;
long unknown12;
long unknown13;
long unknown14;
};
# endif /* CRAY2 */
# endif /* not CRAY_STACK */
# ifdef CRAY2
/* Determine a "stack measure" for an arbitrary ADDRESS.
I doubt that "lint" will like this much. */
static long
i00afunc (long *address)
{
struct stk_stat status;
struct stk_trailer *trailer;
long *block, size;
long result = 0;
/* We want to iterate through all of the segments. The first
step is to get the stack status structure. We could do this
more quickly and more directly, perhaps, by referencing the
$LM00 common block, but I know that this works. */
STKSTAT (&status);
/* Set up the iteration. */
trailer = (struct stk_trailer *) (status.current_address
+ status.current_size
- 15);
/* There must be at least one stack segment. Therefore it is
a fatal error if "trailer" is null. */
if (trailer == 0)
abort ();
/* Discard segments that do not contain our argument address. */
while (trailer != 0)
{
block = (long *) trailer->this_address;
size = trailer->this_size;
if (block == 0 || size == 0)
abort ();
trailer = (struct stk_trailer *) trailer->link;
if ((block <= address) && (address < (block + size)))
break;
}
/* Set the result to the offset in this segment and add the sizes
of all predecessor segments. */
result = address - block;
if (trailer == 0)
{
return result;
}
do
{
if (trailer->this_size <= 0)
abort ();
result += trailer->this_size;
trailer = (struct stk_trailer *) trailer->link;
}
while (trailer != 0);
/* We are done. Note that if you present a bogus address (one
not in any segment), you will get a different number back, formed
from subtracting the address of the first block. This is probably
not what you want. */
return (result);
}
# else /* not CRAY2 */
/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
Determine the number of the cell within the stack,
given the address of the cell. The purpose of this
routine is to linearize, in some sense, stack addresses
for alloca. */
static long
i00afunc (long address)
{
long stkl = 0;
long size, pseg, this_segment, stack;
long result = 0;
struct stack_segment_linkage *ssptr;
/* Register B67 contains the address of the end of the
current stack segment. If you (as a subprogram) store
your registers on the stack and find that you are past
the contents of B67, you have overflowed the segment.
B67 also points to the stack segment linkage control
area, which is what we are really interested in. */
stkl = CRAY_STACKSEG_END ();
ssptr = (struct stack_segment_linkage *) stkl;
/* If one subtracts 'size' from the end of the segment,
one has the address of the first word of the segment.
If this is not the first segment, 'pseg' will be
nonzero. */
pseg = ssptr->sspseg;
size = ssptr->sssize;
this_segment = stkl - size;
/* It is possible that calling this routine itself caused
a stack overflow. Discard stack segments which do not
contain the target address. */
while (!(this_segment <= address && address <= stkl))
{
# ifdef DEBUG_I00AFUNC
fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
# endif
if (pseg == 0)
break;
stkl = stkl - pseg;
ssptr = (struct stack_segment_linkage *) stkl;
size = ssptr->sssize;
pseg = ssptr->sspseg;
this_segment = stkl - size;
}
result = address - this_segment;
/* If you subtract pseg from the current end of the stack,
you get the address of the previous stack segment's end.
This seems a little convoluted to me, but I'll bet you save
a cycle somewhere. */
while (pseg != 0)
{
# ifdef DEBUG_I00AFUNC
fprintf (stderr, "%011o %011o\n", pseg, size);
# endif
stkl = stkl - pseg;
ssptr = (struct stack_segment_linkage *) stkl;
size = ssptr->sssize;
pseg = ssptr->sspseg;
result += size;
}
return (result);
}
# endif /* not CRAY2 */
# endif /* CRAY */
# endif /* no alloca */
#endif /* not GCC version 3 */

View file

@ -5,7 +5,7 @@
This program 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 2, or (at your option)
by the Free Software Foundation; either version 3, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,

View file

@ -0,0 +1,35 @@
/* Formatted output to strings.
Copyright (C) 1999, 2002, 2006, 2009, 2010 Free Software Foundation, Inc.
This program 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, 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 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 Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <config.h>
/* Specification. */
#include "vasnprintf.h"
#include <stdarg.h>
char *
asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
{
va_list args;
char *result;
va_start (args, format);
result = vasnprintf (resultbuf, lengthp, format, args);
va_end (args);
return result;
}

View file

@ -0,0 +1,75 @@
/* basename.c -- return the last element in a file name
Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2010 Free Software
Foundation, Inc.
This program 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.
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include "dirname.h"
#include <string.h>
/* Return the address of the last file name component of NAME. If
NAME has no relative file name components because it is a file
system root, return the empty string. */
char *
last_component (char const *name)
{
char const *base = name + FILE_SYSTEM_PREFIX_LEN (name);
char const *p;
bool saw_slash = false;
while (ISSLASH (*base))
base++;
for (p = base; *p; p++)
{
if (ISSLASH (*p))
saw_slash = true;
else if (saw_slash)
{
base = p;
saw_slash = false;
}
}
return (char *) base;
}
/* Return the length of the basename NAME. Typically NAME is the
value returned by base_name or last_component. Act like strlen
(NAME), except omit all trailing slashes. */
size_t
base_len (char const *name)
{
size_t len;
size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name);
for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--)
continue;
if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1
&& ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2])
return 2;
if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len
&& len == prefix_len && ISSLASH (name[prefix_len]))
return prefix_len + 1;
return len;
}

View file

@ -1,5 +1,6 @@
/* Version hook for Argp.
Copyright (C) 2009, 2010 Free Software Foundation, Inc.
/* Convert unibyte character to wide character.
Copyright (C) 2008, 2010 Free Software Foundation, Inc.
Written by Bruno Haible <bruno@clisp.org>, 2008.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -15,24 +16,24 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <version-etc.h>
#include <argp.h>
#include <argp-version-etc.h>
static const char *program_canonical_name;
static const char * const *program_authors;
/* Specification. */
#include <wchar.h>
static void
version_etc_hook (FILE *stream, struct argp_state *state)
#include <stdio.h>
#include <stdlib.h>
wint_t
btowc (int c)
{
version_etc_ar (stream, program_canonical_name, PACKAGE_NAME, VERSION,
program_authors);
}
if (c != EOF)
{
char buf[1];
wchar_t wc;
void
argp_version_setup (const char *name, const char * const *authors)
{
argp_program_version_hook = version_etc_hook;
program_canonical_name = name;
program_authors = authors;
buf[0] = c;
if (mbtowc (&wc, buf, 1) >= 0)
return wc;
}
return WEOF;
}

View file

@ -0,0 +1,683 @@
#! /bin/sh
# Output a system dependent table of character encoding aliases.
#
# Copyright (C) 2000-2004, 2006-2010 Free Software Foundation, Inc.
#
# This program 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, 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 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 Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The table consists of lines of the form
# ALIAS CANONICAL
#
# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)".
# ALIAS is compared in a case sensitive way.
#
# CANONICAL is the GNU canonical name for this character encoding.
# It must be an encoding supported by libiconv. Support by GNU libc is
# also desirable. CANONICAL is case insensitive. Usually an upper case
# MIME charset name is preferred.
# The current list of GNU canonical charset names is as follows.
#
# name MIME? used by which systems
# ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin cygwin
# ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
# ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
# ISO-8859-3 Y glibc solaris cygwin
# ISO-8859-4 Y osf solaris freebsd netbsd openbsd darwin
# ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
# ISO-8859-6 Y glibc aix hpux solaris cygwin
# ISO-8859-7 Y glibc aix hpux irix osf solaris netbsd openbsd darwin cygwin
# ISO-8859-8 Y glibc aix hpux osf solaris cygwin
# ISO-8859-9 Y glibc aix hpux irix osf solaris darwin cygwin
# ISO-8859-13 glibc netbsd openbsd darwin cygwin
# ISO-8859-14 glibc cygwin
# ISO-8859-15 glibc aix osf solaris freebsd netbsd openbsd darwin cygwin
# KOI8-R Y glibc solaris freebsd netbsd openbsd darwin
# KOI8-U Y glibc freebsd netbsd openbsd darwin cygwin
# KOI8-T glibc
# CP437 dos
# CP775 dos
# CP850 aix osf dos
# CP852 dos
# CP855 dos
# CP856 aix
# CP857 dos
# CP861 dos
# CP862 dos
# CP864 dos
# CP865 dos
# CP866 freebsd netbsd openbsd darwin dos
# CP869 dos
# CP874 woe32 dos
# CP922 aix
# CP932 aix cygwin woe32 dos
# CP943 aix
# CP949 osf darwin woe32 dos
# CP950 woe32 dos
# CP1046 aix
# CP1124 aix
# CP1125 dos
# CP1129 aix
# CP1131 darwin
# CP1250 woe32
# CP1251 glibc solaris netbsd openbsd darwin cygwin woe32
# CP1252 aix woe32
# CP1253 woe32
# CP1254 woe32
# CP1255 glibc woe32
# CP1256 woe32
# CP1257 woe32
# GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin
# EUC-JP Y glibc aix hpux irix osf solaris freebsd netbsd darwin
# EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin
# EUC-TW glibc aix hpux irix osf solaris netbsd
# BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin cygwin
# BIG5-HKSCS glibc solaris darwin
# GBK glibc aix osf solaris darwin cygwin woe32 dos
# GB18030 glibc solaris netbsd darwin
# SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin
# JOHAB glibc solaris woe32
# TIS-620 glibc aix hpux osf solaris cygwin
# VISCII Y glibc
# TCVN5712-1 glibc
# ARMSCII-8 glibc darwin
# GEORGIAN-PS glibc cygwin
# PT154 glibc
# HP-ROMAN8 hpux
# HP-ARABIC8 hpux
# HP-GREEK8 hpux
# HP-HEBREW8 hpux
# HP-TURKISH8 hpux
# HP-KANA8 hpux
# DEC-KANJI osf
# DEC-HANYU osf
# UTF-8 Y glibc aix hpux osf solaris netbsd darwin cygwin
#
# Note: Names which are not marked as being a MIME name should not be used in
# Internet protocols for information interchange (mail, news, etc.).
#
# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications
# must understand both names and treat them as equivalent.
#
# The first argument passed to this file is the canonical host specification,
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
host="$1"
os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'`
echo "# This file contains a table of character encoding aliases,"
echo "# suitable for operating system '${os}'."
echo "# It was automatically generated from config.charset."
# List of references, updated during installation:
echo "# Packages using this file: "
case "$os" in
linux-gnulibc1*)
# Linux libc5 doesn't have nl_langinfo(CODESET); therefore
# localcharset.c falls back to using the full locale name
# from the environment variables.
echo "C ASCII"
echo "POSIX ASCII"
for l in af af_ZA ca ca_ES da da_DK de de_AT de_BE de_CH de_DE de_LU \
en en_AU en_BW en_CA en_DK en_GB en_IE en_NZ en_US en_ZA \
en_ZW es es_AR es_BO es_CL es_CO es_DO es_EC es_ES es_GT \
es_HN es_MX es_PA es_PE es_PY es_SV es_US es_UY es_VE et \
et_EE eu eu_ES fi fi_FI fo fo_FO fr fr_BE fr_CA fr_CH fr_FR \
fr_LU ga ga_IE gl gl_ES id id_ID in in_ID is is_IS it it_CH \
it_IT kl kl_GL nl nl_BE nl_NL no no_NO pt pt_BR pt_PT sv \
sv_FI sv_SE; do
echo "$l ISO-8859-1"
echo "$l.iso-8859-1 ISO-8859-1"
echo "$l.iso-8859-15 ISO-8859-15"
echo "$l.iso-8859-15@euro ISO-8859-15"
echo "$l@euro ISO-8859-15"
echo "$l.cp-437 CP437"
echo "$l.cp-850 CP850"
echo "$l.cp-1252 CP1252"
echo "$l.cp-1252@euro CP1252"
#echo "$l.atari-st ATARI-ST" # not a commonly used encoding
echo "$l.utf-8 UTF-8"
echo "$l.utf-8@euro UTF-8"
done
for l in cs cs_CZ hr hr_HR hu hu_HU pl pl_PL ro ro_RO sk sk_SK sl \
sl_SI sr sr_CS sr_YU; do
echo "$l ISO-8859-2"
echo "$l.iso-8859-2 ISO-8859-2"
echo "$l.cp-852 CP852"
echo "$l.cp-1250 CP1250"
echo "$l.utf-8 UTF-8"
done
for l in mk mk_MK ru ru_RU; do
echo "$l ISO-8859-5"
echo "$l.iso-8859-5 ISO-8859-5"
echo "$l.koi8-r KOI8-R"
echo "$l.cp-866 CP866"
echo "$l.cp-1251 CP1251"
echo "$l.utf-8 UTF-8"
done
for l in ar ar_SA; do
echo "$l ISO-8859-6"
echo "$l.iso-8859-6 ISO-8859-6"
echo "$l.cp-864 CP864"
#echo "$l.cp-868 CP868" # not a commonly used encoding
echo "$l.cp-1256 CP1256"
echo "$l.utf-8 UTF-8"
done
for l in el el_GR gr gr_GR; do
echo "$l ISO-8859-7"
echo "$l.iso-8859-7 ISO-8859-7"
echo "$l.cp-869 CP869"
echo "$l.cp-1253 CP1253"
echo "$l.cp-1253@euro CP1253"
echo "$l.utf-8 UTF-8"
echo "$l.utf-8@euro UTF-8"
done
for l in he he_IL iw iw_IL; do
echo "$l ISO-8859-8"
echo "$l.iso-8859-8 ISO-8859-8"
echo "$l.cp-862 CP862"
echo "$l.cp-1255 CP1255"
echo "$l.utf-8 UTF-8"
done
for l in tr tr_TR; do
echo "$l ISO-8859-9"
echo "$l.iso-8859-9 ISO-8859-9"
echo "$l.cp-857 CP857"
echo "$l.cp-1254 CP1254"
echo "$l.utf-8 UTF-8"
done
for l in lt lt_LT lv lv_LV; do
#echo "$l BALTIC" # not a commonly used encoding, wrong encoding name
echo "$l ISO-8859-13"
done
for l in ru_UA uk uk_UA; do
echo "$l KOI8-U"
done
for l in zh zh_CN; do
#echo "$l GB_2312-80" # not a commonly used encoding, wrong encoding name
echo "$l GB2312"
done
for l in ja ja_JP ja_JP.EUC; do
echo "$l EUC-JP"
done
for l in ko ko_KR; do
echo "$l EUC-KR"
done
for l in th th_TH; do
echo "$l TIS-620"
done
for l in fa fa_IR; do
#echo "$l ISIRI-3342" # a broken encoding
echo "$l.utf-8 UTF-8"
done
;;
linux* | *-gnu*)
# With glibc-2.1 or newer, we don't need any canonicalization,
# because glibc has iconv and both glibc and libiconv support all
# GNU canonical names directly. Therefore, the Makefile does not
# need to install the alias file at all.
# The following applies only to glibc-2.0.x and older libcs.
echo "ISO_646.IRV:1983 ASCII"
;;
aix*)
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-6 ISO-8859-6"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-8 ISO-8859-8"
echo "ISO8859-9 ISO-8859-9"
echo "ISO8859-15 ISO-8859-15"
echo "IBM-850 CP850"
echo "IBM-856 CP856"
echo "IBM-921 ISO-8859-13"
echo "IBM-922 CP922"
echo "IBM-932 CP932"
echo "IBM-943 CP943"
echo "IBM-1046 CP1046"
echo "IBM-1124 CP1124"
echo "IBM-1129 CP1129"
echo "IBM-1252 CP1252"
echo "IBM-eucCN GB2312"
echo "IBM-eucJP EUC-JP"
echo "IBM-eucKR EUC-KR"
echo "IBM-eucTW EUC-TW"
echo "big5 BIG5"
echo "GBK GBK"
echo "TIS-620 TIS-620"
echo "UTF-8 UTF-8"
;;
hpux*)
echo "iso88591 ISO-8859-1"
echo "iso88592 ISO-8859-2"
echo "iso88595 ISO-8859-5"
echo "iso88596 ISO-8859-6"
echo "iso88597 ISO-8859-7"
echo "iso88598 ISO-8859-8"
echo "iso88599 ISO-8859-9"
echo "iso885915 ISO-8859-15"
echo "roman8 HP-ROMAN8"
echo "arabic8 HP-ARABIC8"
echo "greek8 HP-GREEK8"
echo "hebrew8 HP-HEBREW8"
echo "turkish8 HP-TURKISH8"
echo "kana8 HP-KANA8"
echo "tis620 TIS-620"
echo "big5 BIG5"
echo "eucJP EUC-JP"
echo "eucKR EUC-KR"
echo "eucTW EUC-TW"
echo "hp15CN GB2312"
#echo "ccdc ?" # what is this?
echo "SJIS SHIFT_JIS"
echo "utf8 UTF-8"
;;
irix*)
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-9 ISO-8859-9"
echo "eucCN GB2312"
echo "eucJP EUC-JP"
echo "eucKR EUC-KR"
echo "eucTW EUC-TW"
;;
osf*)
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-4 ISO-8859-4"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-8 ISO-8859-8"
echo "ISO8859-9 ISO-8859-9"
echo "ISO8859-15 ISO-8859-15"
echo "cp850 CP850"
echo "big5 BIG5"
echo "dechanyu DEC-HANYU"
echo "dechanzi GB2312"
echo "deckanji DEC-KANJI"
echo "deckorean EUC-KR"
echo "eucJP EUC-JP"
echo "eucKR EUC-KR"
echo "eucTW EUC-TW"
echo "GBK GBK"
echo "KSC5601 CP949"
echo "sdeckanji EUC-JP"
echo "SJIS SHIFT_JIS"
echo "TACTIS TIS-620"
echo "UTF-8 UTF-8"
;;
solaris*)
echo "646 ASCII"
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-3 ISO-8859-3"
echo "ISO8859-4 ISO-8859-4"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-6 ISO-8859-6"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-8 ISO-8859-8"
echo "ISO8859-9 ISO-8859-9"
echo "ISO8859-15 ISO-8859-15"
echo "koi8-r KOI8-R"
echo "ansi-1251 CP1251"
echo "BIG5 BIG5"
echo "Big5-HKSCS BIG5-HKSCS"
echo "gb2312 GB2312"
echo "GBK GBK"
echo "GB18030 GB18030"
echo "cns11643 EUC-TW"
echo "5601 EUC-KR"
echo "ko_KR.johap92 JOHAB"
echo "eucJP EUC-JP"
echo "PCK SHIFT_JIS"
echo "TIS620.2533 TIS-620"
#echo "sun_eu_greek ?" # what is this?
echo "UTF-8 UTF-8"
;;
freebsd* | os2*)
# FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore
# localcharset.c falls back to using the full locale name
# from the environment variables.
# Likewise for OS/2. OS/2 has XFree86 just like FreeBSD. Just
# reuse FreeBSD's locale data for OS/2.
echo "C ASCII"
echo "US-ASCII ASCII"
for l in la_LN lt_LN; do
echo "$l.ASCII ASCII"
done
for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \
lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do
echo "$l.ISO_8859-1 ISO-8859-1"
echo "$l.DIS_8859-15 ISO-8859-15"
done
for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do
echo "$l.ISO_8859-2 ISO-8859-2"
done
for l in la_LN lt_LT; do
echo "$l.ISO_8859-4 ISO-8859-4"
done
for l in ru_RU ru_SU; do
echo "$l.KOI8-R KOI8-R"
echo "$l.ISO_8859-5 ISO-8859-5"
echo "$l.CP866 CP866"
done
echo "uk_UA.KOI8-U KOI8-U"
echo "zh_TW.BIG5 BIG5"
echo "zh_TW.Big5 BIG5"
echo "zh_CN.EUC GB2312"
echo "ja_JP.EUC EUC-JP"
echo "ja_JP.SJIS SHIFT_JIS"
echo "ja_JP.Shift_JIS SHIFT_JIS"
echo "ko_KR.EUC EUC-KR"
;;
netbsd*)
echo "646 ASCII"
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-4 ISO-8859-4"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-13 ISO-8859-13"
echo "ISO8859-15 ISO-8859-15"
echo "eucCN GB2312"
echo "eucJP EUC-JP"
echo "eucKR EUC-KR"
echo "eucTW EUC-TW"
echo "BIG5 BIG5"
echo "SJIS SHIFT_JIS"
;;
openbsd*)
echo "646 ASCII"
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-4 ISO-8859-4"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-13 ISO-8859-13"
echo "ISO8859-15 ISO-8859-15"
;;
darwin[56]*)
# Darwin 6.8 doesn't have nl_langinfo(CODESET); therefore
# localcharset.c falls back to using the full locale name
# from the environment variables.
echo "C ASCII"
for l in en_AU en_CA en_GB en_US la_LN; do
echo "$l.US-ASCII ASCII"
done
for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT nl_BE \
nl_NL no_NO pt_PT sv_SE; do
echo "$l ISO-8859-1"
echo "$l.ISO8859-1 ISO-8859-1"
echo "$l.ISO8859-15 ISO-8859-15"
done
for l in la_LN; do
echo "$l.ISO8859-1 ISO-8859-1"
echo "$l.ISO8859-15 ISO-8859-15"
done
for l in cs_CZ hr_HR hu_HU la_LN pl_PL sl_SI; do
echo "$l.ISO8859-2 ISO-8859-2"
done
for l in la_LN lt_LT; do
echo "$l.ISO8859-4 ISO-8859-4"
done
for l in ru_RU; do
echo "$l.KOI8-R KOI8-R"
echo "$l.ISO8859-5 ISO-8859-5"
echo "$l.CP866 CP866"
done
for l in bg_BG; do
echo "$l.CP1251 CP1251"
done
echo "uk_UA.KOI8-U KOI8-U"
echo "zh_TW.BIG5 BIG5"
echo "zh_TW.Big5 BIG5"
echo "zh_CN.EUC GB2312"
echo "ja_JP.EUC EUC-JP"
echo "ja_JP.SJIS SHIFT_JIS"
echo "ko_KR.EUC EUC-KR"
;;
darwin*)
# Darwin 7.5 has nl_langinfo(CODESET), but sometimes its value is
# useless:
# - It returns the empty string when LANG is set to a locale of the
# form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8
# LC_CTYPE file.
# - The environment variables LANG, LC_CTYPE, LC_ALL are not set by
# the system; nl_langinfo(CODESET) returns "US-ASCII" in this case.
# - The documentation says:
# "... all code that calls BSD system routines should ensure
# that the const *char parameters of these routines are in UTF-8
# encoding. All BSD system functions expect their string
# parameters to be in UTF-8 encoding and nothing else."
# It also says
# "An additional caveat is that string parameters for files,
# paths, and other file-system entities must be in canonical
# UTF-8. In a canonical UTF-8 Unicode string, all decomposable
# characters are decomposed ..."
# but this is not true: You can pass non-decomposed UTF-8 strings
# to file system functions, and it is the OS which will convert
# them to decomposed UTF-8 before accessing the file system.
# - The Apple Terminal application displays UTF-8 by default.
# - However, other applications are free to use different encodings:
# - xterm uses ISO-8859-1 by default.
# - TextEdit uses MacRoman by default.
# We prefer UTF-8 over decomposed UTF-8-MAC because one should
# minimize the use of decomposed Unicode. Unfortunately, through the
# Darwin file system, decomposed UTF-8 strings are leaked into user
# space nevertheless.
# Then there are also the locales with encodings other than US-ASCII
# and UTF-8. These locales can be occasionally useful to users (e.g.
# when grepping through ISO-8859-1 encoded text files), when all their
# file names are in US-ASCII.
echo "ISO8859-1 ISO-8859-1"
echo "ISO8859-2 ISO-8859-2"
echo "ISO8859-4 ISO-8859-4"
echo "ISO8859-5 ISO-8859-5"
echo "ISO8859-7 ISO-8859-7"
echo "ISO8859-9 ISO-8859-9"
echo "ISO8859-13 ISO-8859-13"
echo "ISO8859-15 ISO-8859-15"
echo "KOI8-R KOI8-R"
echo "KOI8-U KOI8-U"
echo "CP866 CP866"
echo "CP949 CP949"
echo "CP1131 CP1131"
echo "CP1251 CP1251"
echo "eucCN GB2312"
echo "GB2312 GB2312"
echo "eucJP EUC-JP"
echo "eucKR EUC-KR"
echo "Big5 BIG5"
echo "Big5HKSCS BIG5-HKSCS"
echo "GBK GBK"
echo "GB18030 GB18030"
echo "SJIS SHIFT_JIS"
echo "ARMSCII-8 ARMSCII-8"
echo "PT154 PT154"
#echo "ISCII-DEV ?"
echo "* UTF-8"
;;
beos* | haiku*)
# BeOS and Haiku have a single locale, and it has UTF-8 encoding.
echo "* UTF-8"
;;
msdosdjgpp*)
# DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore
# localcharset.c falls back to using the full locale name
# from the environment variables.
echo "#"
echo "# The encodings given here may not all be correct."
echo "# If you find that the encoding given for your language and"
echo "# country is not the one your DOS machine actually uses, just"
echo "# correct it in this file, and send a mail to"
echo "# Juan Manuel Guerrero <juan.guerrero@gmx.de>"
echo "# and Bruno Haible <bruno@clisp.org>."
echo "#"
echo "C ASCII"
# ISO-8859-1 languages
echo "ca CP850"
echo "ca_ES CP850"
echo "da CP865" # not CP850 ??
echo "da_DK CP865" # not CP850 ??
echo "de CP850"
echo "de_AT CP850"
echo "de_CH CP850"
echo "de_DE CP850"
echo "en CP850"
echo "en_AU CP850" # not CP437 ??
echo "en_CA CP850"
echo "en_GB CP850"
echo "en_NZ CP437"
echo "en_US CP437"
echo "en_ZA CP850" # not CP437 ??
echo "es CP850"
echo "es_AR CP850"
echo "es_BO CP850"
echo "es_CL CP850"
echo "es_CO CP850"
echo "es_CR CP850"
echo "es_CU CP850"
echo "es_DO CP850"
echo "es_EC CP850"
echo "es_ES CP850"
echo "es_GT CP850"
echo "es_HN CP850"
echo "es_MX CP850"
echo "es_NI CP850"
echo "es_PA CP850"
echo "es_PY CP850"
echo "es_PE CP850"
echo "es_SV CP850"
echo "es_UY CP850"
echo "es_VE CP850"
echo "et CP850"
echo "et_EE CP850"
echo "eu CP850"
echo "eu_ES CP850"
echo "fi CP850"
echo "fi_FI CP850"
echo "fr CP850"
echo "fr_BE CP850"
echo "fr_CA CP850"
echo "fr_CH CP850"
echo "fr_FR CP850"
echo "ga CP850"
echo "ga_IE CP850"
echo "gd CP850"
echo "gd_GB CP850"
echo "gl CP850"
echo "gl_ES CP850"
echo "id CP850" # not CP437 ??
echo "id_ID CP850" # not CP437 ??
echo "is CP861" # not CP850 ??
echo "is_IS CP861" # not CP850 ??
echo "it CP850"
echo "it_CH CP850"
echo "it_IT CP850"
echo "lt CP775"
echo "lt_LT CP775"
echo "lv CP775"
echo "lv_LV CP775"
echo "nb CP865" # not CP850 ??
echo "nb_NO CP865" # not CP850 ??
echo "nl CP850"
echo "nl_BE CP850"
echo "nl_NL CP850"
echo "nn CP865" # not CP850 ??
echo "nn_NO CP865" # not CP850 ??
echo "no CP865" # not CP850 ??
echo "no_NO CP865" # not CP850 ??
echo "pt CP850"
echo "pt_BR CP850"
echo "pt_PT CP850"
echo "sv CP850"
echo "sv_SE CP850"
# ISO-8859-2 languages
echo "cs CP852"
echo "cs_CZ CP852"
echo "hr CP852"
echo "hr_HR CP852"
echo "hu CP852"
echo "hu_HU CP852"
echo "pl CP852"
echo "pl_PL CP852"
echo "ro CP852"
echo "ro_RO CP852"
echo "sk CP852"
echo "sk_SK CP852"
echo "sl CP852"
echo "sl_SI CP852"
echo "sq CP852"
echo "sq_AL CP852"
echo "sr CP852" # CP852 or CP866 or CP855 ??
echo "sr_CS CP852" # CP852 or CP866 or CP855 ??
echo "sr_YU CP852" # CP852 or CP866 or CP855 ??
# ISO-8859-3 languages
echo "mt CP850"
echo "mt_MT CP850"
# ISO-8859-5 languages
echo "be CP866"
echo "be_BE CP866"
echo "bg CP866" # not CP855 ??
echo "bg_BG CP866" # not CP855 ??
echo "mk CP866" # not CP855 ??
echo "mk_MK CP866" # not CP855 ??
echo "ru CP866"
echo "ru_RU CP866"
echo "uk CP1125"
echo "uk_UA CP1125"
# ISO-8859-6 languages
echo "ar CP864"
echo "ar_AE CP864"
echo "ar_DZ CP864"
echo "ar_EG CP864"
echo "ar_IQ CP864"
echo "ar_IR CP864"
echo "ar_JO CP864"
echo "ar_KW CP864"
echo "ar_MA CP864"
echo "ar_OM CP864"
echo "ar_QA CP864"
echo "ar_SA CP864"
echo "ar_SY CP864"
# ISO-8859-7 languages
echo "el CP869"
echo "el_GR CP869"
# ISO-8859-8 languages
echo "he CP862"
echo "he_IL CP862"
# ISO-8859-9 languages
echo "tr CP857"
echo "tr_TR CP857"
# Japanese
echo "ja CP932"
echo "ja_JP CP932"
# Chinese
echo "zh_CN GBK"
echo "zh_TW CP950" # not CP938 ??
# Korean
echo "kr CP949" # not CP934 ??
echo "kr_KR CP949" # not CP934 ??
# Thai
echo "th CP874"
echo "th_TH CP874"
# Other
echo "eo CP850"
echo "eo_EO CP850"
;;
esac

View file

@ -0,0 +1,86 @@
/* dirname.c -- return all but the last element in a file name
Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2010 Free Software
Foundation, Inc.
This program 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.
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include "dirname.h"
#include <stdlib.h>
#include <string.h>
/* Return the length of the prefix of FILE that will be used by
dir_name. If FILE is in the working directory, this returns zero
even though `dir_name (FILE)' will return ".". Works properly even
if there are trailing slashes (by effectively ignoring them). */
size_t
dir_len (char const *file)
{
size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file);
size_t length;
/* Advance prefix_length beyond important leading slashes. */
prefix_length += (prefix_length != 0
? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
&& ISSLASH (file[prefix_length]))
: (ISSLASH (file[0])
? ((DOUBLE_SLASH_IS_DISTINCT_ROOT
&& ISSLASH (file[1]) && ! ISSLASH (file[2])
? 2 : 1))
: 0));
/* Strip the basename and any redundant slashes before it. */
for (length = last_component (file) - file;
prefix_length < length; length--)
if (! ISSLASH (file[length - 1]))
break;
return length;
}
/* In general, we can't use the builtin `dirname' function if available,
since it has different meanings in different environments.
In some environments the builtin `dirname' modifies its argument.
Return the leading directories part of FILE, allocated with malloc.
Works properly even if there are trailing slashes (by effectively
ignoring them). Return NULL on failure.
If lstat (FILE) would succeed, then { chdir (dir_name (FILE));
lstat (base_name (FILE)); } will access the same file. Likewise,
if the sequence { chdir (dir_name (FILE));
rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE
to "foo" in the same directory FILE was in. */
char *
mdir_name (char const *file)
{
size_t length = dir_len (file);
bool append_dot = (length == 0
|| (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
&& length == FILE_SYSTEM_PREFIX_LEN (file)
&& file[2] != '\0' && ! ISSLASH (file[2])));
char *dir = malloc (length + append_dot + 1);
if (!dir)
return NULL;
memcpy (dir, file, length);
if (append_dot)
dir[length++] = '.';
dir[length] = '\0';
return dir;
}

View file

@ -0,0 +1,74 @@
/* Take file names apart into directory and base names.
Copyright (C) 1998, 2001, 2003-2006, 2009-2010 Free Software Foundation,
Inc.
This program 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.
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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef DIRNAME_H_
# define DIRNAME_H_ 1
# include <stdbool.h>
# include <stddef.h>
# ifndef DIRECTORY_SEPARATOR
# define DIRECTORY_SEPARATOR '/'
# endif
# ifndef ISSLASH
# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
# endif
# ifndef FILE_SYSTEM_PREFIX_LEN
# if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX
/* This internal macro assumes ASCII, but all hosts that support drive
letters use ASCII. */
# define _IS_DRIVE_LETTER(c) (((unsigned int) (c) | ('a' - 'A')) - 'a' \
<= 'z' - 'a')
# define FILE_SYSTEM_PREFIX_LEN(Filename) \
(_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
# else
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
# endif
# endif
# ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
# endif
# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
# endif
# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
# else
# define IS_ABSOLUTE_FILE_NAME(F) \
(ISSLASH ((F)[0]) || 0 < FILE_SYSTEM_PREFIX_LEN (F))
# endif
# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
# if GNULIB_DIRNAME
char *base_name (char const *file);
char *dir_name (char const *file);
# endif
char *mdir_name (char const *file);
size_t base_len (char const *file);
size_t dir_len (char const *file);
char *last_component (char const *file);
bool strip_trailing_slashes (char *file);
#endif /* not DIRNAME_H_ */

160
grub-core/gnulib/errno.in.h Normal file
View file

@ -0,0 +1,160 @@
/* A POSIX-like <errno.h>.
Copyright (C) 2008-2010 Free Software Foundation, Inc.
This program 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, 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 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 Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef _GL_ERRNO_H
#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
/* The include_next requires a split double-inclusion guard. */
#@INCLUDE_NEXT@ @NEXT_ERRNO_H@
#ifndef _GL_ERRNO_H
#define _GL_ERRNO_H
/* On native Windows platforms, many macros are not defined. */
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* POSIX says that EAGAIN and EWOULDBLOCK may have the same value. */
# define EWOULDBLOCK EAGAIN
/* Values >= 100 seem safe to use. */
# define ETXTBSY 100
# define GNULIB_defined_ETXTBSY 1
/* These are intentionally the same values as the WSA* error numbers, defined
in <winsock2.h>. */
# define EINPROGRESS 10036
# define EALREADY 10037
# define ENOTSOCK 10038
# define EDESTADDRREQ 10039
# define EMSGSIZE 10040
# define EPROTOTYPE 10041
# define ENOPROTOOPT 10042
# define EPROTONOSUPPORT 10043
# define ESOCKTNOSUPPORT 10044 /* not required by POSIX */
# define EOPNOTSUPP 10045
# define EPFNOSUPPORT 10046 /* not required by POSIX */
# define EAFNOSUPPORT 10047
# define EADDRINUSE 10048
# define EADDRNOTAVAIL 10049
# define ENETDOWN 10050
# define ENETUNREACH 10051
# define ENETRESET 10052
# define ECONNABORTED 10053
# define ECONNRESET 10054
# define ENOBUFS 10055
# define EISCONN 10056
# define ENOTCONN 10057
# define ESHUTDOWN 10058 /* not required by POSIX */
# define ETOOMANYREFS 10059 /* not required by POSIX */
# define ETIMEDOUT 10060
# define ECONNREFUSED 10061
# define ELOOP 10062
# define EHOSTDOWN 10064 /* not required by POSIX */
# define EHOSTUNREACH 10065
# define EPROCLIM 10067 /* not required by POSIX */
# define EUSERS 10068 /* not required by POSIX */
# define EDQUOT 10069
# define ESTALE 10070
# define EREMOTE 10071 /* not required by POSIX */
# define GNULIB_defined_ESOCK 1
# endif
/* On OSF/1 5.1, when _XOPEN_SOURCE_EXTENDED is not defined, the macros
EMULTIHOP, ENOLINK, EOVERFLOW are not defined. */
# if @EMULTIHOP_HIDDEN@
# define EMULTIHOP @EMULTIHOP_VALUE@
# define GNULIB_defined_EMULTIHOP 1
# endif
# if @ENOLINK_HIDDEN@
# define ENOLINK @ENOLINK_VALUE@
# define GNULIB_defined_ENOLINK 1
# endif
# if @EOVERFLOW_HIDDEN@
# define EOVERFLOW @EOVERFLOW_VALUE@
# define GNULIB_defined_EOVERFLOW 1
# endif
/* On OpenBSD 4.0 and on native Windows, the macros ENOMSG, EIDRM, ENOLINK,
EPROTO, EMULTIHOP, EBADMSG, EOVERFLOW, ENOTSUP, ECANCELED are not defined.
Define them here. Values >= 2000 seem safe to use: Solaris ESTALE = 151,
HP-UX EWOULDBLOCK = 246, IRIX EDQUOT = 1133.
Note: When one of these systems defines some of these macros some day,
binaries will have to be recompiled so that they recognizes the new
errno values from the system. */
# ifndef ENOMSG
# define ENOMSG 2000
# define GNULIB_defined_ENOMSG 1
# endif
# ifndef EIDRM
# define EIDRM 2001
# define GNULIB_defined_EIDRM 1
# endif
# ifndef ENOLINK
# define ENOLINK 2002
# define GNULIB_defined_ENOLINK 1
# endif
# ifndef EPROTO
# define EPROTO 2003
# define GNULIB_defined_EPROTO 1
# endif
# ifndef EMULTIHOP
# define EMULTIHOP 2004
# define GNULIB_defined_EMULTIHOP 1
# endif
# ifndef EBADMSG
# define EBADMSG 2005
# define GNULIB_defined_EBADMSG 1
# endif
# ifndef EOVERFLOW
# define EOVERFLOW 2006
# define GNULIB_defined_EOVERFLOW 1
# endif
# ifndef ENOTSUP
# define ENOTSUP 2007
# define GNULIB_defined_ENOTSUP 1
# endif
# ifndef ESTALE
# define ESTALE 2009
# define GNULIB_defined_ESTALE 1
# endif
# ifndef ECANCELED
# define ECANCELED 2008
# define GNULIB_defined_ECANCELED 1
# endif
#endif /* _GL_ERRNO_H */
#endif /* _GL_ERRNO_H */

Some files were not shown because too many files have changed in this diff Show more