Merge pull request #19 from marineam/merge

Merge upstream GRUB changes
This commit is contained in:
Michael Marineau 2015-12-22 17:30:18 -08:00
commit fcefc6bbc5
96 changed files with 6482 additions and 523 deletions

10
NEWS
View file

@ -59,6 +59,7 @@ New in 2.02:
* Command for inspecting coreboot tables (`lscoreboot').
* New target default_payload.elf.
* Increased maximal core size.
* Prefer pmtimer for TSC calibration.
* New/improved platform support:
* New `efifwsetup' and `lsefi' commands on EFI platforms.
@ -88,6 +89,13 @@ New in 2.02:
* Support *-emu on Windows.
* New platform `none' which builds only user level utilities. This is now
default if target CPU is not supported.
* Support for booting little-endian Linux kernel on powerpc.
* Support network boot with Oracle sun4v vnet devices.
* Added SAS disks to the IEEE 1275 Open Firmware device list.
* Try multiple methods for TSC (timestamp counter) calibration - PIT, pmtimer,
EFI Stall. If everything fails, use hardcoded frequency 800MHz.
* Support Hyper-V Gen2 platforms which lack PIT for TSC calibration.
* Map UEFI Persistent Memory to E820 persistent memory.
* Security:
* Add optional facility to enforce that all files read by the core image
@ -150,6 +158,8 @@ New in 2.02:
directly. This removes requirement for target-specific runtime on build
system.
* emu libusb support removed (was broken and unmaintained).
* powerpc64le compile support.
* Use fixed timestamp when generating GRUB image for reproducible builds.
* Revision control moved to git.

2
README
View file

@ -12,8 +12,6 @@ The URL is <http://www.gnu.org/software/grub/grub.html>.
More extensive documentation is available in the Info manual,
accessible using 'info grub' after building and installing GRUB 2.
Please look at the GRUB Wiki <http://grub.enbug.org> for testing
procedures.
There are a number of important user-visible differences from the
first version of GRUB, now known as GRUB Legacy. For a summary, please

View file

@ -5,6 +5,10 @@
.code16
jmp far
.org 4
.space 300
jmp nearer
.org 6
.space 100
nearer:
.space 200
far:
.byte 0

View file

@ -4,8 +4,8 @@
.set mips3
sync
ld $t2, 0($t6)
ld $t2, 0($t1)
a:
addiu $t7, $s0, (b - a)
addiu $t1, $s0, (b - a)
b: nop

View file

@ -23,14 +23,14 @@ fi
if [ -d grub-core/lib/libgcrypt-grub/mpi/generic ]; then
rm -rf grub-core/lib/libgcrypt-grub/mpi/generic
fi
ln -s ../../../grub-core/lib/libgcrypt-grub/src/g10lib.h include/grub/gcrypt/g10lib.h
cp grub-core/lib/libgcrypt-grub/src/g10lib.h include/grub/gcrypt/g10lib.h
cp -R grub-core/lib/libgcrypt/mpi/generic grub-core/lib/libgcrypt-grub/mpi/generic
for x in mpi-asm-defs.h mpih-add1.c mpih-sub1.c mpih-mul1.c mpih-mul2.c mpih-mul3.c mpih-lshift.c mpih-rshift.c; do
if [ -h grub-core/lib/libgcrypt-grub/mpi/"$x" ] || [ -f grub-core/lib/libgcrypt-grub/mpi/"$x" ]; then
rm grub-core/lib/libgcrypt-grub/mpi/"$x"
fi
ln -s generic/"$x" grub-core/lib/libgcrypt-grub/mpi/"$x"
cp grub-core/lib/libgcrypt-grub/mpi/generic/"$x" grub-core/lib/libgcrypt-grub/mpi/"$x"
done
echo "Generating Automake input..."

View file

@ -21,9 +21,6 @@ if COND_powerpc_ieee1275
CFLAGS_PLATFORM += -mcpu=powerpc
endif
#FIXME: discover and check XEN headers
CPPFLAGS_XEN = -I/usr/include
# Other options
CPPFLAGS_DEFAULT = -DGRUB_FILE=\"$(subst $(srcdir)/,,$<)\"

View file

@ -37,7 +37,6 @@ EXTRA_DIST += grub-core/lib/libgcrypt
EXTRA_DIST += grub-core/lib/libgcrypt-grub/mpi/generic
EXTRA_DIST += $(shell find $(top_srcdir)/include -name '*.h')
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/lib -name '*.h')
EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/gnulib -name '*.h')
EXTRA_DIST += grub-core/efiemu/runtime/config.h
EXTRA_DIST += grub-core/lib/LzmaDec.c

View file

@ -315,7 +315,7 @@ AC_PROG_LN_S
if test "x$LEX" = "x:"; then
AC_MSG_ERROR([flex is not found])
else
version=`$LEX --version | $AWK '{ split($NF,x,"."); print x[[1]]*10000+x[[2]]*100+x[[3]]; }'`
version=`$LEX --version | $AWK '{ split($2,x,"."); print x[[1]]*10000+x[[2]]*100+x[[3]]; }'`
if test -n "$version" -a "$version" -ge 20535; then
:
else
@ -562,12 +562,12 @@ AC_COMPILE_IFELSE(
]])],
[grub_cv_cc_target_clang=no], [grub_cv_cc_target_clang=yes])])
if test x$target_cpu = xpowerpc; then
if test x$target_cpu = xpowerpc -o x$target_cpu = xmips; then
AC_CACHE_CHECK([for options to get big-endian compilation], grub_cv_target_cc_big_endian, [
grub_cv_target_cc_big_endian=no
for cand in "-target powerpc -Wl,-EB" "-target powerpc" \
"-target powerpc-linux-gnu -Wl,-EB" "-target powerpc-linux-gnu" \
"-mbig-endian"; do
for cand in "-target $target_cpu -Wl,-EB" "-target $target_cpu" \
"-target $target_cpu-linux-gnu -Wl,-EB" "-target $target_cpu-linux-gnu" \
"-EB" "-mbig-endian"; do
if test x"$grub_cv_target_cc_big_endian" != xno ; then
break
fi
@ -577,6 +577,8 @@ if test x$target_cpu = xpowerpc; then
#error still little endian
#endif
asm (".globl start; start:");
asm (".globl _start; _start:");
asm (".globl __start; __start:");
void __main (void);
void __main (void) {}
int main (void);
@ -595,6 +597,75 @@ int main (void);
TARGET_CPPFLAGS="$TARGET_CPPFLAGS $skip_linkflags"
TARGET_CCASFLAGS="$TARGET_CCASFLAGS $skip_linkflags"
TARGET_LDFLAGS="$TARGET_LDFLAGS $grub_cv_target_cc_big_endian"
elif test x$target_cpu = xmipsel; then
AC_CACHE_CHECK([for options to get little-endian compilation], grub_cv_target_cc_little_endian, [
grub_cv_target_cc_little_endian=no
for cand in "-target $target_cpu -Wl,-EL" "-target $target_cpu" \
"-target $target_cpu-linux-gnu -Wl,-EL" "-target $target_cpu-linux-gnu" \
"-EL"; do
if test x"$grub_cv_target_cc_little_endian" != xno ; then
break
fi
CFLAGS="$TARGET_CFLAGS $cand -Werror"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__ORDER_BIG_ENDIAN__ == __BYTE_ORDER__)
#error still big endian
#endif
asm (".globl start; start:");
asm (".globl _start; _start:");
asm (".globl __start; __start:");
void __main (void);
void __main (void) {}
int main (void);
]], [[]])],
[grub_cv_target_cc_little_endian="$cand"], [])
done
])
if test x"$grub_cv_target_cc_little_endian" = xno ; then
AC_MSG_ERROR([could not force little-endian])
fi
skip_linkflags="$(echo "$grub_cv_target_cc_little_endian"|sed 's@-Wl,-EL@@')"
TARGET_CFLAGS="$TARGET_CFLAGS $skip_linkflags"
TARGET_CPPFLAGS="$TARGET_CPPFLAGS $skip_linkflags"
TARGET_CCASFLAGS="$TARGET_CCASFLAGS $skip_linkflags"
TARGET_LDFLAGS="$TARGET_LDFLAGS $grub_cv_target_cc_little_endian"
fi
# GRUB code is N32-compliant but it's experimental and we would prefer to
# avoid having too much variety when it doesn't result in any real improvement.
# Moreover N64 isn't supported.
if test "x$target_cpu" = xmips || test "x$target_cpu" = xmipsel ; then
AC_CACHE_CHECK([for options to force MIPS o32 ABI], grub_cv_target_cc_mips_o32_abi, [
grub_cv_target_cc_mips_o32_abi=no
for arg in "" "-mabi=32" "-target $target_cpu -mabi=32" ; do
if test x"$grub_cv_target_cc_mips_o32_abi" != xno ; then
break
fi
CFLAGS="$TARGET_CFLAGS $arg -Werror"
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#if !defined(_ABIO32) || !defined(_MIPS_SIM) || (_MIPS_SIM != _ABIO32)
#error not o32 ABI
#endif
asm (".globl start; start:");
asm (".globl _start; _start:");
asm (".globl __start; __start:");
void __main (void);
void __main (void) {}
int main (void);
]], [[]])],
[grub_cv_target_cc_mips_o32_abi="$arg"], [])
done
])
if test x"$grub_cv_target_cc_mips_o32_abi" = xno ; then
AC_MSG_ERROR([could not force MIPS o32 ABI])
fi
TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_mips_o32_abi"
TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_target_cc_mips_o32_abi"
fi
AC_CACHE_CHECK([for options to compile assembly], [grub_cv_cc_target_asm_compile], [
@ -712,7 +783,7 @@ fi
if ( test "x$target_cpu" = xi386 || test "x$target_cpu" = xx86_64 ) && test "x$platform" != xemu; then
# Some toolchains enable these features by default, but they need
# registers that aren't set up properly in GRUB.
TARGET_CFLAGS="$TARGET_CFLAGS -mno-mmx -mno-sse -mno-sse2 -mno-3dnow"
TARGET_CFLAGS="$TARGET_CFLAGS -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow"
fi
# GRUB doesn't use float or doubles at all. Yet some toolchains may decide

View file

@ -3038,6 +3038,8 @@ These variables have special meaning to GRUB.
* cmdpath::
* color_highlight::
* color_normal::
* config_directory::
* config_file::
* debug::
* default::
* fallback::
@ -3180,6 +3182,22 @@ matching colors of first half.
to support whole rgb24 palette but currently there is no compelling reason
to go beyond the current 16 colors.
@node config_directory
@subsection config_directory
This variable is automatically set by GRUB to the directory part of
current configuration file name (@pxref{config_file}).
@node config_file
@subsection config_file
This variable is automatically set by GRUB to the name of configuration file that is being
processed by commands @command{configfile} (@pxref{configfile}) or @command{normal}
(@pxref{normal}). It is restored to the previous value when command completes.
@node debug
@subsection debug
@ -3839,6 +3857,11 @@ you forget a command, you can run the command @command{help}
@comment * vbeinfo:: List available video modes
* verify_detached:: Verify detached digital signature
* videoinfo:: List available video modes
@comment * xen_*:: Xen boot commands
* xen_hypervisor:: Load xen hypervisor binary
* xen_linux:: Load dom0 kernel for xen hypervisor
* xen_initrd:: Load dom0 initrd for dom0 kernel
* xen_xsm:: Load xen security module for xen hypervisor
@end menu
@ -5102,6 +5125,39 @@ successfully. If validation fails, it is set to a non-zero value.
List available video modes. If resolution is given, show only matching modes.
@end deffn
@node xen_hypervisor
@subsection xen_hypervisor
@deffn Command xen_hypervisor file [arguments] @dots{}
Load a Xen hypervisor binary from @var{file}. The rest of the line is passed
verbatim as the @dfn{kernel command-line}. Any other binaries must be
reloaded after using this command.
@end deffn
@node xen_linux
@subsection xen_linux
@deffn Command xen_linux file [arguments]
Load a dom0 kernel image for xen hypervisor at the booting process of xen.
The rest of the line is passed verbatim as the module command line.
@end deffn
@node xen_initrd
@subsection xen_initrd
@deffn Command xen_initrd file
Load a initrd image for dom0 kernel at the booting process of xen.
@end deffn
@node xen_xsm
@subsection xen_xsm
@deffn Command xen_xsm file
Load a xen security module for xen hypervisor at the booting process of xen.
See @uref{http://wiki.xen.org/wiki/XSM} for more detail.
@end deffn
@node Networking commands
@section The list of networking commands
@ -5613,6 +5669,16 @@ BadRAM is the ability to mark some of the RAM as ``bad''. Note: due to protocol
limitations mips-loongson (with Linux protocol)
and mips-qemu_mips can use only memory up to first hole.
Bootlocation is ability of GRUB to automatically detect where it boots from.
``disk'' means the detection is limited to detecting the disk with partition
being discovered on install time. ``partition'' means that disk and partiton
can be automatically discovered. ``file'' means that boot image file name as
well as disk and partition can be discovered. For consistency default install ignores
partition and relies solely on disk detection. If no bootlocation discovery is available
or boot and grub-root disks are different, UUID is used instead. On ARC if no device
to install to is specified, UUID is used instead as well.
@multitable @columnfractions .20 .20 .20 .20 .20
@item @tab BIOS @tab Coreboot @tab Multiboot @tab Qemu
@item video @tab yes @tab yes @tab yes @tab yes
@ -5629,6 +5695,7 @@ and mips-qemu_mips can use only memory up to first hole.
@item badram @tab yes @tab yes @tab yes @tab yes
@item compression @tab always @tab pointless @tab no @tab no
@item exit @tab yes @tab no @tab no @tab no
@item bootlocation @tab disk @tab no @tab no @tab no
@end multitable
@multitable @columnfractions .20 .20 .20 .20 .20
@ -5647,6 +5714,7 @@ and mips-qemu_mips can use only memory up to first hole.
@item badram @tab yes @tab yes @tab no @tab yes
@item compression @tab no @tab no @tab no @tab no
@item exit @tab yes @tab yes @tab yes @tab yes
@item bootlocation @tab file @tab file @tab file, ignored @tab file
@end multitable
@multitable @columnfractions .20 .20 .20 .20 .20
@ -5665,24 +5733,26 @@ and mips-qemu_mips can use only memory up to first hole.
@item badram @tab yes (*) @tab no @tab no @tab no
@item compression @tab configurable @tab no @tab no @tab configurable
@item exit @tab no @tab yes @tab yes @tab yes
@item bootlocation @tab no @tab partition @tab file @tab file (*)
@end multitable
@multitable @columnfractions .20 .20 .20 .20 .20
@item @tab MIPS qemu @tab emu
@item video @tab no @tab yes
@item console charset @tab CP437 @tab Unicode (*)
@item network @tab no @tab yes
@item ATA/AHCI @tab yes @tab no
@item AT keyboard @tab yes @tab no
@item Speaker @tab no @tab no
@item USB @tab N/A @tab yes
@item chainloader @tab yes @tab no
@item cpuid @tab no @tab no
@item hints @tab guess @tab no
@item PCI @tab no @tab no
@item badram @tab yes (*) @tab no
@item compression @tab configurable @tab no
@item exit @tab no @tab yes
@item @tab MIPS qemu @tab emu @tab xen
@item video @tab no @tab yes @tab no
@item console charset @tab CP437 @tab Unicode (*) @tab ASCII
@item network @tab no @tab yes @tab no
@item ATA/AHCI @tab yes @tab no @tab no
@item AT keyboard @tab yes @tab no @tab no
@item Speaker @tab no @tab no @tab no
@item USB @tab N/A @tab yes @tab no
@item chainloader @tab yes @tab no @tab yes
@item cpuid @tab no @tab no @tab yes
@item hints @tab guess @tab no @tab no
@item PCI @tab no @tab no @tab no
@item badram @tab yes (*) @tab no @tab no
@item compression @tab configurable @tab no @tab no
@item exit @tab no @tab yes @tab no
@item bootlocation @tab no @tab file @tab no
@end multitable
@node Platform-specific operations

View file

@ -101,6 +101,7 @@ if COND_i386_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
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/acpi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h
endif
@ -112,10 +113,12 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
endif
if COND_i386_multiboot
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
endif
if COND_i386_qemu
@ -154,11 +157,13 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
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/pci.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
endif
if COND_ia64_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
endif
if COND_mips
@ -233,11 +238,13 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/efi/loader.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
endif
if COND_arm64_efi
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h
endif
if COND_emu

View file

@ -59,9 +59,6 @@ kernel = {
ia64_efi_ldflags = '-Wl,-r,-d';
ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
x86_64_xen_cppflags = '$(CPPFLAGS_XEN)';
i386_xen_cppflags = '$(CPPFLAGS_XEN)';
arm_efi_ldflags = '-Wl,-r,-d';
arm_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version';
@ -174,8 +171,20 @@ kernel = {
efi = kern/efi/init.c;
efi = kern/efi/mm.c;
efi = term/efi/console.c;
efi = kern/acpi.c;
efi = kern/efi/acpi.c;
i386_coreboot = kern/i386/pc/acpi.c;
i386_multiboot = kern/i386/pc/acpi.c;
i386_coreboot = kern/acpi.c;
i386_multiboot = kern/acpi.c;
x86 = kern/i386/tsc.c;
x86 = kern/i386/tsc_pit.c;
i386_efi = kern/i386/efi/tsc.c;
x86_64_efi = kern/i386/efi/tsc.c;
i386_efi = kern/i386/tsc_pmtimer.c;
i386_coreboot = kern/i386/tsc_pmtimer.c;
x86_64_efi = kern/i386/tsc_pmtimer.c;
i386_efi = kern/i386/efi/init.c;
i386_efi = bus/pci.c;
@ -187,6 +196,7 @@ kernel = {
x86_64_efi = bus/pci.c;
xen = kern/i386/tsc.c;
xen = kern/i386/xen/tsc.c;
x86_64_xen = kern/x86_64/xen/hypercall.S;
i386_xen = kern/i386/xen/hypercall.S;
xen = kern/xen/init.c;
@ -604,7 +614,6 @@ module = {
module = {
name = lsxen;
common = commands/xen/lsxen.c;
cppflags = '$(CPPFLAGS_XEN)';
enable = xen;
};
@ -669,10 +678,8 @@ module = {
name = acpi;
common = commands/acpi.c;
efi = commands/efi/acpi.c;
i386_pc = commands/i386/pc/acpi.c;
i386_coreboot = commands/i386/pc/acpi.c;
i386_multiboot = commands/i386/pc/acpi.c;
i386_pc = kern/acpi.c;
i386_pc = kern/i386/pc/acpi.c;
enable = efi;
enable = i386_pc;
@ -847,7 +854,6 @@ module = {
i386_coreboot = lib/i386/halt.c;
i386_qemu = lib/i386/halt.c;
xen = lib/xen/halt.c;
xen_cppflags = '$(CPPFLAGS_XEN)';
efi = lib/efi/halt.c;
ieee1275 = lib/ieee1275/halt.c;
emu = lib/emu/halt.c;
@ -868,7 +874,6 @@ module = {
mips_loongson = lib/mips/loongson/reboot.c;
mips_qemu_mips = lib/mips/qemu_mips/reboot.c;
xen = lib/xen/reboot.c;
xen_cppflags = '$(CPPFLAGS_XEN)';
uboot = lib/uboot/reboot.c;
common = commands/reboot.c;
};
@ -1485,7 +1490,6 @@ module = {
module = {
name = gfxmenu;
common = gfxmenu/gfxmenu.c;
common = gfxmenu/model.c;
common = gfxmenu/view.c;
common = gfxmenu/font.c;
common = gfxmenu/icon_manager.c;
@ -1564,7 +1568,6 @@ module = {
i386_xen = lib/i386/xen/relocator.S;
x86_64_xen = lib/x86_64/xen/relocator.S;
xen = lib/i386/relocator_common_c.c;
xen_cppflags = '$(CPPFLAGS_XEN)';
extra_dist = lib/i386/relocator_common.S;
extra_dist = kern/powerpc/cache_flush.S;
@ -1585,7 +1588,6 @@ module = {
sparc64_ieee1275 = lib/ieee1275/cmos.c;
powerpc_ieee1275 = lib/ieee1275/cmos.c;
xen = lib/xen/datetime.c;
xen_cppflags = '$(CPPFLAGS_XEN)';
mips_arc = lib/arc/datetime.c;
enable = noemu;
@ -1684,11 +1686,17 @@ module = {
enable = x86;
};
module = {
name = xen_boot;
common = lib/cmdline.c;
arm64 = loader/arm64/xen_boot.c;
enable = arm64;
};
module = {
name = linux;
x86 = loader/i386/linux.c;
xen = loader/i386/xen.c;
xen_cppflags = '$(CPPFLAGS_XEN)';
i386_pc = lib/i386/pc/vesa_modes_table.c;
mips = loader/mips/linux.c;
powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c;
@ -1696,12 +1704,18 @@ module = {
ia64_efi = loader/ia64/efi/linux.c;
arm = loader/arm/linux.c;
arm64 = loader/arm64/linux.c;
fdt = lib/fdt.c;
common = loader/linux.c;
common = lib/cmdline.c;
enable = noemu;
};
module = {
name = fdt;
arm64 = loader/arm64/fdt.c;
common = lib/fdt.c;
enable = fdt;
};
module = {
name = xnu;
x86 = loader/xnu_resume.c;

View file

@ -22,6 +22,7 @@
#include <grub/machine/memory.h>
#include <grub/machine/kernel.h>
#include <grub/offsets.h>
#include <grub/mips/asm.h>
#define BASE_ADDR 8
@ -118,32 +119,32 @@ parsestr:
move $v0, $zero
move $t3, $t1
3:
lb $t4, 0($t2)
lb $t5, 0($t3)
lb GRUB_ASM_T4, 0($t2)
lb GRUB_ASM_T5, 0($t3)
addiu $t2, $t2, 1
addiu $t3, $t3, 1
beq $t5, $zero, 1f
beq GRUB_ASM_T5, $zero, 1f
nop
beq $t5, $t4, 3b
beq GRUB_ASM_T5, GRUB_ASM_T4, 3b
nop
bne $t4, $zero, 1f
bne GRUB_ASM_T4, $zero, 1f
nop
addiu $t3, $t3, 0xffff
digcont:
lb $t5, 0($t3)
lb GRUB_ASM_T5, 0($t3)
/* Substract '0' from digit. */
addiu $t5, $t5, 0xffd0
bltz $t5, 1f
addiu GRUB_ASM_T5, GRUB_ASM_T5, 0xffd0
bltz GRUB_ASM_T5, 1f
nop
addiu $t4, $t5, 0xfff7
bgtz $t4, 1f
addiu GRUB_ASM_T4, GRUB_ASM_T5, 0xfff7
bgtz GRUB_ASM_T4, 1f
nop
/* Multiply $v0 by 10 with bitshifts. */
sll $v0, $v0, 1
sll $t4, $v0, 2
addu $v0, $v0, $t4
addu $v0, $v0, $t5
sll GRUB_ASM_T4, $v0, 2
addu $v0, $v0, GRUB_ASM_T4
addu $v0, $v0, GRUB_ASM_T5
addiu $t3, $t3, 1
b digcont
nop
@ -182,10 +183,10 @@ argdone:
b argdone
addiu $a1, $a1, 4
do_check:
lb $t4, 0($t7)
beq $t4, $zero, 1f
lb GRUB_ASM_T4, 0($t7)
beq GRUB_ASM_T4, $zero, 1f
lb $t3, 0($t6)
bne $t3, $t4, 2f
bne $t3, GRUB_ASM_T4, 2f
addiu $t6, $t6, 1
b do_check
addiu $t7, $t7, 1
@ -222,8 +223,8 @@ cmdlinedone:
1:
beq $t1, $t3, 2f
lb $t4, 0($t2)
sb $t4, 0($t1)
lb GRUB_ASM_T4, 0($t2)
sb GRUB_ASM_T4, 0($t1)
addiu $t1, $t1, 1
b 1b
addiu $t2, $t2, 1

View file

@ -61,18 +61,6 @@ static const struct grub_arg_option options[] = {
{0, 0, 0, 0, 0, 0}
};
/* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */
grub_uint8_t
grub_byte_checksum (void *base, grub_size_t size)
{
grub_uint8_t *ptr;
grub_uint8_t ret = 0;
for (ptr = (grub_uint8_t *) base; ptr < ((grub_uint8_t *) base) + size;
ptr++)
ret += *ptr;
return ret;
}
/* rev1 is 1 if ACPIv1 is to be generated, 0 otherwise.
rev2 contains the revision of ACPIv2+ to generate or 0 if none. */
static int rev1, rev2;

View file

@ -51,7 +51,7 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
grub_printf
("Type Physical start - end #Pages "
" Size Attributes\n");
" Size Attributes\n");
memory_map_end = ADD_MEMORY_DESCRIPTOR (memory_map, map_size);
for (desc = memory_map;
desc < memory_map_end;
@ -74,7 +74,8 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
"ACPI-nvs",
"MMIO ",
"IO-ports",
"PAL-code"
"PAL-code",
"persist ",
};
if (desc->type < ARRAY_SIZE (types_str))
grub_printf ("%s ", types_str[desc->type]);
@ -87,21 +88,29 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
desc->physical_start + (desc->num_pages << 12) - 1,
desc->num_pages);
size = desc->num_pages;
size <<= (12 - 10);
if (size < 1024)
grub_printf (" %4" PRIuGRUB_UINT64_T "KB", size);
size = desc->num_pages << 12; /* 4 KiB page size */
/*
* Since size is a multiple of 4 KiB, no need to handle units
* of just Bytes (which would use a mask of 0x3ff).
*
* 14 characters would support the largest possible number of 4 KiB
* pages that are not a multiple of larger units (e.g., MiB):
* 17592186044415 (0xffffff_fffff000), but that uses a lot of
* whitespace for a rare case. 6 characters usually suffices;
* columns will be off if not, but this is preferable to rounding.
*/
if (size & 0xfffff)
grub_printf (" %6" PRIuGRUB_UINT64_T "KiB", size >> 10);
else if (size & 0x3fffffff)
grub_printf (" %6" PRIuGRUB_UINT64_T "MiB", size >> 20);
else if (size & 0xffffffffff)
grub_printf (" %6" PRIuGRUB_UINT64_T "GiB", size >> 30);
else if (size & 0x3ffffffffffff)
grub_printf (" %6" PRIuGRUB_UINT64_T "TiB", size >> 40);
else if (size & 0xfffffffffffffff)
grub_printf (" %6" PRIuGRUB_UINT64_T "PiB", size >> 50);
else
{
size /= 1024;
if (size < 1024)
grub_printf (" %4" PRIuGRUB_UINT64_T "MB", size);
else
{
size /= 1024;
grub_printf (" %4" PRIuGRUB_UINT64_T "GB", size);
}
}
grub_printf (" %6" PRIuGRUB_UINT64_T "EiB", size >> 60);
attr = desc->attribute;
if (attr & GRUB_EFI_MEMORY_RUNTIME)
@ -122,6 +131,12 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)),
grub_printf (" RP");
if (attr & GRUB_EFI_MEMORY_XP)
grub_printf (" XP");
if (attr & GRUB_EFI_MEMORY_NV)
grub_printf (" NV");
if (attr & GRUB_EFI_MEMORY_MORE_RELIABLE)
grub_printf (" MR");
if (attr & GRUB_EFI_MEMORY_RO)
grub_printf (" RO");
grub_printf ("\n");
}

View file

@ -37,10 +37,20 @@ static const struct guid_mapping guid_mappings[] =
{
{ GRUB_EFI_ACPI_20_TABLE_GUID, "ACPI-2.0"},
{ GRUB_EFI_ACPI_TABLE_GUID, "ACPI-1.0"},
{ GRUB_EFI_CRC32_GUIDED_SECTION_EXTRACTION_GUID,
"CRC32 GUIDED SECTION EXTRACTION"},
{ GRUB_EFI_DEBUG_IMAGE_INFO_TABLE_GUID, "DEBUG IMAGE INFO"},
{ GRUB_EFI_DXE_SERVICES_TABLE_GUID, "DXE SERVICES"},
{ GRUB_EFI_HCDP_TABLE_GUID, "HCDP"},
{ GRUB_EFI_HOB_LIST_GUID, "HOB LIST"},
{ GRUB_EFI_LZMA_CUSTOM_DECOMPRESS_GUID, "LZMA CUSTOM DECOMPRESS"},
{ GRUB_EFI_MEMORY_TYPE_INFORMATION_GUID, "MEMORY TYPE INFO"},
{ GRUB_EFI_MPS_TABLE_GUID, "MPS"},
{ GRUB_EFI_SAL_TABLE_GUID, "SAL"},
{ GRUB_EFI_SMBIOS_TABLE_GUID, "SMBIOS"},
{ GRUB_EFI_MPS_TABLE_GUID, "MPS"},
{ GRUB_EFI_HCDP_TABLE_GUID, "HCDP"}
{ GRUB_EFI_SYSTEM_RESOURCE_TABLE_GUID, "SYSTEM RESOURCE TABLE"},
{ GRUB_EFI_TIANO_CUSTOM_DECOMPRESS_GUID, "TIANO CUSTOM DECOMPRESS"},
{ GRUB_EFI_TSC_FREQUENCY_GUID, "TSC FREQUENCY"},
};
static grub_err_t

View file

@ -37,6 +37,8 @@ static const char *names[] =
is required to save accross hibernations. */
[GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage RAM"),
[GRUB_MEMORY_BADRAM] = N_("faulty RAM (BadRAM)"),
[GRUB_MEMORY_PERSISTENT] = N_("persistent RAM"),
[GRUB_MEMORY_PERSISTENT_LEGACY] = N_("persistent RAM (legacy)"),
[GRUB_MEMORY_COREBOOT_TABLES] = N_("RAM holding coreboot tables"),
[GRUB_MEMORY_CODE] = N_("RAM holding firmware code")
};

View file

@ -25,6 +25,7 @@
#include <grub/fs.h>
#include <grub/file.h>
#include <grub/procfs.h>
#include <grub/partition.h>
#ifdef GRUB_UTIL
#include <grub/emu/hostdisk.h>
@ -718,6 +719,7 @@ grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name,
newdev->id = last_cryptodisk_id++;
newdev->source_id = source->id;
newdev->source_dev_id = source->dev->id;
newdev->partition_start = grub_partition_get_start (source->partition);
newdev->next = cryptodisk_list;
cryptodisk_list = newdev;
@ -740,7 +742,9 @@ grub_cryptodisk_get_by_source_disk (grub_disk_t disk)
grub_cryptodisk_t dev;
for (dev = cryptodisk_list; dev != NULL; dev = dev->next)
if (dev->source_id == disk->id && dev->source_dev_id == disk->dev->id)
return dev;
if ((disk->partition && grub_partition_get_start (disk->partition) == dev->partition_start) ||
(!disk->partition && dev->partition_start == 0))
return dev;
return NULL;
}
@ -761,6 +765,7 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name,
newdev->cheat_fd = GRUB_UTIL_FD_INVALID;
newdev->source_id = source->id;
newdev->source_dev_id = source->dev->id;
newdev->partition_start = grub_partition_get_start (source->partition);
newdev->id = last_cryptodisk_id++;
newdev->next = cryptodisk_list;
cryptodisk_list = newdev;
@ -964,33 +969,43 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
grub_disk_t disk;
grub_cryptodisk_t dev;
char *diskname;
char *disklast;
char *disklast = NULL;
grub_size_t len;
search_uuid = NULL;
check_boot = state[2].set;
diskname = args[0];
if (diskname[0] == '(' && *(disklast = &diskname[grub_strlen (diskname) - 1]) == ')')
len = grub_strlen (diskname);
if (len && diskname[0] == '(' && diskname[len - 1] == ')')
{
disklast = &diskname[len - 1];
*disklast = '\0';
disk = grub_disk_open (diskname + 1);
*disklast = ')';
diskname++;
}
else
disk = grub_disk_open (diskname);
disk = grub_disk_open (diskname);
if (!disk)
return grub_errno;
{
if (disklast)
*disklast = ')';
return grub_errno;
}
dev = grub_cryptodisk_get_by_source_disk (disk);
if (dev)
{
grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id);
grub_disk_close (disk);
if (disklast)
*disklast = ')';
return GRUB_ERR_NONE;
}
err = grub_cryptodisk_scan_device_real (args[0], disk);
err = grub_cryptodisk_scan_device_real (diskname, disk);
grub_disk_close (disk);
if (disklast)
*disklast = ')';
return err;
}

View file

@ -228,6 +228,9 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
if (grub_ieee1275_open (alias->path, &ihandle))
return;
/* This method doesn't need memory allocation for the table. Open
firmware takes care of all memory management and the result table
stays in memory and is never freed. */
INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3);
args.method = (grub_ieee1275_cell_t) "vscsi-report-luns";
args.ihandle = ihandle;
@ -260,6 +263,82 @@ dev_iterate (const struct grub_ieee1275_devalias *alias)
grub_free (buf);
return;
}
else if (grub_strcmp (alias->type, "sas_ioa") == 0)
{
/* The method returns the number of disks and a table where
* each ID is 64-bit long. Example of sas paths:
* /pci@80000002000001f/pci1014,034A@0/sas/disk@c05db70800
* /pci@80000002000001f/pci1014,034A@0/sas/disk@a05db70800
* /pci@80000002000001f/pci1014,034A@0/sas/disk@805db70800 */
struct sas_children
{
struct grub_ieee1275_common_hdr common;
grub_ieee1275_cell_t method;
grub_ieee1275_cell_t ihandle;
grub_ieee1275_cell_t max;
grub_ieee1275_cell_t table;
grub_ieee1275_cell_t catch_result;
grub_ieee1275_cell_t nentries;
}
args;
char *buf, *bufptr;
unsigned i;
grub_uint64_t *table;
grub_uint16_t table_size;
grub_ieee1275_ihandle_t ihandle;
buf = grub_malloc (grub_strlen (alias->path) +
sizeof ("/disk@7766554433221100"));
if (!buf)
return;
bufptr = grub_stpcpy (buf, alias->path);
/* Power machines documentation specify 672 as maximum SAS disks in
one system. Using a slightly larger value to be safe. */
table_size = 768;
table = grub_malloc (table_size * sizeof (grub_uint64_t));
if (!table)
{
grub_free (buf);
return;
}
if (grub_ieee1275_open (alias->path, &ihandle))
{
grub_free (buf);
grub_free (table);
return;
}
INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 2);
args.method = (grub_ieee1275_cell_t) "get-sas-children";
args.ihandle = ihandle;
args.max = table_size;
args.table = (grub_ieee1275_cell_t) table;
args.catch_result = 0;
args.nentries = 0;
if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
{
grub_ieee1275_close (ihandle);
grub_free (table);
grub_free (buf);
return;
}
for (i = 0; i < args.nentries; i++)
{
grub_snprintf (bufptr, sizeof ("/disk@7766554433221100"),
"/disk@%" PRIxGRUB_UINT64_T, table[i]);
dev_iterate_real (buf, buf);
}
grub_ieee1275_close (ihandle);
grub_free (table);
grub_free (buf);
}
if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS)
&& grub_strcmp (alias->type, "block") == 0)
@ -422,16 +501,20 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
op = ofdisk_hash_find (devpath);
if (!op)
op = ofdisk_hash_add (devpath, NULL);
else
grub_free (devpath);
if (!op)
return grub_errno;
{
grub_free (devpath);
return grub_errno;
}
disk->id = (unsigned long) op;
disk->data = op->open_path;
err = grub_ofdisk_get_block_size (devpath, &block_size, op);
if (err)
return err;
{
grub_free (devpath);
return err;
}
if (block_size != 0)
{
for (disk->log_sector_size = 0;
@ -442,6 +525,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
disk->log_sector_size = 9;
}
grub_free (devpath);
return 0;
}

View file

@ -963,7 +963,7 @@ grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors,
if (embed_type != GRUB_EMBED_PCBIOS)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"LDM curently supports only PC-BIOS embedding");
"LDM currently supports only PC-BIOS embedding");
if (disk->partition)
return grub_error (GRUB_ERR_BUG, "disk isn't LDM");
pv = grub_diskfilter_get_pv_from_disk (disk, &vg);

View file

@ -344,8 +344,16 @@ init_cbfsdisk (void)
ptr = *(grub_uint32_t *) 0xfffffffc;
head = (struct cbfs_header *) (grub_addr_t) ptr;
grub_dprintf ("cbfs", "head=%p\n", head);
if (!validate_head (head))
/* coreboot current supports only ROMs <= 16 MiB. Bigger ROMs will
have problems as RCBA is 18 MiB below end of 32-bit typically,
so either memory map would have to be rearranged or we'd need to support
reading ROMs through controller directly.
*/
if (ptr < 0xff000000
|| 0xffffffff - ptr < (grub_uint32_t) sizeof (*head) + 0xf
|| !validate_head (head))
return;
cbfsdisk_size = ALIGN_UP (grub_be_to_cpu32 (head->romsize),

View file

@ -394,7 +394,7 @@ grub_ufs_read_file (struct grub_ufs_data *data,
return -1;
}
else
grub_memset (buf, UFS_BLKSZ (sblock) - skipfirst, 0);
grub_memset (buf, 0, blockend);
buf += UFS_BLKSZ (sblock) - skipfirst;
}

View file

@ -29,7 +29,7 @@ BEGIN {
}
}
else {
printf "error: %u: unrecognized input format\n", NR;
printf "error: %u: unrecognized input format\n", NR >"/dev/stderr";
error++;
}
}
@ -39,6 +39,8 @@ END {
if (error >= 1)
exit 1;
total_depcount = 0
for (mod in modtab) {
# Remove duplications.
split(modtab[mod], depmods, " ");
@ -52,14 +54,42 @@ END {
uniqmods[depmod] = 1;
}
modlist = ""
depcount[mod] = 0
for (depmod in uniqmods) {
modlist = modlist " " depmod;
inverse_dependencies[depmod] = inverse_dependencies[depmod] " " mod
depcount[mod]++
total_depcount++
}
if (mod == "all_video") {
continue;
}
printf "%s:%s\n", mod, modlist;
}
# Check that we have no dependency circles
while (total_depcount != 0) {
something_done = 0
for (mod in depcount) {
if (depcount[mod] == 0) {
delete depcount[mod]
split(inverse_dependencies[mod], inv_depmods, " ");
for (ctr in inv_depmods) {
depcount[inv_depmods[ctr]]--
total_depcount--
}
delete inverse_dependencies[mod]
something_done = 1
}
}
if (something_done == 0) {
for (mod in depcount) {
circle = circle " " mod
}
printf "error: modules %s form a dependency circle\n", circle >"/dev/stderr";
exit 1
}
}
modlist = ""
while (getline <"video.lst") {
modlist = modlist " " $1;

View file

@ -255,7 +255,7 @@ theme_set_string (grub_gfxmenu_view_t view,
{
unsigned int tmp;
int err = theme_get_unsigned_int_from_proportional (value,
view->screen.width,
view->screen.height,
&tmp);
if (err != GRUB_ERR_NONE)
return err;
@ -275,7 +275,7 @@ theme_set_string (grub_gfxmenu_view_t view,
{
unsigned int tmp;
int err = theme_get_unsigned_int_from_proportional (value,
view->screen.width,
view->screen.height,
&tmp);
if (err != GRUB_ERR_NONE)
return err;

34
grub-core/kern/acpi.c Normal file
View file

@ -0,0 +1,34 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2012 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/time.h>
#include <grub/misc.h>
#include <grub/acpi.h>
/* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */
grub_uint8_t
grub_byte_checksum (void *base, grub_size_t size)
{
grub_uint8_t *ptr;
grub_uint8_t ret = 0;
for (ptr = (grub_uint8_t *) base; ptr < ((grub_uint8_t *) base) + size;
ptr++)
ret += *ptr;
return ret;
}

View file

@ -28,6 +28,25 @@
GRUB_MOD_LICENSE ("GPLv3+");
#pragma GCC diagnostic ignored "-Wcast-align"
#if defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275)
#define GRUB_ELF_ENABLE_BI_ENDIAN 1
#else
#define GRUB_ELF_ENABLE_BI_ENDIAN 0
#endif
#if defined(GRUB_CPU_WORDS_BIGENDIAN)
#define GRUB_ELF_NATIVE_ENDIANNESS ELFDATA2MSB
#define GRUB_ELF_OPPOSITE_ENDIANNESS ELFDATA2LSB
#else
#define GRUB_ELF_NATIVE_ENDIANNESS ELFDATA2LSB
#define GRUB_ELF_OPPOSITE_ENDIANNESS ELFDATA2MSB
#endif
static int grub_elf32_check_endianess_and_bswap_ehdr (grub_elf_t elf);
static int grub_elf64_check_endianess_and_bswap_ehdr (grub_elf_t elf);
/* Check if EHDR is a valid ELF header. */
static grub_err_t
grub_elf_check_header (grub_elf_t elf)
@ -38,8 +57,25 @@ grub_elf_check_header (grub_elf_t elf)
|| e->e_ident[EI_MAG1] != ELFMAG1
|| e->e_ident[EI_MAG2] != ELFMAG2
|| e->e_ident[EI_MAG3] != ELFMAG3
|| e->e_ident[EI_VERSION] != EV_CURRENT
|| e->e_version != EV_CURRENT)
|| e->e_ident[EI_VERSION] != EV_CURRENT)
return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic"));
if (grub_elf_is_elf32 (elf))
{
if (!grub_elf32_check_endianess_and_bswap_ehdr (elf)) {
return grub_error (GRUB_ERR_BAD_OS, "invalid ELF endianness magic");
}
}
else if (grub_elf_is_elf64 (elf))
{
if (!grub_elf64_check_endianess_and_bswap_ehdr (elf)) {
return grub_error (GRUB_ERR_BAD_OS, "invalid ELF endianness magic");
}
}
else
return grub_error (GRUB_ERR_BAD_OS, "unknown ELF class");
if (e->e_version != EV_CURRENT)
return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic"));
return GRUB_ERR_NONE;
@ -117,6 +153,9 @@ grub_elf_open (const char *name)
}
#define grub_swap_bytes_halfXX grub_swap_bytes16
#define grub_swap_bytes_wordXX grub_swap_bytes32
/* 32-bit */
#define ehdrXX ehdr32
#define ELFCLASSXX ELFCLASS32
@ -127,7 +166,12 @@ grub_elf_open (const char *name)
#define grub_elf_is_elfXX grub_elf_is_elf32
#define grub_elfXX_load_phdrs grub_elf32_load_phdrs
#define ElfXX_Phdr Elf32_Phdr
#define ElfXX_Ehdr Elf32_Ehdr
#define grub_uintXX_t grub_uint32_t
#define grub_swap_bytes_addrXX grub_swap_bytes32
#define grub_swap_bytes_offXX grub_swap_bytes32
#define grub_swap_bytes_XwordXX grub_swap_bytes32
#define grub_elfXX_check_endianess_and_bswap_ehdr grub_elf32_check_endianess_and_bswap_ehdr
#include "elfXX.c"
@ -140,7 +184,12 @@ grub_elf_open (const char *name)
#undef grub_elf_is_elfXX
#undef grub_elfXX_load_phdrs
#undef ElfXX_Phdr
#undef ElfXX_Ehdr
#undef grub_uintXX_t
#undef grub_swap_bytes_addrXX
#undef grub_swap_bytes_offXX
#undef grub_swap_bytes_XwordXX
#undef grub_elfXX_check_endianess_and_bswap_ehdr
/* 64-bit */
@ -153,6 +202,11 @@ grub_elf_open (const char *name)
#define grub_elf_is_elfXX grub_elf_is_elf64
#define grub_elfXX_load_phdrs grub_elf64_load_phdrs
#define ElfXX_Phdr Elf64_Phdr
#define ElfXX_Ehdr Elf64_Ehdr
#define grub_uintXX_t grub_uint64_t
#define grub_swap_bytes_addrXX grub_swap_bytes64
#define grub_swap_bytes_offXX grub_swap_bytes64
#define grub_swap_bytes_XwordXX grub_swap_bytes64
#define grub_elfXX_check_endianess_and_bswap_ehdr grub_elf64_check_endianess_and_bswap_ehdr
#include "elfXX.c"

View file

@ -31,6 +31,25 @@ grub_elfXX_load_phdrs (grub_elf_t elf)
return grub_errno;
}
#if GRUB_ELF_ENABLE_BI_ENDIAN
if (elf->ehdr.ehdrXX.e_ident[EI_DATA] == GRUB_ELF_OPPOSITE_ENDIANNESS)
{
ElfXX_Phdr *phdr;
for (phdr = elf->phdrs; (char *) phdr < (char *) elf->phdrs + phdrs_size;
phdr = (ElfXX_Phdr *) ((char *) phdr + elf->ehdr.ehdrXX.e_phentsize))
{
phdr->p_type = grub_swap_bytes_wordXX (phdr->p_type);
phdr->p_flags = grub_swap_bytes_wordXX (phdr->p_flags);
phdr->p_offset = grub_swap_bytes_offXX (phdr->p_offset);
phdr->p_vaddr = grub_swap_bytes_addrXX (phdr->p_vaddr);
phdr->p_paddr = grub_swap_bytes_addrXX (phdr->p_paddr);
phdr->p_filesz = grub_swap_bytes_XwordXX (phdr->p_filesz);
phdr->p_memsz = grub_swap_bytes_XwordXX (phdr->p_memsz);
phdr->p_align = grub_swap_bytes_XwordXX (phdr->p_align);
}
}
#endif /* GRUB_ELF_ENABLE_BI_ENDIAN */
return GRUB_ERR_NONE;
}
@ -154,3 +173,35 @@ grub_elfXX_load (grub_elf_t elf, const char *filename,
return grub_errno;
}
static int
grub_elfXX_check_endianess_and_bswap_ehdr (grub_elf_t elf)
{
ElfXX_Ehdr *e = &(elf->ehdr.ehdrXX);
if (e->e_ident[EI_DATA] == GRUB_ELF_NATIVE_ENDIANNESS)
{
return 1;
}
#if GRUB_ELF_ENABLE_BI_ENDIAN
if (e->e_ident[EI_DATA] == GRUB_ELF_OPPOSITE_ENDIANNESS)
{
e->e_type = grub_swap_bytes_halfXX (e->e_type);
e->e_machine = grub_swap_bytes_halfXX (e->e_machine);
e->e_version = grub_swap_bytes_wordXX (e->e_version);
e->e_entry = grub_swap_bytes_addrXX (e->e_entry);
e->e_phoff = grub_swap_bytes_offXX (e->e_phoff);
e->e_shoff = grub_swap_bytes_offXX (e->e_shoff);
e->e_flags = grub_swap_bytes_wordXX (e->e_flags);
e->e_ehsize = grub_swap_bytes_halfXX (e->e_ehsize);
e->e_phentsize = grub_swap_bytes_halfXX (e->e_phentsize);
e->e_phnum = grub_swap_bytes_halfXX (e->e_phnum);
e->e_shentsize = grub_swap_bytes_halfXX (e->e_shentsize);
e->e_shnum = grub_swap_bytes_halfXX (e->e_shnum);
e->e_shstrndx = grub_swap_bytes_halfXX (e->e_shstrndx);
return 1;
}
#endif /* GRUB_ELF_ENABLE_BI_ENDIAN */
return 0;
}

View file

@ -89,7 +89,16 @@ grub_file_open (const char *name)
file->device = device;
if (device->disk && file_name[0] != '/')
/* In case of relative pathnames and non-Unix systems (like Windows)
* name of host files may not start with `/'. Blocklists for host files
* are meaningless as well (for a start, host disk does not allow any direct
* access - it is just a marker). So skip host disk in this case.
*/
if (device->disk && file_name[0] != '/'
#if defined(GRUB_UTIL) || defined(GRUB_MACHINE_EMU)
&& grub_strcmp (device->disk->name, "host")
#endif
)
/* This is a block list. */
file->fs = &grub_fs_blocklist;
else

View file

@ -0,0 +1,40 @@
/* kern/i386/tsc.c - x86 TSC time source implementation
* Requires Pentium or better x86 CPU that supports the RDTSC instruction.
* This module uses the PIT to calibrate the TSC to
* real time.
*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/time.h>
#include <grub/misc.h>
#include <grub/i386/tsc.h>
#include <grub/efi/efi.h>
#include <grub/efi/api.h>
int
grub_tsc_calibrate_from_efi (void)
{
grub_uint64_t start_tsc, end_tsc;
/* Use EFI Time Service to calibrate TSC */
start_tsc = grub_get_tsc ();
efi_call_1 (grub_efi_system_table->boot_services->stall, 1000);
end_tsc = grub_get_tsc ();
grub_tsc_rate = grub_divmod64 ((1ULL << 32), end_tsc - start_tsc, 0);
return 1;
}

