Merge pull request #44 from dm0-/sync

Merge with upstream master
This commit is contained in:
David Michael 2017-01-24 12:00:11 -08:00 committed by GitHub
commit ff8d967eff
183 changed files with 5507 additions and 2653 deletions

1
.gitignore vendored
View file

@ -247,3 +247,4 @@ build-aux/test-driver
/garbage-gen /garbage-gen
/garbage-gen.exe /garbage-gen.exe
/grub-fs-tester /grub-fs-tester
grub-core/build-grub-module-verifier

View file

@ -89,16 +89,21 @@ CLEANFILES += build-grub-gen-widthspec$(BUILD_EXEEXT)
if COND_STARFIELD if COND_STARFIELD
starfield_DATA = dejavu_10.pf2 dejavu_12.pf2 dejavu_bold_14.pf2 dejavu_14.pf2 dejavu_16.pf2 $(starfield_theme_files) starfield_DATA = dejavu_10.pf2 dejavu_12.pf2 dejavu_bold_14.pf2 dejavu_14.pf2 dejavu_16.pf2 $(starfield_theme_files)
dejavu_10.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont dejavu_10.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont -s 10 -o $@ $(DJVU_FONT_SOURCE) ./build-grub-mkfont$(BUILD_EXEEXT) -s 10 -o $@ $(DJVU_FONT_SOURCE)
dejavu_12.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont CLEANFILES += dejavu_10.pf2
./build-grub-mkfont -s 12 -o $@ $(DJVU_FONT_SOURCE) dejavu_12.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
dejavu_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont ./build-grub-mkfont$(BUILD_EXEEXT) -s 12 -o $@ $(DJVU_FONT_SOURCE)
./build-grub-mkfont -s 14 -o $@ $(DJVU_FONT_SOURCE) CLEANFILES += dejavu_12.pf2
dejavu_bold_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont dejavu_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont -b -s 14 -o $@ $(DJVU_FONT_SOURCE) ./build-grub-mkfont$(BUILD_EXEEXT) -s 14 -o $@ $(DJVU_FONT_SOURCE)
dejavu_16.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont CLEANFILES += dejavu_14.pf2
./build-grub-mkfont -s 16 -o $@ $(DJVU_FONT_SOURCE) dejavu_bold_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont$(BUILD_EXEEXT) -b -s 14 -o $@ $(DJVU_FONT_SOURCE)
CLEANFILES += dejavu_bold_14.pf2
dejavu_16.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont$(BUILD_EXEEXT) -s 16 -o $@ $(DJVU_FONT_SOURCE)
CLEANFILES += dejavu_16.pf2
else else
starfield_DATA = starfield_DATA =
endif endif
@ -106,28 +111,28 @@ endif
EXTRA_DIST += $(starfield_theme_files) EXTRA_DIST += $(starfield_theme_files)
EXTRA_DIST += $(srcdir)/themes/starfield/src/slider_s.xcf $(srcdir)/themes/starfield/src/slider_n.xcf $(srcdir)/themes/starfield/src/slider_c.xcf $(srcdir)/themes/starfield/src/blob_nw.xcf $(srcdir)/themes/starfield/src/bootmenu/center.xcf $(srcdir)/themes/starfield/src/bootmenu/corner.xcf $(srcdir)/themes/starfield/src/bootmenu/side.xcf $(srcdir)/themes/starfield/src/terminalbox/side.xcf $(srcdir)/themes/starfield/src/terminalbox/corner.xcf $(srcdir)/themes/starfield/src/terminalbox/center.xcf EXTRA_DIST += $(srcdir)/themes/starfield/src/slider_s.xcf $(srcdir)/themes/starfield/src/slider_n.xcf $(srcdir)/themes/starfield/src/slider_c.xcf $(srcdir)/themes/starfield/src/blob_nw.xcf $(srcdir)/themes/starfield/src/bootmenu/center.xcf $(srcdir)/themes/starfield/src/bootmenu/corner.xcf $(srcdir)/themes/starfield/src/bootmenu/side.xcf $(srcdir)/themes/starfield/src/terminalbox/side.xcf $(srcdir)/themes/starfield/src/terminalbox/corner.xcf $(srcdir)/themes/starfield/src/terminalbox/center.xcf
unicode.pf2: $(FONT_SOURCE) build-grub-mkfont unicode.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont -o $@ $(FONT_SOURCE) || (rm -f $@; exit 1) ./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) || (rm -f $@; exit 1)
CLEANFILES += unicode.pf2 CLEANFILES += unicode.pf2
# Arrows and lines are needed to draw the menu, so always include them # Arrows and lines are needed to draw the menu, so always include them
UNICODE_ARROWS=0x2190-0x2193 UNICODE_ARROWS=0x2190-0x2193
UNICODE_LINES=0x2501-0x251B UNICODE_LINES=0x2501-0x251B
ascii.pf2: $(FONT_SOURCE) build-grub-mkfont ascii.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1) ./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1)
CLEANFILES += ascii.pf2 CLEANFILES += ascii.pf2
euro.pf2: $(FONT_SOURCE) build-grub-mkfont euro.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT)
./build-grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1) ./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1)
CLEANFILES += euro.pf2 CLEANFILES += euro.pf2
ascii.h: $(FONT_SOURCE) build-grub-gen-asciih ascii.h: $(FONT_SOURCE) build-grub-gen-asciih$(BUILD_EXEEXT)
./build-grub-gen-asciih $(FONT_SOURCE) $@ || (rm -f $@; exit 1) ./build-grub-gen-asciih$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1)
CLEANFILES += ascii.h CLEANFILES += ascii.h
widthspec.h: $(FONT_SOURCE) build-grub-gen-widthspec widthspec.h: $(FONT_SOURCE) build-grub-gen-widthspec$(BUILD_EXEEXT)
./build-grub-gen-widthspec $(FONT_SOURCE) $@ || (rm -f $@; exit 1) ./build-grub-gen-widthspec$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1)
CLEANFILES += widthspec.h CLEANFILES += widthspec.h
# Install config.h into platformdir # Install config.h into platformdir
@ -340,33 +345,35 @@ bootcheck-ntldr: ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg grub-shell
./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/ntldr.bin=ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/ntldr.bin=ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null
if COND_i386_efi if COND_i386_efi
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386 # NetBSD has no support for finding ACPI on EFI
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386
endif endif
if COND_x86_64_efi if COND_x86_64_efi
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386 # NetBSD has no support for finding ACPI on EFI
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386
endif endif
if COND_i386_multiboot if COND_i386_multiboot
# FreeBSD requires ACPI # *BSD requires ACPI
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64
endif
if COND_i386_qemu
# *BSD requires ACPI
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64
endif endif
if COND_i386_coreboot if COND_i386_coreboot
# Freebsd requires ACPI BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64
endif
if COND_i386_qemu
# FreeBSD requires ACPI
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64
endif endif
if COND_i386_pc if COND_i386_pc
#pc chainloader by definition is only for i386-pc #pc chainloader by definition is only for i386-pc
#ntldr and bootmgr require BIOS. #ntldr and bootmgr require BIOS.
#legacy protocol makes early BIOS calls. #legacy protocol (linux16) makes early BIOS calls.
# NetBSD crashes early on non-BIOS # 32-bit NetBSD crashes early on non-BIOS
BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386 bootcheck-pc-chainloader bootcheck-ntldr bootcheck-linux16-i386 bootcheck-linux16-x86_64 bootcheck-knetbsd-i386 BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386 bootcheck-pc-chainloader bootcheck-ntldr bootcheck-linux16-i386 bootcheck-linux16-x86_64 bootcheck-knetbsd-i386
endif endif
@ -402,8 +409,9 @@ BOOTCHECK_TIMEOUT=180
bootcheck: $(BOOTCHECKS) bootcheck: $(BOOTCHECKS)
if COND_i386_coreboot if COND_i386_coreboot
default_payload.elf: grub-mkstandalone grub-mkimage default_payload.elf: grub-mkstandalone grub-mkimage FORCE
pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata ehci uhci ohci usb_keyboard usbms part_msdos xfs ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg test -f $@ && rm $@ || true
pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata ehci uhci ohci usb_keyboard usbms part_msdos ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help syslinuxcfg xnu $(shell cat grub-core/fs.lst) password_pbkdf2 $(EXTRA_PAYLOAD_MODULES)' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg
endif endif
endif endif

View file

@ -172,6 +172,8 @@ program = {
common = util/grub-mkimage.c; common = util/grub-mkimage.c;
common = util/mkimage.c; common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/resolve.c; common = util/resolve.c;
common = grub-core/kern/emu/argp_common.c; common = grub-core/kern/emu/argp_common.c;
common = grub-core/osdep/init.c; common = grub-core/osdep/init.c;
@ -414,7 +416,7 @@ program = {
ldadd = libgrubgcry.a; ldadd = libgrubgcry.a;
ldadd = libgrubkern.a; ldadd = libgrubkern.a;
ldadd = grub-core/gnulib/libgnu.a; ldadd = grub-core/gnulib/libgnu.a;
ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
}; };
data = { data = {
@ -510,6 +512,8 @@ program = {
common = util/render-label.c; common = util/render-label.c;
common = util/glue-efi.c; common = util/glue-efi.c;
common = util/mkimage.c; common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/grub-install-common.c; common = util/grub-install-common.c;
common = util/setup_bios.c; common = util/setup_bios.c;
common = util/setup_sparc.c; common = util/setup_sparc.c;
@ -552,6 +556,8 @@ program = {
common = util/render-label.c; common = util/render-label.c;
common = util/glue-efi.c; common = util/glue-efi.c;
common = util/mkimage.c; common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/grub-install-common.c; common = util/grub-install-common.c;
common = util/setup_bios.c; common = util/setup_bios.c;
common = util/setup_sparc.c; common = util/setup_sparc.c;
@ -595,6 +601,8 @@ program = {
common = util/grub-install.c; common = util/grub-install.c;
common = util/probe.c; common = util/probe.c;
common = util/mkimage.c; common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/grub-install-common.c; common = util/grub-install-common.c;
common = util/setup_bios.c; common = util/setup_bios.c;
common = util/setup_sparc.c; common = util/setup_sparc.c;
@ -632,6 +640,8 @@ program = {
common = util/grub-mknetdir.c; common = util/grub-mknetdir.c;
common = util/mkimage.c; common = util/mkimage.c;
common = util/grub-mkimage32.c;
common = util/grub-mkimage64.c;
common = util/grub-install-common.c; common = util/grub-install-common.c;
common = util/setup_bios.c; common = util/setup_bios.c;
common = util/setup_sparc.c; common = util/setup_sparc.c;

14
NEWS
View file

@ -18,6 +18,7 @@ New in 2.02:
* ZFS features support. * ZFS features support.
* ZFS LZ4 support. * ZFS LZ4 support.
* XFS V5 format support. * XFS V5 format support.
* LVM RAID1 support.
* New/improved terminal and video support: * New/improved terminal and video support:
* Monochrome text (matching `hercules' in GRUB Legacy). * Monochrome text (matching `hercules' in GRUB Legacy).
@ -49,6 +50,9 @@ New in 2.02:
* Improve TFTP robustness. * Improve TFTP robustness.
* Parse `nd' disk names in GRUB Legacy configuration files. * Parse `nd' disk names in GRUB Legacy configuration files.
* Issue separate DNS queries for IPv4 and IPv6. * Issue separate DNS queries for IPv4 and IPv6.
* Support IPv6 Router Advertisement to configure default router.
* New variable net_<interface>_next_server containing next server
from BOOTP reply.
* Coreboot improvements: * Coreboot improvements:
* CBFS support both in on-disk images (loopback) and flash. * CBFS support both in on-disk images (loopback) and flash.
@ -96,6 +100,8 @@ New in 2.02:
EFI Stall. If everything fails, use hardcoded frequency 800MHz. EFI Stall. If everything fails, use hardcoded frequency 800MHz.
* Support Hyper-V Gen2 platforms which lack PIT for TSC calibration. * Support Hyper-V Gen2 platforms which lack PIT for TSC calibration.
* Map UEFI Persistent Memory to E820 persistent memory. * Map UEFI Persistent Memory to E820 persistent memory.
* New Xen loader on ARM64.
* Respect alignment requirement for block device IO buffers on EFI.
* Security: * Security:
* Add optional facility to enforce that all files read by the core image * Add optional facility to enforce that all files read by the core image
@ -134,6 +140,11 @@ New in 2.02:
menu entry immediately. menu entry immediately.
* New `file' command and grub-file utility to check file types. * New `file' command and grub-file utility to check file types.
* New syslinux configuration file parser. * New syslinux configuration file parser.
* Set menu entry class to primary OS name returned by os-prober to display
OS specific icon.
* On Linux x86 detect EFI word size in grub-install and automatically select
correct platform (x86_64-efi or i386-efi) to install. Requires Linux kernel
4.0 or higher.
* Build system: * Build system:
* Remove all uses of nested functions; GRUB no longer requires an * Remove all uses of nested functions; GRUB no longer requires an
@ -160,6 +171,9 @@ New in 2.02:
* emu libusb support removed (was broken and unmaintained). * emu libusb support removed (was broken and unmaintained).
* powerpc64le compile support. * powerpc64le compile support.
* Use fixed timestamp when generating GRUB image for reproducible builds. * Use fixed timestamp when generating GRUB image for reproducible builds.
* Verify at build time that modules contain only supported relocations and their
structure matches what boot-time module loader expects.
* Do not require fonts on powerpc-ieee1275.
* Revision control moved to git. * Revision control moved to git.

4
TODO
View file

@ -7,7 +7,3 @@ glance. So write to <grub-devel@gnu.org> first.
For bug tracking, refer to: For bug tracking, refer to:
http://savannah.gnu.org/bugs/?group=grub http://savannah.gnu.org/bugs/?group=grub
Our wiki also lists some areas that need work:
http://grub.enbug.org/

View file

@ -390,6 +390,24 @@ else
[fi] [fi]
]) ])
dnl Check if the Linker supports `-no-pie'.
AC_DEFUN([grub_CHECK_NO_PIE],
[AC_MSG_CHECKING([whether linker accepts -no-pie])
AC_CACHE_VAL(grub_cv_cc_ld_no_pie,
[save_LDFLAGS="$LDFLAGS"
LDFLAGS="$LDFLAGS -no-pie"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[grub_cv_cc_ld_no_pie=yes],
[grub_cv_cc_ld_no_pie=no])
LDFLAGS="$save_LDFLAGS"
])
AC_MSG_RESULT([$grub_cv_cc_ld_no_pie])
nopie_possible=no
if test "x$grub_cv_cc_ld_no_pie" = xyes ; then
nopie_possible=yes
fi
])
dnl Check if the C compiler supports `-fPIC'. dnl Check if the C compiler supports `-fPIC'.
AC_DEFUN([grub_CHECK_PIC],[ AC_DEFUN([grub_CHECK_PIC],[
[# Position independent executable. [# Position independent executable.

View file

@ -1,12 +1,16 @@
/* on x86 old clang doesn't support .code16 /* on x86 old clang doesn't support .code16
newer clang supports it but creates 6-byte jumps instead of 3-byte ones newer clang supports it but creates 6-byte jumps instead of 3-byte ones
which makes us go over boot sector size. */ which makes us go over boot sector size.
Starting with 3.9 clang emits 3-byte jumps but still creates 8-bytes movl
instead of 5-bytes, so code overflows into data. */
.code16 .code16
jmp far jmp far
.org 4 .org 4
jmp nearer jmp nearer
.org 6 .org 6
movl nearer, %ebx
.org 11
.space 100 .space 100
nearer: nearer:
.space 200 .space 200

View file

@ -38,7 +38,7 @@ CFLAGS_KERNEL = $(CFLAGS_PLATFORM) -ffreestanding
LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC)
CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1
CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM)
STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx
CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding
LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d

View file

@ -50,8 +50,13 @@ EXTRA_DIST += util/import_gcrypth.sed
EXTRA_DIST += util/bin2h.c EXTRA_DIST += util/bin2h.c
EXTRA_DIST += util/grub-gen-asciih.c EXTRA_DIST += util/grub-gen-asciih.c
EXTRA_DIST += util/grub-gen-widthspec.c EXTRA_DIST += util/grub-gen-widthspec.c
EXTRA_DIST += util/grub-module-verifier.c
EXTRA_DIST += util/grub-module-verifier32.c
EXTRA_DIST += util/grub-module-verifier64.c
EXTRA_DIST += util/grub-module-verifierXX.c
EXTRA_DIST += util/grub-pe2elf.c EXTRA_DIST += util/grub-pe2elf.c
EXTRA_DIST += m4/gnulib-cache.m4 EXTRA_DIST += m4/gnulib-cache.m4
EXTRA_DIST += m4/glibc2.m4 EXTRA_DIST += m4/glibc2.m4
EXTRA_DIST += m4/gnulib-tool.m4 EXTRA_DIST += m4/gnulib-tool.m4

View file

@ -31,7 +31,7 @@ dnl (such as BUILD_CC, BUILD_CFLAGS, etc.) for the build type and variables
dnl with the prefix "TARGET_" (such as TARGET_CC, TARGET_CFLAGS, etc.) are dnl with the prefix "TARGET_" (such as TARGET_CC, TARGET_CFLAGS, etc.) are
dnl used for the target type. See INSTALL for full list of variables. dnl used for the target type. See INSTALL for full list of variables.
AC_INIT([GRUB],[2.02~beta2],[bug-grub@gnu.org]) AC_INIT([GRUB],[2.02~beta3],[bug-grub@gnu.org])
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])
@ -388,7 +388,15 @@ fi
# Check for functions and headers. # Check for functions and headers.
AC_CHECK_FUNCS(posix_memalign memalign getextmntent) AC_CHECK_FUNCS(posix_memalign memalign getextmntent)
AC_CHECK_HEADERS(sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h limits.h) AC_CHECK_HEADERS(sys/param.h sys/mount.h sys/mnttab.h limits.h)
# glibc 2.25 still includes sys/sysmacros.h in sys/types.h but emits deprecation
# warning which causes compilation failure later with -Werror. So use -Werror here
# as well to force proper sys/sysmacros.h detection.
SAVED_CFLAGS="$CFLAGS"
CFLAGS="$HOST_CFLAGS -Werror"
AC_HEADER_MAJOR
CFLAGS="$SAVED_CFLAGS"
AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default
#include <sys/param.h> #include <sys/param.h>
@ -910,12 +918,24 @@ if test x"$target_os" = xcygwin && test "x$grub_cv_cc_no_reorder_functions" = xy
TARGET_CFLAGS="$TARGET_CFLAGS -fno-reorder-functions" TARGET_CFLAGS="$TARGET_CFLAGS -fno-reorder-functions"
fi fi
AC_CACHE_CHECK([whether -mno-stack-arg-probe works], [grub_cv_cc_mno_stack_arg_probe], [
CFLAGS="$TARGET_CFLAGS -mno-stack-arg-probe"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[grub_cv_cc_mno_stack_arg_probe=yes],
[grub_cv_cc_mno_stack_arg_probe=no])
])
if test "x$grub_cv_cc_mno_stack_arg_probe" = xyes; then
TARGET_CFLAGS="$TARGET_CFLAGS -mno-stack-arg-probe"
fi
# By default, GCC 4.6 generates .eh_frame sections containing unwind # By default, GCC 4.6 generates .eh_frame sections containing unwind
# information in some cases where it previously did not. GRUB doesn't need # information in some cases where it previously did not. GRUB doesn't need
# these and they just use up vital space. Restore the old compiler # these and they just use up vital space. Restore the old compiler
# behaviour. # behaviour.
AC_CACHE_CHECK([whether -fno-asynchronous-unwind-tables works], [grub_cv_cc_fno_asynchronous_unwind_tables], [ AC_CACHE_CHECK([whether -fno-asynchronous-unwind-tables works], [grub_cv_cc_fno_asynchronous_unwind_tables], [
CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" CFLAGS="$TARGET_CFLAGS -fno-asynchronous-unwind-tables"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[grub_cv_cc_fno_asynchronous_unwind_tables=yes], [grub_cv_cc_fno_asynchronous_unwind_tables=yes],
[grub_cv_cc_fno_asynchronous_unwind_tables=no]) [grub_cv_cc_fno_asynchronous_unwind_tables=no])
@ -925,66 +945,17 @@ if test "x$grub_cv_cc_fno_asynchronous_unwind_tables" = xyes; then
TARGET_CFLAGS="$TARGET_CFLAGS -fno-asynchronous-unwind-tables" TARGET_CFLAGS="$TARGET_CFLAGS -fno-asynchronous-unwind-tables"
fi fi
AC_ARG_ENABLE([efiemu], AC_CACHE_CHECK([whether -fno-unwind-tables works], [grub_cv_cc_fno_unwind_tables], [
[AS_HELP_STRING([--enable-efiemu], CFLAGS="$TARGET_CFLAGS -fno-unwind-tables"
[build and install the efiemu runtimes (default=guessed)])]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
if test x"$enable_efiemu" = xno ; then [grub_cv_cc_fno_unwind_tables=yes],
efiemu_excuse="explicitly disabled" [grub_cv_cc_fno_unwind_tables=no])
])
if test "x$grub_cv_cc_fno_unwind_tables" = xyes; then
TARGET_CFLAGS="$TARGET_CFLAGS -fno-unwind-tables"
fi fi
if test x"$grub_cv_target_cc_link_format" = x-mi386pe || test x"$grub_cv_target_cc_link_format" = x-mi386pep ; then
efiemu_excuse="not available on cygwin"
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="-m64 -nostdlib -O2 -mcmodel=large -mno-red-zone"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[grub_cv_cc_efiemu=yes],
[grub_cv_cc_efiemu=no])
])
if test x$grub_cv_cc_efiemu = xno; then
efiemu_excuse="cannot compile with -m64 -mcmodel=large -mno-red-zone -nostdlib"
fi
fi
if test x"$efiemu_excuse" = x ; then
AC_CACHE_CHECK([for efiemu64 linking format], [grub_cv_target_cc_efiemu64_link_format], [
grub_cv_target_cc_efiemu64_link_format=unknown
for format in -melf_x86_64 -melf_x86_64_fbsd -melf_x86_64_obsd -melf_x86_64_haiku -arch,x86_64; do
CFLAGS="-m64 -nostdlib -O2 -mcmodel=large -mno-red-zone"
LDFLAGS="-m64 -Wl,$format -nostdlib -static"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
asm (".globl start; start:");
asm (".globl _start; _start:");
asm (".globl __start; __start:");
void __main (void);
void __main (void) {}
]], [[]])], [flag=1], [flag=0])
if test x"$flag" = x1; then
grub_cv_target_cc_efiemu64_link_format="$format"
break
fi
done])
if test x"$grub_cv_target_cc_efiemu64_link_format" = xunknown; then
efiemu_excuse="no suitable link format for efiemu64 found"
else
EFIEMU64_LINK_FORMAT="-Wl,$grub_cv_target_cc_efiemu64_link_format"
fi
fi
if test x"$enable_efiemu" = xyes && test x"$efiemu_excuse" != x ; then
AC_MSG_ERROR([efiemu runtime was explicitly requested but can't be compiled ($efiemu_excuse)])
fi
if test x"$efiemu_excuse" = x ; then
enable_efiemu=yes
else
enable_efiemu=no
fi
AC_SUBST([enable_efiemu])
AC_SUBST([EFIEMU64_LINK_FORMAT])
CFLAGS="$TARGET_CFLAGS" CFLAGS="$TARGET_CFLAGS"
@ -1078,6 +1049,73 @@ else
TARGET_IMG_CFLAGS= TARGET_IMG_CFLAGS=
fi fi
CFLAGS="$TARGET_CFLAGS"
AC_ARG_ENABLE([efiemu],
[AS_HELP_STRING([--enable-efiemu],
[build and install the efiemu runtimes (default=guessed)])])
if test x"$enable_efiemu" = xno ; then
efiemu_excuse="explicitly disabled"
fi
if test x"$grub_cv_target_cc_link_format" = x-mi386pe || test x"$grub_cv_target_cc_link_format" = x-mi386pep ; then
efiemu_excuse="not available on cygwin"
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="-m64 -nostdlib -O2 -mcmodel=large -mno-red-zone"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[grub_cv_cc_efiemu=yes],
[grub_cv_cc_efiemu=no])
])
if test x$grub_cv_cc_efiemu = xno; then
efiemu_excuse="cannot compile with -m64 -mcmodel=large -mno-red-zone -nostdlib"
fi
fi
if test x"$efiemu_excuse" = x ; then
AC_CACHE_CHECK([for efiemu64 linking format], [grub_cv_target_cc_efiemu64_link_format], [
grub_cv_target_cc_efiemu64_link_format=unknown
for format in -melf_x86_64 -melf_x86_64_fbsd -melf_x86_64_obsd -melf_x86_64_haiku -arch,x86_64; do
CFLAGS="-m64 -nostdlib -O2 -mcmodel=large -mno-red-zone"
LDFLAGS="-m64 -Wl,$format -nostdlib -static"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
asm (".globl start; start:");
asm (".globl _start; _start:");
asm (".globl __start; __start:");
void __main (void);
void __main (void) {}
]], [[]])], [flag=1], [flag=0])
if test x"$flag" = x1; then
grub_cv_target_cc_efiemu64_link_format="$format"
break
fi
done])
if test x"$grub_cv_target_cc_efiemu64_link_format" = xunknown; then
efiemu_excuse="no suitable link format for efiemu64 found"
else
EFIEMU64_LINK_FORMAT="-Wl,$grub_cv_target_cc_efiemu64_link_format"
fi
fi
if test x"$enable_efiemu" = xyes && test x"$efiemu_excuse" != x ; then
AC_MSG_ERROR([efiemu runtime was explicitly requested but can't be compiled ($efiemu_excuse)])
fi
if test x"$efiemu_excuse" = x ; then
enable_efiemu=yes
else
enable_efiemu=no
fi
AC_SUBST([enable_efiemu])
AC_SUBST([EFIEMU64_LINK_FORMAT])
CFLAGS="$TARGET_CFLAGS"
AC_SUBST(TARGET_LDFLAGS_OLDMAGIC) AC_SUBST(TARGET_LDFLAGS_OLDMAGIC)
@ -1154,13 +1192,18 @@ CFLAGS="$TARGET_CFLAGS"
# Position independent executable. # Position independent executable.
grub_CHECK_PIE grub_CHECK_PIE
grub_CHECK_NO_PIE
[# Need that, because some distributions ship compilers that include [# Need that, because some distributions ship compilers that include
# `-fPIE' in the default specs. # `-fPIE' or '-fpie' and '-pie' in the default specs.
if [ x"$pie_possible" = xyes ]; then if [ x"$pie_possible" = xyes ]; then
TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIE" TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIE -fno-pie"
fi
if [ x"$nopie_possible" = xyes ] && [ x"$pie_possible" = xyes ]; then
TARGET_LDFLAGS="$TARGET_LDFLAGS -no-pie"
fi] fi]
CFLAGS="$TARGET_CFLAGS" CFLAGS="$TARGET_CFLAGS"
LDFLAGS="$TARGET_LDFLAGS"
# Position independent executable. # Position independent executable.
grub_CHECK_PIC grub_CHECK_PIC
@ -1524,11 +1567,11 @@ if test x"$grub_build_mkfont_excuse" = x ; then
else else
enable_build_grub_mkfont=no enable_build_grub_mkfont=no
fi fi
if test x"$enable_build_grub_mkfont" = xno && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips || test "x$target_cpu"-"$platform" = xpowerpc-ieee1275 || test "x$platform" = xcoreboot ); then if test x"$enable_build_grub_mkfont" = xno && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips || test "x$platform" = xcoreboot ); then
if test x"$grub_build_mkfont_excuse" = x ; then if test x"$grub_build_mkfont_excuse" = x ; then
AC_MSG_ERROR([qemu, powerpc-ieee1275, coreboot and loongson ports needs build-time grub-mkfont]) AC_MSG_ERROR([qemu, coreboot and loongson ports need build-time grub-mkfont])
else else
AC_MSG_ERROR([qemu, powerpc-ieee1275, coreboot and loongson ports needs build-time grub-mkfont ($grub_build_mkfont_excuse)]) AC_MSG_ERROR([qemu, coreboot and loongson ports need build-time grub-mkfont ($grub_build_mkfont_excuse)])
fi fi
fi fi
@ -1598,11 +1641,11 @@ if test x"$enable_build_grub_mkfont" = xno ; then
FONT_SOURCE= FONT_SOURCE=
fi fi
if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips || test "x$target_cpu"-"$platform" = xpowerpc-ieee1275 || test "x$platform" = xcoreboot ); then if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips || test "x$platform" = xcoreboot ); then
if test x"$grub_build_mkfont_excuse" = x ; then if test x"$grub_build_mkfont_excuse" = x ; then
AC_MSG_ERROR([qemu, powerpc-ieee1275, coreboot and loongson ports need unifont]) AC_MSG_ERROR([qemu, coreboot and loongson ports need unifont])
else else
AC_MSG_ERROR([qemu, powerpc-ieee1275, coreboot and loongson ports need unifont ($grub_build_mkfont_excuse)]) AC_MSG_ERROR([qemu, coreboot and loongson ports need unifont ($grub_build_mkfont_excuse)])
fi fi
fi fi

View file

