merge with mainline

This commit is contained in:
BVK Chaitanya 2010-09-19 18:54:45 +05:30
commit b524259bec
396 changed files with 27988 additions and 10840 deletions

View File

@ -4,6 +4,8 @@
30_os-prober
40_custom
41_custom
*.1
*.8
aclocal.m4
ascii.bitmaps
ascii.h
@ -18,8 +20,6 @@ config.log
config.status
config.sub
configure
conf/*.mk
*.d
DISTLIST
docs/*.info
docs/stamp-vti
@ -58,23 +58,29 @@ grub-set-default
grub-setup
grub_setup_init.c
grub_setup_init.h
grub-shell
grub-shell-tester
*.img
*.image
include/grub/cpu
include/grub/machine
install-sh
lib/libgcrypt-grub
libgrub_a_init.c
*.lst
Makefile
*.mod
mod-*.c
missing
*.pf2
*.pp
po/*.mo
po/grub.pot
stamp-h
stamp-h1
stamp-h.in
symlist.c
symlist.h
trigtables.c
update-grub_lib
unidata.c
@ -91,7 +97,11 @@ texinfo.tex
grub-core/lib/libgcrypt-grub
**/.deps-util
**/.deps-core
**/.dirstamp
Makefile.util.am
grub-core/Makefile.core.am
grub-core/Makefile.gcry.am
grub-core/Makefile.gcry.def
grub-core/*.module
grub-core/*.pp
util/bash-completion.d/grub

1949
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@ configuring the GRUB.
On GNU/Linux, you also need:
* libdevmapper (recommended)
* libdevmapper 1.02.34 or later (recommended)
To build grub-emu, you need:

View File

@ -1,7 +1,7 @@
AUTOMAKE_OPTIONS = subdir-objects
DEPDIR = .deps-util
SUBDIRS = . grub-core po docs
SUBDIRS = . grub-core po docs util/bash-completion.d
include $(top_srcdir)/conf/Makefile.common
include $(top_srcdir)/conf/Makefile.extra-dist
@ -44,9 +44,23 @@ libgrub_a_init.c: libgrub_a_init.lst $(top_srcdir)/geninit.sh
sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1)
CLEANFILES += libgrub_a_init.c
# For grub-fstest
grub_fstest.pp: $(grub_fstest_SOURCES)
$(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(grub_fstest_CPPFLAGS) $(CPPFLAGS) \
-D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1)
CLEANFILES += grub_fstest.pp
grub_fstest_init.lst: libgrub.pp grub_fstest.pp
cat $^ | grep '@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1)
CLEANFILES += grub_fstest_init.lst
grub_fstest_init.c: grub_fstest_init.lst $(top_srcdir)/geninit.sh
sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1)
CLEANFILES += grub_fstest_init.c
if COND_GRUB_MKFONT
if COND_HAVE_FONT_SOURCE
grubdata_DATA = unicode.pf2 ascii.pf2 ascii.h widthspec.h
grubdata_DATA = unicode.pf2 ascii.pf2 euro.pf2 ascii.h widthspec.h
endif
endif
@ -62,6 +76,10 @@ ascii.pf2: $(FONT_SOURCE) grub-mkfont
$(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES)
CLEANFILES += ascii.pf2
euro.pf2: $(FONT_SOURCE) grub-mkfont
$(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES)
CLEANFILES += euro.pf2
ascii.bitmaps: $(FONT_SOURCE) grub-mkfont
$(builddir)/grub-mkfont --ascii-bitmaps -o $@ $(FONT_SOURCE)
CLEANFILES += ascii.bitmaps
@ -82,4 +100,223 @@ CLEANFILES += widthspec.h
platform_HEADERS = config.h
pkglib_DATA += grub-mkconfig_lib
pkglib_DATA += update-grub_lib
pkglib_DATA += update-grub_lib
if COND_i386_coreboot
BOOTTARGET=coreboot
QEMU32=qemu-system-i386
endif
if COND_i386_multiboot
BOOTTARGET=cd
QEMU32=qemu-system-i386
endif
if COND_i386_ieee1275
BOOTTARGET=cd
QEMU32=qemu-system-i386
endif
if COND_i386_qemu
BOOTTARGET=qemu
QEMU32=qemu-system-i386
endif
if COND_i386_pc
BOOTTARGET=cd
QEMU32=qemu-system-i386
endif
if COND_i386_efi
QEMU32=qemu-system-i386
BOOTTARGET=cd
endif
if COND_x86_64_efi
QEMU32=qemu-system-x86_64
BOOTTARGET=cd
endif
linux.init.x86_64: $(srcdir)/grub-core/tests/boot/linux.init-x86_64.S
$(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
linux.init.i386: $(srcdir)/grub-core/tests/boot/linux.init-i386.S
$(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
multiboot.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S
$(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -DTARGET_MULTIBOOT=1 -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include
kfreebsd.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S
$(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include
kfreebsd.aout: kfreebsd.elf
$(OBJCOPY) -O a.out-i386-linux $< $@ -R .note.gnu.build-id
pc-chainloader.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S
$(TARGET_CC) -o $@ $< -DTARGET_CHAINLOADER=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0x7c00 -m32
pc-chainloader.bin: pc-chainloader.elf
$(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn $< $@;
ntldr.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S
$(TARGET_CC) -o $@ $< -DTARGET_NTLDR=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0 -m32
ntldr.bin: ntldr.elf
$(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn $< $@;
multiboot2.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S
$(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -DTARGET_MULTIBOOT2=1
kfreebsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kfreebsd.init-x86_64.S
$(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@
kfreebsd.init.i386: $(srcdir)/grub-core/tests/boot/kfreebsd.init-i386.S
$(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@
knetbsd.init.i386: $(srcdir)/grub-core/tests/boot/kbsd.init-i386.S
$(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DTARGET_NETBSD=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
kopenbsd.init.i386: $(srcdir)/grub-core/tests/boot/kbsd.init-i386.S
$(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DTARGET_OPENBSD=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
knetbsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kbsd.init-x86_64.S
$(TARGET_CC) -o $@ $< -m64 -DTARGET_NETBSD=1 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
kopenbsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kbsd.init-x86_64.S
$(TARGET_CC) -o $@ $< -m64 -DTARGET_OPENBSD=1 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\"
linux-initramfs.i386: linux.init.i386 Makefile
TDIR=`mktemp -d`; cp $< $$TDIR/init; (cd $$TDIR; echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@; rm -rf $$TDIR
linux-initramfs.x86_64: linux.init.x86_64 Makefile
TDIR=`mktemp -d`; cp $< $$TDIR/init; (cd $$TDIR; echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@; rm -rf $$TDIR
kfreebsd-mfsroot.i386.img: kfreebsd.init.i386 Makefile
TDIR=`mktemp -d`; mkdir $$TDIR/dev; mkdir $$TDIR/sbin; cp $< $$TDIR/sbin/init; makefs -t ffs -s 30m -f 1000 -o minfree=0,version=1 $@ $$TDIR; rm -rf $$TDIR
knetbsd.image.i386: knetbsd.init.i386 $(srcdir)/grub-core/tests/boot/kbsd.spec.txt
TDIR=`mktemp -d` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 64k -f 10 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR
kopenbsd.image.i386: kopenbsd.init.i386 $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt
TDIR=`mktemp -d` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 128k -f 10 -o minfree=0,version=1 $@ $$TDIR && bsdlabel -f -R $@ $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt && rm -rf $$TDIR || rm -f $@
kopenbsd.image.x86_64: kopenbsd.init.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt
TDIR=`mktemp -d` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 128k -f 10 -o minfree=0,version=1 $@ $$TDIR && bsdlabel -f -R $@ $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt && rm -rf $$TDIR || rm -f $@
knetbsd.miniroot-image.i386.img: knetbsd.image.i386 $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386
$(OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386 $@
kfreebsd-mfsroot.x86_64.img: kfreebsd.init.x86_64 Makefile
TDIR=`mktemp -d`; mkdir $$TDIR/dev; mkdir $$TDIR/sbin; cp $< $$TDIR/sbin/init; makefs -t ffs -s 30m -f 1000 -o minfree=0,version=1 $@ $$TDIR; rm -rf $$TDIR
knetbsd.image.x86_64: knetbsd.init.x86_64 $(srcdir)/grub-core/tests/boot/kbsd.spec.txt
TDIR=`mktemp -d` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 64k -f 10 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR
knetbsd.miniroot-image.x86_64.img: knetbsd.image.x86_64 $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64
$(OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64 $@
CLEANFILES += linux.init.i386 kfreebsd.init.i386 linux.init.x86_64 linux-initramfs.i386 linux-initramfs.x86_64
kfreebsd-mfsroot.i386.gz: kfreebsd-mfsroot.i386.img
gzip < $< > $@
bootcheck-kfreebsd-i386: kfreebsd-mfsroot.i386.gz $(GRUB_PAYLOADS_DIR)/kfreebsd.i386 $(GRUB_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/mfsroot.gz=kfreebsd-mfsroot.i386.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.i386 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
kfreebsd-mfsroot.x86_64.gz: kfreebsd-mfsroot.x86_64.img
gzip < $< > $@
bootcheck-kfreebsd-x86_64: kfreebsd-mfsroot.x86_64.gz $(GRUB_PAYLOADS_DIR)/kfreebsd.x86_64 $(GRUB_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=qemu-system-x86_64 --files=/mfsroot.gz=kfreebsd-mfsroot.x86_64.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.x86_64 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
knetbsd.miniroot-image.i386.gz: knetbsd.miniroot-image.i386.img
gzip < $< > $@
bootcheck-knetbsd-i386: knetbsd.miniroot-image.i386.gz $(GRUB_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/grub-core/tests/boot/knetbsd.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/miniroot.gz=knetbsd.miniroot-image.i386.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-kopenbsd-i386: kopenbsd.image.i386 $(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/ramdisk=kopenbsd.image.i386 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-kopenbsd-x86_64: kopenbsd.image.x86_64 $(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=qemu-system-x86_64 --files=/ramdisk=kopenbsd.image.x86_64 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
knetbsd.miniroot-image.x86_64.gz: knetbsd.miniroot-image.x86_64.img
gzip < $< > $@
bootcheck-knetbsd-x86_64: knetbsd.miniroot-image.x86_64.gz $(GRUB_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/grub-core/tests/boot/knetbsd.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=qemu-system-x86_64 --files=/miniroot.gz=knetbsd.miniroot-image.x86_64.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux-x86_64: linux-initramfs.x86_64 $(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux16-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-linux16-x86_64: linux-initramfs.x86_64 $(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-multiboot: multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/multiboot.elf=multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-multiboot2: multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/multiboot2.elf=multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-kfreebsd-aout: kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/kfreebsd.aout=kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-pc-chainloader: pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/pc-chainloader.bin=pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
bootcheck-ntldr: ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg grub-shell
timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu-opts="$(GRUB_QEMU_OPTS)" --boot=$(BOOTTARGET) --qemu=$(QEMU32) --files=/ntldr.bin=ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
BOOTCHECKS=
if COND_i386_pc
#pc chainloader by definition is only for i386-pc
BOOTCHECKS += bootcheck-pc-chainloader
#ntldr and bootmgr require BIOS.
BOOTCHECKS += bootcheck-ntldr
#legacy protocol makes early BIOS calls.
BOOTCHECKS += bootcheck-linux16-i386 bootcheck-linux16-x86_64
# Crashes early on non-BIOS
BOOTCHECKS += bootcheck-knetbsd-i386
endif
if !COND_i386_coreboot
# Crashes because memory at 0-0x1000 is occupied
BOOTCHECKS += bootcheck-knetbsd-x86_64
# Likewise and require ACPI.
if !COND_i386_multiboot
if !COND_i386_qemu
BOOTCHECKS += bootcheck-kfreebsd-x86_64
BOOTCHECKS += bootcheck-kfreebsd-i386
endif
endif
endif
BOOTCHECKS += bootcheck-kfreebsd-aout
BOOTCHECKS += bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64
BOOTCHECKS += bootcheck-multiboot bootcheck-multiboot2
BOOTCHECKS += bootcheck-linux-i386 bootcheck-linux-x86_64
.PHONY: bootcheck-linux-i386 bootcheck-linux-x86_64 \
bootcheck-kfreebsd-i386 bootcheck-kfreebsd-x86_64 \
bootcheck-knetbsd-i386 bootcheck-knetbsd-x86_64
# Randomly generated
SUCCESSFUL_BOOT_STRING=3e49994fd5d82b7c9298d672d774080d
# tianocore cd access is very slow
BOOTCHECK_TIMEOUT=180
bootcheck: $(BOOTCHECKS)

View File

@ -23,7 +23,6 @@ library = {
common = grub-core/kern/misc.c;
common = grub-core/kern/emu/mm.c;
common = grub-core/kern/emu/misc.c;
common = grub-core/kern/emu/hostfs.c;
common = grub-core/kern/emu/getroot.c;
common = grub-core/kern/emu/hostdisk.c;
@ -31,7 +30,6 @@ library = {
common = grub-core/commands/extcmd.c;
common = grub-core/commands/ls.c;
common = grub-core/disk/dmraid_nvidia.c;
common = grub-core/disk/host.c;
common = grub-core/disk/loopback.c;
common = grub-core/disk/lvm.c;
common = grub-core/disk/mdraid_linux.c;
@ -43,6 +41,7 @@ library = {
common = grub-core/fs/afs.c;
common = grub-core/fs/befs_be.c;
common = grub-core/fs/befs.c;
common = grub-core/fs/btrfs.c;
common = grub-core/fs/cpio.c;
common = grub-core/fs/ext2.c;
common = grub-core/fs/fat.c;
@ -52,6 +51,7 @@ library = {
common = grub-core/fs/iso9660.c;
common = grub-core/fs/jfs.c;
common = grub-core/fs/minix.c;
common = grub-core/fs/minix2.c;
common = grub-core/fs/nilfs2.c;
common = grub-core/fs/ntfs.c;
common = grub-core/fs/ntfscomp.c;
@ -88,6 +88,7 @@ library = {
common = grub-core/partmap/gpt.c;
common = grub-core/partmap/msdos.c;
common = grub-core/partmap/sun.c;
common = grub-core/partmap/sunpc.c;
common = grub-core/script/function.c;
common = grub-core/script/lexer.c;
common = grub-core/script/main.c;
@ -178,11 +179,13 @@ program = {
program = {
name = grub-fstest;
mansection = 1;
common_nodist = grub_fstest_init.c;
common = util/grub-fstest.c;
common = grub-core/kern/emu/hostfs.c;
common = grub-core/disk/host.c;
ldadd = libgrub.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER)';
condition = COND_GRUB_FSTEST;
};
program = {
@ -229,14 +232,11 @@ program = {
name = grub-setup;
installdir = sbin;
mansection = 8;
i386_pc = util/i386/pc/grub-setup.c;
i386_pc = util/raid.c;
i386_pc = util/lvm.c;
common = util/grub-setup.c;
common = util/raid.c;
common = util/lvm.c;
sparc64_ieee1275 = util/ieee1275/ofpath.c;
sparc64_ieee1275 = util/sparc64/ieee1275/grub-setup.c;
sparc64_ieee1275 = util/raid.c;
sparc64_ieee1275 = util/lvm.c;
ldadd = libgrub.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL)';
@ -252,9 +252,20 @@ program = {
ieee1275 = util/ieee1275/ofpath.c;
ldadd = libgrub.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL)';
enable = sparc64_ieee1275;
};
program = {
name = grub-mklayout;
mansection = 1;
common = util/grub-mklayout.c;
ldadd = libgrub.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER)';
};
data = {
common = util/grub.d/README;
installdir = grubconf;
@ -329,11 +340,12 @@ script = {
script = {
mansection = 1;
name = grub-mkrescue;
x86_noieee1275 = util/grub-mkrescue.in;
x86 = util/grub-mkrescue.in;
powerpc_ieee1275 = util/powerpc/ieee1275/grub-mkrescue.in;
enable = i386_pc;
enable = x86_efi;
enable = i386_qemu;
enable = i386_multiboot;
enable = i386_coreboot;
enable = powerpc_ieee1275;
};
@ -343,16 +355,16 @@ script = {
installdir = sbin;
name = grub-install;
mips = util/grub-install.in;
i386_noefi_noieee1275 = util/grub-install.in;
common = util/grub-install.in;
enable = noemu;
};
x86_efi = util/i386/efi/grub-install.in;
i386_ieee1275 = util/ieee1275/grub-install.in;
powerpc_ieee1275 = util/ieee1275/grub-install.in;
script = {
mansection = 8;
installdir = sbin;
name = grub-mknetdir;
enable = x86;
enable = mips;
enable = powerpc_ieee1275;
common = util/grub-mknetdir.in;
};
script = {
@ -388,6 +400,11 @@ script = {
installdir = noinst;
};
script = {
name = grub-kbdcomp;
common = util/grub-kbdcomp.in;
};
script = {
name = grub-shell;
common = tests/util/grub-shell.in;
@ -496,6 +513,48 @@ script = {
common = tests/grub_script_shift.in;
};
script = {
testcase;
name = grub_script_blockarg;
common = tests/grub_script_blockarg.in;
};
script = {
testcase;
name = grub_script_setparams;
common = tests/grub_script_setparams.in;
};
script = {
testcase;
name = grub_script_return;
common = tests/grub_script_return.in;
};
script = {
testcase;
name = grub_cmd_regexp;
common = tests/grub_cmd_regexp.in;
};
script = {
testcase;
name = grub_script_expansion;
common = tests/grub_script_expansion.in;
};
script = {
testcase;
name = grub_script_not;
common = tests/grub_script_not.in;
};
script = {
testcase;
name = partmap_test;
common = tests/partmap_test.in;
};
program = {
testcase;
name = example_unit_test;
@ -508,3 +567,14 @@ program = {
ldadd = libgrub.a;
ldadd = '$(LIBDEVMAPPER)';
};
program = {
name = grub-menulst2cfg;
mansection = 1;
common = util/grub-menulst2cfg.c;
common = grub-core/lib/legacy_parse.c;
common = grub-core/lib/i386/pc/vesa_modes_table.c;
ldadd = libgrub.a;
ldflags = '$(LIBDEVMAPPER)';
};

95
NEWS
View File

@ -1,3 +1,98 @@
New in 1.99:
* New relocator. Allows for more kernel support and more
straightforward loader writing.
* Handle USB pendrives exposed as floppies.
* New Automake-based build system.
* Add `sendkey' command (i386-pc only).
* ZFS support in `grub-install' and `grub-mkconfig'. Note: complete
functionality requires external ZFS implementation (available from
grub-extras).
* Support 1.x versions of mdadm metadata.
* Fix corruption when reading Reiserfs directory entries.
* Bidirectional text and diacritics support.
* Skip LVM snapshots.
* MIPS Yeeloong firmware port.
* Change grub-mkdevicemap to emit /dev/disk/by-id/ names where possible
on GNU/Linux.
* Add `grub-mkconfig' support for Xen with Linux.
* Add `grub-mkconfig' support for initrd images on Fedora 13.
* Support >3GiB and <16MiB RAM in i386-qemu.
* Add support for Cirrus 5446 and Bochs video cards.
* Load more appropriate video drivers automatically in `grub-mkconfig'.
* USB improvements, including hotplugging/hotunplugging, hub support,
and USB serial support.
* AMD Geode CS5536 support.
* Extensive updates to the Texinfo documentation.
* Add `grub-probe' support for the btrfs filesystem, permitting / to
reside on btrfs as long as /boot is on a filesystem natively supported
by GRUB.
* Handle symbolic links under /dev/mapper on GNU/Linux.
* Handle installation across multiple partition table types.
* Add `cmostest' command (i386/x86_64 only).
* Add support for DM-RAID disk devices on GNU/Linux.
* Remove `grub-mkisofs'. `grub-mkrescue' now uses GNU xorriso to build
CD images.
* `grub-mkrescue' support for EFI, coreboot, and QEMU platforms.
* Unify `grub-mkimage' source code across platforms.
* Fix VGA (as opposed to VBE) video driver, formerly a terminal driver.
* Add menu hotkey support.
* Add support for the nilfs2 filesystem.
* `grub-probe' and `grub-mkconfig' support for NetBSD.
* Support setting a background image in `grub-mkconfig'.
* Support multiple terminals in `grub-mkconfig'.
* Regexp support.
* MIPS multiboot2 support.
* Multiboot2 tag support.
* sunpc partition table support.
* Add a number of new language features to GRUB script: `for', `while',
`until', `elif', function parameters, `break', `continue', and
`shift'.
* Support nested partition tables. GRUB now prefers to name partitions
in the form `(hd0,msdos1,bsd1)' rather than `(hd0,1,a)'.
* Speed up consecutive hostdisk operations on the same device.
* Compile parts of `grub-emu' as modules.
New in 1.98 - 2010-03-06:
* Multiboot on EFI support.

View File

@ -1,8 +1,10 @@
# -*- makefile -*-
CFLAGS_PLATFORM=
# Platform specific options
if COND_i386_pc
CFLAGS_PLATFORM = -mrtd -mregparm=3
CFLAGS_PLATFORM += -mrtd -mregparm=3
endif
if COND_i386_efi
LDFLAGS_PLATFORM = -melf_i386
@ -11,27 +13,30 @@ if COND_x86_64_efi
LDFLAGS_PLATFORM = -melf_x86_64
endif
if COND_i386_qemu
CFLAGS_PLATFORM = -mrtd -mregparm=3
CFLAGS_PLATFORM += -mrtd -mregparm=3
endif
if COND_i386_coreboot
CFLAGS_PLATFORM = -mrtd -mregparm=3
CFLAGS_PLATFORM += -mrtd -mregparm=3
endif
if COND_i386_ieee1275
CFLAGS_PLATFORM = -mrtd -mregparm=3
CFLAGS_PLATFORM += -mrtd -mregparm=3
endif
if COND_mips_yeeloong
CFLAGS_PLATFORM = -march=mips3 -mexplicit-relocs -mflush-func=grub_cpu_flush_cache
CFLAGS_PLATFORM += -march=mips3 -mexplicit-relocs
CPPFLAGS_PLATFORM = -DUSE_ASCII_FAILBACK
CCASFLAGS_PLATFORM = -march=mips3
endif
if COND_mips
CFLAGS_PLATFORM += -mflush-func=grub_cpu_flush_cache
endif
if COND_sparc64_ieee1275
CFLAGS_PLATFORM = -mno-app-regs
CFLAGS_PLATFORM += -mno-app-regs
LDFLAGS_PLATFORM = -melf64_sparc -mno-relax
endif
# Other options
CPPFLAGS_DEFAULT = -DGRUB_FILE=\"$(subst $(srcdir),,$<)\"
CPPFLAGS_DEFAULT = -DGRUB_FILE=\"$(subst $(srcdir)/,,$<)\"
CPPFLAGS_DEFAULT += -I$(builddir)
CPPFLAGS_DEFAULT += -I$(srcdir)
CPPFLAGS_DEFAULT += -I$(top_builddir)
@ -121,6 +126,7 @@ pkglib_SCRIPTS =
noinst_PROGRAMS =
grubconf_SCRIPTS =
noinst_LIBRARIES =
dist_noinst_DATA =
TESTS =
EXTRA_DIST =

View File

@ -5,6 +5,11 @@ EXTRA_DIST += gentpl.py
EXTRA_DIST += Makefile.tpl
EXTRA_DIST += Makefile.util.def
EXTRA_DIST += unicode
EXTRA_DIST += util/import_gcry.py
EXTRA_DIST += util/import_unicode.py
EXTRA_DIST += docs/man
EXTRA_DIST += docs/grub.cfg
@ -20,6 +25,7 @@ EXTRA_DIST += grub-core/gensymlist.sh
EXTRA_DIST += grub-core/genemuinit.sh
EXTRA_DIST += grub-core/genemuinitheader.sh
EXTRA_DIST += grub-core/lib/libgcrypt/cipher
EXTRA_DIST += $(shell find $(top_srcdir)/include -name '*.h')
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/lib -name '*.h')
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/gnulib -name '*.h')

View File

@ -176,6 +176,19 @@ AC_SUBST(host_kernel)
AC_SUBST(target_cpu)
AC_SUBST(platform)
# Define default variables
case "$host_os" in
netbsd* | openbsd*)
# Because /boot is used for the boot block in NetBSD and OpenBSD,
bootdirname='' ;;
*) bootdirname='boot' ;;
esac
bootdirname=`echo "$bootdirname" | sed "$program_transform_name"`
AC_SUBST(bootdirname)
grubdirname=`echo "$PACKAGE" | sed "$program_transform_name"`
AC_SUBST(grubdirname)
#
# Checks for build programs.
#
@ -264,8 +277,16 @@ else
fi
# Check for functions and headers.
AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf)
AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h)
AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getextmntent)
AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h)
AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default
#include <sys/param.h>
#include <sys/mount.h>])
AC_CHECK_MEMBERS([struct statfs.f_mntfromname],,,[$ac_includes_default
#include <sys/param.h>
#include <sys/mount.h>])
# For opendisk() and getrawpartition() on NetBSD.
# Used in util/deviceiter.c and in util/hostdisk.c.
@ -586,6 +607,12 @@ AC_ARG_ENABLE([efiemu],
if test x"$enable_efiemu" = xno ; then
efiemu_excuse="explicitly disabled"
fi
if test x"$target_cpu" != xi386 ; then
efiemu_excuse="only available on i386"
fi
if test x"$platform" = xefi ; then
efiemu_excuse="not available on efi"
fi
if test x"$efiemu_excuse" = x ; then
AC_CACHE_CHECK([whether options required for efiemu work], grub_cv_cc_efiemu, [
CFLAGS="$CFLAGS -m64 -mcmodel=large -mno-red-zone -nostdlib"
@ -671,8 +698,8 @@ if test x"$missing_ncurses" = xtrue ; then
AC_MSG_ERROR([grub-emu can't be compiled without ncurses])
fi
if test x"$enable_grub_emu_usb" = xno ; then
grub_emu_usb_excuse="explicitly disabled"
if test x"$enable_grub_emu_usb" != xyes ; then
grub_emu_usb_excuse="not enabled"
fi
if test x"$enable_grub_emu_pci" = xyes ; then
@ -756,19 +783,6 @@ AC_SUBST([enable_grub_emu_usb])
AC_SUBST([enable_grub_emu_pci])
fi
AC_ARG_ENABLE([grub-fstest],
[AS_HELP_STRING([--enable-grub-fstest],
[build and install the `grub-fstest' debugging utility (default=guessed)])])
if test x"$enable_grub_fstest" = xno ; then
grub_fstest_excuse="explicitly disabled"
fi
if test x"$grub_fstest_excuse" = x ; then
enable_grub_fstest=yes
else
enable_grub_fstest=no
fi
AC_SUBST([enable_grub_fstest])
AC_ARG_ENABLE([grub-mkfont],
[AS_HELP_STRING([--enable-grub-mkfont],
[build and install the `grub-mkfont' utility (default=guessed)])])
@ -782,12 +796,12 @@ if test x"$grub_mkfont_excuse" = x ; then
if test "x$FREETYPE" = x ; then
grub_mkfont_excuse=["need freetype2 library"]
fi
freetype_cflags=`freetype-config --cflags`
freetype_libs=`freetype-config --libs`
fi
if test x"$grub_mkfont_excuse" = x ; then
# Check for freetype libraries.
freetype_cflags=`freetype-config --cflags`
freetype_libs=`freetype-config --libs`
SAVED_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $freetype_cflags"
AC_CHECK_HEADERS([ft2build.h], [],
@ -816,12 +830,23 @@ fi
if test x"$device_mapper_excuse" = x ; then
# Check for device-mapper library.
AC_CHECK_LIB([devmapper], [dm_task_create],
[LIBDEVMAPPER="-ldevmapper"
AC_DEFINE([HAVE_DEVICE_MAPPER], [1],
[Define to 1 if you have the devmapper library.])],
AC_CHECK_LIB([devmapper], [dm_task_create], [],
[device_mapper_excuse="need devmapper library"])
fi
if test x"$device_mapper_excuse" = x ; then
# Check for device-mapper library.
AC_CHECK_LIB([devmapper], [dm_log_with_errno_init],
[],
[device_mapper_excuse="need devmapper library"])
fi
if test x"$device_mapper_excuse" = x ; then
LIBDEVMAPPER="-ldevmapper";
AC_DEFINE([HAVE_DEVICE_MAPPER], [1],
[Define to 1 if you have the devmapper library.])
fi
AC_SUBST([LIBDEVMAPPER])
AC_CHECK_LIB([zfs], [libzfs_init],
@ -836,24 +861,14 @@ AC_CHECK_LIB([nvpair], [nvlist_print],
[Define to 1 if you have the NVPAIR library.])],)
AC_SUBST([LIBNVPAIR])
LIBS=""
pkglibrootdir='$(libdir)'/`echo $PACKAGE | sed "$program_transform_name"`
AC_SUBST(pkglibrootdir)
AC_SUBST([FONT_SOURCE])
AS_IF([test x$target_cpu = xi386 -a x$platform = xpc],
[AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x8200)])
AS_IF([test x$target_cpu = xi386 -a x$platform = xcoreboot],
[AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x8200)])
AS_IF([test x$target_cpu = xi386 -a x$platform = xmultiboot],
[AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x8200)])
AS_IF([test x$target_cpu = xmips -a x$platform = xyeeloong],
[AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x80200000)])
AS_IF([test x$target_cpu = xpowerpc -a x$platform = xieee1275],
[AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x200000)])
AS_IF([test x$target_cpu = xi386 -a x$platform = xqemu],
[AC_SUBST([GRUB_BOOT_MACHINE_LINK_ADDR], 0xffe00)])
AS_IF([test x$target_cpu = xi386 -a x$platform = xieee1275],
[AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x10000)])
AS_IF([test x$TARGET_APPLE_CC = x1],
[AC_SUBST([USE_APPLE_CC_FIXES], yes)])
@ -873,6 +888,7 @@ AM_CONDITIONAL([COND_mips_yeeloong], [test x$target_cpu = xmips -a x$platform =
AM_CONDITIONAL([COND_mips_qemu_mips], [test x$target_cpu = xmips -a x$platform = xqemu_mips])
AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275])
AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275])
AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips])
AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd])
AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux])
@ -886,7 +902,6 @@ AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes])
AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes])
AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes])
AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x])
AM_CONDITIONAL([COND_GRUB_FSTEST], [test x$enable_grub_fstest = xyes])
AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x])
AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1])
AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes])
@ -912,6 +927,7 @@ AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([grub-core/Makefile])
AC_CONFIG_FILES([po/Makefile])
AC_CONFIG_FILES([docs/Makefile])
AC_CONFIG_FILES([util/bash-completion.d/Makefile])
AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h])
AC_OUTPUT
@ -936,6 +952,11 @@ else
echo PCI support for grub-emu: No "($grub_emu_pci_excuse)"
fi
fi
if test x"$device_mapper_excuse" = x ; then
echo With devmapper support: Yes
else
echo With devmapper support: No "($device_mapper_excuse)"
fi
if [ x"$enable_mm_debug" = xyes ]; then
echo With memory debugging: Yes
else
@ -946,11 +967,6 @@ echo efiemu runtime: Yes
else
echo efiemu runtime: No "($efiemu_excuse)"
fi
if [ x"$grub_fstest_excuse" = x ]; then
echo grub-fstest: Yes
else
echo grub-fstest: No "($grub_fstest_excuse)"
fi
if [ x"$grub_mkfont_excuse" = x ]; then
echo grub-mkfont: Yes
else

View File

@ -46,6 +46,8 @@ Invariant Sections.
@subtitle The GRand Unified Bootloader, version @value{VERSION}, @value{UPDATED}.
@author Gordon Matzigkeit
@author Yoshinori K. Okuji
@author Colin Watson
@author Colin D. Bennett
@c The following two commands start the copyright page.
@page
@vskip 0pt plus 1filll
@ -77,6 +79,7 @@ This edition documents version @value{VERSION}.
* Installation:: Installing GRUB on your drive
* Booting:: How to boot different operating systems
* Configuration:: Writing your own configuration file
* Theme file format:: Format of GRUB theme files
* Network:: Downloading OS images from a network
* Serial terminal:: Using GRUB via a serial line
* Vendor power-on keys:: Changing GRUB behaviour on vendor power-on keys
@ -85,6 +88,7 @@ This edition documents version @value{VERSION}.
* Interface:: The menu and the command-line
* Commands:: The list of available builtin commands
* Security:: Authentication and authorisation
* Supported kernels:: The list of supported kernels
* Troubleshooting:: Error messages produced by GRUB
* Invoking grub-install:: How to use the GRUB installer
* Invoking grub-mkconfig:: Generate a GRUB configuration file
@ -963,7 +967,6 @@ need to write the whole thing by hand.
* Simple configuration:: Recommended for most users
* Shell-like scripting:: For power users and developers
* Embedded configuration:: Embedding a configuration file into GRUB
* Themes:: Graphical menu themes
@end menu
@ -1125,7 +1128,6 @@ The image will be scaled if necessary to fit the screen.
@item GRUB_THEME
Set a theme for use with the @samp{gfxterm} graphical terminal.
@xref{Themes}.
@item GRUB_GFXPAYLOAD_LINUX
Set to @samp{text} to force the Linux kernel to boot in normal text mode,
@ -1225,8 +1227,10 @@ The @samp{$} character retains its special meaning within double quotes.
The backslash retains its special meaning only when followed by one of the
following characters: @samp{$}, @samp{"}, @samp{\}, or newline. A
backslash-newline pair is treated as a line continuation (that is, it is
removed from the input stream and effectively ignored). A double quote may
be quoted within double quotes by preceding it with a backslash.
removed from the input stream and effectively ignored@footnote{Currently a
backslash-newline pair within a variable name is not handled properly, so
use this feature with some care.}). A double quote may be quoted within
double quotes by preceding it with a backslash.
@heading Variable expansion
@ -1238,11 +1242,15 @@ which could be interpreted as part of the name.
Normal variable names begin with an alphabetic character, followed by zero
or more alphanumeric characters.
Positional variable names consist of one or more digits. These are reserved
for future expansion.
Positional variable names consist of one or more digits. They represent
parameters passed to function calls, with @samp{$1} representing the first
parameter, and so on.
The special variable name @samp{?} expands to the exit status of the most
recently executed command.
recently executed command. When positional variable names are active, other
special variable names @samp{@@}, @samp{*} and @samp{#} are defined and they
expand to all positional parameters with necessary quoting, positional
parameters without any quoting, and positional parameter count respectively.
@heading Comments
@ -1303,6 +1311,45 @@ the body.
@xref{menuentry}.
@end table
@heading Built-in Commands
Some built-in commands are also provided by GRUB script to help script
writers perform actions that are otherwise not possible. For example, these
include commands to jump out of a loop without fully completing it, etc.
@table @asis
@item break [@code{n}]
Exit from within a @code{for}, @code{while}, or @code{until} loop. If
@code{n} is specified, break @code{n} levels. @code{n} must be greater than
or equal to 1. If @code{n} is greater than the number of enclosing loops,
all enclosing loops are exited. The return value is 0 unless @code{n} is
not greater than or equal to 1.
@item continue [@code{n}]
Resume the next iteration of the enclosing @code{for}, @code{while} or
@code{until} loop. If @code{n} is specified, resume at the @code{n}th
enclosing loop. @code{n} must be greater than or equal to 1. If @code{n}
is greater than the number of enclosing loops, the last enclosing loop (the
@dfn{top-level} loop) is resumed. The return value is 0 unless @code{n} is
not greater than or equal to 1.
@item return [@code{n}]
Causes a function to exit with the return value specified by @code{n}. If
@code{n} is omitted, the return status is that of the last command executed
in the function body. If used outside a function the return status is
false.
@item shift [@code{n}]
The positional parameters from @code{n}+1 @dots{} are renamed to
@code{$1}@dots{}. Parameters represented by the numbers @code{$#} down to
@code{$#}-@code{n}+1 are unset. @code{n} must be a non-negative number less
than or equal to @code{$#}. If @code{n} is 0, no parameters are changed.
If @code{n} is not given, it is assumed to be 1. If @code{n} is greater
than @code{$#}, the positional parameters are not changed. The return
status is greater than zero if @code{n} is greater than @code{$#} or less
than zero; otherwise 0.
@end table
@node Embedded configuration
@section Embedding a configuration file into GRUB
@ -1371,9 +1418,372 @@ fi
The embedded configuration file may not contain menu entries directly, but
may only read them from elsewhere using @command{configfile}.
@node Theme file format
@chapter Theme file format
@section Introduction
The GRUB graphical menu supports themes that can customize the layout and
appearance of the GRUB boot menu. The theme is configured through a plain
text file that specifies the layout of the various GUI components (including
the boot menu, timeout progress bar, and text messages) as well as the
appearance using colors, fonts, and images. Example is available in docs/example_theme.txt
@section Theme Elements
@subsection Colors
Colors can be specified in several ways:
@itemize
@item HTML-style ``#RRGGBB'' or ``#RGB'' format, where *R*, *G*, and *B* are hexadecimal digits (e.g., ``#8899FF'')
@item as comma-separated decimal RGB values (e.g., ``128, 128, 255'')
@item with ``SVG 1.0 color names'' (e.g., ``cornflowerblue'') which must be specified in lowercase.
@end itemize
@subsection Fonts
The fonts GRUB uses ``PFF2 font format'' bitmap fonts. Fonts are specified
with full font names. Currently there is no
provision for a preference list of fonts, or deriving one font from another.
Fonts are loaded with the ``loadfont'' command in GRUB. To see the list of
loaded fonts, execute the ``lsfonts'' command. If there are too many fonts to
fit on screen, do ``set pager=1'' before executing ``lsfonts''.
@subsection Progress Bar
@float Figure, Pixmap-styled progress bar
@c @image{Theme_progress_bar,,,,.png}
@end float
@float Figure, Plain progress bar, drawn with solid color.
@c @image{Theme_progress_bar_filled,,,,.png}
@end float
Progress bars are used to display the remaining time before GRUB boots the
default menu entry. To create a progress bar that will display the remaining
time before automatic boot, simply create a ``progress_bar'' component with
the id ``__timeout__''. This indicates to GRUB that the progress bar should
be updated as time passes, and it should be made invisible if the countdown to
automatic boot is interrupted by the user.
Progress bars may optionally have text displayed on them. This is controlled
through the ``show_text'' property, which can be set to either ``true'' or
``false'' to control whether text is displayed. When GRUB is counting down to
automatic boot, the text informs the user of the number of seconds remaining.
@subsection Circular Progress Indicator
@c @image{Theme_circular_progress,,,,.png}
The circular progress indicator functions similarly to the progress bar. When
given an id of ``__timeout__'', GRUB updates the circular progress indicator's
value to indicate the time remaining. For the circular progress indicator,
there are two images used to render it: the *center* image, and the *tick*
image. The center image is rendered in the center of the component, while the
tick image is used to render each mark along the circumference of the
indicator.
@subsection Labels
Text labels can be placed on the boot screen. The font, color, and horizontal
alignment can be specified for labels. If a label is given the id
``__timeout__'', then the ``text'' property for that label is also updated
with a message informing the user of the number of seconds remaining until
automatic boot. This is useful in case you want the text displayed somewhere
else instead of directly on the progress bar.
@subsection Boot Menu
@c @image{Theme_boot_menu,,,,.png}
The boot menu where GRUB displays the menu entries from the ``grub.cfg'' file.
It is a list of items, where each item has a title and an optional icon. The
icon is selected based on the *classes* specified for the menu entry. If
there is a PNG file named ``myclass.png'' in the ``grub/themes/icons''
directory, it will be displayed for items which have the class *myclass*. The
boot menu can be customized in several ways, such as the font and color used
for the menu entry title, and by specifying styled boxes for the menu itself
and for the selected item highlight.
@subsection Styled Boxes
One of the most important features for customizing the layout is the use of
*styled boxes*. A styled box is composed of 9 rectangular (and potentially
empty) regions, which are used to seamlessly draw the styled box on screen:
@multitable @columnfractions 0.3 0.3 0.3
@item Northwest (nw) @tab North (n) @tab Northeast (ne)
@item West (w) @tab Center (c) @tab East (e)
@item Southwest (sw) @tab South (s) @tab Southeast (se)
@end multitable
To support any size of box on screen, the center slice and the slices for the
top, bottom, and sides are all scaled to the correct size for the component on
screen, using the following rules:
@enumerate
@item The edge slices (north, south, east, and west) are scaled in the direction of the edge they are adjacent to. For instance, the west slice is scaled vertically.
@item The corner slices (northwest, northeast, southeast, and southwest) are not scaled.
@item The center slice is scaled to fill the remaining space in the middle.
@end enumerate
As an example of how an image might be sliced up, consider the styled box
used for a terminal view.
@float Figure, An example of the slices (in red) used for a terminal window. This drawing was created and sliced in Inkscape_, as the next section explains.
@c @image{Box_slice_example_terminal,,,,.png}
@end float
@subsection Creating Styled Box Images
The Inkscape_ scalable vector graphics editor is a very useful tool for
creating styled box images. One process that works well for slicing a drawing
into the necessary image slices is:
@enumerate
@item Create or open the drawing you'd like use.
@item Create a new layer on the top of the layer stack. Make it visible. Select this layer as the current layer.
@item Draw 9 rectangles on your drawing where you'd like the slices to be. Clear the fill option, and set the stroke to 1 pixel wide solid stroke. The corners of the slices must meet precisely; if it is off by a single pixel, it will probably be evident when the styled box is rendered in the GRUB menu. You should probably go to File | Document Properties | Grids and enable a grid or create a guide (click on one of the rulers next to the drawing and drag over the drawing; release the mouse button to place the guide) to help place the rectangles precisely.
@item Right click on the center slice rectangle and choose Object Properties. Change the "Id" to ``slice_c`` and click Set. Repeat this for the remaining 8 rectangles, giving them Id values of ``slice_n``, ``slice_ne``, ``slice_e``, and so on according to the location.
@item Save the drawing.
@item Select all the slice rectangles. With the slice layer selected, you can simply press Ctrl+A to select all rectangles. The status bar should indicate that 9 rectangles are selected.
@item Click the layer hide icon for the slice layer in the layer palette. The rectangles will remain selected, even though they are hidden.
@item Choose File | Export Bitmap and check the *Batch export 9 selected objects* box. Make sure that *Hide all except selected* is unchecked. click *Export*. This will create PNG files in the same directory as the drawing, named after the slices. These can now be used for a styled box in a GRUB theme.
@end enumerate
@section Theme File Manual
The theme file is a plain text file. Lines that begin with ``#`` are ignored
and considered comments. (Note: This may not be the case if the previous line
ended where a value was expected.)
The theme file contains two types of statements:
@enumerate
@item Global properties.
@item Component construction.
@end enumerate
@subsection Global Properties
@subsection Format
Global properties are specified with the simple format:
@itemize
@item name1: value1
@item name2: "value which may contain spaces"
@item name3: #88F
@end itemize
In this example, name3 is assigned a color value.
@subsection Global Property List
@multitable @columnfractions 0.3 0.6
@item title-text @tab Specifies the text to display at the top center of the screen as a title.
@item title-font @tab Defines the font used for the title message at the top of the screen.
@item title-color @tab Defines the color of the title message.
@item message-font @tab Defines the font used for messages, such as when GRUB is unable to automatically boot an entry.
@item message-color @tab Defines the color of the message text.
@item message-bg-color @tab Defines the background color of the message text area.
@item desktop-image @tab Specifies the image to use as the background. It will be scaled to fit the screen size.
@item desktop-color @tab Specifies the color for the background if *desktop-image* is not specified.
@item terminal-box @tab Specifies the file name pattern for the styled box slices used for the command line terminal window. For example, ``terminal-box: terminal_*.png'' will use the images ``terminal_c.png`` as the center area, ``terminal_n.png`` as the north (top) edge, ``terminal_nw.png`` as the northwest (upper left) corner, and so on. If the image for any slice is not found, it will simply be left empty.
@end multitable
@subsection Component Construction
Greater customizability comes is provided by components. A tree of components
forms the user interface. *Containers* are components that can contain other
components, and there is always a single root component which is an instance
of a *canvas* container.
Components are created in the theme file by prefixing the type of component
with a '+' sign:
@code{ + label @{ text="GRUB" font="aqui 11" color="#8FF" @} }
properties of a component are specified as "name = value" (whitespace
surrounding tokens is optional and is ignored) where *value* may be:
@itemize
@item a single word (e.g., ``align = center``, ``color = #FF8080``),
@item a quoted string (e.g., ``text = "Hello, World!"``), or
@item a tuple (e.g., ``preferred_size = (120, 80)``).
@end itemize
@subsection Component List
The following is a list of the components and the properties they support.
@itemize
@item label
A label displays a line of text.
Properties:
@multitable @columnfractions 0.2 0.7
@item text @tab The text to display.
@item font @tab The font to use for text display.
@item color @tab The color of the text.
@item align @tab The horizontal alignment of the text within the component. Options are ``left``, ``center``, and ``right``.
@end multitable
@item image
A component that displays an image. The image is scaled to fit the
component, although the preferred size defaults to the image's original
size unless the ``preferred_size`` property is explicitly set.
Properties:
@multitable @columnfractions 0.2 0.7
@item file @tab The full path to the image file to load.
@end multitable
@item progress_bar
Displays a horizontally oriented progress bar. It can be rendered using
simple solid filled rectangles, or using a pair of pixmap styled boxes.
Properties:
@multitable @columnfractions 0.2 0.7
@item fg_color @tab The foreground color for plain solid color rendering.
@item bg_color @tab The background color for plain solid color rendering.
@item border_color @tab The border color for plain solid color rendering.
@item text_color @tab The text color.
@item show_text @tab Boolean value indicating whether or not text should be displayed on the progress bar. If set to *false*, then no text will be displayed on the bar. If set to any other value, text will be displayed on the bar.
@item bar_style @tab The styled box specification for the frame of the progress bar. Example: ``progress_frame_*.png``
@item highlight_style @tab The styled box specification for the highlighted region of the progress bar. This box will be used to paint just the highlighted region of the bar, and will be increased in size as the bar nears completion. Example: ``progress_hl_*.png``.
@item text @tab The text to display on the progress bar. If the progress bar's ID is set to ``__timeout__``, then GRUB will updated this property with an informative message as the timeout approaches.
@item value @tab The progress bar current value. Normally not set manually.
@item start @tab The progress bar start value. Normally not set manually.
@item end @tab The progress bar end value. Normally not set manually.
@end multitable
@item circular_progress
Displays a circular progress indicator. The appearance of this component
is determined by two images: the *center* image and the *tick* image. The
center image is generally larger and will be drawn in the center of the
component. Around the circumference of a circle within the component, the
tick image will be drawn a certain number of times, depending on the
properties of the component.
Properties:
@multitable @columnfractions 0.3 0.6
@item center_bitmap
@tab The file name of the image to draw in the center of the component.
@item tick_bitmap
@tab The file name of the image to draw for the tick marks.
@item num_ticks
@tab The number of ticks that make up a full circle.
@item ticks_disappear
@tab Boolean value indicating whether tick marks should progressively appear,
or progressively disappear as *value* approaches *end*. Specify
``true`` or ``false``.
@item value
@tab The progress indicator current value. Normally not set manually.
@item start
@tab The progress indicator start value. Normally not set manually.
@item end
@tab The progress indicator end value. Normally not set manually.
@end multitable
@item boot_menu
Displays the GRUB boot menu. It allows selecting items and executing them.
Properties:
@multitable @columnfractions 0.4 0.5
@item item_font
@tab The font to use for the menu item titles.
@item selected_item_font
@tab The font to use for the selected menu item, or ``inherit`` (the default)
to use ``item_font`` for the selected menu item as well.
@item item_color
@tab The color to use for the menu item titles.
@item selected_item_color
@tab The color to use for the selected menu item, or ``inherit`` (the default)
to use ``item_color`` for the selected menu item as well.
@item icon_width
@tab The width of menu item icons. Icons are scaled to the specified size.
@item icon_height
@tab The height of menu item icons.
@item item_height
@tab The height of each menu item in pixels.
@item item_padding
@tab The amount of space in pixels to leave on each side of the menu item
contents.
@item item_icon_space
@tab The space between an item's icon and the title text, in pixels.
@item item_spacing
@tab The amount of space to leave between menu items, in pixels.
@item menu_pixmap_style
@tab The image file pattern for the menu frame styled box.
Example: ``menu_*.png`` (this will use images such as ``menu_c.png``,
``menu_w.png``, `menu_nw.png``, etc.)
@item selected_item_pixmap_style
@tab The image file pattern for the selected item highlight styled box.
@item scrollbar
@tab Boolean value indicating whether the scroll bar should be drawn if the
frame and thumb styled boxes are configured.
@item scrollbar_frame
@tab The image file pattern for the entire scroll bar.
Example: ``scrollbar_*.png``
@item scrollbar_thumb
@tab The image file pattern for the scroll bar thumb (the part of the scroll
bar that moves as scrolling occurs).
Example: ``scrollbar_thumb_*.png``
@item max_items_shown
@tab The maximum number of items to show on the menu. If there are more than
*max_items_shown* items in the menu, the list will scroll to make all
items accessible.
@end multitable
@item canvas
Canvas is a container that allows manual placement of components within it.
It does not alter the positions of its child components. It assigns all
child components their preferred sizes.
@item hbox
The *hbox* container lays out its children from left to right, giving each
one its preferred width. The height of each child is set to the maximum of
the preferred heights of all children.
@item vbox
The *vbox* container lays out its children from top to bottom, giving each
one its preferred height. The width of each child is set to the maximum of
the preferred widths of all children.
@end itemize
@subsection Common properties
The following properties are supported by all components:
@table @samp
@item left
The distance from the left border of container to left border of the object in either of three formats:
@multitable @columnfractions 0.2 0.7
@item x @tab Value in pixels
@item p% @tab Percentage
@item p%+x @tab mixture of both
@end multitable
@item top
The distance from the left border of container to left border of the object in same format.
@item width
The width of object in same format.
@item height
The height of object in same format.
@item id
The identifier for the component. This can be any arbitrary string.
The ID can be used by scripts to refer to various components in the GUI
component tree. Currently, there is one special ID value that GRUB
recognizes:
@multitable @columnfractions 0.2 0.7
@item ``__timeout__`` @tab Any component with this ID will have its *text*, *start*, *end*, *value*, and *visible* properties set by GRUB when it is counting down to an automatic boot of the default menu entry.
@end multitable
@end table
@node Themes
@section Graphical menu themes
@node Network
@ -1435,7 +1845,7 @@ The boot file name provided by DHCP. Read-only.
The name of the DHCP server responsible for these boot parameters.
Read-only.
@item net_pxe_blksize
@item pxe_blksize
The PXE transfer block size. Read-write, defaults to 512.
@item pxe_default_server
@ -2005,8 +2415,7 @@ The serial port is not used as a communication channel unless the
@command{terminal_input} or @command{terminal_output} command is used
(@pxref{terminal_input}, @pxref{terminal_output}).
This command is only available if GRUB is compiled with serial
support. See also @ref{Serial terminal}.
See also @ref{Serial terminal}.
@end deffn
@ -2497,7 +2906,7 @@ This command is only available on x86 systems.
@node ls
@subsection ls
@deffn Command ls [arg]
@deffn Command ls [arg @dots{}]
List devices or files.
With no arguments, print all devices known to GRUB.
@ -2862,6 +3271,145 @@ adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2}
commands.
@node Supported kernels
@chapter Supported boot targets
X86 support is summarised in following table. ``Yes'' means that kernel works on the given platform, ``crashes'' means an early kernel crash which we hove will be fixed by concerned kernel developpers. ``no'' means GRUB doesn't load given kernel on a given platform. ``headless'' means that the kernel works but lacks console drivers (you can still use serial or network console). In case of ``no'' and ``crashes'' the reason is given in footnote.
@multitable @columnfractions .50 .22 .22
@item @tab BIOS @tab Coreboot
@item BIOS chainloading @tab yes @tab no (1)
@item NTLDR @tab yes @tab no (1)
@item FreeBSD bootloader @tab yes @tab crashes (1)
@item 32-bit kFreeBSD @tab yes @tab crashes (2,6)
@item 64-bit kFreeBSD @tab yes @tab crashes (2,6)
@item 32-bit kNetBSD @tab yes @tab crashes (1)
@item 64-bit kNetBSD @tab yes @tab crashes (2)
@item 32-bit kOpenBSD @tab yes @tab yes
@item 64-bit kOpenBSD @tab yes @tab yes
@item Multiboot @tab yes @tab yes
@item Multiboot2 @tab yes @tab yes
@item 32-bit Linux (legacy protocol) @tab yes @tab no (1)
@item 64-bit Linux (legacy protocol) @tab yes @tab no (1)
@item 32-bit Linux (modern protocol) @tab yes @tab yes
@item 64-bit Linux (modern protocol) @tab yes @tab yes
@item 32-bit XNU @tab yes @tab ?
@item 64-bit XNU @tab yes @tab ?
@item 32-bit EFI chainloader @tab no (3) @tab no (3)
@item 64-bit EFI chainloader @tab no (3) @tab no (3)
@item Appleloader @tab no (3) @tab no (3)
@end multitable
@multitable @columnfractions .50 .22 .22
@item @tab Multiboot @tab Qemu
@item BIOS chainloading @tab no (1) @tab no (1)
@item NTLDR @tab no (1) @tab no (1)
@item FreeBSD bootloader @tab crashes (1) @tab crashes (1)
@item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6)
@item 64-bit kFreeBSD @tab crashes (6) @tab crashes (6)
@item 32-bit kNetBSD @tab crashes (1) @tab crashes (1)
@item 64-bit kNetBSD @tab yes @tab yes
@item 32-bit kOpenBSD @tab yes @tab yes
@item 64-bit kOpenBSD @tab yes @tab yes
@item Multiboot @tab yes @tab yes
@item Multiboot2 @tab yes @tab yes
@item 32-bit Linux (legacy protocol) @tab no (1) @tab no (1)
@item 64-bit Linux (legacy protocol) @tab no (1) @tab no (1)
@item 32-bit Linux (modern protocol) @tab yes @tab yes
@item 64-bit Linux (modern protocol) @tab yes @tab yes
@item 32-bit XNU @tab ? @tab ?
@item 64-bit XNU @tab ? @tab ?
@item 32-bit EFI chainloader @tab no (3) @tab no (3)
@item 64-bit EFI chainloader @tab no (3) @tab no (3)
@item Appleloader @tab no (3) @tab no (3)
@end multitable
@multitable @columnfractions .50 .22 .22
@item @tab 32-bit EFI @tab 64-bit EFI
@item BIOS chainloading @tab no (1) @tab no (1)
@item NTLDR @tab no (1) @tab no (1)
@item FreeBSD bootloader @tab crashes (1) @tab crashes (1)
@item 32-bit kFreeBSD @tab headless @tab headless
@item 64-bit kFreeBSD @tab headless @tab headless
@item 32-bit kNetBSD @tab crashes (1) @tab crashes (1)
@item 64-bit kNetBSD @tab yes @tab yes
@item 32-bit kOpenBSD @tab headless @tab headless
@item 64-bit kOpenBSD @tab headless @tab headless
@item Multiboot @tab yes @tab yes
@item Multiboot2 @tab yes @tab yes
@item 32-bit Linux (legacy protocol) @tab no (1) @tab no (1)
@item 64-bit Linux (legacy protocol) @tab no (1) @tab no (1)
@item 32-bit Linux (modern protocol) @tab yes @tab yes
@item 64-bit Linux (modern protocol) @tab yes @tab yes
@item 32-bit XNU @tab yes @tab yes
@item 64-bit XNU @tab yes (5) @tab yes
@item 32-bit EFI chainloader @tab yes @tab no (4)
@item 64-bit EFI chainloader @tab no (4) @tab yes
@item Appleloader @tab yes @tab yes
@end multitable
@multitable @columnfractions .50 .22 .22
@item @tab IEEE1275
@item BIOS chainloading @tab no (1)
@item NTLDR @tab no (1)
@item FreeBSD bootloader @tab crashes (1)
@item 32-bit kFreeBSD @tab crashes (6)
@item 64-bit kFreeBSD @tab crashes (6)
@item 32-bit kNetBSD @tab crashes (1)
@item 64-bit kNetBSD @tab ?
@item 32-bit kOpenBSD @tab ?
@item 64-bit kOpenBSD @tab ?
@item Multiboot @tab ?
@item Multiboot2 @tab ?
@item 32-bit Linux (legacy protocol) @tab no (1)
@item 64-bit Linux (legacy protocol) @tab no (1)
@item 32-bit Linux (modern protocol) @tab ?
@item 64-bit Linux (modern protocol) @tab ?
@item 32-bit XNU @tab ?
@item 64-bit XNU @tab ?
@item 32-bit EFI chainloader @tab no (3)
@item 64-bit EFI chainloader @tab no (3)
@item Appleloader @tab no (3)
@end multitable
@enumerate
@item Requires BIOS
@item Crashes because the memory at 0x0-0x1000 isn't available
@item EFI only
@item 32-bit and 64-bit EFI have different structures and work in different CPU modes so it's not possible to chainload 32-bit bootloader on 64-bit platform and vice-versa
@item Some modules may need to be disabled
@item Requires ACPI
@end enumerate
PowerPC and Sparc ports support only Linux. MIPS port supports Linux and multiboot2.
@chapter Boot tests
As you have seen in previous chapter the support matrix is pretty big and some of the configurations are only rarely used. To ensure the quality bootchecks are available for all x86 targets except EFI chainloader, Appleloader and XNU. All x86 platforms have bootcheck facility except ieee1275. Multiboot, multiboot2, BIOS chainloader, ntldr and freebsd-bootloader boot targets are tested only with a fake kernel images. Only Linux is tested among the payloads using Linux protocols.
Following variables must be defined:
@multitable @columnfractions .30 .65
@item GRUB_PAYLOADS_DIR @tab directory containing the required kernels
@item GRUB_CBFSTOOL @tab cbfstoll from Coreboot package (for coreboot platform only)
@item GRUB_COREBOOT_ROM @tab empty Coreboot ROM
@item GRUB_QEMU_OPTS @tab additional options to be supplied to QEMU
@end multitable
Required files are:
@multitable @columnfractions .40 .55
@item kfreebsd_env.i386 @tab 32-bit kFreeBSD device hints
@item kfreebsd.i386 @tab 32-bit FreeBSD kernel image
@item kfreebsd.x86_64, kfreebsd_env.x86_64 @tab same from 64-bit kFreeBSD
@item knetbsd.i386 @tab 32-bit NetBSD kernel image
@item knetbsd.miniroot.i386 @tab 32-bit kNetBSD miniroot.kmod.
@item knetbsd.x86_64, knetbsd.miniroot.x86_64 @tab same from 64-bit kNetBSD
@item kopenbsd.i386 @tab 32-bit OpenBSD kernel bsd.rd image
@item kopenbsd.x86_64 @tab same from 64-bit kOpenBSD
@item linux.i386 @tab 32-bit Linux
@item linux.x86_64 @tab 64-bit Linux
@end multitable
@node Troubleshooting
@chapter Error messages produced by GRUB

View File

@ -0,0 +1,3 @@
[NAME]
grub-menulst2cfg \- transform legacy menu.lst into grub.cfg

View File

@ -0,0 +1,2 @@
[NAME]
grub-mklayout \- generate a GRUB keyboard layout file

View File

@ -0,0 +1,2 @@
[NAME]
grub-mknetdir \- prepare a GRUB netboot directory.

View File

@ -10,46 +10,38 @@ GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot",
"powerpc_ieee1275" ]
GROUPS = {}
GROUPS["common"] = GRUB_PLATFORMS[:]
# Groups based on CPU
GROUPS["i386"] = [ "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275" ]
GROUPS["x86_64"] = [ "x86_64_efi" ]
GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"]
GROUPS["x86_efi"] = [ "i386_efi", "x86_64_efi" ]
GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc")
GROUPS["x86_efi_pc"] = GROUPS["x86_efi"] + ["i386_pc"]
GROUPS["x86_noefi"] = GROUPS["x86"][:]; GROUPS["x86_noefi"].remove("i386_efi"); GROUPS["x86_noefi"].remove("x86_64_efi")
GROUPS["i386_noefi"] = GROUPS["i386"][:]; GROUPS["i386_noefi"].remove("i386_efi")
GROUPS["x86_noieee1275"] = GROUPS["x86"][:]; GROUPS["x86_noieee1275"].remove("i386_ieee1275")
GROUPS["i386_noieee1275"] = GROUPS["i386"][:]; GROUPS["i386_noieee1275"].remove("i386_ieee1275")
GROUPS["i386_noefi_noieee1275"] = GROUPS["i386_noefi"][:]; GROUPS["i386_noefi_noieee1275"].remove("i386_ieee1275")
GROUPS["i386_pc_qemu_coreboot"] = ["i386_pc", "i386_qemu", "i386_coreboot"]
GROUPS["i386_coreboot_multiboot"] = ["i386_coreboot", "i386_multiboot"]
GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"]
GROUPS["i386_pc_coreboot_multiboot_qemu"] = ["i386_pc", "i386_coreboot", "i386_multiboot", "i386_qemu"]
GROUPS["mips"] = [ "mips_yeeloong" ]
GROUPS["sparc64"] = [ "sparc64_ieee1275" ]
GROUPS["powerpc"] = [ "powerpc_ieee1275" ]
GROUPS["nosparc64"] = GRUB_PLATFORMS[:]; GROUPS["nosparc64"].remove("sparc64_ieee1275")
GROUPS["x86_noefi_mips"] = GROUPS["x86_noefi"] + GROUPS["mips"]
# Groups based on firmware
GROUPS["x86_efi"] = [ "i386_efi", "x86_64_efi" ]
GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ]
GROUPS["noieee1275"] = GRUB_PLATFORMS[:]
for i in GROUPS["ieee1275"]: GROUPS["noieee1275"].remove(i)
GROUPS["ieee1275_mips"] = GROUPS["ieee1275"] + GROUPS["mips"]
GROUPS["pci"] = GROUPS["x86"] + GROUPS["mips"]
# emu is a special case so many core functionality isn't needed on this platform
GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu")
GROUPS["noemu_noieee1275"] = GRUB_PLATFORMS[:]
for i in ["emu"] + GROUPS["ieee1275"]: GROUPS["noemu_noieee1275"].remove(i)
GROUPS["common"] = GRUB_PLATFORMS[:]
# Groups based on hardware features
GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_yeeloong"]; GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi")
GROUPS["pci"] = GROUPS["x86"] + GROUPS["mips"]
GROUPS["usb"] = GROUPS["pci"]
# If gfxterm is main output console integrate it into kernel
GROUPS["videoinkernel"] = ["mips_yeeloong"]
GROUPS["videomodules"] = GRUB_PLATFORMS[:];
for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i)
# Miscelaneous groups schedulded to disappear in future
GROUPS["nosparc64"] = GRUB_PLATFORMS[:]; GROUPS["nosparc64"].remove("sparc64_ieee1275")
GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"]
GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc")
#
# Create platform => groups reverse map, where groups covering that
@ -423,7 +415,7 @@ chmod a+x [+ name +]
""")
r += gvar_add("CLEANFILES", "[+ name +]")
r += gvar_add("EXTRA_DIST", platform_sources(platform))
r += gvar_add("dist_noinst_DATA", platform_sources(platform))
return r
def module_rules():

View File

@ -58,8 +58,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dl.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/elf.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/elfload.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h
@ -70,35 +68,24 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/list.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/misc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/reader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/symbol.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/types.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/libgcc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
if COND_i386_pc
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/msdos_partition.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/biosdisk.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/boot.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/console.h
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/vga.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/vbe.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
endif
if COND_i386_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/msdos_partition.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/time.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
@ -106,65 +93,34 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
endif
if COND_i386_coreboot
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/msdos_partition.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/boot.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/console.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/init.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
endif
if COND_i386_multiboot
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/msdos_partition.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/boot.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/console.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/init.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
endif
if COND_i386_qemu
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/msdos_partition.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/boot.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/console.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/init.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loader.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/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/msdos_partition.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loader.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
if COND_x86_64_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/msdos_partition.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/time.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h
endif
if COND_mips_yeeloong
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/msdos_partition.h
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
@ -173,35 +129,22 @@ 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/boot.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/msdos_partition.h
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/boot.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/msdos_partition.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h
endif
if COND_emu
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/time.h
KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/types.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gzio.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/menu.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h
if COND_GRUB_EMU_SDL
@ -342,7 +285,6 @@ $(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT)
platform_DATA += $(MOD_FILES)
CLEANFILES += $(MOD_FILES)
if COND_i386_pc
if COND_ENABLE_EFIEMU
efiemu32.o: efiemu/runtime/efiemu.c $(TARGET_OBJ2ELF)
-rm -f $@; \
@ -385,5 +327,3 @@ efiemu64.o: efiemu64_c.o efiemu64_s.o $(TARGET_OBJ2ELEF)
platform_DATA += efiemu32.o efiemu64.o
CLEANFILES += efiemu32.o efiemu64.o efiemu64_c.o efiemu64_s.o
endif
endif

View File

@ -1,5 +1,15 @@
AutoGen definitions Makefile.tpl;
script = {
name = gensyminfo.sh;
common = gensyminfo.sh.in;
};
script = {
name = genmod.sh;
common = genmod.sh.in;
};
kernel = {
name = kernel;
@ -10,20 +20,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)';
@ -36,7 +46,8 @@ kernel = {
x86_64_efi_startup = kern/x86_64/efi/startup.S;
i386_qemu_startup = kern/i386/qemu/startup.S;
i386_ieee1275_startup = kern/i386/ieee1275/startup.S;
i386_coreboot_multiboot_startup = kern/i386/coreboot/startup.S;
i386_coreboot_startup = kern/i386/coreboot/startup.S;
i386_multiboot_startup = kern/i386/coreboot/startup.S;
mips_yeeloong_startup = kern/mips/startup.S;
sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S;
powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S;
@ -65,7 +76,12 @@ kernel = {
noemu_nodist = symlist.c;
noemu_noieee1275 = kern/generic/rtc_get_time_ms.c;
i386_pc = kern/generic/rtc_get_time_ms.c;
x86_efi = kern/generic/rtc_get_time_ms.c;
i386_qemu = kern/generic/rtc_get_time_ms.c;
i386_coreboot = kern/generic/rtc_get_time_ms.c;
i386_multiboot = kern/generic/rtc_get_time_ms.c;
mips_yeeloong = kern/generic/rtc_get_time_ms.c;
ieee1275 = disk/ieee1275/ofdisk.c;
ieee1275 = kern/ieee1275/cmain.c;
@ -74,20 +90,20 @@ kernel = {
ieee1275 = kern/ieee1275/openfw.c;
ieee1275 = term/ieee1275/ofconsole.c;
ieee1275_mips = term/terminfo.c;
ieee1275_mips = term/tparm.c;
ieee1275 = term/terminfo.c;
ieee1275 = term/tparm.c;
mips = term/terminfo.c;
mips = term/tparm.c;
i386 = kern/i386/dl.c;
i386_coreboot_multiboot_qemu = kern/i386/coreboot/init.c;
i386_coreboot_multiboot_qemu = kern/i386/halt.c;
i386_coreboot_multiboot_qemu = term/i386/pc/vga_text.c;
i386_pc_coreboot_multiboot_qemu = term/i386/vga_common.c;
i386_coreboot_multiboot_qemu = term/i386/vga_common.c;
i386_pc = term/i386/vga_common.c;
i386_noefi = kern/i386/misc.S;
x86_noieee1275 = kern/i386/pit.c;
x86 = kern/i386/pit.c;
x86_efi = disk/efi/efidisk.c;
x86_efi = kern/efi/efi.c;
@ -118,33 +134,21 @@ kernel = {
i386_multiboot = kern/i386/multiboot_mmap.c;
i386_multiboot = kern/i386/tsc.c;
i386_ieee1275 = kern/i386/ieee1275/init.c;
i386_ieee1275 = kern/ieee1275/init.c;
mips_yeeloong = term/ns8250.c;
mips_yeeloong = bus/bonito.c;
mips_yeeloong = bus/cs5536.c;
mips_yeeloong = bus/pci.c;
mips_yeeloong = commands/extcmd.c;
mips_yeeloong = font/font.c;
mips_yeeloong = font/font_cmd.c;
mips_yeeloong = io/bufio.c;
mips_yeeloong = kern/mips/cache.S;
mips_yeeloong = kern/mips/dl.c;
mips_yeeloong = kern/mips/init.c;
mips_yeeloong = kern/mips/yeeloong/init.c;
mips_yeeloong = lib/arg.c;
mips_yeeloong = term/at_keyboard.c;
mips_yeeloong = term/gfxterm.c;
mips_yeeloong = term/serial.c;
mips_yeeloong = video/bitmap.c;
mips_yeeloong = video/bitmap_scale.c;
mips_yeeloong = video/fb/fbblit.c;
mips_yeeloong = video/fb/fbfill.c;
mips_yeeloong = video/fb/fbutil.c;
mips_yeeloong = video/fb/video_fb.c;
mips_yeeloong = video/sm712.c;
mips_yeeloong = video/video.c;
extra_dist = video/sm712_init.c;
mips_yeeloong = commands/keylayouts.c;
powerpc_ieee1275 = kern/ieee1275/init.c;
powerpc_ieee1275 = kern/powerpc/cache.S;
@ -157,6 +161,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;
@ -166,9 +171,25 @@ kernel = {
emu = kern/emu/mm.c;
emu = kern/emu/time.c;
extra_dist = kern/i386/loader.S;
videoinkernel = lib/arg.c;
videoinkernel = term/gfxterm.c;
videoinkernel = commands/extcmd.c;
videoinkernel = font/font.c;
videoinkernel = font/font_cmd.c;
videoinkernel = io/bufio.c;
videoinkernel = video/bitmap.c;
videoinkernel = video/bitmap_scale.c;
videoinkernel = video/fb/fbblit.c;
videoinkernel = video/fb/fbfill.c;
videoinkernel = video/fb/fbutil.c;
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;
};
program = {
@ -180,7 +201,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;
};
@ -193,7 +214,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;
};
@ -305,49 +326,38 @@ module = {
noemu = bus/usb/usbtrans.c;
noemu = bus/usb/usbhub.c;
enable = emu;
enable = i386;
enable = mips_yeeloong;
enable = usb;
emu_condition = COND_GRUB_EMU_USB;
};
module = {
name = usbserial_common;
common = bus/usb/serial/common.c;
enable = emu;
enable = i386_pc;
enable = mips_yeeloong;
emu_condition = COND_GRUB_EMU_USB;
enable = usb;
};
module = {
name = usbserial_pl2303;
common = bus/usb/serial/pl2303.c;
enable = emu;
enable = i386_pc;
enable = mips_yeeloong;
emu_condition = COND_GRUB_EMU_USB;
enable = usb;
};
module = {
name = usbserial_ftdi;
common = bus/usb/serial/ftdi.c;
enable = emu;
enable = i386_pc;
enable = mips_yeeloong;
emu_condition = COND_GRUB_EMU_USB;
enable = usb;
};
module = {
name = uhci;
common = bus/usb/uhci.c;
enable = i386_pc;
enable = x86;
};
module = {
name = ohci;
common = bus/usb/ohci.c;
enable = i386_pc;
enable = mips_yeeloong;
enable = pci;
};
module = {
@ -361,6 +371,7 @@ module = {
enable = x86_efi;
enable = i386_ieee1275;
enable = i386_coreboot;
enable = i386_multiboot;
emu_condition = COND_GRUB_EMU_PCI;
};
@ -379,9 +390,8 @@ library = {
module = {
name = cmostest;
i386 = commands/i386/cmostest.c;
enable = i386_pc;
enable = i386_coreboot;
common = commands/i386/cmostest.c;
enable = cmos;
};
module = {
@ -393,6 +403,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)';
@ -401,12 +412,43 @@ module = {
module = {
name = acpi;
i386 = 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;
i386_multiboot = commands/i386/pc/acpi.c;
enable = x86_efi;
enable = i386_pc;
enable = i386_coreboot;
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 = {
@ -418,6 +460,7 @@ module = {
name = boot;
common = commands/boot.c;
i386_pc = lib/i386/pc/biosnum.c;
enable = videomodules;
};
module = {
@ -486,6 +529,16 @@ 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;
x86_efi = lib/efi/halt.c;
ieee1275 = lib/ieee1275/halt.c;
emu = lib/emu/halt.c;
};
module = {
@ -497,7 +550,7 @@ module = {
name = hdparm;
common = commands/hdparm.c;
common = lib/hexdump.c;
enable = i386_pc;
enable = pci;
};
module = {
@ -542,8 +595,7 @@ module = {
name = lspci;
common = commands/lspci.c;
enable = x86;
enable = mips;
enable = pci;
};
module = {
@ -655,22 +707,14 @@ module = {
module = {
name = usbtest;
common = commands/usbtest.c;
enable = i386_pc;
enable = mips_yeeloong;
enable = usb;
enable = emu;
emu_condition = COND_GRUB_EMU_USB;
};
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 = {
@ -731,15 +775,13 @@ module = {
module = {
name = ata;
common = disk/ata.c;
enable = x86;
enable = mips;
enable = pci;
};
module = {
name = ata_pthru;
common = disk/ata_pthru.c;
enable = x86;
enable = mips_yeeloong;
enable = pci;
};
module = {
@ -751,8 +793,7 @@ module = {
module = {
name = usbms;
common = disk/usbms.c;
enable = i386_pc;
enable = mips_yeeloong;
enable = usb;
enable = emu;
emu_condition = COND_GRUB_EMU_USB;
};
@ -765,19 +806,23 @@ module = {
module = {
name = efiemu;
i386_pc = efiemu/main.c;
i386_pc = efiemu/i386/loadcore32.c;
i386_pc = efiemu/i386/loadcore64.c;
common = efiemu/main.c;
common = efiemu/i386/loadcore32.c;
common = efiemu/i386/loadcore64.c;
i386_pc = efiemu/i386/pc/cfgtables.c;
i386_pc = efiemu/mm.c;
i386_pc = efiemu/loadcore_common.c;
i386_pc = efiemu/symbols.c;
i386_pc = efiemu/loadcore32.c;
i386_pc = efiemu/loadcore64.c;
i386_pc = efiemu/prepare32.c;
i386_pc = efiemu/prepare64.c;
i386_pc = efiemu/pnvram.c;
i386_pc = efiemu/i386/coredetect.c;
i386_coreboot = efiemu/i386/pc/cfgtables.c;
i386_multiboot = efiemu/i386/pc/cfgtables.c;
i386_ieee1275 = efiemu/i386/nocfgtables.c;
i386_qemu = efiemu/i386/nocfgtables.c;
common = efiemu/mm.c;
common = efiemu/loadcore_common.c;
common = efiemu/symbols.c;
common = efiemu/loadcore32.c;
common = efiemu/loadcore64.c;
common = efiemu/prepare32.c;
common = efiemu/prepare64.c;
common = efiemu/pnvram.c;
common = efiemu/i386/coredetect.c;
extra_dist = efiemu/prepare.c;
extra_dist = efiemu/loadcore.c;
@ -785,16 +830,17 @@ module = {
extra_dist = efiemu/runtime/efiemu.c;
enable = i386_pc;
enable = i386_coreboot;
enable = i386_ieee1275;
enable = i386_multiboot;
enable = i386_qemu;
};
module = {
name = font;
common = font/font.c;
common = font/font_cmd.c;
enable = emu;
enable = x86;
enable = sparc64;
enable = powerpc;
enable = videomodules;
};
module = {
@ -822,6 +868,11 @@ module = {
common = fs/befs_be.c;
};
module = {
name = btrfs;
common = fs/btrfs.c;
};
module = {
name = cpio;
common = fs/cpio.c;
@ -867,6 +918,11 @@ module = {
common = fs/minix.c;
};
module = {
name = minix2;
common = fs/minix2.c;
};
module = {
name = nilfs2;
common = fs/nilfs2.c;
@ -962,10 +1018,7 @@ module = {
module = {
name = bufio;
common = io/bufio.c;
enable = emu;
enable = x86;
enable = sparc64;
enable = powerpc;
enable = videomodules;
};
module = {
@ -987,26 +1040,35 @@ module = {
module = {
name = relocator;
mips = lib/mips/relocator.c;
mips = lib/mips/relocator_asm.S;
common = lib/relocator.c;
x86 = lib/i386/relocator16.S;
x86 = lib/i386/relocator32.S;
x86 = lib/i386/relocator64.S;
i386 = lib/i386/relocator_asm.S;
x86_64 = lib/x86_64/relocator_asm.S;
x86 = lib/i386/relocator.c;
x86 = lib/i386/relocator_asm.S;
x86 = lib/i386/relocator_backward.S;
extra_dist = lib/relocator.c;
ieee1275 = lib/ieee1275/relocator.c;
x86_efi = lib/efi/relocator.c;
mips = lib/mips/relocator_asm.S;
mips = lib/mips/relocator.c;
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;
};
module = {
name = datetime;
x86_noefi_mips = lib/cmos_datetime.c;
cmos = lib/cmos_datetime.c;
x86_efi = lib/efi/datetime.c;
sparc64_ieee1275 = lib/ieee1275/datetime.c;
powerpc_ieee1275 = lib/ieee1275/datetime.c;
enable = x86;
enable = mips;
enable = sparc64_ieee1275;
enable = powerpc_ieee1275;
enable = noemu;
};
module = {
@ -1022,28 +1084,19 @@ module = {
module = {
name = aout;
common = loader/aout.c;
enable = i386_pc;
enable = i386_qemu;
enable = i386_coreboot;
enable = i386_multiboot;
enable = i386_ieee1275;
enable = x86;
};
module = {
name = bsd;
i386 = loader/i386/bsd.c;
i386 = loader/i386/bsd32.c;
i386 = loader/i386/bsd64.c;
i386 = loader/i386/bsd_helper.S;
i386 = loader/i386/bsd_trampoline.S;
x86 = loader/i386/bsd.c;
x86 = loader/i386/bsd32.c;
x86 = loader/i386/bsd64.c;
extra_dist = loader/i386/bsdXX.c;
extra_dist = loader/i386/bsd_pagetable.c;
enable = i386_pc;
enable = i386_qemu;
enable = i386_coreboot;
enable = i386_multiboot;
enable = x86;
};
module = {
@ -1052,6 +1105,12 @@ module = {
enable = i386_pc;
};
module = {
name = ntldr;
i386_pc = loader/i386/pc/ntldr.c;
enable = i386_pc;
};
module = {
name = multiboot2;
cppflags = "-DGRUB_USE_MULTIBOOT2";
@ -1072,11 +1131,8 @@ module = {
module = {
name = linux;
i386_noefi_noieee1275 = loader/i386/linux.c;
x86_efi = loader/i386/efi/linux.c;
x86_64_efi = loader/i386/linux_trampoline.S;
i386_ieee1275 = loader/i386/ieee1275/linux.c;
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;
@ -1085,16 +1141,15 @@ module = {
module = {
name = xnu;
x86_efi_pc = loader/xnu_resume.c;
x86_efi_pc = loader/i386/xnu.c;
x86_efi_pc = loader/macho32.c;
x86_efi_pc = loader/macho64.c;
x86_efi_pc = loader/macho.c;
x86_efi_pc = loader/xnu.c;
x86 = loader/xnu_resume.c;
x86 = loader/i386/xnu.c;
x86 = loader/macho32.c;
x86 = loader/macho64.c;
x86 = loader/macho.c;
x86 = loader/xnu.c;
extra_dist = loader/machoXX.c;
enable = i386_pc;
enable = x86_efi;
enable = x86;
};
module = {
@ -1113,34 +1168,15 @@ module = {
module = {
name = mmap;
i386_pc = mmap/mmap.c;
i386_pc = mmap/i386/uppermem.c;
i386_pc = mmap/i386/mmap.c;
common = mmap/mmap.c;
x86 = mmap/i386/uppermem.c;
x86 = mmap/i386/mmap.c;
i386_pc = mmap/i386/pc/mmap.c;
i386_pc = mmap/i386/pc/mmap_helper.S;
x86_efi = mmap/mmap.c;
x86_efi = mmap/i386/uppermem.c;
x86_efi = mmap/i386/mmap.c;
x86_efi = mmap/efi/mmap.c;
i386_coreboot = mmap/mmap.c;
i386_coreboot = mmap/i386/uppermem.c;
i386_coreboot = mmap/i386/mmap.c;
i386_multiboot = mmap/mmap.c;
i386_multiboot = mmap/i386/uppermem.c;
i386_multiboot = mmap/i386/mmap.c;
i386_qemu = mmap/mmap.c;
i386_qemu = mmap/i386/uppermem.c;
i386_qemu = mmap/i386/mmap.c;
i386_ieee1275 = mmap/mmap.c;
i386_ieee1275 = mmap/i386/uppermem.c;
i386_ieee1275 = mmap/i386/mmap.c;
mips_yeeloong = mmap/mmap.c;
mips_yeeloong = mmap/mips/yeeloong/uppermem.c;
enable = x86;
@ -1173,6 +1209,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;
@ -1240,10 +1278,7 @@ module = {
module = {
name = gfxterm;
common = term/gfxterm.c;
enable = emu;
enable = x86;
enable = sparc64;
enable = powerpc;
enable = videomodules;
};
module = {
@ -1272,8 +1307,7 @@ module = {
module = {
name = usb_keyboard;
common = term/usb_keyboard.c;
enable = i386_pc;
enable = mips_yeeloong;
enable = usb;
};
module = {
@ -1284,9 +1318,11 @@ module = {
module = {
name = vga_text;
x86 = term/i386/pc/vga_text.c;
x86 = term/i386/vga_common.c;
enable = x86;
common = term/i386/pc/vga_text.c;
common = term/i386/vga_common.c;
enable = i386_pc;
enable = i386_coreboot;
enable = i386_multiboot;
};
module = {
@ -1316,19 +1352,13 @@ module = {
module = {
name = bitmap;
common = video/bitmap.c;
enable = emu;
enable = x86;
enable = sparc64;
enable = powerpc;
enable = videomodules;
};
module = {
name = bitmap_scale;
common = video/bitmap_scale.c;
enable = emu;
enable = x86;
enable = sparc64;
enable = powerpc;
enable = videomodules;
};
module = {
@ -1370,19 +1400,13 @@ module = {
common = video/fb/fbblit.c;
common = video/fb/fbfill.c;
common = video/fb/fbutil.c;
enable = emu;
enable = x86;
enable = sparc64;
enable = powerpc;
enable = videomodules;
};
module = {
name = video;
common = video/video.c;
enable = emu;
enable = x86;
enable = sparc64;
enable = powerpc;
enable = videomodules;
};
module = {
@ -1404,12 +1428,41 @@ module = {
common = hook/datehook.c;
};
script = {
name = gensyminfo.sh;
common = gensyminfo.sh.in;
module = {
name = legacycfg;
common = commands/legacycfg.c;
common = lib/legacy_parse.c;
enable = i386_pc;
enable = emu;
};
script = {
name = genmod.sh;
common = genmod.sh.in;
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

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

File diff suppressed because it is too large Load Diff

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;
};
@ -228,7 +245,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
/* Link all Transfer Descriptors in a list of available Transfer
Descriptors. */
for (i = 0; i < 256; i++)
u->td[i].linkptr = (grub_uint32_t) &u->td[i + 1];
u->td[i].linkptr = (grub_uint32_t) (grub_addr_t) &u->td[i + 1];
u->td[255 - 1].linkptr = 0;
u->tdfree = u->td;
@ -238,20 +255,20 @@ grub_uhci_pci_iter (grub_pci_device_t dev,
/* Setup the frame list pointers. Since no isochronous transfers
are and will be supported, they all point to the (same!) queue
head. */
fp = (grub_uint32_t) u->qh & (~15);
fp = (grub_uint32_t) (grub_addr_t) u->qh & (~15);
/* Mark this as a queue head. */
fp |= 2;
for (i = 0; i < 1024; i++)
u->framelist[i] = fp;
/* Program the framelist address into the UHCI controller. */
grub_uhci_writereg32 (u, GRUB_UHCI_REG_FLBASEADD,
(grub_uint32_t) u->framelist);
(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) (&u->qh[i + 1]) & (~15);
u->qh[i].linkptr = (grub_uint32_t) (grub_addr_t) (&u->qh[i + 1]) & (~15);
/* This is a QH. */
u->qh[i].linkptr |= GRUB_UHCI_LINK_QUEUE_HEAD;
@ -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));
@ -319,7 +335,7 @@ grub_alloc_td (struct grub_uhci *u)
return NULL;
ret = u->tdfree;
u->tdfree = (grub_uhci_td_t) u->tdfree->linkptr;
u->tdfree = (grub_uhci_td_t) (grub_addr_t) u->tdfree->linkptr;
return ret;
}
@ -327,16 +343,18 @@ grub_alloc_td (struct grub_uhci *u)
static void
grub_free_td (struct grub_uhci *u, grub_uhci_td_t td)
{
td->linkptr = (grub_uint32_t) u->tdfree;
td->linkptr = (grub_uint32_t) (grub_addr_t) u->tdfree;
u->tdfree = 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. */
@ -352,7 +370,7 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td,
/* Unlink the queue. */
tdprev = td;
td = (grub_uhci_td_t) td->linkptr2;
td = (grub_uhci_td_t) (grub_addr_t) td->linkptr2;
/* Free the TD. */
grub_free_td (u, tdprev);
@ -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 };
@ -413,14 +433,15 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp,
}
grub_dprintf ("uhci",
"transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%d data=0x%x td=%p\n",
endp, type, addr, toggle, size, data, td);
"transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%lu data=0x%x td=%p\n",
endp, type, addr, toggle, (unsigned long) size, data, td);
/* Don't point to any TD, just terminate. */
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,27 +495,30 @@ 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) td;
td_prev->linkptr = (grub_uint32_t) td;
td_prev->linkptr2 = (grub_uint32_t) (grub_addr_t) td;
td_prev->linkptr = (grub_uint32_t) (grub_addr_t) td;
td_prev->linkptr |= 4;
}
td_prev = 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) 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) (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) (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);
@ -361,14 +311,37 @@ poll_nonroot_hub (grub_usb_device_t dev)
{
grub_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 = 0x%0x, i = %d, status = %08x\n",
(unsigned int) 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,
@ -54,8 +89,8 @@ grub_usb_control_msg (grub_usb_device_t dev,
grub_memcpy ((char *) data, data_in, size);
grub_dprintf ("usb",
"control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%d\n",
reqtype, request, value, index, size);
"control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%lu\n",
reqtype, request, value, index, (unsigned long)size);
/* Create a transfer. */
transfer = grub_malloc (sizeof (*transfer));
@ -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,29 +197,28 @@ 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%02x type=%d\n", size, type);
grub_dprintf ("usb", "bulk: size=0x%02lx type=%d\n", (unsigned long) size,
type);
/* 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)
@ -209,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
@ -229,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. */
@ -247,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;
}
@ -297,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