View file

@ -1,7 +1,6 @@
/* kern/i386/tsc.c - x86 TSC time source implementation
* Requires Pentium or better x86 CPU that supports the RDTSC instruction.
* This module uses the RTC (via grub_get_rtc()) to calibrate the TSC to
* real time.
* This module calibrates the TSC to real time.
*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
@ -25,12 +24,6 @@
#include <grub/misc.h>
#include <grub/i386/tsc.h>
#include <grub/i386/cpuid.h>
#ifdef GRUB_MACHINE_XEN
#include <grub/xen.h>
#else
#include <grub/i386/pit.h>
#endif
#include <grub/cpu/io.h>
/* This defines the value TSC had at the epoch (that is, when we calibrated it). */
static grub_uint64_t tsc_boot_time;
@ -40,66 +33,6 @@ static grub_uint64_t tsc_boot_time;
in 32-bit. */
grub_uint32_t grub_tsc_rate;
/* Read the TSC value, which increments with each CPU clock cycle. */
static __inline grub_uint64_t
grub_get_tsc (void)
{
grub_uint32_t lo, hi;
grub_uint32_t a,b,c,d;
/* The CPUID instruction is a 'serializing' instruction, and
avoids out-of-order execution of the RDTSC instruction. */
grub_cpuid (0,a,b,c,d);
/* Read TSC value. We cannot use "=A", since this would use
%rax on x86_64. */
__asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi));
return (((grub_uint64_t) hi) << 32) | lo;
}
#ifndef GRUB_MACHINE_XEN
static __inline int
grub_cpu_is_tsc_supported (void)
{
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;
}
static void
grub_pit_wait (grub_uint16_t tics)
{
/* Disable timer2 gate and speaker. */
grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
& ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
GRUB_PIT_SPEAKER_PORT);
/* Set tics. */
grub_outb (GRUB_PIT_CTRL_SELECT_2 | GRUB_PIT_CTRL_READLOAD_WORD,
GRUB_PIT_CTRL);
grub_outb (tics & 0xff, GRUB_PIT_COUNTER_2);
grub_outb (tics >> 8, GRUB_PIT_COUNTER_2);
/* Enable timer2 gate, keep speaker disabled. */
grub_outb ((grub_inb (GRUB_PIT_SPEAKER_PORT) & ~ GRUB_PIT_SPK_DATA)
| GRUB_PIT_SPK_TMR2,
GRUB_PIT_SPEAKER_PORT);
/* Wait. */
while ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == 0x00);
/* Disable timer2 gate and speaker. */
grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
& ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
GRUB_PIT_SPEAKER_PORT);
}
#endif
static grub_uint64_t
grub_tsc_get_time_ms (void)
{
@ -110,52 +43,52 @@ grub_tsc_get_time_ms (void)
return ((al * grub_tsc_rate) >> 32) + ah * grub_tsc_rate;
}
#ifndef GRUB_MACHINE_XEN
/* Calibrate the TSC based on the RTC. */
static void
calibrate_tsc (void)
static __inline int
grub_cpu_is_tsc_supported (void)
{
/* First calibrate the TSC rate (relative, not absolute time). */
grub_uint64_t end_tsc;
#ifndef GRUB_MACHINE_XEN
grub_uint32_t a,b,c,d;
if (! grub_cpu_is_cpuid_supported ())
return 0;
tsc_boot_time = grub_get_tsc ();
grub_pit_wait (0xffff);
end_tsc = grub_get_tsc ();
grub_cpuid(1,a,b,c,d);
grub_tsc_rate = 0;
if (end_tsc > tsc_boot_time)
grub_tsc_rate = grub_divmod64 ((55ULL << 32), end_tsc - tsc_boot_time, 0);
if (grub_tsc_rate == 0)
grub_tsc_rate = 5368;/* 800 MHz */
}
return (d & (1 << 4)) != 0;
#else
return 1;
#endif
}
static int
calibrate_tsc_hardcode (void)
{
grub_tsc_rate = 5368;/* 800 MHz */
return 1;
}
void
grub_tsc_init (void)
{
#ifdef GRUB_MACHINE_XEN
grub_uint64_t t;
tsc_boot_time = grub_get_tsc ();
t = grub_xen_shared_info->vcpu_info[0].time.tsc_to_system_mul;
if (grub_xen_shared_info->vcpu_info[0].time.tsc_shift > 0)
t <<= grub_xen_shared_info->vcpu_info[0].time.tsc_shift;
else
t >>= -grub_xen_shared_info->vcpu_info[0].time.tsc_shift;
grub_tsc_rate = grub_divmod64 (t, 1000000, 0);
grub_install_get_time_ms (grub_tsc_get_time_ms);
#else
if (grub_cpu_is_tsc_supported ())
{
calibrate_tsc ();
grub_install_get_time_ms (grub_tsc_get_time_ms);
}
else
if (!grub_cpu_is_tsc_supported ())
{
#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_IEEE1275)
grub_install_get_time_ms (grub_rtc_get_time_ms);
#else
grub_fatal ("no TSC found");
#endif
return;
}
tsc_boot_time = grub_get_tsc ();
#ifdef GRUB_MACHINE_XEN
(void) (grub_tsc_calibrate_from_xen () || calibrate_tsc_hardcode());
#elif defined (GRUB_MACHINE_EFI)
(void) (grub_tsc_calibrate_from_pit () || grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_efi() || calibrate_tsc_hardcode());
#elif defined (GRUB_MACHINE_COREBOOT)
(void) (grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_pit () || calibrate_tsc_hardcode());
#else
(void) (grub_tsc_calibrate_from_pit () || calibrate_tsc_hardcode());
#endif
grub_install_get_time_ms (grub_tsc_get_time_ms);
}

View file

@ -0,0 +1,84 @@
/* kern/i386/tsc.c - x86 TSC time source implementation
* Requires Pentium or better x86 CPU that supports the RDTSC instruction.
* This module uses the PIT to calibrate the TSC to
* real time.
*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/time.h>
#include <grub/misc.h>
#include <grub/i386/tsc.h>
#include <grub/i386/pit.h>
#include <grub/cpu/io.h>
static int
grub_pit_wait (void)
{
int ret = 0;
/* Disable timer2 gate and speaker. */
grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
& ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
GRUB_PIT_SPEAKER_PORT);
/* Set tics. */
grub_outb (GRUB_PIT_CTRL_SELECT_2 | GRUB_PIT_CTRL_READLOAD_WORD,
GRUB_PIT_CTRL);
/* 0xffff ticks: 55ms. */
grub_outb (0xff, GRUB_PIT_COUNTER_2);
grub_outb (0xff, GRUB_PIT_COUNTER_2);
/* Enable timer2 gate, keep speaker disabled. */
grub_outb ((grub_inb (GRUB_PIT_SPEAKER_PORT) & ~ GRUB_PIT_SPK_DATA)
| GRUB_PIT_SPK_TMR2,
GRUB_PIT_SPEAKER_PORT);
if ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == 0x00) {
ret = 1;
/* Wait. */
while ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == 0x00);
}
/* Disable timer2 gate and speaker. */
grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
& ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
GRUB_PIT_SPEAKER_PORT);
return ret;
}
/* Calibrate the TSC based on the RTC. */
int
grub_tsc_calibrate_from_pit (void)
{
/* First calibrate the TSC rate (relative, not absolute time). */
grub_uint64_t start_tsc, end_tsc;
start_tsc = grub_get_tsc ();
if (!grub_pit_wait ())
return 0;
end_tsc = grub_get_tsc ();
grub_tsc_rate = 0;
if (end_tsc > start_tsc)
grub_tsc_rate = grub_divmod64 ((55ULL << 32), end_tsc - start_tsc, 0);
if (grub_tsc_rate == 0)
return 0;
return 1;
}

View file

@ -0,0 +1,160 @@
/* kern/i386/tsc.c - x86 TSC time source implementation
* Requires Pentium or better x86 CPU that supports the RDTSC instruction.
* This module uses the PIT to calibrate the TSC to
* real time.
*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/time.h>
#include <grub/misc.h>
#include <grub/i386/tsc.h>
#include <grub/acpi.h>
#include <grub/cpu/io.h>
static void *
grub_acpi_rsdt_find_table (struct grub_acpi_table_header *rsdt, const char *sig)
{
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 last;
grub_uint32_t cur, end;
struct grub_acpi_fadt *fadt;
grub_port_t p;
grub_uint64_t start_tsc;
grub_uint64_t end_tsc;
int num_iter = 0;
fadt = grub_acpi_find_fadt ();
if (!fadt)
return 0;
p = fadt->pmtimer;
if (!p)
return 0;
start = grub_inl (p) & 0xffffff;
last = start;
/* It's 3.579545 MHz clock. Wait 1 ms. */
end = start + 3580;
start_tsc = grub_get_tsc ();
while (1)
{
cur = grub_inl (p) & 0xffffff;
if (cur < last)
cur |= 0x1000000;
num_iter++;
if (cur >= end)
{
end_tsc = grub_get_tsc ();
grub_tsc_rate = grub_divmod64 ((1ULL << 32), end_tsc - start_tsc, 0);
return 1;
}
/* Check for broken PM timer.
50000000 TSCs is between 5 ms (10GHz) and 200 ms (250 MHz)
if after this time we still don't have 1 ms on pmtimer, then
pmtimer is broken.
*/
if ((num_iter & 0xffffff) == 0 && grub_get_tsc () - start_tsc > 5000000) {
return 0;
}
}
}

View file

@ -0,0 +1,40 @@
/* kern/i386/tsc.c - x86 TSC time source implementation
* Requires Pentium or better x86 CPU that supports the RDTSC instruction.
* This module uses the PIT to calibrate the TSC to
* real time.
*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/time.h>
#include <grub/misc.h>
#include <grub/i386/tsc.h>
#include <grub/xen.h>
int
grub_tsc_calibrate_from_xen (void)
{
grub_uint64_t t;
t = grub_xen_shared_info->vcpu_info[0].time.tsc_to_system_mul;
if (grub_xen_shared_info->vcpu_info[0].time.tsc_shift > 0)
t <<= grub_xen_shared_info->vcpu_info[0].time.tsc_shift;
else
t >>= -grub_xen_shared_info->vcpu_info[0].time.tsc_shift;
grub_tsc_rate = grub_divmod64 (t, 1000000, 0);
return 1;
}

View file

@ -166,7 +166,7 @@ heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
{
unsigned long *total = data;
if (type != 1)
if (type != GRUB_MEMORY_AVAILABLE)
return 0;
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM))

View file

@ -138,6 +138,10 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
sym = (Elf_Sym *) ((char *) mod->symtab
+ mod->symsize * ELF_R_SYM (rel->r_info));
sym_value = sym->st_value;
if (s->sh_type == SHT_RELA)
{
sym_value += ((Elf_Rela *) rel)->r_addend;
}
if (sym_value == (grub_addr_t) &__gnu_local_gp_dummy)
sym_value = (grub_addr_t) mod->got;
else if (sym_value == (grub_addr_t) &_gp_disp_dummy)

View file

@ -22,6 +22,7 @@
#include <grub/machine/memory.h>
#include <grub/machine/kernel.h>
#include <grub/offsets.h>
#include <grub/mips/asm.h>
#define BASE_ADDR 8
@ -95,8 +96,8 @@ cont:
modulesmovcont:
beq $t3, $0, modulesmovdone
nop
lb $t4, 0($t2)
sb $t4, 0($t1)
lb GRUB_ASM_T4, 0($t2)
sb GRUB_ASM_T4, 0($t1)
addiu $t2, $t2, -1
addiu $t1, $t1, -1
b modulesmovcont

View file

@ -268,6 +268,7 @@ grub_parser_execute (char *source)
grub_parser_execute_getline (&line, 0, &source);
grub_rescue_parse_line (line, grub_parser_execute_getline, &source);
grub_free (line);
grub_print_error ();
}
return grub_errno;

View file

@ -470,7 +470,8 @@ grub_password_get (char buf[], unsigned buf_size)
if (key == '\b')
{
cur_len--;
if (cur_len)
cur_len--;
continue;
}

View file

@ -19,6 +19,9 @@
#include <grub/fdt.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/dl.h>
GRUB_MOD_LICENSE ("GPLv3+");
#define FDT_SUPPORTED_VERSION 17

View file

@ -18,6 +18,7 @@
#include <grub/symbol.h>
#include <grub/dl.h>
#include <grub/mips/asm.h>
.file "setjmp.S"
@ -29,40 +30,42 @@ GRUB_MOD_LICENSE "GPLv3+"
* int grub_setjmp (grub_jmp_buf env)
*/
FUNCTION(grub_setjmp)
sw $s0, 0($a0)
sw $s1, 4($a0)
sw $s2, 8($a0)
sw $s3, 12($a0)
sw $s4, 16($a0)
sw $s5, 20($a0)
sw $s6, 24($a0)
sw $s7, 28($a0)
sw $s8, 32($a0)
sw $gp, 36($a0)
sw $sp, 40($a0)
sw $ra, 44($a0)
GRUB_ASM_REG_S $s0, 0($a0)
GRUB_ASM_REG_S $s1, 8($a0)
GRUB_ASM_REG_S $s2, 16($a0)
GRUB_ASM_REG_S $s3, 24($a0)
GRUB_ASM_REG_S $s4, 32($a0)
GRUB_ASM_REG_S $s5, 40($a0)
GRUB_ASM_REG_S $s6, 48($a0)
GRUB_ASM_REG_S $s7, 56($a0)
GRUB_ASM_REG_S $s8, 64($a0)
GRUB_ASM_REG_S $gp, 72($a0)
GRUB_ASM_REG_S $sp, 80($a0)
GRUB_ASM_REG_S $ra, 88($a0)
move $v0, $zero
move $v1, $zero
jr $ra
nop
/*
* int grub_longjmp (grub_jmp_buf env, int val)
*/
FUNCTION(grub_longjmp)
lw $s0, 0($a0)
lw $s1, 4($a0)
lw $s2, 8($a0)
lw $s3, 12($a0)
lw $s4, 16($a0)
lw $s5, 20($a0)
lw $s6, 24($a0)
lw $s7, 28($a0)
lw $s8, 32($a0)
lw $gp, 36($a0)
lw $sp, 40($a0)
lw $ra, 44($a0)
GRUB_ASM_REG_L $s0, 0($a0)
GRUB_ASM_REG_L $s1, 8($a0)
GRUB_ASM_REG_L $s2, 16($a0)
GRUB_ASM_REG_L $s3, 24($a0)
GRUB_ASM_REG_L $s4, 32($a0)
GRUB_ASM_REG_L $s5, 40($a0)
GRUB_ASM_REG_L $s6, 48($a0)
GRUB_ASM_REG_L $s7, 56($a0)
GRUB_ASM_REG_L $s8, 64($a0)
GRUB_ASM_REG_L $gp, 72($a0)
GRUB_ASM_REG_L $sp, 80($a0)
GRUB_ASM_REG_L $ra, 88($a0)
move $v0, $a1
bne $v0, $zero, 1f
addiu $v0, $v0, 1
1:
move $v1, $zero
jr $ra
nop

View file

@ -23,6 +23,7 @@
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/normal.h>
#include <grub/net.h>
GRUB_MOD_LICENSE ("GPLv3+");
@ -70,7 +71,15 @@ grub_file_progress_hook_real (grub_disk_addr_t sector __attribute__ ((unused)),
percent = grub_divmod64 (100 * file->progress_offset,
file->size, 0);
partial_file_name = grub_strrchr (file->name, '/');
/* grub_net_fs_open() saves off partial file structure before name is initialized.
It already saves passed file name in net structure so just use it in this case.
*/
if (file->device->net)
partial_file_name = grub_strrchr (file->device->net->name, '/');
else if (file->name) /* grub_file_open() may leave it as NULL */
partial_file_name = grub_strrchr (file->name, '/');
else
partial_file_name = NULL;
if (partial_file_name)
partial_file_name++;
else

View file

@ -0,0 +1,185 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013-2015 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/fdt.h>
#include <grub/mm.h>
#include <grub/cpu/fdtload.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/file.h>
#include <grub/efi/efi.h>
static void *loaded_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 *
grub_fdt_load (grub_size_t additional_size)
{
void *raw_fdt;
grub_size_t size;
if (fdt)
{
size = GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt));
grub_efi_free_pages ((grub_efi_physical_address_t) fdt, size);
}
if (loaded_fdt)
raw_fdt = loaded_fdt;
else
raw_fdt = get_firmware_fdt();
size =
raw_fdt ? grub_fdt_get_totalsize (raw_fdt) : GRUB_FDT_EMPTY_TREE_SZ;
size += additional_size;
grub_dprintf ("linux", "allocating %ld bytes for fdt\n", size);
fdt = grub_efi_allocate_pages (0, GRUB_EFI_BYTES_TO_PAGES (size));
if (!fdt)
return NULL;
if (raw_fdt)
{
grub_memmove (fdt, raw_fdt, size);
grub_fdt_set_totalsize (fdt, size);
}
else
{
grub_fdt_create_empty_tree (fdt, size);
}
return fdt;
}
grub_err_t
grub_fdt_install (void)
{
grub_efi_boot_services_t *b;
grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
grub_efi_status_t status;
b = grub_efi_system_table->boot_services;
status = b->install_configuration_table (&fdt_guid, fdt);
if (status != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_IO, "failed to install FDT");
grub_dprintf ("fdt", "Installed/updated FDT configuration table @ %p\n",
fdt);
return GRUB_ERR_NONE;
}
void
grub_fdt_unload (void) {
if (!fdt) {
return;
}
grub_efi_free_pages ((grub_efi_physical_address_t) fdt,
GRUB_EFI_BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt)));
fdt = NULL;
}
static grub_err_t
grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t dtb;
void *blob = NULL;
int size;
if (loaded_fdt)
grub_free (loaded_fdt);
loaded_fdt = NULL;
/* No arguments means "use firmware FDT". */
if (argc == 0)
{
return GRUB_ERR_NONE;
}
dtb = grub_file_open (argv[0]);
if (!dtb)
goto out;
size = grub_file_size (dtb);
blob = grub_malloc (size);
if (!blob)
goto out;
if (grub_file_read (dtb, blob, size) < size)
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
goto out;
}
if (grub_fdt_check_header (blob, size) != 0)
{
grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree"));
goto out;
}
out:
if (dtb)
grub_file_close (dtb);
if (blob)
{
if (grub_errno == GRUB_ERR_NONE)
loaded_fdt = blob;
else
grub_free (blob);
}
return grub_errno;
}
static grub_command_t cmd_devicetree;
GRUB_MOD_INIT (fdt)
{
cmd_devicetree =
grub_register_command ("devicetree", grub_cmd_devicetree, 0,
N_("Load DTB file."));
}
GRUB_MOD_FINI (fdt)
{
grub_unregister_command (cmd_devicetree);
}