@ -2446,6 +2446,10 @@ The boot file name provided by DHCP. Read-only.
The name of the DHCP server responsible for these boot parameters. The name of the DHCP server responsible for these boot parameters.
Read-only. Read-only.
@item net_@var{<interface>}_next_server
The IP address of the next (usually, TFTP) server provided by DHCP.
Read-only.
@item net_default_interface @item net_default_interface
Initially set to name of network interface that was used to load grub. Initially set to name of network interface that was used to load grub.
Read-write, although setting it affects only interpretation of Read-write, although setting it affects only interpretation of
@ -2538,6 +2542,8 @@ team are:
85:3 85:3
@item Asus EeePC 1005PE @item Asus EeePC 1005PE
84:1 (unconfirmed) 84:1 (unconfirmed)
@item LENOVO ThinkPad T410s (2912W1C)
101:3
@end table @end table
To take full advantage of this function, install GRUB into the MBR To take full advantage of this function, install GRUB into the MBR
@ -3060,6 +3066,7 @@ These variables have special meaning to GRUB.
* net_@var{<interface>}_hostname:: * net_@var{<interface>}_hostname::
* net_@var{<interface>}_ip:: * net_@var{<interface>}_ip::
* net_@var{<interface>}_mac:: * net_@var{<interface>}_mac::
* net_@var{<interface>}_next_server::
* net_@var{<interface>}_rootpath:: * net_@var{<interface>}_rootpath::
* net_default_interface:: * net_default_interface::
* net_default_ip:: * net_default_ip::
@ -3420,6 +3427,12 @@ The default is the value of @samp{color_normal} (@pxref{color_normal}).
@xref{Network}. @xref{Network}.
@node net_@var{<interface>}_next_server
@subsection net_@var{<interface>}_next_server
@xref{Network}.
@node net_@var{<interface>}_rootpath @node net_@var{<interface>}_rootpath
@subsection net_@var{<interface>}_rootpath @subsection net_@var{<interface>}_rootpath
@ -4074,12 +4087,15 @@ after @command{configfile} returns.
@node cpuid @node cpuid
@subsection cpuid @subsection cpuid
@deffn Command cpuid [-l] @deffn Command cpuid [-l] [-p]
Check for CPU features. This command is only available on x86 systems. Check for CPU features. This command is only available on x86 systems.
With the @option{-l} option, return true if the CPU supports long mode With the @option{-l} option, return true if the CPU supports long mode
(64-bit). (64-bit).
With the @option{-p} option, return true if the CPU supports Physical
Address Extension (PAE).
If invoked without options, this command currently behaves as if it had been If invoked without options, this command currently behaves as if it had been
invoked with @option{-l}. This may change in the future. invoked with @option{-l}. This may change in the future.
@end deffn @end deffn
@ -5111,6 +5127,8 @@ the length of @var{string} is zero
@var{expression} is false @var{expression} is false
@item @var{expression1} @code{-a} @var{expression2} @item @var{expression1} @code{-a} @var{expression2}
both @var{expression1} and @var{expression2} are true both @var{expression1} and @var{expression2} are true
@item @var{expression1} @var{expression2}
both @var{expression1} and @var{expression2} are true. This syntax is not POSIX-compliant and is not recommended.
@item @var{expression1} @code{-o} @var{expression2} @item @var{expression1} @code{-o} @var{expression2}
either @var{expression1} or @var{expression2} is true either @var{expression1} or @var{expression2} is true
@end table @end table

View file

@ -729,9 +729,11 @@ def kernel(defn, platform):
"""if test x$(TARGET_APPLE_LINKER) = x1; then \ """if test x$(TARGET_APPLE_LINKER) = x1; then \
$(TARGET_STRIP) -S -x $(""" + cname(defn) + """) -o $@.bin $<; \ $(TARGET_STRIP) -S -x $(""" + cname(defn) + """) -o $@.bin $<; \
$(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -ed2016 -wd1106 -nu -nd $@.bin $@; \ $(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -ed2016 -wd1106 -nu -nd $@.bin $@; \
rm -f $@.bin; \
elif test ! -z '$(TARGET_OBJ2ELF)'; then \ elif test ! -z '$(TARGET_OBJ2ELF)'; then \
""" + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@.bin $< && \ """ + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@.bin $< && \
$(TARGET_OBJ2ELF) $@.bin $@ || (rm -f $@; rm -f $@.bin; exit 1); \ $(TARGET_OBJ2ELF) $@.bin $@ || (rm -f $@; rm -f $@.bin; exit 1); \
rm -f $@.bin; \
else """ + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@ $<; \ else """ + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@ $<; \
fi""")) fi"""))
@ -759,7 +761,7 @@ def image(defn, platform):
if test x$(TARGET_APPLE_LINKER) = x1; then \ if test x$(TARGET_APPLE_LINKER) = x1; then \
$(MACHO2IMG) $< $@; \ $(MACHO2IMG) $< $@; \
else \ else \
$(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; \ $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version -R .ARM.exidx $< $@; \
fi fi
""") """)

View file

@ -39,6 +39,10 @@ gentrigtables$(BUILD_EXEEXT): gentrigtables.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM) $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM)
CLEANFILES += gentrigtables$(BUILD_EXEEXT) CLEANFILES += gentrigtables$(BUILD_EXEEXT)
build-grub-module-verifier$(BUILD_EXEEXT): $(top_srcdir)/util/grub-module-verifier.c $(top_srcdir)/util/grub-module-verifier32.c $(top_srcdir)/util/grub-module-verifier64.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c
$(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-module-verifier\" $^
CLEANFILES += build-grub-module-verifier$(BUILD_EXEEXT)
# trigtables.c # trigtables.c
trigtables.c: gentrigtables$(BUILD_EXEEXT) gentrigtables.c $(top_srcdir)/configure.ac trigtables.c: gentrigtables$(BUILD_EXEEXT) gentrigtables.c $(top_srcdir)/configure.ac
./gentrigtables$(BUILD_EXEEXT) > $@ ./gentrigtables$(BUILD_EXEEXT) > $@
@ -104,6 +108,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h
endif endif
if COND_i386_coreboot if COND_i386_coreboot
@ -159,6 +164,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h
endif endif
if COND_ia64_efi if COND_ia64_efi
@ -391,7 +397,7 @@ moddep.lst: syminfo.lst genmoddep.awk video.lst
platform_DATA += moddep.lst platform_DATA += moddep.lst
CLEANFILES += config.log syminfo.lst moddep.lst CLEANFILES += config.log syminfo.lst moddep.lst
$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) $(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier$(BUILD_EXEEXT)
TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@ TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@
platform_DATA += $(MOD_FILES) platform_DATA += $(MOD_FILES)
platform_DATA += modinfo.sh platform_DATA += modinfo.sh

View file

@ -90,7 +90,7 @@ kernel = {
i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)';
emu_cflags = '$(CFLAGS_GNULIB)'; emu_cflags = '$(CFLAGS_GNULIB)';
emu_cppflags = '$(CPPFLAGS_GNULIB)'; emu_cppflags = '$(CPPFLAGS_GNULIB)';
arm_uboot_ldflags = '-Wl,-Ttext=0x08000000'; arm_uboot_ldflags = '-Wl,-r,-d';
arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
i386_pc_startup = kern/i386/pc/startup.S; i386_pc_startup = kern/i386/pc/startup.S;
@ -214,8 +214,10 @@ kernel = {
arm_efi = kern/arm/efi/init.c; arm_efi = kern/arm/efi/init.c;
arm_efi = kern/arm/efi/misc.c; arm_efi = kern/arm/efi/misc.c;
arm_efi = kern/efi/fdt.c;
arm64_efi = kern/arm/efi/init.c; arm64_efi = kern/arm64/efi/init.c;
arm64_efi = kern/efi/fdt.c;
i386_pc = kern/i386/pc/init.c; i386_pc = kern/i386/pc/init.c;
i386_pc = kern/i386/pc/mmap.c; i386_pc = kern/i386/pc/mmap.c;
@ -1585,6 +1587,7 @@ module = {
i386_xen = lib/i386/xen/relocator.S; i386_xen = lib/i386/xen/relocator.S;
x86_64_xen = lib/x86_64/xen/relocator.S; x86_64_xen = lib/x86_64/xen/relocator.S;
xen = lib/i386/relocator_common_c.c; xen = lib/i386/relocator_common_c.c;
x86_64_efi = lib/x86_64/efi/relocator.c;
extra_dist = lib/i386/relocator_common.S; extra_dist = lib/i386/relocator_common.S;
extra_dist = kern/powerpc/cache_flush.S; extra_dist = kern/powerpc/cache_flush.S;
@ -1739,7 +1742,32 @@ module = {
x86 = loader/i386/xnu.c; x86 = loader/i386/xnu.c;
x86 = loader/xnu.c; x86 = loader/xnu.c;
enable = x86; /* Code is pretty generic but relies on RNG which
is available only on few platforms. It's not a
big deal as xnu needs ACPI anyway and we have
RNG on all platforms with ACPI.
*/
enable = i386_multiboot;
enable = i386_coreboot;
enable = i386_pc;
enable = i386_efi;
enable = x86_64_efi;
};
module = {
name = random;
x86 = lib/i386/random.c;
common = lib/random.c;
i386_multiboot = kern/i386/tsc_pmtimer.c;
i386_coreboot = kern/i386/tsc_pmtimer.c;
i386_pc = kern/i386/tsc_pmtimer.c;
enable = i386_multiboot;
enable = i386_coreboot;
enable = i386_pc;
enable = i386_efi;
enable = x86_64_efi;
}; };
module = { module = {

View file

@ -29,6 +29,7 @@
#include <grub/loader.h> #include <grub/loader.h>
#include <grub/cs5536.h> #include <grub/cs5536.h>
#include <grub/disk.h> #include <grub/disk.h>
#include <grub/cache.h>
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
@ -337,6 +338,21 @@ struct grub_ehci
static struct grub_ehci *ehci; static struct grub_ehci *ehci;
static void
sync_all_caches (struct grub_ehci *e)
{
if (!e)
return;
if (e->td_virt)
grub_arch_sync_dma_caches (e->td_virt, sizeof (struct grub_ehci_td) *
GRUB_EHCI_N_TD);
if (e->qh_virt)
grub_arch_sync_dma_caches (e->qh_virt, sizeof (struct grub_ehci_qh) *
GRUB_EHCI_N_QH);
if (e->framelist_virt)
grub_arch_sync_dma_caches (e->framelist_virt, 4096);
}
/* EHCC registers access functions */ /* EHCC registers access functions */
static inline grub_uint32_t static inline grub_uint32_t
grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr) grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr)
@ -437,6 +453,8 @@ grub_ehci_reset (struct grub_ehci *e)
{ {
grub_uint64_t maxtime; grub_uint64_t maxtime;
sync_all_caches (e);
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
GRUB_EHCI_CMD_HC_RESET GRUB_EHCI_CMD_HC_RESET
| grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND));
@ -840,6 +858,8 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid,
e->next = ehci; e->next = ehci;
ehci = e; ehci = e;
sync_all_caches (e);
grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n"); grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n");
grub_dprintf ("ehci", grub_dprintf ("ehci",
@ -1020,6 +1040,7 @@ grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer)
/* Found proper existing (and linked) QH, do setup of QH */ /* Found proper existing (and linked) QH, do setup of QH */
grub_dprintf ("ehci", "find_qh: found, QH=%p\n", qh_iter); grub_dprintf ("ehci", "find_qh: found, QH=%p\n", qh_iter);
grub_ehci_setup_qh (qh_iter, transfer); grub_ehci_setup_qh (qh_iter, transfer);
sync_all_caches (e);
return qh_iter; return qh_iter;
} }
@ -1121,7 +1142,7 @@ grub_ehci_free_tds (struct grub_ehci *e, grub_ehci_td_t td,
token = grub_le_to_cpu32 (td->token); token = grub_le_to_cpu32 (td->token);
to_transfer = (token & GRUB_EHCI_TOTAL_MASK) >> GRUB_EHCI_TOTAL_OFF; to_transfer = (token & GRUB_EHCI_TOTAL_MASK) >> GRUB_EHCI_TOTAL_OFF;
/* Check state of TD - if it did not transfered /* Check state of TD - if it did not transfer
* whole data then set last_trans - it should be last executed TD * whole data then set last_trans - it should be last executed TD
* in case when something went wrong. */ * in case when something went wrong. */
if (transfer && (td->size != to_transfer)) if (transfer && (td->size != to_transfer))
@ -1289,16 +1310,28 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
grub_ehci_td_t td_prev = NULL; grub_ehci_td_t td_prev = NULL;
int i; int i;
struct grub_ehci_transfer_controller_data *cdata; struct grub_ehci_transfer_controller_data *cdata;
grub_uint32_t status;
sync_all_caches (e);
/* Check if EHCI is running and AL is enabled */ /* Check if EHCI is running and AL is enabled */
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
& GRUB_EHCI_ST_HC_HALTED) != 0) if ((status & GRUB_EHCI_ST_HC_HALTED) != 0)
/* XXX: Fix it: Currently we don't do anything to restart EHCI */ /* XXX: Fix it: Currently we don't do anything to restart EHCI */
return GRUB_USB_ERR_INTERNAL; {
if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) grub_dprintf ("ehci", "setup_transfer: halted, status = 0x%x\n",
status);
return GRUB_USB_ERR_INTERNAL;
}
status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS);
if ((status
& (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0) & (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)
/* XXX: Fix it: Currently we don't do anything to restart EHCI */ /* XXX: Fix it: Currently we don't do anything to restart EHCI */
return GRUB_USB_ERR_INTERNAL; {
grub_dprintf ("ehci", "setup_transfer: no AS/PS, status = 0x%x\n",
status);
return GRUB_USB_ERR_INTERNAL;
}
/* Allocate memory for controller transfer data. */ /* Allocate memory for controller transfer data. */
cdata = grub_malloc (sizeof (*cdata)); cdata = grub_malloc (sizeof (*cdata));
@ -1310,6 +1343,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
cdata->qh_virt = grub_ehci_find_qh (e, transfer); cdata->qh_virt = grub_ehci_find_qh (e, transfer);
if (!cdata->qh_virt) if (!cdata->qh_virt)
{ {
grub_dprintf ("ehci", "setup_transfer: no QH\n");
grub_free (cdata); grub_free (cdata);
return GRUB_USB_ERR_INTERNAL; return GRUB_USB_ERR_INTERNAL;
} }
@ -1319,6 +1353,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
cdata->td_alt_virt = grub_ehci_alloc_td (e); cdata->td_alt_virt = grub_ehci_alloc_td (e);
if (!cdata->td_alt_virt) if (!cdata->td_alt_virt)
{ {
grub_dprintf ("ehci", "setup_transfer: no TDs\n");
grub_free (cdata); grub_free (cdata);
return GRUB_USB_ERR_INTERNAL; return GRUB_USB_ERR_INTERNAL;
} }
@ -1345,6 +1380,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
grub_ehci_free_tds (e, cdata->td_first_virt, NULL, &actual); grub_ehci_free_tds (e, cdata->td_first_virt, NULL, &actual);
grub_free (cdata); grub_free (cdata);
grub_dprintf ("ehci", "setup_transfer: no TD\n");
return GRUB_USB_ERR_INTERNAL; return GRUB_USB_ERR_INTERNAL;
} }
@ -1386,6 +1422,8 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev,
* i.e. reset token */ * i.e. reset token */
cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0); cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0);
sync_all_caches (e);
/* Finito */ /* Finito */
transfer->controller_data = cdata; transfer->controller_data = cdata;
@ -1434,6 +1472,8 @@ grub_ehci_parse_notrun (grub_usb_controller_t dev,
grub_ehci_free_td (e, cdata->td_alt_virt); grub_ehci_free_td (e, cdata->td_alt_virt);
grub_free (cdata); grub_free (cdata);
sync_all_caches (e);
/* Additionally, do something with EHCI to make it running (what?) */ /* Additionally, do something with EHCI to make it running (what?) */
/* Try enable EHCI and AL */ /* Try enable EHCI and AL */
grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND,
@ -1469,6 +1509,8 @@ grub_ehci_parse_halt (grub_usb_controller_t dev,
grub_ehci_free_td (e, cdata->td_alt_virt); grub_ehci_free_td (e, cdata->td_alt_virt);
grub_free (cdata); grub_free (cdata);
sync_all_caches (e);
/* Evaluation of error code - currently we don't have GRUB USB error /* Evaluation of error code - currently we don't have GRUB USB error
* codes for some EHCI states, GRUB_USB_ERR_DATA is used for them. * codes for some EHCI states, GRUB_USB_ERR_DATA is used for them.
* Order of evaluation is critical, specially bubble/stall. */ * Order of evaluation is critical, specially bubble/stall. */
@ -1502,6 +1544,8 @@ grub_ehci_parse_success (grub_usb_controller_t dev,
grub_ehci_free_td (e, cdata->td_alt_virt); grub_ehci_free_td (e, cdata->td_alt_virt);
grub_free (cdata); grub_free (cdata);
sync_all_caches (e);
return GRUB_USB_ERR_NONE; return GRUB_USB_ERR_NONE;
} }
@ -1515,6 +1559,8 @@ grub_ehci_check_transfer (grub_usb_controller_t dev,
transfer->controller_data; transfer->controller_data;
grub_uint32_t token, token_ftd; grub_uint32_t token, token_ftd;
sync_all_caches (e);
grub_dprintf ("ehci", grub_dprintf ("ehci",
"check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n", "check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS), grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS),
@ -1581,6 +1627,9 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
int i; int i;
grub_uint64_t maxtime; grub_uint64_t maxtime;
grub_uint32_t qh_phys; grub_uint32_t qh_phys;
sync_all_caches (e);
grub_uint32_t interrupt = grub_uint32_t interrupt =
cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK; cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK;
@ -1600,6 +1649,7 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual); grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual);
grub_ehci_free_td (e, cdata->td_alt_virt); grub_ehci_free_td (e, cdata->td_alt_virt);
grub_free (cdata); grub_free (cdata);
sync_all_caches (e);
grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n"); grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n");
return GRUB_USB_ERR_NONE; return GRUB_USB_ERR_NONE;
} }
@ -1622,6 +1672,8 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
/* Unlink QH from AL */ /* Unlink QH from AL */
e->qh_virt[i].qh_hptr = cdata->qh_virt->qh_hptr; e->qh_virt[i].qh_hptr = cdata->qh_virt->qh_hptr;
sync_all_caches (e);
/* If this is an interrupt transfer, we just wait for the periodic /* If this is an interrupt transfer, we just wait for the periodic
* schedule to advance a few times and then assume that the EHCI * schedule to advance a few times and then assume that the EHCI
* controller has read the updated QH. */ * controller has read the updated QH. */
@ -1676,6 +1728,8 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev,
grub_dprintf ("ehci", "cancel_transfer: end\n"); grub_dprintf ("ehci", "cancel_transfer: end\n");
sync_all_caches (e);
return GRUB_USB_ERR_NONE; return GRUB_USB_ERR_NONE;
} }
@ -1777,11 +1831,6 @@ grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed)
status = grub_ehci_port_read (e, port); status = grub_ehci_port_read (e, port);
grub_dprintf ("ehci", "detect_dev: EHCI STATUS: %08x\n",
grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS));
grub_dprintf ("ehci", "detect_dev: iobase=%p, port=%d, status=0x%02x\n",
e->iobase, port, status);
/* Connect Status Change bit - it detects change of connection */ /* Connect Status Change bit - it detects change of connection */
if (status & GRUB_EHCI_PORT_CONNECT_CH) if (status & GRUB_EHCI_PORT_CONNECT_CH)
{ {

View file

@ -24,6 +24,7 @@
#include <grub/usb.h> #include <grub/usb.h>
#include <grub/usbtrans.h> #include <grub/usbtrans.h>
#include <grub/time.h> #include <grub/time.h>
#include <grub/cache.h>
static inline unsigned int static inline unsigned int
@ -101,6 +102,8 @@ grub_usb_control_msg (grub_usb_device_t dev,
data_addr = grub_dma_get_phys (data_chunk); data_addr = grub_dma_get_phys (data_chunk);
grub_memcpy ((char *) data, data_in, size); grub_memcpy ((char *) data, data_in, size);
grub_arch_sync_dma_caches (data, size);
grub_dprintf ("usb", grub_dprintf ("usb",
"control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%lu\n", "control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%lu\n",
reqtype, request, value, index, (unsigned long)size); reqtype, request, value, index, (unsigned long)size);
@ -161,6 +164,8 @@ grub_usb_control_msg (grub_usb_device_t dev,
setupdata->value = value; setupdata->value = value;
setupdata->index = index; setupdata->index = index;
setupdata->length = size; setupdata->length = size;
grub_arch_sync_dma_caches (setupdata, sizeof (*setupdata));
transfer->transactions[0].size = sizeof (*setupdata); transfer->transactions[0].size = sizeof (*setupdata);
transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP; transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP;
transfer->transactions[0].data = setupdata_addr; transfer->transactions[0].data = setupdata_addr;
@ -202,11 +207,13 @@ grub_usb_control_msg (grub_usb_device_t dev,
grub_free (transfer->transactions); grub_free (transfer->transactions);
grub_free (transfer); grub_free (transfer);
grub_dma_free (data_chunk);
grub_dma_free (setupdata_chunk); grub_dma_free (setupdata_chunk);
grub_arch_sync_dma_caches (data, size0);
grub_memcpy (data_in, (char *) data, size0); grub_memcpy (data_in, (char *) data, size0);
grub_dma_free (data_chunk);
return err; return err;
} }
@ -236,7 +243,10 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev,
data = grub_dma_get_virt (data_chunk); data = grub_dma_get_virt (data_chunk);
data_addr = grub_dma_get_phys (data_chunk); data_addr = grub_dma_get_phys (data_chunk);
if (type == GRUB_USB_TRANSFER_TYPE_OUT) if (type == GRUB_USB_TRANSFER_TYPE_OUT)
grub_memcpy ((char *) data, data_in, size); {
grub_memcpy ((char *) data, data_in, size);
grub_arch_sync_dma_caches (data, size);
}
/* Create a transfer. */ /* Create a transfer. */
transfer = grub_malloc (sizeof (struct grub_usb_transfer)); transfer = grub_malloc (sizeof (struct grub_usb_transfer));
@ -306,9 +316,13 @@ grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer)
dev->toggle[transfer->endpoint] = toggle; dev->toggle[transfer->endpoint] = toggle;
if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN) if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN)
grub_memcpy (transfer->data, (void *) {
grub_dma_get_virt (transfer->data_chunk), grub_arch_sync_dma_caches (grub_dma_get_virt (transfer->data_chunk),
transfer->size + 1); transfer->size + 1);
grub_memcpy (transfer->data, (void *)
grub_dma_get_virt (transfer->data_chunk),
transfer->size + 1);
}
grub_free (transfer->transactions); grub_free (transfer->transactions);
grub_dma_free (transfer->data_chunk); grub_dma_free (transfer->data_chunk);

View file

@ -593,6 +593,9 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args)
if (! table->addr) if (! table->addr)
{ {
free_tables (); free_tables ();
grub_free (exclude);
grub_free (load_only);
grub_free (table);
return grub_errno; return grub_errno;
} }
table->next = acpi_tables; table->next = acpi_tables;

View file

@ -26,6 +26,8 @@
#define grub_dprintf(cond, args...) printf ( args ) #define grub_dprintf(cond, args...) printf ( args )
#define grub_printf printf #define grub_printf printf
#define grub_util_fopen fopen
#define grub_memcmp memcmp
typedef uint64_t grub_uint64_t; typedef uint64_t grub_uint64_t;
typedef uint32_t grub_uint32_t; typedef uint32_t grub_uint32_t;
typedef uint16_t grub_uint16_t; typedef uint16_t grub_uint16_t;
@ -246,6 +248,7 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end,
if (!add) if (!add)
return -1; return -1;
break; break;
case GRUB_ACPI_OPCODE_CREATE_DWORD_FIELD:
case GRUB_ACPI_OPCODE_CREATE_WORD_FIELD: case GRUB_ACPI_OPCODE_CREATE_WORD_FIELD:
case GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD: case GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD:
{ {

View file

@ -140,10 +140,13 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args)
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
} }
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); if (utcount)
for (j = 0; j < utcount; j++) {
grub_printf ("<%x>", (unsigned int) utbuf[j]); grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); for (j = 0; j < utcount; j++)
grub_printf ("<%x>", (unsigned int) utbuf[j]);
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
}
grub_xputs ("\n"); grub_xputs ("\n");
grub_refresh (); grub_refresh ();

View file

@ -45,7 +45,7 @@ static grub_err_t
grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[]) int argc, char *argv[])
{ {
int byte, bit; int byte = 0, bit = 0;
grub_err_t err; grub_err_t err;
grub_uint8_t value; grub_uint8_t value;
@ -67,7 +67,7 @@ static grub_err_t
grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)), grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[]) int argc, char *argv[])
{ {
int byte, bit; int byte = 0, bit = 0;
grub_err_t err; grub_err_t err;
grub_uint8_t value; grub_uint8_t value;
@ -85,7 +85,7 @@ static grub_err_t
grub_cmd_cmosset (struct grub_command *cmd __attribute__ ((unused)), grub_cmd_cmosset (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[]) int argc, char *argv[])
{ {
int byte, bit; int byte = 0, bit = 0;
grub_err_t err; grub_err_t err;
grub_uint8_t value; grub_uint8_t value;

View file

@ -253,6 +253,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
struct grub_command *cmd; struct grub_command *cmd;
char **cutargs; char **cutargs;
int cutargc; int cutargc;
grub_err_t err = GRUB_ERR_NONE;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
@ -314,6 +315,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1)); cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1));
if (!cutargs)
return grub_errno;
cutargc = argc - 1; cutargc = argc - 1;
grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2)); grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2));
cutargs[0] = args[0]; cutargs[0] = args[0];
@ -333,7 +336,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
if (!(cmd->func) (cmd, cutargc, cutargs)) if (!(cmd->func) (cmd, cutargc, cutargs))
{ {
kernel_type = LINUX; kernel_type = LINUX;
return GRUB_ERR_NONE; goto out;
} }
} }
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
@ -348,7 +351,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
if (!(cmd->func) (cmd, argc, args)) if (!(cmd->func) (cmd, argc, args))
{ {
kernel_type = MULTIBOOT; kernel_type = MULTIBOOT;
return GRUB_ERR_NONE; goto out;
} }
} }
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
@ -413,7 +416,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
if (!(cmd->func) (cmd, cutargc, cutargs)) if (!(cmd->func) (cmd, cutargc, cutargs))
{ {
kernel_type = KFREEBSD; kernel_type = KFREEBSD;
return GRUB_ERR_NONE; goto out;
} }
} }
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
@ -422,6 +425,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
char **bsdargs; char **bsdargs;
int bsdargc; int bsdargc;
char bsddevname[sizeof ("wdXXXXXXXXXXXXY")]; char bsddevname[sizeof ("wdXXXXXXXXXXXXY")];
int found = 0;
if (bsd_device == -1) if (bsd_device == -1)
{ {
bsdargs = cutargs; bsdargs = cutargs;
@ -432,6 +437,11 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
char rbuf[3] = "-r"; char rbuf[3] = "-r";
bsdargc = cutargc + 2; bsdargc = cutargc + 2;
bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc); bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc);
if (!bsdargs)
{
err = grub_errno;
goto out;
}
grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0])); grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0]));
bsdargs[argc] = rbuf; bsdargs[argc] = rbuf;
bsdargs[argc + 1] = bsddevname; bsdargs[argc + 1] = bsddevname;
@ -447,7 +457,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
if (!(cmd->func) (cmd, bsdargc, bsdargs)) if (!(cmd->func) (cmd, bsdargc, bsdargs))
{ {
kernel_type = KNETBSD; kernel_type = KNETBSD;
return GRUB_ERR_NONE; found = 1;
goto free_bsdargs;
} }
} }
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
@ -460,20 +471,28 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)),
if (!(cmd->func) (cmd, bsdargc, bsdargs)) if (!(cmd->func) (cmd, bsdargc, bsdargs))
{ {
kernel_type = KOPENBSD; kernel_type = KOPENBSD;
return GRUB_ERR_NONE; found = 1;
goto free_bsdargs;
} }
} }
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
} }
free_bsdargs:
if (bsdargs != cutargs) if (bsdargs != cutargs)
grub_free (bsdargs); grub_free (bsdargs);
if (found)
goto out;
} }
} }
} }
while (0); while (0);
return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s", err = grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s",
args[0]); args[0]);
out:
grub_free (cutargs);
return err;
} }
static grub_err_t static grub_err_t
@ -534,15 +553,17 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused
char **newargs; char **newargs;
grub_err_t err; grub_err_t err;
char nounzipbuf[10] = "--nounzip"; char nounzipbuf[10] = "--nounzip";
cmd = grub_command_find ("module");
if (!cmd)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
"module");
newargs = grub_malloc ((argc + 1) * sizeof (newargs[0])); newargs = grub_malloc ((argc + 1) * sizeof (newargs[0]));
if (!newargs) if (!newargs)
return grub_errno; return grub_errno;
grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0])); grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0]));
newargs[0] = nounzipbuf; newargs[0] = nounzipbuf;
cmd = grub_command_find ("module");
if (!cmd)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"),
"module");
err = cmd->func (cmd, argc + 1, newargs); err = cmd->func (cmd, argc + 1, newargs);
grub_free (newargs); grub_free (newargs);

View file

@ -198,7 +198,10 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
return grub_errno; return grub_errno;
if (get_uuid (NULL, &uuid_root, 0)) if (get_uuid (NULL, &uuid_root, 0))
return grub_errno; {
grub_free (mods);
return grub_errno;
}
prefdev = grub_file_get_device_name (prefix); prefdev = grub_file_get_device_name (prefix);
if (grub_errno) if (grub_errno)
@ -210,6 +213,8 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
if (get_uuid (prefdev, &uuid_prefix, 0)) if (get_uuid (prefdev, &uuid_prefix, 0))
{ {
grub_free (uuid_root); grub_free (uuid_root);
grub_free (prefdev);
grub_free (mods);
return grub_errno; return grub_errno;
} }
@ -289,12 +294,15 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
} }
grub_free (uuid_root); grub_free (uuid_root);
grub_free (uuid_prefix); grub_free (uuid_prefix);
grub_free (prefdev);
grub_free (mods);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
fail: fail:
grub_free (uuid_root); grub_free (uuid_root);
grub_free (uuid_prefix); grub_free (uuid_prefix);
grub_free (prefdev);
for (i = 0; i < mods_loaded; i++) for (i = 0; i < mods_loaded; i++)
if (mods[i]) if (mods[i])
@ -302,6 +310,8 @@ grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)),
mods[i]->fini = 0; mods[i]->fini = 0;
grub_dl_unload (mods[i]); grub_dl_unload (mods[i]);
} }
grub_free (mods);
return grub_errno; return grub_errno;
} }

View file

@ -283,6 +283,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
} }
if (! cur) if (! cur)
{ {
grub_free (parsed);
grub_device_close (dev); grub_device_close (dev);
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"), return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"),
args[i]); args[i]);