@ -38,6 +38,7 @@ grub_cmd_crc (grub_command_t cmd __attribute__ ((unused)),
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
grub_file_filter_disable_compression ();
file = grub_file_open (args[0]);
if (! file)
return 0;

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,107 @@
/* systab.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 @@
/* systab.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>
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}
};
@ -80,7 +81,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 +116,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 +172,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 +205,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 +214,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)
{
@ -242,26 +252,22 @@ static grub_extcmd_t cmd, cmd_md5, cmd_sha256, cmd_sha512;
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.",
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_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum, 0,
N_("[-c FILE [-p PREFIX]] "
"[FILE1 [FILE2 ...]]"),
"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."),

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

@ -21,6 +21,8 @@
#include <grub/misc.h>
#include <grub/extcmd.h>
#include <grub/i18n.h>
#include <grub/machine/int.h>
#include <grub/acpi.h>
static const struct grub_arg_option options[] =
{
@ -28,14 +30,80 @@ static const struct grub_arg_option options[] =
{0, 0, 0, 0, 0, 0}
};
static inline void __attribute__ ((noreturn))
stop (void)
{
while (1)
{
asm volatile ("hlt");
}
}
/*
* Halt the system, using APM if possible. If NO_APM is true, don't use
* APM even if it is available.
*/
void
grub_halt (int no_apm)
{
struct grub_bios_int_registers regs;
grub_acpi_halt ();
if (no_apm)
stop ();
/* 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)
stop ();
/* 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 = 0x5301;
regs.ebx = 0;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x15, &regs);
if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
stop ();
/* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */
regs.eax = 0x530E;
regs.ebx = 0;
regs.ecx = 0x0101;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x15, &regs);
if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
stop ();
/* set the power state to off */
regs.eax = 0x5307;
regs.ebx = 1;
regs.ecx = 3;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x15, &regs);
/* shouldn't reach here */
stop ();
}
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);
@ -46,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,781 @@
/*
* 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);
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);
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 __attribute__ ((unused)),
int argc, char **args)
{
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
return legacy_file (args[0]);
}
static grub_err_t
grub_cmd_legacy_configfile (struct grub_command *cmd __attribute__ ((unused)),
int argc, char **args)
{
grub_err_t ret;
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
grub_cls ();
grub_env_context_open (1);
ret = legacy_file (args[0]);
grub_env_context_close ();
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, cmd_kernel, cmd_initrd;
static grub_command_t cmd_password, cmd_check_password, cmd_initrdnounzip;
GRUB_MOD_INIT(legacycfg)
{
cmd_source = grub_register_command ("legacy_source",
grub_cmd_legacy_source,
N_("FILE"), N_("Parse legacy config"));
cmd_configfile = grub_register_command ("legacy_configfile",
grub_cmd_legacy_configfile,
N_("FILE"),
N_("Parse legacy config"));
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_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

@ -105,6 +105,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)
{
@ -211,6 +212,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;
@ -248,15 +250,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;
}
@ -265,8 +269,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,299 @@
/* 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)
{
unsigned i;
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)
{
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)
{
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;
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;
menu->size++;
return GRUB_ERR_NONE;
fail:
grub_free (menu_sourcecode);
for (i = 0; menu_classes && menu_classes[i].name; i++)
grub_free (menu_classes[i].name);
grub_free (menu_classes);
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);
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);
src[len - 1] = ch;
args[argc - 1] = src;
grub_free (prefix);
return r;
}
static grub_extcmd_t cmd;
void
grub_menu_init (void)
{
cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry,
GRUB_COMMAND_FLAG_BLOCKS,
N_("BLOCK"), N_("Define a menuentry."), options);
}
void
grub_menu_fini (void)
{
grub_unregister_extcmd (cmd);
}

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

View File

@ -0,0 +1,155 @@
/* minicmd.c - commands for the rescue mode */
/*
* 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:

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,9 @@
*/
#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>
#include <grub/mm.h>
@ -28,12 +29,228 @@
#include <grub/term.h>
static int cd_drive = 0;
static int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap);
static int grub_biosdisk_get_num_floppies (void)
{
struct grub_bios_int_registers regs;
int drive;
/* reset the disk system first */
regs.eax = 0;
regs.edx = 0;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
for (drive = 0; drive < 2; drive++)
{
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT | GRUB_CPU_INT_FLAGS_CARRY;
regs.edx = drive;
/* call GET DISK TYPE */
regs.eax = 0x1500;
grub_bios_interrupt (0x13, &regs);
if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
break;
/* check if this drive exists */
if (!(regs.eax & 0x300))
break;
}
return drive;
}
/*
* Call IBM/MS INT13 Extensions (int 13 %ah=AH) for DRIVE. DAP
* is passed for disk address packet. If an error occurs, return
* non-zero, otherwise zero.
*/
static int
grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap)
{
struct grub_bios_int_registers regs;
regs.eax = ah << 8;
/* compute the address of disk_address_packet */
regs.ds = (((grub_addr_t) dap) & 0xffff0000) >> 4;
regs.esi = (((grub_addr_t) dap) & 0xffff);
regs.edx = drive;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
return (regs.eax >> 8) & 0xff;
}
/*
* Call standard and old INT13 (int 13 %ah=AH) for DRIVE. Read/write
* NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs,
* return non-zero, otherwise zero.
*/
static int
grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff,
int soff, int nsec, int segment)
{
int ret, i;
/* Try 3 times. */
for (i = 0; i < 3; i++)
{
struct grub_bios_int_registers regs;
/* set up CHS information */
/* set %ch to low eight bits of cylinder */
regs.ecx = (coff << 8) & 0xff00;
/* set bits 6-7 of %cl to high two bits of cylinder */
regs.ecx |= (coff >> 2) & 0xc0;
/* set bits 0-5 of %cl to sector */
regs.ecx |= soff & 0x3f;
/* set %dh to head and %dl to drive */
regs.edx = (drive & 0xff) | ((hoff << 8) & 0xff00);
/* set %ah to AH */
regs.eax = (ah << 8) & 0xff00;
/* set %al to NSEC */
regs.eax |= nsec & 0xff;
regs.ebx = 0;
regs.es = segment;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
/* check if successful */
if (!(regs.flags & GRUB_CPU_INT_FLAGS_CARRY))
return 0;
/* save return value */
ret = regs.eax >> 8;
/* if fail, reset the disk system */
regs.eax = 0;
regs.edx = (drive & 0xff);
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
}
return ret;
}
/*
* Check if LBA is supported for DRIVE. If it is supported, then return
* the major version of extensions, otherwise zero.
*/
static int
grub_biosdisk_check_int13_extensions (int drive)
{
struct grub_bios_int_registers regs;
regs.edx = drive & 0xff;
regs.eax = 0x4100;
regs.ebx = 0x55aa;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY)
return 0;
if ((regs.ebx & 0xffff) != 0xaa55)
return 0;
/* check if AH=0x42 is supported */
if (!(regs.ecx & 1))
return 0;
return (regs.eax >> 8) & 0xff;
}
/*
* Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an
* error occurs, then return non-zero, otherwise zero.
*/
static int
grub_biosdisk_get_diskinfo_standard (int drive,
unsigned long *cylinders,
unsigned long *heads,
unsigned long *sectors)
{
struct grub_bios_int_registers regs;
regs.eax = 0x0800;
regs.edx = drive & 0xff;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
/* Check if unsuccessful. Ignore return value if carry isn't set to
workaround some buggy BIOSes. */
if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) && ((regs.eax & 0xff00) != 0))
return (regs.eax & 0xff00) >> 8;
/* bogus BIOSes may not return an error number */
/* 0 sectors means no disk */
if (!(regs.ecx & 0x3f))
/* XXX 0x60 is one of the unused error numbers */
return 0x60;
/* the number of heads is counted from zero */
*heads = ((regs.edx >> 8) & 0xff) + 1;
*cylinders = (((regs.ecx >> 8) & 0xff) | ((regs.ecx << 2) & 0x0300)) + 1;
*sectors = regs.ecx & 0x3f;
return 0;
}
static int
grub_biosdisk_get_diskinfo_real (int drive, void *drp, grub_uint16_t ax)
{
struct grub_bios_int_registers regs;
regs.eax = ax;
/* compute the address of drive parameters */
regs.esi = ((grub_addr_t) drp) & 0xf;
regs.ds = ((grub_addr_t) drp) >> 4;
regs.edx = drive & 0xff;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
grub_bios_interrupt (0x13, &regs);
/* Check if unsuccessful. Ignore return value if carry isn't set to
workaround some buggy BIOSes. */
if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) && ((regs.eax & 0xff00) != 0))
return (regs.eax & 0xff00) >> 8;
return 0;
}
/*
* Return the cdrom information of DRIVE in CDRP. If an error occurs,
* then return non-zero, otherwise zero.
*/
static int
grub_biosdisk_get_cdinfo_int13_extensions (int drive, void *cdrp)
{
return grub_biosdisk_get_diskinfo_real (drive, cdrp, 0x4b01);
}
/*
* Return the geometry of DRIVE in a drive parameters, DRP. If an error
* occurs, then return non-zero, otherwise zero.
*/
static int
grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp)
{
return grub_biosdisk_get_diskinfo_real (drive, drp, 0x4800);
}
static int
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;
@ -56,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);
@ -107,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

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