View file

@ -26,6 +26,7 @@
#include <grub/mm.h>
#include <grub/types.h>
#include <grub/cpu/linux.h>
#include <grub/cpu/fdtload.h>
#include <grub/efi/efi.h>
#include <grub/efi/pe32.h>
#include <grub/i18n.h>
@ -45,69 +46,6 @@ static grub_uint32_t cmdline_size;
static grub_addr_t initrd_start;
static grub_addr_t initrd_end;
static void *loaded_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 *
grub_linux_get_fdt (void)
{
void *raw_fdt;
grub_size_t size;
if (fdt)
{
size = BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt));
grub_efi_free_pages ((grub_efi_physical_address_t) fdt, size);
}
if (loaded_fdt)
raw_fdt = loaded_fdt;
else
raw_fdt = get_firmware_fdt();
size =
raw_fdt ? grub_fdt_get_totalsize (raw_fdt) : GRUB_FDT_EMPTY_TREE_SZ;
size += 0x400;
grub_dprintf ("linux", "allocating %ld bytes for fdt\n", size);
fdt = grub_efi_allocate_pages (0, BYTES_TO_PAGES (size));
if (!fdt)
return NULL;
if (raw_fdt)
{
grub_memmove (fdt, raw_fdt, size);
grub_fdt_set_totalsize (fdt, size);
}
else
{
grub_fdt_create_empty_tree (fdt, size);
}
return fdt;
}
grub_err_t
grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header * lh)
{
@ -129,12 +67,13 @@ grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header * lh)
static grub_err_t
finalize_params_linux (void)
{
grub_efi_boot_services_t *b;
grub_efi_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID;
grub_efi_status_t status;
int node, retval;
if (!grub_linux_get_fdt ())
void *fdt;
fdt = grub_fdt_load (0x400);
if (!fdt)
goto failure;
node = grub_fdt_find_subnode (fdt, 0, "chosen");
@ -160,82 +99,16 @@ finalize_params_linux (void)
goto failure;
}
b = grub_efi_system_table->boot_services;
status = b->install_configuration_table (&fdt_guid, fdt);
if (status != GRUB_EFI_SUCCESS)
if (grub_fdt_install() != GRUB_ERR_NONE)
goto failure;
grub_dprintf ("linux", "Installed/updated FDT configuration table @ %p\n",
fdt);
return GRUB_ERR_NONE;
failure:
grub_efi_free_pages ((grub_efi_physical_address_t) fdt,
BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt)));
fdt = NULL;
grub_fdt_unload();
return grub_error(GRUB_ERR_BAD_OS, "failed to install/update FDT");
}
static grub_err_t
grub_cmd_devicetree (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
grub_file_t dtb;
void *blob = NULL;
int size;
if (!loaded)
{
grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the kernel first"));
return GRUB_ERR_BAD_OS;
}
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
if (loaded_fdt)
grub_free (loaded_fdt);
loaded_fdt = NULL;
dtb = grub_file_open (argv[0]);
if (!dtb)
goto out;
size = grub_file_size (dtb);
blob = grub_malloc (size);
if (!blob)
goto out;
if (grub_file_read (dtb, blob, size) < size)
{
if (!grub_errno)
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
goto out;
}
if (grub_fdt_check_header (blob, size) != 0)
{
grub_error (GRUB_ERR_BAD_OS, N_("invalid device tree"));
goto out;
}
out:
if (dtb)
grub_file_close (dtb);
if (blob)
{
if (grub_errno == GRUB_ERR_NONE)
loaded_fdt = blob;
else
grub_free (blob);
}
return grub_errno;
}
grub_err_t
grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
{
@ -276,7 +149,7 @@ grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
(grub_strlen (args) + 1) * sizeof (grub_efi_char16_t);
loaded_image->load_options =
grub_efi_allocate_pages (0,
BYTES_TO_PAGES (loaded_image->load_options_size));
GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
if (!loaded_image->load_options)
return grub_errno;
@ -290,7 +163,7 @@ grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size, char *args)
/* When successful, not reached */
b->unload_image (image_handle);
grub_efi_free_pages ((grub_efi_physical_address_t) loaded_image->load_options,
BYTES_TO_PAGES (loaded_image->load_options_size));
GRUB_EFI_BYTES_TO_PAGES (loaded_image->load_options_size));
return grub_errno;
}
@ -312,16 +185,13 @@ grub_linux_unload (void)
loaded = 0;
if (initrd_start)
grub_efi_free_pages ((grub_efi_physical_address_t) initrd_start,
BYTES_TO_PAGES (initrd_end - initrd_start));
GRUB_EFI_BYTES_TO_PAGES (initrd_end - initrd_start));
initrd_start = initrd_end = 0;
grub_free (linux_args);
if (kernel_addr)
grub_efi_free_pages ((grub_efi_physical_address_t) kernel_addr,
BYTES_TO_PAGES (kernel_size));
if (fdt)
grub_efi_free_pages ((grub_efi_physical_address_t) fdt,
BYTES_TO_PAGES (grub_fdt_get_totalsize (fdt)));
GRUB_EFI_BYTES_TO_PAGES (kernel_size));
grub_fdt_unload ();
return GRUB_ERR_NONE;
}
@ -352,7 +222,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
initrd_size = grub_get_initrd_size (&initrd_ctx);
grub_dprintf ("linux", "Loading initrd\n");
initrd_pages = (BYTES_TO_PAGES (initrd_size));
initrd_pages = (GRUB_EFI_BYTES_TO_PAGES (initrd_size));
initrd_mem = grub_efi_allocate_pages (0, initrd_pages);
if (!initrd_mem)
{
@ -407,9 +277,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
grub_loader_unset();
grub_dprintf ("linux", "kernel file size: %lld\n", (long long) kernel_size);
kernel_addr = grub_efi_allocate_pages (0, BYTES_TO_PAGES (kernel_size));
kernel_addr = grub_efi_allocate_pages (0, GRUB_EFI_BYTES_TO_PAGES (kernel_size));
grub_dprintf ("linux", "kernel numpages: %lld\n",
(long long) BYTES_TO_PAGES (kernel_size));
(long long) GRUB_EFI_BYTES_TO_PAGES (kernel_size));
if (!kernel_addr)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
@ -460,13 +330,13 @@ fail:
if (kernel_addr && !loaded)
grub_efi_free_pages ((grub_efi_physical_address_t) kernel_addr,
BYTES_TO_PAGES (kernel_size));
GRUB_EFI_BYTES_TO_PAGES (kernel_size));
return grub_errno;
}
static grub_command_t cmd_linux, cmd_initrd, cmd_devicetree;
static grub_command_t cmd_linux, cmd_initrd;
GRUB_MOD_INIT (linux)
{
@ -474,9 +344,6 @@ GRUB_MOD_INIT (linux)
N_("Load Linux."));
cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, 0,
N_("Load initrd."));
cmd_devicetree =
grub_register_command ("devicetree", grub_cmd_devicetree, 0,
N_("Load DTB file."));
my_mod = mod;
}
@ -484,5 +351,4 @@ GRUB_MOD_FINI (linux)
{
grub_unregister_command (cmd_linux);
grub_unregister_command (cmd_initrd);
grub_unregister_command (cmd_devicetree);
}

View file

@ -0,0 +1,587 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2014 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/cache.h>
#include <grub/charset.h>
#include <grub/command.h>
#include <grub/err.h>
#include <grub/file.h>
#include <grub/fdt.h>
#include <grub/list.h>
#include <grub/loader.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/types.h>
#include <grub/cpu/fdtload.h>
#include <grub/cpu/linux.h>
#include <grub/efi/efi.h>
#include <grub/efi/pe32.h> /* required by struct xen_hypervisor_header */
#include <grub/i18n.h>
#include <grub/lib/cmdline.h>
GRUB_MOD_LICENSE ("GPLv3+");
#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"
/* This maximum size is defined in Power.org ePAPR V1.1
* https://www.power.org/documentation/epapr-version-1-1/
* 2.2.1.1 Node Name Requirements
* node-name@unit-address
* 31 + 1(@) + 16(64bit address in hex format) + 1(\0) = 49
*/
#define FDT_NODE_NAME_MAX_SIZE (49)
struct compat_string_struct
{
grub_size_t size;
const char *compat_string;
};
typedef struct compat_string_struct compat_string_struct_t;
#define FDT_COMPATIBLE(x) {.size = sizeof(x), .compat_string = (x)}
enum module_type
{
MODULE_IMAGE,
MODULE_INITRD,
MODULE_XSM,
MODULE_CUSTOM
};
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 grub_arm64_linux_kernel_header efi_head;
/* This is always PE\0\0. */
grub_uint8_t signature[GRUB_PE32_SIGNATURE_SIZE];
/* The COFF file header. */
struct grub_pe32_coff_header coff_header;
/* The Optional header. */
struct grub_pe64_optional_header optional_header;
};
struct xen_boot_binary
{
struct xen_boot_binary *next;
struct xen_boot_binary **prev;
const char *name;
grub_addr_t start;
grub_size_t size;
grub_size_t align;
char *cmdline;
int cmdline_size;
struct fdt_node_info node_info;
};
static grub_dl_t my_mod;
static int loaded;
static struct xen_boot_binary *xen_hypervisor;
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
xen_boot_address_align (grub_addr_t start, grub_size_t align)
{
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
prepare_xen_hypervisor_params (void *xen_boot_fdt)
{
int chosen_node = 0;
int retval;
chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
if (chosen_node < 0)
chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
if (chosen_node < 1)
return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
grub_dprintf ("xen_loader",
"Xen Hypervisor cmdline : %s @ %p size:%d\n",
xen_hypervisor->cmdline, xen_hypervisor->cmdline,
xen_hypervisor->cmdline_size);
retval = grub_fdt_set_prop (xen_boot_fdt, chosen_node, "bootargs",
xen_hypervisor->cmdline,
xen_hypervisor->cmdline_size);
if (retval)
return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
return GRUB_ERR_NONE;
}
static grub_err_t
prepare_xen_module_params (struct xen_boot_binary *module, void *xen_boot_fdt)
{
int retval, chosen_node = 0, module_node = 0;
char module_name[FDT_NODE_NAME_MAX_SIZE];
retval = grub_snprintf (module_name, FDT_NODE_NAME_MAX_SIZE, "module@%lx",
xen_boot_address_align (module->start,
module->align));
grub_dprintf ("xen_loader", "Module node name %s \n", module_name);
if (retval < (int) sizeof ("module@"))
return grub_error (GRUB_ERR_IO, N_("failed to get FDT"));
chosen_node = grub_fdt_find_subnode (xen_boot_fdt, 0, "chosen");
if (chosen_node < 0)
chosen_node = grub_fdt_add_subnode (xen_boot_fdt, 0, "chosen");
if (chosen_node < 1)
return grub_error (GRUB_ERR_IO, "failed to get chosen node in FDT");
module_node =
grub_fdt_find_subnode (xen_boot_fdt, chosen_node, module_name);
if (module_node < 0)
module_node =
grub_fdt_add_subnode (xen_boot_fdt, chosen_node, module_name);
retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "compatible",
module->node_info.compat_string,
(grub_uint32_t) module->
node_info.compat_string_size);
if (retval)
return grub_error (GRUB_ERR_IO, "failed to update FDT");
grub_dprintf ("xen_loader", "Module %s compatible = %s size = 0x%lx\n",
module->name, module->node_info.compat_string,
module->node_info.compat_string_size);
retval = grub_fdt_set_reg64 (xen_boot_fdt, module_node,
xen_boot_address_align (module->start,
module->align),
module->size);
if (retval)
return grub_error (GRUB_ERR_IO, "failed to update FDT");
if (module->cmdline && module->cmdline_size > 0)
{
grub_dprintf ("xen_loader",
"Module %s cmdline : %s @ %p size:%d\n", module->name,
module->cmdline, module->cmdline, module->cmdline_size);
retval = grub_fdt_set_prop (xen_boot_fdt, module_node, "bootargs",
module->cmdline, module->cmdline_size + 1);
if (retval)
return grub_error (GRUB_ERR_IO, "failed to update FDT");
}
else
{
grub_dprintf ("xen_loader", "Module %s has not bootargs!\n",
module->name);
}
return GRUB_ERR_NONE;
}
static grub_err_t
finalize_params_xen_boot (void)
{
struct xen_boot_binary *module;
void *xen_boot_fdt;
grub_size_t additional_size = 0x1000;
/* Hypervisor. */
additional_size += FDT_NODE_NAME_MAX_SIZE + xen_hypervisor->cmdline_size;
FOR_LIST_ELEMENTS (module, module_head)
{
additional_size += 6 * FDT_NODE_NAME_MAX_SIZE + module->
node_info.compat_string_size + module->cmdline_size;
}
xen_boot_fdt = grub_fdt_load (additional_size);
if (!xen_boot_fdt)
return grub_error (GRUB_ERR_IO, "failed to get FDT");
if (xen_hypervisor)
{
if (prepare_xen_hypervisor_params (xen_boot_fdt) != GRUB_ERR_NONE)
goto fail;
}
else
{
grub_dprintf ("xen_loader", "Failed to get Xen Hypervisor info!\n");
goto fail;
}
/* Set module params info */
FOR_LIST_ELEMENTS (module, module_head)
{
if (module->start && module->size > 0)
{
grub_dprintf ("xen_loader", "Module %s @ 0x%lx size:0x%lx\n",
module->name,
xen_boot_address_align (module->start, module->align),
module->size);
if (prepare_xen_module_params (module, xen_boot_fdt) != GRUB_ERR_NONE)
goto fail;
}
else
{
grub_dprintf ("xen_loader", "Module info error: %s!\n", module->name);
goto fail;
}
}
if (grub_fdt_install() == GRUB_ERR_NONE)
return GRUB_ERR_NONE;
fail:
grub_fdt_unload ();
return grub_error (GRUB_ERR_IO, "failed to install/update FDT");
}
static grub_err_t
xen_boot (void)
{
grub_err_t err = finalize_params_xen_boot ();
if (err)
return err;
return grub_arm64_uefi_boot_image (xen_hypervisor->start,
xen_hypervisor->size,
xen_hypervisor->cmdline);
}
static void
single_binary_unload (struct xen_boot_binary *binary)
{
if (!binary)
return;
if (binary->start && binary->size > 0)
{
grub_efi_free_pages ((grub_efi_physical_address_t) binary->start,
GRUB_EFI_BYTES_TO_PAGES (binary->size + binary->align));
}
if (binary->cmdline && binary->cmdline_size > 0)
{
grub_free (binary->cmdline);
grub_dprintf ("xen_loader",
"Module %s cmdline memory free @ %p size: %d\n",
binary->name, binary->cmdline, binary->cmdline_size);
}
if (binary->node_info.type == MODULE_CUSTOM)
grub_free ((void *) binary->node_info.compat_string);
if (grub_strcmp (binary->name, XEN_HYPERVISOR_NAME))
grub_list_remove (GRUB_AS_LIST (binary));
grub_dprintf ("xen_loader",
"Module %s struct memory free @ %p size: 0x%lx\n",
binary->name, binary, sizeof (binary));
grub_free (binary);
return;
}
static void
all_binaries_unload (void)
{
struct xen_boot_binary *binary;
FOR_LIST_ELEMENTS (binary, module_head)
{
single_binary_unload (binary);
}
if (xen_hypervisor)
single_binary_unload (xen_hypervisor);
return;
}
static grub_err_t
xen_unload (void)
{
loaded = 0;
all_binaries_unload ();
grub_fdt_unload ();
grub_dl_unref (my_mod);
return GRUB_ERR_NONE;
}
static void
xen_boot_binary_load (struct xen_boot_binary *binary, grub_file_t file,
int argc, char *argv[])
{
binary->size = grub_file_size (file);
grub_dprintf ("xen_loader", "Xen_boot %s file size: 0x%lx\n",
binary->name, binary->size);
binary->start
= (grub_addr_t) grub_efi_allocate_pages (0,
GRUB_EFI_BYTES_TO_PAGES
(binary->size +
binary->align));
if (!binary->start)
{
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
return;
}
grub_dprintf ("xen_loader", "Xen_boot %s numpages: 0x%lx\n",
binary->name, GRUB_EFI_BYTES_TO_PAGES (binary->size + binary->align));
if (grub_file_read (file, (void *) xen_boot_address_align (binary->start,
binary->align),
binary->size) != (grub_ssize_t) binary->size)
{
single_binary_unload (binary);
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), argv[0]);
return;
}
if (argc > 1)
{
binary->cmdline_size = grub_loader_cmdline_size (argc - 1, argv + 1);
binary->cmdline = grub_zalloc (binary->cmdline_size);
if (!binary->cmdline)
{
single_binary_unload (binary);
grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
return;
}
grub_create_loader_cmdline (argc - 1, argv + 1, binary->cmdline,
binary->cmdline_size);
grub_dprintf ("xen_loader",
"Xen_boot %s cmdline @ %p %s, size: %d\n", binary->name,
binary->cmdline, binary->cmdline, binary->cmdline_size);
}
else
{
binary->cmdline_size = 0;
binary->cmdline = NULL;
}
grub_errno = GRUB_ERR_NONE;
return;
}
static grub_err_t
grub_cmd_xen_module (grub_command_t cmd, int argc, char *argv[])
{
struct xen_boot_binary *module = NULL;
grub_file_t file = 0;
if (!argc)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
goto fail;
}
if (!loaded)
{
grub_error (GRUB_ERR_BAD_ARGUMENT,
N_("you need to load the Xen Hypervisor first"));
goto fail;
}
module =
(struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
if (!module)
return grub_errno;
/* process all the options and get module type */
if (set_module_type (cmd, module) != GRUB_ERR_NONE)
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:
/* 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]);
if (!file)
goto fail;
xen_boot_binary_load (module, file, argc, argv);
if (grub_errno == GRUB_ERR_NONE)
grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
fail:
if (file)
grub_file_close (file);
if (grub_errno != GRUB_ERR_NONE)
single_binary_unload (module);
return grub_errno;
}
static grub_err_t
grub_cmd_xen_hypervisor (grub_command_t cmd __attribute__ ((unused)),
int argc, char *argv[])
{
struct xen_hypervisor_header sh;
grub_file_t file = NULL;
grub_dl_ref (my_mod);
if (!argc)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
goto fail;
}
file = grub_file_open (argv[0]);
if (!file)
goto fail;
if (grub_file_read (file, &sh, sizeof (sh)) != (long) sizeof (sh))
goto fail;
if (grub_arm64_uefi_check_image
((struct grub_arm64_linux_kernel_header *) &sh) != GRUB_ERR_NONE)
goto fail;
grub_file_seek (file, 0);
/* if another module has called grub_loader_set,
we need to make sure that another module is unloaded properly */
grub_loader_unset ();
xen_hypervisor =
(struct xen_boot_binary *) grub_zalloc (sizeof (struct xen_boot_binary));
if (!xen_hypervisor)
return grub_errno;
xen_hypervisor->name = XEN_HYPERVISOR_NAME;
xen_hypervisor->align = (grub_size_t) sh.optional_header.section_alignment;
xen_boot_binary_load (xen_hypervisor, file, argc, argv);
if (grub_errno == GRUB_ERR_NONE)
{
grub_loader_set (xen_boot, xen_unload, 0);
loaded = 1;
}
fail:
if (file)
grub_file_close (file);
if (grub_errno != GRUB_ERR_NONE)
{
loaded = 0;
all_binaries_unload ();
grub_dl_unref (my_mod);
}
return grub_errno;
}
static grub_command_t cmd_xen_hypervisor;
static grub_command_t cmd_xen_linux, cmd_xen_initrd, cmd_xen_xsm;
GRUB_MOD_INIT (xen_boot)
{
cmd_xen_hypervisor =
grub_register_command ("xen_hypervisor", grub_cmd_xen_hypervisor, 0,
N_("Load a xen hypervisor."));
cmd_xen_linux =
grub_register_command ("xen_linux", grub_cmd_xen_module, 0,
N_("Load a xen linux kernel for dom0."));
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;
}
GRUB_MOD_FINI (xen_boot)
{
grub_unregister_command (cmd_xen_hypervisor);
grub_unregister_command (cmd_xen_linux);
grub_unregister_command (cmd_xen_initrd);
grub_unregister_command (cmd_xen_xsm);
}

View file

@ -73,6 +73,9 @@ load_kernel (grub_file_t file, const char *filename,
if (grub_multiboot_quirks & GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE)
{
err = grub_multiboot_load_elf (file, filename, buffer);
if (err == GRUB_ERR_NONE) {
return GRUB_ERR_NONE;
}
if (err == GRUB_ERR_UNKNOWN_OS && (header->flags & MULTIBOOT_AOUT_KLUDGE))
grub_errno = err = GRUB_ERR_NONE;
}

View file

@ -240,20 +240,27 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)),
#ifndef GRUB_USE_MULTIBOOT2
grub_multiboot_quirks = GRUB_MULTIBOOT_QUIRKS_NONE;
int option_found = 0;
if (argc != 0 && grub_strcmp (argv[0], "--quirk-bad-kludge") == 0)
do
{
argc--;
argv++;
grub_multiboot_quirks |= GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE;
}
option_found = 0;
if (argc != 0 && grub_strcmp (argv[0], "--quirk-bad-kludge") == 0)
{
argc--;
argv++;
option_found = 1;
grub_multiboot_quirks |= GRUB_MULTIBOOT_QUIRK_BAD_KLUDGE;
}
if (argc != 0 && grub_strcmp (argv[0], "--quirk-modules-after-kernel") == 0)
{
argc--;
argv++;
grub_multiboot_quirks |= GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL;
}
if (argc != 0 && grub_strcmp (argv[0], "--quirk-modules-after-kernel") == 0)
{
argc--;
argv++;
option_found = 1;
grub_multiboot_quirks |= GRUB_MULTIBOOT_QUIRK_MODULES_AFTER_KERNEL;
}
} while (option_found);
#endif
if (argc == 0)

View file

@ -196,7 +196,7 @@ alloc_phys_choose (grub_uint64_t addr, grub_uint64_t len,
struct alloc_phys_ctx *ctx = data;
grub_addr_t end = addr + len;
if (type != 1)
if (type != GRUB_MEMORY_AVAILABLE)
return 0;
addr = ALIGN_UP (addr, FOUR_MB);
@ -430,7 +430,7 @@ static int
get_physbase (grub_uint64_t addr, grub_uint64_t len __attribute__ ((unused)),
grub_memory_type_t type, void *data __attribute__ ((unused)))
{
if (type != 1)
if (type != GRUB_MEMORY_AVAILABLE)
return 0;
if (addr < phys_base)
phys_base = addr;

View file

@ -73,6 +73,7 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
GRUB_MEMORY_AVAILABLE, hook_data);
break;
}
/* FALLTHROUGH */
case GRUB_EFI_RUNTIME_SERVICES_CODE:
hook (desc->physical_start, desc->num_pages * 4096,
GRUB_MEMORY_CODE, hook_data);
@ -83,10 +84,6 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
GRUB_MEMORY_BADRAM, hook_data);
break;
default:
grub_printf ("Unknown memory type %d, considering reserved\n",
desc->type);
case GRUB_EFI_BOOT_SERVICES_DATA:
if (!avoid_efi_boot_services)
{
@ -94,6 +91,7 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
GRUB_MEMORY_AVAILABLE, hook_data);
break;
}
/* FALLTHROUGH */
case GRUB_EFI_RESERVED_MEMORY_TYPE:
case GRUB_EFI_RUNTIME_SERVICES_DATA:
case GRUB_EFI_MEMORY_MAPPED_IO:
@ -119,6 +117,18 @@ grub_efi_mmap_iterate (grub_memory_hook_t hook, void *hook_data,
hook (desc->physical_start, desc->num_pages * 4096,
GRUB_MEMORY_NVS, hook_data);
break;
case GRUB_EFI_PERSISTENT_MEMORY:
hook (desc->physical_start, desc->num_pages * 4096,
GRUB_MEMORY_PERSISTENT, hook_data);
break;
default:
grub_printf ("Unknown memory type %d, considering reserved\n",
desc->type);
hook (desc->physical_start, desc->num_pages * 4096,
GRUB_MEMORY_RESERVED, hook_data);
break;
}
}
@ -142,6 +152,13 @@ make_efi_memtype (int type)
/* No way to remove a chunk of memory from EFI mmap.
So mark it as unusable. */
case GRUB_MEMORY_HOLE:
/*
* AllocatePages() does not support GRUB_EFI_PERSISTENT_MEMORY,
* so no translation for GRUB_MEMORY_PERSISTENT or
* GRUB_MEMORY_PERSISTENT_LEGACY.
*/
case GRUB_MEMORY_PERSISTENT:
case GRUB_MEMORY_PERSISTENT_LEGACY:
case GRUB_MEMORY_RESERVED:
return GRUB_EFI_UNUSABLE_MEMORY;

View file

@ -437,7 +437,7 @@ grub_net_dns_lookup (const char *name,
struct recv_data data = {naddresses, addresses, cache,
grub_cpu_to_be16 (id++), 0, 0, name, 0};
grub_uint8_t *nbd;
int have_server = 0;
grub_size_t try_server = 0;
if (!servers)
{
@ -543,38 +543,35 @@ grub_net_dns_lookup (const char *name,
for (i = 0; i < n_servers * 4; i++)
{
/* Connect to a next server. */
while (!(i & 1) && send_servers < n_servers)
while (!(i & 1) && try_server < n_servers)
{
sockets[send_servers] = grub_net_udp_open (servers[send_servers],
sockets[send_servers] = grub_net_udp_open (servers[try_server++],
DNS_PORT,
recv_hook,
&data);
send_servers++;
if (!sockets[send_servers - 1])
if (!sockets[send_servers])
{
err = grub_errno;
grub_errno = GRUB_ERR_NONE;
}
else
{
have_server = 1;
send_servers++;
break;
}
}
if (!have_server)
if (!send_servers)
goto out;
if (*data.naddresses)
goto out;
for (j = 0; j < send_servers; j++)
{
grub_err_t err2;
if (!sockets[j])
continue;
nb->data = nbd;
grub_size_t t = 0;
do
{
nb->data = nbd;
if (servers[j].option == DNS_OPTION_IPV4 ||
((servers[j].option == DNS_OPTION_PREFER_IPV4) && (t++ == 0)) ||
((servers[j].option == DNS_OPTION_PREFER_IPV6) && (t++ == 1)))

View file

@ -47,19 +47,19 @@ send_card_buffer (struct grub_net_card *dev,
if (st != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_IO,
N_("couldn't send network packet"));
if (txbuf == dev->txbuf)
/*
Some buggy firmware could return an arbitrary address instead of the
txbuf address we trasmitted, so just check that txbuf is non NULL
for success. This is ok because we open the SNP protocol in
exclusive mode so we know we're the only ones transmitting on this
box and since we only transmit one packet at a time we know our
transmit was successfull.
*/
if (txbuf)
{
dev->txbusy = 0;
break;
}
if (txbuf)
{
st = efi_call_7 (net->transmit, net, 0, dev->last_pkt_size,
dev->txbuf, NULL, NULL, NULL);
if (st != GRUB_EFI_SUCCESS)
return grub_error (GRUB_ERR_IO,
N_("couldn't send network packet"));
}
if (limit_time < grub_get_time_ms ())
return grub_error (GRUB_ERR_TIMEOUT,
N_("couldn't send network packet"));
@ -84,8 +84,9 @@ send_card_buffer (struct grub_net_card *dev,
we run in the GRUB_ERR_TIMEOUT case above.
Perhaps a timeout in the FW has discarded the recycle buffer.
*/
txbuf = NULL;
st = efi_call_3 (net->get_status, net, 0, &txbuf);
dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf == dev->txbuf);
dev->txbusy = !(st == GRUB_EFI_SUCCESS && txbuf);
return GRUB_ERR_NONE;
}

View file

@ -305,6 +305,7 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
grub_uint64_t prop;
grub_uint8_t *pprop;
char *shortname;
char need_suffix = 1;
if (grub_strcmp (alias->type, "network") != 0)
return 0;
@ -325,7 +326,43 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
#define SUFFIX ":speed=auto,duplex=auto,1.1.1.1,dummy,1.1.1.1,1.1.1.1,5,5,1.1.1.1,512"
if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX))
if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX))
need_suffix = 0;
/* sun4v vnet devices do not support setting duplex/speed */
{
char *ptr;
grub_ieee1275_finddevice (alias->path, &devhandle);
grub_ieee1275_get_property_length (devhandle, "compatible", &prop_size);
if (prop_size > 0)
{
pprop = grub_malloc (prop_size);
if (!pprop)
{
grub_free (card);
grub_free (ofdata);
grub_print_error ();
return 1;
}
if (!grub_ieee1275_get_property (devhandle, "compatible",
pprop, prop_size, NULL))
{
for (ptr = (char *) pprop; ptr - (char *) pprop < prop_size;
ptr += grub_strlen (ptr) + 1)
{
if (!grub_strcmp(ptr, "SUNW,sun4v-network"))
need_suffix = 0;
}
}
grub_free (pprop);
}
}
if (need_suffix)
ofdata->path = grub_malloc (grub_strlen (alias->path) + sizeof (SUFFIX));
else
ofdata->path = grub_malloc (grub_strlen (alias->path) + 1);
@ -335,7 +372,7 @@ search_net_devices (struct grub_ieee1275_devalias *alias)
return 0;
}
ofdata->suffix = grub_stpcpy (ofdata->path, alias->path);
if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX))
if (need_suffix)
grub_memcpy (ofdata->suffix, SUFFIX, sizeof (SUFFIX));
else
*ofdata->suffix = '\0';

View file

@ -1341,6 +1341,43 @@ grub_net_open_real (const char *name)
}
if (try == 0)
{
const char *prefix, *root;
char *prefdev, *comma;
int skip = 0;
grub_size_t devlen;
/* Do not attempt to load module if it requires protocol provided
by this module - it results in infinite recursion. Just continue,
fail and cleanup on next iteration.
*/
prefix = grub_env_get ("prefix");
if (!prefix)
continue;
prefdev = grub_file_get_device_name (prefix);
if (!prefdev)
{
root = grub_env_get ("root");
if (!root)
continue;
prefdev = grub_strdup (root);
if (!prefdev)
continue;
}
comma = grub_strchr (prefdev, ',');
if (comma)
*comma = '\0';
devlen = grub_strlen (prefdev);
if (protnamelen == devlen && grub_memcmp (prefdev, protname, devlen) == 0)
skip = 1;
grub_free (prefdev);
if (skip)
continue;
if (sizeof ("http") - 1 == protnamelen
&& grub_memcmp ("http", protname, protnamelen) == 0)
{

View file

@ -498,11 +498,22 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock,
struct grub_net_buff *nb_ack;
struct tcphdr *tcph;
grub_err_t err;
grub_net_network_level_address_t gateway;
struct grub_net_network_level_interface *inf;
sock->recv_hook = recv_hook;
sock->error_hook = error_hook;
sock->fin_hook = fin_hook;
sock->hook_data = hook_data;
err = grub_net_route_address (sock->out_nla, &gateway, &inf);
if (err)
return err;
err = grub_net_link_layer_resolve (sock->inf, &gateway, &(sock->ll_target_addr));
if (err)
return err;
nb_ack = grub_netbuff_alloc (sizeof (*tcph)
+ GRUB_NET_OUR_MAX_IP_HEADER_SIZE
+ GRUB_NET_MAX_LINK_HEADER_SIZE);
@ -882,7 +893,10 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
grub_priority_queue_pop (sock->pq);
}
if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq)
return GRUB_ERR_NONE;
{
ack (sock);
return GRUB_ERR_NONE;
}
while (1)
{
nb_top_p = grub_priority_queue_top (sock->pq);

View file

@ -174,8 +174,11 @@ grub_username_get (char buf[], unsigned buf_size)
if (key == '\b')
{
cur_len--;
grub_printf ("\b");
if (cur_len)
{
cur_len--;
grub_printf ("\b \b");
}
continue;
}

View file

@ -208,8 +208,7 @@ grub_util_devmapper_part_to_disk (struct stat *st,
&major, &minor, 0))
{
*is_part = 1;
return grub_find_device ("/dev",
(major << 8) | minor);
return grub_find_device ("/dev", makedev (major, minor));
}
*is_part = 0;
return xstrdup (path);

View file