View file

@ -45,6 +45,7 @@ check_password (const char *user, const char *entered, void *pin)
grub_uint8_t *buf; grub_uint8_t *buf;
struct pbkdf2_password *pass = pin; struct pbkdf2_password *pass = pin;
gcry_err_code_t err; gcry_err_code_t err;
grub_err_t ret;
buf = grub_malloc (pass->buflen); buf = grub_malloc (pass->buflen);
if (!buf) if (!buf)
@ -55,17 +56,17 @@ check_password (const char *user, const char *entered, void *pin)
pass->salt, pass->saltlen, pass->c, pass->salt, pass->saltlen, pass->c,
buf, pass->buflen); buf, pass->buflen);
if (err) if (err)
ret = grub_crypto_gcry_error (err);
else if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0)
ret = GRUB_ACCESS_DENIED;
else
{ {
grub_free (buf); grub_auth_authenticate (user);
return grub_crypto_gcry_error (err); ret = GRUB_ERR_NONE;
} }
if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0) grub_free (buf);
return GRUB_ACCESS_DENIED; return ret;
grub_auth_authenticate (user);
return GRUB_ERR_NONE;
} }
static inline int static inline int

View file

@ -68,7 +68,7 @@ iterate_device (const char *name, void *data)
/* Skip floppy drives when requested. */ /* Skip floppy drives when requested. */
if (ctx->no_floppy && if (ctx->no_floppy &&
name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9')
return 0; return 1;
#if defined(DO_SEARCH_FS_UUID) || defined(DO_SEARCH_DISK_UUID) #if defined(DO_SEARCH_FS_UUID) || defined(DO_SEARCH_DISK_UUID)
#define compare_fn grub_strcasecmp #define compare_fn grub_strcasecmp

View file

@ -338,19 +338,19 @@ grub_load_public_key (grub_file_t f)
if (grub_file_read (f, &l, sizeof (l)) != sizeof (l)) if (grub_file_read (f, &l, sizeof (l)) != sizeof (l))
{ {
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
goto fail; break;
} }
lb = (grub_be_to_cpu16 (l) + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT; lb = (grub_be_to_cpu16 (l) + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT;
if (lb > READBUF_SIZE - sizeof (grub_uint16_t)) if (lb > READBUF_SIZE - sizeof (grub_uint16_t))
{ {
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
goto fail; break;
} }
if (grub_file_read (f, buffer + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb) if (grub_file_read (f, buffer + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb)
{ {
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
goto fail; break;
} }
grub_memcpy (buffer, &l, sizeof (l)); grub_memcpy (buffer, &l, sizeof (l));
@ -360,10 +360,16 @@ grub_load_public_key (grub_file_t f)
buffer, lb + sizeof (grub_uint16_t), 0)) buffer, lb + sizeof (grub_uint16_t), 0))
{ {
grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature"));
goto fail; break;
} }
} }
if (i < pkalgos[pk].nmpipub)
{
grub_free (sk);
goto fail;
}
GRUB_MD_SHA1->final (fingerprint_context); GRUB_MD_SHA1->final (fingerprint_context);
grub_memcpy (sk->fingerprint, GRUB_MD_SHA1->read (fingerprint_context), 20); grub_memcpy (sk->fingerprint, GRUB_MD_SHA1->read (fingerprint_context), 20);

View file

@ -32,7 +32,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
struct grub_ahci_cmd_head struct grub_ahci_cmd_head
{ {
grub_uint32_t config; grub_uint32_t config;
grub_uint32_t transfered; grub_uint32_t transferred;
grub_uint64_t command_table_base; grub_uint64_t command_table_base;
grub_uint32_t unused[4]; grub_uint32_t unused[4];
}; };
@ -954,7 +954,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
grub_dprintf ("ahci", "AHCI tfd = %x\n", grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data); dev->hba->ports[dev->port].task_file_data);
dev->command_list[0].transfered = 0; dev->command_list[0].transferred = 0;
dev->command_list[0].command_table_base dev->command_list[0].command_table_base
= grub_dma_get_phys (dev->command_table_chunk); = grub_dma_get_phys (dev->command_table_chunk);
@ -1044,7 +1044,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
dev->hba->ports[dev->port].command_issue, dev->hba->ports[dev->port].command_issue,
dev->hba->ports[dev->port].intstatus, dev->hba->ports[dev->port].intstatus,
dev->hba->ports[dev->port].task_file_data, dev->hba->ports[dev->port].task_file_data,
dev->command_list[0].transfered, dev->command_list[0].transferred,
dev->hba->ports[dev->port].sata_error, dev->hba->ports[dev->port].sata_error,
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x00], ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x00],
((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x18]); ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x18]);

View file

@ -85,6 +85,12 @@ make_devices (void)
{ {
/* Uggh. */ /* Uggh. */
grub_free (handles); grub_free (handles);
while (devices)
{
d = devices->next;
grub_free (devices);
devices = d;
}
return 0; return 0;
} }
@ -487,8 +493,15 @@ grub_efidisk_open (const char *name, struct grub_disk *disk)
m = d->block_io->media; m = d->block_io->media;
/* FIXME: Probably it is better to store the block size in the disk, /* FIXME: Probably it is better to store the block size in the disk,
and total sectors should be replaced with total blocks. */ and total sectors should be replaced with total blocks. */
grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n", grub_dprintf ("efidisk",
m, (unsigned long long) m->last_block, m->block_size); "m = %p, last block = %llx, block size = %x, io align = %x\n",
m, (unsigned long long) m->last_block, m->block_size,
m->io_align);
/* Ensure required buffer alignment is a power of two (or is zero). */
if (m->io_align & (m->io_align - 1))
return grub_error (GRUB_ERR_IO, "invalid buffer alignment %d", m->io_align);
disk->total_sectors = m->last_block + 1; disk->total_sectors = m->last_block + 1;
/* Don't increase this value due to bug in some EFI. */ /* Don't increase this value due to bug in some EFI. */
disk->max_agglomerate = 0xa0000 >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS); disk->max_agglomerate = 0xa0000 >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS);
@ -518,15 +531,42 @@ grub_efidisk_readwrite (struct grub_disk *disk, grub_disk_addr_t sector,
{ {
struct grub_efidisk_data *d; struct grub_efidisk_data *d;
grub_efi_block_io_t *bio; grub_efi_block_io_t *bio;
grub_efi_status_t status;
grub_size_t io_align, num_bytes;
char *aligned_buf;
d = disk->data; d = disk->data;
bio = d->block_io; bio = d->block_io;
return efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio, /* Set alignment to 1 if 0 specified */
bio->media->media_id, io_align = bio->media->io_align ? bio->media->io_align : 1;
(grub_efi_uint64_t) sector, num_bytes = size << disk->log_sector_size;
(grub_efi_uintn_t) size << disk->log_sector_size,
buf); if ((grub_addr_t) buf & (io_align - 1))
{
aligned_buf = grub_memalign (io_align, num_bytes);
if (! aligned_buf)
return GRUB_EFI_OUT_OF_RESOURCES;
if (wr)
grub_memcpy (aligned_buf, buf, num_bytes);
}
else
{
aligned_buf = buf;
}
status = efi_call_5 ((wr ? bio->write_blocks : bio->read_blocks), bio,
bio->media->media_id, (grub_efi_uint64_t) sector,
(grub_efi_uintn_t) num_bytes, aligned_buf);
if ((grub_addr_t) buf & (io_align - 1))
{
if (!wr)
grub_memcpy (buf, aligned_buf, num_bytes);
grub_free (aligned_buf);
}
return status;
} }
static grub_err_t static grub_err_t
@ -541,7 +581,9 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector,
status = grub_efidisk_readwrite (disk, sector, size, buf, 0); status = grub_efidisk_readwrite (disk, sector, size, buf, 0);
if (status != GRUB_EFI_SUCCESS) if (status == GRUB_EFI_NO_MEDIA)
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("no media in `%s'"), disk->name);
else if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_READ_ERROR, return grub_error (GRUB_ERR_READ_ERROR,
N_("failure reading sector 0x%llx from `%s'"), N_("failure reading sector 0x%llx from `%s'"),
(unsigned long long) sector, (unsigned long long) sector,
@ -562,7 +604,9 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector,
status = grub_efidisk_readwrite (disk, sector, size, (char *) buf, 1); status = grub_efidisk_readwrite (disk, sector, size, (char *) buf, 1);
if (status != GRUB_EFI_SUCCESS) if (status == GRUB_EFI_NO_MEDIA)
return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("no media in `%s'"), disk->name);
else if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_WRITE_ERROR, return grub_error (GRUB_ERR_WRITE_ERROR,
N_("failure writing sector 0x%llx to `%s'"), N_("failure writing sector 0x%llx to `%s'"),
(unsigned long long) sector, disk->name); (unsigned long long) sector, disk->name);

View file

@ -154,7 +154,10 @@ grub_efiemu_init_segments (grub_efiemu_segment_t *segs, const Elf_Ehdr *e)
s->sh_flags & SHF_EXECINSTR ? GRUB_EFI_RUNTIME_SERVICES_CODE s->sh_flags & SHF_EXECINSTR ? GRUB_EFI_RUNTIME_SERVICES_CODE
: GRUB_EFI_RUNTIME_SERVICES_DATA); : GRUB_EFI_RUNTIME_SERVICES_DATA);
if (seg->handle < 0) if (seg->handle < 0)
return grub_errno; {
grub_free (seg);
return grub_errno;
}
seg->off = 0; seg->off = 0;
} }
@ -343,7 +346,7 @@ SUFFIX (grub_efiemu_loadcore_init) (void *core, const char *filename,
return grub_error (GRUB_ERR_BAD_MODULE, N_("this ELF file is not of the right type")); return grub_error (GRUB_ERR_BAD_MODULE, N_("this ELF file is not of the right type"));
/* Make sure that every section is within the core. */ /* Make sure that every section is within the core. */
if ((grub_size_t) core_size < e->e_shoff + e->e_shentsize * e->e_shnum) if ((grub_size_t) core_size < e->e_shoff + (grub_uint32_t) e->e_shentsize * e->e_shnum)
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
filename); filename);

View file

@ -196,7 +196,7 @@ grub_efiemu_load_file (const char *filename)
{ {
grub_file_close (file); grub_file_close (file);
grub_efiemu_unload (); grub_efiemu_unload ();
return grub_errno; return err;
} }
grub_dprintf ("efiemu", "mm initialized\n"); grub_dprintf ("efiemu", "mm initialized\n");

View file

@ -99,7 +99,8 @@ grub_efiemu_request_memalign (grub_size_t align, grub_size_t size,
grub_size_t align_overhead; grub_size_t align_overhead;
struct grub_efiemu_memrequest *ret, *cur, *prev; struct grub_efiemu_memrequest *ret, *cur, *prev;
/* Check that the request is correct */ /* Check that the request is correct */
if (type >= GRUB_EFI_MAX_MEMORY_TYPE || type <= GRUB_EFI_LOADER_CODE) if (type <= GRUB_EFI_LOADER_CODE || type == GRUB_EFI_PERSISTENT_MEMORY ||
type >= GRUB_EFI_MAX_MEMORY_TYPE)
return -2; return -2;
/* Add new size to requested size */ /* Add new size to requested size */
@ -166,6 +167,13 @@ efiemu_alloc_requests (void)
GRUB_EFI_MEMORY_MAPPED_IO, GRUB_EFI_MEMORY_MAPPED_IO,
GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE, GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE,
GRUB_EFI_PAL_CODE GRUB_EFI_PAL_CODE
/*
* These are not allocatable:
* GRUB_EFI_RESERVED_MEMORY_TYPE
* GRUB_EFI_PERSISTENT_MEMORY
* >= GRUB_EFI_MAX_MEMORY_TYPE
*/
}; };
/* Compute total memory needed */ /* Compute total memory needed */
@ -402,6 +410,10 @@ fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type,
return grub_efiemu_add_to_mmap (addr, size, return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_ACPI_MEMORY_NVS); GRUB_EFI_ACPI_MEMORY_NVS);
case GRUB_MEMORY_PERSISTENT:
case GRUB_MEMORY_PERSISTENT_LEGACY:
return grub_efiemu_add_to_mmap (addr, size,
GRUB_EFI_PERSISTENT_MEMORY);
default: default:
grub_dprintf ("efiemu", grub_dprintf ("efiemu",
"Unknown memory type %d. Assuming unusable\n", type); "Unknown memory type %d. Assuming unusable\n", type);
@ -445,7 +457,7 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
case GRUB_EFI_MEMORY_MAPPED_IO: case GRUB_EFI_MEMORY_MAPPED_IO:
case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE: case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE:
case GRUB_EFI_PAL_CODE: case GRUB_EFI_PAL_CODE:
case GRUB_EFI_MAX_MEMORY_TYPE: default:
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
GRUB_MEMORY_RESERVED, hook_data); GRUB_MEMORY_RESERVED, hook_data);
break; break;
@ -468,6 +480,12 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
GRUB_MEMORY_NVS, hook_data); GRUB_MEMORY_NVS, hook_data);
break; break;
case GRUB_EFI_PERSISTENT_MEMORY:
hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096,
GRUB_MEMORY_PERSISTENT, hook_data);
break;
} }
return 0; return 0;
@ -503,7 +521,8 @@ grub_efiemu_mmap_sort_and_uniq (void)
[GRUB_EFI_ACPI_MEMORY_NVS] = 3, [GRUB_EFI_ACPI_MEMORY_NVS] = 3,
[GRUB_EFI_MEMORY_MAPPED_IO] = 4, [GRUB_EFI_MEMORY_MAPPED_IO] = 4,
[GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE] = 4, [GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE] = 4,
[GRUB_EFI_PAL_CODE] = 4 [GRUB_EFI_PAL_CODE] = 4,
[GRUB_EFI_PERSISTENT_MEMORY] = 4
}; };
int i, j, k, done; int i, j, k, done;

View file

@ -83,10 +83,16 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks,
((grub_uint8_t *) grub_efiemu_mm_obtain_request (handle) + off); ((grub_uint8_t *) grub_efiemu_mm_obtain_request (handle) + off);
/* Put pointer to the list of configuration tables in system table */ /* Put pointer to the list of configuration tables in system table */
grub_efiemu_write_value err = grub_efiemu_write_value
(&(SUFFIX (grub_efiemu_system_table)->configuration_table), 0, (&(SUFFIX (grub_efiemu_system_table)->configuration_table), 0,
conftable_handle, 0, 1, conftable_handle, 0, 1,
sizeof (SUFFIX (grub_efiemu_system_table)->configuration_table)); sizeof (SUFFIX (grub_efiemu_system_table)->configuration_table));
if (err)
{
grub_efiemu_unload ();
return err;
}
SUFFIX(grub_efiemu_system_table)->num_table_entries = cntconftables; SUFFIX(grub_efiemu_system_table)->num_table_entries = cntconftables;
/* Fill the list of configuration tables */ /* Fill the list of configuration tables */

View file

@ -681,7 +681,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node,
ctxt->dir.file_size ctxt->dir.file_size
= grub_cpu_to_le64 (sec.type_specific.stream_extension.file_size); = grub_cpu_to_le64 (sec.type_specific.stream_extension.file_size);
ctxt->dir.have_stream = 1; ctxt->dir.have_stream = 1;
ctxt->dir.is_contiguous = !!(dir.type_specific.stream_extension.flags ctxt->dir.is_contiguous = !!(sec.type_specific.stream_extension.flags
& grub_cpu_to_le16_compile_time (FLAG_CONTIGUOUS)); & grub_cpu_to_le16_compile_time (FLAG_CONTIGUOUS));
break; break;
case 0xc1: case 0xc1:

View file

@ -1308,6 +1308,7 @@ grub_hfs_open (struct grub_file *file, const char *name)
if (grub_hfs_find_dir (data, name, &found, GRUB_FSHELP_REG)) if (grub_hfs_find_dir (data, name, &found, GRUB_FSHELP_REG))
{ {
grub_free (data); grub_free (data);
grub_free (found);
grub_dl_unref (my_mod); grub_dl_unref (my_mod);
return grub_errno; return grub_errno;
} }

View file

@ -750,19 +750,15 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir,
if (dir->data->joliet && !ctx.filename) if (dir->data->joliet && !ctx.filename)
{ {
char *oldname, *semicolon; char *semicolon;
oldname = name;
ctx.filename = grub_iso9660_convert_string ctx.filename = grub_iso9660_convert_string
((grub_uint8_t *) oldname, dirent.namelen >> 1); ((grub_uint8_t *) name, dirent.namelen >> 1);
semicolon = grub_strrchr (ctx.filename, ';'); semicolon = grub_strrchr (ctx.filename, ';');
if (semicolon) if (semicolon)
*semicolon = '\0'; *semicolon = '\0';
if (ctx.filename_alloc)
grub_free (oldname);
ctx.filename_alloc = 1; ctx.filename_alloc = 1;
} }

View file