@ -17,7 +17,6 @@
*/
#include <grub/efiemu/efiemu.h>
#include <grub/machine/efiemu.h>
#include <grub/command.h>
#define cpuid(num,a,b,c,d) \

View File

@ -1,3 +1,4 @@
/* Register SMBIOS and ACPI tables. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
@ -16,12 +17,14 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_LOADER_MACHINE_HEADER
#define GRUB_LOADER_MACHINE_HEADER 1
#include <grub/err.h>
#include <grub/efiemu/efiemu.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/acpi.h>
/* The symbol shared between the normal mode and rescue mode
loader. */
void grub_rescue_cmd_linux (int argc, char *argv[]);
void grub_rescue_cmd_initrd (int argc, char *argv[]);
#endif /* ! GRUB_LOADER_MACHINE_HEADER */
grub_err_t
grub_machine_efiemu_init_tables (void)
{
return GRUB_ERR_NONE;
}

View File

@ -19,7 +19,6 @@
#include <grub/err.h>
#include <grub/efiemu/efiemu.h>
#include <grub/machine/efiemu.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/acpi.h>

View File

@ -22,7 +22,6 @@
#include <grub/misc.h>
#include <grub/efiemu/efiemu.h>
#include <grub/cpu/efiemu.h>
#include <grub/machine/efiemu.h>
#include <grub/elf.h>
/* ELF symbols and their values */