@ -45,12 +45,6 @@
#ifdef __linux__
#include <sys/ioctl.h> /* ioctl */
#include <sys/mount.h>
#ifndef MAJOR
# ifndef MINORBITS
# define MINORBITS 8
# endif /* ! MINORBITS */
# define MAJOR(dev) ((unsigned) ((dev) >> MINORBITS))
#endif /* ! MAJOR */
#ifndef FLOPPY_MAJOR
# define FLOPPY_MAJOR 2
#endif /* ! FLOPPY_MAJOR */
@ -73,7 +67,6 @@
#include <grub/emu/getroot.h>
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
# define MAJOR(dev) major(dev)
# define FLOPPY_MAJOR 2
#endif
@ -90,7 +83,6 @@
#endif /* defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
#if defined(__NetBSD__) || defined(__OpenBSD__)
# define MAJOR(dev) major(dev)
# ifdef HAVE_GETRAWPARTITION
# include <util.h> /* getrawpartition */
# endif /* HAVE_GETRAWPARTITION */

View file

@ -54,7 +54,8 @@ grub_password_get (char buf[], unsigned buf_size)
grub_memset (buf, 0, buf_size);
if (!fgets (buf, buf_size, stdin))
{
fclose (in);
if (in != stdin)
fclose (in);
return 0;
}
ptr = buf + strlen (buf) - 1;
@ -67,7 +68,8 @@ grub_password_get (char buf[], unsigned buf_size)
grub_xputs ("\n");
grub_refresh ();
fclose (in);
if (in != stdin)
fclose (in);
return 1;
}

View file

@ -249,7 +249,7 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
if (embed_type != GRUB_EMBED_PCBIOS)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"PC-style partitions curently support "
"PC-style partitions currently support "
"only PC-BIOS embedding");
if (disk->partition)

View file