@ -104,7 +104,7 @@ decomp_block (struct grub_ntfs_comp *cc, grub_uint8_t *dest)
if (tag & 1) if (tag & 1)
{ {
grub_uint32_t i, len, delta, code, lmask, dshift; grub_uint32_t i, len, delta, code, lmask, dshift;
grub_uint16_t word; grub_uint16_t word = 0;
if (decomp_get16 (cc, &word)) if (decomp_get16 (cc, &word))
return grub_errno; return grub_errno;

View file

@ -76,8 +76,13 @@ GRUB_MOD_LICENSE ("GPLv3+");
/* incompat feature flags */ /* incompat feature flags */
#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */
#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */
#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */
/* We do not currently verify metadata UUID so it is safe to read such filesystem */
#define XFS_SB_FEAT_INCOMPAT_SUPPORTED \ #define XFS_SB_FEAT_INCOMPAT_SUPPORTED \
(XFS_SB_FEAT_INCOMPAT_FTYPE) (XFS_SB_FEAT_INCOMPAT_FTYPE | \
XFS_SB_FEAT_INCOMPAT_META_UUID)
struct grub_xfs_sblock struct grub_xfs_sblock
{ {
@ -775,7 +780,10 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir,
c = de->name[de->len]; c = de->name[de->len];
de->name[de->len] = '\0'; de->name[de->len] = '\0';
if (iterate_dir_call_hook (ino, de->name, &ctx)) if (iterate_dir_call_hook (ino, de->name, &ctx))
return 1; {
de->name[de->len] = c;
return 1;
}
de->name[de->len] = c; de->name[de->len] = c;
de = grub_xfs_inline_next_de(dir->data, head, de); de = grub_xfs_inline_next_de(dir->data, head, de);

View file

@ -3132,7 +3132,7 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data)
{ {
void *osp; void *osp;
blkptr_t *bp; blkptr_t *bp;
grub_size_t ospsize; grub_size_t ospsize = 0;
grub_err_t err; grub_err_t err;
grub_dprintf ("zfs", "endian = %d\n", mdn->endian); grub_dprintf ("zfs", "endian = %d\n", mdn->endian);

View file

@ -184,6 +184,8 @@ LZ4_uncompress_unknownOutputSize(const char *source,
} }
} }
/* copy literals */ /* copy literals */
if ((grub_addr_t) length > ~(grub_addr_t)op)
goto _output_error;
cpy = op + length; cpy = op + length;
if ((cpy > oend - COPYLENGTH) || if ((cpy > oend - COPYLENGTH) ||
(ip + length > iend - COPYLENGTH)) { (ip + length > iend - COPYLENGTH)) {

View file

@ -15,12 +15,12 @@ set -e
# #
# Example: # Example:
# #
# genmod.sh moddep.lst normal.module normal.mod # genmod.sh moddep.lst normal.module build-grub-module-verifier normal.mod
# #
moddep=$1 moddep=$1
infile=$2 infile=$2
outfile=$3 outfile=$4
tmpfile=${outfile}.tmp tmpfile=${outfile}.tmp
modname=`echo $infile | sed -e 's@\.module.*$@@'` modname=`echo $infile | sed -e 's@\.module.*$@@'`
@ -58,7 +58,7 @@ if test x@TARGET_APPLE_LINKER@ != x1; then
-K grub_mod_init -K grub_mod_fini \ -K grub_mod_init -K grub_mod_fini \
-K _grub_mod_init -K _grub_mod_fini \ -K _grub_mod_init -K _grub_mod_fini \
-R .note.gnu.gold-version -R .note.GNU-stack \ -R .note.gnu.gold-version -R .note.GNU-stack \
-R .note -R .comment $tmpfile || exit 1 -R .note -R .comment -R .ARM.exidx $tmpfile || exit 1
fi fi
if ! test -z "${TARGET_OBJ2ELF}"; then if ! test -z "${TARGET_OBJ2ELF}"; then
"${TARGET_OBJ2ELF}" $tmpfile || exit 1 "${TARGET_OBJ2ELF}" $tmpfile || exit 1
@ -91,6 +91,9 @@ else
-nr:_grub_mod_init:grub_mod_init \ -nr:_grub_mod_init:grub_mod_init \
-nr:_grub_mod_fini:grub_mod_fini \ -nr:_grub_mod_fini:grub_mod_fini \
-wd1106 -nu -nd $tmpfile.bin $tmpfile || exit 1 -wd1106 -nu -nd $tmpfile.bin $tmpfile || exit 1
rm -f $name.bin rm -f $tmpfile.bin
fi
if test x@platform@ != xemu; then
./build-grub-module-verifier@BUILD_EXEEXT@ $tmpfile @target_cpu@
fi fi
mv $tmpfile $outfile mv $tmpfile $outfile

View file

@ -45,6 +45,7 @@ grub_font_draw_string (const char *str, grub_font_t font,
grub_uint32_t *logical; grub_uint32_t *logical;
grub_ssize_t logical_len, visual_len; grub_ssize_t logical_len, visual_len;
struct grub_unicode_glyph *visual, *ptr; struct grub_unicode_glyph *visual, *ptr;
grub_err_t err;
logical_len = grub_utf8_to_ucs4_alloc (str, &logical, 0); logical_len = grub_utf8_to_ucs4_alloc (str, &logical, 0);
if (logical_len < 0) if (logical_len < 0)
@ -56,24 +57,28 @@ grub_font_draw_string (const char *str, grub_font_t font,
if (visual_len < 0) if (visual_len < 0)
return grub_errno; return grub_errno;
err = GRUB_ERR_NONE;
for (ptr = visual, x = left_x; ptr < visual + visual_len; ptr++) for (ptr = visual, x = left_x; ptr < visual + visual_len; ptr++)
{ {
grub_err_t err;
struct grub_font_glyph *glyph; struct grub_font_glyph *glyph;
glyph = grub_font_construct_glyph (font, ptr); glyph = grub_font_construct_glyph (font, ptr);
if (!glyph) if (!glyph)
return grub_errno; {
err = grub_errno;
goto out;
}
err = grub_font_draw_glyph (glyph, color, x, baseline_y); err = grub_font_draw_glyph (glyph, color, x, baseline_y);
x += glyph->device_width;
if (err) if (err)
return err; goto out;
x += glyph->device_width;
} }
out:
for (ptr = visual; ptr < visual + visual_len; ptr++) for (ptr = visual; ptr < visual + visual_len; ptr++)
grub_unicode_destroy_glyph (ptr); grub_unicode_destroy_glyph (ptr);
grub_free (visual); grub_free (visual);
return GRUB_ERR_NONE; return err;
} }
/* Get the width in pixels of the specified UTF-8 string, when rendered in /* Get the width in pixels of the specified UTF-8 string, when rendered in

View file

@ -63,14 +63,14 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"),
"theme"); "theme");
instance = grub_zalloc (sizeof (*instance));
if (!instance)
return grub_errno;
err = grub_video_get_info (&mode_info); err = grub_video_get_info (&mode_info);
if (err) if (err)
return err; return err;
instance = grub_zalloc (sizeof (*instance));
if (!instance)
return grub_errno;
if (theme_path[0] != '/' && theme_path[0] != '(') if (theme_path[0] != '/' && theme_path[0] != '(')
{ {
const char *prefix; const char *prefix;

View file

@ -32,3 +32,88 @@ grub_byte_checksum (void *base, grub_size_t size)
ret += *ptr; ret += *ptr;
return ret; return ret;
} }
static void *
grub_acpi_rsdt_find_table (struct grub_acpi_table_header *rsdt, const char *sig)
{
grub_size_t s;
grub_unaligned_uint32_t *ptr;
if (!rsdt)
return 0;
if (grub_memcmp (rsdt->signature, "RSDT", 4) != 0)
return 0;
ptr = (grub_unaligned_uint32_t *) (rsdt + 1);
s = (rsdt->length - sizeof (*rsdt)) / sizeof (grub_uint32_t);
for (; s; s--, ptr++)
{
struct grub_acpi_table_header *tbl;
tbl = (struct grub_acpi_table_header *) (grub_addr_t) ptr->val;
if (grub_memcmp (tbl->signature, sig, 4) == 0)
return tbl;
}
return 0;
}
static void *
grub_acpi_xsdt_find_table (struct grub_acpi_table_header *xsdt, const char *sig)
{
grub_size_t s;
grub_unaligned_uint64_t *ptr;
if (!xsdt)
return 0;
if (grub_memcmp (xsdt->signature, "XSDT", 4) != 0)
return 0;
ptr = (grub_unaligned_uint64_t *) (xsdt + 1);
s = (xsdt->length - sizeof (*xsdt)) / sizeof (grub_uint32_t);
for (; s; s--, ptr++)
{
struct grub_acpi_table_header *tbl;
#if GRUB_CPU_SIZEOF_VOID_P != 8
if (ptr->val >> 32)
continue;
#endif
tbl = (struct grub_acpi_table_header *) (grub_addr_t) ptr->val;
if (grub_memcmp (tbl->signature, sig, 4) == 0)
return tbl;
}
return 0;
}
struct grub_acpi_fadt *
grub_acpi_find_fadt (void)
{
struct grub_acpi_fadt *fadt = 0;
struct grub_acpi_rsdp_v10 *rsdpv1;
struct grub_acpi_rsdp_v20 *rsdpv2;
rsdpv1 = grub_machine_acpi_get_rsdpv1 ();
if (rsdpv1)
fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *)
(grub_addr_t) rsdpv1->rsdt_addr,
GRUB_ACPI_FADT_SIGNATURE);
if (fadt)
return fadt;
rsdpv2 = grub_machine_acpi_get_rsdpv2 ();
if (rsdpv2)
fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *)
(grub_addr_t) rsdpv2->rsdpv1.rsdt_addr,
GRUB_ACPI_FADT_SIGNATURE);
if (fadt)
return fadt;
if (rsdpv2
#if GRUB_CPU_SIZEOF_VOID_P != 8
&& !(rsdpv2->xsdt_addr >> 32)
#endif
)
fadt = grub_acpi_xsdt_find_table ((struct grub_acpi_table_header *)
(grub_addr_t) rsdpv2->xsdt_addr,
GRUB_ACPI_FADT_SIGNATURE);
if (fadt)
return fadt;
return 0;
}

View file

@ -38,7 +38,7 @@ static void
increment_timer (grub_efi_event_t event __attribute__ ((unused)), increment_timer (grub_efi_event_t event __attribute__ ((unused)),
void *context __attribute__ ((unused))) void *context __attribute__ ((unused)))
{ {
tmr++; tmr += 10;
} }
void void
@ -52,7 +52,7 @@ grub_machine_init (void)
efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL, efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL,
GRUB_EFI_TPL_CALLBACK, increment_timer, NULL, &tmr_evt); GRUB_EFI_TPL_CALLBACK, increment_timer, NULL, &tmr_evt);
efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 10000); efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 100000);
grub_install_get_time_ms (grub_efi_get_time_ms); grub_install_get_time_ms (grub_efi_get_time_ms);
} }

View file

@ -55,10 +55,6 @@ FUNCTION(_start)
VARIABLE(grub_total_module_size) VARIABLE(grub_total_module_size)
.long 0 .long 0
VARIABLE(grub_uboot_machine_type)
.long 0
VARIABLE(grub_uboot_boot_data)
.long 0
VARIABLE(grub_modbase) VARIABLE(grub_modbase)
.long 0 .long 0
bss_start_ptr: bss_start_ptr:
@ -66,29 +62,66 @@ bss_start_ptr:
end_ptr: end_ptr:
.long EXT_C(_end) .long EXT_C(_end)
@ Memory map at start:
@ * text+data
@ * list relocations
@ * modules
@ Before we enter C, we need to apply the relocations
@ and get following map:
@ * text+data
@ * BSS (cleared)
@ * stack
@ * modules
@
@ To make things easier we ensure
@ that BSS+stack is larger than list of relocations
@ by increasing stack if necessarry.
@ This allows us to always unconditionally copy backwards
@ Currently list of relocations is ~5K and stack is set
@ to be at least 256K
FUNCTION(codestart) FUNCTION(codestart)
@ Store context: Machine ID, atags/dtb, ... @ Store context: Machine ID, atags/dtb, ...
@ U-Boot API signature is stored on the U-Boot heap @ U-Boot API signature is stored on the U-Boot heap
@ Stack pointer used as start address for signature probing @ Stack pointer used as start address for signature probing
mov r12, sp mov r12, sp
adr sp, entry_state adr sp, entry_state
push {r4-r12,lr} @ store U-Boot context (sp in r12) push {r1-r12,lr} @ store U-Boot context (sp in r12)
str r1, EXT_C(grub_uboot_machine_type) adr r1, _start
str r2, EXT_C(grub_uboot_boot_data)
@ Modules have been stored as a blob in BSS,
@ they need to be manually relocated to _end
ldr r0, bss_start_ptr @ src ldr r0, bss_start_ptr @ src
add r0, r0, r1
add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
mvn r2, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
and r0, r0, r2
1:
ldr r3, [r0], #4 @load next offset
@ both -2 and -1 are treated the same as we have only one type of relocs
@ -2 means "end of this type of relocs" and -1 means "end of all relocs"
add r2, r3, #2
cmp r2, #1
bls reloc_done
@ Adjust next offset
ldr r2, [r3, r1]
add r2, r2, r1
str r2, [r3, r1]
b 1b
reloc_done:
@ Modules have been stored as a blob
@ they need to be manually relocated to _end
add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
mvn r1, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) mvn r1, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1)
and r0, r0, r1 and r0, r0, r1 @ src = aligned end of relocations
ldr r1, end_ptr @ dst = End of BSS ldr r1, end_ptr @ dst = End of BSS
ldr r2, grub_total_module_size @ blob size ldr r2, grub_total_module_size @ blob size
add r1, r1, #GRUB_KERNEL_MACHINE_STACK_SIZE add r1, r1, #GRUB_KERNEL_MACHINE_STACK_SIZE
and r1, r1, #~0x7 @ Ensure 8-byte alignment and r1, r1, #~0x7 @ Ensure 8-byte alignment
sub sp, r1, #8 sub sp, r1, #8
add r1, r1, #1024 add r1, r1, #1024
@ -157,6 +190,11 @@ FUNCTION(grub_uboot_return)
.align 3 .align 3
@ U-boot context stack space @ U-boot context stack space
entry_state_end: entry_state_end:
VARIABLE(grub_uboot_machine_type)
.long 0 @ r1
VARIABLE(grub_uboot_boot_data)
.long 0 @ r2
.long 0 @ r3
.long 0 @ r4 .long 0 @ r4
.long 0 @ r5 .long 0 @ r5
.long 0 @ r6 .long 0 @ r6

View file

@ -132,6 +132,12 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
*abs_place = (grub_uint64_t) sym_addr; *abs_place = (grub_uint64_t) sym_addr;
} }
break; break;
case R_AARCH64_ADD_ABS_LO12_NC:
grub_arm64_set_abs_lo12 (place, sym_addr);
break;
case R_AARCH64_LDST64_ABS_LO12_NC:
grub_arm64_set_abs_lo12_ldst64 (place, sym_addr);
break;
case R_AARCH64_CALL26: case R_AARCH64_CALL26:
case R_AARCH64_JUMP26: case R_AARCH64_JUMP26:
{ {
@ -154,6 +160,18 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
grub_arm64_set_xxxx26_offset (place, offset); grub_arm64_set_xxxx26_offset (place, offset);
} }
break; break;
case R_AARCH64_ADR_PREL_PG_HI21:
{
grub_int64_t offset = (sym_addr & ~0xfffULL) - (((grub_uint64_t) place) & ~0xfffULL);
if (!grub_arm64_check_hi21_signed (offset))
return grub_error (GRUB_ERR_BAD_MODULE,
"HI21 out of range");
grub_arm64_set_hi21 (place, offset);
}
break;
default: default:
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
N_("relocation 0x%x is not implemented yet"), N_("relocation 0x%x is not implemented yet"),

View file

@ -53,3 +53,43 @@ grub_arm64_set_xxxx26_offset (grub_uint32_t *place, grub_int64_t offset)
*place &= insmask; *place &= insmask;
*place |= grub_cpu_to_le32 (offset >> 2) & ~insmask; *place |= grub_cpu_to_le32 (offset >> 2) & ~insmask;
} }
int
grub_arm64_check_hi21_signed (grub_int64_t offset)
{
if (offset != (grub_int64_t)(grub_int32_t)offset)
return 0;
return 1;
}
void
grub_arm64_set_hi21 (grub_uint32_t *place, grub_int64_t offset)
{
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0x9f00001f);
grub_uint32_t val;
offset >>= 12;
val = ((offset & 3) << 29) | (((offset >> 2) & 0x7ffff) << 5);
*place &= insmask;
*place |= grub_cpu_to_le32 (val) & ~insmask;
}
void
grub_arm64_set_abs_lo12 (grub_uint32_t *place, grub_int64_t target)
{
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff);
*place &= insmask;
*place |= grub_cpu_to_le32 (target << 10) & ~insmask;
}
void
grub_arm64_set_abs_lo12_ldst64 (grub_uint32_t *place, grub_int64_t target)
{
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfff803ff);
*place &= insmask;
*place |= grub_cpu_to_le32 (target << 7) & ~insmask;
}

View file

@ -0,0 +1,60 @@
/* init.c - initialize an arm-based EFI system */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013 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/env.h>
#include <grub/kernel.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/efi/efi.h>
#include <grub/loader.h>
static grub_uint64_t timer_frequency_in_khz;
static grub_uint64_t
grub_efi_get_time_ms (void)
{
grub_uint64_t tmr;
asm volatile("mrs %0, cntvct_el0" : "=r" (tmr));
return tmr / timer_frequency_in_khz;
}
void
grub_machine_init (void)
{
grub_uint64_t timer_frequency;
grub_efi_init ();
asm volatile("mrs %0, cntfrq_el0" : "=r" (timer_frequency));
timer_frequency_in_khz = timer_frequency / 1000;
grub_install_get_time_ms (grub_efi_get_time_ms);
}
void
grub_machine_fini (int flags)
{
if (!(flags & GRUB_LOADER_FLAG_NORETURN))
return;
grub_efi_fini ();
}

View file

@ -342,8 +342,11 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
if (s->sh_type == SHT_SYMTAB) if (s->sh_type == SHT_SYMTAB)
break; break;
/* Module without symbol table may still be used to pull in dependencies.
We verify at build time that such modules do not contain any relocations
that may reference symbol table. */
if (i == e->e_shnum) if (i == e->e_shnum)
return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); return GRUB_ERR_NONE;
#ifdef GRUB_MODULES_MACHINE_READONLY #ifdef GRUB_MODULES_MACHINE_READONLY
mod->symtab = grub_malloc (s->sh_size); mod->symtab = grub_malloc (s->sh_size);
@ -585,6 +588,9 @@ grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
if (seg) if (seg)
{ {
if (!mod->symtab)
return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table");
err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg);
if (err) if (err)
return err; return err;
@ -614,7 +620,7 @@ grub_dl_load_core_noinit (void *addr, grub_size_t size)
} }
/* Make sure that every section is within the core. */ /* Make sure that every section is within the core. */
if (size < e->e_shoff + e->e_shentsize * e->e_shnum) if (size < e->e_shoff + (grub_uint32_t) e->e_shentsize * e->e_shnum)
{ {
grub_error (GRUB_ERR_BAD_OS, "ELF sections outside core"); grub_error (GRUB_ERR_BAD_OS, "ELF sections outside core");
return 0; return 0;

43
grub-core/kern/efi/fdt.c Normal file
View file

@ -0,0 +1,43 @@
/* fdt.c - EFI Flattened Device Tree interaction */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,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/efi/efi.h>
#include <grub/mm.h>
void *
grub_efi_get_firmware_fdt (void)
{
grub_efi_configuration_table_t *tables;
grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
void *firmware_fdt = NULL;
unsigned int i;
/* Look for FDT in UEFI config tables. */
tables = grub_efi_system_table->configuration_table;
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
if (grub_memcmp (&tables[i].vendor_guid, &fdt_guid, sizeof (fdt_guid)) == 0)
{
firmware_fdt = tables[i].vendor_table;
grub_dprintf ("linux", "found registered FDT @ %p\n", firmware_fdt);
break;
}
return firmware_fdt;
}

View file

@ -59,10 +59,13 @@ grub_machine_get_bootlocation (char **device, char **path)
if (!image) if (!image)
return; return;
*device = grub_efidisk_get_device_name (image->device_handle); *device = grub_efidisk_get_device_name (image->device_handle);
*path = grub_efi_get_filename (image->file_path);
if (!*device && grub_efi_net_config) if (!*device && grub_efi_net_config)
grub_efi_net_config (image->device_handle, device, path); {
grub_efi_net_config (image->device_handle, device, path);
return;
}
*path = grub_efi_get_filename (image->file_path);
if (*path) if (*path)
{ {
/* Get the directory. */ /* Get the directory. */

View file

@ -12,7 +12,7 @@ grub_elfXX_load_phdrs (grub_elf_t elf)
if (elf->phdrs) if (elf->phdrs)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
phdrs_size = elf->ehdr.ehdrXX.e_phnum * elf->ehdr.ehdrXX.e_phentsize; phdrs_size = (grub_uint32_t) elf->ehdr.ehdrXX.e_phnum * elf->ehdr.ehdrXX.e_phentsize;
grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n", grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n",
(unsigned long long) elf->ehdr.ehdrXX.e_phoff, (unsigned long long) elf->ehdr.ehdrXX.e_phoff,

View file

@ -161,9 +161,9 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
{ {
struct stat st; struct stat st;
# if GRUB_DISK_DEVS_ARE_CHAR # if GRUB_DISK_DEVS_ARE_CHAR
if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode)) if (fstat (fd, &st) >= 0 && S_ISCHR (st.st_mode))
# else # else
if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode)) if (fstat (fd, &st) >= 0 && S_ISBLK (st.st_mode))
# endif # endif
data->is_disk = 1; data->is_disk = 1;
} }

View file

@ -65,6 +65,12 @@ grub_reboot (void)
longjmp (main_env, 1); longjmp (main_env, 1);
} }
void
grub_exit (void)
{
grub_reboot ();
}
void void
grub_machine_init (void) grub_machine_init (void)
{ {
@ -86,11 +92,16 @@ grub_machine_fini (int flags)
#define OPT_MEMDISK 257
static struct argp_option options[] = { static struct argp_option options[] = {
{"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2}, {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2},
{"device-map", 'm', N_("FILE"), 0, {"device-map", 'm', N_("FILE"), 0,
/* TRANSLATORS: There are many devices in device map. */ /* TRANSLATORS: There are many devices in device map. */
N_("use FILE as the device map [default=%s]"), 0}, N_("use FILE as the device map [default=%s]"), 0},
{"memdisk", OPT_MEMDISK, N_("FILE"), 0,
/* TRANSLATORS: There are many devices in device map. */
N_("use FILE as memdisk"), 0},
{"directory", 'd', N_("DIR"), 0, {"directory", 'd', N_("DIR"), 0,
N_("use GRUB files in the directory DIR [default=%s]"), 0}, N_("use GRUB files in the directory DIR [default=%s]"), 0},
{"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, {"verbose", 'v', 0, 0, N_("print verbose messages."), 0},
@ -119,6 +130,7 @@ help_filter (int key, const char *text, void *input __attribute__ ((unused)))
struct arguments struct arguments
{ {
const char *dev_map; const char *dev_map;
const char *mem_disk;
int hold; int hold;
}; };
@ -131,6 +143,9 @@ argp_parser (int key, char *arg, struct argp_state *state)
switch (key) switch (key)
{ {
case OPT_MEMDISK:
arguments->mem_disk = arg;
break;
case 'r': case 'r':
free (root_dev); free (root_dev);
root_dev = xstrdup (arg); root_dev = xstrdup (arg);
@ -180,9 +195,13 @@ main (int argc, char *argv[])
struct arguments arguments = struct arguments arguments =
{ {
.dev_map = DEFAULT_DEVICE_MAP, .dev_map = DEFAULT_DEVICE_MAP,
.hold = 0 .hold = 0,
.mem_disk = 0,
}; };
volatile int hold = 0; volatile int hold = 0;
size_t total_module_size = sizeof (struct grub_module_info), memdisk_size = 0;
struct grub_module_info *modinfo;
void *mods;
grub_util_host_init (&argc, &argv); grub_util_host_init (&argc, &argv);
@ -194,6 +213,33 @@ main (int argc, char *argv[])
exit(1); exit(1);
} }
if (arguments.mem_disk)
{
memdisk_size = ALIGN_UP(grub_util_get_image_size (arguments.mem_disk), 512);
total_module_size += memdisk_size + sizeof (struct grub_module_header);
}
mods = xmalloc (total_module_size);
modinfo = grub_memset (mods, 0, total_module_size);
mods = (char *) (modinfo + 1);
modinfo->magic = GRUB_MODULE_MAGIC;
modinfo->offset = sizeof (struct grub_module_info);
modinfo->size = total_module_size;
if (arguments.mem_disk)
{
struct grub_module_header *header = (struct grub_module_header *) mods;
header->type = OBJ_TYPE_MEMDISK;
header->size = memdisk_size + sizeof (*header);
mods = header + 1;
grub_util_load_image (arguments.mem_disk, mods);
mods = (char *) mods + memdisk_size;
}
grub_modbase = (grub_addr_t) modinfo;
hold = arguments.hold; hold = arguments.hold;
/* Wait until the ARGS.HOLD variable is cleared by an attached debugger. */ /* Wait until the ARGS.HOLD variable is cleared by an attached debugger. */
if (hold && verbosity > 0) if (hold && verbosity > 0)

View file

@ -127,6 +127,7 @@ xasprintf (const char *fmt, ...)
va_start (ap, fmt); va_start (ap, fmt);
result = grub_xvasprintf (fmt, ap); result = grub_xvasprintf (fmt, ap);
va_end (ap);
if (!result) if (!result)
grub_util_error ("%s", _("out of memory")); grub_util_error ("%s", _("out of memory"));
@ -134,11 +135,13 @@ xasprintf (const char *fmt, ...)
} }
#endif #endif
#if !defined (GRUB_MACHINE_EMU) || defined (GRUB_UTIL)
void void
grub_exit (void) grub_exit (void)
{ {
exit (1); exit (1);
} }
#endif
grub_uint64_t grub_uint64_t
grub_get_time_ms (void) grub_get_time_ms (void)
@ -149,3 +152,51 @@ grub_get_time_ms (void)
return (tv.tv_sec * 1000 + tv.tv_usec / 1000); return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
} }
size_t
grub_util_get_image_size (const char *path)
{
FILE *f;
size_t ret;
off_t sz;
f = grub_util_fopen (path, "rb");
if (!f)
grub_util_error (_("cannot open `%s': %s"), path, strerror (errno));
fseeko (f, 0, SEEK_END);
sz = ftello (f);
if (sz < 0)
grub_util_error (_("cannot open `%s': %s"), path, strerror (errno));
if (sz != (size_t) sz)
grub_util_error (_("file `%s' is too big"), path);
ret = (size_t) sz;
fclose (f);
return ret;
}
void
grub_util_load_image (const char *path, char *buf)
{
FILE *fp;
size_t size;
grub_util_info ("reading %s", path);
size = grub_util_get_image_size (path);
fp = grub_util_fopen (path, "rb");
if (! fp)
grub_util_error (_("cannot open `%s': %s"), path,
strerror (errno));
if (fread (buf, 1, size, fp) != size)
grub_util_error (_("cannot read `%s': %s"), path,
strerror (errno));
fclose (fp);
}

View file

@ -44,6 +44,13 @@ FUNCTION(grub_bios_interrupt)
movl 24(%edx), %esi movl 24(%edx), %esi
movl 28(%edx), %edx movl 28(%edx), %edx
/*
Via C3 CPUs have cache coherence problems, so we need to call
wbinvd at these 2 points. As wbinvd slows down boot, don't do
it on non-VIA. 9090 is nop nop. */
VARIABLE(grub_bios_via_workaround1)
.byte 0x90, 0x90
PROT_TO_REAL PROT_TO_REAL
.code16 .code16
pushf pushf
@ -92,6 +99,10 @@ intno:
movw %ax, LOCAL(bios_register_es) movw %ax, LOCAL(bios_register_es)
popf popf
VARIABLE(grub_bios_via_workaround2)
.byte 0x90, 0x90
REAL_TO_PROT REAL_TO_PROT
.code32 .code32

View file

@ -32,6 +32,7 @@
#include <grub/env.h> #include <grub/env.h>
#include <grub/cache.h> #include <grub/cache.h>
#include <grub/time.h> #include <grub/time.h>
#include <grub/cpu/cpuid.h>
#include <grub/cpu/tsc.h> #include <grub/cpu/tsc.h>
#include <grub/machine/time.h> #include <grub/machine/time.h>
@ -184,6 +185,26 @@ mmap_iterate_hook (grub_uint64_t addr, grub_uint64_t size,
return 0; return 0;
} }
extern grub_uint16_t grub_bios_via_workaround1, grub_bios_via_workaround2;
/* Via needs additional wbinvd. */
static void
grub_via_workaround_init (void)
{
grub_uint32_t manufacturer[3], max_cpuid;
if (! grub_cpu_is_cpuid_supported ())
return;
grub_cpuid (0, max_cpuid, manufacturer[0], manufacturer[2], manufacturer[1]);
if (grub_memcmp (manufacturer, "CentaurHauls", 12) != 0)
return;
grub_bios_via_workaround1 = 0x090f;
grub_bios_via_workaround2 = 0x090f;
asm volatile ("wbinvd");
}
void void
grub_machine_init (void) grub_machine_init (void)
{ {
@ -193,6 +214,9 @@ grub_machine_init (void)
#endif #endif
grub_addr_t modend; grub_addr_t modend;
/* This has to happen before any BIOS calls. */
grub_via_workaround_init ();
grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start); grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start);
/* Initialize the console as early as possible. */ /* Initialize the console as early as possible. */

View file

@ -43,22 +43,6 @@ grub_tsc_get_time_ms (void)
return ((al * grub_tsc_rate) >> 32) + ah * grub_tsc_rate; return ((al * grub_tsc_rate) >> 32) + ah * grub_tsc_rate;
} }
static __inline int
grub_cpu_is_tsc_supported (void)
{
#ifndef GRUB_MACHINE_XEN
grub_uint32_t a,b,c,d;
if (! grub_cpu_is_cpuid_supported ())
return 0;
grub_cpuid(1,a,b,c,d);
return (d & (1 << 4)) != 0;
#else
return 1;
#endif
}
static int static int
calibrate_tsc_hardcode (void) calibrate_tsc_hardcode (void)
{ {

View file

@ -24,129 +24,35 @@
#include <grub/time.h> #include <grub/time.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/i386/tsc.h> #include <grub/i386/tsc.h>
#include <grub/i386/pmtimer.h>
#include <grub/acpi.h> #include <grub/acpi.h>
#include <grub/cpu/io.h> #include <grub/cpu/io.h>
static void * grub_uint64_t
grub_acpi_rsdt_find_table (struct grub_acpi_table_header *rsdt, const char *sig) grub_pmtimer_wait_count_tsc (grub_port_t pmtimer,
{ grub_uint16_t num_pm_ticks)
grub_size_t s;
grub_uint32_t *ptr;
if (!rsdt)
return 0;
if (grub_memcmp (rsdt->signature, "RSDT", 4) != 0)
return 0;
ptr = (grub_uint32_t *) (rsdt + 1);
s = (rsdt->length - sizeof (*rsdt)) / sizeof (grub_uint32_t);
for (; s; s--, ptr++)
{
struct grub_acpi_table_header *tbl;
tbl = (struct grub_acpi_table_header *) (grub_addr_t) *ptr;
if (grub_memcmp (tbl->signature, sig, 4) == 0)
return tbl;
}
return 0;
}
static void *
grub_acpi_xsdt_find_table (struct grub_acpi_table_header *xsdt, const char *sig)
{
grub_size_t s;
grub_uint64_t *ptr;
if (!xsdt)
return 0;
if (grub_memcmp (xsdt->signature, "XSDT", 4) != 0)
return 0;
ptr = (grub_uint64_t *) (xsdt + 1);
s = (xsdt->length - sizeof (*xsdt)) / sizeof (grub_uint32_t);
for (; s; s--, ptr++)
{
struct grub_acpi_table_header *tbl;
#if GRUB_CPU_SIZEOF_VOID_P != 8
if (*ptr >> 32)
continue;
#endif
tbl = (struct grub_acpi_table_header *) (grub_addr_t) *ptr;
if (grub_memcmp (tbl->signature, sig, 4) == 0)
return tbl;
}
return 0;
}
struct grub_acpi_fadt *
grub_acpi_find_fadt (void)
{
struct grub_acpi_fadt *fadt = 0;
struct grub_acpi_rsdp_v10 *rsdpv1;
struct grub_acpi_rsdp_v20 *rsdpv2;
rsdpv1 = grub_machine_acpi_get_rsdpv1 ();
if (rsdpv1)
fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *)
(grub_addr_t) rsdpv1->rsdt_addr,
GRUB_ACPI_FADT_SIGNATURE);
if (fadt)
return fadt;
rsdpv2 = grub_machine_acpi_get_rsdpv2 ();
if (rsdpv2)
fadt = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *)
(grub_addr_t) rsdpv2->rsdpv1.rsdt_addr,
GRUB_ACPI_FADT_SIGNATURE);
if (fadt)
return fadt;
if (rsdpv2
#if GRUB_CPU_SIZEOF_VOID_P != 8
&& !(rsdpv2->xsdt_addr >> 32)
#endif
)
fadt = grub_acpi_xsdt_find_table ((struct grub_acpi_table_header *)
(grub_addr_t) rsdpv2->xsdt_addr,
GRUB_ACPI_FADT_SIGNATURE);
if (fadt)
return fadt;
return 0;
}
int
grub_tsc_calibrate_from_pmtimer (void)
{ {
grub_uint32_t start; grub_uint32_t start;
grub_uint32_t last; grub_uint32_t last;
grub_uint32_t cur, end; grub_uint32_t cur, end;
struct grub_acpi_fadt *fadt;
grub_port_t p;
grub_uint64_t start_tsc; grub_uint64_t start_tsc;
grub_uint64_t end_tsc; grub_uint64_t end_tsc;
int num_iter = 0; int num_iter = 0;
fadt = grub_acpi_find_fadt (); start = grub_inl (pmtimer) & 0xffffff;
if (!fadt)
return 0;
p = fadt->pmtimer;
if (!p)
return 0;
start = grub_inl (p) & 0xffffff;
last = start; last = start;
/* It's 3.579545 MHz clock. Wait 1 ms. */ end = start + num_pm_ticks;
end = start + 3580;
start_tsc = grub_get_tsc (); start_tsc = grub_get_tsc ();
while (1) while (1)
{ {
cur = grub_inl (p) & 0xffffff; cur = grub_inl (pmtimer) & 0xffffff;
if (cur < last) if (cur < last)
cur |= 0x1000000; cur |= 0x1000000;
num_iter++; num_iter++;
if (cur >= end) if (cur >= end)
{ {
end_tsc = grub_get_tsc (); end_tsc = grub_get_tsc ();
grub_tsc_rate = grub_divmod64 ((1ULL << 32), end_tsc - start_tsc, 0); return end_tsc - start_tsc;
return 1;
} }
/* Check for broken PM timer. /* Check for broken PM timer.
50000000 TSCs is between 5 ms (10GHz) and 200 ms (250 MHz) 50000000 TSCs is between 5 ms (10GHz) and 200 ms (250 MHz)
@ -158,3 +64,25 @@ grub_tsc_calibrate_from_pmtimer (void)
} }
} }
} }
int
grub_tsc_calibrate_from_pmtimer (void)
{
struct grub_acpi_fadt *fadt;
grub_port_t pmtimer;
grub_uint64_t tsc_diff;
fadt = grub_acpi_find_fadt ();
if (!fadt)
return 0;
pmtimer = fadt->pmtimer;
if (!pmtimer)
return 0;
/* It's 3.579545 MHz clock. Wait 1 ms. */
tsc_diff = grub_pmtimer_wait_count_tsc (pmtimer, 3580);
if (tsc_diff == 0)
return 0;
grub_tsc_rate = grub_divmod64 ((1ULL << 32), tsc_diff, 0);
return 1;
}

View file

@ -46,11 +46,19 @@
#define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) #define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024)
/* The maximum heap size we're going to claim */ /* The maximum heap size we're going to claim */
#ifdef __i386__
#define HEAP_MAX_SIZE (unsigned long) (64 * 1024 * 1024)
#else
#define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024) #define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024)
#endif
/* If possible, we will avoid claiming heap above this address, because it /* If possible, we will avoid claiming heap above this address, because it
seems to cause relocation problems with OSes that link at 4 MiB */ seems to cause relocation problems with OSes that link at 4 MiB */
#ifdef __i386__
#define HEAP_MAX_ADDR (unsigned long) (64 * 1024 * 1024)
#else
#define HEAP_MAX_ADDR (unsigned long) (32 * 1024 * 1024) #define HEAP_MAX_ADDR (unsigned long) (32 * 1024 * 1024)
#endif
extern char _start[]; extern char _start[];
extern char _end[]; extern char _end[];

View file

@ -25,7 +25,7 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
{ {
grub_ieee1275_phandle_t root; grub_ieee1275_phandle_t root;
grub_ieee1275_phandle_t memory; grub_ieee1275_phandle_t memory;
grub_uint32_t available[32]; grub_uint32_t available[128];
grub_ssize_t available_size; grub_ssize_t available_size;
grub_uint32_t address_cells = 1; grub_uint32_t address_cells = 1;
grub_uint32_t size_cells = 1; grub_uint32_t size_cells = 1;
@ -49,6 +49,9 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data)
sizeof available, &available_size)) sizeof available, &available_size))
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"couldn't examine /memory/available property"); "couldn't examine /memory/available property");
if (available_size < 0 || (grub_size_t) available_size > sizeof (available))
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"/memory response buffer exceeded");
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS)) if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS))
{ {

View file

@ -740,6 +740,12 @@ parse_printf_args (const char *fmt0, struct printf_args *args,
fmt++; fmt++;
c = *fmt++; c = *fmt++;
if (c == '%')
{
n--;
continue;
}
if (c == 'l') if (c == 'l')
{ {
c = *fmt++; c = *fmt++;
@ -876,6 +882,7 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0,
if (c == '%') if (c == '%')
{ {
write_char (str, &count, max_len,c); write_char (str, &count, max_len,c);
n--;
continue; continue;
} }
@ -1099,6 +1106,8 @@ grub_fatal (const char *fmt, ...)
grub_vprintf (_(fmt), ap); grub_vprintf (_(fmt), ap);
va_end (ap); va_end (ap);
grub_refresh ();
grub_abort (); grub_abort ();
} }

View file

@ -325,6 +325,15 @@ grub_memalign (grub_size_t align, grub_size_t size)
if (!grub_mm_base) if (!grub_mm_base)
goto fail; goto fail;
if (size > ~(grub_size_t) align)
goto fail;
/* We currently assume at least a 32-bit grub_size_t,
so limiting allocations to <adress space size> - 1MiB
in name of sanity is beneficial. */
if ((size + align) > ~(grub_size_t) 0x100000)
goto fail;
align = (align >> GRUB_MM_ALIGN_LOG2); align = (align >> GRUB_MM_ALIGN_LOG2);
if (align == 0) if (align == 0)
align = 1; align = 1;

View file

@ -43,13 +43,17 @@ grub_rescue_parse_line (char *line,
/* In case of an assignment set the environment accordingly /* In case of an assignment set the environment accordingly
instead of calling a function. */ instead of calling a function. */
if (n == 1 && grub_strchr (line, '=')) if (n == 1)
{ {
char *val = grub_strchr (args[0], '='); char *val = grub_strchr (args[0], '=');
val[0] = 0;
grub_env_set (args[0], val + 1); if (val)
val[0] = '='; {
goto quit; val[0] = 0;
grub_env_set (args[0], val + 1);
val[0] = '=';
goto quit;
}
} }
/* Get the command name. */ /* Get the command name. */
@ -72,6 +76,7 @@ grub_rescue_parse_line (char *line,
} }
quit: quit:
/* Arguments are returned in single memory chunk separated by zeroes */
grub_free (args[0]); grub_free (args[0]);
grub_free (args); grub_free (args);

View file

@ -50,6 +50,7 @@ FUNCTION(grub_longjmp)
ldp x29, x30, [x0], #16 ldp x29, x30, [x0], #16
ldr x2, [x0] ldr x2, [x0]
mov sp, x2 mov sp, x2
mov x0, #1
cmp x1, #0 cmp x1, #0
csel x0, x1, x0, ne csel x0, x1, x0, ne
ret ret

View file

@ -56,11 +56,11 @@ void
grub_backtrace (void) grub_backtrace (void)
{ {
#ifdef __x86_64__ #ifdef __x86_64__
asm volatile ("movq %rbp, %rdi\n" asm volatile ("movq %%rbp, %%rdi\n"
"call " EXT_C("grub_backtrace_pointer")); "callq *%%rax": :"a"(grub_backtrace_pointer));
#else #else
asm volatile ("movl %ebp, %eax\n" asm volatile ("movl %%ebp, %%eax\n"
"call " EXT_C("grub_backtrace_pointer")); "calll *%%ecx": :"c"(grub_backtrace_pointer));
#endif #endif
} }

103
grub-core/lib/i386/random.c Normal file
View file

@ -0,0 +1,103 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2016 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/random.h>
#include <grub/i386/io.h>
#include <grub/i386/tsc.h>
#include <grub/i386/pmtimer.h>
#include <grub/acpi.h>
static int have_tsc = -1, have_pmtimer = -1;
static grub_port_t pmtimer_port;
static int
detect_pmtimer (void)
{
struct grub_acpi_fadt *fadt;
fadt = grub_acpi_find_fadt ();
if (!fadt)
return 0;
pmtimer_port = fadt->pmtimer;
if (!pmtimer_port)
return 0;
return 1;
}
static int
pmtimer_tsc_get_random_bit (void)
{
/* It's hard to come up with figures about pmtimer and tsc jitter but
50 ppm seems to be typical. So we need 10^6/50 tsc cycles to get drift
of one tsc cycle. With TSC at least of 800 MHz it means 1/(50*800)
= 1/40000 s or about 3579545 / 40000 = 90 pmtimer ticks.
This gives us rate of 40000 bit/s or 5 kB/s.
*/
grub_uint64_t tsc_diff;
tsc_diff = grub_pmtimer_wait_count_tsc (pmtimer_port, 90);
if (tsc_diff == 0)
{
have_pmtimer = 0;
return -1;
}
return tsc_diff & 1;
}
static int
pmtimer_tsc_get_random_byte (void)
{
grub_uint8_t ret = 0;
int i, c;
for (i = 0; i < 8; i++)
{
c = pmtimer_tsc_get_random_bit ();
if (c < 0)
return -1;
ret |= c << i;
}
return ret;
}
static int
pmtimer_fill_buffer (void *buffer, grub_size_t sz)
{
grub_uint8_t *p = buffer;
int c;
while (sz)
{
c = pmtimer_tsc_get_random_byte ();
if (c < 0)
return 0;
*p++ = c;
sz--;
}
return 1;
}
int
grub_crypto_arch_get_random (void *buffer, grub_size_t sz)
{
if (have_tsc == -1)
have_tsc = grub_cpu_is_tsc_supported ();
if (!have_tsc)
return 0;
if (have_pmtimer == -1)
have_pmtimer = detect_pmtimer ();
if (!have_pmtimer)
return 0;
return pmtimer_fill_buffer (buffer, sz);
}

View file

@ -73,6 +73,14 @@ VARIABLE(grub_relocator64_rsp)
movq %rax, %rsp movq %rax, %rsp
/*
* Here is grub_relocator64_efi_start() entry point.
* Following code is shared between grub_relocator64_efi_start()
* and grub_relocator64_start().
*
* Think twice before changing anything below!!!
*/
VARIABLE(grub_relocator64_efi_start)
/* mov imm64, %rax */ /* mov imm64, %rax */
.byte 0x48 .byte 0x48
.byte 0xb8 .byte 0xb8
@ -120,6 +128,9 @@ LOCAL(jump_addr):
VARIABLE(grub_relocator64_rip) VARIABLE(grub_relocator64_rip)
.quad 0 .quad 0
/* Here grub_relocator64_efi_start() ends. Ufff... */
VARIABLE(grub_relocator64_efi_end)
#ifndef __x86_64__ #ifndef __x86_64__
.p2align 4 .p2align 4
LOCAL(gdt): LOCAL(gdt):

View file

@ -16,6 +16,8 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <grub/i386/memory.h>
#include <grub/i386/types.h>
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/xen.h> #include <grub/xen.h>
@ -23,78 +25,86 @@
VARIABLE(grub_relocator_xen_remap_start) VARIABLE(grub_relocator_xen_remap_start)
LOCAL(base): LOCAL(base):
/* mov imm32, %ebx */ /* Remap the remapper to it's new address. */
/* mov imm32, %ebx - %ebx: new virtual address of remapper */
.byte 0xbb .byte 0xbb
VARIABLE(grub_relocator_xen_remapper_virt) VARIABLE(grub_relocator_xen_remapper_virt)
.long 0 .long 0
/* mov imm32, %ecx */ /* mov imm32, %ecx - %ecx: low part of page table entry */
.byte 0xb9 .byte 0xb9
VARIABLE(grub_relocator_xen_remapper_map) VARIABLE(grub_relocator_xen_remapper_map)
.long 0 .long 0
/* mov imm32, %edx */ /* mov imm32, %edx - %edx: high part of page table entry */
.byte 0xba .byte 0xba
VARIABLE(grub_relocator_xen_remapper_map_high) VARIABLE(grub_relocator_xen_remapper_map_high)
.long 0 .long 0
movl %ebx, %ebp movl %ebx, %ebp /* %ebx is clobbered by hypercall */
movl $2, %esi movl $UVMF_INVLPG, %esi /* esi: flags (inv. single entry) */
movl $__HYPERVISOR_update_va_mapping, %eax movl $__HYPERVISOR_update_va_mapping, %eax
int $0x82 int $0x82
movl %ebp, %ebx movl %ebp, %ebx
addl $(LOCAL(cont) - LOCAL(base)), %ebx addl $(LOCAL(cont) - LOCAL(base)), %ebx
jmp *%ebx jmp *%ebx /* Continue with new virtual address */
LOCAL(cont): LOCAL(cont):
xorl %eax, %eax /* Modify mappings of new page tables to be read-only. */
movl %eax, %ebp /* mov imm32, %eax */
.byte 0xb8
VARIABLE(grub_relocator_xen_paging_areas_addr)
.long 0
movl %eax, %ebx
1: 1:
movl 0(%ebx), %ebp /* Get start pfn of the current area */
movl GRUB_TARGET_SIZEOF_LONG(%ebx), %ecx /* Get # of pg tables */
testl %ecx, %ecx /* 0 -> last area reached */
jz 3f
addl $(2 * GRUB_TARGET_SIZEOF_LONG), %ebx
movl %ebx, %esp /* Save current area pointer */
2:
movl %ecx, %edi
/* mov imm32, %eax */ /* mov imm32, %eax */
.byte 0xb8 .byte 0xb8
VARIABLE(grub_relocator_xen_mfn_list) VARIABLE(grub_relocator_xen_mfn_list)
.long 0 .long 0
movl %eax, %edi movl 0(%eax, %ebp, 4), %ecx /* mfn */
movl %ebp, %eax movl %ebp, %ebx
movl 0(%edi, %eax, 4), %ecx shll $PAGE_SHIFT, %ebx /* virtual address (1:1 mapping) */
/* mov imm32, %ebx */
.byte 0xbb
VARIABLE(grub_relocator_xen_paging_start)
.long 0
shll $12, %eax
addl %eax, %ebx
movl %ecx, %edx movl %ecx, %edx
shll $12, %ecx shll $PAGE_SHIFT, %ecx /* prepare pte low part */
shrl $20, %edx shrl $(32 - PAGE_SHIFT), %edx /* pte high part */
orl $5, %ecx orl $(GRUB_PAGE_PRESENT | GRUB_PAGE_USER), %ecx /* pte low */
movl $2, %esi movl $UVMF_INVLPG, %esi
movl $__HYPERVISOR_update_va_mapping, %eax movl $__HYPERVISOR_update_va_mapping, %eax
int $0x82 int $0x82 /* parameters: eax, ebx, ecx, edx, esi */
incl %ebp incl %ebp /* next pfn */
/* mov imm32, %ecx */ movl %edi, %ecx
.byte 0xb9
VARIABLE(grub_relocator_xen_paging_size)
.long 0
cmpl %ebp, %ecx
ja 1b loop 2b
mov %esp, %ebx /* restore area poniter */
jmp 1b
3:
/* Switch page tables: pin new L3 pt, load cr3, unpin old L3. */
/* mov imm32, %ebx */ /* mov imm32, %ebx */
.byte 0xbb .byte 0xbb
VARIABLE(grub_relocator_xen_mmu_op_addr) VARIABLE(grub_relocator_xen_mmu_op_addr)
.long 0 .long 0
movl $3, %ecx movl $3, %ecx /* 3 mmu ops */
movl $0, %edx movl $0, %edx /* pdone (not used) */
movl $0x7FF0, %esi movl $DOMID_SELF, %esi
movl $__HYPERVISOR_mmuext_op, %eax movl $__HYPERVISOR_mmuext_op, %eax
int $0x82 int $0x82
/* Continue in virtual kernel mapping. */
/* mov imm32, %eax */ /* mov imm32, %eax */
.byte 0xb8 .byte 0xb8
VARIABLE(grub_relocator_xen_remap_continue) VARIABLE(grub_relocator_xen_remap_continue)
@ -102,6 +112,9 @@ VARIABLE(grub_relocator_xen_remap_continue)
jmp *%eax jmp *%eax
VARIABLE(grub_relocator_xen_paging_areas)
.long 0, 0, 0, 0, 0, 0, 0, 0
VARIABLE(grub_relocator_xen_mmu_op) VARIABLE(grub_relocator_xen_mmu_op)
.space 256 .space 256
@ -109,6 +122,7 @@ VARIABLE(grub_relocator_xen_remap_end)
VARIABLE(grub_relocator_xen_start) VARIABLE(grub_relocator_xen_start)
/* Unmap old remapper area. */
/* mov imm32, %eax */ /* mov imm32, %eax */
.byte 0xb8 .byte 0xb8
VARIABLE(grub_relocator_xen_remapper_virt2) VARIABLE(grub_relocator_xen_remapper_virt2)
@ -116,14 +130,14 @@ VARIABLE(grub_relocator_xen_remapper_virt2)
movl %eax, %edi movl %eax, %edi
xorl %ecx, %ecx xorl %ecx, %ecx /* Invalid pte */
xorl %edx, %edx xorl %edx, %edx
movl $2, %esi movl $UVMF_INVLPG, %esi
movl $__HYPERVISOR_update_va_mapping, %eax movl $__HYPERVISOR_update_va_mapping, %eax
int $0x82 int $0x82
/* Prepare registers for starting kernel. */
/* mov imm32, %eax */ /* mov imm32, %eax */
.byte 0xb8 .byte 0xb8
VARIABLE(grub_relocator_xen_stack) VARIABLE(grub_relocator_xen_stack)
@ -145,6 +159,7 @@ VARIABLE(grub_relocator_xen_start_info)
VARIABLE(grub_relocator_xen_entry_point) VARIABLE(grub_relocator_xen_entry_point)
.long 0 .long 0
/* Now start the new kernel. */
jmp *%eax jmp *%eax
VARIABLE(grub_relocator_xen_end) VARIABLE(grub_relocator_xen_end)

View file

@ -95,7 +95,7 @@ grub_get_datetime (struct grub_datetime *datetime)
datetime->year = args.year; datetime->year = args.year;
datetime->month = args.month; datetime->month = args.month;
datetime->day = args.day; datetime->day = args.day + 1;
datetime->hour = args.hour; datetime->hour = args.hour;
datetime->minute = args.minute; datetime->minute = args.minute;
datetime->second = args.second; datetime->second = args.second;
@ -140,7 +140,7 @@ grub_set_datetime (struct grub_datetime *datetime)
args.year = datetime->year; args.year = datetime->year;
args.month = datetime->month; args.month = datetime->month;
args.day = datetime->day; args.day = datetime->day - 1;
args.hour = datetime->hour; args.hour = datetime->hour;
args.minute = datetime->minute; args.minute = datetime->minute;
args.second = datetime->second; args.second = datetime->second;

View file

@ -31,7 +31,6 @@ GRUB_MOD_LICENSE ("GPLv2+");
desired derived output length DKLEN. Output buffer is DK which desired derived output length DKLEN. Output buffer is DK which
must have room for at least DKLEN octets. The output buffer will must have room for at least DKLEN octets. The output buffer will
be filled with the derived data. */ be filled with the derived data. */
#pragma GCC diagnostic ignored "-Wunreachable-code"
gcry_err_code_t gcry_err_code_t
grub_crypto_pbkdf2 (const struct gcry_md_spec *md, grub_crypto_pbkdf2 (const struct gcry_md_spec *md,

View file

@ -38,11 +38,17 @@ grub_file_progress_hook_real (grub_disk_addr_t sector __attribute__ ((unused)),
grub_uint64_t now; grub_uint64_t now;
static grub_uint64_t last_progress_update_time; static grub_uint64_t last_progress_update_time;
grub_file_t file = data; grub_file_t file = data;
const char *e;
file->progress_offset += length; file->progress_offset += length;
if (call_depth) if (call_depth)
return; return;
e = grub_env_get ("enable_progress_indicator");
if (e && e[0] == '0') {
return;
}
call_depth = 1; call_depth = 1;
now = grub_get_time_ms (); now = grub_get_time_ms ();

120
grub-core/lib/random.c Normal file
View file

@ -0,0 +1,120 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2016 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/random.h>
#include <grub/dl.h>
#include <grub/lib/hexdump.h>
#include <grub/command.h>
#include <grub/mm.h>
GRUB_MOD_LICENSE ("GPLv3+");
grub_err_t
grub_crypto_get_random (void *buffer, grub_size_t sz)
{
/* This is an arbitrer between different methods.
TODO: Add more methods in the future. */
/* TODO: Add some PRNG smartness to reduce damage from bad entropy. */
if (grub_crypto_arch_get_random (buffer, sz))
return GRUB_ERR_NONE;
return grub_error (GRUB_ERR_IO, "no random sources found");
}
static int
get_num_digits (int val)
{
int ret = 0;
while (val != 0)
{
ret++;
val /= 10;
}
if (ret == 0)
return 1;
return ret;
}
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
static grub_err_t
grub_cmd_hexdump_random (grub_command_t cmd __attribute__ ((unused)), int argc, char **args)
{
grub_size_t length = 64;
grub_err_t err;
void *buffer;
grub_uint8_t *ptr;
int stats[256];
int i, digits = 2;
char template[10];
if (argc >= 1)
length = grub_strtoull (args[0], 0, 0);
if (length == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "length pust be positive");
buffer = grub_malloc (length);
if (!buffer)
return grub_errno;
err = grub_crypto_get_random (buffer, length);
if (err)
{
grub_free (buffer);
return err;
}
hexdump (0, buffer, length);
grub_memset(stats, 0, sizeof(stats));
for (ptr = buffer; ptr < (grub_uint8_t *) buffer + length; ptr++)
stats[*ptr]++;
grub_printf ("Statistics:\n");
for (i = 0; i < 256; i++)
{
int z = get_num_digits (stats[i]);
if (z > digits)
digits = z;
}
grub_snprintf (template, sizeof (template), "%%0%dd ", digits);
for (i = 0; i < 256; i++)
{
grub_printf ("%s", template);//, stats[i]);
if ((i & 0xf) == 0xf)
grub_printf ("\n");
}
grub_free (buffer);
return 0;
}
static grub_command_t cmd;
GRUB_MOD_INIT (random)
{
cmd = grub_register_command ("hexdump_random", grub_cmd_hexdump_random,
N_("[LENGTH]"),
N_("Hexdump random data."));
}
GRUB_MOD_FINI (random)
{
grub_unregister_command (cmd);
}

View file

@ -736,26 +736,36 @@ malloc_in_range (struct grub_relocator *rel,
} }
isinsideafter = (!ncollisions && (nstarted || ((nlefto || nstartedfw) isinsideafter = (!ncollisions && (nstarted || ((nlefto || nstartedfw)
&& !nblockfw))); && !nblockfw)));
if (!isinsidebefore && isinsideafter) if (from_low_priv) {
starta = from_low_priv ? ALIGN_UP (events[j].pos, align) if (!isinsidebefore && isinsideafter)
: ALIGN_DOWN (events[j].pos - size, align) + size; starta = ALIGN_UP (events[j].pos, align);
if (isinsidebefore && !isinsideafter && from_low_priv)
{ if (isinsidebefore && !isinsideafter)
target = starta; {
if (target < start) target = starta;
target = start; if (target < start)
if (target + size <= end && target + size <= events[j].pos) target = start;
/* Found an usable address. */ if (target + size <= end && target + size <= events[j].pos)
goto found; /* Found an usable address. */
} goto found;
if (isinsidebefore && !isinsideafter && !from_low_priv) }
{ } else {
target = starta - size; if (!isinsidebefore && isinsideafter)
if (target > end - size) {
target = end - size; if (events[j].pos >= size)
if (target >= start && target >= events[j].pos) starta = ALIGN_DOWN (events[j].pos - size, align) + size;
goto found; else
} starta = 0;
}
if (isinsidebefore && !isinsideafter && starta >= size)
{
target = starta - size;
if (target > end - size)
target = end - size;
if (target >= start && target >= events[j].pos)
goto found;
}
}
} }
} }

View file

@ -0,0 +1,80 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
* Copyright (C) 2016 Oracle and/or its affiliates. All rights reserved.
*
* 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/misc.h>
#include <grub/types.h>
#include <grub/err.h>
#include <grub/i386/relocator.h>
#include <grub/relocator_private.h>
extern grub_uint64_t grub_relocator64_rax;
extern grub_uint64_t grub_relocator64_rbx;
extern grub_uint64_t grub_relocator64_rcx;
extern grub_uint64_t grub_relocator64_rdx;
extern grub_uint64_t grub_relocator64_rip;
extern grub_uint64_t grub_relocator64_rsi;
extern grub_uint8_t grub_relocator64_efi_start;
extern grub_uint8_t grub_relocator64_efi_end;
#define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start)
grub_err_t
grub_relocator64_efi_boot (struct grub_relocator *rel,
struct grub_relocator64_efi_state state)
{
grub_err_t err;
void *relst;
grub_relocator_chunk_t ch;
/*
* 64-bit relocator code may live above 4 GiB quite well.
* However, I do not want ask for problems. Just in case.
*/
err = grub_relocator_alloc_chunk_align (rel, &ch, 0,
0x100000000 - RELOCATOR_SIZEOF (64_efi),
RELOCATOR_SIZEOF (64_efi), 16,
GRUB_RELOCATOR_PREFERENCE_NONE, 1);
if (err)
return err;
/* Do not touch %rsp! It points to EFI created stack. */
grub_relocator64_rax = state.rax;
grub_relocator64_rbx = state.rbx;
grub_relocator64_rcx = state.rcx;
grub_relocator64_rdx = state.rdx;
grub_relocator64_rip = state.rip;
grub_relocator64_rsi = state.rsi;
grub_memmove (get_virtual_current_address (ch), &grub_relocator64_efi_start,
RELOCATOR_SIZEOF (64_efi));
err = grub_relocator_prepare_relocs (rel, get_physical_target_address (ch),
&relst, NULL);
if (err)
return err;
((void (*) (void)) relst) ();
/* Not reached. */
return GRUB_ERR_NONE;
}

View file

@ -16,94 +16,85 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <grub/x86_64/memory.h>
#include <grub/x86_64/types.h>
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/xen.h> #include <grub/xen.h>
/* Macro to load an imm64 value stored by the C-part into %rax: */
#define MOV_IMM64_RAX(var) .byte 0x48, 0xb8; VARIABLE(var); .quad 0
.p2align 4 /* force 16-byte alignment */ .p2align 4 /* force 16-byte alignment */
VARIABLE(grub_relocator_xen_remap_start) VARIABLE(grub_relocator_xen_remap_start)
LOCAL(base): LOCAL(base):
/* mov imm64, %rax */ /* Remap the remapper to it's new address. */
.byte 0x48 MOV_IMM64_RAX(grub_relocator_xen_remapper_virt)
.byte 0xb8
VARIABLE(grub_relocator_xen_remapper_virt)
.quad 0
movq %rax, %rdi movq %rax, %rdi /* %rdi: new virtual address of remapper */
movq %rax, %rbx movq %rax, %rbx /* Remember new virtual address */
/* mov imm64, %rax */ MOV_IMM64_RAX(grub_relocator_xen_remapper_map)
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_remapper_map)
.quad 0
movq %rax, %rsi movq %rax, %rsi /* %rsi: page table entry */
movq $2, %rdx movq $UVMF_INVLPG, %rdx /* %rdx: flags (inv. single entry) */
movq $__HYPERVISOR_update_va_mapping, %rax movq $__HYPERVISOR_update_va_mapping, %rax
syscall syscall /* Do the remap operation */
addq $(LOCAL(cont) - LOCAL(base)), %rbx addq $(LOCAL(cont) - LOCAL(base)), %rbx
jmp *%rbx jmp *%rbx /* Continue with new virtual address */
LOCAL(cont): LOCAL(cont):
/* Modify mappings of new page tables to be read-only. */
MOV_IMM64_RAX(grub_relocator_xen_mfn_list)
/* mov imm64, %rcx */ movq %rax, %rbx /* %rbx is the base of the p2m list */
.byte 0x48 leaq EXT_C(grub_relocator_xen_paging_areas) (%rip), %r8
.byte 0xb9
VARIABLE(grub_relocator_xen_paging_size)
.quad 0
/* mov imm64, %rax */
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_paging_start)
.quad 0
movq %rax, %r12
/* mov imm64, %rax */
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_mfn_list)
.quad 0
movq %rax, %rsi
1: 1:
movq 0(%r8), %r12 /* Get start pfn of the current area */
movq GRUB_TARGET_SIZEOF_LONG(%r8), %rcx /* Get # of pg tables */
testq %rcx, %rcx /* 0 -> last area reached */
jz 3f
2:
movq %r12, %rdi movq %r12, %rdi
movq %rsi, %rbx shlq $PAGE_SHIFT, %rdi /* virtual address (1:1 mapping) */
movq 0(%rsi), %rsi movq (%rbx, %r12, 8), %rsi /* mfn */
shlq $12, %rsi shlq $PAGE_SHIFT, %rsi
orq $5, %rsi orq $(GRUB_PAGE_PRESENT | GRUB_PAGE_USER), %rsi /* Build pte */
movq $2, %rdx movq $UVMF_INVLPG, %rdx
movq %rcx, %r9 movq %rcx, %r9 /* %rcx clobbered by hypercall */
movq $__HYPERVISOR_update_va_mapping, %rax movq $__HYPERVISOR_update_va_mapping, %rax
syscall syscall
movq %r9, %rcx movq %r9, %rcx
addq $8, %rbx incq %r12 /* next pfn */
addq $4096, %r12
movq %rbx, %rsi
loop 1b loop 2b
addq $(2 * GRUB_TARGET_SIZEOF_LONG), %r8 /* next pg table area */
jmp 1b
3:
/* Switch page tables: pin new L4 pt, load cr3, unpin old L4. */
leaq EXT_C(grub_relocator_xen_mmu_op) (%rip), %rdi leaq EXT_C(grub_relocator_xen_mmu_op) (%rip), %rdi
movq $3, %rsi movq $3, %rsi /* 3 mmu ops */
movq $0, %rdx movq $0, %rdx /* pdone (not used) */
movq $0x7FF0, %r10 movq $DOMID_SELF, %r10
movq $__HYPERVISOR_mmuext_op, %rax movq $__HYPERVISOR_mmuext_op, %rax
syscall syscall
/* mov imm64, %rax */ /* Continue in virtual kernel mapping. */
.byte 0x48 MOV_IMM64_RAX(grub_relocator_xen_remap_continue)
.byte 0xb8
VARIABLE(grub_relocator_xen_remap_continue)
.quad 0
jmp *%rax jmp *%rax
VARIABLE(grub_relocator_xen_paging_areas)
/* array of start, size pairs, size 0 is end marker */
.quad 0, 0, 0, 0, 0, 0, 0, 0
VARIABLE(grub_relocator_xen_mmu_op) VARIABLE(grub_relocator_xen_mmu_op)
.space 256 .space 256
@ -111,46 +102,32 @@ VARIABLE(grub_relocator_xen_remap_end)
VARIABLE(grub_relocator_xen_start) VARIABLE(grub_relocator_xen_start)
/* mov imm64, %rax */ /* Unmap old remapper area. */
.byte 0x48 MOV_IMM64_RAX(grub_relocator_xen_remapper_virt2)
.byte 0xb8
VARIABLE(grub_relocator_xen_remapper_virt2)
.quad 0
movq %rax, %rdi movq %rax, %rdi
xorq %rax, %rax xorq %rax, %rax /* Invalid pte */
movq %rax, %rsi movq %rax, %rsi
movq $2, %rdx movq $UVMF_INVLPG, %rdx
movq $__HYPERVISOR_update_va_mapping, %rax movq $__HYPERVISOR_update_va_mapping, %rax
syscall syscall
/* Prepare registers for starting kernel. */
/* mov imm64, %rax */ MOV_IMM64_RAX(grub_relocator_xen_stack)
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_stack)
.quad 0
movq %rax, %rsp movq %rax, %rsp
/* mov imm64, %rax */ MOV_IMM64_RAX(grub_relocator_xen_start_info)
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_start_info)
.quad 0
movq %rax, %rsi movq %rax, %rsi
cld cld
/* mov imm64, %rax */ MOV_IMM64_RAX(grub_relocator_xen_entry_point)
.byte 0x48
.byte 0xb8
VARIABLE(grub_relocator_xen_entry_point)
.quad 0
/* Now start the new kernel. */
jmp *%rax jmp *%rax
VARIABLE(grub_relocator_xen_end) VARIABLE(grub_relocator_xen_end)