View File

@ -29,7 +29,6 @@
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/efiemu/efiemu.h>
#include <grub/machine/efiemu.h>
#include <grub/command.h>
#include <grub/i18n.h>
@ -183,22 +182,6 @@ grub_cmd_efiemu_prepare (grub_command_t cmd __attribute__ ((unused)),
int
grub_efiemu_exit_boot_services (grub_efi_uintn_t map_key
__attribute__ ((unused)))
{
/* Nothing to do here yet */
return 1;
}
int
grub_efiemu_finish_boot_services (void)
{
/* Nothing to do here yet */
return 1;
}
/* Load the runtime from the file FILENAME. */
static grub_err_t
grub_efiemu_load_file (const char *filename)

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;
@ -323,6 +324,25 @@ grub_efiemu_get_memory_map (grub_efi_uintn_t *memory_map_size,
return 1;
}
grub_err_t
grub_efiemu_finish_boot_services (grub_efi_uintn_t *memory_map_size,
grub_efi_memory_descriptor_t *memory_map,
grub_efi_uintn_t *map_key,
grub_efi_uintn_t *descriptor_size,
grub_efi_uint32_t *descriptor_version)
{
int val = grub_efiemu_get_memory_map (memory_map_size,
memory_map, map_key,
descriptor_size,
descriptor_version);
if (val == 1)
return GRUB_ERR_NONE;
if (val == -1)
return grub_errno;
return grub_error (GRUB_ERR_IO, "memory map buffer is too small");
}
/* Free everything */
grub_err_t
grub_efiemu_mm_unload (void)
@ -363,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);
}
@ -402,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;
@ -413,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:
@ -433,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