@ -104,26 +104,12 @@ const unsigned efi_codes[] =
GRUB_TERM_KEY_DC, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_F1,
GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5,
GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9,
GRUB_TERM_KEY_F10, 0, 0, '\e'
GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, '\e'
};
static int
grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
grub_efi_translate_key (grub_efi_input_key_t key)
{
grub_efi_simple_input_interface_t *i;
grub_efi_input_key_t key;
grub_efi_status_t status;
if (grub_efi_is_finished)
return 0;
i = grub_efi_system_table->con_in;
status = efi_call_2 (i->read_key_stroke, i, &key);
if (status != GRUB_EFI_SUCCESS)
return GRUB_TERM_NO_KEY;
if (key.scan_code == 0)
{
/* Some firmware implementations use VT100-style codes against the spec.
@ -139,9 +125,100 @@ grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
else if (key.scan_code < ARRAY_SIZE (efi_codes))
return efi_codes[key.scan_code];
if ((key.unicode_char >= 0x20 && key.unicode_char <= 0x7f)
|| key.unicode_char == '\t' || key.unicode_char == '\b'
|| key.unicode_char == '\n' || key.unicode_char == '\r')
return key.unicode_char;
return GRUB_TERM_NO_KEY;
}
static int
grub_console_getkey_con (struct grub_term_input *term __attribute__ ((unused)))
{
grub_efi_simple_input_interface_t *i;
grub_efi_input_key_t key;
grub_efi_status_t status;
i = grub_efi_system_table->con_in;
status = efi_call_2 (i->read_key_stroke, i, &key);
if (status != GRUB_EFI_SUCCESS)
return GRUB_TERM_NO_KEY;
return grub_efi_translate_key(key);
}
static int
grub_console_getkey_ex(struct grub_term_input *term)
{
grub_efi_key_data_t key_data;
grub_efi_status_t status;
grub_efi_uint32_t kss;
int key = -1;
grub_efi_simple_text_input_ex_interface_t *text_input = term->data;
status = efi_call_2 (text_input->read_key_stroke, text_input, &key_data);
if (status != GRUB_EFI_SUCCESS)
return GRUB_TERM_NO_KEY;
kss = key_data.key_state.key_shift_state;
key = grub_efi_translate_key(key_data.key);
if (key == GRUB_TERM_NO_KEY)
return GRUB_TERM_NO_KEY;
if (kss & GRUB_EFI_SHIFT_STATE_VALID)
{
if ((kss & GRUB_EFI_LEFT_SHIFT_PRESSED
|| kss & GRUB_EFI_RIGHT_SHIFT_PRESSED)
&& (key & GRUB_TERM_EXTENDED))
key |= GRUB_TERM_SHIFT;
if (kss & GRUB_EFI_LEFT_ALT_PRESSED || kss & GRUB_EFI_RIGHT_ALT_PRESSED)
key |= GRUB_TERM_ALT;
if (kss & GRUB_EFI_LEFT_CONTROL_PRESSED
|| kss & GRUB_EFI_RIGHT_CONTROL_PRESSED)
key |= GRUB_TERM_CTRL;
}
return key;
}
static grub_err_t
grub_efi_console_input_init (struct grub_term_input *term)
{
grub_efi_guid_t text_input_ex_guid =
GRUB_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
if (grub_efi_is_finished)
return 0;
grub_efi_simple_text_input_ex_interface_t *text_input = term->data;
if (text_input)
return 0;
text_input = grub_efi_open_protocol(grub_efi_system_table->console_in_handler,
&text_input_ex_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
term->data = (void *)text_input;
return 0;
}
static int
grub_console_getkey (struct grub_term_input *term)
{
if (grub_efi_is_finished)
return 0;
if (term->data)
return grub_console_getkey_ex(term);
else
return grub_console_getkey_con(term);
}
static struct grub_term_coordinate
grub_console_getwh (struct grub_term_output *term __attribute__ ((unused)))
{
@ -243,7 +320,7 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
}
static grub_err_t
grub_efi_console_init (struct grub_term_output *term)
grub_efi_console_output_init (struct grub_term_output *term)
{
grub_efi_set_text_mode (1);
grub_console_setcursor (term, 1);
@ -251,7 +328,7 @@ grub_efi_console_init (struct grub_term_output *term)
}
static grub_err_t
grub_efi_console_fini (struct grub_term_output *term)
grub_efi_console_output_fini (struct grub_term_output *term)
{
grub_console_setcursor (term, 0);
grub_efi_set_text_mode (0);
@ -262,13 +339,14 @@ static struct grub_term_input grub_console_term_input =
{
.name = "console",
.getkey = grub_console_getkey,
.init = grub_efi_console_input_init,
};
static struct grub_term_output grub_console_term_output =
{
.name = "console",
.init = grub_efi_console_init,
.fini = grub_efi_console_fini,
.init = grub_efi_console_output_init,
.fini = grub_efi_console_output_fini,
.putchar = grub_console_putchar,
.getwh = grub_console_getwh,
.getxy = grub_console_getxy,
@ -291,8 +369,8 @@ grub_console_init (void)
return;
}
grub_term_register_input ("console", &grub_console_term_input);
grub_term_register_output ("console", &grub_console_term_output);
grub_term_register_input ("console", &grub_console_term_input);
}
void

View file

@ -67,10 +67,14 @@ struct grub_acpi_fadt
grub_uint32_t dsdt_addr;
grub_uint8_t somefields1[20];
grub_uint32_t pm1a;
grub_uint8_t somefields2[64];
grub_uint8_t somefields2[8];
grub_uint32_t pmtimer;
grub_uint8_t somefields3[32];
grub_uint32_t flags;
grub_uint8_t somefields4[16];
grub_uint64_t facs_xaddr;
grub_uint64_t dsdt_xaddr;
grub_uint8_t somefields3[96];
grub_uint8_t somefields5[96];
} GRUB_PACKED;
#define GRUB_ACPI_MADT_SIGNATURE "APIC"
@ -176,9 +180,9 @@ enum
#ifndef GRUB_DSDT_TEST
struct grub_acpi_rsdp_v10 *grub_acpi_get_rsdpv1 (void);
struct grub_acpi_rsdp_v20 *grub_acpi_get_rsdpv2 (void);
struct grub_acpi_rsdp_v10 *grub_machine_acpi_get_rsdpv1 (void);
struct grub_acpi_rsdp_v20 *grub_machine_acpi_get_rsdpv2 (void);
grub_uint8_t grub_byte_checksum (void *base, grub_size_t size);
struct grub_acpi_rsdp_v10 *EXPORT_FUNC(grub_machine_acpi_get_rsdpv1) (void);
struct grub_acpi_rsdp_v20 *EXPORT_FUNC(grub_machine_acpi_get_rsdpv2) (void);
grub_uint8_t EXPORT_FUNC(grub_byte_checksum) (void *base, grub_size_t size);
grub_err_t grub_acpi_create_ebda (void);
@ -234,4 +238,7 @@ enum
GRUB_ACPI_EXTOPCODE_BANK_FIELD_OP = 0x87,
};
struct grub_acpi_fadt *
grub_acpi_find_fadt (void);
#endif /* ! GRUB_ACPI_HEADER */

View file

@ -0,0 +1,35 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2013-2015 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/>.
*/
#ifndef GRUB_FDTLOAD_CPU_HEADER
#define GRUB_FDTLOAD_CPU_HEADER 1
#include <grub/types.h>
#include <grub/err.h>
void *
grub_fdt_load (grub_size_t additional_size);
void
grub_fdt_unload (void);
grub_err_t
grub_fdt_install (void);
#define GRUB_EFI_PAGE_SHIFT 12
#define GRUB_EFI_BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT)
#endif

View file

@ -23,8 +23,6 @@
#define GRUB_ARM64_LINUX_MAGIC 0x644d5241 /* 'ARM\x64' */
#define GRUB_EFI_PAGE_SHIFT 12
#define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> GRUB_EFI_PAGE_SHIFT)
#define GRUB_EFI_PE_MAGIC 0x5A4D
/* From linux/Documentation/arm64/booting.txt */
@ -42,8 +40,6 @@ struct grub_arm64_linux_kernel_header
grub_uint32_t hdr_offset; /* Offset of PE/COFF header */
};
/* Declare the functions for getting dtb and checking/booting image */
void *grub_linux_get_fdt (void);
grub_err_t grub_arm64_uefi_check_image (struct grub_arm64_linux_kernel_header
*lh);
grub_err_t grub_arm64_uefi_boot_image (grub_addr_t addr, grub_size_t size,

View file

@ -97,6 +97,7 @@ struct grub_cryptodisk
grub_uint8_t rekey_key[64];
grub_uint64_t last_rekey;
int rekey_derived_size;
grub_disk_addr_t partition_start;
};
typedef struct grub_cryptodisk *grub_cryptodisk_t;

View file

@ -49,6 +49,9 @@
#define GRUB_EFI_MEMORY_WP 0x0000000000001000LL
#define GRUB_EFI_MEMORY_RP 0x0000000000002000LL
#define GRUB_EFI_MEMORY_XP 0x0000000000004000LL
#define GRUB_EFI_MEMORY_NV 0x0000000000008000LL
#define GRUB_EFI_MEMORY_MORE_RELIABLE 0x0000000000010000LL
#define GRUB_EFI_MEMORY_RO 0x0000000000020000LL
#define GRUB_EFI_MEMORY_RUNTIME 0x8000000000000000LL
#define GRUB_EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001
@ -111,7 +114,7 @@
{ 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
}
#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
#define GRUB_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
{ 0xdd9e7534, 0x7762, 0x4698, \
{ 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } \
}
@ -246,6 +249,51 @@
{ 0x8E, 0x8B, 0xBB, 0xA2, 0x0B, 0x1B, 0x5B, 0x75 } \
}
#define GRUB_EFI_TIANO_CUSTOM_DECOMPRESS_GUID \
{ 0xa31280ad, 0x481e, 0x41b6, \
{ 0x95, 0xe8, 0x12, 0x7f, 0x4c, 0x98, 0x47, 0x79 } \
}
#define GRUB_EFI_CRC32_GUIDED_SECTION_EXTRACTION_GUID \
{ 0xfc1bcdb0, 0x7d31, 0x49aa, \
{ 0x93, 0x6a, 0xa4, 0x60, 0x0d, 0x9d, 0xd0, 0x83 } \
}
#define GRUB_EFI_LZMA_CUSTOM_DECOMPRESS_GUID \
{ 0xee4e5898, 0x3914, 0x4259, \
{ 0x9d, 0x6e, 0xdc, 0x7b, 0xd7, 0x94, 0x03, 0xcf } \
}
#define GRUB_EFI_TSC_FREQUENCY_GUID \
{ 0xdba6a7e3, 0xbb57, 0x4be7, \
{ 0x8a, 0xf8, 0xd5, 0x78, 0xdb, 0x7e, 0x56, 0x87 } \
}
#define GRUB_EFI_SYSTEM_RESOURCE_TABLE_GUID \
{ 0xb122a263, 0x3661, 0x4f68, \
{ 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 } \
}
#define GRUB_EFI_DXE_SERVICES_TABLE_GUID \
{ 0x05ad34ba, 0x6f02, 0x4214, \
{ 0x95, 0x2e, 0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9 } \
}
#define GRUB_EFI_HOB_LIST_GUID \
{ 0x7739f24c, 0x93d7, 0x11d4, \
{ 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
}
#define GRUB_EFI_MEMORY_TYPE_INFORMATION_GUID \
{ 0x4c19049f, 0x4137, 0x4dd3, \
{ 0x9c, 0x10, 0x8b, 0x97, 0xa8, 0x3f, 0xfd, 0xfa } \
}
#define GRUB_EFI_DEBUG_IMAGE_INFO_TABLE_GUID \
{ 0x49152e77, 0x1ada, 0x4764, \
{ 0xb7, 0xa2, 0x7a, 0xfe, 0xfe, 0xd9, 0x5e, 0x8b } \
}
#define GRUB_EFI_MPS_TABLE_GUID \
{ 0xeb9d2d2f, 0x2d88, 0x11d3, \
{ 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
@ -431,6 +479,7 @@ enum grub_efi_memory_type
GRUB_EFI_MEMORY_MAPPED_IO,
GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE,
GRUB_EFI_PAL_CODE,
GRUB_EFI_PERSISTENT_MEMORY,
GRUB_EFI_MAX_MEMORY_TYPE
};
typedef enum grub_efi_memory_type grub_efi_memory_type_t;
@ -952,6 +1001,32 @@ struct grub_efi_input_key
};
typedef struct grub_efi_input_key grub_efi_input_key_t;
typedef grub_efi_uint8_t grub_efi_key_toggle_state_t;
struct grub_efi_key_state
{
grub_efi_uint32_t key_shift_state;
grub_efi_key_toggle_state_t key_toggle_state;
};
typedef struct grub_efi_key_state grub_efi_key_state_t;
#define GRUB_EFI_SHIFT_STATE_VALID 0x80000000
#define GRUB_EFI_RIGHT_SHIFT_PRESSED 0x00000001
#define GRUB_EFI_LEFT_SHIFT_PRESSED 0x00000002
#define GRUB_EFI_RIGHT_CONTROL_PRESSED 0x00000004
#define GRUB_EFI_LEFT_CONTROL_PRESSED 0x00000008
#define GRUB_EFI_RIGHT_ALT_PRESSED 0x00000010
#define GRUB_EFI_LEFT_ALT_PRESSED 0x00000020
#define GRUB_EFI_RIGHT_LOGO_PRESSED 0x00000040
#define GRUB_EFI_LEFT_LOGO_PRESSED 0x00000080
#define GRUB_EFI_MENU_KEY_PRESSED 0x00000100
#define GRUB_EFI_SYS_REQ_PRESSED 0x00000200
#define GRUB_EFI_TOGGLE_STATE_VALID 0x80
#define GRUB_EFI_KEY_STATE_EXPOSED 0x40
#define GRUB_EFI_SCROLL_LOCK_ACTIVE 0x01
#define GRUB_EFI_NUM_LOCK_ACTIVE 0x02
#define GRUB_EFI_CAPS_LOCK_ACTIVE 0x04
struct grub_efi_simple_text_output_mode
{
grub_efi_int32_t max_mode;
@ -1294,6 +1369,43 @@ struct grub_efi_simple_input_interface
};
typedef struct grub_efi_simple_input_interface grub_efi_simple_input_interface_t;
struct grub_efi_key_data {
grub_efi_input_key_t key;
grub_efi_key_state_t key_state;
};
typedef struct grub_efi_key_data grub_efi_key_data_t;
typedef grub_efi_status_t (*grub_efi_key_notify_function_t) (
grub_efi_key_data_t *key_data
);
struct grub_efi_simple_text_input_ex_interface
{
grub_efi_status_t
(*reset) (struct grub_efi_simple_text_input_ex_interface *this,
grub_efi_boolean_t extended_verification);
grub_efi_status_t
(*read_key_stroke) (struct grub_efi_simple_text_input_ex_interface *this,
grub_efi_key_data_t *key_data);
grub_efi_event_t wait_for_key;
grub_efi_status_t
(*set_state) (struct grub_efi_simple_text_input_ex_interface *this,
grub_efi_key_toggle_state_t *key_toggle_state);
grub_efi_status_t
(*register_key_notify) (struct grub_efi_simple_text_input_ex_interface *this,
grub_efi_key_data_t *key_data,
grub_efi_key_notify_function_t key_notification_function);
grub_efi_status_t
(*unregister_key_notify) (struct grub_efi_simple_text_input_ex_interface *this,
void *notification_handle);
};
typedef struct grub_efi_simple_text_input_ex_interface grub_efi_simple_text_input_ex_interface_t;
struct grub_efi_simple_text_output_interface
{
grub_efi_status_t

View file

@ -20,9 +20,35 @@
#define KERNEL_CPU_TSC_HEADER 1
#include <grub/types.h>
#include <grub/i386/cpuid.h>
void grub_tsc_init (void);
/* In ms per 2^32 ticks. */
extern grub_uint32_t EXPORT_VAR(grub_tsc_rate);
int
grub_tsc_calibrate_from_xen (void);
int
grub_tsc_calibrate_from_efi (void);
int
grub_tsc_calibrate_from_pmtimer (void);
int
grub_tsc_calibrate_from_pit (void);
/* Read the TSC value, which increments with each CPU clock cycle. */
static __inline grub_uint64_t
grub_get_tsc (void)
{
grub_uint32_t lo, hi;
grub_uint32_t a,b,c,d;
/* The CPUID instruction is a 'serializing' instruction, and
avoids out-of-order execution of the RDTSC instruction. */
grub_cpuid (0,a,b,c,d);
/* Read TSC value. We cannot use "=A", since this would use
%rax on x86_64. */
__asm__ __volatile__ ("rdtsc":"=a" (lo), "=d" (hi));
return (((grub_uint64_t) hi) << 32) | lo;
}
#endif /* ! KERNEL_CPU_TSC_HEADER */

View file

@ -30,6 +30,8 @@ typedef enum grub_memory_type
GRUB_MEMORY_ACPI = 3,
GRUB_MEMORY_NVS = 4,
GRUB_MEMORY_BADRAM = 5,
GRUB_MEMORY_PERSISTENT = 7,
GRUB_MEMORY_PERSISTENT_LEGACY = 12,
GRUB_MEMORY_COREBOOT_TABLES = 16,
GRUB_MEMORY_CODE = 20,
/* This one is special: it's used internally but is never reported

18
include/grub/mips/asm.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef GRUB_MIPS_ASM_HEADER
#define GRUB_MIPS_ASM_HEADER 1
#if defined(_MIPS_SIM) && defined(_ABIN32) && _MIPS_SIM == _ABIN32
#define GRUB_ASM_T4 $a4
#define GRUB_ASM_T5 $a5
#define GRUB_ASM_SZREG 8
#define GRUB_ASM_REG_S sd
#define GRUB_ASM_REG_L ld
#else
#define GRUB_ASM_T4 $t4
#define GRUB_ASM_T5 $t5
#define GRUB_ASM_SZREG 4
#define GRUB_ASM_REG_S sw
#define GRUB_ASM_REG_L lw
#endif
#endif

View file

@ -19,7 +19,7 @@
#ifndef GRUB_SETJMP_CPU_HEADER
#define GRUB_SETJMP_CPU_HEADER 1
typedef unsigned long grub_jmp_buf[12];
typedef grub_uint64_t grub_jmp_buf[12];
int grub_setjmp (grub_jmp_buf env) RETURNS_TWICE;
void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn));

View file

@ -39,7 +39,7 @@
{ "locales", GRUB_INSTALL_OPTIONS_INSTALL_LOCALES, N_("LOCALES"),\
0, N_("install only LOCALES [default=all]"), 1 }, \
{ "compress", GRUB_INSTALL_OPTIONS_INSTALL_COMPRESS, \
"no,xz,gz,lzo", OPTION_ARG_OPTIONAL, \
"no|xz|gz|lzo", 0, \
N_("compress GRUB files [optional]"), 1 }, \
{"core-compress", GRUB_INSTALL_OPTIONS_INSTALL_CORE_COMPRESS, \
"xz|none|auto", \

View file

@ -33,7 +33,12 @@
#include <grub/err.h>
#ifndef GRUB_SYMBOL_GENERATOR
#include <stdint.h>
typedef grub_int8_t int8_t;
typedef grub_int16_t int16_t;
typedef grub_uint8_t uint8_t;
typedef grub_uint16_t uint16_t;
typedef grub_uint32_t uint32_t;
typedef grub_uint64_t uint64_t;
#include <xen/xen.h>
#include <xen/sched.h>

View file

@ -0,0 +1,171 @@
/******************************************************************************
* xen-x86_32.h
*
* Guest OS interface to x86 32-bit Xen.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2004-2007, K A Fraser
*/
#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
#define __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
/*
* Hypercall interface:
* Input: %ebx, %ecx, %edx, %esi, %edi, %ebp (arguments 1-6)
* Output: %eax
* Access is via hypercall page (set up by guest loader or via a Xen MSR):
* call hypercall_page + hypercall-number * 32
* Clobbered: Argument registers (e.g., 2-arg hypercall clobbers %ebx,%ecx)
*/
/*
* These flat segments are in the Xen-private section of every GDT. Since these
* are also present in the initial GDT, many OSes will be able to avoid
* installing their own GDT.
*/
#define FLAT_RING1_CS 0xe019 /* GDT index 259 */
#define FLAT_RING1_DS 0xe021 /* GDT index 260 */
#define FLAT_RING1_SS 0xe021 /* GDT index 260 */
#define FLAT_RING3_CS 0xe02b /* GDT index 261 */
#define FLAT_RING3_DS 0xe033 /* GDT index 262 */
#define FLAT_RING3_SS 0xe033 /* GDT index 262 */
#define FLAT_KERNEL_CS FLAT_RING1_CS
#define FLAT_KERNEL_DS FLAT_RING1_DS
#define FLAT_KERNEL_SS FLAT_RING1_SS
#define FLAT_USER_CS FLAT_RING3_CS
#define FLAT_USER_DS FLAT_RING3_DS
#define FLAT_USER_SS FLAT_RING3_SS
#define __HYPERVISOR_VIRT_START_PAE 0xF5800000
#define __MACH2PHYS_VIRT_START_PAE 0xF5800000
#define __MACH2PHYS_VIRT_END_PAE 0xF6800000
#define HYPERVISOR_VIRT_START_PAE \
mk_unsigned_long(__HYPERVISOR_VIRT_START_PAE)
#define MACH2PHYS_VIRT_START_PAE \
mk_unsigned_long(__MACH2PHYS_VIRT_START_PAE)
#define MACH2PHYS_VIRT_END_PAE \
mk_unsigned_long(__MACH2PHYS_VIRT_END_PAE)
/* Non-PAE bounds are obsolete. */
#define __HYPERVISOR_VIRT_START_NONPAE 0xFC000000
#define __MACH2PHYS_VIRT_START_NONPAE 0xFC000000
#define __MACH2PHYS_VIRT_END_NONPAE 0xFC400000
#define HYPERVISOR_VIRT_START_NONPAE \
mk_unsigned_long(__HYPERVISOR_VIRT_START_NONPAE)
#define MACH2PHYS_VIRT_START_NONPAE \
mk_unsigned_long(__MACH2PHYS_VIRT_START_NONPAE)
#define MACH2PHYS_VIRT_END_NONPAE \
mk_unsigned_long(__MACH2PHYS_VIRT_END_NONPAE)
#define __HYPERVISOR_VIRT_START __HYPERVISOR_VIRT_START_PAE
#define __MACH2PHYS_VIRT_START __MACH2PHYS_VIRT_START_PAE
#define __MACH2PHYS_VIRT_END __MACH2PHYS_VIRT_END_PAE
#ifndef HYPERVISOR_VIRT_START
#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
#endif
#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START)
#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END)
#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>2)
#ifndef machine_to_phys_mapping
#define machine_to_phys_mapping ((unsigned long *)MACH2PHYS_VIRT_START)
#endif
/* 32-/64-bit invariability for control interfaces (domctl/sysctl). */
#if defined(__XEN__) || defined(__XEN_TOOLS__)
#undef ___DEFINE_XEN_GUEST_HANDLE
#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
typedef struct { type *p; } \
__guest_handle_ ## name; \
typedef struct { union { type *p; uint64_aligned_t q; }; } \
__guest_handle_64_ ## name
#undef set_xen_guest_handle_raw
#define set_xen_guest_handle_raw(hnd, val) \
do { if ( sizeof(hnd) == 8 ) *(uint64_t *)&(hnd) = 0; \
(hnd).p = val; \
} while ( 0 )
#define uint64_aligned_t uint64_t __attribute__((aligned(8)))
#define __XEN_GUEST_HANDLE_64(name) __guest_handle_64_ ## name
#define XEN_GUEST_HANDLE_64(name) __XEN_GUEST_HANDLE_64(name)
#endif
#ifndef __ASSEMBLY__
struct cpu_user_regs {
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
uint32_t esi;
uint32_t edi;
uint32_t ebp;
uint32_t eax;
uint16_t error_code; /* private */
uint16_t entry_vector; /* private */
uint32_t eip;
uint16_t cs;
uint8_t saved_upcall_mask;
uint8_t _pad0;
uint32_t eflags; /* eflags.IF == !saved_upcall_mask */
uint32_t esp;
uint16_t ss, _pad1;
uint16_t es, _pad2;
uint16_t ds, _pad3;
uint16_t fs, _pad4;
uint16_t gs, _pad5;
};
typedef struct cpu_user_regs cpu_user_regs_t;
DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
/*
* Page-directory addresses above 4GB do not fit into architectural %cr3.
* When accessing %cr3, or equivalent field in vcpu_guest_context, guests
* must use the following accessor macros to pack/unpack valid MFNs.
*/
#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20))
#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20))
struct arch_vcpu_info {
unsigned long cr2;
unsigned long pad[5]; /* sizeof(vcpu_info_t) == 64 */
};
typedef struct arch_vcpu_info arch_vcpu_info_t;
struct xen_callback {
unsigned long cs;
unsigned long eip;
};
typedef struct xen_callback xen_callback_t;
#endif /* !__ASSEMBLY__ */
#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/

View file

@ -0,0 +1,202 @@
/******************************************************************************
* xen-x86_64.h
*
* Guest OS interface to x86 64-bit Xen.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2004-2006, K A Fraser
*/
#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
#define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
/*
* Hypercall interface:
* Input: %rdi, %rsi, %rdx, %r10, %r8, %r9 (arguments 1-6)
* Output: %rax
* Access is via hypercall page (set up by guest loader or via a Xen MSR):
* call hypercall_page + hypercall-number * 32
* Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi)
*/
/*
* 64-bit segment selectors
* These flat segments are in the Xen-private section of every GDT. Since these
* are also present in the initial GDT, many OSes will be able to avoid
* installing their own GDT.
*/
#define FLAT_RING3_CS32 0xe023 /* GDT index 260 */
#define FLAT_RING3_CS64 0xe033 /* GDT index 261 */
#define FLAT_RING3_DS32 0xe02b /* GDT index 262 */
#define FLAT_RING3_DS64 0x0000 /* NULL selector */
#define FLAT_RING3_SS32 0xe02b /* GDT index 262 */
#define FLAT_RING3_SS64 0xe02b /* GDT index 262 */
#define FLAT_KERNEL_DS64 FLAT_RING3_DS64
#define FLAT_KERNEL_DS32 FLAT_RING3_DS32
#define FLAT_KERNEL_DS FLAT_KERNEL_DS64
#define FLAT_KERNEL_CS64 FLAT_RING3_CS64
#define FLAT_KERNEL_CS32 FLAT_RING3_CS32
#define FLAT_KERNEL_CS FLAT_KERNEL_CS64
#define FLAT_KERNEL_SS64 FLAT_RING3_SS64
#define FLAT_KERNEL_SS32 FLAT_RING3_SS32
#define FLAT_KERNEL_SS FLAT_KERNEL_SS64
#define FLAT_USER_DS64 FLAT_RING3_DS64
#define FLAT_USER_DS32 FLAT_RING3_DS32
#define FLAT_USER_DS FLAT_USER_DS64
#define FLAT_USER_CS64 FLAT_RING3_CS64
#define FLAT_USER_CS32 FLAT_RING3_CS32
#define FLAT_USER_CS FLAT_USER_CS64
#define FLAT_USER_SS64 FLAT_RING3_SS64
#define FLAT_USER_SS32 FLAT_RING3_SS32
#define FLAT_USER_SS FLAT_USER_SS64
#define __HYPERVISOR_VIRT_START 0xFFFF800000000000
#define __HYPERVISOR_VIRT_END 0xFFFF880000000000
#define __MACH2PHYS_VIRT_START 0xFFFF800000000000
#define __MACH2PHYS_VIRT_END 0xFFFF804000000000
#ifndef HYPERVISOR_VIRT_START
#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
#define HYPERVISOR_VIRT_END mk_unsigned_long(__HYPERVISOR_VIRT_END)
#endif
#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START)
#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END)
#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3)
#ifndef machine_to_phys_mapping
#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
#endif
/*
* int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
* @which == SEGBASE_* ; @base == 64-bit base address
* Returns 0 on success.
*/
#define SEGBASE_FS 0
#define SEGBASE_GS_USER 1
#define SEGBASE_GS_KERNEL 2
#define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */
/*
* int HYPERVISOR_iret(void)
* All arguments are on the kernel stack, in the following format.
* Never returns if successful. Current kernel context is lost.
* The saved CS is mapped as follows:
* RING0 -> RING3 kernel mode.
* RING1 -> RING3 kernel mode.
* RING2 -> RING3 kernel mode.
* RING3 -> RING3 user mode.
* However RING0 indicates that the guest kernel should return to iteself
* directly with
* orb $3,1*8(%rsp)
* iretq
* If flags contains VGCF_in_syscall:
* Restore RAX, RIP, RFLAGS, RSP.
* Discard R11, RCX, CS, SS.
* Otherwise:
* Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP.
* All other registers are saved on hypercall entry and restored to user.
*/
/* Guest exited in SYSCALL context? Return to guest with SYSRET? */
#define _VGCF_in_syscall 8
#define VGCF_in_syscall (1<<_VGCF_in_syscall)
#define VGCF_IN_SYSCALL VGCF_in_syscall
#ifndef __ASSEMBLY__
struct iret_context {
/* Top of stack (%rsp at point of hypercall). */
uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
/* Bottom of iret stack frame. */
};
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
#define __DECL_REG(name) union { \
uint64_t r ## name, e ## name; \
uint32_t _e ## name; \
}
#else
/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
#define __DECL_REG(name) uint64_t r ## name
#endif
struct cpu_user_regs {
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
__DECL_REG(bp);
__DECL_REG(bx);
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
__DECL_REG(ax);
__DECL_REG(cx);
__DECL_REG(dx);
__DECL_REG(si);
__DECL_REG(di);
uint32_t error_code; /* private */
uint32_t entry_vector; /* private */
__DECL_REG(ip);
uint16_t cs, _pad0[1];
uint8_t saved_upcall_mask;
uint8_t _pad1[3];
__DECL_REG(flags); /* rflags.IF == !saved_upcall_mask */
__DECL_REG(sp);
uint16_t ss, _pad2[3];
uint16_t es, _pad3[3];
uint16_t ds, _pad4[3];
uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base. */
uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */
};
typedef struct cpu_user_regs cpu_user_regs_t;
DEFINE_XEN_GUEST_HANDLE(cpu_user_regs_t);
#undef __DECL_REG
#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12)
struct arch_vcpu_info {
unsigned long cr2;
unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
};
typedef struct arch_vcpu_info arch_vcpu_info_t;
typedef unsigned long xen_callback_t;
#endif /* !__ASSEMBLY__ */
#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/

273
include/xen/arch-x86/xen.h Normal file
View file

@ -0,0 +1,273 @@
/******************************************************************************
* arch-x86/xen.h
*
* Guest OS interface to x86 Xen.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2004-2006, K A Fraser
*/
#include "../xen.h"
#ifndef __XEN_PUBLIC_ARCH_X86_XEN_H__
#define __XEN_PUBLIC_ARCH_X86_XEN_H__
/* Structural guest handles introduced in 0x00030201. */
#if __XEN_INTERFACE_VERSION__ >= 0x00030201
#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
typedef struct { type *p; } __guest_handle_ ## name
#else
#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
typedef type * __guest_handle_ ## name
#endif
/*
* XEN_GUEST_HANDLE represents a guest pointer, when passed as a field
* in a struct in memory.
* XEN_GUEST_HANDLE_PARAM represent a guest pointer, when passed as an
* hypercall argument.
* XEN_GUEST_HANDLE_PARAM and XEN_GUEST_HANDLE are the same on X86 but
* they might not be on other architectures.
*/
#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
___DEFINE_XEN_GUEST_HANDLE(name, type); \
___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
#define __XEN_GUEST_HANDLE(name) __guest_handle_ ## name
#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name)
#define XEN_GUEST_HANDLE_PARAM(name) XEN_GUEST_HANDLE(name)
#define set_xen_guest_handle_raw(hnd, val) do { (hnd).p = val; } while (0)
#ifdef __XEN_TOOLS__
#define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0)
#endif
#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val)
#if defined(__i386__)
#include "xen-x86_32.h"
#elif defined(__x86_64__)
#include "xen-x86_64.h"
#endif
#ifndef __ASSEMBLY__
typedef unsigned long xen_pfn_t;
#define PRI_xen_pfn "lx"
#endif
#define XEN_HAVE_PV_GUEST_ENTRY 1
#define XEN_HAVE_PV_UPCALL_MASK 1
/*
* `incontents 200 segdesc Segment Descriptor Tables
*/
/*
* ` enum neg_errnoval
* ` HYPERVISOR_set_gdt(const xen_pfn_t frames[], unsigned int entries);
* `
*/
/*
* A number of GDT entries are reserved by Xen. These are not situated at the
* start of the GDT because some stupid OSes export hard-coded selector values
* in their ABI. These hard-coded values are always near the start of the GDT,
* so Xen places itself out of the way, at the far end of the GDT.
*
* NB The LDT is set using the MMUEXT_SET_LDT op of HYPERVISOR_mmuext_op
*/
#define FIRST_RESERVED_GDT_PAGE 14
#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096)
#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8)
/*
* ` enum neg_errnoval
* ` HYPERVISOR_update_descriptor(u64 pa, u64 desc);
* `
* ` @pa The machine physical address of the descriptor to
* ` update. Must be either a descriptor page or writable.
* ` @desc The descriptor value to update, in the same format as a
* ` native descriptor table entry.
*/
/* Maximum number of virtual CPUs in legacy multi-processor guests. */
#define XEN_LEGACY_MAX_VCPUS 32
#ifndef __ASSEMBLY__
typedef unsigned long xen_ulong_t;
#define PRI_xen_ulong "lx"
/*
* ` enum neg_errnoval
* ` HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp);
* `
* Sets the stack segment and pointer for the current vcpu.
*/
/*
* ` enum neg_errnoval
* ` HYPERVISOR_set_trap_table(const struct trap_info traps[]);
* `
*/
/*
* Send an array of these to HYPERVISOR_set_trap_table().
* Terminate the array with a sentinel entry, with traps[].address==0.
* The privilege level specifies which modes may enter a trap via a software
* interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate
* privilege levels as follows:
* Level == 0: Noone may enter
* Level == 1: Kernel may enter
* Level == 2: Kernel may enter
* Level == 3: Everyone may enter
*/
#define TI_GET_DPL(_ti) ((_ti)->flags & 3)
#define TI_GET_IF(_ti) ((_ti)->flags & 4)
#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl))
#define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2))
struct trap_info {
uint8_t vector; /* exception vector */
uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */
uint16_t cs; /* code selector */
unsigned long address; /* code offset */
};
typedef struct trap_info trap_info_t;
DEFINE_XEN_GUEST_HANDLE(trap_info_t);
typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
/*
* The following is all CPU context. Note that the fpu_ctxt block is filled
* in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
*
* Also note that when calling DOMCTL_setvcpucontext and VCPU_initialise
* for HVM and PVH guests, not all information in this structure is updated:
*
* - For HVM guests, the structures read include: fpu_ctxt (if
* VGCT_I387_VALID is set), flags, user_regs, debugreg[*]
*
* - PVH guests are the same as HVM guests, but additionally use ctrlreg[3] to
* set cr3. All other fields not used should be set to 0.
*/
struct vcpu_guest_context {
/* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
#define VGCF_I387_VALID (1<<0)
#define VGCF_IN_KERNEL (1<<2)
#define _VGCF_i387_valid 0
#define VGCF_i387_valid (1<<_VGCF_i387_valid)
#define _VGCF_in_kernel 2
#define VGCF_in_kernel (1<<_VGCF_in_kernel)
#define _VGCF_failsafe_disables_events 3
#define VGCF_failsafe_disables_events (1<<_VGCF_failsafe_disables_events)
#define _VGCF_syscall_disables_events 4
#define VGCF_syscall_disables_events (1<<_VGCF_syscall_disables_events)
#define _VGCF_online 5
#define VGCF_online (1<<_VGCF_online)
unsigned long flags; /* VGCF_* flags */
struct cpu_user_regs user_regs; /* User-level CPU registers */
struct trap_info trap_ctxt[256]; /* Virtual IDT */
unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */
unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */
/* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */
unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */
#ifdef __i386__
unsigned long event_callback_cs; /* CS:EIP of event callback */
unsigned long event_callback_eip;
unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */
unsigned long failsafe_callback_eip;
#else
unsigned long event_callback_eip;
unsigned long failsafe_callback_eip;
#ifdef __XEN__
union {
unsigned long syscall_callback_eip;
struct {
unsigned int event_callback_cs; /* compat CS of event cb */
unsigned int failsafe_callback_cs; /* compat CS of failsafe cb */
};
};
#else
unsigned long syscall_callback_eip;
#endif
#endif
unsigned long vm_assist; /* VMASST_TYPE_* bitmap */
#ifdef __x86_64__
/* Segment base addresses. */
uint64_t fs_base;
uint64_t gs_base_kernel;
uint64_t gs_base_user;
#endif
};
typedef struct vcpu_guest_context vcpu_guest_context_t;
DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
struct arch_shared_info {
unsigned long max_pfn; /* max pfn that appears in table */
/* Frame containing list of mfns containing list of mfns containing p2m. */
xen_pfn_t pfn_to_mfn_frame_list_list;
unsigned long nmi_reason;
uint64_t pad[32];
};
typedef struct arch_shared_info arch_shared_info_t;
#endif /* !__ASSEMBLY__ */
/*
* ` enum neg_errnoval
* ` HYPERVISOR_fpu_taskswitch(int set);
* `
* Sets (if set!=0) or clears (if set==0) CR0.TS.
*/
/*
* ` enum neg_errnoval
* ` HYPERVISOR_set_debugreg(int regno, unsigned long value);
*
* ` unsigned long
* ` HYPERVISOR_get_debugreg(int regno);
* For 0<=reg<=7, returns the debug register value.
* For other values of reg, returns ((unsigned long)-EINVAL).
* (Unfortunately, this interface is defective.)
*/
/*
* Prefix forces emulation of some non-trapping instructions.
* Currently only CPUID.
*/
#ifdef __ASSEMBLY__
#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ;
#define XEN_CPUID XEN_EMULATE_PREFIX cpuid
#else
#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; "
#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid"
#endif
#endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/

381
include/xen/event_channel.h Normal file
View file

@ -0,0 +1,381 @@
/******************************************************************************
* event_channel.h
*
* Event channels between domains.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2003-2004, K A Fraser.
*/
#ifndef __XEN_PUBLIC_EVENT_CHANNEL_H__
#define __XEN_PUBLIC_EVENT_CHANNEL_H__
#include "xen.h"
/*
* `incontents 150 evtchn Event Channels
*
* Event channels are the basic primitive provided by Xen for event
* notifications. An event is the Xen equivalent of a hardware
* interrupt. They essentially store one bit of information, the event
* of interest is signalled by transitioning this bit from 0 to 1.
*
* Notifications are received by a guest via an upcall from Xen,
* indicating when an event arrives (setting the bit). Further
* notifications are masked until the bit is cleared again (therefore,
* guests must check the value of the bit after re-enabling event
* delivery to ensure no missed notifications).
*
* Event notifications can be masked by setting a flag; this is
* equivalent to disabling interrupts and can be used to ensure
* atomicity of certain operations in the guest kernel.
*
* Event channels are represented by the evtchn_* fields in
* struct shared_info and struct vcpu_info.
*/
/*
* ` enum neg_errnoval
* ` HYPERVISOR_event_channel_op(enum event_channel_op cmd, void *args)
* `
* @cmd == EVTCHNOP_* (event-channel operation).
* @args == struct evtchn_* Operation-specific extra arguments (NULL if none).
*/
/* ` enum event_channel_op { // EVTCHNOP_* => struct evtchn_* */
#define EVTCHNOP_bind_interdomain 0
#define EVTCHNOP_bind_virq 1
#define EVTCHNOP_bind_pirq 2
#define EVTCHNOP_close 3
#define EVTCHNOP_send 4
#define EVTCHNOP_status 5
#define EVTCHNOP_alloc_unbound 6
#define EVTCHNOP_bind_ipi 7
#define EVTCHNOP_bind_vcpu 8
#define EVTCHNOP_unmask 9
#define EVTCHNOP_reset 10
#define EVTCHNOP_init_control 11
#define EVTCHNOP_expand_array 12
#define EVTCHNOP_set_priority 13
/* ` } */
typedef uint32_t evtchn_port_t;
DEFINE_XEN_GUEST_HANDLE(evtchn_port_t);
/*
* EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
* accepting interdomain bindings from domain <remote_dom>. A fresh port
* is allocated in <dom> and returned as <port>.
* NOTES:
* 1. If the caller is unprivileged then <dom> must be DOMID_SELF.
* 2. <rdom> may be DOMID_SELF, allowing loopback connections.
*/
struct evtchn_alloc_unbound {
/* IN parameters */
domid_t dom, remote_dom;
/* OUT parameters */
evtchn_port_t port;
};
typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t;
/*
* EVTCHNOP_bind_interdomain: Construct an interdomain event channel between
* the calling domain and <remote_dom>. <remote_dom,remote_port> must identify
* a port that is unbound and marked as accepting bindings from the calling
* domain. A fresh port is allocated in the calling domain and returned as
* <local_port>.
*
* In case the peer domain has already tried to set our event channel
* pending, before it was bound, EVTCHNOP_bind_interdomain always sets
* the local event channel pending.
*
* The usual pattern of use, in the guest's upcall (or subsequent
* handler) is as follows: (Re-enable the event channel for subsequent
* signalling and then) check for the existence of whatever condition
* is being waited for by other means, and take whatever action is
* needed (if any).
*
* NOTES:
* 1. <remote_dom> may be DOMID_SELF, allowing loopback connections.
*/
struct evtchn_bind_interdomain {
/* IN parameters. */
domid_t remote_dom;
evtchn_port_t remote_port;
/* OUT parameters. */
evtchn_port_t local_port;
};
typedef struct evtchn_bind_interdomain evtchn_bind_interdomain_t;
/*
* EVTCHNOP_bind_virq: Bind a local event channel to VIRQ <irq> on specified
* vcpu.
* NOTES:
* 1. Virtual IRQs are classified as per-vcpu or global. See the VIRQ list
* in xen.h for the classification of each VIRQ.
* 2. Global VIRQs must be allocated on VCPU0 but can subsequently be
* re-bound via EVTCHNOP_bind_vcpu.
* 3. Per-vcpu VIRQs may be bound to at most one event channel per vcpu.
* The allocated event channel is bound to the specified vcpu and the
* binding cannot be changed.
*/
struct evtchn_bind_virq {
/* IN parameters. */
uint32_t virq; /* enum virq */
uint32_t vcpu;
/* OUT parameters. */
evtchn_port_t port;
};
typedef struct evtchn_bind_virq evtchn_bind_virq_t;
/*
* EVTCHNOP_bind_pirq: Bind a local event channel to a real IRQ (PIRQ <irq>).
* NOTES:
* 1. A physical IRQ may be bound to at most one event channel per domain.
* 2. Only a sufficiently-privileged domain may bind to a physical IRQ.
*/
struct evtchn_bind_pirq {
/* IN parameters. */
uint32_t pirq;
#define BIND_PIRQ__WILL_SHARE 1
uint32_t flags; /* BIND_PIRQ__* */
/* OUT parameters. */
evtchn_port_t port;
};
typedef struct evtchn_bind_pirq evtchn_bind_pirq_t;
/*
* EVTCHNOP_bind_ipi: Bind a local event channel to receive events.
* NOTES:
* 1. The allocated event channel is bound to the specified vcpu. The binding
* may not be changed.
*/
struct evtchn_bind_ipi {
uint32_t vcpu;
/* OUT parameters. */
evtchn_port_t port;
};
typedef struct evtchn_bind_ipi evtchn_bind_ipi_t;
/*
* EVTCHNOP_close: Close a local event channel <port>. If the channel is
* interdomain then the remote end is placed in the unbound state
* (EVTCHNSTAT_unbound), awaiting a new connection.
*/
struct evtchn_close {
/* IN parameters. */
evtchn_port_t port;
};
typedef struct evtchn_close evtchn_close_t;
/*
* EVTCHNOP_send: Send an event to the remote end of the channel whose local
* endpoint is <port>.
*/
struct evtchn_send {
/* IN parameters. */
evtchn_port_t port;
};
typedef struct evtchn_send evtchn_send_t;
/*
* EVTCHNOP_status: Get the current status of the communication channel which
* has an endpoint at <dom, port>.
* NOTES:
* 1. <dom> may be specified as DOMID_SELF.
* 2. Only a sufficiently-privileged domain may obtain the status of an event
* channel for which <dom> is not DOMID_SELF.
*/
struct evtchn_status {
/* IN parameters */
domid_t dom;
evtchn_port_t port;
/* OUT parameters */
#define EVTCHNSTAT_closed 0 /* Channel is not in use. */
#define EVTCHNSTAT_unbound 1 /* Channel is waiting interdom connection.*/
#define EVTCHNSTAT_interdomain 2 /* Channel is connected to remote domain. */
#define EVTCHNSTAT_pirq 3 /* Channel is bound to a phys IRQ line. */
#define EVTCHNSTAT_virq 4 /* Channel is bound to a virtual IRQ line */
#define EVTCHNSTAT_ipi 5 /* Channel is bound to a virtual IPI line */
uint32_t status;
uint32_t vcpu; /* VCPU to which this channel is bound. */
union {
struct {
domid_t dom;
} unbound; /* EVTCHNSTAT_unbound */
struct {
domid_t dom;
evtchn_port_t port;
} interdomain; /* EVTCHNSTAT_interdomain */
uint32_t pirq; /* EVTCHNSTAT_pirq */
uint32_t virq; /* EVTCHNSTAT_virq */
} u;
};
typedef struct evtchn_status evtchn_status_t;
/*
* EVTCHNOP_bind_vcpu: Specify which vcpu a channel should notify when an
* event is pending.
* NOTES:
* 1. IPI-bound channels always notify the vcpu specified at bind time.
* This binding cannot be changed.
* 2. Per-VCPU VIRQ channels always notify the vcpu specified at bind time.
* This binding cannot be changed.
* 3. All other channels notify vcpu0 by default. This default is set when
* the channel is allocated (a port that is freed and subsequently reused
* has its binding reset to vcpu0).
*/
struct evtchn_bind_vcpu {
/* IN parameters. */
evtchn_port_t port;
uint32_t vcpu;
};
typedef struct evtchn_bind_vcpu evtchn_bind_vcpu_t;
/*
* EVTCHNOP_unmask: Unmask the specified local event-channel port and deliver
* a notification to the appropriate VCPU if an event is pending.
*/
struct evtchn_unmask {
/* IN parameters. */
evtchn_port_t port;
};
typedef struct evtchn_unmask evtchn_unmask_t;
/*
* EVTCHNOP_reset: Close all event channels associated with specified domain.
* NOTES:
* 1. <dom> may be specified as DOMID_SELF.
* 2. Only a sufficiently-privileged domain may specify other than DOMID_SELF.
*/
struct evtchn_reset {
/* IN parameters. */
domid_t dom;
};
typedef struct evtchn_reset evtchn_reset_t;
/*
* EVTCHNOP_init_control: initialize the control block for the FIFO ABI.
*
* Note: any events that are currently pending will not be resent and
* will be lost. Guests should call this before binding any event to
* avoid losing any events.
*/
struct evtchn_init_control {
/* IN parameters. */
uint64_t control_gfn;
uint32_t offset;
uint32_t vcpu;
/* OUT parameters. */
uint8_t link_bits;
uint8_t _pad[7];
};
typedef struct evtchn_init_control evtchn_init_control_t;
/*
* EVTCHNOP_expand_array: add an additional page to the event array.
*/
struct evtchn_expand_array {
/* IN parameters. */
uint64_t array_gfn;
};
typedef struct evtchn_expand_array evtchn_expand_array_t;
/*
* EVTCHNOP_set_priority: set the priority for an event channel.
*/
struct evtchn_set_priority {
/* IN parameters. */
uint32_t port;
uint32_t priority;
};
typedef struct evtchn_set_priority evtchn_set_priority_t;
/*
* ` enum neg_errnoval
* ` HYPERVISOR_event_channel_op_compat(struct evtchn_op *op)
* `
* Superceded by new event_channel_op() hypercall since 0x00030202.
*/
struct evtchn_op {
uint32_t cmd; /* enum event_channel_op */
union {
struct evtchn_alloc_unbound alloc_unbound;
struct evtchn_bind_interdomain bind_interdomain;
struct evtchn_bind_virq bind_virq;
struct evtchn_bind_pirq bind_pirq;
struct evtchn_bind_ipi bind_ipi;
struct evtchn_close close;
struct evtchn_send send;
struct evtchn_status status;
struct evtchn_bind_vcpu bind_vcpu;
struct evtchn_unmask unmask;
} u;
};
typedef struct evtchn_op evtchn_op_t;
DEFINE_XEN_GUEST_HANDLE(evtchn_op_t);
/*
* 2-level ABI
*/
#define EVTCHN_2L_NR_CHANNELS (sizeof(xen_ulong_t) * sizeof(xen_ulong_t) * 64)
/*
* FIFO ABI
*/
/* Events may have priorities from 0 (highest) to 15 (lowest). */
#define EVTCHN_FIFO_PRIORITY_MAX 0
#define EVTCHN_FIFO_PRIORITY_DEFAULT 7
#define EVTCHN_FIFO_PRIORITY_MIN 15
#define EVTCHN_FIFO_MAX_QUEUES (EVTCHN_FIFO_PRIORITY_MIN + 1)
typedef uint32_t event_word_t;
#define EVTCHN_FIFO_PENDING 31
#define EVTCHN_FIFO_MASKED 30
#define EVTCHN_FIFO_LINKED 29
#define EVTCHN_FIFO_BUSY 28
#define EVTCHN_FIFO_LINK_BITS 17
#define EVTCHN_FIFO_LINK_MASK ((1 << EVTCHN_FIFO_LINK_BITS) - 1)
#define EVTCHN_FIFO_NR_CHANNELS (1 << EVTCHN_FIFO_LINK_BITS)
struct evtchn_fifo_control_block {
uint32_t ready;
uint32_t _rsvd;
uint32_t head[EVTCHN_FIFO_MAX_QUEUES];
};
typedef struct evtchn_fifo_control_block evtchn_fifo_control_block_t;
#endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/

662
include/xen/grant_table.h Normal file
View file

@ -0,0 +1,662 @@
/******************************************************************************
* grant_table.h
*
* Interface for granting foreign access to page frames, and receiving
* page-ownership transfers.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2004, K A Fraser
*/
#ifndef __XEN_PUBLIC_GRANT_TABLE_H__
#define __XEN_PUBLIC_GRANT_TABLE_H__
#include "xen.h"
/*
* `incontents 150 gnttab Grant Tables
*
* Xen's grant tables provide a generic mechanism to memory sharing
* between domains. This shared memory interface underpins the split
* device drivers for block and network IO.
*
* Each domain has its own grant table. This is a data structure that
* is shared with Xen; it allows the domain to tell Xen what kind of
* permissions other domains have on its pages. Entries in the grant
* table are identified by grant references. A grant reference is an
* integer, which indexes into the grant table. It acts as a
* capability which the grantee can use to perform operations on the
* granters memory.
*
* This capability-based system allows shared-memory communications
* between unprivileged domains. A grant reference also encapsulates
* the details of a shared page, removing the need for a domain to
* know the real machine address of a page it is sharing. This makes
* it possible to share memory correctly with domains running in
* fully virtualised memory.
*/
/***********************************
* GRANT TABLE REPRESENTATION
*/
/* Some rough guidelines on accessing and updating grant-table entries
* in a concurrency-safe manner. For more information, Linux contains a
* reference implementation for guest OSes (drivers/xen/grant_table.c, see
* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/xen/grant-table.c;hb=HEAD
*
* NB. WMB is a no-op on current-generation x86 processors. However, a
* compiler barrier will still be required.
*
* Introducing a valid entry into the grant table:
* 1. Write ent->domid.
* 2. Write ent->frame:
* GTF_permit_access: Frame to which access is permitted.
* GTF_accept_transfer: Pseudo-phys frame slot being filled by new
* frame, or zero if none.
* 3. Write memory barrier (WMB).
* 4. Write ent->flags, inc. valid type.
*
* Invalidating an unused GTF_permit_access entry:
* 1. flags = ent->flags.
* 2. Observe that !(flags & (GTF_reading|GTF_writing)).
* 3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
* NB. No need for WMB as reuse of entry is control-dependent on success of
* step 3, and all architectures guarantee ordering of ctrl-dep writes.
*
* Invalidating an in-use GTF_permit_access entry:
* This cannot be done directly. Request assistance from the domain controller
* which can set a timeout on the use of a grant entry and take necessary
* action. (NB. This is not yet implemented!).
*
* Invalidating an unused GTF_accept_transfer entry:
* 1. flags = ent->flags.
* 2. Observe that !(flags & GTF_transfer_committed). [*]
* 3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
* NB. No need for WMB as reuse of entry is control-dependent on success of
* step 3, and all architectures guarantee ordering of ctrl-dep writes.
* [*] If GTF_transfer_committed is set then the grant entry is 'committed'.
* The guest must /not/ modify the grant entry until the address of the
* transferred frame is written. It is safe for the guest to spin waiting
* for this to occur (detect by observing GTF_transfer_completed in
* ent->flags).
*
* Invalidating a committed GTF_accept_transfer entry:
* 1. Wait for (ent->flags & GTF_transfer_completed).
*
* Changing a GTF_permit_access from writable to read-only:
* Use SMP-safe CMPXCHG to set GTF_readonly, while checking !GTF_writing.
*
* Changing a GTF_permit_access from read-only to writable:
* Use SMP-safe bit-setting instruction.
*/
/*
* Reference to a grant entry in a specified domain's grant table.
*/
typedef uint32_t grant_ref_t;
/*
* A grant table comprises a packed array of grant entries in one or more
* page frames shared between Xen and a guest.
* [XEN]: This field is written by Xen and read by the sharing guest.
* [GST]: This field is written by the guest and read by Xen.
*/
/*
* Version 1 of the grant table entry structure is maintained purely
* for backwards compatibility. New guests should use version 2.
*/
#if __XEN_INTERFACE_VERSION__ < 0x0003020a
#define grant_entry_v1 grant_entry
#define grant_entry_v1_t grant_entry_t
#endif
struct grant_entry_v1 {
/* GTF_xxx: various type and flag information. [XEN,GST] */
uint16_t flags;
/* The domain being granted foreign privileges. [GST] */
domid_t domid;
/*
* GTF_permit_access: Frame that @domid is allowed to map and access. [GST]
* GTF_accept_transfer: Frame whose ownership transferred by @domid. [XEN]
*/
uint32_t frame;
};
typedef struct grant_entry_v1 grant_entry_v1_t;
/* The first few grant table entries will be preserved across grant table
* version changes and may be pre-populated at domain creation by tools.
*/
#define GNTTAB_NR_RESERVED_ENTRIES 8
#define GNTTAB_RESERVED_CONSOLE 0
#define GNTTAB_RESERVED_XENSTORE 1
/*
* Type of grant entry.
* GTF_invalid: This grant entry grants no privileges.
* GTF_permit_access: Allow @domid to map/access @frame.
* GTF_accept_transfer: Allow @domid to transfer ownership of one page frame
* to this guest. Xen writes the page number to @frame.
* GTF_transitive: Allow @domid to transitively access a subrange of
* @trans_grant in @trans_domid. No mappings are allowed.
*/
#define GTF_invalid (0U<<0)
#define GTF_permit_access (1U<<0)
#define GTF_accept_transfer (2U<<0)
#define GTF_transitive (3U<<0)
#define GTF_type_mask (3U<<0)
/*
* Subflags for GTF_permit_access.
* GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST]
* GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
* GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
* GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags for the grant [GST]
* GTF_sub_page: Grant access to only a subrange of the page. @domid
* will only be allowed to copy from the grant, and not
* map it. [GST]
*/
#define _GTF_readonly (2)
#define GTF_readonly (1U<<_GTF_readonly)
#define _GTF_reading (3)
#define GTF_reading (1U<<_GTF_reading)
#define _GTF_writing (4)
#define GTF_writing (1U<<_GTF_writing)
#define _GTF_PWT (5)
#define GTF_PWT (1U<<_GTF_PWT)
#define _GTF_PCD (6)
#define GTF_PCD (1U<<_GTF_PCD)
#define _GTF_PAT (7)
#define GTF_PAT (1U<<_GTF_PAT)
#define _GTF_sub_page (8)
#define GTF_sub_page (1U<<_GTF_sub_page)
/*
* Subflags for GTF_accept_transfer:
* GTF_transfer_committed: Xen sets this flag to indicate that it is committed
* to transferring ownership of a page frame. When a guest sees this flag
* it must /not/ modify the grant entry until GTF_transfer_completed is
* set by Xen.
* GTF_transfer_completed: It is safe for the guest to spin-wait on this flag
* after reading GTF_transfer_committed. Xen will always write the frame
* address, followed by ORing this flag, in a timely manner.
*/
#define _GTF_transfer_committed (2)
#define GTF_transfer_committed (1U<<_GTF_transfer_committed)
#define _GTF_transfer_completed (3)
#define GTF_transfer_completed (1U<<_GTF_transfer_completed)
/*
* Version 2 grant table entries. These fulfil the same role as
* version 1 entries, but can represent more complicated operations.
* Any given domain will have either a version 1 or a version 2 table,
* and every entry in the table will be the same version.
*
* The interface by which domains use grant references does not depend
* on the grant table version in use by the other domain.
*/
#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
/*
* Version 1 and version 2 grant entries share a common prefix. The
* fields of the prefix are documented as part of struct
* grant_entry_v1.
*/
struct grant_entry_header {
uint16_t flags;
domid_t domid;
};
typedef struct grant_entry_header grant_entry_header_t;
/*
* Version 2 of the grant entry structure.
*/
union grant_entry_v2 {
grant_entry_header_t hdr;
/*
* This member is used for V1-style full page grants, where either:
*
* -- hdr.type is GTF_accept_transfer, or
* -- hdr.type is GTF_permit_access and GTF_sub_page is not set.
*
* In that case, the frame field has the same semantics as the
* field of the same name in the V1 entry structure.
*/
struct {
grant_entry_header_t hdr;
uint32_t pad0;
uint64_t frame;
} full_page;
/*
* If the grant type is GTF_grant_access and GTF_sub_page is set,
* @domid is allowed to access bytes [@page_off,@page_off+@length)
* in frame @frame.
*/
struct {
grant_entry_header_t hdr;
uint16_t page_off;
uint16_t length;
uint64_t frame;
} sub_page;
/*
* If the grant is GTF_transitive, @domid is allowed to use the
* grant @gref in domain @trans_domid, as if it was the local
* domain. Obviously, the transitive access must be compatible
* with the original grant.
*
* The current version of Xen does not allow transitive grants
* to be mapped.
*/
struct {
grant_entry_header_t hdr;
domid_t trans_domid;
uint16_t pad0;
grant_ref_t gref;
} transitive;
uint32_t __spacer[4]; /* Pad to a power of two */
};
typedef union grant_entry_v2 grant_entry_v2_t;
typedef uint16_t grant_status_t;
#endif /* __XEN_INTERFACE_VERSION__ */
/***********************************
* GRANT TABLE QUERIES AND USES
*/
/* ` enum neg_errnoval
* ` HYPERVISOR_grant_table_op(enum grant_table_op cmd,
* ` void *args,
* ` unsigned int count)
* `
*
* @args points to an array of a per-command data structure. The array
* has @count members
*/
/* ` enum grant_table_op { // GNTTABOP_* => struct gnttab_* */
#define GNTTABOP_map_grant_ref 0
#define GNTTABOP_unmap_grant_ref 1
#define GNTTABOP_setup_table 2
#define GNTTABOP_dump_table 3
#define GNTTABOP_transfer 4
#define GNTTABOP_copy 5
#define GNTTABOP_query_size 6
#define GNTTABOP_unmap_and_replace 7
#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
#define GNTTABOP_set_version 8
#define GNTTABOP_get_status_frames 9
#define GNTTABOP_get_version 10
#define GNTTABOP_swap_grant_ref 11
#endif /* __XEN_INTERFACE_VERSION__ */
/* ` } */
/*
* Handle to track a mapping created via a grant reference.
*/
typedef uint32_t grant_handle_t;
/*
* GNTTABOP_map_grant_ref: Map the grant entry (<dom>,<ref>) for access
* by devices and/or host CPUs. If successful, <handle> is a tracking number
* that must be presented later to destroy the mapping(s). On error, <handle>
* is a negative status code.
* NOTES:
* 1. If GNTMAP_device_map is specified then <dev_bus_addr> is the address
* via which I/O devices may access the granted frame.
* 2. If GNTMAP_host_map is specified then a mapping will be added at
* either a host virtual address in the current address space, or at
* a PTE at the specified machine address. The type of mapping to
* perform is selected through the GNTMAP_contains_pte flag, and the
* address is specified in <host_addr>.
* 3. Mappings should only be destroyed via GNTTABOP_unmap_grant_ref. If a
* host mapping is destroyed by other means then it is *NOT* guaranteed
* to be accounted to the correct grant reference!
*/
struct gnttab_map_grant_ref {
/* IN parameters. */
uint64_t host_addr;
uint32_t flags; /* GNTMAP_* */
grant_ref_t ref;
domid_t dom;
/* OUT parameters. */
int16_t status; /* => enum grant_status */
grant_handle_t handle;
uint64_t dev_bus_addr;
};
typedef struct gnttab_map_grant_ref gnttab_map_grant_ref_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_map_grant_ref_t);
/*
* GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
* tracked by <handle>. If <host_addr> or <dev_bus_addr> is zero, that
* field is ignored. If non-zero, they must refer to a device/host mapping
* that is tracked by <handle>
* NOTES:
* 1. The call may fail in an undefined manner if either mapping is not
* tracked by <handle>.
* 3. After executing a batch of unmaps, it is guaranteed that no stale
* mappings will remain in the device or host TLBs.
*/
struct gnttab_unmap_grant_ref {
/* IN parameters. */
uint64_t host_addr;
uint64_t dev_bus_addr;
grant_handle_t handle;
/* OUT parameters. */
int16_t status; /* => enum grant_status */
};
typedef struct gnttab_unmap_grant_ref gnttab_unmap_grant_ref_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
/*
* GNTTABOP_setup_table: Set up a grant table for <dom> comprising at least
* <nr_frames> pages. The frame addresses are written to the <frame_list>.
* Only <nr_frames> addresses are written, even if the table is larger.
* NOTES:
* 1. <dom> may be specified as DOMID_SELF.
* 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
* 3. Xen may not support more than a single grant-table page per domain.
*/
struct gnttab_setup_table {
/* IN parameters. */
domid_t dom;
uint32_t nr_frames;
/* OUT parameters. */
int16_t status; /* => enum grant_status */
#if __XEN_INTERFACE_VERSION__ < 0x00040300
XEN_GUEST_HANDLE(ulong) frame_list;
#else
XEN_GUEST_HANDLE(xen_pfn_t) frame_list;
#endif
};
typedef struct gnttab_setup_table gnttab_setup_table_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_setup_table_t);
/*
* GNTTABOP_dump_table: Dump the contents of the grant table to the
* xen console. Debugging use only.
*/
struct gnttab_dump_table {
/* IN parameters. */
domid_t dom;
/* OUT parameters. */
int16_t status; /* => enum grant_status */
};
typedef struct gnttab_dump_table gnttab_dump_table_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_dump_table_t);
/*
* GNTTABOP_transfer_grant_ref: Transfer <frame> to a foreign domain. The
* foreign domain has previously registered its interest in the transfer via
* <domid, ref>.
*
* Note that, even if the transfer fails, the specified page no longer belongs
* to the calling domain *unless* the error is GNTST_bad_page.
*/
struct gnttab_transfer {
/* IN parameters. */
xen_pfn_t mfn;
domid_t domid;
grant_ref_t ref;
/* OUT parameters. */
int16_t status;
};
typedef struct gnttab_transfer gnttab_transfer_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_transfer_t);
/*
* GNTTABOP_copy: Hypervisor based copy
* source and destinations can be eithers MFNs or, for foreign domains,
* grant references. the foreign domain has to grant read/write access
* in its grant table.
*
* The flags specify what type source and destinations are (either MFN
* or grant reference).
*
* Note that this can also be used to copy data between two domains
* via a third party if the source and destination domains had previously
* grant appropriate access to their pages to the third party.
*
* source_offset specifies an offset in the source frame, dest_offset
* the offset in the target frame and len specifies the number of
* bytes to be copied.
*/
#define _GNTCOPY_source_gref (0)
#define GNTCOPY_source_gref (1<<_GNTCOPY_source_gref)
#define _GNTCOPY_dest_gref (1)
#define GNTCOPY_dest_gref (1<<_GNTCOPY_dest_gref)
struct gnttab_copy {
/* IN parameters. */
struct {
union {
grant_ref_t ref;
xen_pfn_t gmfn;
} u;
domid_t domid;
uint16_t offset;
} source, dest;
uint16_t len;
uint16_t flags; /* GNTCOPY_* */
/* OUT parameters. */
int16_t status;
};
typedef struct gnttab_copy gnttab_copy_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_copy_t);
/*
* GNTTABOP_query_size: Query the current and maximum sizes of the shared
* grant table.
* NOTES:
* 1. <dom> may be specified as DOMID_SELF.
* 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
*/
struct gnttab_query_size {
/* IN parameters. */
domid_t dom;
/* OUT parameters. */
uint32_t nr_frames;
uint32_t max_nr_frames;
int16_t status; /* => enum grant_status */
};
typedef struct gnttab_query_size gnttab_query_size_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_query_size_t);
/*
* GNTTABOP_unmap_and_replace: Destroy one or more grant-reference mappings
* tracked by <handle> but atomically replace the page table entry with one
* pointing to the machine address under <new_addr>. <new_addr> will be
* redirected to the null entry.
* NOTES:
* 1. The call may fail in an undefined manner if either mapping is not
* tracked by <handle>.
* 2. After executing a batch of unmaps, it is guaranteed that no stale
* mappings will remain in the device or host TLBs.
*/
struct gnttab_unmap_and_replace {
/* IN parameters. */
uint64_t host_addr;
uint64_t new_addr;
grant_handle_t handle;
/* OUT parameters. */
int16_t status; /* => enum grant_status */
};
typedef struct gnttab_unmap_and_replace gnttab_unmap_and_replace_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_and_replace_t);
#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
/*
* GNTTABOP_set_version: Request a particular version of the grant
* table shared table structure. This operation can only be performed
* once in any given domain. It must be performed before any grants
* are activated; otherwise, the domain will be stuck with version 1.
* The only defined versions are 1 and 2.
*/
struct gnttab_set_version {
/* IN/OUT parameters */
uint32_t version;
};
typedef struct gnttab_set_version gnttab_set_version_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_set_version_t);
/*
* GNTTABOP_get_status_frames: Get the list of frames used to store grant
* status for <dom>. In grant format version 2, the status is separated
* from the other shared grant fields to allow more efficient synchronization
* using barriers instead of atomic cmpexch operations.
* <nr_frames> specify the size of vector <frame_list>.
* The frame addresses are returned in the <frame_list>.
* Only <nr_frames> addresses are returned, even if the table is larger.
* NOTES:
* 1. <dom> may be specified as DOMID_SELF.
* 2. Only a sufficiently-privileged domain may specify <dom> != DOMID_SELF.
*/
struct gnttab_get_status_frames {
/* IN parameters. */
uint32_t nr_frames;
domid_t dom;
/* OUT parameters. */
int16_t status; /* => enum grant_status */
XEN_GUEST_HANDLE(uint64_t) frame_list;
};
typedef struct gnttab_get_status_frames gnttab_get_status_frames_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_get_status_frames_t);
/*
* GNTTABOP_get_version: Get the grant table version which is in
* effect for domain <dom>.
*/
struct gnttab_get_version {
/* IN parameters */
domid_t dom;
uint16_t pad;
/* OUT parameters */
uint32_t version;
};
typedef struct gnttab_get_version gnttab_get_version_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_get_version_t);
/*
* GNTTABOP_swap_grant_ref: Swap the contents of two grant entries.
*/
struct gnttab_swap_grant_ref {
/* IN parameters */
grant_ref_t ref_a;
grant_ref_t ref_b;
/* OUT parameters */
int16_t status; /* => enum grant_status */
};
typedef struct gnttab_swap_grant_ref gnttab_swap_grant_ref_t;
DEFINE_XEN_GUEST_HANDLE(gnttab_swap_grant_ref_t);
#endif /* __XEN_INTERFACE_VERSION__ */
/*
* Bitfield values for gnttab_map_grant_ref.flags.
*/
/* Map the grant entry for access by I/O devices. */
#define _GNTMAP_device_map (0)
#define GNTMAP_device_map (1<<_GNTMAP_device_map)
/* Map the grant entry for access by host CPUs. */
#define _GNTMAP_host_map (1)
#define GNTMAP_host_map (1<<_GNTMAP_host_map)
/* Accesses to the granted frame will be restricted to read-only access. */
#define _GNTMAP_readonly (2)
#define GNTMAP_readonly (1<<_GNTMAP_readonly)
/*
* GNTMAP_host_map subflag:
* 0 => The host mapping is usable only by the guest OS.
* 1 => The host mapping is usable by guest OS + current application.
*/
#define _GNTMAP_application_map (3)
#define GNTMAP_application_map (1<<_GNTMAP_application_map)
/*
* GNTMAP_contains_pte subflag:
* 0 => This map request contains a host virtual address.
* 1 => This map request contains the machine addess of the PTE to update.
*/
#define _GNTMAP_contains_pte (4)
#define GNTMAP_contains_pte (1<<_GNTMAP_contains_pte)
#define _GNTMAP_can_fail (5)
#define GNTMAP_can_fail (1<<_GNTMAP_can_fail)
/*
* Bits to be placed in guest kernel available PTE bits (architecture
* dependent; only supported when XENFEAT_gnttab_map_avail_bits is set).
*/
#define _GNTMAP_guest_avail0 (16)
#define GNTMAP_guest_avail_mask ((uint32_t)~0 << _GNTMAP_guest_avail0)
/*
* Values for error status returns. All errors are -ve.
*/
/* ` enum grant_status { */
#define GNTST_okay (0) /* Normal return. */
#define GNTST_general_error (-1) /* General undefined error. */
#define GNTST_bad_domain (-2) /* Unrecognsed domain id. */
#define GNTST_bad_gntref (-3) /* Unrecognised or inappropriate gntref. */
#define GNTST_bad_handle (-4) /* Unrecognised or inappropriate handle. */
#define GNTST_bad_virt_addr (-5) /* Inappropriate virtual address to map. */
#define GNTST_bad_dev_addr (-6) /* Inappropriate device address to unmap.*/
#define GNTST_no_device_space (-7) /* Out of space in I/O MMU. */
#define GNTST_permission_denied (-8) /* Not enough privilege for operation. */
#define GNTST_bad_page (-9) /* Specified page was invalid for op. */
#define GNTST_bad_copy_arg (-10) /* copy arguments cross page boundary. */
#define GNTST_address_too_big (-11) /* transfer page address too large. */
#define GNTST_eagain (-12) /* Operation not done; try again. */
/* ` } */
#define GNTTABOP_error_msgs { \
"okay", \
"undefined error", \
"unrecognised domain id", \
"invalid grant reference", \
"invalid mapping handle", \
"invalid virtual address", \
"invalid device address", \
"no spare translation slot in the I/O MMU", \
"permission denied", \
"bad page", \
"copy arguments cross page boundary", \
"page address size too large", \
"operation not done; try again" \
}
#endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/