View file

@ -29,6 +29,11 @@
typedef grub_addr_t grub_xen_reg_t; typedef grub_addr_t grub_xen_reg_t;
struct grub_relocator_xen_paging_area {
grub_xen_reg_t start;
grub_xen_reg_t size;
} GRUB_PACKED;
extern grub_uint8_t grub_relocator_xen_start; extern grub_uint8_t grub_relocator_xen_start;
extern grub_uint8_t grub_relocator_xen_end; extern grub_uint8_t grub_relocator_xen_end;
extern grub_uint8_t grub_relocator_xen_remap_start; extern grub_uint8_t grub_relocator_xen_remap_start;
@ -36,15 +41,16 @@ extern grub_uint8_t grub_relocator_xen_remap_end;
extern grub_xen_reg_t grub_relocator_xen_stack; extern grub_xen_reg_t grub_relocator_xen_stack;
extern grub_xen_reg_t grub_relocator_xen_start_info; extern grub_xen_reg_t grub_relocator_xen_start_info;
extern grub_xen_reg_t grub_relocator_xen_entry_point; extern grub_xen_reg_t grub_relocator_xen_entry_point;
extern grub_xen_reg_t grub_relocator_xen_paging_start;
extern grub_xen_reg_t grub_relocator_xen_paging_size;
extern grub_xen_reg_t grub_relocator_xen_remapper_virt; extern grub_xen_reg_t grub_relocator_xen_remapper_virt;
extern grub_xen_reg_t grub_relocator_xen_remapper_virt2; extern grub_xen_reg_t grub_relocator_xen_remapper_virt2;
extern grub_xen_reg_t grub_relocator_xen_remapper_map; extern grub_xen_reg_t grub_relocator_xen_remapper_map;
extern grub_xen_reg_t grub_relocator_xen_mfn_list; extern grub_xen_reg_t grub_relocator_xen_mfn_list;
extern struct grub_relocator_xen_paging_area
grub_relocator_xen_paging_areas[XEN_MAX_MAPPINGS];
extern grub_xen_reg_t grub_relocator_xen_remap_continue; extern grub_xen_reg_t grub_relocator_xen_remap_continue;
#ifdef __i386__ #ifdef __i386__
extern grub_xen_reg_t grub_relocator_xen_mmu_op_addr; extern grub_xen_reg_t grub_relocator_xen_mmu_op_addr;
extern grub_xen_reg_t grub_relocator_xen_paging_areas_addr;
extern grub_xen_reg_t grub_relocator_xen_remapper_map_high; extern grub_xen_reg_t grub_relocator_xen_remapper_map_high;
#endif #endif
extern mmuext_op_t grub_relocator_xen_mmu_op[3]; extern mmuext_op_t grub_relocator_xen_mmu_op[3];
@ -61,6 +67,7 @@ grub_relocator_xen_boot (struct grub_relocator *rel,
{ {
grub_err_t err; grub_err_t err;
void *relst; void *relst;
int i;
grub_relocator_chunk_t ch, ch_tramp; grub_relocator_chunk_t ch, ch_tramp;
grub_xen_mfn_t *mfn_list = grub_xen_mfn_t *mfn_list =
(grub_xen_mfn_t *) grub_xen_start_page_addr->mfn_list; (grub_xen_mfn_t *) grub_xen_start_page_addr->mfn_list;
@ -77,8 +84,11 @@ grub_relocator_xen_boot (struct grub_relocator *rel,
grub_relocator_xen_stack = state.stack; grub_relocator_xen_stack = state.stack;
grub_relocator_xen_start_info = state.start_info; grub_relocator_xen_start_info = state.start_info;
grub_relocator_xen_entry_point = state.entry_point; grub_relocator_xen_entry_point = state.entry_point;
grub_relocator_xen_paging_start = state.paging_start << 12; for (i = 0; i < XEN_MAX_MAPPINGS; i++)
grub_relocator_xen_paging_size = state.paging_size; {
grub_relocator_xen_paging_areas[i].start = state.paging_start[i];
grub_relocator_xen_paging_areas[i].size = state.paging_size[i];
}
grub_relocator_xen_remapper_virt = remapper_virt; grub_relocator_xen_remapper_virt = remapper_virt;
grub_relocator_xen_remapper_virt2 = remapper_virt; grub_relocator_xen_remapper_virt2 = remapper_virt;
grub_relocator_xen_remap_continue = trampoline_virt; grub_relocator_xen_remap_continue = trampoline_virt;
@ -88,10 +98,12 @@ grub_relocator_xen_boot (struct grub_relocator *rel,
grub_relocator_xen_remapper_map_high = (mfn_list[remapper_pfn] >> 20); grub_relocator_xen_remapper_map_high = (mfn_list[remapper_pfn] >> 20);
grub_relocator_xen_mmu_op_addr = (char *) &grub_relocator_xen_mmu_op grub_relocator_xen_mmu_op_addr = (char *) &grub_relocator_xen_mmu_op
- (char *) &grub_relocator_xen_remap_start + remapper_virt; - (char *) &grub_relocator_xen_remap_start + remapper_virt;
grub_relocator_xen_paging_areas_addr =
(char *) &grub_relocator_xen_paging_areas
- (char *) &grub_relocator_xen_remap_start + remapper_virt;
#endif #endif
grub_relocator_xen_mfn_list = state.mfn_list grub_relocator_xen_mfn_list = state.mfn_list;
+ state.paging_start * sizeof (grub_addr_t);
grub_memset (grub_relocator_xen_mmu_op, 0, grub_memset (grub_relocator_xen_mmu_op, 0,
sizeof (grub_relocator_xen_mmu_op)); sizeof (grub_relocator_xen_mmu_op));
@ -100,9 +112,9 @@ grub_relocator_xen_boot (struct grub_relocator *rel,
#else #else
grub_relocator_xen_mmu_op[0].cmd = MMUEXT_PIN_L4_TABLE; grub_relocator_xen_mmu_op[0].cmd = MMUEXT_PIN_L4_TABLE;
#endif #endif
grub_relocator_xen_mmu_op[0].arg1.mfn = mfn_list[state.paging_start]; grub_relocator_xen_mmu_op[0].arg1.mfn = mfn_list[state.paging_start[0]];
grub_relocator_xen_mmu_op[1].cmd = MMUEXT_NEW_BASEPTR; grub_relocator_xen_mmu_op[1].cmd = MMUEXT_NEW_BASEPTR;
grub_relocator_xen_mmu_op[1].arg1.mfn = mfn_list[state.paging_start]; grub_relocator_xen_mmu_op[1].arg1.mfn = mfn_list[state.paging_start[0]];
grub_relocator_xen_mmu_op[2].cmd = MMUEXT_UNPIN_TABLE; grub_relocator_xen_mmu_op[2].cmd = MMUEXT_UNPIN_TABLE;
grub_relocator_xen_mmu_op[2].arg1.mfn = grub_relocator_xen_mmu_op[2].arg1.mfn =
mfn_list[grub_xen_start_page_addr->pt_base >> 12]; mfn_list[grub_xen_start_page_addr->pt_base >> 12];

View file

@ -28,28 +28,6 @@
static void *loaded_fdt; static void *loaded_fdt;
static void *fdt; static void *fdt;
static void *
get_firmware_fdt (void)
{
grub_efi_configuration_table_t *tables;
grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
void *firmware_fdt = NULL;
unsigned int i;
/* Look for FDT in UEFI config tables. */
tables = grub_efi_system_table->configuration_table;
for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
if (grub_memcmp (&tables[i].vendor_guid, &fdt_guid, sizeof (fdt_guid)) == 0)
{
firmware_fdt = tables[i].vendor_table;
grub_dprintf ("linux", "found registered FDT @ %p\n", firmware_fdt);
break;
}
return firmware_fdt;
}
void * void *
grub_fdt_load (grub_size_t additional_size) grub_fdt_load (grub_size_t additional_size)
{ {
@ -65,7 +43,7 @@ grub_fdt_load (grub_size_t additional_size)
if (loaded_fdt) if (loaded_fdt)
raw_fdt = loaded_fdt; raw_fdt = loaded_fdt;
else else
raw_fdt = get_firmware_fdt(); raw_fdt = grub_efi_get_firmware_fdt();
size = size =
raw_fdt ? grub_fdt_get_totalsize (raw_fdt) : GRUB_FDT_EMPTY_TREE_SZ; raw_fdt ? grub_fdt_get_totalsize (raw_fdt) : GRUB_FDT_EMPTY_TREE_SZ;

View file

@ -37,16 +37,6 @@
GRUB_MOD_LICENSE ("GPLv3+"); GRUB_MOD_LICENSE ("GPLv3+");
#define XEN_HYPERVISOR_NAME "xen_hypervisor" #define XEN_HYPERVISOR_NAME "xen_hypervisor"
#define MODULE_DEFAULT_ALIGN (0x0)
#define MODULE_IMAGE_MIN_ALIGN MODULE_DEFAULT_ALIGN
#define MODULE_INITRD_MIN_ALIGN MODULE_DEFAULT_ALIGN
#define MODULE_XSM_MIN_ALIGN MODULE_DEFAULT_ALIGN
#define MODULE_CUSTOM_MIN_ALIGN MODULE_DEFAULT_ALIGN
#define MODULE_IMAGE_COMPATIBLE "multiboot,kernel\0multiboot,module"
#define MODULE_INITRD_COMPATIBLE "multiboot,ramdisk\0multiboot,module"
#define MODULE_XSM_COMPATIBLE "xen,xsm-policy\0multiboot,module"
#define MODULE_CUSTOM_COMPATIBLE "multiboot,module" #define MODULE_CUSTOM_COMPATIBLE "multiboot,module"
/* This maximum size is defined in Power.org ePAPR V1.1 /* This maximum size is defined in Power.org ePAPR V1.1
@ -74,14 +64,6 @@ enum module_type
}; };
typedef enum module_type module_type_t; typedef enum module_type module_type_t;
struct fdt_node_info
{
module_type_t type;
const char *compat_string;
grub_size_t compat_string_size;
};
struct xen_hypervisor_header struct xen_hypervisor_header
{ {
struct grub_arm64_linux_kernel_header efi_head; struct grub_arm64_linux_kernel_header efi_head;
@ -98,7 +80,7 @@ struct xen_boot_binary
{ {
struct xen_boot_binary *next; struct xen_boot_binary *next;
struct xen_boot_binary **prev; struct xen_boot_binary **prev;
const char *name; int is_hypervisor;
grub_addr_t start; grub_addr_t start;
grub_size_t size; grub_size_t size;
@ -106,8 +88,6 @@ struct xen_boot_binary
char *cmdline; char *cmdline;
int cmdline_size; int cmdline_size;
struct fdt_node_info node_info;
}; };
static grub_dl_t my_mod; static grub_dl_t my_mod;
@ -116,19 +96,6 @@ static int loaded;
static struct xen_boot_binary *xen_hypervisor; static struct xen_boot_binary *xen_hypervisor;
static struct xen_boot_binary *module_head; static struct xen_boot_binary *module_head;
static const grub_size_t module_default_align[] = {
MODULE_IMAGE_MIN_ALIGN,
MODULE_INITRD_MIN_ALIGN,
MODULE_XSM_MIN_ALIGN,
MODULE_CUSTOM_MIN_ALIGN
};
static const compat_string_struct_t default_compat_string[] = {
FDT_COMPATIBLE (MODULE_IMAGE_COMPATIBLE),
FDT_COMPATIBLE (MODULE_INITRD_COMPATIBLE),
FDT_COMPATIBLE (MODULE_XSM_COMPATIBLE),
FDT_COMPATIBLE (MODULE_CUSTOM_COMPATIBLE)
};
static __inline grub_addr_t static __inline grub_addr_t
xen_boot_address_align (grub_addr_t start, grub_size_t align) xen_boot_address_align (grub_addr_t start, grub_size_t align)
@ -136,20 +103,6 @@ xen_boot_address_align (grub_addr_t start, grub_size_t align)
return (align ? (ALIGN_UP (start, align)) : start); return (align ? (ALIGN_UP (start, align)) : start);
} }
/* set module type according to command name. */
static grub_err_t
set_module_type (grub_command_t cmd, struct xen_boot_binary *module)
{
if (!grub_strcmp (cmd->name, "xen_linux"))
module->node_info.type = MODULE_IMAGE;
else if (!grub_strcmp (cmd->name, "xen_initrd"))
module->node_info.type = MODULE_INITRD;
else if (!grub_strcmp (cmd->name, "xen_xsm"))
module->node_info.type = MODULE_XSM;
return GRUB_ERR_NONE;
}
static grub_err_t static grub_err_t
prepare_xen_hypervisor_params (void *xen_boot_fdt) prepare_xen_hypervisor_params (void *xen_boot_fdt)
{ {
@ -203,15 +156,11 @@ prepare_xen_module_params (struct xen_boot_binary *module, void *xen_boot_fdt)
grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name); grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible", retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
module->node_info.compat_string, MODULE_CUSTOM_COMPATIBLE, sizeof(MODULE_CUSTOM_COMPATIBLE) - 1);
(grub_uint32_t) module->
node_info.compat_string_size);
if (retval) if (retval)
return grub_error (GRUB_ERR_IO, "failed to update FDT"); return grub_error (GRUB_ERR_IO, "failed to update FDT");
grub_dprintf ("xen_loader", "Module %s compatible = %s size = 0x%lx\n", grub_dprintf ("xen_loader", "Module\n");
module->name, module->node_info.compat_string,
module->node_info.compat_string_size);
retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node, retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
xen_boot_address_align (module->start, xen_boot_address_align (module->start,
@ -223,7 +172,7 @@ prepare_xen_module_params (struct xen_boot_binary *module, void *xen_boot_fdt)
if (module->cmdline && module->cmdline_size > 0) if (module->cmdline && module->cmdline_size > 0)
{ {
grub_dprintf ("xen_loader", grub_dprintf ("xen_loader",
"Module %s cmdline : %s @ %p size:%d\n", module->name, "Module cmdline : %s @ %p size:%d\n",
module->cmdline, module->cmdline, module->cmdline_size); module->cmdline, module->cmdline, module->cmdline_size);
retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs", retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
@ -233,8 +182,7 @@ prepare_xen_module_params (struct xen_boot_binary *module, void *xen_boot_fdt)
} }
else else
{ {
grub_dprintf ("xen_loader", "Module %s has not bootargs!\n", grub_dprintf ("xen_loader", "Module has no bootargs!\n");
module->name);
} }
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
@ -251,8 +199,8 @@ finalize_params_xen_boot (void)
additional_size += FDT_NODE_NAME_MAX_SIZE + xen_hypervisor->cmdline_size; additional_size += FDT_NODE_NAME_MAX_SIZE + xen_hypervisor->cmdline_size;
FOR_LIST_ELEMENTS (module, module_head) FOR_LIST_ELEMENTS (module, module_head)
{ {
additional_size += 6 * FDT_NODE_NAME_MAX_SIZE + module-> additional_size += 6 * FDT_NODE_NAME_MAX_SIZE + sizeof(MODULE_CUSTOM_COMPATIBLE) - 1
node_info.compat_string_size + module->cmdline_size; + module->cmdline_size;
} }
xen_boot_fdt = grub_fdt_load (additional_size); xen_boot_fdt = grub_fdt_load (additional_size);
@ -275,8 +223,7 @@ finalize_params_xen_boot (void)
{ {
if (module->start && module->size > 0) if (module->start && module->size > 0)
{ {
grub_dprintf ("xen_loader", "Module %s @ 0x%lx size:0x%lx\n", grub_dprintf ("xen_loader", "Module @ 0x%lx size:0x%lx\n",
module->name,
xen_boot_address_align (module->start, module->align), xen_boot_address_align (module->start, module->align),
module->size); module->size);
if (prepare_xen_module_params (module, xen_boot_fdt) != GRUB_ERR_NONE) if (prepare_xen_module_params (module, xen_boot_fdt) != GRUB_ERR_NONE)
@ -284,7 +231,7 @@ finalize_params_xen_boot (void)
} }
else else
{ {
grub_dprintf ("xen_loader", "Module info error: %s!\n", module->name); grub_dprintf ("xen_loader", "Module info error!\n");
goto fail; goto fail;
} }
} }
@ -327,19 +274,16 @@ single_binary_unload (struct xen_boot_binary *binary)
{ {
grub_free (binary->cmdline); grub_free (binary->cmdline);
grub_dprintf ("xen_loader", grub_dprintf ("xen_loader",
"Module %s cmdline memory free @ %p size: %d\n", "Module cmdline memory free @ %p size: %d\n",
binary->name, binary->cmdline, binary->cmdline_size); binary->cmdline, binary->cmdline_size);
} }
if (binary->node_info.type == MODULE_CUSTOM) if (!binary->is_hypervisor)
grub_free ((void *) binary->node_info.compat_string);
if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
grub_list_remove (GRUB_AS_LIST (binary)); grub_list_remove (GRUB_AS_LIST (binary));
grub_dprintf ("xen_loader", grub_dprintf ("xen_loader",
"Module %s struct memory free @ %p size: 0x%lx\n", "Module struct memory free @ %p size: 0x%lx\n",
binary->name, binary, sizeof (binary)); binary, sizeof (binary));
grub_free (binary); grub_free (binary);
return; return;
@ -377,8 +321,7 @@ xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
int argc, char *argv[]) int argc, char *argv[])
{ {
binary->size = grub_file_size (file); binary->size = grub_file_size (file);
grub_dprintf ("xen_loader", "Xen_boot %s file size: 0x%lx\n", grub_dprintf ("xen_loader", "Xen_boot file size: 0x%lx\n", binary->size);
binary->name, binary->size);
binary->start binary->start
= (grub_addr_t) grub_efi_allocate_pages (0, = (grub_addr_t) grub_efi_allocate_pages (0,
@ -391,8 +334,8 @@ xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
return; return;
} }
grub_dprintf ("xen_loader", "Xen_boot %s numpages: 0x%lx\n", grub_dprintf ("xen_loader", "Xen_boot numpages: 0x%lx\n",
binary->name, GRUB_EFI_BYTES_TO_PAGES (binary->size + binary->align)); GRUB_EFI_BYTES_TO_PAGES (binary->size + binary->align));
if (grub_file_read (file, (void *) xen_boot_address_align (binary->start, if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
binary->align), binary->align),
@ -416,7 +359,7 @@ xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline, grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline,
binary->cmdline_size); binary->cmdline_size);
grub_dprintf ("xen_loader", grub_dprintf ("xen_loader",
"Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name, "Xen_boot cmdline @ %p %s, size: %d\n",
binary->cmdline, binary->cmdline, binary->cmdline_size); binary->cmdline, binary->cmdline, binary->cmdline_size);
} }
else else
@ -430,7 +373,8 @@ xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
} }
static grub_err_t static grub_err_t
grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[]) grub_cmd_xen_module (grub_command_t cmd __attribute__((unused)),
int argc, char *argv[])
{ {
struct xen_boot_binary *module = NULL; struct xen_boot_binary *module = NULL;
@ -454,34 +398,10 @@ grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
if (!module) if (!module)
return grub_errno; return grub_errno;
/* process all the options and get module type */ module->is_hypervisor = 0;
if (set_module_type (cmd, module) != GRUB_ERR_NONE) module->align = 4096;
goto fail;
switch (module->node_info.type)
{
case MODULE_IMAGE:
case MODULE_INITRD:
case MODULE_XSM:
module->node_info.compat_string =
default_compat_string[module->node_info.type].compat_string;
module->node_info.compat_string_size =
default_compat_string[module->node_info.type].size;
break;
case MODULE_CUSTOM: grub_dprintf ("xen_loader", "Init module and node info\n");
/* we have set the node_info in set_module_type */
break;
default:
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument"));
}
module->name = module->node_info.compat_string;
module->align = module_default_align[module->node_info.type];
grub_dprintf ("xen_loader", "Init %s module and node info:\n"
"compatible %s\ncompat_string_size 0x%lx\n",
module->name, module->node_info.compat_string,
module->node_info.compat_string_size);
file = grub_file_open (argv[0]); file = grub_file_open (argv[0]);
if (!file) if (!file)
@ -491,7 +411,7 @@ grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
if (grub_errno == GRUB_ERR_NONE) if (grub_errno == GRUB_ERR_NONE)
grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module)); grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
fail: fail:
if (file) if (file)
grub_file_close (file); grub_file_close (file);
if (grub_errno != GRUB_ERR_NONE) if (grub_errno != GRUB_ERR_NONE)
@ -535,7 +455,7 @@ grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
if (!xen_hypervisor) if (!xen_hypervisor)
return grub_errno; return grub_errno;
xen_hypervisor->name = XEN_HYPERVISOR_NAME; xen_hypervisor->is_hypervisor = 1;
xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment; xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
xen_boot_binary_load (xen_hypervisor, file, argc, argv); xen_boot_binary_load (xen_hypervisor, file, argc, argv);
@ -559,29 +479,21 @@ fail:
} }
static grub_command_t cmd_xen_hypervisor; static grub_command_t cmd_xen_hypervisor;
static grub_command_t cmd_xen_linux, cmd_xen_initrd, cmd_xen_xsm; static grub_command_t cmd_xen_module;
GRUB_MOD_INIT (xen_boot) GRUB_MOD_INIT (xen_boot)
{ {
cmd_xen_hypervisor = cmd_xen_hypervisor =
grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0, grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
N_("Load a xen hypervisor.")); N_("Load a xen hypervisor."));
cmd_xen_linux = cmd_xen_module =
grub_register_command ("xen_linux", grub_cmd_xen_module, 0, grub_register_command ("xen_module", grub_cmd_xen_module, 0,
N_("Load a xen linux kernel for dom0.")); N_("Load a xen module."));
cmd_xen_initrd =
grub_register_command ("xen_initrd", grub_cmd_xen_module, 0,
N_("Load a xen initrd for dom0."));
cmd_xen_xsm =
grub_register_command ("xen_xsm", grub_cmd_xen_module, 0,
N_("Load a xen security module."));
my_mod = mod; my_mod = mod;
} }
GRUB_MOD_FINI (xen_boot) GRUB_MOD_FINI (xen_boot)
{ {
grub_unregister_command (cmd_xen_hypervisor); grub_unregister_command (cmd_xen_hypervisor);
grub_unregister_command (cmd_xen_linux); grub_unregister_command (cmd_xen_module);
grub_unregister_command (cmd_xen_initrd);
grub_unregister_command (cmd_xen_xsm);
} }