@ -1,4 +0,0 @@
gcc -c -m32 -DELF32 -o efiemu32.o ./efiemu.c -Wall -Werror -nostdlib -O2 -I. -I../../include
gcc -c -m64 -DELF64 -o efiemu64_c.o ./efiemu.c -Wall -Werror -mcmodel=large -O2 -I. -I../../include
gcc -c -m64 -DELF64 -o efiemu64_s.o ./efiemu.S -Wall -Werror -mcmodel=large -O2 -I. -I../../include
ld -o efiemu64.o -r efiemu64_s.o efiemu64_c.o -nostdlib

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

@ -27,6 +27,7 @@
#include <grub/env.h>
#include <grub/machine/pxe.h>
#include <grub/machine/int.h>
#include <grub/machine/memory.h>
#define SEGMENT(x) ((x) >> 4)
@ -40,7 +41,7 @@ struct grub_pxe_disk_data
grub_uint32_t gateway_ip;
};
struct grub_pxenv *grub_pxe_pxenv;
struct grub_pxe_bangpxe *grub_pxe_pxenv;
static grub_uint32_t grub_pxe_your_ip;
static grub_uint32_t grub_pxe_default_server_ip;
static grub_uint32_t grub_pxe_default_gateway_ip;
@ -55,6 +56,51 @@ struct grub_pxe_data
char filename[0];
};
static grub_uint32_t pxe_rm_entry = 0;
static struct grub_pxe_bangpxe *
grub_pxe_scan (void)
{
struct grub_bios_int_registers regs;
struct grub_pxenv *pxenv;
struct grub_pxe_bangpxe *bangpxe;
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
regs.ebx = 0;
regs.ecx = 0;
regs.eax = 0x5650;
regs.es = 0;
grub_bios_interrupt (0x1a, &regs);
if ((regs.eax & 0xffff) != 0x564e)
return NULL;
pxenv = (struct grub_pxenv *) ((regs.es << 4) + (regs.ebx & 0xffff));
if (grub_memcmp (pxenv->signature, GRUB_PXE_SIGNATURE,
sizeof (pxenv->signature))
!= 0)
return NULL;
if (pxenv->version < 0x201)
return NULL;
bangpxe = (void *) ((((pxenv->pxe_ptr & 0xffff0000) >> 16) << 4)
+ (pxenv->pxe_ptr & 0xffff));
if (!bangpxe)
return NULL;
if (grub_memcmp (bangpxe->signature, GRUB_PXE_BANGPXE_SIGNATURE,
sizeof (bangpxe->signature)) != 0)
return NULL;
pxe_rm_entry = bangpxe->rm_entry;
return bangpxe;
}
static int
grub_pxe_iterate (int (*hook) (const char *name))
{
@ -130,7 +176,6 @@ grub_pxe_open (const char *name, grub_disk_t disk)
disk->total_sectors = 0;
disk->id = (unsigned long) data;
disk->has_partitions = 0;
disk->data = data;
return GRUB_ERR_NONE;
@ -202,14 +247,14 @@ grub_pxefs_open (struct grub_file *file, const char *name)
if (curr_file != 0)
{
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2);
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2, pxe_rm_entry);
curr_file = 0;
}
c.c1.server_ip = disk_data->server_ip;
c.c1.gateway_ip = disk_data->gateway_ip;
grub_strcpy ((char *)&c.c1.filename[0], name);
grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1);
grub_pxe_call (GRUB_PXENV_TFTP_GET_FSIZE, &c.c1, pxe_rm_entry);
if (c.c1.status)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
@ -217,7 +262,7 @@ grub_pxefs_open (struct grub_file *file, const char *name)
c.c2.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT);
c.c2.packet_size = grub_pxe_blksize;
grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2);
grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &c.c2, pxe_rm_entry);
if (c.c2.status)
return grub_error (GRUB_ERR_BAD_FS, "open fails");
@ -236,6 +281,7 @@ grub_pxefs_open (struct grub_file *file, const char *name)
}
file->data = data;
file->not_easly_seekable = 1;
grub_memcpy (file_int, file, sizeof (struct grub_file));
curr_file = file_int;
@ -275,14 +321,14 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len)
struct grub_pxenv_tftp_open o;
if (curr_file != 0)
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o);
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &o, pxe_rm_entry);
o.server_ip = disk_data->server_ip;
o.gateway_ip = disk_data->gateway_ip;
grub_strcpy ((char *)&o.filename[0], data->filename);
o.tftp_port = grub_cpu_to_be16 (GRUB_PXE_TFTP_PORT);
o.packet_size = grub_pxe_blksize;
grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &o);
o.packet_size = data->block_size;
grub_pxe_call (GRUB_PXENV_TFTP_OPEN, &o, pxe_rm_entry);
if (o.status)
{
grub_error (GRUB_ERR_BAD_FS, "open fails");
@ -297,7 +343,7 @@ grub_pxefs_read (grub_file_t file, char *buf, grub_size_t len)
while (pn >= data->packet_number)
{
c.buffer_size = data->block_size;
grub_pxe_call (GRUB_PXENV_TFTP_READ, &c);
grub_pxe_call (GRUB_PXENV_TFTP_READ, &c, pxe_rm_entry);
if (c.status)
{
grub_error (GRUB_ERR_BAD_FS, "read fails");
@ -318,7 +364,7 @@ grub_pxefs_close (grub_file_t file)
if (curr_file == file)
{
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c);
grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c, pxe_rm_entry);
curr_file = 0;
}
@ -443,7 +489,7 @@ parse_dhcp_vendor (void *vend, int limit)
static void
grub_pxe_detect (void)
{
struct grub_pxenv *pxenv;
struct grub_pxe_bangpxe *pxenv;
struct grub_pxenv_get_cached_info ci;
struct grub_pxenv_boot_player *bp;
@ -454,7 +500,7 @@ grub_pxe_detect (void)
ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK;
ci.buffer = 0;
ci.buffer_size = 0;
grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci);
grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry);
if (ci.status)
return;

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

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

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