608
include/xen/io/blkif.h Normal file
View file

@ -0,0 +1,608 @@
/******************************************************************************
* blkif.h
*
* Unified block-device I/O interface for Xen guest OSes.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2003-2004, Keir Fraser
* Copyright (c) 2012, Spectra Logic Corporation
*/
#ifndef __XEN_PUBLIC_IO_BLKIF_H__
#define __XEN_PUBLIC_IO_BLKIF_H__
#include "ring.h"
#include "../grant_table.h"
/*
* Front->back notifications: When enqueuing a new request, sending a
* notification can be made conditional on req_event (i.e., the generic
* hold-off mechanism provided by the ring macros). Backends must set
* req_event appropriately (e.g., using RING_FINAL_CHECK_FOR_REQUESTS()).
*
* Back->front notifications: When enqueuing a new response, sending a
* notification can be made conditional on rsp_event (i.e., the generic
* hold-off mechanism provided by the ring macros). Frontends must set
* rsp_event appropriately (e.g., using RING_FINAL_CHECK_FOR_RESPONSES()).
*/
#ifndef blkif_vdev_t
#define blkif_vdev_t uint16_t
#endif
#define blkif_sector_t uint64_t
/*
* Feature and Parameter Negotiation
* =================================
* The two halves of a Xen block driver utilize nodes within the XenStore to
* communicate capabilities and to negotiate operating parameters. This
* section enumerates these nodes which reside in the respective front and
* backend portions of the XenStore, following the XenBus convention.
*
* All data in the XenStore is stored as strings. Nodes specifying numeric
* values are encoded in decimal. Integer value ranges listed below are
* expressed as fixed sized integer types capable of storing the conversion
* of a properly formated node string, without loss of information.
*
* Any specified default value is in effect if the corresponding XenBus node
* is not present in the XenStore.
*
* XenStore nodes in sections marked "PRIVATE" are solely for use by the
* driver side whose XenBus tree contains them.
*
* XenStore nodes marked "DEPRECATED" in their notes section should only be
* used to provide interoperability with legacy implementations.
*
* See the XenBus state transition diagram below for details on when XenBus
* nodes must be published and when they can be queried.
*
*****************************************************************************
* Backend XenBus Nodes
*****************************************************************************
*
*------------------ Backend Device Identification (PRIVATE) ------------------
*
* mode
* Values: "r" (read only), "w" (writable)
*
* The read or write access permissions to the backing store to be
* granted to the frontend.
*
* params
* Values: string
*
* A free formatted string providing sufficient information for the
* backend driver to open the backing device. (e.g. the path to the
* file or block device representing the backing store.)
*
* type
* Values: "file", "phy", "tap"
*
* The type of the backing device/object.
*
*--------------------------------- Features ---------------------------------
*
* feature-barrier
* Values: 0/1 (boolean)
* Default Value: 0
*
* A value of "1" indicates that the backend can process requests
* containing the BLKIF_OP_WRITE_BARRIER request opcode. Requests
* of this type may still be returned at any time with the
* BLKIF_RSP_EOPNOTSUPP result code.
*
* feature-flush-cache
* Values: 0/1 (boolean)
* Default Value: 0
*
* A value of "1" indicates that the backend can process requests
* containing the BLKIF_OP_FLUSH_DISKCACHE request opcode. Requests
* of this type may still be returned at any time with the
* BLKIF_RSP_EOPNOTSUPP result code.
*
* feature-discard
* Values: 0/1 (boolean)
* Default Value: 0
*
* A value of "1" indicates that the backend can process requests
* containing the BLKIF_OP_DISCARD request opcode. Requests
* of this type may still be returned at any time with the
* BLKIF_RSP_EOPNOTSUPP result code.
*
* feature-persistent
* Values: 0/1 (boolean)
* Default Value: 0
* Notes: 7
*
* A value of "1" indicates that the backend can keep the grants used
* by the frontend driver mapped, so the same set of grants should be
* used in all transactions. The maximum number of grants the backend
* can map persistently depends on the implementation, but ideally it
* should be RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST. Using this
* feature the backend doesn't need to unmap each grant, preventing
* costly TLB flushes. The backend driver should only map grants
* persistently if the frontend supports it. If a backend driver chooses
* to use the persistent protocol when the frontend doesn't support it,
* it will probably hit the maximum number of persistently mapped grants
* (due to the fact that the frontend won't be reusing the same grants),
* and fall back to non-persistent mode. Backend implementations may
* shrink or expand the number of persistently mapped grants without
* notifying the frontend depending on memory constraints (this might
* cause a performance degradation).
*
* If a backend driver wants to limit the maximum number of persistently
* mapped grants to a value less than RING_SIZE *
* BLKIF_MAX_SEGMENTS_PER_REQUEST a LRU strategy should be used to
* discard the grants that are less commonly used. Using a LRU in the
* backend driver paired with a LIFO queue in the frontend will
* allow us to have better performance in this scenario.
*
*----------------------- Request Transport Parameters ------------------------
*
* max-ring-page-order
* Values: <uint32_t>
* Default Value: 0
* Notes: 1, 3
*
* The maximum supported size of the request ring buffer in units of
* lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages,
* etc.).
*
* max-ring-pages
* Values: <uint32_t>
* Default Value: 1
* Notes: DEPRECATED, 2, 3
*
* The maximum supported size of the request ring buffer in units of
* machine pages. The value must be a power of 2.
*
*------------------------- Backend Device Properties -------------------------
*
* discard-alignment
* Values: <uint32_t>
* Default Value: 0
* Notes: 4, 5
*
* The offset, in bytes from the beginning of the virtual block device,
* to the first, addressable, discard extent on the underlying device.
*
* discard-granularity
* Values: <uint32_t>
* Default Value: <"sector-size">
* Notes: 4
*
* The size, in bytes, of the individually addressable discard extents
* of the underlying device.
*
* discard-secure
* Values: 0/1 (boolean)
* Default Value: 0
* Notes: 10
*
* A value of "1" indicates that the backend can process BLKIF_OP_DISCARD
* requests with the BLKIF_DISCARD_SECURE flag set.
*
* info
* Values: <uint32_t> (bitmap)
*
* A collection of bit flags describing attributes of the backing
* device. The VDISK_* macros define the meaning of each bit
* location.
*
* sector-size
* Values: <uint32_t>
*
* The logical sector size, in bytes, of the backend device.
*
* physical-sector-size
* Values: <uint32_t>
*
* The physical sector size, in bytes, of the backend device.
*
* sectors
* Values: <uint64_t>
*
* The size of the backend device, expressed in units of its logical
* sector size ("sector-size").
*
*****************************************************************************
* Frontend XenBus Nodes
*****************************************************************************
*
*----------------------- Request Transport Parameters -----------------------
*
* event-channel
* Values: <uint32_t>
*
* The identifier of the Xen event channel used to signal activity
* in the ring buffer.
*
* ring-ref
* Values: <uint32_t>
* Notes: 6
*
* The Xen grant reference granting permission for the backend to map
* the sole page in a single page sized ring buffer.
*
* ring-ref%u
* Values: <uint32_t>
* Notes: 6
*
* For a frontend providing a multi-page ring, a "number of ring pages"
* sized list of nodes, each containing a Xen grant reference granting
* permission for the backend to map the page of the ring located
* at page index "%u". Page indexes are zero based.
*
* protocol
* Values: string (XEN_IO_PROTO_ABI_*)
* Default Value: XEN_IO_PROTO_ABI_NATIVE
*
* The machine ABI rules governing the format of all ring request and
* response structures.
*
* ring-page-order
* Values: <uint32_t>
* Default Value: 0
* Maximum Value: MAX(ffs(max-ring-pages) - 1, max-ring-page-order)
* Notes: 1, 3
*
* The size of the frontend allocated request ring buffer in units
* of lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages,
* etc.).
*
* num-ring-pages
* Values: <uint32_t>
* Default Value: 1
* Maximum Value: MAX(max-ring-pages,(0x1 << max-ring-page-order))
* Notes: DEPRECATED, 2, 3
*
* The size of the frontend allocated request ring buffer in units of
* machine pages. The value must be a power of 2.
*
* feature-persistent
* Values: 0/1 (boolean)
* Default Value: 0
* Notes: 7, 8, 9
*
* A value of "1" indicates that the frontend will reuse the same grants
* for all transactions, allowing the backend to map them with write
* access (even when it should be read-only). If the frontend hits the
* maximum number of allowed persistently mapped grants, it can fallback
* to non persistent mode. This will cause a performance degradation,
* since the the backend driver will still try to map those grants
* persistently. Since the persistent grants protocol is compatible with
* the previous protocol, a frontend driver can choose to work in
* persistent mode even when the backend doesn't support it.
*
* It is recommended that the frontend driver stores the persistently
* mapped grants in a LIFO queue, so a subset of all persistently mapped
* grants gets used commonly. This is done in case the backend driver
* decides to limit the maximum number of persistently mapped grants
* to a value less than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
*
*------------------------- Virtual Device Properties -------------------------
*
* device-type
* Values: "disk", "cdrom", "floppy", etc.
*
* virtual-device
* Values: <uint32_t>
*
* A value indicating the physical device to virtualize within the
* frontend's domain. (e.g. "The first ATA disk", "The third SCSI
* disk", etc.)
*
* See docs/misc/vbd-interface.txt for details on the format of this
* value.
*
* Notes
* -----
* (1) Multi-page ring buffer scheme first developed in the Citrix XenServer
* PV drivers.
* (2) Multi-page ring buffer scheme first used in some RedHat distributions
* including a distribution deployed on certain nodes of the Amazon
* EC2 cluster.
* (3) Support for multi-page ring buffers was implemented independently,
* in slightly different forms, by both Citrix and RedHat/Amazon.
* For full interoperability, block front and backends should publish
* identical ring parameters, adjusted for unit differences, to the
* XenStore nodes used in both schemes.
* (4) Devices that support discard functionality may internally allocate space
* (discardable extents) in units that are larger than the exported logical
* block size. If the backing device has such discardable extents the
* backend should provide both discard-granularity and discard-alignment.
* Providing just one of the two may be considered an error by the frontend.
* Backends supporting discard should include discard-granularity and
* discard-alignment even if it supports discarding individual sectors.
* Frontends should assume discard-alignment == 0 and discard-granularity
* == sector size if these keys are missing.
* (5) The discard-alignment parameter allows a physical device to be
* partitioned into virtual devices that do not necessarily begin or
* end on a discardable extent boundary.
* (6) When there is only a single page allocated to the request ring,
* 'ring-ref' is used to communicate the grant reference for this
* page to the backend. When using a multi-page ring, the 'ring-ref'
* node is not created. Instead 'ring-ref0' - 'ring-refN' are used.
* (7) When using persistent grants data has to be copied from/to the page
* where the grant is currently mapped. The overhead of doing this copy
* however doesn't suppress the speed improvement of not having to unmap
* the grants.
* (8) The frontend driver has to allow the backend driver to map all grants
* with write access, even when they should be mapped read-only, since
* further requests may reuse these grants and require write permissions.
* (9) Linux implementation doesn't have a limit on the maximum number of
* grants that can be persistently mapped in the frontend driver, but
* due to the frontent driver implementation it should never be bigger
* than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
*(10) The discard-secure property may be present and will be set to 1 if the
* backing device supports secure discard.
*/
/*
* STATE DIAGRAMS
*
*****************************************************************************
* Startup *
*****************************************************************************
*
* Tool stack creates front and back nodes with state XenbusStateInitialising.
*
* Front Back
* ================================= =====================================
* XenbusStateInitialising XenbusStateInitialising
* o Query virtual device o Query backend device identification
* properties. data.
* o Setup OS device instance. o Open and validate backend device.
* o Publish backend features and
* transport parameters.
* |
* |
* V
* XenbusStateInitWait
*
* o Query backend features and
* transport parameters.
* o Allocate and initialize the
* request ring.
* o Publish transport parameters
* that will be in effect during
* this connection.
* |
* |
* V
* XenbusStateInitialised
*
* o Query frontend transport parameters.
* o Connect to the request ring and
* event channel.
* o Publish backend device properties.
* |
* |
* V
* XenbusStateConnected
*
* o Query backend device properties.
* o Finalize OS virtual device
* instance.
* |
* |
* V
* XenbusStateConnected
*
* Note: Drivers that do not support any optional features, or the negotiation
* of transport parameters, can skip certain states in the state machine:
*
* o A frontend may transition to XenbusStateInitialised without
* waiting for the backend to enter XenbusStateInitWait. In this
* case, default transport parameters are in effect and any
* transport parameters published by the frontend must contain
* their default values.
*
* o A backend may transition to XenbusStateInitialised, bypassing
* XenbusStateInitWait, without waiting for the frontend to first
* enter the XenbusStateInitialised state. In this case, default
* transport parameters are in effect and any transport parameters
* published by the backend must contain their default values.
*
* Drivers that support optional features and/or transport parameter
* negotiation must tolerate these additional state transition paths.
* In general this means performing the work of any skipped state
* transition, if it has not already been performed, in addition to the
* work associated with entry into the current state.
*/
/*
* REQUEST CODES.
*/
#define BLKIF_OP_READ 0
#define BLKIF_OP_WRITE 1
/*
* All writes issued prior to a request with the BLKIF_OP_WRITE_BARRIER
* operation code ("barrier request") must be completed prior to the
* execution of the barrier request. All writes issued after the barrier
* request must not execute until after the completion of the barrier request.
*
* Optional. See "feature-barrier" XenBus node documentation above.
*/
#define BLKIF_OP_WRITE_BARRIER 2
/*
* Commit any uncommitted contents of the backing device's volatile cache
* to stable storage.
*
* Optional. See "feature-flush-cache" XenBus node documentation above.
*/
#define BLKIF_OP_FLUSH_DISKCACHE 3
/*
* Used in SLES sources for device specific command packet
* contained within the request. Reserved for that purpose.
*/
#define BLKIF_OP_RESERVED_1 4
/*
* Indicate to the backend device that a region of storage is no longer in
* use, and may be discarded at any time without impact to the client. If
* the BLKIF_DISCARD_SECURE flag is set on the request, all copies of the
* discarded region on the device must be rendered unrecoverable before the
* command returns.
*
* This operation is analogous to performing a trim (ATA) or unamp (SCSI),
* command on a native device.
*
* More information about trim/unmap operations can be found at:
* http://t13.org/Documents/UploadedDocuments/docs2008/
* e07154r6-Data_Set_Management_Proposal_for_ATA-ACS2.doc
* http://www.seagate.com/staticfiles/support/disc/manuals/
* Interface%20manuals/100293068c.pdf
*
* Optional. See "feature-discard", "discard-alignment",
* "discard-granularity", and "discard-secure" in the XenBus node
* documentation above.
*/
#define BLKIF_OP_DISCARD 5
/*
* Recognized if "feature-max-indirect-segments" in present in the backend
* xenbus info. The "feature-max-indirect-segments" node contains the maximum
* number of segments allowed by the backend per request. If the node is
* present, the frontend might use blkif_request_indirect structs in order to
* issue requests with more than BLKIF_MAX_SEGMENTS_PER_REQUEST (11). The
* maximum number of indirect segments is fixed by the backend, but the
* frontend can issue requests with any number of indirect segments as long as
* it's less than the number provided by the backend. The indirect_grefs field
* in blkif_request_indirect should be filled by the frontend with the
* grant references of the pages that are holding the indirect segments.
* These pages are filled with an array of blkif_request_segment that hold the
* information about the segments. The number of indirect pages to use is
* determined by the number of segments an indirect request contains. Every
* indirect page can contain a maximum of
* (PAGE_SIZE / sizeof(struct blkif_request_segment)) segments, so to
* calculate the number of indirect pages to use we have to do
* ceil(indirect_segments / (PAGE_SIZE / sizeof(struct blkif_request_segment))).
*
* If a backend does not recognize BLKIF_OP_INDIRECT, it should *not*
* create the "feature-max-indirect-segments" node!
*/
#define BLKIF_OP_INDIRECT 6
/*
* Maximum scatter/gather segments per request.
* This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE.
* NB. This could be 12 if the ring indexes weren't stored in the same page.
*/
#define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
/*
* Maximum number of indirect pages to use per request.
*/
#define BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST 8
/*
* NB. first_sect and last_sect in blkif_request_segment, as well as
* sector_number in blkif_request, are always expressed in 512-byte units.
* However they must be properly aligned to the real sector size of the
* physical disk, which is reported in the "physical-sector-size" node in
* the backend xenbus info. Also the xenbus "sectors" node is expressed in
* 512-byte units.
*/
struct blkif_request_segment {
grant_ref_t gref; /* reference to I/O buffer frame */
/* @first_sect: first sector in frame to transfer (inclusive). */
/* @last_sect: last sector in frame to transfer (inclusive). */
uint8_t first_sect, last_sect;
};
/*
* Starting ring element for any I/O request.
*/
struct blkif_request {
uint8_t operation; /* BLKIF_OP_??? */
uint8_t nr_segments; /* number of segments */
blkif_vdev_t handle; /* only for read/write requests */
uint64_t id; /* private guest value, echoed in resp */
blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
};
typedef struct blkif_request blkif_request_t;
/*
* Cast to this structure when blkif_request.operation == BLKIF_OP_DISCARD
* sizeof(struct blkif_request_discard) <= sizeof(struct blkif_request)
*/
struct blkif_request_discard {
uint8_t operation; /* BLKIF_OP_DISCARD */
uint8_t flag; /* BLKIF_DISCARD_SECURE or zero */
#define BLKIF_DISCARD_SECURE (1<<0) /* ignored if discard-secure=0 */
blkif_vdev_t handle; /* same as for read/write requests */
uint64_t id; /* private guest value, echoed in resp */
blkif_sector_t sector_number;/* start sector idx on disk */
uint64_t nr_sectors; /* number of contiguous sectors to discard*/
};
typedef struct blkif_request_discard blkif_request_discard_t;
struct blkif_request_indirect {
uint8_t operation; /* BLKIF_OP_INDIRECT */
uint8_t indirect_op; /* BLKIF_OP_{READ/WRITE} */
uint16_t nr_segments; /* number of segments */
uint64_t id; /* private guest value, echoed in resp */
blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
blkif_vdev_t handle; /* same as for read/write requests */
grant_ref_t indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
#ifdef __i386__
uint64_t pad; /* Make it 64 byte aligned on i386 */
#endif
};
typedef struct blkif_request_indirect blkif_request_indirect_t;
struct blkif_response {
uint64_t id; /* copied from request */
uint8_t operation; /* copied from request */
int16_t status; /* BLKIF_RSP_??? */
};
typedef struct blkif_response blkif_response_t;
/*
* STATUS RETURN CODES.
*/
/* Operation not supported (only happens on barrier writes). */
#define BLKIF_RSP_EOPNOTSUPP -2
/* Operation failed for some unspecified reason (-EIO). */
#define BLKIF_RSP_ERROR -1
/* Operation completed successfully. */
#define BLKIF_RSP_OKAY 0
/*
* Generate blkif ring structures and types.
*/
DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response);
#define VDISK_CDROM 0x1
#define VDISK_REMOVABLE 0x2
#define VDISK_READONLY 0x4
#endif /* __XEN_PUBLIC_IO_BLKIF_H__ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/

51
include/xen/io/console.h Normal file
View file

@ -0,0 +1,51 @@
/******************************************************************************
* console.h
*
* Console I/O interface for Xen guest OSes.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2005, Keir Fraser
*/
#ifndef __XEN_PUBLIC_IO_CONSOLE_H__
#define __XEN_PUBLIC_IO_CONSOLE_H__
typedef uint32_t XENCONS_RING_IDX;
#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
struct xencons_interface {
char in[1024];
char out[2048];
XENCONS_RING_IDX in_cons, in_prod;
XENCONS_RING_IDX out_cons, out_prod;
};
#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/

View file