View file

@ -122,6 +122,8 @@ copy_file_path (grub_efi_file_path_device_path_t *fp,
if (*p == '/') if (*p == '/')
*p = '\\'; *p = '\\';
/* File Path is NULL terminated */
fp->path_name[size++] = '\0';
fp->header.length = size * sizeof (grub_efi_char16_t) + sizeof (*fp); fp->header.length = size * sizeof (grub_efi_char16_t) + sizeof (*fp);
} }
@ -156,8 +158,10 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
d = GRUB_EFI_NEXT_DEVICE_PATH (d); d = GRUB_EFI_NEXT_DEVICE_PATH (d);
} }
/* File Path is NULL terminated. Allocate space for 2 extra characters */
/* FIXME why we split path in two components? */
file_path = grub_malloc (size file_path = grub_malloc (size
+ ((grub_strlen (dir_start) + 1) + ((grub_strlen (dir_start) + 2)
* GRUB_MAX_UTF16_PER_UTF8 * GRUB_MAX_UTF16_PER_UTF8
* sizeof (grub_efi_char16_t)) * sizeof (grub_efi_char16_t))
+ sizeof (grub_efi_file_path_device_path_t) * 2); + sizeof (grub_efi_file_path_device_path_t) * 2);

View file

@ -1889,6 +1889,10 @@ grub_cmd_freebsd_module (grub_command_t cmd __attribute__ ((unused)),
grub_err_t err; grub_err_t err;
void *src; void *src;
if (! grub_loader_is_loaded ())
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the kernel first"));
if (kernel_type != KERNEL_TYPE_FREEBSD) if (kernel_type != KERNEL_TYPE_FREEBSD)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no FreeBSD loaded"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "no FreeBSD loaded");
@ -1992,6 +1996,10 @@ grub_cmd_netbsd_module (grub_command_t cmd,
{ {
grub_uint32_t type; grub_uint32_t type;
if (! grub_loader_is_loaded ())
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the kernel first"));
if (kernel_type != KERNEL_TYPE_NETBSD) if (kernel_type != KERNEL_TYPE_NETBSD)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no NetBSD loaded"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "no NetBSD loaded");
@ -2070,6 +2078,10 @@ grub_cmd_openbsd_ramdisk (grub_command_t cmd __attribute__ ((unused)),
if (argc != 1) if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
if (! grub_loader_is_loaded ())
return grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the kernel first"));
if (kernel_type != KERNEL_TYPE_OPENBSD) if (kernel_type != KERNEL_TYPE_OPENBSD)
return grub_error (GRUB_ERR_BAD_OS, "no kOpenBSD loaded"); return grub_error (GRUB_ERR_BAD_OS, "no kOpenBSD loaded");

View file

@ -48,15 +48,15 @@ read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, char **shdr)
if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS)) if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS))
return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic")); return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
*shdr = grub_malloc (e->e_shnum * e->e_shentsize); *shdr = grub_malloc ((grub_uint32_t) e->e_shnum * e->e_shentsize);
if (! *shdr) if (! *shdr)
return grub_errno; return grub_errno;
if (grub_file_seek (file, e->e_shoff) == (grub_off_t) -1) if (grub_file_seek (file, e->e_shoff) == (grub_off_t) -1)
return grub_errno; return grub_errno;
if (grub_file_read (file, *shdr, e->e_shnum * e->e_shentsize) if (grub_file_read (file, *shdr, (grub_uint32_t) e->e_shnum * e->e_shentsize)
!= e->e_shnum * e->e_shentsize) != (grub_ssize_t) ((grub_uint32_t) e->e_shnum * e->e_shentsize))
{ {
if (grub_errno) if (grub_errno)
return grub_errno; return grub_errno;
@ -200,8 +200,8 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator,
if (chunk_size < sizeof (e)) if (chunk_size < sizeof (e))
chunk_size = sizeof (e); chunk_size = sizeof (e);
chunk_size += e.e_phnum * e.e_phentsize; chunk_size += (grub_uint32_t) e.e_phnum * e.e_phentsize;
chunk_size += e.e_shnum * e.e_shentsize; chunk_size += (grub_uint32_t) e.e_shnum * e.e_shentsize;
{ {
grub_relocator_chunk_t ch; grub_relocator_chunk_t ch;
@ -253,14 +253,14 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator,
curload = module + sizeof (e); curload = module + sizeof (e);
load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_shoff, load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_shoff,
e.e_shnum * e.e_shentsize); (grub_uint32_t) e.e_shnum * e.e_shentsize);
e.e_shoff = curload - module; e.e_shoff = curload - module;
curload += e.e_shnum * e.e_shentsize; curload += (grub_uint32_t) e.e_shnum * e.e_shentsize;
load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_phoff, load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_phoff,
e.e_phnum * e.e_phentsize); (grub_uint32_t) e.e_phnum * e.e_phentsize);
e.e_phoff = curload - module; e.e_phoff = curload - module;
curload += e.e_phnum * e.e_phentsize; curload += (grub_uint32_t) e.e_phnum * e.e_phentsize;
*kern_end = curload; *kern_end = curload;
@ -462,7 +462,7 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
chunk_size = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t)) chunk_size = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
+ ALIGN_UP (strsize, sizeof (grub_freebsd_addr_t)) + ALIGN_UP (strsize, sizeof (grub_freebsd_addr_t))
+ sizeof (e) + e.e_shnum * e.e_shentsize; + sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t)); symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
{ {
@ -498,10 +498,10 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
s2 = (Elf_Shdr *) curload; s2 = (Elf_Shdr *) curload;
grub_memcpy (curload, s, e.e_shentsize); grub_memcpy (curload, s, e.e_shentsize);
if (s == symsh) if (s == symsh)
s2->sh_offset = sizeof (e) + e.e_shnum * e.e_shentsize; s2->sh_offset = sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
else if (s == strsh) else if (s == strsh)
s2->sh_offset = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t)) s2->sh_offset = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
+ sizeof (e) + e.e_shnum * e.e_shentsize; + sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
else else
s2->sh_offset = 0; s2->sh_offset = 0;
s2->sh_addr = s2->sh_offset; s2->sh_addr = s2->sh_offset;

View file

@ -929,8 +929,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_env_set ("gfxpayload", "text"); grub_env_set ("gfxpayload", "text");
grub_printf_ (N_("%s is deprecated. " grub_printf_ (N_("%s is deprecated. "
"Use set gfxpayload=%s before " "Use set gfxpayload=%s before "
"linux command instead.\n"), "text", "linux command instead.\n"),
argv[i]); argv[i], "text");
break; break;
case 1: case 1:
@ -939,8 +939,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_env_set ("gfxpayload", "text"); grub_env_set ("gfxpayload", "text");
grub_printf_ (N_("%s is deprecated. " grub_printf_ (N_("%s is deprecated. "
"Use set gfxpayload=%s before " "Use set gfxpayload=%s before "
"linux command instead.\n"), "text", "linux command instead.\n"),
argv[i]); argv[i], "text");
break; break;
default: default:
/* Ignore invalid values. */ /* Ignore invalid values. */

View file