@ -0,0 +1,58 @@
/* 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>
#include "xalloc.h"
#include "xstrndup.h"
char *
base_name (char const *name)
{
char const *base = last_component (name);
size_t length;
/* If there is no last component, then name is a file system root or the
empty string. */
if (! *base)
return xstrndup (name, base_len (name));
/* Collapse a sequence of trailing slashes into one. */
length = base_len (base);
if (ISSLASH (base[length]))
length++;
/* On systems with drive letters, `a/b:c' must return `./b:c' rather
than `b:c' to avoid confusion with a drive letter. On systems
with pure POSIX semantics, this is not an issue. */
if (FILE_SYSTEM_PREFIX_LEN (base))
{
char *p = xmalloc (length + 3);
p[0] = '.';
p[1] = '/';
memcpy (p + 2, base, length);
p[length + 2] = '\0';
return p;
}
/* Finally, copy the basename. */
return xstrndup (base, length);
}

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,38 @@
/* 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>
#include "xalloc.h"
/* Just like mdir_name (dirname-lgpl.c), except, rather than
returning NULL upon malloc failure, here, we report the
"memory exhausted" condition and exit. */
char *
dir_name (char const *file)
{
char *result = mdir_name (file);
if (!result)
xalloc_die ();
return result;
}

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_ */