@ -0,0 +1,40 @@
/******************************************************************************
* protocols.h
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __XEN_PROTOCOLS_H__
#define __XEN_PROTOCOLS_H__
#define XEN_IO_PROTO_ABI_X86_32 "x86_32-abi"
#define XEN_IO_PROTO_ABI_X86_64 "x86_64-abi"
#define XEN_IO_PROTO_ABI_ARM "arm-abi"
#if defined(__i386__)
# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
#elif defined(__x86_64__)
# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
#elif defined(__arm__) || defined(__aarch64__)
# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_ARM
#else
# error arch fixup needed here
#endif
#endif

312
include/xen/io/ring.h Normal file
View file

@ -0,0 +1,312 @@
/******************************************************************************
* ring.h
*
* Shared producer-consumer ring macros.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Tim Deegan and Andrew Warfield November 2004.
*/
#ifndef __XEN_PUBLIC_IO_RING_H__
#define __XEN_PUBLIC_IO_RING_H__
#include "../xen-compat.h"
#if __XEN_INTERFACE_VERSION__ < 0x00030208
#define xen_mb() mb()
#define xen_rmb() rmb()
#define xen_wmb() wmb()
#endif
typedef unsigned int RING_IDX;
/* Round a 32-bit unsigned constant down to the nearest power of two. */
#define __RD2(_x) (((_x) & 0x00000002) ? 0x2 : ((_x) & 0x1))
#define __RD4(_x) (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2 : __RD2(_x))
#define __RD8(_x) (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4 : __RD4(_x))
#define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8 : __RD8(_x))
#define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x))
/*
* Calculate size of a shared ring, given the total available space for the
* ring and indexes (_sz), and the name tag of the request/response structure.
* A ring contains as many entries as will fit, rounded down to the nearest
* power of two (so we can mask with (size-1) to loop around).
*/
#define __CONST_RING_SIZE(_s, _sz) \
(__RD32(((_sz) - offsetof(struct _s##_sring, ring)) / \
sizeof(((struct _s##_sring *)0)->ring[0])))
/*
* The same for passing in an actual pointer instead of a name tag.
*/
#define __RING_SIZE(_s, _sz) \
(__RD32(((_sz) - (long)(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
/*
* Macros to make the correct C datatypes for a new kind of ring.
*
* To make a new ring datatype, you need to have two message structures,
* let's say request_t, and response_t already defined.
*
* In a header where you want the ring datatype declared, you then do:
*
* DEFINE_RING_TYPES(mytag, request_t, response_t);
*
* These expand out to give you a set of types, as you can see below.
* The most important of these are:
*
* mytag_sring_t - The shared ring.
* mytag_front_ring_t - The 'front' half of the ring.
* mytag_back_ring_t - The 'back' half of the ring.
*
* To initialize a ring in your code you need to know the location and size
* of the shared memory area (PAGE_SIZE, for instance). To initialise
* the front half:
*
* mytag_front_ring_t front_ring;
* SHARED_RING_INIT((mytag_sring_t *)shared_page);
* FRONT_RING_INIT(&front_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
*
* Initializing the back follows similarly (note that only the front
* initializes the shared ring):
*
* mytag_back_ring_t back_ring;
* BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
*/
#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t) \
\
/* Shared ring entry */ \
union __name##_sring_entry { \
__req_t req; \
__rsp_t rsp; \
}; \
\
/* Shared ring page */ \
struct __name##_sring { \
RING_IDX req_prod, req_event; \
RING_IDX rsp_prod, rsp_event; \
union { \
struct { \
uint8_t smartpoll_active; \
} netif; \
struct { \
uint8_t msg; \
} tapif_user; \
uint8_t pvt_pad[4]; \
} private; \
uint8_t __pad[44]; \
union __name##_sring_entry ring[1]; /* variable-length */ \
}; \
\
/* "Front" end's private variables */ \
struct __name##_front_ring { \
RING_IDX req_prod_pvt; \
RING_IDX rsp_cons; \
unsigned int nr_ents; \
struct __name##_sring *sring; \
}; \
\
/* "Back" end's private variables */ \
struct __name##_back_ring { \
RING_IDX rsp_prod_pvt; \
RING_IDX req_cons; \
unsigned int nr_ents; \
struct __name##_sring *sring; \
}; \
\
/* Syntactic sugar */ \
typedef struct __name##_sring __name##_sring_t; \
typedef struct __name##_front_ring __name##_front_ring_t; \
typedef struct __name##_back_ring __name##_back_ring_t
/*
* Macros for manipulating rings.
*
* FRONT_RING_whatever works on the "front end" of a ring: here
* requests are pushed on to the ring and responses taken off it.
*
* BACK_RING_whatever works on the "back end" of a ring: here
* requests are taken off the ring and responses put on.
*
* N.B. these macros do NO INTERLOCKS OR FLOW CONTROL.
* This is OK in 1-for-1 request-response situations where the
* requestor (front end) never has more than RING_SIZE()-1
* outstanding requests.
*/
/* Initialising empty rings */
#define SHARED_RING_INIT(_s) do { \
(_s)->req_prod = (_s)->rsp_prod = 0; \
(_s)->req_event = (_s)->rsp_event = 1; \
(void)memset((_s)->private.pvt_pad, 0, sizeof((_s)->private.pvt_pad)); \
(void)memset((_s)->__pad, 0, sizeof((_s)->__pad)); \
} while(0)
#define FRONT_RING_INIT(_r, _s, __size) do { \
(_r)->req_prod_pvt = 0; \
(_r)->rsp_cons = 0; \
(_r)->nr_ents = __RING_SIZE(_s, __size); \
(_r)->sring = (_s); \
} while (0)
#define BACK_RING_INIT(_r, _s, __size) do { \
(_r)->rsp_prod_pvt = 0; \
(_r)->req_cons = 0; \
(_r)->nr_ents = __RING_SIZE(_s, __size); \
(_r)->sring = (_s); \
} while (0)
/* How big is this ring? */
#define RING_SIZE(_r) \
((_r)->nr_ents)
/* Number of free requests (for use on front side only). */
#define RING_FREE_REQUESTS(_r) \
(RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
/* Test if there is an empty slot available on the front ring.
* (This is only meaningful from the front. )
*/
#define RING_FULL(_r) \
(RING_FREE_REQUESTS(_r) == 0)
/* Test if there are outstanding messages to be processed on a ring. */
#define RING_HAS_UNCONSUMED_RESPONSES(_r) \
((_r)->sring->rsp_prod - (_r)->rsp_cons)
#ifdef __GNUC__
#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({ \
unsigned int req = (_r)->sring->req_prod - (_r)->req_cons; \
unsigned int rsp = RING_SIZE(_r) - \
((_r)->req_cons - (_r)->rsp_prod_pvt); \
req < rsp ? req : rsp; \
})
#else
/* Same as above, but without the nice GCC ({ ... }) syntax. */
#define RING_HAS_UNCONSUMED_REQUESTS(_r) \
((((_r)->sring->req_prod - (_r)->req_cons) < \
(RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ? \
((_r)->sring->req_prod - (_r)->req_cons) : \
(RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt)))
#endif
/* Direct access to individual ring elements, by index. */
#define RING_GET_REQUEST(_r, _idx) \
(&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
#define RING_GET_RESPONSE(_r, _idx) \
(&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
/* Loop termination condition: Would the specified index overflow the ring? */
#define RING_REQUEST_CONS_OVERFLOW(_r, _cons) \
(((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
/* Ill-behaved frontend determination: Can there be this many requests? */
#define RING_REQUEST_PROD_OVERFLOW(_r, _prod) \
(((_prod) - (_r)->rsp_prod_pvt) > RING_SIZE(_r))
#define RING_PUSH_REQUESTS(_r) do { \
xen_wmb(); /* back sees requests /before/ updated producer index */ \
(_r)->sring->req_prod = (_r)->req_prod_pvt; \
} while (0)
#define RING_PUSH_RESPONSES(_r) do { \
xen_wmb(); /* front sees resps /before/ updated producer index */ \
(_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \
} while (0)
/*
* Notification hold-off (req_event and rsp_event):
*
* When queueing requests or responses on a shared ring, it may not always be
* necessary to notify the remote end. For example, if requests are in flight
* in a backend, the front may be able to queue further requests without
* notifying the back (if the back checks for new requests when it queues
* responses).
*
* When enqueuing requests or responses:
*
* Use RING_PUSH_{REQUESTS,RESPONSES}_AND_CHECK_NOTIFY(). The second argument
* is a boolean return value. True indicates that the receiver requires an
* asynchronous notification.
*
* After dequeuing requests or responses (before sleeping the connection):
*
* Use RING_FINAL_CHECK_FOR_REQUESTS() or RING_FINAL_CHECK_FOR_RESPONSES().
* The second argument is a boolean return value. True indicates that there
* are pending messages on the ring (i.e., the connection should not be put
* to sleep).
*
* These macros will set the req_event/rsp_event field to trigger a
* notification on the very next message that is enqueued. If you want to
* create batches of work (i.e., only receive a notification after several
* messages have been enqueued) then you will need to create a customised
* version of the FINAL_CHECK macro in your own code, which sets the event
* field appropriately.
*/
#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do { \
RING_IDX __old = (_r)->sring->req_prod; \
RING_IDX __new = (_r)->req_prod_pvt; \
xen_wmb(); /* back sees requests /before/ updated producer index */ \
(_r)->sring->req_prod = __new; \
xen_mb(); /* back sees new requests /before/ we check req_event */ \
(_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) < \
(RING_IDX)(__new - __old)); \
} while (0)
#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do { \
RING_IDX __old = (_r)->sring->rsp_prod; \
RING_IDX __new = (_r)->rsp_prod_pvt; \
xen_wmb(); /* front sees resps /before/ updated producer index */ \
(_r)->sring->rsp_prod = __new; \
xen_mb(); /* front sees new resps /before/ we check rsp_event */ \
(_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) < \
(RING_IDX)(__new - __old)); \
} while (0)
#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do { \
(_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
if (_work_to_do) break; \
(_r)->sring->req_event = (_r)->req_cons + 1; \
xen_mb(); \
(_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \
} while (0)
#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do { \
(_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
if (_work_to_do) break; \
(_r)->sring->rsp_event = (_r)->rsp_cons + 1; \
xen_mb(); \
(_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \
} while (0)
#endif /* __XEN_PUBLIC_IO_RING_H__ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/

80
include/xen/io/xenbus.h Normal file
View file

@ -0,0 +1,80 @@
/*****************************************************************************
* xenbus.h
*
* Xenbus protocol details.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (C) 2005 XenSource Ltd.
*/
#ifndef _XEN_PUBLIC_IO_XENBUS_H
#define _XEN_PUBLIC_IO_XENBUS_H
/*
* The state of either end of the Xenbus, i.e. the current communication
* status of initialisation across the bus. States here imply nothing about
* the state of the connection between the driver and the kernel's device
* layers.
*/
enum xenbus_state {
XenbusStateUnknown = 0,
XenbusStateInitialising = 1,
/*
* InitWait: Finished early initialisation but waiting for information
* from the peer or hotplug scripts.
*/
XenbusStateInitWait = 2,
/*
* Initialised: Waiting for a connection from the peer.
*/
XenbusStateInitialised = 3,
XenbusStateConnected = 4,
/*
* Closing: The device is being closed due to an error or an unplug event.
*/
XenbusStateClosing = 5,
XenbusStateClosed = 6,
/*
* Reconfiguring: The device is being reconfigured.
*/
XenbusStateReconfiguring = 7,
XenbusStateReconfigured = 8
};
typedef enum xenbus_state XenbusState;
#endif /* _XEN_PUBLIC_IO_XENBUS_H */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/

138
include/xen/io/xs_wire.h Normal file
View file

@ -0,0 +1,138 @@
/*
* Details of the "wire" protocol between Xen Store Daemon and client
* library or guest kernel.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (C) 2005 Rusty Russell IBM Corporation
*/
#ifndef _XS_WIRE_H
#define _XS_WIRE_H
enum xsd_sockmsg_type
{
XS_DEBUG,
XS_DIRECTORY,
XS_READ,
XS_GET_PERMS,
XS_WATCH,
XS_UNWATCH,
XS_TRANSACTION_START,
XS_TRANSACTION_END,
XS_INTRODUCE,
XS_RELEASE,
XS_GET_DOMAIN_PATH,
XS_WRITE,
XS_MKDIR,
XS_RM,
XS_SET_PERMS,
XS_WATCH_EVENT,
XS_ERROR,
XS_IS_DOMAIN_INTRODUCED,
XS_RESUME,
XS_SET_TARGET,
XS_RESTRICT,
XS_RESET_WATCHES
};
#define XS_WRITE_NONE "NONE"
#define XS_WRITE_CREATE "CREATE"
#define XS_WRITE_CREATE_EXCL "CREATE|EXCL"
/* We hand errors as strings, for portability. */
struct xsd_errors
{
int errnum;
const char *errstring;
};
#ifdef EINVAL
#define XSD_ERROR(x) { x, #x }
/* LINTED: static unused */
static struct xsd_errors xsd_errors[]
#if defined(__GNUC__)
__attribute__((unused))
#endif
= {
XSD_ERROR(EINVAL),
XSD_ERROR(EACCES),
XSD_ERROR(EEXIST),
XSD_ERROR(EISDIR),
XSD_ERROR(ENOENT),
XSD_ERROR(ENOMEM),
XSD_ERROR(ENOSPC),
XSD_ERROR(EIO),
XSD_ERROR(ENOTEMPTY),
XSD_ERROR(ENOSYS),
XSD_ERROR(EROFS),
XSD_ERROR(EBUSY),
XSD_ERROR(EAGAIN),
XSD_ERROR(EISCONN),
XSD_ERROR(E2BIG)
};
#endif
struct xsd_sockmsg
{
uint32_t type; /* XS_??? */
uint32_t req_id;/* Request identifier, echoed in daemon's response. */
uint32_t tx_id; /* Transaction id (0 if not related to a transaction). */
uint32_t len; /* Length of data following this. */
/* Generally followed by nul-terminated string(s). */
};
enum xs_watch_type
{
XS_WATCH_PATH = 0,
XS_WATCH_TOKEN
};
/*
* `incontents 150 xenstore_struct XenStore wire protocol.
*
* Inter-domain shared memory communications. */
#define XENSTORE_RING_SIZE 1024
typedef uint32_t XENSTORE_RING_IDX;
#define MASK_XENSTORE_IDX(idx) ((idx) & (XENSTORE_RING_SIZE-1))
struct xenstore_domain_interface {
char req[XENSTORE_RING_SIZE]; /* Requests to xenstore daemon. */
char rsp[XENSTORE_RING_SIZE]; /* Replies and async watch events. */
XENSTORE_RING_IDX req_cons, req_prod;
XENSTORE_RING_IDX rsp_cons, rsp_prod;
};
/* Violating this is very bad. See docs/misc/xenstore.txt. */
#define XENSTORE_PAYLOAD_MAX 4096
/* Violating these just gets you an error back */
#define XENSTORE_ABS_PATH_MAX 3072
#define XENSTORE_REL_PATH_MAX 2048
#endif /* _XS_WIRE_H */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/

174
include/xen/sched.h Normal file
View file

@ -0,0 +1,174 @@
/******************************************************************************
* sched.h
*
* Scheduler state interactions
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2005, Keir Fraser <keir@xensource.com>
*/
#ifndef __XEN_PUBLIC_SCHED_H__
#define __XEN_PUBLIC_SCHED_H__
#include "event_channel.h"
/*
* `incontents 150 sched Guest Scheduler Operations
*
* The SCHEDOP interface provides mechanisms for a guest to interact
* with the scheduler, including yield, blocking and shutting itself
* down.
*/
/*
* The prototype for this hypercall is:
* ` long HYPERVISOR_sched_op(enum sched_op cmd, void *arg, ...)
*
* @cmd == SCHEDOP_??? (scheduler operation).
* @arg == Operation-specific extra argument(s), as described below.
* ... == Additional Operation-specific extra arguments, described below.
*
* Versions of Xen prior to 3.0.2 provided only the following legacy version
* of this hypercall, supporting only the commands yield, block and shutdown:
* long sched_op(int cmd, unsigned long arg)
* @cmd == SCHEDOP_??? (scheduler operation).
* @arg == 0 (SCHEDOP_yield and SCHEDOP_block)
* == SHUTDOWN_* code (SCHEDOP_shutdown)
*
* This legacy version is available to new guests as:
* ` long HYPERVISOR_sched_op_compat(enum sched_op cmd, unsigned long arg)
*/
/* ` enum sched_op { // SCHEDOP_* => struct sched_* */
/*
* Voluntarily yield the CPU.
* @arg == NULL.
*/
#define SCHEDOP_yield 0
/*
* Block execution of this VCPU until an event is received for processing.
* If called with event upcalls masked, this operation will atomically
* reenable event delivery and check for pending events before blocking the
* VCPU. This avoids a "wakeup waiting" race.
* @arg == NULL.
*/
#define SCHEDOP_block 1
/*
* Halt execution of this domain (all VCPUs) and notify the system controller.
* @arg == pointer to sched_shutdown_t structure.
*
* If the sched_shutdown_t reason is SHUTDOWN_suspend then this
* hypercall takes an additional extra argument which should be the
* MFN of the guest's start_info_t.
*
* In addition, which reason is SHUTDOWN_suspend this hypercall
* returns 1 if suspend was cancelled or the domain was merely
* checkpointed, and 0 if it is resuming in a new domain.
*/
#define SCHEDOP_shutdown 2
/*
* Poll a set of event-channel ports. Return when one or more are pending. An
* optional timeout may be specified.
* @arg == pointer to sched_poll_t structure.
*/
#define SCHEDOP_poll 3
/*
* Declare a shutdown for another domain. The main use of this function is
* in interpreting shutdown requests and reasons for fully-virtualized
* domains. A para-virtualized domain may use SCHEDOP_shutdown directly.
* @arg == pointer to sched_remote_shutdown_t structure.
*/
#define SCHEDOP_remote_shutdown 4
/*
* Latch a shutdown code, so that when the domain later shuts down it
* reports this code to the control tools.
* @arg == sched_shutdown_t, as for SCHEDOP_shutdown.
*/
#define SCHEDOP_shutdown_code 5
/*
* Setup, poke and destroy a domain watchdog timer.
* @arg == pointer to sched_watchdog_t structure.
* With id == 0, setup a domain watchdog timer to cause domain shutdown
* after timeout, returns watchdog id.
* With id != 0 and timeout == 0, destroy domain watchdog timer.
* With id != 0 and timeout != 0, poke watchdog timer and set new timeout.
*/
#define SCHEDOP_watchdog 6
/* ` } */
struct sched_shutdown {
unsigned int reason; /* SHUTDOWN_* => enum sched_shutdown_reason */
};
typedef struct sched_shutdown sched_shutdown_t;
DEFINE_XEN_GUEST_HANDLE(sched_shutdown_t);
struct sched_poll {
XEN_GUEST_HANDLE(evtchn_port_t) ports;
unsigned int nr_ports;
uint64_t timeout;
};
typedef struct sched_poll sched_poll_t;
DEFINE_XEN_GUEST_HANDLE(sched_poll_t);
struct sched_remote_shutdown {
domid_t domain_id; /* Remote domain ID */
unsigned int reason; /* SHUTDOWN_* => enum sched_shutdown_reason */
};
typedef struct sched_remote_shutdown sched_remote_shutdown_t;
DEFINE_XEN_GUEST_HANDLE(sched_remote_shutdown_t);
struct sched_watchdog {
uint32_t id; /* watchdog ID */
uint32_t timeout; /* timeout */
};
typedef struct sched_watchdog sched_watchdog_t;
DEFINE_XEN_GUEST_HANDLE(sched_watchdog_t);
/*
* Reason codes for SCHEDOP_shutdown. These may be interpreted by control
* software to determine the appropriate action. For the most part, Xen does
* not care about the shutdown code.
*/
/* ` enum sched_shutdown_reason { */
#define SHUTDOWN_poweroff 0 /* Domain exited normally. Clean up and kill. */
#define SHUTDOWN_reboot 1 /* Clean up, kill, and then restart. */
#define SHUTDOWN_suspend 2 /* Clean up, save suspend info, kill. */
#define SHUTDOWN_crash 3 /* Tell controller we've crashed. */
#define SHUTDOWN_watchdog 4 /* Restart because watchdog time expired. */
#define SHUTDOWN_MAX 4 /* Maximum valid shutdown reason. */
/* ` } */
#endif /* __XEN_PUBLIC_SCHED_H__ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/

44
include/xen/xen-compat.h Normal file
View file

@ -0,0 +1,44 @@
/******************************************************************************
* xen-compat.h
*
* Guest OS interface to Xen. Compatibility layer.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2006, Christian Limpach
*/
#ifndef __XEN_PUBLIC_XEN_COMPAT_H__
#define __XEN_PUBLIC_XEN_COMPAT_H__
#define __XEN_LATEST_INTERFACE_VERSION__ 0x00040400
#if defined(__XEN__) || defined(__XEN_TOOLS__)
/* Xen is built with matching headers and implements the latest interface. */
#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__
#elif !defined(__XEN_INTERFACE_VERSION__)
/* Guests which do not specify a version get the legacy interface. */
#define __XEN_INTERFACE_VERSION__ 0x00000000
#endif
#if __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__
#error "These header files do not support the requested interface version."
#endif
#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */

899
include/xen/xen.h Normal file
View file

@ -0,0 +1,899 @@
/******************************************************************************
* xen.h
*
* Guest OS interface to Xen.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2004, K A Fraser
*/
#ifndef __XEN_PUBLIC_XEN_H__
#define __XEN_PUBLIC_XEN_H__
#include "xen-compat.h"
#if defined(__i386__) || defined(__x86_64__)
#include "arch-x86/xen.h"
#elif defined(__arm__) || defined (__aarch64__)
#include "arch-arm.h"
#else
#error "Unsupported architecture"
#endif
#ifndef __ASSEMBLY__
/* Guest handles for primitive C types. */
DEFINE_XEN_GUEST_HANDLE(char);
__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char);
DEFINE_XEN_GUEST_HANDLE(int);
__DEFINE_XEN_GUEST_HANDLE(uint, unsigned int);
#if __XEN_INTERFACE_VERSION__ < 0x00040300
DEFINE_XEN_GUEST_HANDLE(long);
__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long);
#endif
DEFINE_XEN_GUEST_HANDLE(void);
DEFINE_XEN_GUEST_HANDLE(uint64_t);
DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
#endif
/*
* HYPERCALLS
*/
/* `incontents 100 hcalls List of hypercalls
* ` enum hypercall_num { // __HYPERVISOR_* => HYPERVISOR_*()
*/
#define __HYPERVISOR_set_trap_table 0
#define __HYPERVISOR_mmu_update 1
#define __HYPERVISOR_set_gdt 2
#define __HYPERVISOR_stack_switch 3
#define __HYPERVISOR_set_callbacks 4
#define __HYPERVISOR_fpu_taskswitch 5
#define __HYPERVISOR_sched_op_compat 6 /* compat since 0x00030101 */
#define __HYPERVISOR_platform_op 7
#define __HYPERVISOR_set_debugreg 8
#define __HYPERVISOR_get_debugreg 9
#define __HYPERVISOR_update_descriptor 10
#define __HYPERVISOR_memory_op 12
#define __HYPERVISOR_multicall 13
#define __HYPERVISOR_update_va_mapping 14
#define __HYPERVISOR_set_timer_op 15
#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
#define __HYPERVISOR_xen_version 17
#define __HYPERVISOR_console_io 18
#define __HYPERVISOR_physdev_op_compat 19 /* compat since 0x00030202 */
#define __HYPERVISOR_grant_table_op 20
#define __HYPERVISOR_vm_assist 21
#define __HYPERVISOR_update_va_mapping_otherdomain 22
#define __HYPERVISOR_iret 23 /* x86 only */
#define __HYPERVISOR_vcpu_op 24
#define __HYPERVISOR_set_segment_base 25 /* x86/64 only */
#define __HYPERVISOR_mmuext_op 26
#define __HYPERVISOR_xsm_op 27
#define __HYPERVISOR_nmi_op 28
#define __HYPERVISOR_sched_op 29
#define __HYPERVISOR_callback_op 30
#define __HYPERVISOR_xenoprof_op 31
#define __HYPERVISOR_event_channel_op 32
#define __HYPERVISOR_physdev_op 33
#define __HYPERVISOR_hvm_op 34
#define __HYPERVISOR_sysctl 35
#define __HYPERVISOR_domctl 36
#define __HYPERVISOR_kexec_op 37
#define __HYPERVISOR_tmem_op 38
#define __HYPERVISOR_xc_reserved_op 39 /* reserved for XenClient */
/* Architecture-specific hypercall definitions. */
#define __HYPERVISOR_arch_0 48
#define __HYPERVISOR_arch_1 49
#define __HYPERVISOR_arch_2 50
#define __HYPERVISOR_arch_3 51
#define __HYPERVISOR_arch_4 52
#define __HYPERVISOR_arch_5 53
#define __HYPERVISOR_arch_6 54
#define __HYPERVISOR_arch_7 55
/* ` } */
/*
* HYPERCALL COMPATIBILITY.
*/
/* New sched_op hypercall introduced in 0x00030101. */
#if __XEN_INTERFACE_VERSION__ < 0x00030101
#undef __HYPERVISOR_sched_op
#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat
#endif
/* New event-channel and physdev hypercalls introduced in 0x00030202. */
#if __XEN_INTERFACE_VERSION__ < 0x00030202
#undef __HYPERVISOR_event_channel_op
#define __HYPERVISOR_event_channel_op __HYPERVISOR_event_channel_op_compat
#undef __HYPERVISOR_physdev_op
#define __HYPERVISOR_physdev_op __HYPERVISOR_physdev_op_compat
#endif
/* New platform_op hypercall introduced in 0x00030204. */
#if __XEN_INTERFACE_VERSION__ < 0x00030204
#define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op
#endif
/*
* VIRTUAL INTERRUPTS
*
* Virtual interrupts that a guest OS may receive from Xen.
*
* In the side comments, 'V.' denotes a per-VCPU VIRQ while 'G.' denotes a
* global VIRQ. The former can be bound once per VCPU and cannot be re-bound.
* The latter can be allocated only once per guest: they must initially be
* allocated to VCPU0 but can subsequently be re-bound.
*/
/* ` enum virq { */
#define VIRQ_TIMER 0 /* V. Timebase update, and/or requested timeout. */
#define VIRQ_DEBUG 1 /* V. Request guest to dump debug info. */
#define VIRQ_CONSOLE 2 /* G. (DOM0) Bytes received on emergency console. */
#define VIRQ_DOM_EXC 3 /* G. (DOM0) Exceptional event for some domain. */
#define VIRQ_TBUF 4 /* G. (DOM0) Trace buffer has records available. */
#define VIRQ_DEBUGGER 6 /* G. (DOM0) A domain has paused for debugging. */
#define VIRQ_XENOPROF 7 /* V. XenOprofile interrupt: new sample available */
#define VIRQ_CON_RING 8 /* G. (DOM0) Bytes received on console */
#define VIRQ_PCPU_STATE 9 /* G. (DOM0) PCPU state changed */
#define VIRQ_MEM_EVENT 10 /* G. (DOM0) A memory event has occured */
#define VIRQ_XC_RESERVED 11 /* G. Reserved for XenClient */
#define VIRQ_ENOMEM 12 /* G. (DOM0) Low on heap memory */
/* Architecture-specific VIRQ definitions. */
#define VIRQ_ARCH_0 16
#define VIRQ_ARCH_1 17
#define VIRQ_ARCH_2 18
#define VIRQ_ARCH_3 19
#define VIRQ_ARCH_4 20
#define VIRQ_ARCH_5 21
#define VIRQ_ARCH_6 22
#define VIRQ_ARCH_7 23
/* ` } */
#define NR_VIRQS 24
/*
* ` enum neg_errnoval
* ` HYPERVISOR_mmu_update(const struct mmu_update reqs[],
* ` unsigned count, unsigned *done_out,
* ` unsigned foreigndom)
* `
* @reqs is an array of mmu_update_t structures ((ptr, val) pairs).
* @count is the length of the above array.
* @pdone is an output parameter indicating number of completed operations
* @foreigndom[15:0]: FD, the expected owner of data pages referenced in this
* hypercall invocation. Can be DOMID_SELF.
* @foreigndom[31:16]: PFD, the expected owner of pagetable pages referenced
* in this hypercall invocation. The value of this field
* (x) encodes the PFD as follows:
* x == 0 => PFD == DOMID_SELF
* x != 0 => PFD == x - 1
*
* Sub-commands: ptr[1:0] specifies the appropriate MMU_* command.
* -------------
* ptr[1:0] == MMU_NORMAL_PT_UPDATE:
* Updates an entry in a page table belonging to PFD. If updating an L1 table,
* and the new table entry is valid/present, the mapped frame must belong to
* FD. If attempting to map an I/O page then the caller assumes the privilege
* of the FD.
* FD == DOMID_IO: Permit /only/ I/O mappings, at the priv level of the caller.
* FD == DOMID_XEN: Map restricted areas of Xen's heap space.
* ptr[:2] -- Machine address of the page-table entry to modify.
* val -- Value to write.
*
* There also certain implicit requirements when using this hypercall. The
* pages that make up a pagetable must be mapped read-only in the guest.
* This prevents uncontrolled guest updates to the pagetable. Xen strictly
* enforces this, and will disallow any pagetable update which will end up
* mapping pagetable page RW, and will disallow using any writable page as a
* pagetable. In practice it means that when constructing a page table for a
* process, thread, etc, we MUST be very dilligient in following these rules:
* 1). Start with top-level page (PGD or in Xen language: L4). Fill out
* the entries.
* 2). Keep on going, filling out the upper (PUD or L3), and middle (PMD
* or L2).
* 3). Start filling out the PTE table (L1) with the PTE entries. Once
* done, make sure to set each of those entries to RO (so writeable bit
* is unset). Once that has been completed, set the PMD (L2) for this
* PTE table as RO.
* 4). When completed with all of the PMD (L2) entries, and all of them have
* been set to RO, make sure to set RO the PUD (L3). Do the same
* operation on PGD (L4) pagetable entries that have a PUD (L3) entry.
* 5). Now before you can use those pages (so setting the cr3), you MUST also
* pin them so that the hypervisor can verify the entries. This is done
* via the HYPERVISOR_mmuext_op(MMUEXT_PIN_L4_TABLE, guest physical frame
* number of the PGD (L4)). And this point the HYPERVISOR_mmuext_op(
* MMUEXT_NEW_BASEPTR, guest physical frame number of the PGD (L4)) can be
* issued.
* For 32-bit guests, the L4 is not used (as there is less pagetables), so
* instead use L3.
* At this point the pagetables can be modified using the MMU_NORMAL_PT_UPDATE
* hypercall. Also if so desired the OS can also try to write to the PTE
* and be trapped by the hypervisor (as the PTE entry is RO).
*
* To deallocate the pages, the operations are the reverse of the steps
* mentioned above. The argument is MMUEXT_UNPIN_TABLE for all levels and the
* pagetable MUST not be in use (meaning that the cr3 is not set to it).
*
* ptr[1:0] == MMU_MACHPHYS_UPDATE:
* Updates an entry in the machine->pseudo-physical mapping table.
* ptr[:2] -- Machine address within the frame whose mapping to modify.
* The frame must belong to the FD, if one is specified.
* val -- Value to write into the mapping entry.
*
* ptr[1:0] == MMU_PT_UPDATE_PRESERVE_AD:
* As MMU_NORMAL_PT_UPDATE above, but A/D bits currently in the PTE are ORed
* with those in @val.
*
* @val is usually the machine frame number along with some attributes.
* The attributes by default follow the architecture defined bits. Meaning that
* if this is a X86_64 machine and four page table layout is used, the layout
* of val is:
* - 63 if set means No execute (NX)
* - 46-13 the machine frame number
* - 12 available for guest
* - 11 available for guest
* - 10 available for guest
* - 9 available for guest
* - 8 global
* - 7 PAT (PSE is disabled, must use hypercall to make 4MB or 2MB pages)
* - 6 dirty
* - 5 accessed
* - 4 page cached disabled
* - 3 page write through
* - 2 userspace accessible
* - 1 writeable
* - 0 present
*
* The one bits that does not fit with the default layout is the PAGE_PSE
* also called PAGE_PAT). The MMUEXT_[UN]MARK_SUPER arguments to the
* HYPERVISOR_mmuext_op serve as mechanism to set a pagetable to be 4MB
* (or 2MB) instead of using the PAGE_PSE bit.
*
* The reason that the PAGE_PSE (bit 7) is not being utilized is due to Xen
* using it as the Page Attribute Table (PAT) bit - for details on it please
* refer to Intel SDM 10.12. The PAT allows to set the caching attributes of
* pages instead of using MTRRs.
*
* The PAT MSR is as follows (it is a 64-bit value, each entry is 8 bits):
* PAT4 PAT0
* +-----+-----+----+----+----+-----+----+----+
* | UC | UC- | WC | WB | UC | UC- | WC | WB | <= Linux
* +-----+-----+----+----+----+-----+----+----+
* | UC | UC- | WT | WB | UC | UC- | WT | WB | <= BIOS (default when machine boots)
* +-----+-----+----+----+----+-----+----+----+
* | rsv | rsv | WP | WC | UC | UC- | WT | WB | <= Xen
* +-----+-----+----+----+----+-----+----+----+
*
* The lookup of this index table translates to looking up
* Bit 7, Bit 4, and Bit 3 of val entry:
*
* PAT/PSE (bit 7) ... PCD (bit 4) .. PWT (bit 3).
*
* If all bits are off, then we are using PAT0. If bit 3 turned on,
* then we are using PAT1, if bit 3 and bit 4, then PAT2..
*
* As you can see, the Linux PAT1 translates to PAT4 under Xen. Which means
* that if a guest that follows Linux's PAT setup and would like to set Write
* Combined on pages it MUST use PAT4 entry. Meaning that Bit 7 (PAGE_PAT) is
* set. For example, under Linux it only uses PAT0, PAT1, and PAT2 for the
* caching as:
*
* WB = none (so PAT0)
* WC = PWT (bit 3 on)
* UC = PWT | PCD (bit 3 and 4 are on).
*
* To make it work with Xen, it needs to translate the WC bit as so:
*
* PWT (so bit 3 on) --> PAT (so bit 7 is on) and clear bit 3
*
* And to translate back it would:
*
* PAT (bit 7 on) --> PWT (bit 3 on) and clear bit 7.
*/
#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */
#define MMU_MACHPHYS_UPDATE 1 /* ptr = MA of frame to modify entry for */
#define MMU_PT_UPDATE_PRESERVE_AD 2 /* atomically: *ptr = val | (*ptr&(A|D)) */
/*
* MMU EXTENDED OPERATIONS
*
* ` enum neg_errnoval
* ` HYPERVISOR_mmuext_op(mmuext_op_t uops[],
* ` unsigned int count,
* ` unsigned int *pdone,
* ` unsigned int foreigndom)
*/
/* HYPERVISOR_mmuext_op() accepts a list of mmuext_op structures.
* A foreigndom (FD) can be specified (or DOMID_SELF for none).
* Where the FD has some effect, it is described below.
*
* cmd: MMUEXT_(UN)PIN_*_TABLE
* mfn: Machine frame number to be (un)pinned as a p.t. page.
* The frame must belong to the FD, if one is specified.
*
* cmd: MMUEXT_NEW_BASEPTR
* mfn: Machine frame number of new page-table base to install in MMU.
*
* cmd: MMUEXT_NEW_USER_BASEPTR [x86/64 only]
* mfn: Machine frame number of new page-table base to install in MMU
* when in user space.
*
* cmd: MMUEXT_TLB_FLUSH_LOCAL
* No additional arguments. Flushes local TLB.
*
* cmd: MMUEXT_INVLPG_LOCAL
* linear_addr: Linear address to be flushed from the local TLB.
*
* cmd: MMUEXT_TLB_FLUSH_MULTI
* vcpumask: Pointer to bitmap of VCPUs to be flushed.
*
* cmd: MMUEXT_INVLPG_MULTI
* linear_addr: Linear address to be flushed.
* vcpumask: Pointer to bitmap of VCPUs to be flushed.
*
* cmd: MMUEXT_TLB_FLUSH_ALL
* No additional arguments. Flushes all VCPUs' TLBs.
*
* cmd: MMUEXT_INVLPG_ALL
* linear_addr: Linear address to be flushed from all VCPUs' TLBs.
*
* cmd: MMUEXT_FLUSH_CACHE
* No additional arguments. Writes back and flushes cache contents.
*
* cmd: MMUEXT_FLUSH_CACHE_GLOBAL
* No additional arguments. Writes back and flushes cache contents
* on all CPUs in the system.
*
* cmd: MMUEXT_SET_LDT
* linear_addr: Linear address of LDT base (NB. must be page-aligned).
* nr_ents: Number of entries in LDT.
*
* cmd: MMUEXT_CLEAR_PAGE
* mfn: Machine frame number to be cleared.
*
* cmd: MMUEXT_COPY_PAGE
* mfn: Machine frame number of the destination page.
* src_mfn: Machine frame number of the source page.
*
* cmd: MMUEXT_[UN]MARK_SUPER
* mfn: Machine frame number of head of superpage to be [un]marked.
*/
/* ` enum mmuext_cmd { */
#define MMUEXT_PIN_L1_TABLE 0
#define MMUEXT_PIN_L2_TABLE 1
#define MMUEXT_PIN_L3_TABLE 2
#define MMUEXT_PIN_L4_TABLE 3
#define MMUEXT_UNPIN_TABLE 4
#define MMUEXT_NEW_BASEPTR 5
#define MMUEXT_TLB_FLUSH_LOCAL 6
#define MMUEXT_INVLPG_LOCAL 7
#define MMUEXT_TLB_FLUSH_MULTI 8
#define MMUEXT_INVLPG_MULTI 9
#define MMUEXT_TLB_FLUSH_ALL 10
#define MMUEXT_INVLPG_ALL 11
#define MMUEXT_FLUSH_CACHE 12
#define MMUEXT_SET_LDT 13
#define MMUEXT_NEW_USER_BASEPTR 15
#define MMUEXT_CLEAR_PAGE 16
#define MMUEXT_COPY_PAGE 17
#define MMUEXT_FLUSH_CACHE_GLOBAL 18
#define MMUEXT_MARK_SUPER 19
#define MMUEXT_UNMARK_SUPER 20
/* ` } */
#ifndef __ASSEMBLY__
struct mmuext_op {
unsigned int cmd; /* => enum mmuext_cmd */
union {
/* [UN]PIN_TABLE, NEW_BASEPTR, NEW_USER_BASEPTR
* CLEAR_PAGE, COPY_PAGE, [UN]MARK_SUPER */
xen_pfn_t mfn;
/* INVLPG_LOCAL, INVLPG_ALL, SET_LDT */
unsigned long linear_addr;
} arg1;
union {
/* SET_LDT */
unsigned int nr_ents;
/* TLB_FLUSH_MULTI, INVLPG_MULTI */
#if __XEN_INTERFACE_VERSION__ >= 0x00030205
XEN_GUEST_HANDLE(const_void) vcpumask;
#else
const void *vcpumask;
#endif
/* COPY_PAGE */
xen_pfn_t src_mfn;
} arg2;
};
typedef struct mmuext_op mmuext_op_t;
DEFINE_XEN_GUEST_HANDLE(mmuext_op_t);
#endif
/*
* ` enum neg_errnoval
* ` HYPERVISOR_update_va_mapping(unsigned long va, u64 val,
* ` enum uvm_flags flags)
* `
* ` enum neg_errnoval
* ` HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, u64 val,
* ` enum uvm_flags flags,
* ` domid_t domid)
* `
* ` @va: The virtual address whose mapping we want to change
* ` @val: The new page table entry, must contain a machine address
* ` @flags: Control TLB flushes
*/
/* These are passed as 'flags' to update_va_mapping. They can be ORed. */
/* When specifying UVMF_MULTI, also OR in a pointer to a CPU bitmap. */
/* UVMF_LOCAL is merely UVMF_MULTI with a NULL bitmap pointer. */
/* ` enum uvm_flags { */
#define UVMF_NONE (0UL<<0) /* No flushing at all. */
#define UVMF_TLB_FLUSH (1UL<<0) /* Flush entire TLB(s). */
#define UVMF_INVLPG (2UL<<0) /* Flush only one entry. */
#define UVMF_FLUSHTYPE_MASK (3UL<<0)
#define UVMF_MULTI (0UL<<2) /* Flush subset of TLBs. */
#define UVMF_LOCAL (0UL<<2) /* Flush local TLB. */
#define UVMF_ALL (1UL<<2) /* Flush all TLBs. */
/* ` } */
/*
* Commands to HYPERVISOR_console_io().
*/
#define CONSOLEIO_write 0
#define CONSOLEIO_read 1
/*
* Commands to HYPERVISOR_vm_assist().
*/
#define VMASST_CMD_enable 0
#define VMASST_CMD_disable 1
/* x86/32 guests: simulate full 4GB segment limits. */
#define VMASST_TYPE_4gb_segments 0
/* x86/32 guests: trap (vector 15) whenever above vmassist is used. */
#define VMASST_TYPE_4gb_segments_notify 1
/*
* x86 guests: support writes to bottom-level PTEs.
* NB1. Page-directory entries cannot be written.
* NB2. Guest must continue to remove all writable mappings of PTEs.
*/
#define VMASST_TYPE_writable_pagetables 2
/* x86/PAE guests: support PDPTs above 4GB. */
#define VMASST_TYPE_pae_extended_cr3 3
#define MAX_VMASST_TYPE 3
#ifndef __ASSEMBLY__
typedef uint16_t domid_t;
/* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */
#define DOMID_FIRST_RESERVED (0x7FF0U)
/* DOMID_SELF is used in certain contexts to refer to oneself. */
#define DOMID_SELF (0x7FF0U)
/*
* DOMID_IO is used to restrict page-table updates to mapping I/O memory.
* Although no Foreign Domain need be specified to map I/O pages, DOMID_IO
* is useful to ensure that no mappings to the OS's own heap are accidentally
* installed. (e.g., in Linux this could cause havoc as reference counts
* aren't adjusted on the I/O-mapping code path).
* This only makes sense in MMUEXT_SET_FOREIGNDOM, but in that context can
* be specified by any calling domain.
*/
#define DOMID_IO (0x7FF1U)
/*
* DOMID_XEN is used to allow privileged domains to map restricted parts of
* Xen's heap space (e.g., the machine_to_phys table).
* This only makes sense in MMUEXT_SET_FOREIGNDOM, and is only permitted if
* the caller is privileged.
*/
#define DOMID_XEN (0x7FF2U)
/*
* DOMID_COW is used as the owner of sharable pages */
#define DOMID_COW (0x7FF3U)
/* DOMID_INVALID is used to identify pages with unknown owner. */
#define DOMID_INVALID (0x7FF4U)
/* Idle domain. */
#define DOMID_IDLE (0x7FFFU)
/*
* Send an array of these to HYPERVISOR_mmu_update().
* NB. The fields are natural pointer/address size for this architecture.
*/
struct mmu_update {
uint64_t ptr; /* Machine address of PTE. */
uint64_t val; /* New contents of PTE. */
};
typedef struct mmu_update mmu_update_t;
DEFINE_XEN_GUEST_HANDLE(mmu_update_t);
/*
* ` enum neg_errnoval
* ` HYPERVISOR_multicall(multicall_entry_t call_list[],
* ` uint32_t nr_calls);
*
* NB. The fields are logically the natural register size for this
* architecture. In cases where xen_ulong_t is larger than this then
* any unused bits in the upper portion must be zero.
*/
struct multicall_entry {
xen_ulong_t op, result;
xen_ulong_t args[6];
};
typedef struct multicall_entry multicall_entry_t;
DEFINE_XEN_GUEST_HANDLE(multicall_entry_t);
#if __XEN_INTERFACE_VERSION__ < 0x00040400
/*
* Event channel endpoints per domain (when using the 2-level ABI):
* 1024 if a long is 32 bits; 4096 if a long is 64 bits.
*/
#define NR_EVENT_CHANNELS EVTCHN_2L_NR_CHANNELS
#endif
struct vcpu_time_info {
/*
* Updates to the following values are preceded and followed by an
* increment of 'version'. The guest can therefore detect updates by
* looking for changes to 'version'. If the least-significant bit of
* the version number is set then an update is in progress and the guest
* must wait to read a consistent set of values.
* The correct way to interact with the version number is similar to
* Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
*/
uint32_t version;
uint32_t pad0;
uint64_t tsc_timestamp; /* TSC at last update of time vals. */
uint64_t system_time; /* Time, in nanosecs, since boot. */
/*
* Current system time:
* system_time +
* ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32)
* CPU frequency (Hz):
* ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
*/
uint32_t tsc_to_system_mul;
int8_t tsc_shift;
int8_t pad1[3];
}; /* 32 bytes */
typedef struct vcpu_time_info vcpu_time_info_t;
struct vcpu_info {
/*
* 'evtchn_upcall_pending' is written non-zero by Xen to indicate
* a pending notification for a particular VCPU. It is then cleared
* by the guest OS /before/ checking for pending work, thus avoiding
* a set-and-check race. Note that the mask is only accessed by Xen
* on the CPU that is currently hosting the VCPU. This means that the
* pending and mask flags can be updated by the guest without special
* synchronisation (i.e., no need for the x86 LOCK prefix).
* This may seem suboptimal because if the pending flag is set by
* a different CPU then an IPI may be scheduled even when the mask
* is set. However, note:
* 1. The task of 'interrupt holdoff' is covered by the per-event-
* channel mask bits. A 'noisy' event that is continually being
* triggered can be masked at source at this very precise
* granularity.
* 2. The main purpose of the per-VCPU mask is therefore to restrict
* reentrant execution: whether for concurrency control, or to
* prevent unbounded stack usage. Whatever the purpose, we expect
* that the mask will be asserted only for short periods at a time,
* and so the likelihood of a 'spurious' IPI is suitably small.
* The mask is read before making an event upcall to the guest: a
* non-zero mask therefore guarantees that the VCPU will not receive
* an upcall activation. The mask is cleared when the VCPU requests
* to block: this avoids wakeup-waiting races.
*/
uint8_t evtchn_upcall_pending;
#ifdef XEN_HAVE_PV_UPCALL_MASK
uint8_t evtchn_upcall_mask;
#else /* XEN_HAVE_PV_UPCALL_MASK */
uint8_t pad0;
#endif /* XEN_HAVE_PV_UPCALL_MASK */
xen_ulong_t evtchn_pending_sel;
struct arch_vcpu_info arch;
struct vcpu_time_info time;
}; /* 64 bytes (x86) */
#ifndef __XEN__
typedef struct vcpu_info vcpu_info_t;
#endif
/*
* `incontents 200 startofday_shared Start-of-day shared data structure
* Xen/kernel shared data -- pointer provided in start_info.
*
* This structure is defined to be both smaller than a page, and the
* only data on the shared page, but may vary in actual size even within
* compatible Xen versions; guests should not rely on the size
* of this structure remaining constant.
*/
struct shared_info {
struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS];
/*
* A domain can create "event channels" on which it can send and receive
* asynchronous event notifications. There are three classes of event that
* are delivered by this mechanism:
* 1. Bi-directional inter- and intra-domain connections. Domains must
* arrange out-of-band to set up a connection (usually by allocating
* an unbound 'listener' port and avertising that via a storage service
* such as xenstore).
* 2. Physical interrupts. A domain with suitable hardware-access
* privileges can bind an event-channel port to a physical interrupt
* source.
* 3. Virtual interrupts ('events'). A domain can bind an event-channel
* port to a virtual interrupt source, such as the virtual-timer
* device or the emergency console.
*
* Event channels are addressed by a "port index". Each channel is
* associated with two bits of information:
* 1. PENDING -- notifies the domain that there is a pending notification
* to be processed. This bit is cleared by the guest.
* 2. MASK -- if this bit is clear then a 0->1 transition of PENDING
* will cause an asynchronous upcall to be scheduled. This bit is only
* updated by the guest. It is read-only within Xen. If a channel
* becomes pending while the channel is masked then the 'edge' is lost
* (i.e., when the channel is unmasked, the guest must manually handle
* pending notifications as no upcall will be scheduled by Xen).
*
* To expedite scanning of pending notifications, any 0->1 pending
* transition on an unmasked channel causes a corresponding bit in a
* per-vcpu selector word to be set. Each bit in the selector covers a
* 'C long' in the PENDING bitfield array.
*/
xen_ulong_t evtchn_pending[sizeof(xen_ulong_t) * 8];
xen_ulong_t evtchn_mask[sizeof(xen_ulong_t) * 8];
/*
* Wallclock time: updated only by control software. Guests should base
* their gettimeofday() syscall on this wallclock-base value.
*/
uint32_t wc_version; /* Version counter: see vcpu_time_info_t. */
uint32_t wc_sec; /* Secs 00:00:00 UTC, Jan 1, 1970. */
uint32_t wc_nsec; /* Nsecs 00:00:00 UTC, Jan 1, 1970. */
struct arch_shared_info arch;
};
#ifndef __XEN__
typedef struct shared_info shared_info_t;
#endif
/*
* `incontents 200 startofday Start-of-day memory layout
*
* 1. The domain is started within contiguous virtual-memory region.
* 2. The contiguous region ends on an aligned 4MB boundary.
* 3. This the order of bootstrap elements in the initial virtual region:
* a. relocated kernel image
* b. initial ram disk [mod_start, mod_len]
* c. list of allocated page frames [mfn_list, nr_pages]
* (unless relocated due to XEN_ELFNOTE_INIT_P2M)
* d. start_info_t structure [register ESI (x86)]
* e. bootstrap page tables [pt_base and CR3 (x86)]
* f. bootstrap stack [register ESP (x86)]
* 4. Bootstrap elements are packed together, but each is 4kB-aligned.
* 5. The initial ram disk may be omitted.
* 6. The list of page frames forms a contiguous 'pseudo-physical' memory
* layout for the domain. In particular, the bootstrap virtual-memory
* region is a 1:1 mapping to the first section of the pseudo-physical map.
* 7. All bootstrap elements are mapped read-writable for the guest OS. The
* only exception is the bootstrap page table, which is mapped read-only.
* 8. There is guaranteed to be at least 512kB padding after the final
* bootstrap element. If necessary, the bootstrap virtual region is
* extended by an extra 4MB to ensure this.
*
* Note: Prior to 25833:bb85bbccb1c9. ("x86/32-on-64 adjust Dom0 initial page
* table layout") a bug caused the pt_base (3.e above) and cr3 to not point
* to the start of the guest page tables (it was offset by two pages).
* This only manifested itself on 32-on-64 dom0 kernels and not 32-on-64 domU
* or 64-bit kernels of any colour. The page tables for a 32-on-64 dom0 got
* allocated in the order: 'first L1','first L2', 'first L3', so the offset
* to the page table base is by two pages back. The initial domain if it is
* 32-bit and runs under a 64-bit hypervisor should _NOT_ use two of the
* pages preceding pt_base and mark them as reserved/unused.
*/
#ifdef XEN_HAVE_PV_GUEST_ENTRY
struct start_info {
/* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */
char magic[32]; /* "xen-<version>-<platform>". */
unsigned long nr_pages; /* Total pages allocated to this domain. */
unsigned long shared_info; /* MACHINE address of shared info struct. */
uint32_t flags; /* SIF_xxx flags. */
xen_pfn_t store_mfn; /* MACHINE page number of shared page. */
uint32_t store_evtchn; /* Event channel for store communication. */
union {
struct {
xen_pfn_t mfn; /* MACHINE page number of console page. */
uint32_t evtchn; /* Event channel for console page. */
} domU;
struct {
uint32_t info_off; /* Offset of console_info struct. */
uint32_t info_size; /* Size of console_info struct from start.*/
} dom0;
} console;
/* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */
unsigned long pt_base; /* VIRTUAL address of page directory. */
unsigned long nr_pt_frames; /* Number of bootstrap p.t. frames. */
unsigned long mfn_list; /* VIRTUAL address of page-frame list. */
unsigned long mod_start; /* VIRTUAL address of pre-loaded module */
/* (PFN of pre-loaded module if */
/* SIF_MOD_START_PFN set in flags). */
unsigned long mod_len; /* Size (bytes) of pre-loaded module. */
#define MAX_GUEST_CMDLINE 1024
int8_t cmd_line[MAX_GUEST_CMDLINE];
/* The pfn range here covers both page table and p->m table frames. */
unsigned long first_p2m_pfn;/* 1st pfn forming initial P->M table. */
unsigned long nr_p2m_frames;/* # of pfns forming initial P->M table. */
};
typedef struct start_info start_info_t;
/* New console union for dom0 introduced in 0x00030203. */
#if __XEN_INTERFACE_VERSION__ < 0x00030203
#define console_mfn console.domU.mfn
#define console_evtchn console.domU.evtchn
#endif
#endif /* XEN_HAVE_PV_GUEST_ENTRY */
/* These flags are passed in the 'flags' field of start_info_t. */
#define SIF_PRIVILEGED (1<<0) /* Is the domain privileged? */
#define SIF_INITDOMAIN (1<<1) /* Is this the initial control domain? */
#define SIF_MULTIBOOT_MOD (1<<2) /* Is mod_start a multiboot module? */
#define SIF_MOD_START_PFN (1<<3) /* Is mod_start a PFN? */
#define SIF_PM_MASK (0xFF<<8) /* reserve 1 byte for xen-pm options */
/*
* A multiboot module is a package containing modules very similar to a
* multiboot module array. The only differences are:
* - the array of module descriptors is by convention simply at the beginning
* of the multiboot module,
* - addresses in the module descriptors are based on the beginning of the
* multiboot module,
* - the number of modules is determined by a termination descriptor that has
* mod_start == 0.
*
* This permits to both build it statically and reference it in a configuration
* file, and let the PV guest easily rebase the addresses to virtual addresses
* and at the same time count the number of modules.
*/
struct xen_multiboot_mod_list
{
/* Address of first byte of the module */
uint32_t mod_start;
/* Address of last byte of the module (inclusive) */
uint32_t mod_end;
/* Address of zero-terminated command line */
uint32_t cmdline;
/* Unused, must be zero */
uint32_t pad;
};
/*
* `incontents 200 startofday_dom0_console Dom0_console
*
* The console structure in start_info.console.dom0
*
* This structure includes a variety of information required to
* have a working VGA/VESA console.
*/
typedef struct dom0_vga_console_info {
uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */
#define XEN_VGATYPE_TEXT_MODE_3 0x03
#define XEN_VGATYPE_VESA_LFB 0x23
#define XEN_VGATYPE_EFI_LFB 0x70
union {
struct {
/* Font height, in pixels. */
uint16_t font_height;
/* Cursor location (column, row). */
uint16_t cursor_x, cursor_y;
/* Number of rows and columns (dimensions in characters). */
uint16_t rows, columns;
} text_mode_3;
struct {
/* Width and height, in pixels. */
uint16_t width, height;
/* Bytes per scan line. */
uint16_t bytes_per_line;
/* Bits per pixel. */
uint16_t bits_per_pixel;
/* LFB physical address, and size (in units of 64kB). */
uint32_t lfb_base;
uint32_t lfb_size;
/* RGB mask offsets and sizes, as defined by VBE 1.2+ */
uint8_t red_pos, red_size;
uint8_t green_pos, green_size;
uint8_t blue_pos, blue_size;
uint8_t rsvd_pos, rsvd_size;
#if __XEN_INTERFACE_VERSION__ >= 0x00030206
/* VESA capabilities (offset 0xa, VESA command 0x4f00). */
uint32_t gbl_caps;
/* Mode attributes (offset 0x0, VESA command 0x4f01). */
uint16_t mode_attrs;
#endif
} vesa_lfb;
} u;
} dom0_vga_console_info_t;
#define xen_vga_console_info dom0_vga_console_info
#define xen_vga_console_info_t dom0_vga_console_info_t
typedef uint8_t xen_domain_handle_t[16];
/* Turn a plain number into a C unsigned long constant. */
#define __mk_unsigned_long(x) x ## UL
#define mk_unsigned_long(x) __mk_unsigned_long(x)
__DEFINE_XEN_GUEST_HANDLE(uint8, uint8_t);
__DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t);
__DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t);
__DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
#else /* __ASSEMBLY__ */
/* In assembly code we cannot use C numeric constant suffixes. */
#define mk_unsigned_long(x) x
#endif /* !__ASSEMBLY__ */
/* Default definitions for macros used by domctl/sysctl. */
#if defined(__XEN__) || defined(__XEN_TOOLS__)
#ifndef uint64_aligned_t
#define uint64_aligned_t uint64_t
#endif
#ifndef XEN_GUEST_HANDLE_64
#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name)
#endif
#ifndef __ASSEMBLY__
struct xenctl_bitmap {
XEN_GUEST_HANDLE_64(uint8) bitmap;
uint32_t nr_bits;
};
#endif
#endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
#endif /* __XEN_PUBLIC_XEN_H__ */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/

View file

@ -6,7 +6,7 @@ autogenerated="en@quot en@hebrew de@hebrew en@cyrillic en@greek en@arabic en@pig
for x in $autogenerated; do
rm "po/$x.po";
rm -f "po/$x.po";
done

View file

@ -3,5 +3,5 @@
DISTFILES.common.extra2 = swiss.sed Rules-swiss
de_CH.po-create: de.po swiss.sed
LC_ALL=en_US.UTF-8 $(MSGFILTER) -i $< -o $(srcdir)/de_CH.po sed -f $(srcdir)/swiss.sed
LC_ALL=C.UTF-8 $(MSGFILTER) -i $< -o $(srcdir)/de_CH.po sed -f $(srcdir)/swiss.sed

View file

@ -1,16 +1,16 @@
DISTFILES.common.extra4 = hebrew.sed cyrillic.sed greek.sed arabic.sed Rules-translit
de@hebrew.po-create: de.po hebrew.sed
LC_ALL=en_US.UTF-8 $(MSGFILTER) -i $< -o $(srcdir)/de@hebrew.po sed -f $(srcdir)/hebrew.sed
LC_ALL=C $(MSGFILTER) -i $< -o $(srcdir)/de@hebrew.po sed -f $(srcdir)/hebrew.sed
en@hebrew.po-create: $(DOMAIN).pot hebrew.sed
LC_ALL=en_US.UTF-8 $(MSGINIT) -i $(srcdir)/$(DOMAIN).pot --no-translator -l en@hebrew -o - 2>/dev/null | LC_ALL=en_US.UTF-8 $(MSGCONV) -t UTF-8 | LC_ALL=en_US.UTF-8 $(MSGFILTER) -o $(srcdir)/en@hebrew.po -i - sed -f $(srcdir)/hebrew.sed
LC_ALL=C $(MSGINIT) -i $(srcdir)/$(DOMAIN).pot --no-translator -l en@hebrew -o - 2>/dev/null | LC_ALL=C $(MSGCONV) -t UTF-8 | LC_ALL=C $(MSGFILTER) -o $(srcdir)/en@hebrew.po -i - sed -f $(srcdir)/hebrew.sed
en@cyrillic.po-create: $(DOMAIN).pot cyrillic.sed
LC_ALL=en_US.UTF-8 $(MSGINIT) -i $(srcdir)/$(DOMAIN).pot --no-translator -l en@cyrillic -o - 2>/dev/null | LC_ALL=en_US.UTF-8 $(MSGCONV) -t UTF-8 | LC_ALL=en_US.UTF-8 $(MSGFILTER) -o $(srcdir)/en@cyrillic.po -i - sed -f $(srcdir)/cyrillic.sed
LC_ALL=C $(MSGINIT) -i $(srcdir)/$(DOMAIN).pot --no-translator -l en@cyrillic -o - 2>/dev/null | LC_ALL=C $(MSGCONV) -t UTF-8 | LC_ALL=C $(MSGFILTER) -o $(srcdir)/en@cyrillic.po -i - sed -f $(srcdir)/cyrillic.sed
en@greek.po-create: $(DOMAIN).pot greek.sed
LC_ALL=en_US.UTF-8 $(MSGINIT) -i $(srcdir)/$(DOMAIN).pot --no-translator -l en@greek -o - 2>/dev/null | LC_ALL=en_US.UTF-8 $(MSGCONV) -t UTF-8 | LC_ALL=en_US.UTF-8 $(MSGFILTER) -o $(srcdir)/en@greek.po -i - sed -f $(srcdir)/greek.sed
LC_ALL=C $(MSGINIT) -i $(srcdir)/$(DOMAIN).pot --no-translator -l en@greek -o - 2>/dev/null | LC_ALL=C $(MSGCONV) -t UTF-8 | LC_ALL=C $(MSGFILTER) -o $(srcdir)/en@greek.po -i - sed -f $(srcdir)/greek.sed
en@arabic.po-create: $(DOMAIN).pot arabic.sed
LC_ALL=en_US.UTF-8 $(MSGINIT) -i $(srcdir)/$(DOMAIN).pot --no-translator -l en@arabic -o - 2>/dev/null | LC_ALL=en_US.UTF-8 $(MSGCONV) -t UTF-8 | LC_ALL=en_US.UTF-8 $(MSGFILTER) -o $(srcdir)/en@arabic.po -i - sed -f $(srcdir)/arabic.sed
LC_ALL=C $(MSGINIT) -i $(srcdir)/$(DOMAIN).pot --no-translator -l en@arabic -o - 2>/dev/null | LC_ALL=C $(MSGCONV) -t UTF-8 | LC_ALL=C $(MSGFILTER) -o $(srcdir)/en@arabic.po -i - sed -f $(srcdir)/arabic.sed

View file

@ -10,8 +10,84 @@
/^Content-Transfer-Encoding:/ b
/^Plural-Forms:/ b
y,abcdefghijklmnopqrstuvwxyz,абцдефгхийклмнопќрстувўѯѝз,
y,ABCDEFGHIJKLMNOPQRSTUVWXYZ,АБЦДЕФГХИЙКЛМНОПЌРСТУВЎѮЍЗ,
s,a,а,g
s,b,б,g
s,c,ц,g
s,d,д,g
s,e,е,g
s,f,ф,g
s,g,г,g
s,h,х,g
s,i,и,g
s,j,й,g
s,k,к,g
s,l,л,g
s,m,м,g
s,n,н,g
s,o,о,g
s,p,п,g
s,q,ќ,g
s,r,р,g
s,s,с,g
s,t,т,g
s,u,у,g
s,v,в,g
s,w,ў,g
s,x,ѯ,g
s,y,ѝ,g
s,z,з,g
s,A,А,g
s,B,Б,g
s,C,Ц,g
s,D,Д,g
s,E,Е,g
s,F,Ф,g
s,G,Г,g
s,H,Х,g
s,I,И,g
s,J,Й,g
s,K,К,g
s,L,Л,g
s,M,М,g
s,N,Н,g
s,O,О,g
s,P,П,g
s,Q,Ќ,g
s,R,Р,g
s,S,С,g
s,T,Т,g
s,U,У,g
s,V,В,g
s,W,Ў,g
s,X,Ѯ,g
s,Y,Ѝ,g
s,Z,З,g
s,А,А,g
s,Б,Б,g
s,Ц,Ц,g
s,Д,Д,g
s,Е,Е,g
s,Ф,Ф,g
s,Г,Г,g
s,Х,Х,g
s,И,И,g
s,Й,Й,g
s,К,К,g
s,Л,Л,g
s,М,М,g
s,Н,Н,g
s,О,О,g
s,П,П,g
s,Ќ,Ќ,g
s,Р,Р,g
s,С,С,g
s,Т,Т,g
s,У,У,g
s,В,В,g
s,Ў,Ў,g
s,Ѯ,Ѯ,g
s,Ѝ,Ѝ,g
s,З,З,g
s,%\([0-9]*\)Ц,%\1C,g
s,%\([0-9]*\)ц,%\1c,g

View file

@ -12,8 +12,84 @@
s,%\([0-9]*\)C,%\1#,g
y,abcdefghijklmnopqrstuvwxyz,αϭϲδεφγχιϊκλμνοπϗρστυβωξϋζ,
y,ABCDEFGHIJKLMNOPQRSTUVWXYZ,ΑϬϲΔΕΦΓΧΙΪΚΛΜΝΟΠϏΡΣΤΥΒΩΞΫΖ,
s,a,α,g
s,b,ϭ,g
s,c,ϲ,g
s,d,δ,g
s,e,ε,g
s,f,φ,g
s,g,γ,g
s,h,χ,g
s,i,ι,g
s,j,ϊ,g
s,k,κ,g
s,l,λ,g
s,m,μ,g
s,n,ν,g
s,o,ο,g
s,p,π,g
s,q,ϗ,g
s,r,ρ,g
s,s,σ,g
s,t,τ,g
s,u,υ,g
s,v,β,g
s,w,ω,g
s,x,ξ,g
s,y,ϋ,g
s,z,ζ,g
s,A,Α,g
s,B,Ϭ,g
s,C,ϲ,g
s,D,Δ,g
s,E,Ε,g
s,F,Φ,g
s,G,Γ,g
s,H,Χ,g
s,I,Ι,g
s,J,Ϊ,g
s,K,Κ,g
s,L,Λ,g
s,M,Μ,g
s,N,Ν,g
s,O,Ο,g
s,P,Π,g
s,Q,Ϗ,g
s,R,Ρ,g
s,S,Σ,g
s,T,Τ,g
s,U,Υ,g
s,V,Β,g
s,W,Ω,g
s,X,Ξ,g
s,Y,Ϋ,g
s,Z,Ζ,g
s,А,А,g
s,Б,Б,g
s,Ц,Ц,g
s,Д,Д,g
s,Е,Е,g
s,Ф,Ф,g
s,Г,Г,g
s,Х,Х,g
s,И,И,g
s,Й,Й,g
s,К,К,g
s,Л,Л,g
s,М,М,g
s,Н,Н,g
s,О,О,g
s,П,П,g
s,Ќ,Ќ,g
s,Р,Р,g
s,С,С,g
s,Т,Т,g
s,У,У,g
s,В,В,g
s,Ў,Ў,g
s,Ѯ,Ѯ,g
s,Ѝ,Ѝ,g
s,З,З,g
s,%\([0-9]*\)#,%\1C,g
s,%\([0-9]*\)ϲ,%\1c,g

View file

@ -92,6 +92,12 @@ case "${grub_modinfo_target_cpu}-${grub_modinfo_platform}" in
disk=hd0
;;
esac
if ! which parted >/dev/null 2>&1; then
echo "parted not installed; cannot test partmap"
exit 77
fi
imgfile="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1
outfile="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1

View file

@ -10,7 +10,7 @@ tempdir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1
# This wrapper is to ease insertion of valgrind or time statistics
run_it () {
"$GRUBFSTEST" "$@"
LC_ALL=C "$GRUBFSTEST" "$@"
}
run_grubfstest () {

View file

@ -1698,7 +1698,7 @@ main (int argc, char *argv[])
/* Now perform the installation. */
if (install_bootsector)
grub_util_sparc_setup (platdir, "boot.img", "core.img",
install_device, force,
install_drive, force,
fs_probe, allow_floppy,
0 /* unused */ );
break;

View file

@ -101,7 +101,7 @@ SUFFIX (generate_elf) (const struct grub_install_image_target_desc *image_target
program_size = ALIGN_ADDR (*core_size);
elf_img = xmalloc (program_size + header_size + footer_size);
memset (elf_img, 0, program_size + header_size);
memset (elf_img, 0, program_size + header_size + footer_size);
memcpy (elf_img + header_size, *core_img, *core_size);
ehdr = (void *) elf_img;
phdr = (void *) (elf_img + sizeof (*ehdr));
@ -1587,6 +1587,7 @@ SUFFIX (load_image) (const char *kernel_path, size_t *exec_size,
}
out_img = xmalloc (*kernel_sz + total_module_size);
memset (out_img, 0, *kernel_sz + total_module_size);
if (image_target->id == IMAGE_EFI)
{

View file

@ -992,7 +992,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
{
char *kernel_img, *core_img;
size_t kernel_size, total_module_size, core_size, exec_size;
size_t memdisk_size = 0, config_size = 0, config_size_pure = 0;
size_t memdisk_size = 0, config_size = 0;
size_t prefix_size = 0;
char *kernel_path;
size_t offset;
@ -1043,8 +1043,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
if (config_path)
{
config_size_pure = grub_util_get_image_size (config_path) + 1;
config_size = ALIGN_ADDR (config_size_pure);
config_size = ALIGN_ADDR (grub_util_get_image_size (config_path) + 1);
grub_util_info ("the size of config file is 0x%" GRUB_HOST_PRIxLONG_LONG,
(unsigned long long) config_size);
total_module_size += config_size + sizeof (struct grub_module_header);
@ -1080,7 +1079,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
= grub_host_to_target32 (total_module_size);
if (image_target->flags & PLATFORM_FLAGS_MODULES_BEFORE_KERNEL)
memmove (kernel_img + total_module_size, kernel_img, kernel_size);
{
memmove (kernel_img + total_module_size, kernel_img, kernel_size);
memset (kernel_img, 0, total_module_size);
}
if (image_target->voidp_sizeof == 8)
{
@ -1090,7 +1092,6 @@ grub_install_generate_image (const char *dir, const char *prefix,
modinfo = (struct grub_module_info64 *) kernel_img;
else
modinfo = (struct grub_module_info64 *) (kernel_img + kernel_size);
memset (modinfo, 0, sizeof (struct grub_module_info64));
modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info64));
modinfo->size = grub_host_to_target_addr (total_module_size);
@ -1107,7 +1108,6 @@ grub_install_generate_image (const char *dir, const char *prefix,
modinfo = (struct grub_module_info32 *) kernel_img;
else
modinfo = (struct grub_module_info32 *) (kernel_img + kernel_size);
memset (modinfo, 0, sizeof (struct grub_module_info32));
modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC);
modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info32));
modinfo->size = grub_host_to_target_addr (total_module_size);
@ -1120,17 +1120,14 @@ grub_install_generate_image (const char *dir, const char *prefix,
for (p = path_list; p; p = p->next)
{
struct grub_module_header *header;
size_t mod_size, orig_size;
size_t mod_size;
orig_size = grub_util_get_image_size (p->name);
mod_size = ALIGN_ADDR (orig_size);
mod_size = ALIGN_ADDR (grub_util_get_image_size (p->name));
header = (struct grub_module_header *) (kernel_img + offset);
memset (header, 0, sizeof (struct grub_module_header));
header->type = grub_host_to_target32 (OBJ_TYPE_ELF);
header->size = grub_host_to_target32 (mod_size + sizeof (*header));
offset += sizeof (*header);
memset (kernel_img + offset + orig_size, 0, mod_size - orig_size);
grub_util_load_image (p->name, kernel_img + offset);
offset += mod_size;
@ -1146,7 +1143,6 @@ grub_install_generate_image (const char *dir, const char *prefix,
curs = grub_util_get_image_size (pubkey_paths[i]);
header = (struct grub_module_header *) (kernel_img + offset);
memset (header, 0, sizeof (struct grub_module_header));
header->type = grub_host_to_target32 (OBJ_TYPE_PUBKEY);
header->size = grub_host_to_target32 (curs + sizeof (*header));
offset += sizeof (*header);
@ -1161,7 +1157,6 @@ grub_install_generate_image (const char *dir, const char *prefix,
struct grub_module_header *header;
header = (struct grub_module_header *) (kernel_img + offset);
memset (header, 0, sizeof (struct grub_module_header));
header->type = grub_host_to_target32 (OBJ_TYPE_MEMDISK);
header->size = grub_host_to_target32 (memdisk_size + sizeof (*header));
offset += sizeof (*header);
@ -1175,13 +1170,11 @@ grub_install_generate_image (const char *dir, const char *prefix,
struct grub_module_header *header;
header = (struct grub_module_header *) (kernel_img + offset);
memset (header, 0, sizeof (struct grub_module_header));
header->type = grub_host_to_target32 (OBJ_TYPE_CONFIG);
header->size = grub_host_to_target32 (config_size + sizeof (*header));
offset += sizeof (*header);
grub_util_load_image (config_path, kernel_img + offset);
*(kernel_img + offset + config_size_pure - 1) = 0;
offset += config_size;
}
@ -1190,12 +1183,10 @@ grub_install_generate_image (const char *dir, const char *prefix,
struct grub_module_header *header;
header = (struct grub_module_header *) (kernel_img + offset);
memset (header, 0, sizeof (struct grub_module_header));
header->type = grub_host_to_target32 (OBJ_TYPE_PREFIX);
header->size = grub_host_to_target32 (prefix_size + sizeof (*header));
offset += sizeof (*header);
grub_memset (kernel_img + offset, 0, prefix_size);
grub_strcpy (kernel_img + offset, prefix);
offset += prefix_size;
}
@ -1269,15 +1260,11 @@ grub_install_generate_image (const char *dir, const char *prefix,
full_size = core_size + decompress_size;
full_img = xmalloc (full_size);
memset (full_img, 0, full_size);
memcpy (full_img, decompress_img, decompress_size);
memcpy (full_img + decompress_size, core_img, core_size);
memset (full_img + decompress_size + core_size, 0,
full_size - (decompress_size + core_size));
free (core_img);
core_img = full_img;
core_size = full_size;
@ -1428,6 +1415,7 @@ grub_install_generate_image (const char *dir, const char *prefix,
pe_img = xmalloc (reloc_addr + reloc_size);
memset (pe_img, 0, header_size);
memcpy ((char *) pe_img + header_size, core_img, core_size);
memset ((char *) pe_img + header_size + core_size, 0, reloc_addr - (header_size + core_size));
memcpy ((char *) pe_img + reloc_addr, rel_section, reloc_size);
header = pe_img;