@ -71,9 +71,18 @@ load_kernel (grub_file_t file, const char *filename,
char *buffer, struct multiboot_header *header) char *buffer, struct multiboot_header *header)
{ {
grub_err_t err; grub_err_t err;
mbi_load_data_t mld;
mld.file = file;
mld.filename = filename;
mld.buffer = buffer;
mld.mbi_ver = 1;
mld.relocatable = 0;
mld.avoid_efi_boot_services = 0;
if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE) if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE)
{ {
err = grub_multiboot_load_elf (file, filename, buffer); err = grub_multiboot_load_elf (&mld);
if (err == GRUB_ERR_NONE) { if (err == GRUB_ERR_NONE) {
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -122,7 +131,7 @@ load_kernel (grub_file_t file, const char *filename,
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
return grub_multiboot_load_elf (file, filename, buffer); return grub_multiboot_load_elf (&mld);
} }
static struct multiboot_header * static struct multiboot_header *

View file

@ -205,7 +205,7 @@ grub_cmd_truecrypt (grub_command_t cmd __attribute__ ((unused)),
fail: fail:
if (!grub_errno) if (!grub_errno)
return grub_error (GRUB_ERR_BAD_OS, "bad truecrypt ISO"); grub_error (GRUB_ERR_BAD_OS, "bad truecrypt ISO");
if (file) if (file)
grub_file_close (file); grub_file_close (file);

File diff suppressed because it is too large Load diff

View file

@ -65,14 +65,14 @@ grub_xen_file_and_cmdline (grub_file_t file,
grub_dprintf ("xen", "found bzimage payload 0x%llx-0x%llx\n", grub_dprintf ("xen", "found bzimage payload 0x%llx-0x%llx\n",
(unsigned long long) (lh.setup_sects + 1) * 512 (unsigned long long) (lh.setup_sects + 1) * 512
+ lh.payload_offset, + lh.payload_offset,
(unsigned long long) lh.payload_length - 4); (unsigned long long) lh.payload_length);
if (cmdline) if (cmdline)
grub_pass_verity_hash (&lh, cmdline, cmdline_max_len); grub_pass_verity_hash (&lh, cmdline, cmdline_max_len);
off_file = grub_file_offset_open (file, (lh.setup_sects + 1) * 512 off_file = grub_file_offset_open (file, (lh.setup_sects + 1) * 512
+ lh.payload_offset, + lh.payload_offset,
lh.payload_length - 4); lh.payload_length);
if (!off_file) if (!off_file)
goto fail; goto fail;

View file

@ -18,6 +18,7 @@
#include <grub/xen_file.h> #include <grub/xen_file.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <xen/elfnote.h>
static grub_err_t static grub_err_t
parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi, parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
@ -26,6 +27,8 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
char *buf; char *buf;
char *ptr; char *ptr;
int has_paddr = 0; int has_paddr = 0;
grub_errno = GRUB_ERR_NONE;
if (grub_file_seek (elf->file, off) == (grub_off_t) -1) if (grub_file_seek (elf->file, off) == (grub_off_t) -1)
return grub_errno; return grub_errno;
buf = grub_malloc (sz); buf = grub_malloc (sz);
@ -35,7 +38,8 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
if (grub_file_read (elf->file, buf, sz) != (grub_ssize_t) sz) if (grub_file_read (elf->file, buf, sz) != (grub_ssize_t) sz)
{ {
if (grub_errno) if (grub_errno)
return grub_errno; goto out;
grub_free (buf);
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
elf->file->name); elf->file->name);
} }
@ -123,14 +127,14 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
{ {
xi->virt_base = grub_strtoull (ptr + sizeof ("VIRT_BASE=") - 1, &ptr, 16); xi->virt_base = grub_strtoull (ptr + sizeof ("VIRT_BASE=") - 1, &ptr, 16);
if (grub_errno) if (grub_errno)
return grub_errno; goto out;
continue; continue;
} }
if (grub_strncmp (ptr, "VIRT_ENTRY=", sizeof ("VIRT_ENTRY=") - 1) == 0) if (grub_strncmp (ptr, "VIRT_ENTRY=", sizeof ("VIRT_ENTRY=") - 1) == 0)
{ {
xi->entry_point = grub_strtoull (ptr + sizeof ("VIRT_ENTRY=") - 1, &ptr, 16); xi->entry_point = grub_strtoull (ptr + sizeof ("VIRT_ENTRY=") - 1, &ptr, 16);
if (grub_errno) if (grub_errno)
return grub_errno; goto out;
continue; continue;
} }
if (grub_strncmp (ptr, "HYPERCALL_PAGE=", sizeof ("HYPERCALL_PAGE=") - 1) == 0) if (grub_strncmp (ptr, "HYPERCALL_PAGE=", sizeof ("HYPERCALL_PAGE=") - 1) == 0)
@ -138,7 +142,7 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
xi->hypercall_page = grub_strtoull (ptr + sizeof ("HYPERCALL_PAGE=") - 1, &ptr, 16); xi->hypercall_page = grub_strtoull (ptr + sizeof ("HYPERCALL_PAGE=") - 1, &ptr, 16);
xi->has_hypercall_page = 1; xi->has_hypercall_page = 1;
if (grub_errno) if (grub_errno)
return grub_errno; goto out;
continue; continue;
} }
if (grub_strncmp (ptr, "ELF_PADDR_OFFSET=", sizeof ("ELF_PADDR_OFFSET=") - 1) == 0) if (grub_strncmp (ptr, "ELF_PADDR_OFFSET=", sizeof ("ELF_PADDR_OFFSET=") - 1) == 0)
@ -146,7 +150,7 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
xi->paddr_offset = grub_strtoull (ptr + sizeof ("ELF_PADDR_OFFSET=") - 1, &ptr, 16); xi->paddr_offset = grub_strtoull (ptr + sizeof ("ELF_PADDR_OFFSET=") - 1, &ptr, 16);
has_paddr = 1; has_paddr = 1;
if (grub_errno) if (grub_errno)
return grub_errno; goto out;
continue; continue;
} }
} }
@ -154,7 +158,11 @@ parse_xen_guest (grub_elf_t elf, struct grub_xen_file_info *xi,
xi->hypercall_page = (xi->hypercall_page << 12) + xi->virt_base; xi->hypercall_page = (xi->hypercall_page << 12) + xi->virt_base;
if (!has_paddr) if (!has_paddr)
xi->paddr_offset = xi->virt_base; xi->paddr_offset = xi->virt_base;
return GRUB_ERR_NONE;
out:
grub_free (buf);
return grub_errno;
} }
#pragma GCC diagnostic ignored "-Wcast-align" #pragma GCC diagnostic ignored "-Wcast-align"
@ -196,35 +204,35 @@ parse_note (grub_elf_t elf, struct grub_xen_file_info *xi,
xi->has_note = 1; xi->has_note = 1;
switch (nh->n_type) switch (nh->n_type)
{ {
case 1: case XEN_ELFNOTE_ENTRY:
xi->entry_point = grub_le_to_cpu_addr (*(Elf_Addr *) desc); xi->entry_point = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
break; break;
case 2: case XEN_ELFNOTE_HYPERCALL_PAGE:
xi->hypercall_page = grub_le_to_cpu_addr (*(Elf_Addr *) desc); xi->hypercall_page = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
xi->has_hypercall_page = 1; xi->has_hypercall_page = 1;
break; break;
case 3: case XEN_ELFNOTE_VIRT_BASE:
xi->virt_base = grub_le_to_cpu_addr (*(Elf_Addr *) desc); xi->virt_base = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
break; break;
case 4: case XEN_ELFNOTE_PADDR_OFFSET:
xi->paddr_offset = grub_le_to_cpu_addr (*(Elf_Addr *) desc); xi->paddr_offset = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
break; break;
case 5: case XEN_ELFNOTE_XEN_VERSION:
grub_dprintf ("xen", "xenversion = `%s'\n", (char *) desc); grub_dprintf ("xen", "xenversion = `%s'\n", (char *) desc);
break; break;
case 6: case XEN_ELFNOTE_GUEST_OS:
grub_dprintf ("xen", "name = `%s'\n", (char *) desc); grub_dprintf ("xen", "name = `%s'\n", (char *) desc);
break; break;
case 7: case XEN_ELFNOTE_GUEST_VERSION:
grub_dprintf ("xen", "version = `%s'\n", (char *) desc); grub_dprintf ("xen", "version = `%s'\n", (char *) desc);
break; break;
case 8: case XEN_ELFNOTE_LOADER:
if (descsz < 7 if (descsz < 7
|| grub_memcmp (desc, "generic", descsz == 7 ? 7 : 8) != 0) || grub_memcmp (desc, "generic", descsz == 7 ? 7 : 8) != 0)
return grub_error (GRUB_ERR_BAD_OS, "invalid loader"); return grub_error (GRUB_ERR_BAD_OS, "invalid loader");
break; break;
/* PAE */ /* PAE */
case 9: case XEN_ELFNOTE_PAE_MODE:
grub_dprintf ("xen", "pae = `%s', %d, %d\n", (char *) desc, grub_dprintf ("xen", "pae = `%s', %d, %d\n", (char *) desc,
xi->arch, descsz); xi->arch, descsz);
if (xi->arch != GRUB_XEN_FILE_I386 if (xi->arch != GRUB_XEN_FILE_I386
@ -253,6 +261,13 @@ parse_note (grub_elf_t elf, struct grub_xen_file_info *xi,
descsz == 2 ? 2 : 3) == 0) descsz == 2 ? 2 : 3) == 0)
xi->arch = GRUB_XEN_FILE_I386; xi->arch = GRUB_XEN_FILE_I386;
break; break;
case XEN_ELFNOTE_INIT_P2M:
xi->p2m_base = grub_le_to_cpu_addr (*(Elf_Addr *) desc);
xi->has_p2m_base = 1;
break;
case XEN_ELFNOTE_MOD_START_PFN:
xi->unmapped_initrd = !!grub_le_to_cpu32(*(grub_uint32_t *) desc);
break;
default: default:
grub_dprintf ("xen", "unknown note type %d\n", nh->n_type); grub_dprintf ("xen", "unknown note type %d\n", nh->n_type);
break; break;

View file

@ -35,6 +35,7 @@
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/bitmap_scale.h> #include <grub/bitmap_scale.h>
#include <grub/cpu/io.h> #include <grub/cpu/io.h>
#include <grub/random.h>
#define min(a,b) (((a) < (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b))
#define max(a,b) (((a) > (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b))
@ -338,7 +339,7 @@ grub_xnu_devprop_add_property_utf16 (struct grub_xnu_devprop_device_descriptor *
utf8 = grub_malloc (namelen * 4 + 1); utf8 = grub_malloc (namelen * 4 + 1);
if (!utf8) if (!utf8)
{ {
grub_free (utf8); grub_free (utf16);
return grub_errno; return grub_errno;
} }
@ -577,11 +578,31 @@ static grub_err_t
grub_cpu_xnu_fill_devicetree (grub_uint64_t *fsbfreq_out) grub_cpu_xnu_fill_devicetree (grub_uint64_t *fsbfreq_out)
{ {
struct grub_xnu_devtree_key *efikey; struct grub_xnu_devtree_key *efikey;
struct grub_xnu_devtree_key *chosenkey;
struct grub_xnu_devtree_key *cfgtablekey; struct grub_xnu_devtree_key *cfgtablekey;
struct grub_xnu_devtree_key *curval; struct grub_xnu_devtree_key *curval;
struct grub_xnu_devtree_key *runtimesrvkey; struct grub_xnu_devtree_key *runtimesrvkey;
struct grub_xnu_devtree_key *platformkey; struct grub_xnu_devtree_key *platformkey;
unsigned i, j; unsigned i, j;
grub_err_t err;
chosenkey = grub_xnu_create_key (&grub_xnu_devtree_root, "chosen");
if (! chosenkey)
return grub_errno;
/* Random seed. */
curval = grub_xnu_create_value (&(chosenkey->first_child), "random-seed");
if (! curval)
return grub_errno;
curval->datasize = 64;
curval->data = grub_malloc (curval->datasize);
if (! curval->data)
return grub_errno;
/* Our random is not peer-reviewed but xnu uses this seed only for
ASLR in kernel. */
err = grub_crypto_get_random (curval->data, curval->datasize);
if (err)
return err;
/* The value "model". */ /* The value "model". */
/* FIXME: may this value be sometimes different? */ /* FIXME: may this value be sometimes different? */
@ -897,6 +918,28 @@ grub_xnu_set_video (struct grub_xnu_boot_params_common *params)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
static int
total_ram_hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size,
grub_memory_type_t type,
void *data)
{
grub_uint64_t *result = data;
if (type != GRUB_MEMORY_AVAILABLE)
return 0;
*result += size;
return 0;
}
static grub_uint64_t
get_total_ram (void)
{
grub_uint64_t result = 0;
grub_mmap_iterate (total_ram_hook, &result);
return result;
}
/* Boot xnu. */ /* Boot xnu. */
grub_err_t grub_err_t
grub_xnu_boot (void) grub_xnu_boot (void)
@ -973,6 +1016,7 @@ grub_xnu_boot (void)
{ {
bootparams_common = &bootparams->v2.common; bootparams_common = &bootparams->v2.common;
bootparams->v2.fsbfreq = fsbfreq; bootparams->v2.fsbfreq = fsbfreq;
bootparams->v2.ram_size = get_total_ram();
} }
else else
bootparams_common = &bootparams->v1.common; bootparams_common = &bootparams->v1.common;
@ -1080,7 +1124,7 @@ grub_xnu_boot (void)
bootparams_common->efi_mmap = memory_map_target; bootparams_common->efi_mmap = memory_map_target;
bootparams_common->efi_mmap_size = memory_map_size; bootparams_common->efi_mmap_size = memory_map_size;
bootparams_common->heap_start = grub_xnu_heap_target_start; bootparams_common->heap_start = grub_xnu_heap_target_start;
bootparams_common->heap_size = grub_xnu_heap_size; bootparams_common->heap_size = curruntimepage * GRUB_XNU_PAGESIZE - grub_xnu_heap_target_start;
/* Parameters for asm helper. */ /* Parameters for asm helper. */
grub_xnu_stack = bootparams_common->heap_start grub_xnu_stack = bootparams_common->heap_start

View file

@ -119,6 +119,48 @@ grub_multiboot_set_video_mode (void)
return err; return err;
} }
#ifdef GRUB_MACHINE_EFI
#ifdef __x86_64__
#define grub_relocator_efi_boot grub_relocator64_efi_boot
#define grub_relocator_efi_state grub_relocator64_efi_state
#endif
#endif
#ifdef grub_relocator_efi_boot
static void
efi_boot (struct grub_relocator *rel,
grub_uint32_t target)
{
struct grub_relocator_efi_state state_efi = MULTIBOOT_EFI_INITIAL_STATE;
state_efi.MULTIBOOT_EFI_ENTRY_REGISTER = grub_multiboot_payload_eip;
state_efi.MULTIBOOT_EFI_MBI_REGISTER = target;
grub_relocator_efi_boot (rel, state_efi);
}
#else
#define grub_efi_is_finished 1
static void
efi_boot (struct grub_relocator *rel __attribute__ ((unused)),
grub_uint32_t target __attribute__ ((unused)))
{
}
#endif
#if defined (__i386__) || defined (__x86_64__)
static void
normal_boot (struct grub_relocator *rel, struct grub_relocator32_state state)
{
grub_relocator32_boot (rel, state, 0);
}
#else
static void
normal_boot (struct grub_relocator *rel, struct grub_relocator32_state state)
{
grub_relocator32_boot (rel, state);
}
#endif
static grub_err_t static grub_err_t
grub_multiboot_boot (void) grub_multiboot_boot (void)
{ {
@ -132,11 +174,10 @@ grub_multiboot_boot (void)
if (err) if (err)
return err; return err;
#if defined (__i386__) || defined (__x86_64__) if (grub_efi_is_finished)
grub_relocator32_boot (grub_multiboot_relocator, state, 0); normal_boot (grub_multiboot_relocator, state);
#else else
grub_relocator32_boot (grub_multiboot_relocator, state); efi_boot (grub_multiboot_relocator, state.MULTIBOOT_MBI_REGISTER);
#endif
/* Not reached. */ /* Not reached. */
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
@ -167,13 +208,12 @@ static grub_uint64_t highest_load;
/* Load ELF32 or ELF64. */ /* Load ELF32 or ELF64. */
grub_err_t grub_err_t
grub_multiboot_load_elf (grub_file_t file, const char *filename, grub_multiboot_load_elf (mbi_load_data_t *mld)
void *buffer)
{ {
if (grub_multiboot_is_elf32 (buffer)) if (grub_multiboot_is_elf32 (mld->buffer))
return grub_multiboot_load_elf32 (file, filename, buffer); return grub_multiboot_load_elf32 (mld);
else if (grub_multiboot_is_elf64 (buffer)) else if (grub_multiboot_is_elf64 (mld->buffer))
return grub_multiboot_load_elf64 (file, filename, buffer); return grub_multiboot_load_elf64 (mld);
return grub_error (GRUB_ERR_UNKNOWN_OS, N_("invalid arch-dependent ELF magic")); return grub_error (GRUB_ERR_UNKNOWN_OS, N_("invalid arch-dependent ELF magic"));
} }

View file

@ -51,11 +51,15 @@ CONCAT(grub_multiboot_is_elf, XX) (void *buffer)
} }
static grub_err_t static grub_err_t
CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, void *buffer) CONCAT(grub_multiboot_load_elf, XX) (mbi_load_data_t *mld)
{ {
Elf_Ehdr *ehdr = (Elf_Ehdr *) buffer; Elf_Ehdr *ehdr = (Elf_Ehdr *) mld->buffer;
char *phdr_base; char *phdr_base;
grub_err_t err;
grub_relocator_chunk_t ch;
grub_uint32_t load_offset, load_size;
int i; int i;
void *source;
if (ehdr->e_ident[EI_MAG0] != ELFMAG0 if (ehdr->e_ident[EI_MAG0] != ELFMAG0
|| ehdr->e_ident[EI_MAG1] != ELFMAG1 || ehdr->e_ident[EI_MAG1] != ELFMAG1
@ -72,57 +76,89 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
return grub_error (GRUB_ERR_UNKNOWN_OS, N_("this ELF file is not of the right type")); return grub_error (GRUB_ERR_UNKNOWN_OS, N_("this ELF file is not of the right type"));
/* FIXME: Should we support program headers at strange locations? */ /* FIXME: Should we support program headers at strange locations? */
if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH) if (ehdr->e_phoff + (grub_uint32_t) ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH)
return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset"); return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
phdr_base = (char *) buffer + ehdr->e_phoff; phdr_base = (char *) mld->buffer + ehdr->e_phoff;
#define phdr(i) ((Elf_Phdr *) (phdr_base + (i) * ehdr->e_phentsize)) #define phdr(i) ((Elf_Phdr *) (phdr_base + (i) * ehdr->e_phentsize))
mld->link_base_addr = ~0;
/* Calculate lowest and highest load address. */
for (i = 0; i < ehdr->e_phnum; i++)
if (phdr(i)->p_type == PT_LOAD)
{
mld->link_base_addr = grub_min (mld->link_base_addr, phdr(i)->p_paddr);
highest_load = grub_max (highest_load, phdr(i)->p_paddr + phdr(i)->p_memsz);
}
#ifdef MULTIBOOT_LOAD_ELF64
if (highest_load >= 0x100000000)
return grub_error (GRUB_ERR_BAD_OS, "segment crosses 4 GiB border");
#endif
load_size = highest_load - mld->link_base_addr;
if (mld->relocatable)
{
if (load_size > mld->max_addr || mld->min_addr > mld->max_addr - load_size)
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
mld->min_addr, mld->max_addr - load_size,
load_size, mld->align ? mld->align : 1,
mld->preference, mld->avoid_efi_boot_services);
}
else
err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, &ch,
mld->link_base_addr, load_size);
if (err)
{
grub_dprintf ("multiboot_loader", "Cannot allocate memory for OS image\n");
return err;
}
mld->load_base_addr = get_physical_target_address (ch);
source = get_virtual_current_address (ch);
grub_dprintf ("multiboot_loader", "link_base_addr=0x%x, load_base_addr=0x%x, "
"load_size=0x%x, relocatable=%d\n", mld->link_base_addr,
mld->load_base_addr, load_size, mld->relocatable);
if (mld->relocatable)
grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, avoid_efi_boot_services=%d\n",
(long) mld->align, mld->preference, mld->avoid_efi_boot_services);
/* Load every loadable segment in memory. */ /* Load every loadable segment in memory. */
for (i = 0; i < ehdr->e_phnum; i++) for (i = 0; i < ehdr->e_phnum; i++)
{ {
if (phdr(i)->p_type == PT_LOAD) if (phdr(i)->p_type == PT_LOAD)
{ {
grub_err_t err;
void *source;
if (phdr(i)->p_paddr + phdr(i)->p_memsz > highest_load)
highest_load = phdr(i)->p_paddr + phdr(i)->p_memsz;
grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n", grub_dprintf ("multiboot_loader", "segment %d: paddr=0x%lx, memsz=0x%lx, vaddr=0x%lx\n",
i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr); i, (long) phdr(i)->p_paddr, (long) phdr(i)->p_memsz, (long) phdr(i)->p_vaddr);
{ load_offset = phdr(i)->p_paddr - mld->link_base_addr;
grub_relocator_chunk_t ch;
err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator,
&ch, phdr(i)->p_paddr,
phdr(i)->p_memsz);
if (err)
{
grub_dprintf ("multiboot_loader", "Error loading phdr %d\n", i);
return err;
}
source = get_virtual_current_address (ch);
}
if (phdr(i)->p_filesz != 0) if (phdr(i)->p_filesz != 0)
{ {
if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset) if (grub_file_seek (mld->file, (grub_off_t) phdr(i)->p_offset)
== (grub_off_t) -1) == (grub_off_t) -1)
return grub_errno; return grub_errno;
if (grub_file_read (file, source, phdr(i)->p_filesz) if (grub_file_read (mld->file, (grub_uint8_t *) source + load_offset, phdr(i)->p_filesz)
!= (grub_ssize_t) phdr(i)->p_filesz) != (grub_ssize_t) phdr(i)->p_filesz)
{ {
if (!grub_errno) if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
filename); mld->filename);
return grub_errno; return grub_errno;
} }
} }
if (phdr(i)->p_filesz < phdr(i)->p_memsz) if (phdr(i)->p_filesz < phdr(i)->p_memsz)
grub_memset ((grub_uint8_t *) source + phdr(i)->p_filesz, 0, grub_memset ((grub_uint8_t *) source + load_offset + phdr(i)->p_filesz, 0,
phdr(i)->p_memsz - phdr(i)->p_filesz); phdr(i)->p_memsz - phdr(i)->p_filesz);
} }
} }
@ -164,22 +200,22 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
{ {
grub_uint8_t *shdr, *shdrptr; grub_uint8_t *shdr, *shdrptr;
shdr = grub_malloc (ehdr->e_shnum * ehdr->e_shentsize); shdr = grub_malloc ((grub_uint32_t) ehdr->e_shnum * ehdr->e_shentsize);
if (!shdr) if (!shdr)
return grub_errno; return grub_errno;
if (grub_file_seek (file, ehdr->e_shoff) == (grub_off_t) -1) if (grub_file_seek (mld->file, ehdr->e_shoff) == (grub_off_t) -1)
{ {
grub_free (shdr); grub_free (shdr);
return grub_errno; return grub_errno;
} }
if (grub_file_read (file, shdr, ehdr->e_shnum * ehdr->e_shentsize) if (grub_file_read (mld->file, shdr, (grub_uint32_t) ehdr->e_shnum * ehdr->e_shentsize)
!= (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize) != (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize)
{ {
if (!grub_errno) if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
filename); mld->filename);
return grub_errno; return grub_errno;
} }
@ -189,7 +225,9 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
Elf_Shdr *sh = (Elf_Shdr *) shdrptr; Elf_Shdr *sh = (Elf_Shdr *) shdrptr;
void *src; void *src;
grub_addr_t target; grub_addr_t target;
grub_err_t err;
if (mld->mbi_ver >= 2 && (sh->sh_type == SHT_REL || sh->sh_type == SHT_RELA))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ELF files with relocs are not supported yet");
/* This section is a loaded section, /* This section is a loaded section,
so we don't care. */ so we don't care. */
@ -200,33 +238,28 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, voi
if (sh->sh_size == 0) if (sh->sh_size == 0)
continue; continue;
{ err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, 0,
grub_relocator_chunk_t ch; (0xffffffff - sh->sh_size) + 1,
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, sh->sh_size, sh->sh_addralign,
&ch, 0, GRUB_RELOCATOR_PREFERENCE_NONE,
(0xffffffff - sh->sh_size) mld->avoid_efi_boot_services);
+ 1, sh->sh_size, if (err)
sh->sh_addralign, {
GRUB_RELOCATOR_PREFERENCE_NONE, grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i);
0); return err;
if (err) }
{ src = get_virtual_current_address (ch);
grub_dprintf ("multiboot_loader", "Error loading shdr %d\n", i); target = get_physical_target_address (ch);
return err;
}
src = get_virtual_current_address (ch);
target = get_physical_target_address (ch);
}
if (grub_file_seek (file, sh->sh_offset) == (grub_off_t) -1) if (grub_file_seek (mld->file, sh->sh_offset) == (grub_off_t) -1)
return grub_errno; return grub_errno;
if (grub_file_read (file, src, sh->sh_size) if (grub_file_read (mld->file, src, sh->sh_size)
!= (grub_ssize_t) sh->sh_size) != (grub_ssize_t) sh->sh_size)
{ {
if (!grub_errno) if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
filename); mld->filename);
return grub_errno; return grub_errno;
} }
sh->sh_addr = target; sh->sh_addr = target;

View file