View File

@ -88,6 +88,15 @@ extern void __error_at_line (int status, int errnum, const char *file_name,
# include <fcntl.h>
# include <unistd.h>
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* Get declarations of the Win32 API functions. */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# endif
/* The gnulib override of fcntl is not needed in this file. */
# undef fcntl
# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P
# ifndef HAVE_DECL_STRERROR_R
"this configure-time declaration test was not run"
@ -104,10 +113,29 @@ extern char *program_name;
# endif /* HAVE_STRERROR_R || defined strerror_r */
#endif /* not _LIBC */
#if !_LIBC
/* Return non-zero if FD is open. */
static inline int
is_open (int fd)
{
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
/* On Win32: The initial state of unassigned standard file descriptors is
that they are open but point to an INVALID_HANDLE_VALUE. There is no
fcntl, and the gnulib replacement fcntl does not support F_GETFL. */
return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE;
# else
# ifndef F_GETFL
# error Please port fcntl to your platform
# endif
return 0 <= fcntl (fd, F_GETFL);
# endif
}
#endif
static inline void
flush_stdout (void)
{
#if !_LIBC && defined F_GETFL
#if !_LIBC
int stdout_fd;
# if GNULIB_FREOPEN_SAFER
@ -124,7 +152,7 @@ flush_stdout (void)
/* POSIX states that fflush (stdout) after fclose is unspecified; it
is safe in glibc, but not on all other platforms. fflush (NULL)
is always defined, but too draconian. */
if (0 <= stdout_fd && 0 <= fcntl (stdout_fd, F_GETFL))
if (0 <= stdout_fd && is_open (stdout_fd))
#endif
fflush (stdout);
}

View File

@ -348,8 +348,6 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
int long_only, struct _getopt_data *d, int posixly_correct)
{
int print_errors = d->opterr;
if (optstring[0] == ':')
print_errors = 0;
if (argc < 1)
return -1;
@ -364,6 +362,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
posixly_correct);
d->__initialized = 1;
}
else if (optstring[0] == '-' || optstring[0] == '+')
optstring++;
if (optstring[0] == ':')
print_errors = 0;
/* Test whether ARGV[optind] points to a non-option argument.
Either it does not have option syntax, or there is an environment flag
@ -633,8 +635,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
char *buf;
if (__asprintf (&buf, _("\
%s: option '%s' requires an argument\n"),
argv[0], argv[d->optind - 1]) >= 0)
%s: option '--%s' requires an argument\n"),
argv[0], pfound->name) >= 0)
{
_IO_flockfile (stderr);
@ -651,8 +653,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
}
#else
fprintf (stderr,
_("%s: option '%s' requires an argument\n"),
argv[0], argv[d->optind - 1]);
_("%s: option '--%s' requires an argument\n"),
argv[0], pfound->name);
#endif
}
d->__nextchar += strlen (d->__nextchar);
@ -736,13 +738,13 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
{
char c = *d->__nextchar++;
char *temp = strchr (optstring, c);
const char *temp = strchr (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*d->__nextchar == '\0')
++d->optind;
if (temp == NULL || c == ':')
if (temp == NULL || c == ':' || c == ';')
{
if (print_errors)
{
@ -864,7 +866,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
pfound = p;
indfound = option_index;
}
else
else if (long_only
|| pfound->has_arg != p->has_arg
|| pfound->flag != p->flag
|| pfound->val != p->val)
/* Second or later nonexact match found. */
ambig = 1;
}
@ -876,7 +881,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
char *buf;
if (__asprintf (&buf, _("%s: option '-W %s' is ambiguous\n"),
argv[0], argv[d->optind]) >= 0)
argv[0], d->optarg) >= 0)
{
_IO_flockfile (stderr);
@ -892,7 +897,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
}
#else
fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"),
argv[0], argv[d->optind]);
argv[0], d->optarg);
#endif
}
d->__nextchar += strlen (d->__nextchar);
@ -955,8 +960,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
char *buf;
if (__asprintf (&buf, _("\
%s: option '%s' requires an argument\n"),
argv[0], argv[d->optind - 1]) >= 0)
%s: option '-W %s' requires an argument\n"),
argv[0], pfound->name) >= 0)
{
_IO_flockfile (stderr);
@ -972,15 +977,17 @@ _getopt_internal_r (int argc, char **argv, const char *optstring,
free (buf);
}
#else
fprintf (stderr,
_("%s: option '%s' requires an argument\n"),
argv[0], argv[d->optind - 1]);
fprintf (stderr, _("\
%s: option '-W %s' requires an argument\n"),
argv[0], pfound->name);
#endif
}
d->__nextchar += strlen (d->__nextchar);
return optstring[0] == ':' ? ':' : '?';
}
}
else
d->optarg = NULL;
d->__nextchar += strlen (d->__nextchar);
if (longind != NULL)
*longind = option_index;

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