@ -69,6 +69,7 @@ static grub_size_t elf_sec_num, elf_sec_entsize;
static unsigned elf_sec_shstrndx; static unsigned elf_sec_shstrndx;
static void *elf_sections; static void *elf_sections;
static int keep_bs = 0; static int keep_bs = 0;
static grub_uint32_t load_base_addr;
void void
grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize, grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize,
@ -102,39 +103,43 @@ find_header (grub_properly_aligned_t *buffer, grub_ssize_t len)
grub_err_t grub_err_t
grub_multiboot_load (grub_file_t file, const char *filename) grub_multiboot_load (grub_file_t file, const char *filename)
{ {
grub_properly_aligned_t *buffer;
grub_ssize_t len; grub_ssize_t len;
struct multiboot_header *header; struct multiboot_header *header;
grub_err_t err; grub_err_t err;
struct multiboot_header_tag *tag; struct multiboot_header_tag *tag;
struct multiboot_header_tag_address *addr_tag = NULL; struct multiboot_header_tag_address *addr_tag = NULL;
int entry_specified = 0; struct multiboot_header_tag_relocatable *rel_tag;
grub_addr_t entry = 0; int entry_specified = 0, efi_entry_specified = 0;
grub_addr_t entry = 0, efi_entry = 0;
grub_uint32_t console_required = 0; grub_uint32_t console_required = 0;
struct multiboot_header_tag_framebuffer *fbtag = NULL; struct multiboot_header_tag_framebuffer *fbtag = NULL;
int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT; int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
mbi_load_data_t mld;
buffer = grub_malloc (MULTIBOOT_SEARCH); mld.mbi_ver = 2;
if (!buffer) mld.relocatable = 0;
mld.buffer = grub_malloc (MULTIBOOT_SEARCH);
if (!mld.buffer)
return grub_errno; return grub_errno;
len = grub_file_read (file, buffer, MULTIBOOT_SEARCH); len = grub_file_read (file, mld.buffer, MULTIBOOT_SEARCH);
if (len < 32) if (len < 32)
{ {
grub_free (buffer); grub_free (mld.buffer);
return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), filename); return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), filename);
} }
COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0); COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0);
grub_tpm_measure ((unsigned char *)buffer, len, GRUB_BINARY_PCR, "grub_multiboot", filename); grub_tpm_measure ((unsigned char *)mld.buffer, len, GRUB_BINARY_PCR, "grub_multiboot", filename);
grub_print_error(); grub_print_error();
header = find_header (buffer, len); header = find_header (mld.buffer, len);
if (header == 0) if (header == 0)
{ {
grub_free (buffer); grub_free (mld.buffer);
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
} }
@ -176,10 +181,13 @@ grub_multiboot_load (grub_file_t file, const char *filename)
case MULTIBOOT_TAG_TYPE_NETWORK: case MULTIBOOT_TAG_TYPE_NETWORK:
case MULTIBOOT_TAG_TYPE_EFI_MMAP: case MULTIBOOT_TAG_TYPE_EFI_MMAP:
case MULTIBOOT_TAG_TYPE_EFI_BS: case MULTIBOOT_TAG_TYPE_EFI_BS:
case MULTIBOOT_TAG_TYPE_EFI32_IH:
case MULTIBOOT_TAG_TYPE_EFI64_IH:
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
break; break;
default: default:
grub_free (buffer); grub_free (mld.buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS, return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported information tag: 0x%x", "unsupported information tag: 0x%x",
request_tag->requests[i]); request_tag->requests[i]);
@ -196,6 +204,13 @@ grub_multiboot_load (grub_file_t file, const char *filename)
entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr; entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
break; break;
case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64:
#if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
efi_entry_specified = 1;
efi_entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
#endif
break;
case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS: case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
& MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED)) & MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
@ -210,27 +225,50 @@ grub_multiboot_load (grub_file_t file, const char *filename)
accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER; accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER;
break; break;
case MULTIBOOT_HEADER_TAG_RELOCATABLE:
mld.relocatable = 1;
rel_tag = (struct multiboot_header_tag_relocatable *) tag;
mld.min_addr = rel_tag->min_addr;
mld.max_addr = rel_tag->max_addr;
mld.align = rel_tag->align;
switch (rel_tag->preference)
{
case MULTIBOOT_LOAD_PREFERENCE_LOW:
mld.preference = GRUB_RELOCATOR_PREFERENCE_LOW;
break;
case MULTIBOOT_LOAD_PREFERENCE_HIGH:
mld.preference = GRUB_RELOCATOR_PREFERENCE_HIGH;
break;
default:
mld.preference = GRUB_RELOCATOR_PREFERENCE_NONE;
}
break;
/* GRUB always page-aligns modules. */ /* GRUB always page-aligns modules. */
case MULTIBOOT_HEADER_TAG_MODULE_ALIGN: case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
break; break;
case MULTIBOOT_HEADER_TAG_EFI_BS: case MULTIBOOT_HEADER_TAG_EFI_BS:
#ifdef GRUB_MACHINE_EFI
keep_bs = 1; keep_bs = 1;
#endif
break; break;
default: default:
if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)) if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL))
{ {
grub_free (buffer); grub_free (mld.buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS, return grub_error (GRUB_ERR_UNKNOWN_OS,
"unsupported tag: 0x%x", tag->type); "unsupported tag: 0x%x", tag->type);
} }
break; break;
} }
if (addr_tag && !entry_specified) if (addr_tag && !entry_specified && !(keep_bs && efi_entry_specified))
{ {
grub_free (buffer); grub_free (mld.buffer);
return grub_error (GRUB_ERR_UNKNOWN_OS, return grub_error (GRUB_ERR_UNKNOWN_OS,
"load address tag without entry address tag"); "load address tag without entry address tag");
} }
@ -239,8 +277,8 @@ grub_multiboot_load (grub_file_t file, const char *filename)
{ {
grub_uint64_t load_addr = (addr_tag->load_addr + 1) grub_uint64_t load_addr = (addr_tag->load_addr + 1)
? addr_tag->load_addr : (addr_tag->header_addr ? addr_tag->load_addr : (addr_tag->header_addr
- ((char *) header - (char *) buffer)); - ((char *) header - (char *) mld.buffer));
int offset = ((char *) header - (char *) buffer - int offset = ((char *) header - (char *) mld.buffer -
(addr_tag->header_addr - load_addr)); (addr_tag->header_addr - load_addr));
int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset : int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset :
addr_tag->load_end_addr - addr_tag->load_addr); addr_tag->load_end_addr - addr_tag->load_addr);
@ -253,27 +291,50 @@ grub_multiboot_load (grub_file_t file, const char *filename)
else else
code_size = load_size; code_size = load_size;
err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator, if (mld.relocatable)
&ch, load_addr, {
code_size); if (code_size > mld.max_addr || mld.min_addr > mld.max_addr - code_size)
{
grub_free (mld.buffer);
return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
}
err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch,
mld.min_addr, mld.max_addr - code_size,
code_size, mld.align ? mld.align : 1,
mld.preference, keep_bs);
}
else
err = grub_relocator_alloc_chunk_addr (grub_multiboot_relocator,
&ch, load_addr, code_size);
if (err) if (err)
{ {
grub_dprintf ("multiboot_loader", "Error loading aout kludge\n"); grub_dprintf ("multiboot_loader", "Error loading aout kludge\n");
grub_free (buffer); grub_free (mld.buffer);
return err; return err;
} }
mld.link_base_addr = load_addr;
mld.load_base_addr = get_physical_target_address (ch);
source = get_virtual_current_address (ch); source = get_virtual_current_address (ch);
grub_dprintf ("multiboot_loader", "link_base_addr=0x%x, load_base_addr=0x%x, "
"load_size=0x%lx, relocatable=%d\n", mld.link_base_addr,
mld.load_base_addr, (long) code_size, mld.relocatable);
if (mld.relocatable)
grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, avoid_efi_boot_services=%d\n",
(long) mld.align, mld.preference, keep_bs);
if ((grub_file_seek (file, offset)) == (grub_off_t) -1) if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
{ {
grub_free (buffer); grub_free (mld.buffer);
return grub_errno; return grub_errno;
} }
grub_file_read (file, source, load_size); grub_file_read (file, source, load_size);
if (grub_errno) if (grub_errno)
{ {
grub_free (buffer); grub_free (mld.buffer);
return grub_errno; return grub_errno;
} }
@ -283,17 +344,41 @@ grub_multiboot_load (grub_file_t file, const char *filename)
} }
else else
{ {
err = grub_multiboot_load_elf (file, filename, buffer); mld.file = file;
mld.filename = filename;
mld.avoid_efi_boot_services = keep_bs;
err = grub_multiboot_load_elf (&mld);
if (err) if (err)
{ {
grub_free (buffer); grub_free (mld.buffer);
return err; return err;
} }
} }
if (entry_specified) load_base_addr = mld.load_base_addr;
if (keep_bs && efi_entry_specified)
grub_multiboot_payload_eip = efi_entry;
else if (entry_specified)
grub_multiboot_payload_eip = entry; grub_multiboot_payload_eip = entry;
if (mld.relocatable)
{
/*
* Both branches are mathematically equivalent. However, it looks
* that real life (C?) is more complicated. I am trying to avoid
* wrap around here if mld.load_base_addr < mld.link_base_addr.
* If you look at C operator precedence then everything should work.
* However, I am not 100% sure that a given compiler will not
* optimize/break this stuff. So, maybe we should use signed
* 64-bit int here.
*/
if (mld.load_base_addr >= mld.link_base_addr)
grub_multiboot_payload_eip += mld.load_base_addr - mld.link_base_addr;
else
grub_multiboot_payload_eip -= mld.link_base_addr - mld.load_base_addr;
}
if (fbtag) if (fbtag)
err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER, err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
accepted_consoles, accepted_consoles,
@ -381,7 +466,7 @@ static grub_size_t
grub_multiboot_get_mbi_size (void) grub_multiboot_get_mbi_size (void)
{ {
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
if (!efi_mmap_size) if (!keep_bs && !efi_mmap_size)
find_efi_mmap_size (); find_efi_mmap_size ();
#endif #endif
return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag) return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag)
@ -400,13 +485,16 @@ grub_multiboot_get_mbi_size (void)
+ grub_get_multiboot_mmap_count () + grub_get_multiboot_mmap_count ()
* sizeof (struct multiboot_mmap_entry)), MULTIBOOT_TAG_ALIGN) * sizeof (struct multiboot_mmap_entry)), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN) + ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_efi32), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_efi64), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_old_acpi) + ALIGN_UP (sizeof (struct multiboot_tag_old_acpi)
+ sizeof (struct grub_acpi_rsdp_v10), MULTIBOOT_TAG_ALIGN) + sizeof (struct grub_acpi_rsdp_v10), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_load_base_addr), MULTIBOOT_TAG_ALIGN)
+ acpiv2_size () + acpiv2_size ()
+ net_size () + net_size ()
#ifdef GRUB_MACHINE_EFI #ifdef GRUB_MACHINE_EFI
+ ALIGN_UP (sizeof (struct multiboot_tag_efi32), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_efi32_ih), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_efi64), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_efi64_ih), MULTIBOOT_TAG_ALIGN)
+ ALIGN_UP (sizeof (struct multiboot_tag_efi_mmap) + ALIGN_UP (sizeof (struct multiboot_tag_efi_mmap)
+ efi_mmap_size, MULTIBOOT_TAG_ALIGN) + efi_mmap_size, MULTIBOOT_TAG_ALIGN)
#endif #endif
@ -424,6 +512,7 @@ grub_fill_multiboot_mmap_iter (grub_uint64_t addr, grub_uint64_t size,
(*mmap_entry)->addr = addr; (*mmap_entry)->addr = addr;
(*mmap_entry)->len = size; (*mmap_entry)->len = size;
(*mmap_entry)->type = type; (*mmap_entry)->type = type;
(*mmap_entry)->zero = 0;
(*mmap_entry)++; (*mmap_entry)++;
return 0; return 0;
@ -681,6 +770,15 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
% sizeof (grub_properly_aligned_t) == 0); % sizeof (grub_properly_aligned_t) == 0);
ptrorig += (2 * sizeof (grub_uint32_t)) / sizeof (grub_properly_aligned_t); ptrorig += (2 * sizeof (grub_uint32_t)) / sizeof (grub_properly_aligned_t);
{
struct multiboot_tag_load_base_addr *tag = (struct multiboot_tag_load_base_addr *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR;
tag->size = sizeof (struct multiboot_tag_load_base_addr);
tag->load_base_addr = load_base_addr;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
{ {
struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig; struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_CMDLINE; tag->type = MULTIBOOT_TAG_TYPE_CMDLINE;
@ -743,12 +841,13 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
} }
} }
{ if (!keep_bs)
struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig; {
grub_fill_multiboot_mmap (tag); struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) grub_fill_multiboot_mmap (tag);
/ sizeof (grub_properly_aligned_t); ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
} / sizeof (grub_properly_aligned_t);
}
{ {
struct multiboot_tag_elf_sections *tag struct multiboot_tag_elf_sections *tag
@ -764,18 +863,19 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
/ sizeof (grub_properly_aligned_t); / sizeof (grub_properly_aligned_t);
} }
{ if (!keep_bs)
struct multiboot_tag_basic_meminfo *tag {
= (struct multiboot_tag_basic_meminfo *) ptrorig; struct multiboot_tag_basic_meminfo *tag
tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO; = (struct multiboot_tag_basic_meminfo *) ptrorig;
tag->size = sizeof (struct multiboot_tag_basic_meminfo); tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
tag->size = sizeof (struct multiboot_tag_basic_meminfo);
/* Convert from bytes to kilobytes. */ /* Convert from bytes to kilobytes. */
tag->mem_lower = grub_mmap_get_lower () / 1024; tag->mem_lower = grub_mmap_get_lower () / 1024;
tag->mem_upper = grub_mmap_get_upper () / 1024; tag->mem_upper = grub_mmap_get_upper () / 1024;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t); / sizeof (grub_properly_aligned_t);
} }
{ {
struct grub_net_network_level_interface *net; struct grub_net_network_level_interface *net;
@ -874,36 +974,57 @@ grub_multiboot_make_mbi (grub_uint32_t *target)
grub_efi_uintn_t efi_desc_size; grub_efi_uintn_t efi_desc_size;
grub_efi_uint32_t efi_desc_version; grub_efi_uint32_t efi_desc_version;
tag->type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
tag->size = sizeof (*tag) + efi_mmap_size;
if (!keep_bs) if (!keep_bs)
err = grub_efi_finish_boot_services (&efi_mmap_size, tag->efi_mmap, NULL,
&efi_desc_size, &efi_desc_version);
else
{ {
if (grub_efi_get_memory_map (&efi_mmap_size, (void *) tag->efi_mmap, tag->type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
NULL, tag->size = sizeof (*tag) + efi_mmap_size;
&efi_desc_size, &efi_desc_version) <= 0)
err = grub_error (GRUB_ERR_IO, "couldn't retrieve memory map");
}
if (err)
return err;
tag->descr_size = efi_desc_size;
tag->descr_vers = efi_desc_version;
tag->size = sizeof (*tag) + efi_mmap_size;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) err = grub_efi_finish_boot_services (&efi_mmap_size, tag->efi_mmap, NULL,
/ sizeof (grub_properly_aligned_t); &efi_desc_size, &efi_desc_version);
if (err)
return err;
tag->descr_size = efi_desc_size;
tag->descr_vers = efi_desc_version;
tag->size = sizeof (*tag) + efi_mmap_size;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
} }
if (keep_bs) if (keep_bs)
{ {
struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig; {
tag->type = MULTIBOOT_TAG_TYPE_EFI_BS; struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
tag->size = sizeof (struct multiboot_tag); tag->type = MULTIBOOT_TAG_TYPE_EFI_BS;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) tag->size = sizeof (struct multiboot_tag);
/ sizeof (grub_properly_aligned_t); ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
#ifdef __i386__
{
struct multiboot_tag_efi32_ih *tag = (struct multiboot_tag_efi32_ih *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_EFI32_IH;
tag->size = sizeof (struct multiboot_tag_efi32_ih);
tag->pointer = (grub_addr_t) grub_efi_image_handle;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
#endif
#ifdef __x86_64__
{
struct multiboot_tag_efi64_ih *tag = (struct multiboot_tag_efi64_ih *) ptrorig;
tag->type = MULTIBOOT_TAG_TYPE_EFI64_IH;
tag->size = sizeof (struct multiboot_tag_efi64_ih);
tag->pointer = (grub_addr_t) grub_efi_image_handle;
ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
/ sizeof (grub_properly_aligned_t);
}
#endif
} }
#endif #endif

View file

@ -140,17 +140,17 @@ grub_linux_boot (void)
grub_dprintf ("loader", "Jumping to Linux...\n"); grub_dprintf ("loader", "Jumping to Linux...\n");
/* Boot the kernel. */ /* Boot the kernel. */
asm volatile ("sethi %hi(grub_ieee1275_entry_fn), %o1\n" asm volatile ("ldx %0, %%o4\n"
"ldx [%o1 + %lo(grub_ieee1275_entry_fn)], %o4\n" "ldx %1, %%o6\n"
"sethi %hi(grub_ieee1275_original_stack), %o1\n" "ldx %2, %%o5\n"
"ldx [%o1 + %lo(grub_ieee1275_original_stack)], %o6\n" "mov %%g0, %%o0\n"
"sethi %hi(linux_addr), %o1\n" "mov %%g0, %%o2\n"
"ldx [%o1 + %lo(linux_addr)], %o5\n" "mov %%g0, %%o3\n"
"mov %g0, %o0\n" "jmp %%o5\n"
"mov %g0, %o2\n" "mov %%g0, %%o1\n": :
"mov %g0, %o3\n" "m"(grub_ieee1275_entry_fn),
"jmp %o5\n" "m"(grub_ieee1275_original_stack),
"mov %g0, %o1\n"); "m"(linux_addr));
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
@ -203,20 +203,20 @@ alloc_phys_choose (grub_uint64_t addr, grub_uint64_t len,
if (addr + ctx->size >= end) if (addr + ctx->size >= end)
return 0; return 0;
if (addr >= grub_phys_start && addr < grub_phys_end) /* OBP available region contains grub. Start at grub_phys_end. */
{ /* grub_phys_start does not start at the beginning of the memory region */
addr = ALIGN_UP (grub_phys_end, FOUR_MB); if ((grub_phys_start >= addr && grub_phys_end < end) ||
if (addr + ctx->size >= end) (addr > grub_phys_start && addr < grub_phys_end))
return 0;
}
if ((addr + ctx->size) >= grub_phys_start
&& (addr + ctx->size) < grub_phys_end)
{ {
addr = ALIGN_UP (grub_phys_end, FOUR_MB); addr = ALIGN_UP (grub_phys_end, FOUR_MB);
if (addr + ctx->size >= end) if (addr + ctx->size >= end)
return 0; return 0;
} }
grub_dprintf("loader",
"addr = 0x%lx grub_phys_start = 0x%lx grub_phys_end = 0x%lx\n",
addr, grub_phys_start, grub_phys_end);
if (loaded) if (loaded)
{ {
grub_addr_t linux_end = ALIGN_UP (linux_paddr + linux_size, FOUR_MB); grub_addr_t linux_end = ALIGN_UP (linux_paddr + linux_size, FOUR_MB);

View file

@ -100,7 +100,7 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
grub_memcpy (&gw.ipv4, ptr, sizeof (gw.ipv4)); grub_memcpy (&gw.ipv4, ptr, sizeof (gw.ipv4));
rname = grub_xasprintf ("%s:default", name); rname = grub_xasprintf ("%s:default", name);
if (rname) if (rname)
grub_net_add_route_gw (rname, target, gw); grub_net_add_route_gw (rname, target, gw, NULL);
grub_free (rname); grub_free (rname);
} }
break; break;
@ -160,6 +160,7 @@ grub_net_configure_by_dhcp_ack (const char *name,
grub_net_link_level_address_t hwaddr; grub_net_link_level_address_t hwaddr;
struct grub_net_network_level_interface *inter; struct grub_net_network_level_interface *inter;
int mask = -1; int mask = -1;
char server_ip[sizeof ("xxx.xxx.xxx.xxx")];
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
addr.ipv4 = bp->your_ip; addr.ipv4 = bp->your_ip;
@ -175,6 +176,9 @@ grub_net_configure_by_dhcp_ack (const char *name,
hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags); inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags);
if (!inter)
return 0;
#if 0 #if 0
/* This is likely based on misunderstanding. gateway_ip refers to /* This is likely based on misunderstanding. gateway_ip refers to
address of BOOTP relay and should not be used after BOOTP transaction address of BOOTP relay and should not be used after BOOTP transaction
@ -207,15 +211,22 @@ grub_net_configure_by_dhcp_ack (const char *name,
if (size > OFFSET_OF (boot_file, bp)) if (size > OFFSET_OF (boot_file, bp))
grub_env_set_net_property (name, "boot_file", bp->boot_file, grub_env_set_net_property (name, "boot_file", bp->boot_file,
sizeof (bp->boot_file)); sizeof (bp->boot_file));
if (bp->server_ip)
{
grub_snprintf (server_ip, sizeof (server_ip), "%d.%d.%d.%d",
((grub_uint8_t *) &bp->server_ip)[0],
((grub_uint8_t *) &bp->server_ip)[1],
((grub_uint8_t *) &bp->server_ip)[2],
((grub_uint8_t *) &bp->server_ip)[3]);
grub_env_set_net_property (name, "next_server", server_ip, sizeof (server_ip));
grub_print_error ();
}
if (is_def) if (is_def)
grub_net_default_server = 0; grub_net_default_server = 0;
if (is_def && !grub_net_default_server && bp->server_ip) if (is_def && !grub_net_default_server && bp->server_ip)
{ {
grub_net_default_server = grub_xasprintf ("%d.%d.%d.%d", grub_net_default_server = grub_strdup (server_ip);
((grub_uint8_t *) &bp->server_ip)[0],
((grub_uint8_t *) &bp->server_ip)[1],
((grub_uint8_t *) &bp->server_ip)[2],
((grub_uint8_t *) &bp->server_ip)[3]);
grub_print_error (); grub_print_error ();
} }
@ -227,11 +238,7 @@ grub_net_configure_by_dhcp_ack (const char *name,
if (device && !*device && bp->server_ip) if (device && !*device && bp->server_ip)
{ {
*device = grub_xasprintf ("tftp,%d.%d.%d.%d", *device = grub_xasprintf ("tftp,%s", server_ip);
((grub_uint8_t *) &bp->server_ip)[0],
((grub_uint8_t *) &bp->server_ip)[1],
((grub_uint8_t *) &bp->server_ip)[2],
((grub_uint8_t *) &bp->server_ip)[3]);
grub_print_error (); grub_print_error ();
} }
if (size > OFFSET_OF (server_name, bp) if (size > OFFSET_OF (server_name, bp)
@ -386,6 +393,7 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
if (grub_strcmp (args[3], "string") == 0) if (grub_strcmp (args[3], "string") == 0)
{ {
grub_err_t err = GRUB_ERR_NONE;
char *val = grub_malloc (taglength + 1); char *val = grub_malloc (taglength + 1);
if (!val) if (!val)
return grub_errno; return grub_errno;
@ -394,8 +402,9 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
if (args[0][0] == '-' && args[0][1] == 0) if (args[0][0] == '-' && args[0][1] == 0)
grub_printf ("%s\n", val); grub_printf ("%s\n", val);
else else
return grub_env_set (args[0], val); err = grub_env_set (args[0], val);
return GRUB_ERR_NONE; grub_free (val);
return err;
} }
if (grub_strcmp (args[3], "number") == 0) if (grub_strcmp (args[3], "number") == 0)
@ -417,6 +426,7 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
if (grub_strcmp (args[3], "hex") == 0) if (grub_strcmp (args[3], "hex") == 0)
{ {
grub_err_t err = GRUB_ERR_NONE;
char *val = grub_malloc (2 * taglength + 1); char *val = grub_malloc (2 * taglength + 1);
int i; int i;
if (!val) if (!val)
@ -430,8 +440,9 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
if (args[0][0] == '-' && args[0][1] == 0) if (args[0][0] == '-' && args[0][1] == 0)
grub_printf ("%s\n", val); grub_printf ("%s\n", val);
else else
return grub_env_set (args[0], val); err = grub_env_set (args[0], val);
return GRUB_ERR_NONE; grub_free (val);
return err;
} }
return grub_error (GRUB_ERR_BAD_ARGUMENT, return grub_error (GRUB_ERR_BAD_ARGUMENT,

View file

@ -238,6 +238,15 @@ recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)),
char *redirect_save = NULL; char *redirect_save = NULL;
grub_uint32_t ttl_all = ~0U; grub_uint32_t ttl_all = ~0U;
/* Code apparently assumed that only one packet is received as response.
We may get multiple responses due to network condition, so check here
and quit early. */
if (*data->addresses)
{
grub_netbuff_free (nb);
return GRUB_ERR_NONE;
}
head = (struct dns_header *) nb->data; head = (struct dns_header *) nb->data;
ptr = (grub_uint8_t *) (head + 1); ptr = (grub_uint8_t *) (head + 1);
if (ptr >= nb->tail) if (ptr >= nb->tail)

View file

@ -85,24 +85,30 @@ get_card_packet (struct grub_net_card *dev)
grub_uint64_t start_time; grub_uint64_t start_time;
struct grub_net_buff *nb; struct grub_net_buff *nb;
nb = grub_netbuff_alloc (dev->mtu + 64 + 2); start_time = grub_get_time_ms ();
do
rc = grub_ieee1275_read (data->handle, dev->rcvbuf, dev->rcvbufsize, &actual);
while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
if (actual <= 0)
return NULL;
nb = grub_netbuff_alloc (actual + 2);
if (!nb) if (!nb)
return NULL; return NULL;
/* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible
by 4. So that IP header is aligned on 4 bytes. */ by 4. So that IP header is aligned on 4 bytes. */
grub_netbuff_reserve (nb, 2); grub_netbuff_reserve (nb, 2);
start_time = grub_get_time_ms (); grub_memcpy (nb->data, dev->rcvbuf, actual);
do
rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu + 64, &actual); if (grub_netbuff_put (nb, actual))
while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200));
if (actual > 0)
{ {
grub_netbuff_put (nb, actual); grub_netbuff_free (nb);
return nb; return NULL;
} }
grub_netbuff_free (nb);
return NULL; return nb;
} }
static struct grub_net_card_driver ofdriver = static struct grub_net_card_driver ofdriver =
@ -151,7 +157,7 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
grub_net_network_level_address_t client_addr, gateway_addr, subnet_mask; grub_net_network_level_address_t client_addr, gateway_addr, subnet_mask;
grub_net_link_level_address_t hw_addr; grub_net_link_level_address_t hw_addr;
grub_net_interface_flags_t flags = 0; grub_net_interface_flags_t flags = 0;
struct grub_net_network_level_interface *inter; struct grub_net_network_level_interface *inter = NULL;
hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
@ -221,7 +227,7 @@ grub_ieee1275_parse_bootpath (const char *devpath, char *bootpath,
target.ipv4.masksize = 0; target.ipv4.masksize = 0;
rname = grub_xasprintf ("%s:default", ((*card)->name)); rname = grub_xasprintf ("%s:default", ((*card)->name));
if (rname) if (rname)
grub_net_add_route_gw (rname, target, gateway_addr); grub_net_add_route_gw (rname, target, gateway_addr, inter);
else else
return grub_errno; return grub_errno;
} }
@ -294,6 +300,91 @@ grub_ieee1275_net_config_real (const char *devpath, char **device, char **path,
} }
} }
/* Allocate memory with alloc-mem */
static void *
grub_ieee1275_alloc_mem (grub_size_t len)
{
struct alloc_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t method;
grub_ieee1275_cell_t len;
grub_ieee1275_cell_t catch;
grub_ieee1275_cell_t result;
}
args;
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
{
grub_error (GRUB_ERR_UNKNOWN_COMMAND, N_("interpret is not supported"));
return NULL;
}
INIT_IEEE1275_COMMON (&args.common, "interpret", 2, 2);
args.len = len;
args.method = (grub_ieee1275_cell_t) "alloc-mem";
if (IEEE1275_CALL_ENTRY_FN (&args) == -1 || args.catch)
{
grub_error (GRUB_ERR_INVALID_COMMAND, N_("alloc-mem failed"));
return NULL;
}
else
return (void *)args.result;
}
/* Free memory allocated by alloc-mem */
static grub_err_t
grub_ieee1275_free_mem (void *addr, grub_size_t len)
{
struct free_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t method;
grub_ieee1275_cell_t len;
grub_ieee1275_cell_t addr;
grub_ieee1275_cell_t catch;
}
args;
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET))
{
grub_error (GRUB_ERR_UNKNOWN_COMMAND, N_("interpret is not supported"));
return grub_errno;
}
INIT_IEEE1275_COMMON (&args.common, "interpret", 3, 1);
args.addr = (grub_ieee1275_cell_t)addr;
args.len = len;
args.method = (grub_ieee1275_cell_t) "free-mem";
if (IEEE1275_CALL_ENTRY_FN(&args) == -1 || args.catch)
{
grub_error (GRUB_ERR_INVALID_COMMAND, N_("free-mem failed"));
return grub_errno;
}
return GRUB_ERR_NONE;
}
static void *
ofnet_alloc_netbuf (grub_size_t len)
{
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN))
return grub_ieee1275_alloc_mem (len);
else
return grub_zalloc (len);
}
static void
ofnet_free_netbuf (void *addr, grub_size_t len)
{
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN))
grub_ieee1275_free_mem (addr, len);
else
grub_free (addr);
}
static int static int
search_net_devices (struct grub_ieee1275_devalias *alias) search_net_devices (struct grub_ieee1275_devalias *alias)
{ {
@ -409,40 +500,19 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
card->default_address = lla; card->default_address = lla;
card->txbufsize = ALIGN_UP (card->mtu, 64) + 256; card->txbufsize = ALIGN_UP (card->mtu, 64) + 256;
card->rcvbufsize = ALIGN_UP (card->mtu, 64) + 256;
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN)) card->txbuf = ofnet_alloc_netbuf (card->txbufsize);
{
struct alloc_args
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t method;
grub_ieee1275_cell_t len;
grub_ieee1275_cell_t catch;
grub_ieee1275_cell_t result;
}
args;
INIT_IEEE1275_COMMON (&args.common, "interpret", 2, 2);
args.len = card->txbufsize;
args.method = (grub_ieee1275_cell_t) "alloc-mem";
if (IEEE1275_CALL_ENTRY_FN (&args) == -1
|| args.catch)
{
card->txbuf = 0;
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
}
else
card->txbuf = (void *) args.result;
}
else
card->txbuf = grub_zalloc (card->txbufsize);
if (!card->txbuf) if (!card->txbuf)
goto fail_netbuf;
card->rcvbuf = ofnet_alloc_netbuf (card->rcvbufsize);
if (!card->rcvbuf)
{ {
grub_free (ofdata->path); grub_error_push ();
grub_free (ofdata); ofnet_free_netbuf (card->txbuf, card->txbufsize);
grub_free (card); grub_error_pop ();
grub_print_error (); goto fail_netbuf;
return 0;
} }
card->driver = NULL; card->driver = NULL;
card->data = ofdata; card->data = ofdata;
@ -455,6 +525,13 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
card->driver = &ofdriver; card->driver = &ofdriver;
grub_net_card_register (card); grub_net_card_register (card);
return 0; return 0;
fail_netbuf:
grub_free (ofdata->path);
grub_free (ofdata);
grub_free (card);
grub_print_error ();
return 0;
} }
static void static void

View file

@ -381,9 +381,8 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
ptr = nb->tail; ptr = nb->tail;
grub_snprintf ((char *) ptr, grub_snprintf ((char *) ptr,
sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX-" sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX-"
"\r\n"
"\r\n"), "\r\n"),
"Range: bytes=%" PRIuGRUB_UINT64_T "-\r\n\r\n", "Range: bytes=%" PRIuGRUB_UINT64_T "-\r\n",
offset); offset);
grub_netbuff_put (nb, grub_strlen ((char *) ptr)); grub_netbuff_put (nb, grub_strlen ((char *) ptr));
} }
@ -454,6 +453,7 @@ http_seek (struct grub_file *file, grub_off_t off)
} }
file->device->net->stall = 0; file->device->net->stall = 0;
file->device->net->eof = 0;
file->device->net->offset = off; file->device->net->offset = off;
data = grub_zalloc (sizeof (*data)); data = grub_zalloc (sizeof (*data));

View file

@ -115,6 +115,7 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
grub_uint8_t ttl) grub_uint8_t ttl)
{ {
struct icmp_header *icmph; struct icmp_header *icmph;
struct grub_net_network_level_interface *orig_inf = inf;
grub_err_t err; grub_err_t err;
grub_uint16_t checksum; grub_uint16_t checksum;
@ -345,14 +346,31 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
{ {
grub_uint8_t *ptr; grub_uint8_t *ptr;
struct option_header *ohdr; struct option_header *ohdr;
struct router_adv *radv;
struct grub_net_network_level_interface *route_inf = NULL;
int default_route = 0;
if (icmph->code) if (icmph->code)
break; break;
radv = (struct router_adv *)nb->data;
err = grub_netbuff_pull (nb, sizeof (struct router_adv)); err = grub_netbuff_pull (nb, sizeof (struct router_adv));
if (err) if (err)
{ {
grub_netbuff_free (nb); grub_netbuff_free (nb);
return err; return err;
} }
if (grub_be_to_cpu16 (radv->router_lifetime) > 0)
{
struct grub_net_route *route;
FOR_NET_ROUTES (route)
{
if (!grub_memcmp (&route->gw, source, sizeof (route->gw)))
break;
}
if (route == NULL)
default_route = 1;
}
for (ptr = (grub_uint8_t *) nb->data; ptr < nb->tail; for (ptr = (grub_uint8_t *) nb->data; ptr < nb->tail;
ptr += ohdr->len * 8) ptr += ohdr->len * 8)
{ {
@ -413,7 +431,11 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
/* Update lease time if needed here once we have /* Update lease time if needed here once we have
lease times. */ lease times. */
if (inf) if (inf)
continue; {
if (!route_inf)
route_inf = inf;
continue;
}
grub_dprintf ("net", "creating slaac\n"); grub_dprintf ("net", "creating slaac\n");
@ -429,12 +451,51 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
inf = grub_net_add_addr (name, inf = grub_net_add_addr (name,
card, &addr, card, &addr,
&slaac->address, 0); &slaac->address, 0);
if (!route_inf)
route_inf = inf;
grub_net_add_route (name, netaddr, inf); grub_net_add_route (name, netaddr, inf);
grub_free (name); grub_free (name);
} }
} }
} }
} }
if (default_route)
{
char *name;
grub_net_network_level_netaddress_t netaddr;
name = grub_xasprintf ("%s:ra:default6", card->name);
if (!name)
{
grub_errno = GRUB_ERR_NONE;
goto next;
}
/* Default routes take alll of the traffic, so make the mask huge */
netaddr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
netaddr.ipv6.masksize = 0;
netaddr.ipv6.base[0] = 0;
netaddr.ipv6.base[1] = 0;
/* May not have gotten slaac info, find a global address on this
card. */
if (route_inf == NULL)
{
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
{
if (inf->card == card && inf != orig_inf
&& inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
&& grub_net_hwaddr_cmp(&inf->hwaddress,
&orig_inf->hwaddress) == 0)
{
route_inf = inf;
break;
}
}
}
if (route_inf != NULL)
grub_net_add_route_gw (name, netaddr, *source, route_inf);
grub_free (name);
}
next:
if (ptr != nb->tail) if (ptr != nb->tail)
break; break;
} }

View file

@ -363,7 +363,9 @@ static void
free_old_fragments (void) free_old_fragments (void)
{ {
struct reassemble *rsm, **prev; struct reassemble *rsm, **prev;
grub_uint64_t limit_time = grub_get_time_ms () - 90000; grub_uint64_t limit_time = grub_get_time_ms ();
limit_time = (limit_time > 90000) ? limit_time - 90000 : 0;
for (prev = &reassembles, rsm = *prev; rsm; rsm = *prev) for (prev = &reassembles, rsm = *prev; rsm; rsm = *prev)
if (rsm->last_time < limit_time) if (rsm->last_time < limit_time)

View file

@ -37,21 +37,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
char *grub_net_default_server; char *grub_net_default_server;
struct grub_net_route
{
struct grub_net_route *next;
struct grub_net_route **prev;
grub_net_network_level_netaddress_t target;
char *name;
struct grub_net_network_level_protocol *prot;
int is_gateway;
union
{
struct grub_net_network_level_interface *interface;
grub_net_network_level_address_t gw;
};
};
struct grub_net_route *grub_net_routes = NULL; struct grub_net_route *grub_net_routes = NULL;
struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL; struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL;
struct grub_net_card *grub_net_cards = NULL; struct grub_net_card *grub_net_cards = NULL;
@ -299,12 +284,6 @@ grub_net_ipv6_get_link_local (struct grub_net_card *card,
char *ptr; char *ptr;
grub_net_network_level_address_t addr; grub_net_network_level_address_t addr;
name = grub_malloc (grub_strlen (card->name)
+ GRUB_NET_MAX_STR_HWADDR_LEN
+ sizeof (":link"));
if (!name)
return NULL;
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
addr.ipv6[0] = grub_cpu_to_be64_compile_time (0xfe80ULL << 48); addr.ipv6[0] = grub_cpu_to_be64_compile_time (0xfe80ULL << 48);
addr.ipv6[1] = grub_net_ipv6_get_id (hwaddr); addr.ipv6[1] = grub_net_ipv6_get_id (hwaddr);
@ -317,6 +296,12 @@ grub_net_ipv6_get_link_local (struct grub_net_card *card,
return inf; return inf;
} }
name = grub_malloc (grub_strlen (card->name)
+ GRUB_NET_MAX_STR_HWADDR_LEN
+ sizeof (":link"));
if (!name)
return NULL;
ptr = grub_stpcpy (name, card->name); ptr = grub_stpcpy (name, card->name);
if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0) if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0)
{ {
@ -410,14 +395,6 @@ grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)),
return err; return err;
} }
static inline void
grub_net_route_register (struct grub_net_route *route)
{
grub_list_push (GRUB_AS_LIST_P (&grub_net_routes),
GRUB_AS_LIST (route));
}
#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next)
static int static int
parse_ip (const char *val, grub_uint32_t *ip, const char **rest) parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
@ -524,6 +501,8 @@ match_net (const grub_net_network_level_netaddress_t *net,
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
{ {
grub_uint64_t mask[2]; grub_uint64_t mask[2];
if (net->ipv6.masksize == 0)
return 1;
if (net->ipv6.masksize <= 64) if (net->ipv6.masksize <= 64)
{ {
mask[0] = 0xffffffffffffffffULL << (64 - net->ipv6.masksize); mask[0] = 0xffffffffffffffffULL << (64 - net->ipv6.masksize);
@ -687,7 +666,14 @@ grub_net_route_address (grub_net_network_level_address_t addr,
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
if (depth == 0) if (depth == 0)
*gateway = bestroute->gw; {
*gateway = bestroute->gw;
if (bestroute->interface != NULL)
{
*interf = bestroute->interface;
return GRUB_ERR_NONE;
}
}
curtarget = bestroute->gw; curtarget = bestroute->gw;
} }
@ -1109,7 +1095,8 @@ grub_net_add_route (const char *name,
grub_err_t grub_err_t
grub_net_add_route_gw (const char *name, grub_net_add_route_gw (const char *name,
grub_net_network_level_netaddress_t target, grub_net_network_level_netaddress_t target,
grub_net_network_level_address_t gw) grub_net_network_level_address_t gw,
struct grub_net_network_level_interface *inter)
{ {
struct grub_net_route *route; struct grub_net_route *route;
@ -1127,6 +1114,7 @@ grub_net_add_route_gw (const char *name,
route->target = target; route->target = target;
route->is_gateway = 1; route->is_gateway = 1;
route->gw = gw; route->gw = gw;
route->interface = inter;
grub_net_route_register (route); grub_net_route_register (route);
@ -1152,7 +1140,7 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)),
err = grub_net_resolve_address (args[3], &gw); err = grub_net_resolve_address (args[3], &gw);
if (err) if (err)
return err; return err;
return grub_net_add_route_gw (args[0], target, gw); return grub_net_add_route_gw (args[0], target, gw, NULL);
} }
else else
{ {
@ -1333,7 +1321,8 @@ grub_net_open_real (const char *name)
if (!ret) if (!ret)
return NULL; return NULL;
ret->protocol = proto; ret->protocol = proto;
if (server) ret->server = grub_strdup (server);
if (!ret->server)
{ {
ret->server = grub_strdup (server); ret->server = grub_strdup (server);
ret->port = port; ret->port = port;
@ -1343,11 +1332,7 @@ grub_net_open_real (const char *name)
return NULL; return NULL;
} }
} }
else
ret->server = NULL;
ret->fs = &grub_net_fs; ret->fs = &grub_net_fs;
ret->offset = 0;
ret->eof = 0;
return ret; return ret;
} }
} }
@ -1377,6 +1362,15 @@ grub_net_open_real (const char *name)
continue; continue;
} }
if (grub_strncmp (prefdev, "pxe", sizeof ("pxe") - 1) == 0 &&
(!prefdev[sizeof ("pxe") - 1] || (prefdev[sizeof("pxe") - 1] == ':')))
{
grub_free (prefdev);
prefdev = grub_strdup ("tftp");
if (!prefdev)
continue;
}
comma = grub_strchr (prefdev, ','); comma = grub_strchr (prefdev, ',');
if (comma) if (comma)
*comma = '\0'; *comma = '\0';
@ -1440,7 +1434,10 @@ grub_net_fs_open (struct grub_file *file_out, const char *name)
file->device->net->packs.last = NULL; file->device->net->packs.last = NULL;
file->device->net->name = grub_strdup (name); file->device->net->name = grub_strdup (name);
if (!file->device->net->name) if (!file->device->net->name)
return grub_errno; {
grub_free (file);
return grub_errno;
}
err = file->device->net->protocol->open (file, name); err = file->device->net->protocol->open (file, name);
if (err) if (err)
@ -1700,6 +1697,7 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset)
file->device->net->packs.last = NULL; file->device->net->packs.last = NULL;
file->device->net->offset = 0; file->device->net->offset = 0;
file->device->net->eof = 0; file->device->net->eof = 0;
file->device->net->stall = 0;
err = file->device->net->protocol->open (file, file->device->net->name); err = file->device->net->protocol->open (file, file->device->net->name);
if (err) if (err)
return err; return err;

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