summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/arch
diff options
context:
space:
mode:
authorDon Dugger <n0ano@n0ano.com>2016-06-03 03:33:22 +0000
committerGerrit Code Review <gerrit@172.30.200.206>2016-06-03 03:33:23 +0000
commitda27230f80795d0028333713f036d44c53cb0e68 (patch)
treeb3d379eaf000adf72b36cb01cdf4d79c3e3f064c /qemu/roms/ipxe/src/arch
parent0e68cb048bb8aadb14675f5d4286d8ab2fc35449 (diff)
parent437fd90c0250dee670290f9b714253671a990160 (diff)
Merge "These changes are the raw update to qemu-2.6."
Diffstat (limited to 'qemu/roms/ipxe/src/arch')
-rw-r--r--qemu/roms/ipxe/src/arch/i386/Makefile11
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/basemem_packet.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/cachedhcp.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/gdbmach.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/patch_cf.S6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/pci_autoboot.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/rdtsc_timer.c12
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/relocate.c2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/runtime.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/setjmp.S84
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/stack.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/stack16.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/timer2.c87
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/virtaddr.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/drivers/net/undi.c7
-rw-r--r--qemu/roms/ipxe/src/arch/i386/drivers/net/undiload.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/drivers/net/undionly.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/drivers/net/undipreload.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/firmware/pcbios/basemem.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/firmware/pcbios/bios_console.c12
-rw-r--r--qemu/roms/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/firmware/pcbios/fakee820.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/firmware/pcbios/hidemem.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/firmware/pcbios/memmap.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/hci/commands/pxe_cmd.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/image/bootsector.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/image/bzimage.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/image/elfboot.c39
-rw-r--r--qemu/roms/ipxe/src/arch/i386/image/initrd.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/image/multiboot.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/image/pxe_image.c52
-rw-r--r--qemu/roms/ipxe/src/arch/i386/image/sdi.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/basemem.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/basemem_packet.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bios.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/biosint.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/byteswap.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/compiler.h5
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/endian.h8
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/entropy.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/hyperv.h72
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/nap.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/profile.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/reboot.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/sanboot.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/smbios.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/stdint.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/strings.h48
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/time.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/timer.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/uaccess.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bits/umalloc.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bootsector.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/bzimage.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h11
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/fakee820.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/initrd.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/int13.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_nap.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_reboot.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_smbios.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_timer.h8
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/errno/pcbios.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/guestrpc.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/memtop_umalloc.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/msr.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/rdtsc_timer.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/rtc_time.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/timer2.h14
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/vesafb.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/ipxe/vmware.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/librm.h14
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/limits.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/memsizes.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/multiboot.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h11
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/pnpbios.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/pxe.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/pxe_api.h6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/pxe_call.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/pxe_error.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/pxe_types.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/realmode.h14
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/registers.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/rtc.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/sdi.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/setjmp.h46
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/undi.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/undiload.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/undinet.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/undipreload.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/include/undirom.h2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/apm.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_nap.c2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_reboot.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/biosint.c2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13con.c284
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c12
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/vesafb.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c7
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c24
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c43
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c130
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c29
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/vmware/vmware.c6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/bootpart.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/exeprefix.S6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/hdprefix.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/isaromprefix.S6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/kkkpxeprefix.S6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/kkpxeprefix.S5
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/kpxeprefix.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/libprefix.S75
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/lkrnprefix.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/mbr.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/mromprefix.S7
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/nbiprefix.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/nullprefix.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/pciromprefix.S6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/pxeprefix.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/romprefix.S31
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/undiloader.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/unlzma.S942
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/unlzma16.S (renamed from qemu/roms/ipxe/src/arch/i386/prefix/unnrv2b16.S)4
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/unnrv2b.S184
-rw-r--r--qemu/roms/ipxe/src/arch/i386/prefix/usbdisk.S23
-rw-r--r--qemu/roms/ipxe/src/arch/i386/scripts/i386.lds9
-rw-r--r--qemu/roms/ipxe/src/arch/i386/transitions/liba20.S6
-rw-r--r--qemu/roms/ipxe/src/arch/i386/transitions/libkir.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/transitions/librm.S2
-rw-r--r--qemu/roms/ipxe/src/arch/i386/transitions/librm_mgmt.c4
-rw-r--r--qemu/roms/ipxe/src/arch/i386/transitions/librm_test.c7
-rw-r--r--qemu/roms/ipxe/src/arch/x86/Makefile5
-rw-r--r--qemu/roms/ipxe/src/arch/x86/Makefile.efi2
-rw-r--r--qemu/roms/ipxe/src/arch/x86/core/cpuid.c6
-rw-r--r--qemu/roms/ipxe/src/arch/x86/core/cpuid_settings.c6
-rw-r--r--qemu/roms/ipxe/src/arch/x86/core/debugcon.c6
-rw-r--r--qemu/roms/ipxe/src/arch/x86/core/pcidirect.c6
-rw-r--r--qemu/roms/ipxe/src/arch/x86/core/pic8259.c (renamed from qemu/roms/ipxe/src/arch/i386/core/pic8259.c)0
-rw-r--r--qemu/roms/ipxe/src/arch/x86/core/pit8254.c70
-rw-r--r--qemu/roms/ipxe/src/arch/x86/core/vram_settings.c72
-rw-r--r--qemu/roms/ipxe/src/arch/x86/core/x86_bigint.c6
-rw-r--r--qemu/roms/ipxe/src/arch/x86/core/x86_io.c6
-rw-r--r--qemu/roms/ipxe/src/arch/x86/core/x86_string.c90
-rw-r--r--qemu/roms/ipxe/src/arch/x86/core/x86_tcpip.c6
-rw-r--r--qemu/roms/ipxe/src/arch/x86/core/x86_uart.c69
-rw-r--r--qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.c597
-rw-r--r--qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.h57
-rw-r--r--qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.c9
-rw-r--r--qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c6
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/bits/bigint.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/bits/endian.h8
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/bits/errfile.h6
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/bits/io.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/bits/pci_io.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/bits/string.h140
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/bits/tcpip.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/bits/uart.h41
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/bits/xen.h21
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/ipxe/cpuid.h5
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/ipxe/efi/efix86_nap.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/ipxe/pcibios.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/ipxe/pcidirect.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/ipxe/pit8254.h81
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/ipxe/x86_io.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/linux/ipxe/dhcp_arch.h11
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/pic8259.h (renamed from qemu/roms/ipxe/src/arch/i386/include/pic8259.h)5
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/valgrind/memcheck.h311
-rw-r--r--qemu/roms/ipxe/src/arch/x86/include/valgrind/valgrind.h4538
-rw-r--r--qemu/roms/ipxe/src/arch/x86/interface/efi/efi_entropy.c223
-rw-r--r--qemu/roms/ipxe/src/arch/x86/interface/efi/efix86_nap.c6
-rw-r--r--qemu/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c35
-rw-r--r--qemu/roms/ipxe/src/arch/x86/prefix/efiprefix.c5
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/Makefile1
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/core/setjmp.S65
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/bits/byteswap.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/bits/compiler.h3
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/bits/endian.h6
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/bits/entropy.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/bits/hyperv.h75
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/bits/profile.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/bits/reboot.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/bits/sanboot.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/bits/strings.h40
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/bits/time.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h11
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/ipxe/msr.h2
-rw-r--r--qemu/roms/ipxe/src/arch/x86_64/include/setjmp.h34
205 files changed, 3883 insertions, 5612 deletions
diff --git a/qemu/roms/ipxe/src/arch/i386/Makefile b/qemu/roms/ipxe/src/arch/i386/Makefile
index 4925cc4e6..99f875314 100644
--- a/qemu/roms/ipxe/src/arch/i386/Makefile
+++ b/qemu/roms/ipxe/src/arch/i386/Makefile
@@ -69,6 +69,17 @@ CFLAGS += -fshort-wchar
#
CFLAGS += -Ui386
+# Some widespread patched versions of gcc include -fPIE -Wl,-pie by
+# default. Note that gcc will exit *successfully* if it fails to
+# recognise an option that starts with "no", so we have to test for
+# output on stderr instead of checking the exit status.
+#
+ifeq ($(CCTYPE),gcc)
+PIE_TEST = [ -z "`$(CC) -fno-PIE -nopie -x c -c /dev/null -o /dev/null 2>&1`" ]
+PIE_FLAGS := $(shell $(PIE_TEST) && $(ECHO) '-fno-PIE -nopie')
+WORKAROUND_CFLAGS += $(PIE_FLAGS)
+endif
+
# Define version string for lkrnprefix.S
#
CFLAGS_lkrnprefix += -DVERSION="\"$(VERSION)\""
diff --git a/qemu/roms/ipxe/src/arch/i386/core/basemem_packet.c b/qemu/roms/ipxe/src/arch/i386/core/basemem_packet.c
index 06ffa3bbd..9f5fbf330 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/basemem_packet.c
+++ b/qemu/roms/ipxe/src/arch/i386/core/basemem_packet.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* @file
diff --git a/qemu/roms/ipxe/src/arch/i386/core/cachedhcp.c b/qemu/roms/ipxe/src/arch/i386/core/cachedhcp.c
index 3cac28e7d..a5c624035 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/cachedhcp.c
+++ b/qemu/roms/ipxe/src/arch/i386/core/cachedhcp.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stdlib.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/core/gdbmach.c b/qemu/roms/ipxe/src/arch/i386/core/gdbmach.c
index 4d6897f7d..d92a4ac08 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/gdbmach.c
+++ b/qemu/roms/ipxe/src/arch/i386/core/gdbmach.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stddef.h>
#include <stdio.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/core/patch_cf.S b/qemu/roms/ipxe/src/arch/i386/core/patch_cf.S
index 97a62f494..4365563fe 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/patch_cf.S
+++ b/qemu/roms/ipxe/src/arch/i386/core/patch_cf.S
@@ -14,9 +14,13 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.text
.arch i386
diff --git a/qemu/roms/ipxe/src/arch/i386/core/pci_autoboot.c b/qemu/roms/ipxe/src/arch/i386/core/pci_autoboot.c
index a3eb1f97d..337598091 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/pci_autoboot.c
+++ b/qemu/roms/ipxe/src/arch/i386/core/pci_autoboot.c
@@ -16,9 +16,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/device.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/core/rdtsc_timer.c b/qemu/roms/ipxe/src/arch/i386/core/rdtsc_timer.c
index 2f31afc66..e720a239c 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/rdtsc_timer.c
+++ b/qemu/roms/ipxe/src/arch/i386/core/rdtsc_timer.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
@@ -27,7 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <assert.h>
#include <ipxe/timer.h>
-#include <ipxe/timer2.h>
+#include <ipxe/pit8254.h>
/**
* Number of TSC ticks per microsecond
@@ -56,10 +60,10 @@ static void rdtsc_udelay ( unsigned long usecs ) {
elapsed = ( currticks() - start );
} while ( elapsed < ( usecs * rdtsc_ticks_per_usec ) );
} else {
- /* Not yet calibrated; use timer2 and calibrate
+ /* Not yet calibrated; use 8254 PIT and calibrate
* based on result.
*/
- timer2_udelay ( usecs );
+ pit8254_udelay ( usecs );
elapsed = ( currticks() - start );
rdtsc_ticks_per_usec = ( elapsed / usecs );
DBG ( "RDTSC timer calibrated: %ld ticks in %ld usecs "
diff --git a/qemu/roms/ipxe/src/arch/i386/core/relocate.c b/qemu/roms/ipxe/src/arch/i386/core/relocate.c
index 5fbf2d2c2..54ad387e4 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/relocate.c
+++ b/qemu/roms/ipxe/src/arch/i386/core/relocate.c
@@ -8,7 +8,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/*
* The linker passes in the symbol _max_align, which is the alignment
diff --git a/qemu/roms/ipxe/src/arch/i386/core/runtime.c b/qemu/roms/ipxe/src/arch/i386/core/runtime.c
index 18ca7936e..d160fee04 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/runtime.c
+++ b/qemu/roms/ipxe/src/arch/i386/core/runtime.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
diff --git a/qemu/roms/ipxe/src/arch/i386/core/setjmp.S b/qemu/roms/ipxe/src/arch/i386/core/setjmp.S
index 03727148c..81d3b4911 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/setjmp.S
+++ b/qemu/roms/ipxe/src/arch/i386/core/setjmp.S
@@ -1,42 +1,64 @@
-/* setjmp and longjmp. Use of these functions is deprecated. */
-
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.text
.arch i386
.code32
-
-/**************************************************************************
-SETJMP - Save stack context for non-local goto
-**************************************************************************/
+
+ /* Must match jmp_buf structure layout */
+ .struct 0
+env_retaddr: .long 0
+env_stack: .long 0
+env_ebx: .long 0
+env_esi: .long 0
+env_edi: .long 0
+env_ebp: .long 0
+ .previous
+
+/*
+ * Save stack context for non-local goto
+ */
.globl setjmp
setjmp:
- movl 4(%esp),%ecx /* jmpbuf */
- movl 0(%esp),%edx /* return address */
- movl %edx,0(%ecx)
- movl %ebx,4(%ecx)
- movl %esp,8(%ecx)
- movl %ebp,12(%ecx)
- movl %esi,16(%ecx)
- movl %edi,20(%ecx)
- movl $0,%eax
+ /* Get jmp_buf pointer in %edx */
+ movl 4(%esp),%edx
+ /* Save return address */
+ movl 0(%esp),%eax
+ movl %eax, env_retaddr(%edx)
+ /* Save stack pointer */
+ movl %esp, env_stack(%edx)
+ /* Save other registers */
+ movl %ebx, env_ebx(%edx)
+ movl %esi, env_esi(%edx)
+ movl %edi, env_edi(%edx)
+ movl %ebp, env_ebp(%edx)
+ /* Return 0 when returning as setjmp() */
+ xorl %eax, %eax
ret
+ .size setjmp, . - setjmp
-/**************************************************************************
-LONGJMP - Non-local jump to a saved stack context
-**************************************************************************/
+/*
+ * Non-local jump to a saved stack context
+ */
.globl longjmp
longjmp:
- movl 4(%esp),%edx /* jumpbuf */
- movl 8(%esp),%eax /* result */
- movl 0(%edx),%ecx
- movl 4(%edx),%ebx
- movl 8(%edx),%esp
- movl 12(%edx),%ebp
- movl 16(%edx),%esi
- movl 20(%edx),%edi
- cmpl $0,%eax
- jne 1f
- movl $1,%eax
-1: movl %ecx,0(%esp)
+ /* Get jmp_buf pointer in %edx */
+ movl 4(%esp),%edx
+ /* Get result in %eax */
+ movl 8(%esp),%eax
+ /* Force result to non-zero */
+ testl %eax, %eax
+ jnz 1f
+ incl %eax
+1: /* Restore stack pointer */
+ movl env_stack(%edx), %esp
+ /* Restore other registers */
+ movl env_ebx(%edx), %ebx
+ movl env_esi(%edx), %esi
+ movl env_edi(%edx), %edi
+ movl env_ebp(%edx), %ebp
+ /* Replace return address on the new stack */
+ popl %ecx /* discard */
+ pushl env_retaddr(%edx)
+ /* Return to setjmp() caller */
ret
+ .size longjmp, . - longjmp
diff --git a/qemu/roms/ipxe/src/arch/i386/core/stack.S b/qemu/roms/ipxe/src/arch/i386/core/stack.S
index 737ec0eed..98f1cd9b9 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/stack.S
+++ b/qemu/roms/ipxe/src/arch/i386/core/stack.S
@@ -1,4 +1,4 @@
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.arch i386
diff --git a/qemu/roms/ipxe/src/arch/i386/core/stack16.S b/qemu/roms/ipxe/src/arch/i386/core/stack16.S
index 523f0288b..4bc6f081a 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/stack16.S
+++ b/qemu/roms/ipxe/src/arch/i386/core/stack16.S
@@ -1,4 +1,4 @@
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.arch i386
diff --git a/qemu/roms/ipxe/src/arch/i386/core/timer2.c b/qemu/roms/ipxe/src/arch/i386/core/timer2.c
deleted file mode 100644
index 077866562..000000000
--- a/qemu/roms/ipxe/src/arch/i386/core/timer2.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * arch/i386/core/i386_timer.c
- *
- * Use the "System Timer 2" to implement the udelay callback in
- * the BIOS timer driver. Also used to calibrate the clock rate
- * in the RTDSC timer driver.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2, or (at
- * your option) any later version.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <stddef.h>
-#include <ipxe/timer2.h>
-#include <ipxe/io.h>
-
-/* Timers tick over at this rate */
-#define TIMER2_TICKS_PER_SEC 1193180U
-
-/* Parallel Peripheral Controller Port B */
-#define PPC_PORTB 0x61
-
-/* Meaning of the port bits */
-#define PPCB_T2OUT 0x20 /* Bit 5 */
-#define PPCB_SPKR 0x02 /* Bit 1 */
-#define PPCB_T2GATE 0x01 /* Bit 0 */
-
-/* Ports for the 8254 timer chip */
-#define TIMER2_PORT 0x42
-#define TIMER_MODE_PORT 0x43
-
-/* Meaning of the mode bits */
-#define TIMER0_SEL 0x00
-#define TIMER1_SEL 0x40
-#define TIMER2_SEL 0x80
-#define READBACK_SEL 0xC0
-
-#define LATCH_COUNT 0x00
-#define LOBYTE_ACCESS 0x10
-#define HIBYTE_ACCESS 0x20
-#define WORD_ACCESS 0x30
-
-#define MODE0 0x00
-#define MODE1 0x02
-#define MODE2 0x04
-#define MODE3 0x06
-#define MODE4 0x08
-#define MODE5 0x0A
-
-#define BINARY_COUNT 0x00
-#define BCD_COUNT 0x01
-
-static void load_timer2 ( unsigned int ticks ) {
- /*
- * Now let's take care of PPC channel 2
- *
- * Set the Gate high, program PPC channel 2 for mode 0,
- * (interrupt on terminal count mode), binary count,
- * load 5 * LATCH count, (LSB and MSB) to begin countdown.
- *
- * Note some implementations have a bug where the high bits byte
- * of channel 2 is ignored.
- */
- /* Set up the timer gate, turn off the speaker */
- /* Set the Gate high, disable speaker */
- outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
- /* binary, mode 0, LSB/MSB, Ch 2 */
- outb(TIMER2_SEL|WORD_ACCESS|MODE0|BINARY_COUNT, TIMER_MODE_PORT);
- /* LSB of ticks */
- outb(ticks & 0xFF, TIMER2_PORT);
- /* MSB of ticks */
- outb(ticks >> 8, TIMER2_PORT);
-}
-
-static int timer2_running ( void ) {
- return ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
-}
-
-void timer2_udelay ( unsigned long usecs ) {
- load_timer2 ( ( usecs * TIMER2_TICKS_PER_SEC ) / ( 1000 * 1000 ) );
- while (timer2_running()) {
- /* Do nothing */
- }
-}
diff --git a/qemu/roms/ipxe/src/arch/i386/core/virtaddr.S b/qemu/roms/ipxe/src/arch/i386/core/virtaddr.S
index 5e5d77352..425591570 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/virtaddr.S
+++ b/qemu/roms/ipxe/src/arch/i386/core/virtaddr.S
@@ -4,7 +4,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include "librm.h"
diff --git a/qemu/roms/ipxe/src/arch/i386/drivers/net/undi.c b/qemu/roms/ipxe/src/arch/i386/drivers/net/undi.c
index 2bc54824c..9820cf629 100644
--- a/qemu/roms/ipxe/src/arch/i386/drivers/net/undi.c
+++ b/qemu/roms/ipxe/src/arch/i386/drivers/net/undi.c
@@ -68,10 +68,6 @@ static int undipci_probe ( struct pci_device *pci ) {
struct undi_rom *undirom;
int rc;
- /* Ignore non-network devices */
- if ( PCI_BASE_CLASS ( pci->class ) != PCI_BASE_CLASS_NETWORK )
- return -ENOTTY;
-
/* Allocate UNDI device structure */
undi = zalloc ( sizeof ( *undi ) );
if ( ! undi )
@@ -138,12 +134,13 @@ static void undipci_remove ( struct pci_device *pci ) {
}
static struct pci_device_id undipci_nics[] = {
-PCI_ROM ( 0xffff, 0xffff, "undipci", "UNDI (PCI)", 0 ),
+ PCI_ROM ( 0xffff, 0xffff, "undipci", "UNDI (PCI)", 0 ),
};
struct pci_driver undipci_driver __pci_driver_fallback = {
.ids = undipci_nics,
.id_count = ( sizeof ( undipci_nics ) / sizeof ( undipci_nics[0] ) ),
+ .class = PCI_CLASS_ID ( PCI_CLASS_NETWORK, PCI_ANY_ID, PCI_ANY_ID ),
.probe = undipci_probe,
.remove = undipci_remove,
};
diff --git a/qemu/roms/ipxe/src/arch/i386/drivers/net/undiload.c b/qemu/roms/ipxe/src/arch/i386/drivers/net/undiload.c
index 77134dcb8..7160ee384 100644
--- a/qemu/roms/ipxe/src/arch/i386/drivers/net/undiload.c
+++ b/qemu/roms/ipxe/src/arch/i386/drivers/net/undiload.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stdlib.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/drivers/net/undionly.c b/qemu/roms/ipxe/src/arch/i386/drivers/net/undionly.c
index 028fac5d9..70dbe4bfd 100644
--- a/qemu/roms/ipxe/src/arch/i386/drivers/net/undionly.c
+++ b/qemu/roms/ipxe/src/arch/i386/drivers/net/undionly.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stdlib.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/drivers/net/undipreload.c b/qemu/roms/ipxe/src/arch/i386/drivers/net/undipreload.c
index 81d7a80eb..fca771843 100644
--- a/qemu/roms/ipxe/src/arch/i386/drivers/net/undipreload.c
+++ b/qemu/roms/ipxe/src/arch/i386/drivers/net/undipreload.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <realmode.h>
#include <undipreload.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/basemem.c b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/basemem.c
index b23f2c356..6a46081aa 100644
--- a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/basemem.c
+++ b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/basemem.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <realmode.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/bios_console.c b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/bios_console.c
index bd73838b5..63413cdc1 100644
--- a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/bios_console.c
+++ b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/bios_console.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <assert.h>
#include <realmode.h>
@@ -39,6 +43,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ATTR_FCOL_YELLOW 0x06
#define ATTR_FCOL_WHITE 0x07
+#define ATTR_BLINK 0x80
+
#define ATTR_BCOL_MASK 0x70
#define ATTR_BCOL_BLACK 0x00
#define ATTR_BCOL_BLUE 0x10
@@ -137,8 +143,12 @@ static void bios_handle_sgr ( struct ansiesc_context *ctx __unused,
bios_attr = ATTR_DEFAULT;
} else if ( aspect == 1 ) {
bios_attr |= ATTR_BOLD;
+ } else if ( aspect == 5 ) {
+ bios_attr |= ATTR_BLINK;
} else if ( aspect == 22 ) {
bios_attr &= ~ATTR_BOLD;
+ } else if ( aspect == 25 ) {
+ bios_attr &= ~ATTR_BLINK;
} else if ( ( aspect >= 30 ) && ( aspect <= 39 ) ) {
bios_attr &= ~ATTR_FCOL_MASK;
bios_attr |= bios_attr_fcols[ aspect - 30 ];
diff --git a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S
index cea17ef8e..d5d97b482 100644
--- a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S
+++ b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/e820mangler.S
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.text
.arch i386
diff --git a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/fakee820.c b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/fakee820.c
index e5f713728..15f4d772f 100644
--- a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/fakee820.c
+++ b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/fakee820.c
@@ -14,9 +14,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <realmode.h>
#include <biosint.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/hidemem.c b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/hidemem.c
index 8f3069e18..253c601ff 100644
--- a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/hidemem.c
+++ b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/hidemem.c
@@ -14,9 +14,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <assert.h>
#include <realmode.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/memmap.c b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/memmap.c
index 0937a7ce2..bcacecd6a 100644
--- a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/memmap.c
+++ b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/memmap.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <errno.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c
index 5c74b0431..20ec35d75 100644
--- a/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c
+++ b/qemu/roms/ipxe/src/arch/i386/firmware/pcbios/pnpbios.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <string.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/hci/commands/pxe_cmd.c b/qemu/roms/ipxe/src/arch/i386/hci/commands/pxe_cmd.c
index 523724ab0..473b97f97 100644
--- a/qemu/roms/ipxe/src/arch/i386/hci/commands/pxe_cmd.c
+++ b/qemu/roms/ipxe/src/arch/i386/hci/commands/pxe_cmd.c
@@ -15,6 +15,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
#include <ipxe/netdevice.h>
@@ -23,7 +27,7 @@
#include <hci/ifmgmt_cmd.h>
#include <pxe_call.h>
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
diff --git a/qemu/roms/ipxe/src/arch/i386/image/bootsector.c b/qemu/roms/ipxe/src/arch/i386/image/bootsector.c
index 9a089e6bb..dba87613c 100644
--- a/qemu/roms/ipxe/src/arch/i386/image/bootsector.c
+++ b/qemu/roms/ipxe/src/arch/i386/image/bootsector.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* @file
diff --git a/qemu/roms/ipxe/src/arch/i386/image/bzimage.c b/qemu/roms/ipxe/src/arch/i386/image/bzimage.c
index 4865c394c..a64206cd3 100644
--- a/qemu/roms/ipxe/src/arch/i386/image/bzimage.c
+++ b/qemu/roms/ipxe/src/arch/i386/image/bzimage.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* @file
diff --git a/qemu/roms/ipxe/src/arch/i386/image/elfboot.c b/qemu/roms/ipxe/src/arch/i386/image/elfboot.c
index 0f6957f02..dc3568929 100644
--- a/qemu/roms/ipxe/src/arch/i386/image/elfboot.c
+++ b/qemu/roms/ipxe/src/arch/i386/image/elfboot.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <errno.h>
#include <elf.h>
@@ -75,6 +79,27 @@ static int elfboot_exec ( struct image *image ) {
}
/**
+ * Check that ELF segment uses flat physical addressing
+ *
+ * @v image ELF file
+ * @v phdr ELF program header
+ * @v dest Destination address
+ * @ret rc Return status code
+ */
+static int elfboot_check_segment ( struct image *image, Elf_Phdr *phdr,
+ physaddr_t dest ) {
+
+ /* Check that ELF segment uses flat physical addressing */
+ if ( phdr->p_vaddr != dest ) {
+ DBGC ( image, "ELF %p uses virtual addressing (phys %x, "
+ "virt %x)\n", image, phdr->p_paddr, phdr->p_vaddr );
+ return -ENOEXEC;
+ }
+
+ return 0;
+}
+
+/**
* Probe ELF image
*
* @v image ELF file
@@ -91,14 +116,24 @@ static int elfboot_probe ( struct image *image ) {
[EI_DATA] = ELFDATA2LSB,
[EI_VERSION] = EV_CURRENT,
};
+ physaddr_t entry;
+ physaddr_t max;
+ int rc;
/* Read ELF header */
copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
if ( memcmp ( ehdr.e_ident, e_ident, sizeof ( e_ident ) ) != 0 ) {
- DBG ( "Invalid ELF identifier\n" );
+ DBGC ( image, "Invalid ELF identifier\n" );
return -ENOEXEC;
}
+ /* Check that this image uses flat physical addressing */
+ if ( ( rc = elf_segments ( image, &ehdr, elfboot_check_segment,
+ &entry, &max ) ) != 0 ) {
+ DBGC ( image, "Unloadable ELF image\n" );
+ return rc;
+ }
+
return 0;
}
diff --git a/qemu/roms/ipxe/src/arch/i386/image/initrd.c b/qemu/roms/ipxe/src/arch/i386/image/initrd.c
index eaba3a645..80c197417 100644
--- a/qemu/roms/ipxe/src/arch/i386/image/initrd.c
+++ b/qemu/roms/ipxe/src/arch/i386/image/initrd.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <errno.h>
#include <initrd.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/image/multiboot.c b/qemu/roms/ipxe/src/arch/i386/image/multiboot.c
index 86b0bc12d..0c85df708 100644
--- a/qemu/roms/ipxe/src/arch/i386/image/multiboot.c
+++ b/qemu/roms/ipxe/src/arch/i386/image/multiboot.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* @file
diff --git a/qemu/roms/ipxe/src/arch/i386/image/pxe_image.c b/qemu/roms/ipxe/src/arch/i386/image/pxe_image.c
index dc28f6082..5b0f6eb89 100644
--- a/qemu/roms/ipxe/src/arch/i386/image/pxe_image.c
+++ b/qemu/roms/ipxe/src/arch/i386/image/pxe_image.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* @file
@@ -34,6 +38,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/netdevice.h>
#include <ipxe/features.h>
#include <ipxe/console.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/IndustryStandard/PeImage.h>
FEATURE ( FEATURE_IMAGE, "PXE", DHCP_EB_FEATURE_PXE, 1 );
@@ -121,9 +127,45 @@ int pxe_probe ( struct image *image ) {
return 0;
}
+/**
+ * Probe PXE image (with rejection of potential EFI images)
+ *
+ * @v image PXE file
+ * @ret rc Return status code
+ */
+int pxe_probe_no_mz ( struct image *image ) {
+ uint16_t magic;
+ int rc;
+
+ /* Probe PXE image */
+ if ( ( rc = pxe_probe ( image ) ) != 0 )
+ return rc;
+
+ /* Reject image with an "MZ" signature which may indicate an
+ * EFI image incorrectly handed out to a BIOS system.
+ */
+ if ( image->len >= sizeof ( magic ) ) {
+ copy_from_user ( &magic, image->data, 0, sizeof ( magic ) );
+ if ( magic == cpu_to_le16 ( EFI_IMAGE_DOS_SIGNATURE ) ) {
+ DBGC ( image, "IMAGE %p may be an EFI image\n",
+ image );
+ return -ENOTTY;
+ }
+ }
+
+ return 0;
+}
+
/** PXE image type */
-struct image_type pxe_image_type __image_type ( PROBE_PXE ) = {
- .name = "PXE",
- .probe = pxe_probe,
- .exec = pxe_exec,
+struct image_type pxe_image_type[] __image_type ( PROBE_PXE ) = {
+ {
+ .name = "PXE-NBP",
+ .probe = pxe_probe_no_mz,
+ .exec = pxe_exec,
+ },
+ {
+ .name = "PXE-NBP (may be EFI?)",
+ .probe = pxe_probe,
+ .exec = pxe_exec,
+ },
};
diff --git a/qemu/roms/ipxe/src/arch/i386/image/sdi.c b/qemu/roms/ipxe/src/arch/i386/image/sdi.c
index df1c3a868..fa2d0b73f 100644
--- a/qemu/roms/ipxe/src/arch/i386/image/sdi.c
+++ b/qemu/roms/ipxe/src/arch/i386/image/sdi.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <string.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/basemem.h b/qemu/roms/ipxe/src/arch/i386/include/basemem.h
index c477c7fe2..01c2ea917 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/basemem.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/basemem.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <realmode.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/basemem_packet.h b/qemu/roms/ipxe/src/arch/i386/include/basemem_packet.h
index 3cb477671..def6dee31 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/basemem_packet.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/basemem_packet.h
@@ -1,7 +1,7 @@
#ifndef BASEMEM_PACKET_H
#define BASEMEM_PACKET_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <realmode.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bios.h b/qemu/roms/ipxe/src/arch/i386/include/bios.h
index 0754b1168..988bbc62b 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bios.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bios.h
@@ -1,7 +1,7 @@
#ifndef BIOS_H
#define BIOS_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define BDA_SEG 0x0040
#define BDA_EQUIPMENT_WORD 0x0010
diff --git a/qemu/roms/ipxe/src/arch/i386/include/biosint.h b/qemu/roms/ipxe/src/arch/i386/include/biosint.h
index ab466af3c..67d6a3811 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/biosint.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/biosint.h
@@ -6,7 +6,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <realmode.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/byteswap.h b/qemu/roms/ipxe/src/arch/i386/include/bits/byteswap.h
index 0d9cb967c..53b6a454d 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/byteswap.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/byteswap.h
@@ -9,7 +9,7 @@
#include <stdint.h>
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
static inline __attribute__ (( always_inline, const )) uint16_t
__bswap_variable_16 ( uint16_t x ) {
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/compiler.h b/qemu/roms/ipxe/src/arch/i386/include/bits/compiler.h
index d48b4b385..87201135f 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/compiler.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/compiler.h
@@ -1,7 +1,10 @@
#ifndef _BITS_COMPILER_H
#define _BITS_COMPILER_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/** Dummy relocation type */
+#define RELOC_TYPE_NONE R_386_NONE
#ifndef ASSEMBLY
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/endian.h b/qemu/roms/ipxe/src/arch/i386/include/bits/endian.h
deleted file mode 100644
index 841885424..000000000
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/endian.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef ETHERBOOT_BITS_ENDIAN_H
-#define ETHERBOOT_BITS_ENDIAN_H
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#define __BYTE_ORDER __LITTLE_ENDIAN
-
-#endif /* ETHERBOOT_BITS_ENDIAN_H */
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/entropy.h b/qemu/roms/ipxe/src/arch/i386/include/bits/entropy.h
index 6dcceec6d..bfeb5e3b5 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/entropy.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/entropy.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/rtc_entropy.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/hyperv.h b/qemu/roms/ipxe/src/arch/i386/include/bits/hyperv.h
new file mode 100644
index 000000000..3565c8a83
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/hyperv.h
@@ -0,0 +1,72 @@
+#ifndef _BITS_HYPERV_H
+#define _BITS_HYPERV_H
+
+/** @file
+ *
+ * Hyper-V interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stddef.h>
+#include <stdint.h>
+#include <ipxe/io.h>
+
+/**
+ * Issue hypercall
+ *
+ * @v hv Hyper-V hypervisor
+ * @v code Call code
+ * @v in Input parameters
+ * @v out Output parameters
+ * @ret status Status code
+ */
+static inline __attribute__ (( always_inline )) int
+hv_call ( struct hv_hypervisor *hv, unsigned int code, const void *in,
+ void *out ) {
+ void *hypercall = hv->hypercall;
+ uint32_t in_phys;
+ uint32_t out_phys;
+ uint32_t discard_ecx;
+ uint32_t discard_edx;
+ uint16_t result;
+
+ in_phys = ( ( __builtin_constant_p ( in ) && ( in == NULL ) )
+ ? 0 : virt_to_phys ( in ) );
+ out_phys = ( ( __builtin_constant_p ( out ) && ( out == NULL ) )
+ ? 0 : virt_to_phys ( out ) );
+ __asm__ __volatile__ ( "call *%9"
+ : "=a" ( result ), "=c" ( discard_ecx ),
+ "=d" ( discard_edx )
+ : "d" ( 0 ), "a" ( code ),
+ "b" ( 0 ), "c" ( in_phys ),
+ "D" ( 0 ), "S" ( out_phys ),
+ "m" ( hypercall ) );
+ return result;
+}
+
+/**
+ * Set bit atomically
+ *
+ * @v bits Bit field
+ * @v bit Bit to set
+ */
+static inline __attribute__ (( always_inline )) void
+hv_set_bit ( void *bits, unsigned int bit ) {
+ struct {
+ uint32_t dword[ ( bit / 32 ) + 1 ];
+ } *dwords = bits;
+
+ /* Set bit using "lock bts". Inform compiler that any memory
+ * from the start of the bit field up to and including the
+ * dword containing this bit may be modified. (This is
+ * overkill but shouldn't matter in practice since we're
+ * unlikely to subsequently read other bits from the same bit
+ * field.)
+ */
+ __asm__ __volatile__ ( "lock bts %1, %0"
+ : "+m" ( *dwords ) : "Ir" ( bit ) );
+}
+
+#endif /* _BITS_HYPERV_H */
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/nap.h b/qemu/roms/ipxe/src/arch/i386/include/bits/nap.h
index 64066e6ab..e8bcfd13b 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/nap.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/nap.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/bios_nap.h>
#include <ipxe/efi/efix86_nap.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/profile.h b/qemu/roms/ipxe/src/arch/i386/include/bits/profile.h
index f3ee54ae9..e184d7b51 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/profile.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/profile.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/reboot.h b/qemu/roms/ipxe/src/arch/i386/include/bits/reboot.h
index 5b09e95f7..803dacfe4 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/reboot.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/reboot.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/bios_reboot.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/sanboot.h b/qemu/roms/ipxe/src/arch/i386/include/bits/sanboot.h
index 9c77a4d42..f02d2e649 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/sanboot.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/sanboot.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/bios_sanboot.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/smbios.h b/qemu/roms/ipxe/src/arch/i386/include/bits/smbios.h
index cc79eec51..2ab31e74b 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/smbios.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/smbios.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/bios_smbios.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/stdint.h b/qemu/roms/ipxe/src/arch/i386/include/bits/stdint.h
index 8edf13192..fe1f9946a 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/stdint.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/stdint.h
@@ -1,7 +1,7 @@
#ifndef _BITS_STDINT_H
#define _BITS_STDINT_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
typedef __SIZE_TYPE__ size_t;
typedef signed long ssize_t;
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/strings.h b/qemu/roms/ipxe/src/arch/i386/include/bits/strings.h
index 092bcb593..453545f00 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/strings.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/strings.h
@@ -1,7 +1,51 @@
#ifndef _BITS_STRINGS_H
#define _BITS_STRINGS_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/**
+ * Find first (i.e. least significant) set bit
+ *
+ * @v value Value
+ * @ret lsb Least significant bit set in value (LSB=1), or zero
+ */
+static inline __attribute__ (( always_inline )) int __ffsl ( long value ) {
+ long lsb_minus_one;
+
+ /* If the input value is zero, the BSF instruction returns
+ * ZF=0 and leaves an undefined value in the output register.
+ * Perform this check in C rather than asm so that it can be
+ * omitted in cases where the compiler is able to prove that
+ * the input is non-zero.
+ */
+ if ( value ) {
+ __asm__ ( "bsfl %1, %0"
+ : "=r" ( lsb_minus_one )
+ : "rm" ( value ) );
+ return ( lsb_minus_one + 1 );
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * Find first (i.e. least significant) set bit
+ *
+ * @v value Value
+ * @ret lsb Least significant bit set in value (LSB=1), or zero
+ */
+static inline __attribute__ (( always_inline )) int __ffsll ( long long value ){
+ unsigned long high = ( value >> 32 );
+ unsigned long low = ( value >> 0 );
+
+ if ( low ) {
+ return ( __ffsl ( low ) );
+ } else if ( high ) {
+ return ( 32 + __ffsl ( high ) );
+ } else {
+ return 0;
+ }
+}
/**
* Find last (i.e. most significant) set bit
@@ -13,7 +57,7 @@ static inline __attribute__ (( always_inline )) int __flsl ( long value ) {
long msb_minus_one;
/* If the input value is zero, the BSR instruction returns
- * ZF=1 and leaves an undefined value in the output register.
+ * ZF=0 and leaves an undefined value in the output register.
* Perform this check in C rather than asm so that it can be
* omitted in cases where the compiler is able to prove that
* the input is non-zero.
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/time.h b/qemu/roms/ipxe/src/arch/i386/include/bits/time.h
index 24dd020e9..6a5d63d32 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/time.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/time.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/rtc_time.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/timer.h b/qemu/roms/ipxe/src/arch/i386/include/bits/timer.h
index 50b676b77..f7d86d78c 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/timer.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/timer.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/bios_timer.h>
#include <ipxe/rdtsc_timer.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/uaccess.h b/qemu/roms/ipxe/src/arch/i386/include/bits/uaccess.h
index 2bb52e021..aac09ba95 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/uaccess.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/uaccess.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <librm.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bits/umalloc.h b/qemu/roms/ipxe/src/arch/i386/include/bits/umalloc.h
index 54fb006f0..113f16fd1 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bits/umalloc.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bits/umalloc.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/memtop_umalloc.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bootsector.h b/qemu/roms/ipxe/src/arch/i386/include/bootsector.h
index 8730fbfcc..c5d35aae3 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bootsector.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bootsector.h
@@ -6,7 +6,7 @@
* x86 bootsector image format
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
extern int call_bootsector ( unsigned int segment, unsigned int offset,
unsigned int drive );
diff --git a/qemu/roms/ipxe/src/arch/i386/include/bzimage.h b/qemu/roms/ipxe/src/arch/i386/include/bzimage.h
index 7e42e3188..4933ce5b1 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/bzimage.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/bzimage.h
@@ -1,7 +1,7 @@
#ifndef _BZIMAGE_H
#define _BZIMAGE_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h b/qemu/roms/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h
index 184177219..c17c1ea5e 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/efi/ipxe/dhcp_arch.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
+ * License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -13,7 +13,12 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
#ifndef _DHCP_ARCH_H
@@ -24,7 +29,7 @@
* Architecture-specific DHCP options
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/fakee820.h b/qemu/roms/ipxe/src/arch/i386/include/fakee820.h
index 9d00fb670..552b1e48d 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/fakee820.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/fakee820.h
@@ -1,7 +1,7 @@
#ifndef _FAKEE820_H
#define _FAKEE820_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
extern void fake_e820 ( void );
extern void unfake_e820 ( void );
diff --git a/qemu/roms/ipxe/src/arch/i386/include/initrd.h b/qemu/roms/ipxe/src/arch/i386/include/initrd.h
index a5659f43c..ddb3e5a45 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/initrd.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/initrd.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/uaccess.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/int13.h b/qemu/roms/ipxe/src/arch/i386/include/int13.h
index e337ca1d1..f82a583c6 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/int13.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/int13.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/list.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_nap.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_nap.h
index 5b684c041..c9b82c1e5 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_nap.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_nap.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef NAP_PCBIOS
#define NAP_PREFIX_pcbios
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_reboot.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_reboot.h
index a0845328d..3f6df9073 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_reboot.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_reboot.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef REBOOT_PCBIOS
#define REBOOT_PREFIX_pcbios
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h
index 689227b70..1a86b7d57 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_sanboot.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef SANBOOT_PCBIOS
#define SANBOOT_PREFIX_pcbios
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_smbios.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_smbios.h
index d8c7f648a..9f7f9c8ff 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_smbios.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_smbios.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef SMBIOS_PCBIOS
#define SMBIOS_PREFIX_pcbios
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_timer.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_timer.h
index f9fc80412..6b88a623c 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_timer.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/bios_timer.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef TIMER_PCBIOS
#define TIMER_PREFIX_pcbios
@@ -15,7 +15,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define TIMER_PREFIX_pcbios __pcbios_
#endif
-#include <ipxe/timer2.h>
+#include <ipxe/pit8254.h>
/**
* Delay for a fixed number of microseconds
@@ -25,9 +25,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
static inline __always_inline void
TIMER_INLINE ( pcbios, udelay ) ( unsigned long usecs ) {
/* BIOS timer is not high-resolution enough for udelay(), so
- * we use timer2
+ * we use the 8254 Programmable Interval Timer.
*/
- timer2_udelay ( usecs );
+ pit8254_udelay ( usecs );
}
/**
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/errno/pcbios.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/errno/pcbios.h
index 3a9eb2495..6312adaa4 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/errno/pcbios.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/errno/pcbios.h
@@ -10,7 +10,7 @@
* for the PC-BIOS platform.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <pxe_error.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/guestrpc.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/guestrpc.h
index 72a0f714f..bc3d85506 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/guestrpc.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/guestrpc.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/vmware.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/memtop_umalloc.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/memtop_umalloc.h
index 001648fe5..dee055d16 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/memtop_umalloc.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/memtop_umalloc.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef UMALLOC_MEMTOP
#define UMALLOC_PREFIX_memtop
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/msr.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/msr.h
index c88e26a39..5705318fd 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/msr.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/msr.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* Read model-specific register
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/rdtsc_timer.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/rdtsc_timer.h
index 472e14007..598f4bb08 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/rdtsc_timer.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/rdtsc_timer.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef TIMER_RDTSC
#define TIMER_PREFIX_rdtsc
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h
index 6c3cf2104..e214745d0 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/rtc_entropy.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/rtc_time.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/rtc_time.h
index c0dfe3f88..cb8c7f49e 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/rtc_time.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/rtc_time.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef TIME_RTC
#define TIME_PREFIX_rtc
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/timer2.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/timer2.h
deleted file mode 100644
index 322a3ed59..000000000
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/timer2.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _IPXE_TIMER2_H
-#define _IPXE_TIMER2_H
-
-/** @file
- *
- * Timer chip control
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-extern void timer2_udelay ( unsigned long usecs );
-
-#endif /* _IPXE_TIMER2_H */
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/vesafb.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/vesafb.h
index 48cd6a7b7..efc8f2cb8 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/vesafb.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/vesafb.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <realmode.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/ipxe/vmware.h b/qemu/roms/ipxe/src/arch/i386/include/ipxe/vmware.h
index 2ac65f436..24f60a03a 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/ipxe/vmware.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/ipxe/vmware.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/librm.h b/qemu/roms/ipxe/src/arch/i386/include/librm.h
index c8ba72b53..a8a578a39 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/librm.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/librm.h
@@ -1,7 +1,7 @@
#ifndef LIBRM_H
#define LIBRM_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/* Segment selectors as used in our protected-mode GDTs.
*
@@ -170,18 +170,6 @@ extern uint16_t __text16 ( rm_cs );
extern uint16_t __text16 ( rm_ds );
#define rm_ds __use_text16 ( rm_ds )
-/**
- * Convert segment:offset address to user buffer
- *
- * @v segment Real-mode segment
- * @v offset Real-mode offset
- * @ret buffer User buffer
- */
-static inline __always_inline userptr_t
-real_to_user ( unsigned int segment, unsigned int offset ) {
- return ( phys_to_user ( ( segment << 4 ) + offset ) );
-}
-
extern uint16_t copy_user_to_rm_stack ( userptr_t data, size_t size );
extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
diff --git a/qemu/roms/ipxe/src/arch/i386/include/limits.h b/qemu/roms/ipxe/src/arch/i386/include/limits.h
index 031b6c57a..bb48b75ab 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/limits.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/limits.h
@@ -1,7 +1,7 @@
#ifndef LIMITS_H
#define LIMITS_H 1
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/* Number of bits in a `char' */
#define CHAR_BIT 8
diff --git a/qemu/roms/ipxe/src/arch/i386/include/memsizes.h b/qemu/roms/ipxe/src/arch/i386/include/memsizes.h
index 7b217494a..f115f7574 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/memsizes.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/memsizes.h
@@ -1,7 +1,7 @@
#ifndef _MEMSIZES_H
#define _MEMSIZES_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <basemem.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/multiboot.h b/qemu/roms/ipxe/src/arch/i386/include/multiboot.h
index 44614c73a..ae09df6c7 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/multiboot.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/multiboot.h
@@ -8,7 +8,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h b/qemu/roms/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h
index a36d9cfa1..e07e4c192 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/pcbios/ipxe/dhcp_arch.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
+ * License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -13,7 +13,12 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
#ifndef _DHCP_ARCH_H
@@ -24,7 +29,7 @@
* Architecture-specific DHCP options
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/pnpbios.h b/qemu/roms/ipxe/src/arch/i386/include/pnpbios.h
index 4c20e73ed..d14873700 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/pnpbios.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/pnpbios.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/* BIOS segment address */
#define BIOS_SEG 0xf000
diff --git a/qemu/roms/ipxe/src/arch/i386/include/pxe.h b/qemu/roms/ipxe/src/arch/i386/include/pxe.h
index b95b0cce5..66d752683 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/pxe.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/pxe.h
@@ -1,7 +1,7 @@
#ifndef PXE_H
#define PXE_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include "pxe_types.h"
#include "pxe_error.h"
diff --git a/qemu/roms/ipxe/src/arch/i386/include/pxe_api.h b/qemu/roms/ipxe/src/arch/i386/include/pxe_api.h
index e4396efb2..3110d26da 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/pxe_api.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/pxe_api.h
@@ -17,6 +17,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ *
* As an alternative, at your option, you may use this file under the
* following terms, known as the "MIT license":
*
@@ -49,7 +53,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include "pxe_types.h"
diff --git a/qemu/roms/ipxe/src/arch/i386/include/pxe_call.h b/qemu/roms/ipxe/src/arch/i386/include/pxe_call.h
index 45af46549..cbd548318 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/pxe_call.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/pxe_call.h
@@ -6,7 +6,7 @@
* PXE API entry point
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <pxe_api.h>
#include <realmode.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/pxe_error.h b/qemu/roms/ipxe/src/arch/i386/include/pxe_error.h
index a1398cbd4..51298e665 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/pxe_error.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/pxe_error.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* @defgroup pxeerrors PXE error codes
diff --git a/qemu/roms/ipxe/src/arch/i386/include/pxe_types.h b/qemu/roms/ipxe/src/arch/i386/include/pxe_types.h
index db8214591..483666e33 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/pxe_types.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/pxe_types.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <errno.h> /* PXE status codes */
diff --git a/qemu/roms/ipxe/src/arch/i386/include/realmode.h b/qemu/roms/ipxe/src/arch/i386/include/realmode.h
index dafc5a32a..4defd3b97 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/realmode.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/realmode.h
@@ -10,7 +10,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/*
* Declaration of variables in .data16
@@ -65,6 +65,18 @@ FILE_LICENCE ( GPL2_OR_LATER );
*/
/**
+ * Convert segment:offset address to user buffer
+ *
+ * @v segment Real-mode segment
+ * @v offset Real-mode offset
+ * @ret buffer User buffer
+ */
+static inline __always_inline userptr_t
+real_to_user ( unsigned int segment, unsigned int offset ) {
+ return ( phys_to_user ( ( segment << 4 ) + offset ) );
+}
+
+/**
* Copy data to base memory
*
* @v dest_seg Destination segment
diff --git a/qemu/roms/ipxe/src/arch/i386/include/registers.h b/qemu/roms/ipxe/src/arch/i386/include/registers.h
index 06d236524..d9aa3c376 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/registers.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/registers.h
@@ -10,7 +10,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/rtc.h b/qemu/roms/ipxe/src/arch/i386/include/rtc.h
index 2a6abbae5..6294b63e3 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/rtc.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/rtc.h
@@ -13,7 +13,7 @@
* http://wiki.osdev.org/CMOS
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <pic8259.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/sdi.h b/qemu/roms/ipxe/src/arch/i386/include/sdi.h
index fc486402d..806c3f194 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/sdi.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/sdi.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** SDI image header */
struct sdi_header {
diff --git a/qemu/roms/ipxe/src/arch/i386/include/setjmp.h b/qemu/roms/ipxe/src/arch/i386/include/setjmp.h
index 5d3c11b69..fe1a9ef4d 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/setjmp.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/setjmp.h
@@ -1,40 +1,50 @@
-#ifndef ETHERBOOT_SETJMP_H
-#define ETHERBOOT_SETJMP_H
+#ifndef _SETJMP_H
+#define _SETJMP_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <realmode.h>
/** A jump buffer */
typedef struct {
+ /** Saved return address */
uint32_t retaddr;
+ /** Saved stack pointer */
+ uint32_t stack;
+ /** Saved %ebx */
uint32_t ebx;
- uint32_t esp;
- uint32_t ebp;
+ /** Saved %esi */
uint32_t esi;
+ /** Saved %edi */
uint32_t edi;
+ /** Saved %ebp */
+ uint32_t ebp;
} jmp_buf[1];
/** A real-mode-extended jump buffer */
typedef struct {
+ /** Jump buffer */
jmp_buf env;
- uint16_t rm_ss;
- uint16_t rm_sp;
+ /** Real-mode stack pointer */
+ segoff_t rm_stack;
} rmjmp_buf[1];
-extern int __asmcall setjmp ( jmp_buf env );
-extern void __asmcall longjmp ( jmp_buf env, int val );
+extern int __asmcall __attribute__ (( returns_twice ))
+setjmp ( jmp_buf env );
+
+extern void __asmcall __attribute__ (( noreturn ))
+longjmp ( jmp_buf env, int val );
-#define rmsetjmp( _env ) ( { \
- (_env)->rm_ss = rm_ss; \
- (_env)->rm_sp = rm_sp; \
- setjmp ( (_env)->env ); } ) \
+#define rmsetjmp( _env ) ( { \
+ (_env)->rm_stack.segment = rm_ss; \
+ (_env)->rm_stack.offset = rm_sp; \
+ setjmp ( (_env)->env ); } ) \
-#define rmlongjmp( _env, _val ) do { \
- rm_ss = (_env)->rm_ss; \
- rm_sp = (_env)->rm_sp; \
- longjmp ( (_env)->env, (_val) ); \
+#define rmlongjmp( _env, _val ) do { \
+ rm_ss = (_env)->rm_stack.segment; \
+ rm_sp = (_env)->rm_stack.offset; \
+ longjmp ( (_env)->env, (_val) ); \
} while ( 0 )
-#endif /* ETHERBOOT_SETJMP_H */
+#endif /* _SETJMP_H */
diff --git a/qemu/roms/ipxe/src/arch/i386/include/undi.h b/qemu/roms/ipxe/src/arch/i386/include/undi.h
index 325fcbbf9..7a5624f93 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/undi.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/undi.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifndef ASSEMBLY
diff --git a/qemu/roms/ipxe/src/arch/i386/include/undiload.h b/qemu/roms/ipxe/src/arch/i386/include/undiload.h
index 426830e8d..235e7a79e 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/undiload.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/undiload.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
struct undi_device;
struct undi_rom;
diff --git a/qemu/roms/ipxe/src/arch/i386/include/undinet.h b/qemu/roms/ipxe/src/arch/i386/include/undinet.h
index c3c17c11a..2798c4466 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/undinet.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/undinet.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
struct undi_device;
diff --git a/qemu/roms/ipxe/src/arch/i386/include/undipreload.h b/qemu/roms/ipxe/src/arch/i386/include/undipreload.h
index de9b8fb52..57f493cec 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/undipreload.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/undipreload.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <realmode.h>
#include <undi.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/undirom.h b/qemu/roms/ipxe/src/arch/i386/include/undirom.h
index 86d7077b5..1c530118d 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/undirom.h
+++ b/qemu/roms/ipxe/src/arch/i386/include/undirom.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <pxe_types.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/apm.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/apm.c
index 3b13e1cd0..50b19cb81 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/apm.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/apm.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* @file
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_nap.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_nap.c
index 1e7de756b..f1ba8297b 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_nap.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_nap.c
@@ -1,7 +1,7 @@
#include <ipxe/nap.h>
#include <realmode.h>
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* Save power by halting the CPU until the next interrupt
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_reboot.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_reboot.c
index 68546b2e5..10a1ecb89 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_reboot.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_reboot.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c
index dd7897e29..a8c0fc325 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <string.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c
index 65bbf9e01..3299c9aae 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/biosint.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/biosint.c
index a193defa3..3b8e80438 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/biosint.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/biosint.c
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* Hook INT vector
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13.c
index 1c7a8128f..f0450da90 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stdlib.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13con.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13con.c
new file mode 100644
index 000000000..2414c6909
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13con.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/console.h>
+#include <ipxe/init.h>
+#include <realmode.h>
+#include <int13.h>
+#include <config/console.h>
+
+/** @file
+ *
+ * INT13 disk log console
+ *
+ */
+
+/* Set default console usage if applicable */
+#if ! ( defined ( CONSOLE_INT13 ) && CONSOLE_EXPLICIT ( CONSOLE_INT13 ) )
+#undef CONSOLE_INT13
+#define CONSOLE_INT13 ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
+#endif
+
+/** Disk drive number */
+#define INT13CON_DRIVE 0x80
+
+/** Log partition type */
+#define INT13CON_PARTITION_TYPE 0xe0
+
+/** Maximum number of outstanding unwritten characters */
+#define INT13CON_MAX_UNWRITTEN 64
+
+/** Log partition header */
+struct int13con_header {
+ /** Magic signature */
+ char magic[10];
+} __attribute__ (( packed ));
+
+/** Log partition magic signature */
+#define INT13CON_MAGIC "iPXE LOG\n\n"
+
+/** Sector buffer */
+static uint8_t __bss16_array ( int13con_buffer, [INT13_BLKSIZE] );
+#define int13con_buffer __use_data16 ( int13con_buffer )
+
+/** Disk address packet */
+static struct int13_disk_address __bss16 ( int13con_address );
+#define int13con_address __use_data16 ( int13con_address )
+
+/** Current LBA */
+static uint64_t int13con_lba;
+
+/** Maximum LBA */
+static uint64_t int13con_max_lba;
+
+/** Current offset within sector */
+static size_t int13con_offset;
+
+/** Number of unwritten characters */
+static size_t int13con_unwritten;
+
+struct console_driver int13con __console_driver;
+
+/**
+ * Read/write disk sector
+ *
+ * @v op Operation
+ * @v lba Logical block address
+ * @ret rc Return status code
+ */
+static int int13con_rw ( unsigned int op, uint64_t lba ) {
+ uint8_t error;
+
+ /* Construct disk address packet */
+ int13con_address.bufsize = sizeof ( int13con_address );
+ int13con_address.count = 1;
+ int13con_address.buffer.segment = rm_ds;
+ int13con_address.buffer.offset = __from_data16 ( int13con_buffer );
+ int13con_address.lba = lba;
+
+ /* Issue INT13 */
+ __asm__ ( REAL_CODE ( "int $0x13\n\t" )
+ : "=a" ( error )
+ : "0" ( op << 8 ), "d" ( INT13CON_DRIVE ),
+ "S" ( __from_data16 ( &int13con_address ) ) );
+ if ( error ) {
+ DBG ( "INT13CON operation %04x failed: %02x\n",
+ op, error );
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * Write character to console
+ *
+ * @v character Character
+ */
+static void int13con_putchar ( int character ) {
+ static int busy;
+ int rc;
+
+ /* Ignore if we are already mid-logging */
+ if ( busy )
+ return;
+ busy = 1;
+
+ /* Write character to buffer */
+ int13con_buffer[int13con_offset++] = character;
+ int13con_unwritten++;
+
+ /* Write sector to disk, if applicable */
+ if ( ( int13con_offset == INT13_BLKSIZE ) ||
+ ( int13con_unwritten == INT13CON_MAX_UNWRITTEN ) ||
+ ( character == '\n' ) ) {
+
+ /* Write sector to disk */
+ if ( ( rc = int13con_rw ( INT13_EXTENDED_WRITE,
+ int13con_lba ) ) != 0 ) {
+ DBG ( "INT13CON could not write log\n" );
+ /* Ignore and continue; there's nothing we can do */
+ }
+
+ /* Reset count of unwritten characters */
+ int13con_unwritten = 0;
+ }
+
+ /* Move to next sector, if applicable */
+ if ( int13con_offset == INT13_BLKSIZE ) {
+
+ /* Disable console if we have run out of space */
+ if ( int13con_lba >= int13con_max_lba )
+ int13con.disabled = 1;
+
+ /* Clear log buffer */
+ memset ( int13con_buffer, 0, sizeof ( int13con_buffer ) );
+ int13con_offset = 0;
+
+ /* Move to next sector */
+ int13con_lba++;
+ }
+
+ /* Clear busy flag */
+ busy = 0;
+}
+
+/**
+ * Find log partition
+ *
+ * @ret rc Return status code
+ */
+static int int13con_find ( void ) {
+ struct master_boot_record *mbr =
+ ( ( struct master_boot_record * ) int13con_buffer );
+ struct int13con_header *hdr =
+ ( ( struct int13con_header * ) int13con_buffer );
+ struct partition_table_entry part[4];
+ unsigned int i;
+ int rc;
+
+ /* Read MBR */
+ if ( ( rc = int13con_rw ( INT13_EXTENDED_READ, 0 ) ) != 0 ) {
+ DBG ( "INT13CON could not read MBR: %s\n", strerror ( rc ) );
+ return rc;
+ }
+
+ /* Check MBR magic */
+ if ( mbr->magic != INT13_MBR_MAGIC ) {
+ DBG ( "INT13CON incorrect MBR magic\n" );
+ DBG2_HDA ( 0, mbr, sizeof ( *mbr ) );
+ return -EINVAL;
+ }
+
+ /* Look for magic partition */
+ memcpy ( part, mbr->partitions, sizeof ( part ) );
+ for ( i = 0 ; i < ( sizeof ( part ) / sizeof ( part[0] ) ) ; i++ ) {
+
+ /* Skip partitions of the wrong type */
+ if ( part[i].type != INT13CON_PARTITION_TYPE )
+ continue;
+
+ /* Read partition header */
+ if ( ( rc = int13con_rw ( INT13_EXTENDED_READ,
+ part[i].start ) ) != 0 ) {
+ DBG ( "INT13CON partition %d could not read header: "
+ "%s\n", ( i + 1 ), strerror ( rc ) );
+ continue;
+ }
+
+ /* Check partition header */
+ if ( memcmp ( hdr->magic, INT13CON_MAGIC,
+ sizeof ( hdr->magic ) ) != 0 ) {
+ DBG ( "INT13CON partition %d bad magic\n", ( i + 1 ) );
+ DBG2_HDA ( 0, hdr, sizeof ( *hdr ) );
+ continue;
+ }
+
+ /* Found log partition */
+ DBG ( "INT13CON partition %d at [%08x,%08x)\n", ( i + 1 ),
+ part[i].start, ( part[i].start + part[i].length ) );
+ int13con_lba = part[i].start;
+ int13con_max_lba = ( part[i].start + part[i].length - 1 );
+
+ /* Initialise log buffer */
+ memset ( &int13con_buffer[ sizeof ( *hdr ) ], 0,
+ ( sizeof ( int13con_buffer ) - sizeof ( *hdr ) ) );
+ int13con_offset = sizeof ( hdr->magic );
+
+ return 0;
+ }
+
+ DBG ( "INT13CON found no log partition\n" );
+ return -ENOENT;
+}
+
+/**
+ * Initialise INT13 console
+ *
+ */
+static void int13con_init ( void ) {
+ uint8_t error;
+ uint16_t check;
+ unsigned int discard_c;
+ unsigned int discard_d;
+ int rc;
+
+ /* Check for INT13 extensions */
+ __asm__ __volatile__ ( REAL_CODE ( "int $0x13\n\t"
+ "setc %%al\n\t" )
+ : "=a" ( error ), "=b" ( check ),
+ "=c" ( discard_c ), "=d" ( discard_d )
+ : "0" ( INT13_EXTENSION_CHECK << 8 ),
+ "1" ( 0x55aa ), "3" ( INT13CON_DRIVE ) );
+ if ( error || ( check != 0xaa55 ) ) {
+ DBG ( "INT13CON missing extensions (%02x,%04x)\n",
+ error, check );
+ return;
+ }
+
+ /* Locate log partition */
+ if ( ( rc = int13con_find() ) != 0)
+ return;
+
+ /* Enable console */
+ int13con.disabled = 0;
+}
+
+/**
+ * INT13 console initialisation function
+ */
+struct init_fn int13con_init_fn __init_fn ( INIT_CONSOLE ) = {
+ .initialise = int13con_init,
+};
+
+/** INT13 console driver */
+struct console_driver int13con __console_driver = {
+ .putchar = int13con_putchar,
+ .disabled = CONSOLE_DISABLED,
+ .usage = CONSOLE_INT13,
+};
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
index c382e3c36..957f8e324 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* @file
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c
index 61873039f..34efa0b39 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/pci.h>
@@ -38,7 +42,11 @@ static int pcibios_num_bus ( void ) {
int discard_a, discard_D;
uint8_t max_bus;
- __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
+ /* We issue this call using flat real mode, to work around a
+ * bug in some HP BIOSes.
+ */
+ __asm__ __volatile__ ( REAL_CODE ( "call flatten_real_mode\n\t"
+ "stc\n\t"
"int $0x1a\n\t"
"jnc 1f\n\t"
"xorw %%cx, %%cx\n\t"
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c
index fad421c2a..9aab03c03 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c
index 67041d4ca..cdbeac8d5 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/vesafb.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/vesafb.c
index 2adc7b040..9cf2bf29e 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/vesafb.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/vesafb.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c
index 657d47b6c..104313666 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/uaccess.h>
#include <ipxe/init.h>
@@ -342,6 +346,7 @@ int pxe_start_nbp ( void ) {
return 0;
}
+REQUIRING_SYMBOL ( pxe_api_call );
REQUIRE_OBJECT ( pxe_preboot );
REQUIRE_OBJECT ( pxe_undi );
REQUIRE_OBJECT ( pxe_udp );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S
index 6274264ff..07852cd50 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S
@@ -16,9 +16,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ *
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.arch i386
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c
index 9d1896507..f92dae0d1 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c
@@ -21,9 +21,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <realmode.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c
index 6e9610294..456ffb5fd 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c
@@ -31,9 +31,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 2 );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c
index 695af3b93..e6a2e072a 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/init.h>
#include "pxe.h"
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c
index 534352b2b..6e09080bc 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c
@@ -22,9 +22,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <string.h>
@@ -174,18 +178,16 @@ pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
}
info = &cached_info[idx];
- /* Construct cached version of packet, if not already constructed. */
- if ( ! info->dhcphdr.op ) {
- /* Construct DHCP packet */
- creator = &pxe_dhcp_packet_creators[idx];
- if ( ( rc = creator->create ( pxe_netdev, info,
- sizeof ( *info ) ) ) != 0 ) {
- DBGC ( &pxe_netdev, " failed to build packet: %s\n",
- strerror ( rc ) );
- goto err;
- }
+ /* Construct DHCP packet */
+ creator = &pxe_dhcp_packet_creators[idx];
+ if ( ( rc = creator->create ( pxe_netdev, info,
+ sizeof ( *info ) ) ) != 0 ) {
+ DBGC ( &pxe_netdev, " failed to build packet: %s\n",
+ strerror ( rc ) );
+ goto err;
}
+ /* Copy packet (if applicable) */
len = get_cached_info->BufferSize;
if ( len == 0 ) {
/* Point client at our cached buffer.
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c
index f4801bad0..068d8a7b2 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c
@@ -21,9 +21,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdlib.h>
#include <stdio.h>
@@ -36,6 +40,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/xfer.h>
#include <ipxe/open.h>
#include <ipxe/process.h>
+#include <ipxe/uri.h>
+#include <realmode.h>
#include <pxe.h>
/** A PXE TFTP connection */
@@ -170,11 +176,10 @@ static struct pxe_tftp_connection pxe_tftp = {
* @v blksize Requested block size
* @ret rc Return status code
*/
-static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port,
- const unsigned char *filename, size_t blksize,
- int sizeonly ) {
- char uri_string[PXE_TFTP_URI_LEN];
+static int pxe_tftp_open ( IP4_t ipaddress, UDP_PORT_t port,
+ UINT8_t *filename, UINT16_t blksize ) {
struct in_addr address;
+ struct uri *uri;
int rc;
/* Reset PXE TFTP connection structure */
@@ -185,19 +190,20 @@ static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port,
pxe_tftp.blksize = blksize;
pxe_tftp.rc = -EINPROGRESS;
- /* Construct URI string */
+ /* Construct URI */
address.s_addr = ipaddress;
- if ( ! port )
- port = htons ( TFTP_PORT );
- snprintf ( uri_string, sizeof ( uri_string ), "tftp%s://%s:%d%s%s",
- sizeonly ? "size" : "", inet_ntoa ( address ),
- ntohs ( port ), ( ( filename[0] == '/' ) ? "" : "/" ),
- filename );
- DBG ( " %s", uri_string );
+ DBG ( " %s", inet_ntoa ( address ) );
+ if ( port )
+ DBG ( ":%d", ntohs ( port ) );
+ DBG ( ":%s", filename );
+ uri = tftp_uri ( address, ntohs ( port ), ( ( char * ) filename ) );
+ if ( ! uri ) {
+ DBG ( " could not create URI\n" );
+ return -ENOMEM;
+ }
/* Open PXE TFTP connection */
- if ( ( rc = xfer_open_uri_string ( &pxe_tftp.xfer,
- uri_string ) ) != 0 ) {
+ if ( ( rc = xfer_open_uri ( &pxe_tftp.xfer, uri ) ) != 0 ) {
DBG ( " could not open (%s)\n", strerror ( rc ) );
return rc;
}
@@ -259,8 +265,7 @@ static PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) {
if ( ( rc = pxe_tftp_open ( tftp_open->ServerIPAddress,
tftp_open->TFTPPort,
tftp_open->FileName,
- tftp_open->PacketSize,
- 0) ) != 0 ) {
+ tftp_open->PacketSize ) ) != 0 ) {
tftp_open->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE;
}
@@ -483,7 +488,7 @@ PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
/* Open TFTP file */
if ( ( rc = pxe_tftp_open ( tftp_read_file->ServerIPAddress, 0,
- tftp_read_file->FileName, 0, 0 ) ) != 0 ) {
+ tftp_read_file->FileName, 0 ) ) != 0 ) {
tftp_read_file->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE;
}
@@ -553,7 +558,7 @@ static PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE
/* Open TFTP file */
if ( ( rc = pxe_tftp_open ( tftp_get_fsize->ServerIPAddress, 0,
- tftp_get_fsize->FileName, 0, 1 ) ) != 0 ) {
+ tftp_get_fsize->FileName, 0 ) ) != 0 ) {
tftp_get_fsize->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE;
}
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c
index 32bc39c8e..071cb59db 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c
@@ -11,6 +11,7 @@
#include <ipxe/udp.h>
#include <ipxe/uaccess.h>
#include <ipxe/process.h>
+#include <realmode.h>
#include <pxe.h>
/*
@@ -30,9 +31,25 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/** A PXE UDP pseudo-header */
+struct pxe_udp_pseudo_header {
+ /** Source IP address */
+ IP4_t src_ip;
+ /** Source port */
+ UDP_PORT_t s_port;
+ /** Destination IP address */
+ IP4_t dest_ip;
+ /** Destination port */
+ UDP_PORT_t d_port;
+} __attribute__ (( packed ));
/** A PXE UDP connection */
struct pxe_udp_connection {
@@ -40,8 +57,8 @@ struct pxe_udp_connection {
struct interface xfer;
/** Local address */
struct sockaddr_in local;
- /** Current PXENV_UDP_READ parameter block */
- struct s_PXENV_UDP_READ *pxenv_udp_read;
+ /** List of received packets */
+ struct list_head list;
};
/**
@@ -58,45 +75,38 @@ struct pxe_udp_connection {
static int pxe_udp_deliver ( struct pxe_udp_connection *pxe_udp,
struct io_buffer *iobuf,
struct xfer_metadata *meta ) {
- struct s_PXENV_UDP_READ *pxenv_udp_read = pxe_udp->pxenv_udp_read;
+ struct pxe_udp_pseudo_header *pshdr;
struct sockaddr_in *sin_src;
struct sockaddr_in *sin_dest;
- userptr_t buffer;
- size_t len;
- int rc = 0;
-
- if ( ! pxenv_udp_read ) {
- DBG ( "PXE discarded UDP packet\n" );
- rc = -ENOBUFS;
- goto done;
- }
-
- /* Copy packet to buffer and record length */
- buffer = real_to_user ( pxenv_udp_read->buffer.segment,
- pxenv_udp_read->buffer.offset );
- len = iob_len ( iobuf );
- if ( len > pxenv_udp_read->buffer_size )
- len = pxenv_udp_read->buffer_size;
- copy_to_user ( buffer, 0, iobuf->data, len );
- pxenv_udp_read->buffer_size = len;
+ int rc;
- /* Fill in source/dest information */
+ /* Extract metadata */
assert ( meta );
sin_src = ( struct sockaddr_in * ) meta->src;
assert ( sin_src );
assert ( sin_src->sin_family == AF_INET );
- pxenv_udp_read->src_ip = sin_src->sin_addr.s_addr;
- pxenv_udp_read->s_port = sin_src->sin_port;
sin_dest = ( struct sockaddr_in * ) meta->dest;
assert ( sin_dest );
assert ( sin_dest->sin_family == AF_INET );
- pxenv_udp_read->dest_ip = sin_dest->sin_addr.s_addr;
- pxenv_udp_read->d_port = sin_dest->sin_port;
- /* Mark as received */
- pxe_udp->pxenv_udp_read = NULL;
+ /* Construct pseudo-header */
+ if ( ( rc = iob_ensure_headroom ( iobuf, sizeof ( *pshdr ) ) ) != 0 ) {
+ DBG ( "PXE could not prepend pseudo-header\n" );
+ rc = -ENOMEM;
+ goto drop;
+ }
+ pshdr = iob_push ( iobuf, sizeof ( *pshdr ) );
+ pshdr->src_ip = sin_src->sin_addr.s_addr;
+ pshdr->s_port = sin_src->sin_port;
+ pshdr->dest_ip = sin_dest->sin_addr.s_addr;
+ pshdr->d_port = sin_dest->sin_port;
- done:
+ /* Add to queue */
+ list_add_tail ( &iobuf->list, &pxe_udp->list );
+
+ return 0;
+
+ drop:
free_iob ( iobuf );
return rc;
}
@@ -116,6 +126,7 @@ static struct pxe_udp_connection pxe_udp = {
.local = {
.sin_family = AF_INET,
},
+ .list = LIST_HEAD_INIT ( pxe_udp.list ),
};
/**
@@ -205,11 +216,20 @@ static PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) {
*/
static PXENV_EXIT_t
pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) {
+ struct io_buffer *iobuf;
+ struct io_buffer *tmp;
+
DBG ( "PXENV_UDP_CLOSE\n" );
/* Close UDP connection */
intf_restart ( &pxe_udp.xfer, 0 );
+ /* Discard any received packets */
+ list_for_each_entry_safe ( iobuf, tmp, &pxe_udp.list, list ) {
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
+ }
+
pxenv_udp_close->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
}
@@ -365,20 +385,32 @@ pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
static PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) {
struct in_addr dest_ip_wanted = { .s_addr = pxenv_udp_read->dest_ip };
struct in_addr dest_ip;
+ struct io_buffer *iobuf;
+ struct pxe_udp_pseudo_header *pshdr;
uint16_t d_port_wanted = pxenv_udp_read->d_port;
uint16_t d_port;
+ userptr_t buffer;
+ size_t len;
+
+ /* Try receiving a packet, if the queue is empty */
+ if ( list_empty ( &pxe_udp.list ) )
+ step();
- /* Try receiving a packet */
- pxe_udp.pxenv_udp_read = pxenv_udp_read;
- step();
- if ( pxe_udp.pxenv_udp_read ) {
+ /* Remove first packet from the queue */
+ iobuf = list_first_entry ( &pxe_udp.list, struct io_buffer, list );
+ if ( ! iobuf ) {
/* No packet received */
DBG2 ( "PXENV_UDP_READ\n" );
- pxe_udp.pxenv_udp_read = NULL;
goto no_packet;
}
- dest_ip.s_addr = pxenv_udp_read->dest_ip;
- d_port = pxenv_udp_read->d_port;
+ list_del ( &iobuf->list );
+
+ /* Strip pseudo-header */
+ assert ( iob_len ( iobuf ) >= sizeof ( *pshdr ) );
+ pshdr = iobuf->data;
+ iob_pull ( iobuf, sizeof ( *pshdr ) );
+ dest_ip.s_addr = pshdr->dest_ip;
+ d_port = pshdr->d_port;
DBG ( "PXENV_UDP_READ" );
/* Filter on destination address and/or port */
@@ -386,14 +418,29 @@ static PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) {
( dest_ip_wanted.s_addr != dest_ip.s_addr ) ) {
DBG ( " wrong IP %s", inet_ntoa ( dest_ip ) );
DBG ( " (wanted %s)\n", inet_ntoa ( dest_ip_wanted ) );
- goto no_packet;
+ goto drop;
}
if ( d_port_wanted && ( d_port_wanted != d_port ) ) {
DBG ( " wrong port %d", htons ( d_port ) );
DBG ( " (wanted %d)\n", htons ( d_port_wanted ) );
- goto no_packet;
+ goto drop;
}
+ /* Copy packet to buffer and record length */
+ buffer = real_to_user ( pxenv_udp_read->buffer.segment,
+ pxenv_udp_read->buffer.offset );
+ len = iob_len ( iobuf );
+ if ( len > pxenv_udp_read->buffer_size )
+ len = pxenv_udp_read->buffer_size;
+ copy_to_user ( buffer, 0, iobuf->data, len );
+ pxenv_udp_read->buffer_size = len;
+
+ /* Fill in source/dest information */
+ pxenv_udp_read->src_ip = pshdr->src_ip;
+ pxenv_udp_read->s_port = pshdr->s_port;
+ pxenv_udp_read->dest_ip = pshdr->dest_ip;
+ pxenv_udp_read->d_port = pshdr->d_port;
+
DBG ( " %04x:%04x+%x %s:", pxenv_udp_read->buffer.segment,
pxenv_udp_read->buffer.offset, pxenv_udp_read->buffer_size,
inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->src_ip ) ));
@@ -401,9 +448,14 @@ static PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) {
inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->dest_ip ) ),
ntohs ( pxenv_udp_read->d_port ) );
+ /* Free I/O buffer */
+ free_iob ( iobuf );
+
pxenv_udp_read->Status = PXENV_STATUS_SUCCESS;
return PXENV_EXIT_SUCCESS;
+ drop:
+ free_iob ( iobuf );
no_packet:
pxenv_udp_read->Status = PXENV_STATUS_FAILURE;
return PXENV_EXIT_FAILURE;
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c
index 29e586ed2..2eb68178a 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c
@@ -21,9 +21,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stdio.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c b/qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c
index 1854501de..69d94c407 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c
@@ -41,8 +41,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/image.h>
#include <ipxe/version.h>
#include <usr/imgmgmt.h>
-#include "config/console.h"
-#include "config/serial.h"
/** The "SYSLINUX" version string */
static char __bss16_array ( syslinux_version, [32] );
@@ -86,7 +84,6 @@ rmjmp_buf comboot_return;
/* Mode flags set by INT 22h AX=0017h */
static uint16_t comboot_graphics_mode = 0;
-
/**
* Print a string with a particular terminator
*/
@@ -261,8 +258,10 @@ static __asmcall void int21 ( struct i386_all_regs *ix86 ) {
break;
case 0x04: /* Write Character to Serial Port */
- serial_putc ( ix86->regs.dl );
- ix86->flags &= ~CF;
+ if ( serial_console.base ) {
+ uart_transmit ( &serial_console, ix86->regs.dl );
+ ix86->flags &= ~CF;
+ }
break;
case 0x09: /* Write DOS String to Console */
@@ -455,15 +454,16 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
break;
case 0x000B: /* Get Serial Console Configuration */
-#if defined(CONSOLE_SERIAL) && !defined(COMPRESERVE)
- ix86->regs.dx = COMCONSOLE;
- ix86->regs.cx = 115200 / COMSPEED;
- ix86->regs.bx = 0;
-#else
- ix86->regs.dx = 0;
-#endif
+ if ( serial_console.base ) {
+ ix86->regs.dx = ( ( intptr_t ) serial_console.base );
+ ix86->regs.cx = serial_console.divisor;
+ ix86->regs.bx = 0;
+ ix86->flags &= ~CF;
+ }
+ break;
- ix86->flags &= ~CF;
+ case 0x000C: /* Perform final cleanup */
+ shutdown_boot();
break;
case 0x000E: /* Get configuration file name */
@@ -712,3 +712,6 @@ void unhook_comboot_interrupts ( ) {
unhook_bios_interrupt ( 0x22, ( unsigned int ) int22_wrapper,
&int22_vector );
}
+
+/* Avoid dragging in serial console support unconditionally */
+struct uart serial_console __attribute__ (( weak ));
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c b/qemu/roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c
index 390fc5545..ef7ee8151 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c b/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c
index c6b9fff12..f7df4f75b 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmware.c b/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmware.c
index 8074e6118..a415465fb 100644
--- a/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmware.c
+++ b/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmware.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/bootpart.S b/qemu/roms/ipxe/src/arch/i386/prefix/bootpart.S
index 968da1a38..6d0c6034a 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/bootpart.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/bootpart.S
@@ -1,4 +1,4 @@
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define BOOT_SEG 0x07c0
#define EXEC_SEG 0x0100
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/exeprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/exeprefix.S
index cb61287d3..5c648d51d 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/exeprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/exeprefix.S
@@ -16,9 +16,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ *
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
/* Initial temporary stack size */
#define EXE_STACK_SIZE 0x400
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/hdprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/hdprefix.S
index 876bfe1be..1d012d80b 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/hdprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/hdprefix.S
@@ -1,4 +1,4 @@
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.text
.arch i386
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/isaromprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/isaromprefix.S
index e28208089..fb49819ee 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/isaromprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/isaromprefix.S
@@ -16,9 +16,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ *
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define BUSTYPE "ISAR"
#define _rom_start _isarom_start
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/kkkpxeprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/kkkpxeprefix.S
index 27ed231e7..6e43cd26a 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/kkkpxeprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/kkkpxeprefix.S
@@ -5,12 +5,10 @@
*****************************************************************************
*/
-FILE_LICENCE ( GPL2_OR_LATER )
-
-/* Since we have the whole stack, we can use cached DHCP information */
-REQUIRE_OBJECT ( pxeparent_dhcp )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
/* Provide the PXENV_FILE_EXIT_HOOK API call */
+REQUIRING_SYMBOL ( _kkkpxe_start )
REQUIRE_OBJECT ( pxe_exit_hook )
#define PXELOADER_KEEP_UNDI
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/kkpxeprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/kkpxeprefix.S
index d177d7d62..3c17dbdb1 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/kkpxeprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/kkpxeprefix.S
@@ -3,10 +3,7 @@
*****************************************************************************
*/
-FILE_LICENCE ( GPL2_OR_LATER )
-
-/* Since we have the whole stack, we can use cached DHCP information */
-REQUEST_OBJECT ( pxeparent_dhcp )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define PXELOADER_KEEP_UNDI
#define PXELOADER_KEEP_PXE
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/kpxeprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/kpxeprefix.S
index c75608172..200006d83 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/kpxeprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/kpxeprefix.S
@@ -3,7 +3,7 @@
*****************************************************************************
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define PXELOADER_KEEP_UNDI
#define _pxe_start _kpxe_start
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/libprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/libprefix.S
index 7c1ece791..7d5c1ed53 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/libprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/libprefix.S
@@ -16,9 +16,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ *
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.arch i386
@@ -296,11 +300,9 @@ copy_bytes:
* Zero bytes
*
* Parameters:
- * %ds:esi : source address
* %es:edi : destination address
* %ecx : length
* Returns:
- * %ds:esi : next source address
* %es:edi : next destination address
* Corrupts:
* None
@@ -396,8 +398,10 @@ process_bytes:
movw %ax, %fs
movw %ax, %gs
+#ifdef NDEBUG
/* Call memcpy()-like function */
call *%bx
+#endif
/* Return to (flat) real mode */
movl %cr0, %eax
@@ -411,6 +415,20 @@ process_bytes:
popw %fs
popw %gs
+#ifndef NDEBUG
+ /* Call memcpy()-like function in flat real mode (to allow for
+ * debug output via INT 10).
+ */
+ pushw %ds
+ pushw %es
+ xorw %ax, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ call *%bx
+ popw %es
+ popw %ds
+#endif
+
/* Restore GDT */
data32 lgdt -8(%bp)
addw $( 8 /* saved GDT */ + ( PM_DS + 8 ) /* GDT on stack */ ), %sp
@@ -442,11 +460,11 @@ process_bytes:
/* Convert %ds:esi and %es:edi back to physical addresses */
xorl %eax, %eax
- movw %ds, %cx
+ movw %ds, %ax
shll $4, %eax
addl %eax, %esi
xorl %eax, %eax
- movw %es, %cx
+ movw %es, %ax
shll $4, %eax
addl %eax, %edi
@@ -678,12 +696,21 @@ install:
.globl install_prealloc
install_prealloc:
progress "install_prealloc:\n"
- /* Save registers */
+ /* Save registers on external stack */
pushal
pushw %ds
pushw %es
cld /* Sanity: clear the direction flag asap */
+ /* Switch to temporary stack in .bss16 */
+ pushw %ss
+ popw %ds
+ movl %esp, %ecx
+ movw %bx, %ss
+ movl $_data16_memsz, %esp
+ pushw %ds
+ pushl %ecx
+
/* Set up %ds for (read-only) access to .prefix */
pushw %cs
popw %ds
@@ -710,6 +737,7 @@ install_prealloc:
popl %esi
#ifndef KEEP_IT_REAL
+
/* Access high memory by enabling the A20 gate. (We will
* already have 4GB segment limits as a result of calling
* install_block.)
@@ -778,7 +806,7 @@ payload_death_message:
movzwl %bx, %edi
shll $4, %edi
movl $_data16_filesz, %ecx
- movl $_data16_memsz, %edx
+ movl $_data16_filesz, %edx /* do not zero our temporary stack */
call install_block /* .data16 */
/* Set up %ds for access to .data16 */
@@ -787,11 +815,8 @@ payload_death_message:
/* Restore decompression temporary area physical address */
popl %edi
-#ifdef KEEP_IT_REAL
- /* Initialise libkir */
- movw %ax, (init_libkir_vector+2)
- lcall *init_libkir_vector
-#else
+#ifndef KEEP_IT_REAL
+
/* Find a suitable decompression temporary area, if none specified */
pushl %eax
testl %edi, %edi
@@ -823,6 +848,22 @@ payload_death_message:
call install_block
popl %edi
+#endif /* KEEP_IT_REAL */
+
+ /* Switch back to original stack and zero .bss16 */
+ addr32 lss %ss:(%esp), %esp
+ pushl %edi
+ pushw %es
+ movw %bx, %es
+ movl $_data16_filesz, %edi
+ movl $_data16_memsz, %ecx
+ subl %edi, %ecx
+ call zero_bytes
+ popw %es
+ popl %edi
+
+#ifndef KEEP_IT_REAL
+
/* Initialise librm at current location */
progress " init_librm\n"
movw %ax, (init_librm_vector+2)
@@ -834,7 +875,6 @@ payload_death_message:
incb memmap_post
decl %ebp
1:
-
/* Call relocate() to determine target address for relocation.
* relocate() will return with %esi, %edi and %ecx set up
* ready for the copy to the new location.
@@ -857,7 +897,14 @@ payload_death_message:
/* Initialise librm at new location */
progress " init_librm\n"
lcall *init_librm_vector
-#endif
+
+#else /* KEEP_IT_REAL */
+
+ /* Initialise libkir */
+ movw %ax, (init_libkir_vector+2)
+ lcall *init_libkir_vector
+
+#endif /* KEEP_IT_REAL */
/* Close access to payload */
progress " close_payload\n"
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/lkrnprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/lkrnprefix.S
index 259bc6ba5..64135e14b 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/lkrnprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/lkrnprefix.S
@@ -1,4 +1,4 @@
-FILE_LICENCE ( GPL_ANY )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define BZI_LOAD_HIGH_ADDR 0x100000
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/mbr.S b/qemu/roms/ipxe/src/arch/i386/prefix/mbr.S
index adfe20410..a1e237de8 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/mbr.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/mbr.S
@@ -1,3 +1,5 @@
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+
.text
.arch i386
.section ".prefix", "awx", @progbits
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/mromprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/mromprefix.S
index 4c94457c2..b636b92af 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/mromprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/mromprefix.S
@@ -16,9 +16,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ *
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define PCIBIOS_READ_CONFIG_WORD 0xb109
#define PCIBIOS_READ_CONFIG_DWORD 0xb10a
@@ -463,6 +467,7 @@ pci_set_mem_access:
.org 0x00
mromheader:
.word 0xaa55 /* BIOS extension signature */
+ .byte 0x01 /* Dummy size (BIOS bug workaround) */
.org 0x18
.word mpciheader
.org 0x1a
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/nbiprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/nbiprefix.S
index 06e7df5b7..16c79566c 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/nbiprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/nbiprefix.S
@@ -1,3 +1,5 @@
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+
.text
.arch i386
.code16
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/nullprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/nullprefix.S
index 032d41e0f..bd0ff339e 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/nullprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/nullprefix.S
@@ -1,3 +1,5 @@
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+
.org 0
.text
.arch i386
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/pciromprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/pciromprefix.S
index 45ba31f50..5a5a49647 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/pciromprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/pciromprefix.S
@@ -16,9 +16,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ *
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define BUSTYPE "PCIR"
#define _rom_start _pcirom_start
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/pxeprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/pxeprefix.S
index 6e29c7949..465ce4345 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/pxeprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/pxeprefix.S
@@ -1,4 +1,4 @@
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define PXENV_UNDI_SHUTDOWN 0x0005
#define PXENV_UNDI_GET_NIC_TYPE 0x0012
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/romprefix.S b/qemu/roms/ipxe/src/arch/i386/prefix/romprefix.S
index 7bc4fe8cd..18dda2b37 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/romprefix.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/romprefix.S
@@ -6,9 +6,10 @@
* table so using a noticeable amount of stack space is a no-no.
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#include <config/general.h>
+#include <config/branding.h>
#define PNP_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'n' << 16 ) + ( 'P' << 24 ) )
#define PMM_SIGNATURE ( '$' + ( 'P' << 8 ) + ( 'M' << 16 ) + ( 'M' << 24 ) )
@@ -90,7 +91,7 @@ pciheader:
.ascii "PCIR" /* Signature */
.word pci_vendor_id /* Vendor identification */
.word pci_device_id /* Device identification */
- .word 0x0000 /* Device list pointer */
+ .word ( pci_devlist - pciheader ) /* Device list pointer */
.word pciheader_len /* PCI data structure length */
.byte 0x03 /* PCI data structure revision */
.byte 0x02, 0x00, 0x00 /* Class code */
@@ -106,6 +107,17 @@ pciheader_runtime_length:
.equ pciheader_len, . - pciheader
.size pciheader, . - pciheader
+ /* PCI additional device list (filled in by linker) */
+ .section ".pci_devlist.00000000", "a", @progbits
+pci_devlist:
+ .previous
+ .section ".pci_devlist.ffffffff", "a", @progbits
+pci_devlist_end:
+ .short 0x0000 /* List terminator */
+ .previous
+ /* Ensure that terminator is always present */
+ .reloc pciheader, RELOC_TYPE_NONE, pci_devlist_end
+
.section ".zinfo.fixup", "a", @progbits /* Compressor fixups */
.ascii ZINFO_TYPE_ADxW
.long pciheader_image_length
@@ -573,7 +585,7 @@ get_pmm_decompress_to:
* Note to hardware vendors:
*
* If you wish to brand this boot ROM, please do so by defining the
- * strings PRODUCT_NAME and PRODUCT_SHORT_NAME in config/general.h.
+ * strings PRODUCT_NAME and PRODUCT_SHORT_NAME in config/branding.h.
*
* While nothing in the GPL prevents you from removing all references
* to iPXE or http://ipxe.org, we prefer you not to do so.
@@ -589,7 +601,10 @@ init_message:
.ascii "\n"
.ascii PRODUCT_NAME
.ascii "\n"
- .asciz "iPXE (http://ipxe.org)"
+ .ascii PRODUCT_SHORT_NAME
+ .ascii " ("
+ .ascii PRODUCT_URI
+ .asciz ")"
.size init_message, . - init_message
.ifeqs BUSTYPE, "PCIR"
init_message_pci:
@@ -771,7 +786,9 @@ exec: /* Set %ds = %cs */
/* Store PCI bus:dev.fn, if applicable */
.ifeqs BUSTYPE, "PCIR"
+#ifdef AUTOBOOT_ROM_FILTER
movw %ax, autoboot_busdevfn
+#endif /* AUTOBOOT_ROM_FILTER */
.endif
/* Call main() */
@@ -870,3 +887,9 @@ wait_for_tick:
popl %eax
ret
.size wait_for_tick, . - wait_for_tick
+
+/* Drag in objects via _rom_start */
+REQUIRING_SYMBOL ( _rom_start )
+
+/* Drag in ROM configuration */
+REQUIRE_OBJECT ( config_romprefix )
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/undiloader.S b/qemu/roms/ipxe/src/arch/i386/prefix/undiloader.S
index 74bb59041..5cace44b7 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/undiloader.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/undiloader.S
@@ -1,4 +1,4 @@
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.text
.code16
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/unlzma.S b/qemu/roms/ipxe/src/arch/i386/prefix/unlzma.S
new file mode 100644
index 000000000..8d4b3c1a8
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/unlzma.S
@@ -0,0 +1,942 @@
+/*
+ * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/****************************************************************************
+ *
+ * This file provides the decompress() and decompress16() functions
+ * which can be called in order to decompress an LZMA-compressed
+ * image. The code is modelled on the public-domain "XZ Embedded"
+ * implementation as used by the Linux kernel. Symbol names are
+ * chosen to match the XZ Embedded implementation where possible, for
+ * ease of reference.
+ *
+ * This code is optimised for size rather than speed, since the amount
+ * of data to be decompressed is trivially small by modern standards.
+ *
+ * The same basic assembly code is used to compile both decompress()
+ * and decompress16().
+ *
+ * Note that these functions require large amounts of stack space.
+ *
+ ****************************************************************************
+ */
+
+ .text
+ .arch i586
+ .section ".prefix.lib", "ax", @progbits
+
+#ifdef CODE16
+#define ADDR16
+#define ADDR32 addr32
+#define decompress decompress16
+ .code16
+#else /* CODE16 */
+#define ADDR16 addr16
+#define ADDR32
+ .code32
+#endif /* CODE16 */
+
+/****************************************************************************
+ * Debugging
+ ****************************************************************************
+ *
+ * This code will usually run in 16-bit protected mode, in which case
+ * only the 0xe9 debug port (present on some virtual machines) can be
+ * used.
+ *
+ * To debug on real hardware, build with DEBUG=libprefix. This will
+ * cause this code to be called in flat real mode, and so DEBUG_INT10
+ * may be used.
+ */
+
+/* Enable debugging via 0xe9 debug port */
+#define DEBUG_E9 0
+
+/* Enable debugging via BIOS INT 10 (works only when in flat real mode) */
+#define DEBUG_INT10 0
+
+#if ( DEBUG_E9 || DEBUG_INT10 )
+ .macro print_character, reg
+ pushfl
+ pushw %ax
+ pushw %bx
+ pushw %bp
+ movb \reg, %al
+ movw $0x0007, %bx
+ movb $0x0e, %ah
+#if DEBUG_E9
+ outb %al, $0xe9
+#endif
+#if DEBUG_INT10
+ cmpb $('\n'), %al
+ jne L\@
+ int $0x10
+ movb $('\r'), %al
+L\@: int $0x10
+#endif
+ popw %bp
+ popw %bx
+ popw %ax
+ popfl
+ .endm
+
+ .macro print_hex_nibble
+ pushfl
+ pushw %ax
+ cmpb $10, %al
+ sbb $0x69, %al
+ das
+ print_character %al
+ popw %ax
+ popfl
+ .endm
+
+ .macro print_hex_byte, reg
+ pushfl
+ pushw %ax
+ movb \reg, %al
+ pushw %ax
+ shrb $4, %al
+ print_hex_nibble
+ popw %ax
+ andb $0x0f, %al
+ print_hex_nibble
+ popw %ax
+ popfl
+ .endm
+
+ .macro print_hex_word, reg
+ pushw %ax
+ movw \reg, %ax
+ print_hex_byte %ah
+ print_hex_byte %al
+ popw %ax
+ .endm
+
+ .macro print_hex_dword, reg
+ pushl %eax
+ movl \reg, %eax
+ rorl $16, %eax
+ print_hex_word %ax
+ rorl $16, %eax
+ print_hex_word %ax
+ popl %eax
+ .endm
+#else
+ .macro print_character, char
+ .endm
+ .macro print_hex_byte, reg
+ .endm
+ .macro print_hex_word, reg
+ .endm
+ .macro print_hex_dword, reg
+ .endm
+#endif
+
+/****************************************************************************
+ * LZMA parameters and data structures
+ ****************************************************************************
+ */
+
+/* LZMA decompressor states (as used in XZ Embedded) */
+#define STATE_LIT_LIT 0x00
+#define STATE_MATCH_LIT_LIT 0x01
+#define STATE_REP_LIT_LIT 0x02
+#define STATE_SHORTREP_LIT_LIT 0x03
+#define STATE_MATCH_LIT 0x04
+#define STATE_REP_LIT 0x05
+#define STATE_SHORTREP_LIT 0x06
+#define STATE_LIT_MATCH 0x07
+#define STATE_LIT_LONGREP 0x08
+#define STATE_LIT_SHORTREP 0x09
+#define STATE_NONLIT_MATCH 0x0a
+#define STATE_NONLIT_REP 0x0b
+
+/* LZMA maximum decompressor state in which most recent symbol was a literal */
+#define STATE_LIT_MAX 0x06
+
+/* LZMA number of literal context bits ("lc=" parameter) */
+#define LZMA_LC 2
+
+ .struct 0
+lzma_len_dec:
+choice: .word 0
+choice2: .word 0
+low: .rept ( 1 << 3 )
+ .word 0
+ .endr
+mid: .rept ( 1 << 3 )
+ .word 0
+ .endr
+high: .rept ( 1 << 8 )
+ .word 0
+ .endr
+ .equ sizeof__lzma_len_dec, . - lzma_len_dec
+ .previous
+
+ .struct 0
+lzma_dec:
+out_start: .long 0
+rc_code: .long 0
+rc_range: .long 0
+len: .word 0
+reps:
+rep0: .long 0
+rep1: .long 0
+rep2: .long 0
+rep3: .long 0
+probs:
+is_match: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+is_rep: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+is_rep0: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+is_rep1: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+is_rep2: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+is_rep0_long: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+dist_slot: .rept ( 4 * ( 1 << 6 ) )
+ .word 0
+ .endr
+dist_special: .rept ( ( 1 << ( 14 / 2 ) ) - 14 )
+ .word 0
+ .endr
+dist_align: .rept ( 1 << 4 )
+ .word 0
+ .endr
+match_len_dec: .space sizeof__lzma_len_dec
+rep_len_dec: .space sizeof__lzma_len_dec
+literal: .rept ( ( 1 << LZMA_LC ) * 0x300 )
+ .word 0
+ .endr
+ .align 4
+ .equ sizeof__lzma_dec, . - lzma_dec
+ .previous
+
+ /* Some binutils versions seem not to handle .struct/.previous */
+ .section ".prefix.lib", "ax", @progbits
+
+/*****************************************************************************
+ * Normalise range encoder
+ *
+ * Parameters:
+ * %ss:%ebp : LZMA parameter block
+ * %ds:%esi : compressed input data pointer
+ * Returns:
+ * %ds:%esi : compressed input data pointer (possibly updated)
+ * %eax : current range
+ *****************************************************************************
+ */
+rc_normalise:
+ /* Check if rc_range is less than 1<<24 */
+ testb $0xff, (rc_range+3)(%ebp)
+ jnz 1f
+ /* If it is, shift in a new byte from the compressed input data */
+ shll $8, rc_range(%ebp)
+ shll $8, rc_code(%ebp)
+ ADDR32 lodsb
+ movb %al, (rc_code+0)(%ebp)
+1: /* Return current range */
+ movl rc_range(%ebp), %eax
+ ret
+ .size rc_normalise, . - rc_normalise
+
+/*****************************************************************************
+ * Decode single range-encoded bit using a probability estimate
+ *
+ * Parameters:
+ * %ss:%ebp : LZMA parameter block
+ * %ds:%esi : compressed input data pointer
+ * %ebx : probability estimate pointer (offset from %ebp)
+ * Returns:
+ * %ds:%esi : compressed input data pointer (possibly updated)
+ * CF : decoded bit
+ * ZF : inverse of decoded bit
+ * Corrupts:
+ * none
+ *****************************************************************************
+ */
+rc_bit:
+ /* Preserve registers */
+ pushl %eax
+ pushl %edx
+ /* Perform normalisation */
+ call rc_normalise
+ /* Calculate bound in %eax and probability estimate in %dx */
+ shrl $11, %eax
+ movzwl (%ebp,%ebx), %edx
+ mul %edx /* will zero %edx */
+ movw (%ebp,%ebx), %dx
+ /* Compare code against bound */
+ cmpl %eax, rc_code(%ebp)
+ jae 2f
+1: /* Code is less than bound */
+ movl %eax, rc_range(%ebp)
+ negw %dx
+ addw $(1<<11), %dx
+ shrw $5, %dx
+ addw %dx, (%ebp,%ebx)
+ xorw %ax, %ax /* Clear CF, set ZF */
+ jmp 99f
+2: /* Code is greater than or equal to bound */
+ subl %eax, rc_range(%ebp)
+ subl %eax, rc_code(%ebp)
+ shrw $5, %dx
+ subw %dx, (%ebp,%ebx)
+ incw %dx /* Clear ZF (%dx is 11-bit; can never wrap) */
+ stc /* Set CF */
+99: /* Restore registers and return */
+ popl %edx
+ popl %eax
+ ret
+ .size rc_bit, . - rc_bit
+
+/*****************************************************************************
+ * Decode MSB-first bittree
+ *
+ * Parameters:
+ * %ss:%ebp : LZMA parameter block
+ * %ds:%esi : compressed input data pointer
+ * %ebx : probability estimate set pointer (offset from %ebp)
+ * %cx : number of bits to decode
+ * Returns:
+ * %ds:%esi : compressed input data pointer (possibly updated)
+ * %eax : decoded bittree
+ * Corrupts:
+ * none
+ *****************************************************************************
+ */
+rc_bittree:
+ /* Preserve registers */
+ pushl %edi
+ pushw %cx
+ movl %ebx, %edi
+ /* Initialise registers */
+ movl $1, %eax
+1: /* Decode bit */
+ leaw (%edi,%eax,2), %bx /* high word always zero anyway */
+ call rc_bit
+ rclw %ax
+ ADDR16 loop 1b
+ /* Restore registers, clear unwanted high bit of result, and return */
+ movl %edi, %ebx
+ popw %cx
+ popl %edi
+ btrw %cx, %ax
+ ret
+ .size rc_bittree, . - rc_bittree
+
+/*****************************************************************************
+ * Decode LSB-first bittree
+ *
+ * Parameters:
+ * %ss:%ebp : LZMA parameter block
+ * %ds:%esi : compressed input data pointer
+ * %ebx : probability estimate set pointer (offset from %ebp)
+ * %cx : number of bits to decode
+ * Returns:
+ * %ds:%esi : compressed input data pointer (possibly updated)
+ * %eax : decoded bittree
+ * Corrupts:
+ * none
+ *****************************************************************************
+ */
+rc_bittree_reverse:
+ /* Preserve registers */
+ pushw %cx
+ /* Decode bittree */
+ call rc_bittree
+1: /* Reverse result */
+ rcrb %al
+ rclb %ah
+ ADDR16 loop 1b
+ shrw $8, %ax
+ /* Restore registers and return */
+ popw %cx
+ ret
+ .size rc_bittree_reverse, . - rc_bittree_reverse
+
+/*****************************************************************************
+ * Decode MSB-first bittree with optional match byte
+ *
+ * Parameters:
+ * %ss:%ebp : LZMA parameter block
+ * %ds:%esi : compressed input data pointer
+ * %ebx : probability estimate set pointer (offset from %ebp)
+ * %cl : match byte
+ * %ch : 1 to use match byte, 0 to ignore match byte
+ * Returns:
+ * %ds:%esi : compressed input data pointer (possibly updated)
+ * %eax : decoded bittree
+ * Corrupts:
+ * none
+ *****************************************************************************
+ */
+rc_bittree_match:
+ /* Preserve registers */
+ pushl %edi
+ pushw %cx
+ pushw %dx
+ movl %ebx, %edi
+ /* Initialise registers */
+ movl $1, %eax
+1: /* Decode bit */
+ rolb $1, %cl
+ movw %cx, %dx
+ andb %dh, %dl /* match_bit in %dl */
+ movw %dx, %bx
+ addb %bl, %bh
+ xorb %bl, %bl
+ addw %ax, %bx /* offset + match_bit + symbol */
+ leaw (%edi,%ebx,2), %bx /* high word always zero anyway */
+ call rc_bit
+ rclw %ax
+ movb %al, %dh
+ notb %dh
+ xorb %dh, %dl
+ andb %dl, %ch /* offset &= ( match_bit ^ bit ) */
+ testb %ah, %ah
+ jz 1b
+ /* Restore registers, clear unwanted high bit of result, and return */
+ movl %edi, %ebx
+ popw %dx
+ popw %cx
+ popl %edi
+ xorb %ah, %ah
+ ret
+ .size rc_bittree_match, . - rc_bittree_match
+
+/*****************************************************************************
+ * Decode direct bits (no probability estimates)
+ *
+ * Parameters:
+ * %ss:%ebp : LZMA parameter block
+ * %ds:%esi : compressed input data pointer
+ * %cx : number of bits to decode
+ * Returns:
+ * %ds:%esi : compressed input data pointer (possibly updated)
+ * %eax : decoded bits
+ * Corrupts:
+ * none
+ *****************************************************************************
+ */
+rc_direct:
+ /* Preserve registers */
+ pushl %ebx
+ pushw %cx
+ pushl %edx
+ /* Initialise registers */
+ xorl %edx, %edx
+1: /* Perform normalisation */
+ call rc_normalise
+ /* Decode bit */
+ shrl $1, %eax
+ movl %eax, rc_range(%ebp)
+ movl rc_code(%ebp), %ebx
+ subl %eax, %ebx
+ js 2f
+ movl %ebx, rc_code(%ebp)
+2: rcll %ebx
+ rcll %edx
+ xorb $1, %dl
+ ADDR16 loop 1b
+ /* Restore registers and return */
+ movl %edx, %eax
+ popl %edx
+ popw %cx
+ popl %ebx
+ ret
+ .size rc_direct, . - rc_direct
+
+/*****************************************************************************
+ * Decode an LZMA literal
+ *
+ * Parameters:
+ * %ss:%ebp : LZMA parameter block
+ * %ds:%esi : compressed input data pointer
+ * %es:%edi : uncompressed output data pointer
+ * %edx : LZMA state
+ * Returns:
+ * %ds:%esi : compressed input data pointer (possibly updated)
+ * %es:%edi : uncompressed output data pointer (updated)
+ * %edx : LZMA state
+ * CF : end of payload marker found (always zero)
+ * Corrupts:
+ * %eax
+ * %ebx
+ * %ecx
+ *****************************************************************************
+ *
+ * Literals are coded as an eight-bit tree, using a match byte if the
+ * previous symbol was not a literal.
+ *
+ */
+lzma_literal:
+ /* Get most recent output byte, if available */
+ xorl %ebx, %ebx
+ cmpl %edi, out_start(%ebp)
+ je 1f
+ movb %es:-1(%edi), %bh
+1: /* Locate probability estimate set */
+ shrb $( 8 - LZMA_LC ), %bh
+ shlb $1, %bh
+ leaw literal(%ebx,%ebx,2), %bx
+ /* Get match byte, if applicable */
+ xorw %cx, %cx
+ cmpb $STATE_LIT_MAX, %dl
+ jbe 1f
+ movl rep0(%ebp), %eax
+ notl %eax
+ movb %es:(%edi,%eax), %cl
+ movb $1, %ch
+1: /* Decode bittree */
+ call rc_bittree_match
+ /* Store output byte */
+ ADDR32 stosb
+ print_hex_byte %al
+ print_character $(' ')
+ /* Update LZMA state */
+ subb $3, %dl
+ jns 1f
+ xorb %dl, %dl
+1: cmpb $7, %dl
+ jb 1f
+ subb $3, %dl
+1: /* Clear CF and return */
+ clc
+ ret
+ .size lzma_literal, . - lzma_literal
+
+/*****************************************************************************
+ * Decode an LZMA length
+ *
+ * Parameters:
+ * %ss:%ebp : LZMA parameter block
+ * %ds:%esi : compressed input data pointer
+ * %ebx : length parameter pointer (offset from %ebp)
+ * Returns:
+ * %ds:%esi : compressed input data pointer (possibly updated)
+ * Corrupts:
+ * %ebx
+ *****************************************************************************
+ *
+ * Lengths are encoded as:
+ *
+ * "0" + 3 bits : lengths 2-9 ("low")
+ * "10" + 3 bits : lengths 10-17 ("mid")
+ * "11" + 8 bits : lengths 18-273 ("high")
+ */
+lzma_len:
+ /* Preserve registers */
+ pushl %eax
+ pushl %ecx
+ pushl %edi
+ movl %ebx, %edi
+ /* Start by assuming three bits and a base length of 2 */
+ movw $3, %cx
+ movw $2, len(%ebp)
+ /* Check low-length choice bit */
+ leal choice(%edi), %ebx
+ call rc_bit
+ leal low(%edi), %ebx
+ jz 1f
+ /* Check high-length choice bit */
+ leal choice2(%edi), %ebx
+ call rc_bit
+ leal mid(%edi), %ebx
+ movb $10, len(%ebp)
+ jz 1f
+ leal high(%edi), %ebx
+ movb $8, %cl
+ movb $18, len(%ebp)
+1: /* Get encoded length */
+ call rc_bittree
+ addw %ax, len(%ebp)
+ /* Restore registers and return */
+ movl %edi, %ebx
+ popl %edi
+ popl %ecx
+ popl %eax
+ ret
+ .size lzma_len, . - lzma_len
+
+/*****************************************************************************
+ * Copy (possibly repeated) matched data
+ *
+ * Parameters:
+ * %ss:%ebp : LZMA parameter block
+ * %ds:%esi : compressed input data pointer
+ * %es:%edi : uncompressed output data pointer
+ * %cl : repeated match distance index (for repeated matches)
+ * %eax : match distance (for non-repeated matches)
+ * Returns:
+ * %ds:%esi : compressed input data pointer (possibly updated)
+ * %es:%edi : uncompressed output data pointer
+ * CF : match distance is out of range
+ * Corrupts:
+ * %eax
+ * %ebx
+ * %ecx
+ *****************************************************************************
+ */
+match: /* Update repeated match list */
+ print_character $('[')
+ movl $3, %ecx
+ jmp 1f
+match_rep:
+ print_character $('[')
+ print_character $('R')
+ print_hex_byte %cl
+ print_character $('=')
+ movzbl %cl, %ecx
+ movl reps(%ebp,%ecx,4), %eax
+ jcxz 2f
+1: movl (reps-4)(%ebp,%ecx,4), %ebx
+ movl %ebx, reps(%ebp,%ecx,4)
+ loop 1b
+ movl %eax, rep0(%ebp)
+2: /* Preserve registers */
+ pushl %esi
+ /* Get stored match length */
+ movzwl len(%ebp), %ecx
+ print_hex_dword %eax
+ print_character $('+')
+ print_hex_word %cx
+ print_character $(']')
+ print_character $(' ')
+ /* Abort with CF set if match distance is out of range */
+ movl out_start(%ebp), %esi
+ negl %esi
+ leal -1(%edi,%esi), %esi
+ cmpl %eax, %esi
+ jc 99f
+ /* Perform copy */
+ notl %eax
+ leal (%edi,%eax), %esi
+ ADDR32 es rep movsb
+99: /* Restore registers and return */
+ popl %esi
+ ret
+ .size match, . - match
+
+/*****************************************************************************
+ * Decode an LZMA match
+ *
+ * Parameters:
+ * %ss:%ebp : LZMA parameter block
+ * %ds:%esi : compressed input data pointer
+ * %es:%edi : uncompressed output data pointer
+ * %edx : LZMA state
+ * Returns:
+ * %ds:%esi : compressed input data pointer (possibly updated)
+ * %es:%edi : uncompressed output data pointer
+ * %edx : LZMA state
+ * CF : end of payload marker found
+ * Corrupts:
+ * %eax
+ * %ebx
+ * %ecx
+ *****************************************************************************
+ *
+ * Matches are encoded as an LZMA length followed by a 6-bit "distance
+ * slot" code, 0-26 fixed-probability bits, and 0-5 context encoded
+ * bits.
+ */
+lzma_match:
+ /* Preserve registers */
+ pushl %edi
+ /* Update LZMA state */
+ cmpb $STATE_LIT_MAX, %dl
+ movb $STATE_LIT_MATCH, %dl
+ jbe 1f
+ movb $STATE_NONLIT_MATCH, %dl
+1: /* Decode length */
+ movl $match_len_dec, %ebx
+ call lzma_len
+ /* Decode distance slot */
+ movw len(%ebp), %bx
+ subw $2, %bx
+ cmpw $4, %bx
+ jb 1f
+ movw $3, %bx
+1: shlw $7, %bx
+ addw $dist_slot, %bx
+ movw $6, %cx
+ call rc_bittree
+ /* Distance slots 0-3 are literal distances */
+ cmpb $4, %al
+ jb 99f
+ /* Determine initial bits: 10/11 for even/odd distance codes */
+ movl %eax, %edi
+ andw $1, %di
+ orw $2, %di
+ /* Determine number of context-encoded bits */
+ movw %ax, %cx
+ shrb $1, %cl
+ decb %cl
+ /* Select context to be used in absence of fixed-probability bits */
+ movl %edi, %ebx
+ shlw %cl, %bx
+ subw %ax, %bx
+ leaw (dist_special-2)(%ebx,%ebx), %bx
+ /* Decode fixed-probability bits, if any */
+ cmpb $6, %cl
+ jb 1f
+ subb $4, %cl
+ shll %cl, %edi
+ call rc_direct
+ orl %eax, %edi
+ /* Select context to be used in presence of fixed-probability bits */
+ movb $4, %cl
+ movl $dist_align, %ebx
+1: /* Decode context-encoded bits */
+ shll %cl, %edi
+ call rc_bittree_reverse
+ orl %edi, %eax
+99: /* Restore registers and tail-call */
+ popl %edi
+ jmp match
+ .size lzma_match, . - lzma_match
+
+/*****************************************************************************
+ * Decode an LZMA repeated match
+ *
+ * Parameters:
+ * %ss:%ebp : LZMA parameter block
+ * %ds:%esi : compressed input data pointer
+ * %es:%edi : uncompressed output data pointer
+ * %edx : LZMA state
+ * Returns:
+ * %ds:%esi : compressed input data pointer (possibly updated)
+ * %es:%edi : uncompressed output data pointer
+ * %edx : LZMA state
+ * CF : end of payload marker found
+ * Corrupts:
+ * %eax
+ * %ebx
+ * %ecx
+ *****************************************************************************
+ *
+ * Repeated matches are encoded as:
+ *
+ * "00" : shortrep0 (implicit length 1)
+ * "01" + len : longrep0
+ * "10" + len : longrep1
+ * "110" + len : longrep2
+ * "111" + len : longrep3
+ */
+lzma_rep_match:
+ /* Initially assume longrep0 */
+ movw $(STATE_LIT_LONGREP << 8), %cx
+ /* Get is_rep0 bit */
+ leal is_rep0(,%edx,2), %ebx
+ call rc_bit
+ jnz 1f
+ /* Get is_rep0_long bit */
+ leal is_rep0_long(,%edx,2), %ebx
+ call rc_bit
+ jnz 98f
+ movw $1, len(%ebp)
+ movb $STATE_LIT_SHORTREP, %ch
+ jmp 99f
+1: /* Get is_rep1 bit */
+ incb %cl
+ leal is_rep1(,%edx,2), %ebx
+ call rc_bit
+ jz 98f
+ /* Get is_rep2 bit */
+ incb %cl
+ leal is_rep2(,%edx,2), %ebx
+ call rc_bit
+ adcb $0, %cl
+98: /* Decode length */
+ movl $rep_len_dec, %ebx
+ call lzma_len
+99: /* Update LZMA state */
+ cmpb $STATE_LIT_MAX, %dl
+ movb %ch, %dl
+ jbe 1f
+ movb $STATE_NONLIT_REP, %dl
+1: /* Tail call */
+ jmp match_rep
+ .size lzma_match, . - lzma_match
+
+/*****************************************************************************
+ * Decode one LZMA symbol
+ *
+ * Parameters:
+ * %ss:%ebp : LZMA parameter block
+ * %ds:%esi : compressed input data pointer
+ * %es:%edi : uncompressed output data pointer
+ * %edx : LZMA state
+ * Returns:
+ * %ds:%esi : compressed input data pointer (possibly updated)
+ * %es:%edi : uncompressed output data pointer (updated)
+ * %edx : LZMA state
+ * CF : end of payload marker found
+ * Corrupts:
+ * %eax
+ * %ebx
+ * %ecx
+ *****************************************************************************
+ */
+lzma_decode:
+ /* Get is_match bit */
+ leal is_match(,%edx,2), %ebx
+ call rc_bit
+ jz lzma_literal
+ /* Get is_rep bit */
+ leal is_rep(,%edx,2), %ebx
+ call rc_bit
+ jz lzma_match
+ jmp lzma_rep_match
+ .size lzma_decode, . - lzma_decode
+
+/****************************************************************************
+ * Undo effect of branch-call-jump (BCJ) filter
+ *
+ * Parameters:
+ * %es:%esi : start of uncompressed output data (note %es)
+ * %es:%edi : end of uncompressed output data
+ * Returns:
+ * Corrupts:
+ * %eax
+ * %ebx
+ * %ecx
+ * %edx
+ * %esi
+ *****************************************************************************
+ */
+bcj_filter:
+ /* Store (negative) start of data in %edx */
+ movl %esi, %edx
+ negl %edx
+ /* Calculate limit in %ecx */
+ leal -5(%edi,%edx), %ecx
+1: /* Calculate offset in %ebx */
+ leal (%esi,%edx), %ebx
+ /* Check for end of data */
+ cmpl %ecx, %ebx
+ ja 99f
+ /* Check for an opcode which would be followed by a rel32 address */
+ ADDR32 es lodsb
+ andb $0xfe, %al
+ cmpb $0xe8, %al
+ jne 1b
+ /* Get current jump target value in %eax */
+ ADDR32 es lodsl
+ /* Convert absolute addresses in the range [0,limit) back to
+ * relative addresses in the range [-offset,limit-offset).
+ */
+ cmpl %ecx, %eax
+ jae 2f
+ subl %ebx,%es:-4(%esi)
+2: /* Convert negative numbers in the range [-offset,0) back to
+ * positive numbers in the range [limit-offset,limit).
+ */
+ notl %eax /* Range is now [0,offset) */
+ cmpl %ebx, %eax
+ jae 1b
+ addl %ecx,%es:-4(%esi)
+ jmp 1b
+99: /* Return */
+ ret
+ .size bcj_filter, . - bcj_filter
+
+/****************************************************************************
+ * decompress (real-mode or 16/32-bit protected-mode near call)
+ *
+ * Decompress data
+ *
+ * Parameters (passed via registers):
+ * %ds:%esi : Start of compressed input data
+ * %es:%edi : Start of output buffer
+ * Returns:
+ * %ds:%esi - End of compressed input data
+ * %es:%edi - End of decompressed output data
+ * All other registers are preserved
+ *
+ * NOTE: It would be possible to build a smaller version of the
+ * decompression code for -DKEEP_IT_REAL by using 16-bit registers
+ * where possible.
+ ****************************************************************************
+ */
+ .globl decompress
+decompress:
+ /* Preserve registers */
+ pushl %eax
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ pushl %ebp
+ /* Allocate parameter block */
+ subl $sizeof__lzma_dec, %esp
+ movl %esp, %ebp
+ /* Zero parameter block and set all probabilities to 0.5 */
+ pushl %edi
+ pushw %es
+ pushw %ss
+ popw %es
+ movl %ebp, %edi
+ xorl %eax, %eax
+ movl $( sizeof__lzma_dec / 4 ), %ecx
+ ADDR32 rep stosl
+ leal probs(%ebp), %edi
+ movw $( ( 1 << 11 ) / 2 ), %ax
+ movl $( ( sizeof__lzma_dec - probs ) / 2 ), %ecx
+ ADDR32 rep stosw
+ popw %es
+ popl %edi
+ /* Initialise remaining parameters */
+ movl %edi, out_start(%ebp)
+ print_character $('\n')
+ ADDR32 lodsb /* discard initial byte */
+ print_hex_byte %al
+ ADDR32 lodsl
+ bswapl %eax
+ print_hex_dword %eax
+ print_character $('\n')
+ movl %eax, rc_code(%ebp)
+ decl rc_range(%ebp)
+ movl $STATE_LIT_LIT, %edx
+1: /* Decompress until we reach end of buffer */
+ call lzma_decode
+ jnc 1b
+ call rc_normalise
+ print_character $('\n')
+ /* Undo BCJ filter */
+ pushl %esi
+ movl out_start(%ebp), %esi
+ call bcj_filter
+ popl %esi
+ /* Restore registers and return */
+ addl $sizeof__lzma_dec, %esp
+ popl %ebp
+ popl %edx
+ popl %ecx
+ popl %ebx
+ popl %eax
+ ret
+
+ /* Specify minimum amount of stack space required */
+ .globl _min_decompress_stack
+ .equ _min_decompress_stack, ( sizeof__lzma_dec + 512 /* margin */ )
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/unnrv2b16.S b/qemu/roms/ipxe/src/arch/i386/prefix/unlzma16.S
index b24c2846f..32b43f0dc 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/unnrv2b16.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/unlzma16.S
@@ -3,7 +3,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
#define CODE16
-#include "unnrv2b.S"
+#include "unlzma.S"
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/unnrv2b.S b/qemu/roms/ipxe/src/arch/i386/prefix/unnrv2b.S
deleted file mode 100644
index f5724c134..000000000
--- a/qemu/roms/ipxe/src/arch/i386/prefix/unnrv2b.S
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
- *
- * This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * Originally this code was part of ucl the data compression library
- * for upx the ``Ultimate Packer of eXecutables''.
- *
- * - Converted to gas assembly, and refitted to work with etherboot.
- * Eric Biederman 20 Aug 2002
- *
- * - Structure modified to be a subroutine call rather than an
- * executable prefix.
- * Michael Brown 30 Mar 2004
- *
- * - Modified to be compilable as either 16-bit or 32-bit code.
- * Michael Brown 9 Mar 2005
- */
-
-FILE_LICENCE ( GPL2_OR_LATER )
-
-/****************************************************************************
- * This file provides the decompress() and decompress16() functions
- * which can be called in order to decompress an image compressed with
- * the nrv2b utility in src/util.
- *
- * These functions are designed to be called by the prefix. They are
- * position-independent code.
- *
- * The same basic assembly code is used to compile both
- * decompress() and decompress16().
- ****************************************************************************
- */
-
- .text
- .arch i386
- .section ".prefix.lib", "ax", @progbits
-
-#ifdef CODE16
-/****************************************************************************
- * decompress16 (real-mode near call, position independent)
- *
- * Decompress data in 16-bit mode
- *
- * Parameters (passed via registers):
- * %ds:%esi - Start of compressed input data
- * %es:%edi - Start of output buffer
- * Returns:
- * %ds:%esi - End of compressed input data
- * %es:%edi - End of decompressed output data
- * All other registers are preserved
- *
- * NOTE: It would be possible to build a smaller version of the
- * decompression code for -DKEEP_IT_REAL by using
- * #define REG(x) x
- * to use 16-bit registers where possible. This would impose limits
- * that the compressed data size must be in the range [1,65533-%si]
- * and the uncompressed data size must be in the range [1,65536-%di]
- * (where %si and %di are the input values for those registers). Note
- * particularly that the lower limit is 1, not 0, and that the upper
- * limit on the input (compressed) data really is 65533, since the
- * algorithm may read up to three bytes beyond the end of the input
- * data, since it reads dwords.
- ****************************************************************************
- */
-
-#define REG(x) e ## x
-#define ADDR32 addr32
-
- .code16
- .globl decompress16
-decompress16:
-
-#else /* CODE16 */
-
-/****************************************************************************
- * decompress (32-bit protected-mode near call, position independent)
- *
- * Parameters (passed via registers):
- * %ds:%esi - Start of compressed input data
- * %es:%edi - Start of output buffer
- * Returns:
- * %ds:%esi - End of compressed input data
- * %es:%edi - End of decompressed output data
- * All other registers are preserved
- ****************************************************************************
- */
-
-#define REG(x) e ## x
-#define ADDR32
-
- .code32
- .globl decompress
-decompress:
-
-#endif /* CODE16 */
-
-#define xAX REG(ax)
-#define xCX REG(cx)
-#define xBP REG(bp)
-#define xSI REG(si)
-#define xDI REG(di)
-
- /* Save registers */
- push %xAX
- pushl %ebx
- push %xCX
- push %xBP
- /* Do the decompression */
- cld
- xor %xBP, %xBP
- dec %xBP /* last_m_off = -1 */
- jmp dcl1_n2b
-
-decompr_literals_n2b:
- ADDR32 movsb
-decompr_loop_n2b:
- addl %ebx, %ebx
- jnz dcl2_n2b
-dcl1_n2b:
- call getbit32
-dcl2_n2b:
- jc decompr_literals_n2b
- xor %xAX, %xAX
- inc %xAX /* m_off = 1 */
-loop1_n2b:
- call getbit1
- adc %xAX, %xAX /* m_off = m_off*2 + getbit() */
- call getbit1
- jnc loop1_n2b /* while(!getbit()) */
- sub $3, %xAX
- jb decompr_ebpeax_n2b /* if (m_off == 2) goto decompr_ebpeax_n2b ? */
- shl $8, %xAX
- ADDR32 movb (%xSI), %al /* m_off = (m_off - 3)*256 + src[ilen++] */
- inc %xSI
- xor $-1, %xAX
- jz decompr_end_n2b /* if (m_off == 0xffffffff) goto decomp_end_n2b */
- mov %xAX, %xBP /* last_m_off = m_off ?*/
-decompr_ebpeax_n2b:
- xor %xCX, %xCX
- call getbit1
- adc %xCX, %xCX /* m_len = getbit() */
- call getbit1
- adc %xCX, %xCX /* m_len = m_len*2 + getbit()) */
- jnz decompr_got_mlen_n2b /* if (m_len == 0) goto decompr_got_mlen_n2b */
- inc %xCX /* m_len++ */
-loop2_n2b:
- call getbit1
- adc %xCX, %xCX /* m_len = m_len*2 + getbit() */
- call getbit1
- jnc loop2_n2b /* while(!getbit()) */
- inc %xCX
- inc %xCX /* m_len += 2 */
-decompr_got_mlen_n2b:
- cmp $-0xd00, %xBP
- adc $1, %xCX /* m_len = m_len + 1 + (last_m_off > 0xd00) */
- push %xSI
- ADDR32 lea (%xBP,%xDI), %xSI /* m_pos = dst + olen + -m_off */
- rep
- es ADDR32 movsb /* dst[olen++] = *m_pos++ while(m_len > 0) */
- pop %xSI
- jmp decompr_loop_n2b
-
-
-getbit1:
- addl %ebx, %ebx
- jnz 1f
-getbit32:
- ADDR32 movl (%xSI), %ebx
- sub $-4, %xSI /* sets carry flag */
- adcl %ebx, %ebx
-1:
- ret
-
-decompr_end_n2b:
- /* Restore registers and return */
- pop %xBP
- pop %xCX
- popl %ebx
- pop %xAX
- ret
diff --git a/qemu/roms/ipxe/src/arch/i386/prefix/usbdisk.S b/qemu/roms/ipxe/src/arch/i386/prefix/usbdisk.S
index fa7d1956e..9676406e2 100644
--- a/qemu/roms/ipxe/src/arch/i386/prefix/usbdisk.S
+++ b/qemu/roms/ipxe/src/arch/i386/prefix/usbdisk.S
@@ -1,3 +1,5 @@
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+
.text
.arch i386
.section ".prefix", "awx", @progbits
@@ -6,18 +8,27 @@
#include "mbr.S"
-/* Partition table: ZIP-compatible partition 4, 64 heads, 32 sectors/track */
+/* Partition table: 64 heads, 32 sectors/track (ZIP-drive compatible) */
.org 446
.space 16
.space 16
- .space 16
- .byte 0x80, 0x01, 0x01, 0x00
- .byte 0xeb, 0x3f, 0x20, 0x01
+ /* Partition 3: log partition (for CONSOLE_INT13) */
+ .byte 0x00, 0x01, 0x01, 0x00
+ .byte 0xe0, 0x3f, 0x20, 0x00
.long 0x00000020
- .long 0x00000fe0
+ .long 0x000007e0
+ /* Partition 4: boot partition */
+ .byte 0x80, 0x00, 0x01, 0x01
+ .byte 0xeb, 0x3f, 0x20, 0x02
+ .long 0x00000800
+ .long 0x00001000
.org 510
.byte 0x55, 0xaa
-/* Skip to start of partition */
+/* Skip to start of log partition */
.org 32 * 512
+ .ascii "iPXE LOG\n\n"
+
+/* Skip to start of boot partition */
+ .org 2048 * 512
diff --git a/qemu/roms/ipxe/src/arch/i386/scripts/i386.lds b/qemu/roms/ipxe/src/arch/i386/scripts/i386.lds
index 98f95cb23..38c89e14b 100644
--- a/qemu/roms/ipxe/src/arch/i386/scripts/i386.lds
+++ b/qemu/roms/ipxe/src/arch/i386/scripts/i386.lds
@@ -27,6 +27,13 @@ SECTIONS {
PROVIDE ( _max_align = 16 );
/*
+ * Allow decompressor to require a minimum amount of temporary stack
+ * space.
+ *
+ */
+ PROVIDE ( _min_decompress_stack = 0 );
+
+ /*
* The prefix
*
*/
@@ -34,6 +41,7 @@ SECTIONS {
.prefix 0x0 : AT ( _prefix_lma ) {
_prefix = .;
*(.prefix)
+ *(SORT(.pci_devlist.*))
*(.prefix.*)
_mprefix = .;
} .bss.prefix (NOLOAD) : AT ( _end_lma ) {
@@ -87,6 +95,7 @@ SECTIONS {
*(.bss16.*)
*(.stack16)
*(.stack16.*)
+ . = MAX ( ., _mdata16 + _min_decompress_stack );
_edata16 = .;
}
_data16_filesz = ABSOLUTE ( _mdata16 ) - ABSOLUTE ( _data16 );
diff --git a/qemu/roms/ipxe/src/arch/i386/transitions/liba20.S b/qemu/roms/ipxe/src/arch/i386/transitions/liba20.S
index 684697525..6c1e1f62f 100644
--- a/qemu/roms/ipxe/src/arch/i386/transitions/liba20.S
+++ b/qemu/roms/ipxe/src/arch/i386/transitions/liba20.S
@@ -16,9 +16,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ *
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
.arch i386
diff --git a/qemu/roms/ipxe/src/arch/i386/transitions/libkir.S b/qemu/roms/ipxe/src/arch/i386/transitions/libkir.S
index 1176fcced..fa9459d52 100644
--- a/qemu/roms/ipxe/src/arch/i386/transitions/libkir.S
+++ b/qemu/roms/ipxe/src/arch/i386/transitions/libkir.S
@@ -5,7 +5,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
/****************************************************************************
* This file defines libkir: an interface between external and
diff --git a/qemu/roms/ipxe/src/arch/i386/transitions/librm.S b/qemu/roms/ipxe/src/arch/i386/transitions/librm.S
index 2e447b030..863e22415 100644
--- a/qemu/roms/ipxe/src/arch/i386/transitions/librm.S
+++ b/qemu/roms/ipxe/src/arch/i386/transitions/librm.S
@@ -5,7 +5,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER )
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
/* Drag in local definitions */
#include "librm.h"
diff --git a/qemu/roms/ipxe/src/arch/i386/transitions/librm_mgmt.c b/qemu/roms/ipxe/src/arch/i386/transitions/librm_mgmt.c
index cc4765de2..becb02677 100644
--- a/qemu/roms/ipxe/src/arch/i386/transitions/librm_mgmt.c
+++ b/qemu/roms/ipxe/src/arch/i386/transitions/librm_mgmt.c
@@ -5,7 +5,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/profile.h>
@@ -103,7 +103,7 @@ void init_idt ( void ) {
( uint32_t ) vec->next );
set_interrupt_vector ( intr, vec );
}
- DBGC ( &intr_vec[0], "INTn vector at %p+%xn (phys %#lx+%xn)\n",
+ DBGC ( &intr_vec[0], "INTn vector at %p+%zxn (phys %#lx+%zxn)\n",
intr_vec, sizeof ( intr_vec[0] ),
virt_to_phys ( intr_vec ), sizeof ( intr_vec[0] ) );
diff --git a/qemu/roms/ipxe/src/arch/i386/transitions/librm_test.c b/qemu/roms/ipxe/src/arch/i386/transitions/librm_test.c
index e07cfccdd..f1a517eda 100644
--- a/qemu/roms/ipxe/src/arch/i386/transitions/librm_test.c
+++ b/qemu/roms/ipxe/src/arch/i386/transitions/librm_test.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
@@ -114,4 +118,5 @@ struct self_test librm_test __self_test = {
.exec = librm_test_exec,
};
+REQUIRING_SYMBOL ( librm_test );
REQUIRE_OBJECT ( test );
diff --git a/qemu/roms/ipxe/src/arch/x86/Makefile b/qemu/roms/ipxe/src/arch/x86/Makefile
index e555587df..98c49b98d 100644
--- a/qemu/roms/ipxe/src/arch/x86/Makefile
+++ b/qemu/roms/ipxe/src/arch/x86/Makefile
@@ -9,9 +9,14 @@ SRCDIRS += arch/x86/interface/efi
SRCDIRS += arch/x86/prefix
SRCDIRS += arch/x86/hci/commands
SRCDIRS += arch/x86/drivers/xen
+SRCDIRS += arch/x86/drivers/hyperv
# breaks building some of the linux-related objects
CFLAGS += -Ulinux
# disable valgrind
CFLAGS += -DNVALGRIND
+
+# Include Hyper-V driver in the all-drivers build
+#
+DRIVERS_hyperv += hyperv
diff --git a/qemu/roms/ipxe/src/arch/x86/Makefile.efi b/qemu/roms/ipxe/src/arch/x86/Makefile.efi
index 13a69d9f7..f73bc7d5d 100644
--- a/qemu/roms/ipxe/src/arch/x86/Makefile.efi
+++ b/qemu/roms/ipxe/src/arch/x86/Makefile.efi
@@ -17,7 +17,7 @@ NON_AUTO_MEDIA += efirom
# Include SNP driver in the all-drivers build
#
-DRIVERS += snp
+DRIVERS_net += snp
# Rules for building EFI files
#
diff --git a/qemu/roms/ipxe/src/arch/x86/core/cpuid.c b/qemu/roms/ipxe/src/arch/x86/core/cpuid.c
index 5908f4419..bc5a6c68c 100644
--- a/qemu/roms/ipxe/src/arch/x86/core/cpuid.c
+++ b/qemu/roms/ipxe/src/arch/x86/core/cpuid.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
#include <ipxe/cpuid.h>
diff --git a/qemu/roms/ipxe/src/arch/x86/core/cpuid_settings.c b/qemu/roms/ipxe/src/arch/x86/core/cpuid_settings.c
index 42dea9336..08bd3918a 100644
--- a/qemu/roms/ipxe/src/arch/x86/core/cpuid_settings.c
+++ b/qemu/roms/ipxe/src/arch/x86/core/cpuid_settings.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
#include <errno.h>
diff --git a/qemu/roms/ipxe/src/arch/x86/core/debugcon.c b/qemu/roms/ipxe/src/arch/x86/core/debugcon.c
index 263cb4af1..60de61f55 100644
--- a/qemu/roms/ipxe/src/arch/x86/core/debugcon.c
+++ b/qemu/roms/ipxe/src/arch/x86/core/debugcon.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
diff --git a/qemu/roms/ipxe/src/arch/x86/core/pcidirect.c b/qemu/roms/ipxe/src/arch/x86/core/pcidirect.c
index dbc8317b8..9b8e6b1d9 100644
--- a/qemu/roms/ipxe/src/arch/x86/core/pcidirect.c
+++ b/qemu/roms/ipxe/src/arch/x86/core/pcidirect.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/io.h>
#include <ipxe/pci.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/core/pic8259.c b/qemu/roms/ipxe/src/arch/x86/core/pic8259.c
index 0a9ea2e03..0a9ea2e03 100644
--- a/qemu/roms/ipxe/src/arch/i386/core/pic8259.c
+++ b/qemu/roms/ipxe/src/arch/x86/core/pic8259.c
diff --git a/qemu/roms/ipxe/src/arch/x86/core/pit8254.c b/qemu/roms/ipxe/src/arch/x86/core/pit8254.c
new file mode 100644
index 000000000..da2099263
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/x86/core/pit8254.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <assert.h>
+#include <ipxe/io.h>
+#include <ipxe/pit8254.h>
+
+/** @file
+ *
+ * 8254 Programmable Interval Timer
+ *
+ */
+
+/**
+ * Delay for a fixed number of timer ticks using the speaker channel
+ *
+ * @v ticks Number of timer ticks for which to delay
+ */
+void pit8254_speaker_delay ( unsigned int ticks ) {
+ uint8_t spkr;
+ uint8_t cmd;
+ uint8_t low;
+ uint8_t high;
+
+ /* Sanity check */
+ assert ( ticks <= 0xffff );
+
+ /* Disable speaker, set speaker channel gate input high */
+ spkr = inb ( PIT8254_SPKR );
+ spkr &= ~PIT8254_SPKR_ENABLE;
+ spkr |= PIT8254_SPKR_GATE;
+ outb ( spkr, PIT8254_SPKR );
+
+ /* Program speaker channel to "interrupt" on terminal count */
+ cmd = ( PIT8254_CMD_CHANNEL ( PIT8254_CH_SPKR ) |
+ PIT8254_CMD_ACCESS_LOHI | PIT8254_CMD_OP_TERMINAL |
+ PIT8254_CMD_BINARY );
+ low = ( ( ticks >> 0 ) & 0xff );
+ high = ( ( ticks >> 8 ) & 0xff );
+ outb ( cmd, PIT8254_CMD );
+ outb ( low, PIT8254_DATA ( PIT8254_CH_SPKR ) );
+ outb ( high, PIT8254_DATA ( PIT8254_CH_SPKR ) );
+
+ /* Wait for channel to "interrupt" */
+ do {
+ spkr = inb ( PIT8254_SPKR );
+ } while ( ! ( spkr & PIT8254_SPKR_OUT ) );
+}
diff --git a/qemu/roms/ipxe/src/arch/x86/core/vram_settings.c b/qemu/roms/ipxe/src/arch/x86/core/vram_settings.c
new file mode 100644
index 000000000..9c169b40c
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/x86/core/vram_settings.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <ipxe/uaccess.h>
+#include <ipxe/settings.h>
+
+/** @file
+ *
+ * Video RAM dump
+ *
+ */
+
+/** Video RAM base address */
+#define VRAM_BASE 0xb8000
+
+/** Video RAM length */
+#define VRAM_LEN \
+ ( 80 /* columns */ * 25 /* rows */ * 2 /* bytes per character */ )
+
+/**
+ * Fetch video RAM setting
+ *
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int vram_fetch ( void *data, size_t len ) {
+ userptr_t vram = phys_to_user ( VRAM_BASE );
+
+ /* Copy video RAM */
+ if ( len > VRAM_LEN )
+ len = VRAM_LEN;
+ copy_from_user ( data, vram, 0, len );
+
+ return VRAM_LEN;
+}
+
+/** Video RAM setting */
+const struct setting vram_setting __setting ( SETTING_MISC, vram ) = {
+ .name = "vram",
+ .description = "Video RAM",
+ .type = &setting_type_base64,
+ .scope = &builtin_scope,
+};
+
+/** Video RAM built-in setting */
+struct builtin_setting vram_builtin_setting __builtin_setting = {
+ .setting = &vram_setting,
+ .fetch = vram_fetch,
+};
diff --git a/qemu/roms/ipxe/src/arch/x86/core/x86_bigint.c b/qemu/roms/ipxe/src/arch/x86/core/x86_bigint.c
index 418ac2309..6413b2fa8 100644
--- a/qemu/roms/ipxe/src/arch/x86/core/x86_bigint.c
+++ b/qemu/roms/ipxe/src/arch/x86/core/x86_bigint.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <string.h>
diff --git a/qemu/roms/ipxe/src/arch/x86/core/x86_io.c b/qemu/roms/ipxe/src/arch/x86/core/x86_io.c
index 9b2d2d935..3081fa8b9 100644
--- a/qemu/roms/ipxe/src/arch/x86/core/x86_io.c
+++ b/qemu/roms/ipxe/src/arch/x86/core/x86_io.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/io.h>
#include <ipxe/x86_io.h>
diff --git a/qemu/roms/ipxe/src/arch/x86/core/x86_string.c b/qemu/roms/ipxe/src/arch/x86/core/x86_string.c
index d48347c96..7d5e4a5f1 100644
--- a/qemu/roms/ipxe/src/arch/x86/core/x86_string.c
+++ b/qemu/roms/ipxe/src/arch/x86/core/x86_string.c
@@ -15,6 +15,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
/** @file
@@ -23,7 +27,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
@@ -104,87 +108,3 @@ void * __memmove ( void *dest, const void *src, size_t len ) {
return __memcpy_reverse ( dest, src, len );
}
}
-
-/**
- * Swap memory areas
- *
- * @v dest Destination address
- * @v src Source address
- * @v len Length
- * @ret dest Destination address
- */
-void * memswap ( void *dest, void *src, size_t len ) {
- size_t discard_c;
- int discard;
-
- __asm__ __volatile__ ( "\n1:\n\t"
- "dec %2\n\t"
- "js 2f\n\t"
- "movb (%0,%2), %b3\n\t"
- "xchgb (%1,%2), %b3\n\t"
- "movb %b3, (%0,%2)\n\t"
- "jmp 1b\n\t"
- "2:\n\t"
- : "=r" ( src ), "=r" ( dest ),
- "=&c" ( discard_c ), "=&q" ( discard )
- : "0" ( src ), "1" ( dest ), "2" ( len )
- : "memory" );
-
- return dest;
-}
-
-/**
- * Calculate length of string
- *
- * @v string String
- * @ret len Length (excluding NUL)
- */
-size_t strlen ( const char *string ) {
- const char *discard_D;
- size_t len_plus_one;
-
- __asm__ __volatile__ ( "repne scasb\n\t"
- "not %1\n\t"
- : "=&D" ( discard_D ), "=&c" ( len_plus_one )
- : "0" ( string ), "1" ( -1UL ), "a" ( 0 ) );
-
- return ( len_plus_one - 1 );
-}
-
-/**
- * Compare strings (up to a specified length)
- *
- * @v str1 First string
- * @v str2 Second string
- * @v len Maximum length
- * @ret diff Difference
- */
-int strncmp ( const char *str1, const char *str2, size_t len ) {
- const void *discard_S;
- const void *discard_D;
- size_t discard_c;
- int diff;
-
- __asm__ __volatile__ ( "\n1:\n\t"
- "dec %2\n\t"
- "js 2f\n\t"
- "lodsb\n\t"
- "scasb\n\t"
- "jne 3f\n\t"
- "testb %b3, %b3\n\t"
- "jnz 1b\n\t"
- /* Equal */
- "\n2:\n\t"
- "xor %3, %3\n\t"
- "jmp 4f\n\t"
- /* Not equal; CF indicates difference */
- "\n3:\n\t"
- "sbb %3, %3\n\t"
- "orb $1, %b3\n\t"
- "\n4:\n\t"
- : "=&S" ( discard_S ), "=&D" ( discard_D ),
- "=&c" ( discard_c ), "=&a" ( diff )
- : "0" ( str1 ), "1" ( str2 ), "2" ( len ) );
-
- return diff;
-}
diff --git a/qemu/roms/ipxe/src/arch/x86/core/x86_tcpip.c b/qemu/roms/ipxe/src/arch/x86/core/x86_tcpip.c
index 8a4ce5152..88042f5f7 100644
--- a/qemu/roms/ipxe/src/arch/x86/core/x86_tcpip.c
+++ b/qemu/roms/ipxe/src/arch/x86/core/x86_tcpip.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
diff --git a/qemu/roms/ipxe/src/arch/x86/core/x86_uart.c b/qemu/roms/ipxe/src/arch/x86/core/x86_uart.c
new file mode 100644
index 000000000..e455775bf
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/x86/core/x86_uart.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/** @file
+ *
+ * 16550-compatible UART
+ *
+ */
+
+#include <errno.h>
+#include <ipxe/uart.h>
+
+/** UART port bases */
+static uint16_t uart_base[] = {
+ [COM1] = 0x3f8,
+ [COM2] = 0x2f8,
+ [COM3] = 0x3e8,
+ [COM4] = 0x2e8,
+};
+
+/**
+ * Select UART port
+ *
+ * @v uart UART
+ * @v port Port number, or 0 to disable
+ * @ret rc Return status code
+ */
+int uart_select ( struct uart *uart, unsigned int port ) {
+ int rc;
+
+ /* Set new UART base */
+ if ( port >= ( sizeof ( uart_base ) / sizeof ( uart_base[0] ) ) ) {
+ rc = -ENODEV;
+ goto err;
+ }
+ uart->base = ( ( void * ) ( intptr_t ) uart_base[port] );
+
+ /* Check that UART exists */
+ if ( ( rc = uart_exists ( uart ) ) != 0 )
+ goto err;
+
+ return 0;
+
+ err:
+ uart->base = NULL;
+ return rc;
+}
diff --git a/qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.c b/qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.c
new file mode 100644
index 000000000..f73829bd5
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.c
@@ -0,0 +1,597 @@
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/** @file
+ *
+ * Hyper-V driver
+ *
+ */
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <pic8259.h>
+#include <ipxe/malloc.h>
+#include <ipxe/device.h>
+#include <ipxe/cpuid.h>
+#include <ipxe/msr.h>
+#include <ipxe/hyperv.h>
+#include <ipxe/vmbus.h>
+#include "hyperv.h"
+
+/** Maximum time to wait for a message response
+ *
+ * This is a policy decision.
+ */
+#define HV_MESSAGE_MAX_WAIT_MS 1000
+
+/**
+ * Convert a Hyper-V status code to an iPXE status code
+ *
+ * @v status Hyper-V status code
+ * @ret rc iPXE status code (before negation)
+ */
+#define EHV( status ) EPLATFORM ( EINFO_EPLATFORM, (status) )
+
+/**
+ * Allocate zeroed pages
+ *
+ * @v hv Hyper-V hypervisor
+ * @v ... Page addresses to fill in, terminated by NULL
+ * @ret rc Return status code
+ */
+__attribute__ (( sentinel )) int
+hv_alloc_pages ( struct hv_hypervisor *hv, ... ) {
+ va_list args;
+ void **page;
+ int i;
+
+ /* Allocate and zero pages */
+ va_start ( args, hv );
+ for ( i = 0 ; ( ( page = va_arg ( args, void ** ) ) != NULL ); i++ ) {
+ *page = malloc_dma ( PAGE_SIZE, PAGE_SIZE );
+ if ( ! *page )
+ goto err_alloc;
+ memset ( *page, 0, PAGE_SIZE );
+ }
+ va_end ( args );
+
+ return 0;
+
+ err_alloc:
+ va_end ( args );
+ va_start ( args, hv );
+ for ( ; i >= 0 ; i-- ) {
+ page = va_arg ( args, void ** );
+ free_dma ( *page, PAGE_SIZE );
+ }
+ va_end ( args );
+ return -ENOMEM;
+}
+
+/**
+ * Free pages
+ *
+ * @v hv Hyper-V hypervisor
+ * @v ... Page addresses, terminated by NULL
+ */
+__attribute__ (( sentinel )) void
+hv_free_pages ( struct hv_hypervisor *hv, ... ) {
+ va_list args;
+ void *page;
+
+ va_start ( args, hv );
+ while ( ( page = va_arg ( args, void * ) ) != NULL )
+ free_dma ( page, PAGE_SIZE );
+ va_end ( args );
+}
+
+/**
+ * Allocate message buffer
+ *
+ * @v hv Hyper-V hypervisor
+ * @ret rc Return status code
+ */
+static int hv_alloc_message ( struct hv_hypervisor *hv ) {
+
+ /* Allocate buffer. Must be aligned to at least 8 bytes and
+ * must not cross a page boundary, so align on its own size.
+ */
+ hv->message = malloc_dma ( sizeof ( *hv->message ),
+ sizeof ( *hv->message ) );
+ if ( ! hv->message )
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * Free message buffer
+ *
+ * @v hv Hyper-V hypervisor
+ */
+static void hv_free_message ( struct hv_hypervisor *hv ) {
+
+ /* Free buffer */
+ free_dma ( hv->message, sizeof ( *hv->message ) );
+}
+
+/**
+ * Check whether or not we are running in Hyper-V
+ *
+ * @v hv Hyper-V hypervisor
+ * @ret rc Return status code
+ */
+static int hv_check_hv ( struct hv_hypervisor *hv ) {
+ struct x86_features features;
+ uint32_t interface_id;
+ uint32_t discard_ebx;
+ uint32_t discard_ecx;
+ uint32_t discard_edx;
+ uint32_t available;
+ uint32_t permissions;
+
+ /* Check for presence of a hypervisor (not necessarily Hyper-V) */
+ x86_features ( &features );
+ if ( ! ( features.intel.ecx & CPUID_FEATURES_INTEL_ECX_HYPERVISOR ) ) {
+ DBGC ( hv, "HV %p not running in a hypervisor\n", hv );
+ return -ENODEV;
+ }
+
+ /* Check that hypervisor is Hyper-V */
+ cpuid ( HV_CPUID_INTERFACE_ID, &interface_id, &discard_ebx,
+ &discard_ecx, &discard_edx );
+ if ( interface_id != HV_INTERFACE_ID ) {
+ DBGC ( hv, "HV %p not running in Hyper-V (interface ID "
+ "%#08x)\n", hv, interface_id );
+ return -ENODEV;
+ }
+
+ /* Check that required features and privileges are available */
+ cpuid ( HV_CPUID_FEATURES, &available, &permissions, &discard_ecx,
+ &discard_edx );
+ if ( ! ( available & HV_FEATURES_AVAIL_HYPERCALL_MSR ) ) {
+ DBGC ( hv, "HV %p has no hypercall MSRs (features %08x:%08x)\n",
+ hv, available, permissions );
+ return -ENODEV;
+ }
+ if ( ! ( available & HV_FEATURES_AVAIL_SYNIC_MSR ) ) {
+ DBGC ( hv, "HV %p has no SynIC MSRs (features %08x:%08x)\n",
+ hv, available, permissions );
+ return -ENODEV;
+ }
+ if ( ! ( permissions & HV_FEATURES_PERM_POST_MESSAGES ) ) {
+ DBGC ( hv, "HV %p cannot post messages (features %08x:%08x)\n",
+ hv, available, permissions );
+ return -EACCES;
+ }
+ if ( ! ( permissions & HV_FEATURES_PERM_SIGNAL_EVENTS ) ) {
+ DBGC ( hv, "HV %p cannot signal events (features %08x:%08x)",
+ hv, available, permissions );
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+/**
+ * Map hypercall page
+ *
+ * @v hv Hyper-V hypervisor
+ * @ret rc Return status code
+ */
+static int hv_map_hypercall ( struct hv_hypervisor *hv ) {
+ union {
+ struct {
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+ } __attribute__ (( packed ));
+ char text[ 13 /* "bbbbccccdddd" + NUL */ ];
+ } vendor_id;
+ uint32_t build;
+ uint32_t version;
+ uint32_t discard_eax;
+ uint32_t discard_ecx;
+ uint32_t discard_edx;
+ uint64_t guest_os_id;
+ uint64_t hypercall;
+
+ /* Report guest OS identity */
+ guest_os_id = rdmsr ( HV_X64_MSR_GUEST_OS_ID );
+ if ( guest_os_id != 0 ) {
+ DBGC ( hv, "HV %p guest OS ID MSR already set to %#08llx\n",
+ hv, guest_os_id );
+ return -EBUSY;
+ }
+ guest_os_id = HV_GUEST_OS_ID_IPXE;
+ DBGC2 ( hv, "HV %p guest OS ID MSR is %#08llx\n", hv, guest_os_id );
+ wrmsr ( HV_X64_MSR_GUEST_OS_ID, guest_os_id );
+
+ /* Get hypervisor system identity (for debugging) */
+ cpuid ( HV_CPUID_VENDOR_ID, &discard_eax, &vendor_id.ebx,
+ &vendor_id.ecx, &vendor_id.edx );
+ vendor_id.text[ sizeof ( vendor_id.text ) - 1 ] = '\0';
+ cpuid ( HV_CPUID_HYPERVISOR_ID, &build, &version, &discard_ecx,
+ &discard_edx );
+ DBGC ( hv, "HV %p detected \"%s\" version %d.%d build %d\n", hv,
+ vendor_id.text, ( version >> 16 ), ( version & 0xffff ), build );
+
+ /* Map hypercall page */
+ hypercall = rdmsr ( HV_X64_MSR_HYPERCALL );
+ hypercall &= ( PAGE_SIZE - 1 );
+ hypercall |= ( virt_to_phys ( hv->hypercall ) | HV_HYPERCALL_ENABLE );
+ DBGC2 ( hv, "HV %p hypercall MSR is %#08llx\n", hv, hypercall );
+ wrmsr ( HV_X64_MSR_HYPERCALL, hypercall );
+
+ return 0;
+}
+
+/**
+ * Unmap hypercall page
+ *
+ * @v hv Hyper-V hypervisor
+ */
+static void hv_unmap_hypercall ( struct hv_hypervisor *hv ) {
+ uint64_t hypercall;
+ uint64_t guest_os_id;
+
+ /* Unmap the hypercall page */
+ hypercall = rdmsr ( HV_X64_MSR_HYPERCALL );
+ hypercall &= ( ( PAGE_SIZE - 1 ) & ~HV_HYPERCALL_ENABLE );
+ DBGC2 ( hv, "HV %p hypercall MSR is %#08llx\n", hv, hypercall );
+ wrmsr ( HV_X64_MSR_HYPERCALL, hypercall );
+
+ /* Reset the guest OS identity */
+ guest_os_id = 0;
+ DBGC2 ( hv, "HV %p guest OS ID MSR is %#08llx\n", hv, guest_os_id );
+ wrmsr ( HV_X64_MSR_GUEST_OS_ID, guest_os_id );
+}
+
+/**
+ * Map synthetic interrupt controller
+ *
+ * @v hv Hyper-V hypervisor
+ * @ret rc Return status code
+ */
+static int hv_map_synic ( struct hv_hypervisor *hv ) {
+ uint64_t simp;
+ uint64_t siefp;
+ uint64_t scontrol;
+
+ /* Map SynIC message page */
+ simp = rdmsr ( HV_X64_MSR_SIMP );
+ simp &= ( PAGE_SIZE - 1 );
+ simp |= ( virt_to_phys ( hv->synic.message ) | HV_SIMP_ENABLE );
+ DBGC2 ( hv, "HV %p SIMP MSR is %#08llx\n", hv, simp );
+ wrmsr ( HV_X64_MSR_SIMP, simp );
+
+ /* Map SynIC event page */
+ siefp = rdmsr ( HV_X64_MSR_SIEFP );
+ siefp &= ( PAGE_SIZE - 1 );
+ siefp |= ( virt_to_phys ( hv->synic.event ) | HV_SIEFP_ENABLE );
+ DBGC2 ( hv, "HV %p SIEFP MSR is %#08llx\n", hv, siefp );
+ wrmsr ( HV_X64_MSR_SIEFP, siefp );
+
+ /* Enable SynIC */
+ scontrol = rdmsr ( HV_X64_MSR_SCONTROL );
+ scontrol |= HV_SCONTROL_ENABLE;
+ DBGC2 ( hv, "HV %p SCONTROL MSR is %#08llx\n", hv, scontrol );
+ wrmsr ( HV_X64_MSR_SCONTROL, scontrol );
+
+ return 0;
+}
+
+/**
+ * Unmap synthetic interrupt controller
+ *
+ * @v hv Hyper-V hypervisor
+ */
+static void hv_unmap_synic ( struct hv_hypervisor *hv ) {
+ uint64_t scontrol;
+ uint64_t siefp;
+ uint64_t simp;
+
+ /* Disable SynIC */
+ scontrol = rdmsr ( HV_X64_MSR_SCONTROL );
+ scontrol &= ~HV_SCONTROL_ENABLE;
+ DBGC2 ( hv, "HV %p SCONTROL MSR is %#08llx\n", hv, scontrol );
+ wrmsr ( HV_X64_MSR_SCONTROL, scontrol );
+
+ /* Unmap SynIC event page */
+ siefp = rdmsr ( HV_X64_MSR_SIEFP );
+ siefp &= ( ( PAGE_SIZE - 1 ) & ~HV_SIEFP_ENABLE );
+ DBGC2 ( hv, "HV %p SIEFP MSR is %#08llx\n", hv, siefp );
+ wrmsr ( HV_X64_MSR_SIEFP, siefp );
+
+ /* Unmap SynIC message page */
+ simp = rdmsr ( HV_X64_MSR_SIMP );
+ simp &= ( ( PAGE_SIZE - 1 ) & ~HV_SIMP_ENABLE );
+ DBGC2 ( hv, "HV %p SIMP MSR is %#08llx\n", hv, simp );
+ wrmsr ( HV_X64_MSR_SIMP, simp );
+}
+
+/**
+ * Enable synthetic interrupt
+ *
+ * @v hv Hyper-V hypervisor
+ * @v sintx Synthetic interrupt number
+ */
+void hv_enable_sint ( struct hv_hypervisor *hv, unsigned int sintx ) {
+ unsigned long msr = HV_X64_MSR_SINT ( sintx );
+ uint64_t sint;
+
+ /* Enable synthetic interrupt
+ *
+ * We have to enable the interrupt, otherwise messages will
+ * not be delivered (even though the documentation implies
+ * that polling for messages is possible). We enable AutoEOI
+ * and hook the interrupt to the obsolete IRQ13 (FPU
+ * exception) vector, which will be implemented as a no-op.
+ */
+ sint = rdmsr ( msr );
+ sint &= ~( HV_SINT_MASKED | HV_SINT_VECTOR_MASK );
+ sint |= ( HV_SINT_AUTO_EOI |
+ HV_SINT_VECTOR ( IRQ_INT ( 13 /* See comment above */ ) ) );
+ DBGC2 ( hv, "HV %p SINT%d MSR is %#08llx\n", hv, sintx, sint );
+ wrmsr ( msr, sint );
+}
+
+/**
+ * Disable synthetic interrupt
+ *
+ * @v hv Hyper-V hypervisor
+ * @v sintx Synthetic interrupt number
+ */
+void hv_disable_sint ( struct hv_hypervisor *hv, unsigned int sintx ) {
+ unsigned long msr = HV_X64_MSR_SINT ( sintx );
+ uint64_t sint;
+
+ /* Disable synthetic interrupt */
+ sint = rdmsr ( msr );
+ sint &= ~HV_SINT_AUTO_EOI;
+ sint |= HV_SINT_MASKED;
+ DBGC2 ( hv, "HV %p SINT%d MSR is %#08llx\n", hv, sintx, sint );
+ wrmsr ( msr, sint );
+}
+
+/**
+ * Post message
+ *
+ * @v hv Hyper-V hypervisor
+ * @v id Connection ID
+ * @v type Message type
+ * @v data Message
+ * @v len Length of message
+ * @ret rc Return status code
+ */
+int hv_post_message ( struct hv_hypervisor *hv, unsigned int id,
+ unsigned int type, const void *data, size_t len ) {
+ struct hv_post_message *msg = &hv->message->posted;
+ int status;
+ int rc;
+
+ /* Sanity check */
+ assert ( len <= sizeof ( msg->data ) );
+
+ /* Construct message */
+ memset ( msg, 0, sizeof ( *msg ) );
+ msg->id = cpu_to_le32 ( id );
+ msg->type = cpu_to_le32 ( type );
+ msg->len = cpu_to_le32 ( len );
+ memcpy ( msg->data, data, len );
+ DBGC2 ( hv, "HV %p connection %d posting message type %#08x:\n",
+ hv, id, type );
+ DBGC2_HDA ( hv, 0, msg->data, len );
+
+ /* Post message */
+ if ( ( status = hv_call ( hv, HV_POST_MESSAGE, msg, NULL ) ) != 0 ) {
+ rc = -EHV ( status );
+ DBGC ( hv, "HV %p could not post message to %#08x: %s\n",
+ hv, id, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Wait for received message
+ *
+ * @v hv Hyper-V hypervisor
+ * @v sintx Synthetic interrupt number
+ * @ret rc Return status code
+ */
+int hv_wait_for_message ( struct hv_hypervisor *hv, unsigned int sintx ) {
+ struct hv_message *msg = &hv->message->received;
+ struct hv_message *src = &hv->synic.message[sintx];
+ unsigned int retries;
+ size_t len;
+
+ /* Wait for message to arrive */
+ for ( retries = 0 ; retries < HV_MESSAGE_MAX_WAIT_MS ; retries++ ) {
+
+ /* Check for message */
+ if ( src->type ) {
+
+ /* Copy message */
+ memset ( msg, 0, sizeof ( *msg ) );
+ len = src->len;
+ assert ( len <= sizeof ( *msg ) );
+ memcpy ( msg, src,
+ ( offsetof ( typeof ( *msg ), data ) + len ) );
+ DBGC2 ( hv, "HV %p SINT%d received message type "
+ "%#08x:\n", hv, sintx,
+ le32_to_cpu ( msg->type ) );
+ DBGC2_HDA ( hv, 0, msg->data, len );
+
+ /* Consume message */
+ src->type = 0;
+
+ return 0;
+ }
+
+ /* Trigger message delivery */
+ wrmsr ( HV_X64_MSR_EOM, 0 );
+
+ /* Delay */
+ mdelay ( 1 );
+ }
+
+ DBGC ( hv, "HV %p SINT%d timed out waiting for message\n",
+ hv, sintx );
+ return -ETIMEDOUT;
+}
+
+/**
+ * Signal event
+ *
+ * @v hv Hyper-V hypervisor
+ * @v id Connection ID
+ * @v flag Flag number
+ * @ret rc Return status code
+ */
+int hv_signal_event ( struct hv_hypervisor *hv, unsigned int id,
+ unsigned int flag ) {
+ struct hv_signal_event *event = &hv->message->signalled;
+ int status;
+ int rc;
+
+ /* Construct event */
+ memset ( event, 0, sizeof ( *event ) );
+ event->id = cpu_to_le32 ( id );
+ event->flag = cpu_to_le16 ( flag );
+
+ /* Signal event */
+ if ( ( status = hv_call ( hv, HV_SIGNAL_EVENT, event, NULL ) ) != 0 ) {
+ rc = -EHV ( status );
+ DBGC ( hv, "HV %p could not signal event to %#08x: %s\n",
+ hv, id, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Probe root device
+ *
+ * @v rootdev Root device
+ * @ret rc Return status code
+ */
+static int hv_probe ( struct root_device *rootdev ) {
+ struct hv_hypervisor *hv;
+ int rc;
+
+ /* Allocate and initialise structure */
+ hv = zalloc ( sizeof ( *hv ) );
+ if ( ! hv ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+
+ /* Check we are running in Hyper-V */
+ if ( ( rc = hv_check_hv ( hv ) ) != 0 )
+ goto err_check_hv;
+
+ /* Allocate pages */
+ if ( ( rc = hv_alloc_pages ( hv, &hv->hypercall, &hv->synic.message,
+ &hv->synic.event, NULL ) ) != 0 )
+ goto err_alloc_pages;
+
+ /* Allocate message buffer */
+ if ( ( rc = hv_alloc_message ( hv ) ) != 0 )
+ goto err_alloc_message;
+
+ /* Map hypercall page */
+ if ( ( rc = hv_map_hypercall ( hv ) ) != 0 )
+ goto err_map_hypercall;
+
+ /* Map synthetic interrupt controller */
+ if ( ( rc = hv_map_synic ( hv ) ) != 0 )
+ goto err_map_synic;
+
+ /* Probe Hyper-V devices */
+ if ( ( rc = vmbus_probe ( hv, &rootdev->dev ) ) != 0 )
+ goto err_vmbus_probe;
+
+ rootdev_set_drvdata ( rootdev, hv );
+ return 0;
+
+ vmbus_remove ( hv, &rootdev->dev );
+ err_vmbus_probe:
+ hv_unmap_synic ( hv );
+ err_map_synic:
+ hv_unmap_hypercall ( hv );
+ err_map_hypercall:
+ hv_free_message ( hv );
+ err_alloc_message:
+ hv_free_pages ( hv, hv->hypercall, hv->synic.message, hv->synic.event,
+ NULL );
+ err_alloc_pages:
+ err_check_hv:
+ free ( hv );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Remove root device
+ *
+ * @v rootdev Root device
+ */
+static void hv_remove ( struct root_device *rootdev ) {
+ struct hv_hypervisor *hv = rootdev_get_drvdata ( rootdev );
+
+ vmbus_remove ( hv, &rootdev->dev );
+ hv_unmap_synic ( hv );
+ hv_unmap_hypercall ( hv );
+ hv_free_message ( hv );
+ hv_free_pages ( hv, hv->hypercall, hv->synic.message, hv->synic.event,
+ NULL );
+ free ( hv );
+}
+
+/** Hyper-V root device driver */
+static struct root_driver hv_root_driver = {
+ .probe = hv_probe,
+ .remove = hv_remove,
+};
+
+/** Hyper-V root device */
+struct root_device hv_root_device __root_device = {
+ .dev = { .name = "Hyper-V" },
+ .driver = &hv_root_driver,
+};
+
+/* Drag in objects via hv_root_device */
+REQUIRING_SYMBOL ( hv_root_device );
+
+/* Drag in netvsc driver */
+REQUIRE_OBJECT ( netvsc );
diff --git a/qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.h b/qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.h
new file mode 100644
index 000000000..0d09beb44
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/x86/drivers/hyperv/hyperv.h
@@ -0,0 +1,57 @@
+#ifndef _HYPERV_H
+#define _HYPERV_H
+
+/** @file
+ *
+ * Hyper-V driver
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/** Get vendor identification */
+#define HV_CPUID_VENDOR_ID 0x40000000UL
+
+/** Get interface identification */
+#define HV_CPUID_INTERFACE_ID 0x40000001UL
+
+/** Get hypervisor identification */
+#define HV_CPUID_HYPERVISOR_ID 0x40000002UL
+
+/** Get hypervisor features */
+#define HV_CPUID_FEATURES 0x40000003UL
+
+/** SynIC MSRs are available */
+#define HV_FEATURES_AVAIL_SYNIC_MSR 0x00000004UL
+
+/** Hypercall MSRs are available */
+#define HV_FEATURES_AVAIL_HYPERCALL_MSR 0x00000020UL
+
+/** Guest may post messages */
+#define HV_FEATURES_PERM_POST_MESSAGES 0x00000010UL
+
+/** Guest may signal events */
+#define HV_FEATURES_PERM_SIGNAL_EVENTS 0x00000020UL
+
+/** Guest OS identity MSR */
+#define HV_X64_MSR_GUEST_OS_ID 0x40000000UL
+
+/** Hypercall page MSR */
+#define HV_X64_MSR_HYPERCALL 0x40000001UL
+
+/** SynIC control MSR */
+#define HV_X64_MSR_SCONTROL 0x40000080UL
+
+/** SynIC event flags page MSR */
+#define HV_X64_MSR_SIEFP 0x40000082UL
+
+/** SynIC message page MSR */
+#define HV_X64_MSR_SIMP 0x40000083UL
+
+/** SynIC end of message MSR */
+#define HV_X64_MSR_EOM 0x40000084UL
+
+/** SynIC interrupt source MSRs */
+#define HV_X64_MSR_SINT(x) ( 0x40000090UL + (x) )
+
+#endif /* _HYPERV_H */
diff --git a/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.c b/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.c
index 7406ca68d..7ac32d54c 100644
--- a/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.c
+++ b/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stdio.h>
@@ -492,5 +496,8 @@ struct pci_driver hvm_driver __pci_driver = {
.remove = hvm_remove,
};
+/* Drag in objects via hvm_driver */
+REQUIRING_SYMBOL ( hvm_driver );
+
/* Drag in netfront driver */
REQUIRE_OBJECT ( netfront );
diff --git a/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.h b/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.h
index 325d20d66..72ed94f6d 100644
--- a/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.h
+++ b/qemu/roms/ipxe/src/arch/x86/drivers/xen/hvm.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/xen.h>
diff --git a/qemu/roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c b/qemu/roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c
index c4e35d179..d73ce2a3e 100644
--- a/qemu/roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c
+++ b/qemu/roms/ipxe/src/arch/x86/hci/commands/cpuid_cmd.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <stdio.h>
diff --git a/qemu/roms/ipxe/src/arch/x86/include/bits/bigint.h b/qemu/roms/ipxe/src/arch/x86/include/bits/bigint.h
index d3449af5a..c9bb6ea45 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/bits/bigint.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/bits/bigint.h
@@ -6,7 +6,7 @@
* Big integer support
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <string.h>
diff --git a/qemu/roms/ipxe/src/arch/x86/include/bits/endian.h b/qemu/roms/ipxe/src/arch/x86/include/bits/endian.h
new file mode 100644
index 000000000..85718cfdd
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/x86/include/bits/endian.h
@@ -0,0 +1,8 @@
+#ifndef _BITS_ENDIAN_H
+#define _BITS_ENDIAN_H
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#define __BYTE_ORDER __LITTLE_ENDIAN
+
+#endif /* _BITS_ENDIAN_H */
diff --git a/qemu/roms/ipxe/src/arch/x86/include/bits/errfile.h b/qemu/roms/ipxe/src/arch/x86/include/bits/errfile.h
index 624575621..0d1617d20 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/bits/errfile.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/bits/errfile.h
@@ -1,7 +1,7 @@
#ifndef _BITS_ERRFILE_H
#define _BITS_ERRFILE_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* @addtogroup errfile Error file identifiers
@@ -21,6 +21,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_guestinfo ( ERRFILE_ARCH | ERRFILE_CORE | 0x000a0000 )
#define ERRFILE_apm ( ERRFILE_ARCH | ERRFILE_CORE | 0x000b0000 )
#define ERRFILE_vesafb ( ERRFILE_ARCH | ERRFILE_CORE | 0x000c0000 )
+#define ERRFILE_int13con ( ERRFILE_ARCH | ERRFILE_CORE | 0x000d0000 )
#define ERRFILE_bootsector ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
#define ERRFILE_bzimage ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )
@@ -46,9 +47,12 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_timer_rdtsc ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00000000 )
#define ERRFILE_timer_bios ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 )
#define ERRFILE_hvm ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00020000 )
+#define ERRFILE_hyperv ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00030000 )
+#define ERRFILE_x86_uart ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00040000 )
#define ERRFILE_cpuid_cmd ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00000000 )
#define ERRFILE_cpuid_settings ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00010000 )
+#define ERRFILE_efi_entropy ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00020000 )
/** @} */
diff --git a/qemu/roms/ipxe/src/arch/x86/include/bits/io.h b/qemu/roms/ipxe/src/arch/x86/include/bits/io.h
index cb1b67a6f..60c2e3edf 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/bits/io.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/bits/io.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/x86_io.h>
diff --git a/qemu/roms/ipxe/src/arch/x86/include/bits/pci_io.h b/qemu/roms/ipxe/src/arch/x86/include/bits/pci_io.h
index 01b12326e..b41e562ee 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/bits/pci_io.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/bits/pci_io.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/pcibios.h>
#include <ipxe/pcidirect.h>
diff --git a/qemu/roms/ipxe/src/arch/x86/include/bits/string.h b/qemu/roms/ipxe/src/arch/x86/include/bits/string.h
index dce994983..c26fe30d5 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/bits/string.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/bits/string.h
@@ -18,9 +18,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
@@ -28,8 +32,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
*
*/
-#define __HAVE_ARCH_MEMCPY
-
extern void * __memcpy ( void *dest, const void *src, size_t len );
extern void * __memcpy_reverse ( void *dest, const void *src, size_t len );
@@ -169,8 +171,6 @@ memcpy ( void *dest, const void *src, size_t len ) {
}
}
-#define __HAVE_ARCH_MEMMOVE
-
extern void * __memmove ( void *dest, const void *src, size_t len );
/**
@@ -196,8 +196,6 @@ memmove ( void *dest, const void *src, size_t len ) {
}
}
-#define __HAVE_ARCH_MEMSET
-
/**
* Fill memory region
*
@@ -206,7 +204,8 @@ memmove ( void *dest, const void *src, size_t len ) {
* @v len Length
* @ret dest Destination address
*/
-static inline void * memset ( void *dest, int fill, size_t len ) {
+static inline __attribute__ (( always_inline )) void *
+__memset ( void *dest, int fill, size_t len ) {
void *discard_D;
size_t discard_c;
@@ -217,16 +216,129 @@ static inline void * memset ( void *dest, int fill, size_t len ) {
return dest;
}
-#define __HAVE_ARCH_MEMSWAP
+/**
+ * Fill memory region with zero (where length is a compile-time constant)
+ *
+ * @v dest Destination address
+ * @v len Length
+ * @ret dest Destination address
+ */
+static inline __attribute__ (( always_inline )) void *
+__constant_memset_zero ( void *dest, size_t len ) {
+ union {
+ uint32_t u32[2];
+ uint16_t u16[4];
+ uint8_t u8[8];
+ } __attribute__ (( __may_alias__ )) *dest_u = dest;
+ void *edi;
+ uint32_t eax;
+
+ switch ( len ) {
+ case 0 : /* 0 bytes */
+ return dest;
+
+ /* Single-register moves. Almost certainly better than a
+ * string operation. We can avoid clobbering any registers,
+ * we can reuse a zero that happens to already be in a
+ * register, and we can optimise away the code entirely if the
+ * memset() is used to clear a region which then gets
+ * immediately overwritten.
+ */
+ case 1 : /* 3 bytes */
+ dest_u->u8[0] = 0;
+ return dest;
+ case 2: /* 5 bytes */
+ dest_u->u16[0] = 0;
+ return dest;
+ case 4: /* 6 bytes */
+ dest_u->u32[0] = 0;
+ return dest;
+
+ /* Double-register moves. Very probably better than a string
+ * operation.
+ */
+ case 3 : /* 9 bytes */
+ dest_u->u16[0] = 0;
+ dest_u->u8[2] = 0;
+ return dest;
+ case 5 : /* 10 bytes */
+ dest_u->u32[0] = 0;
+ dest_u->u8[4] = 0;
+ return dest;
+ case 6 : /* 12 bytes */
+ dest_u->u32[0] = 0;
+ dest_u->u16[2] = 0;
+ return dest;
+ case 8 : /* 13 bytes */
+ dest_u->u32[0] = 0;
+ dest_u->u32[1] = 0;
+ return dest;
+ }
+
+ /* As with memcpy(), we can potentially save space by using
+ * multiple single-byte "stos" instructions instead of loading
+ * up ecx and using "rep stosb".
+ *
+ * "load ecx, rep movsb" is 7 bytes, plus an average of 1 byte
+ * to allow for saving/restoring ecx 50% of the time.
+ *
+ * "stosl" and "stosb" are 1 byte each, "stosw" is two bytes.
+ *
+ * The calculations are therefore the same as for memcpy(),
+ * giving a cutoff point of around 26 bytes.
+ */
-extern void * memswap ( void *dest, void *src, size_t len );
+ edi = dest;
+ eax = 0;
+
+ if ( len >= 26 )
+ return __memset ( dest, 0, len );
-#define __HAVE_ARCH_STRNCMP
+ if ( len >= 6*4 )
+ __asm__ __volatile__ ( "stosl" : "=&D" ( edi ), "=&a" ( eax )
+ : "0" ( edi ), "1" ( eax ) : "memory" );
+ if ( len >= 5*4 )
+ __asm__ __volatile__ ( "stosl" : "=&D" ( edi ), "=&a" ( eax )
+ : "0" ( edi ), "1" ( eax ) : "memory" );
+ if ( len >= 4*4 )
+ __asm__ __volatile__ ( "stosl" : "=&D" ( edi ), "=&a" ( eax )
+ : "0" ( edi ), "1" ( eax ) : "memory" );
+ if ( len >= 3*4 )
+ __asm__ __volatile__ ( "stosl" : "=&D" ( edi ), "=&a" ( eax )
+ : "0" ( edi ), "1" ( eax ) : "memory" );
+ if ( len >= 2*4 )
+ __asm__ __volatile__ ( "stosl" : "=&D" ( edi ), "=&a" ( eax )
+ : "0" ( edi ), "1" ( eax ) : "memory" );
+ if ( len >= 1*4 )
+ __asm__ __volatile__ ( "stosl" : "=&D" ( edi ), "=&a" ( eax )
+ : "0" ( edi ), "1" ( eax ) : "memory" );
+ if ( ( len % 4 ) >= 2 )
+ __asm__ __volatile__ ( "stosw" : "=&D" ( edi ), "=&a" ( eax )
+ : "0" ( edi ), "1" ( eax ) : "memory" );
+ if ( ( len % 2 ) >= 1 )
+ __asm__ __volatile__ ( "stosb" : "=&D" ( edi ), "=&a" ( eax )
+ : "0" ( edi ), "1" ( eax ) : "memory" );
-extern int strncmp ( const char *str1, const char *str2, size_t len );
+ return dest;
+}
-#define __HAVE_ARCH_STRLEN
+/**
+ * Fill memory region
+ *
+ * @v dest Destination address
+ * @v fill Fill pattern
+ * @v len Length
+ * @ret dest Destination address
+ */
+static inline __attribute__ (( always_inline )) void *
+memset ( void *dest, int fill, size_t len ) {
-extern size_t strlen ( const char *string );
+ if ( __builtin_constant_p ( fill ) && ( fill == 0 ) &&
+ __builtin_constant_p ( len ) ) {
+ return __constant_memset_zero ( dest, len );
+ } else {
+ return __memset ( dest, fill, len );
+ }
+}
#endif /* X86_BITS_STRING_H */
diff --git a/qemu/roms/ipxe/src/arch/x86/include/bits/tcpip.h b/qemu/roms/ipxe/src/arch/x86/include/bits/tcpip.h
index a4b335eb1..5c2baffcf 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/bits/tcpip.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/bits/tcpip.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
extern uint16_t x86_tcpip_continue_chksum ( uint16_t partial,
const void *data, size_t len );
diff --git a/qemu/roms/ipxe/src/arch/x86/include/bits/uart.h b/qemu/roms/ipxe/src/arch/x86/include/bits/uart.h
new file mode 100644
index 000000000..e09cd3f4c
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/x86/include/bits/uart.h
@@ -0,0 +1,41 @@
+#ifndef _BITS_UART_H
+#define _BITS_UART_H
+
+/** @file
+ *
+ * 16550-compatible UART
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stdint.h>
+#include <ipxe/io.h>
+
+/**
+ * Write to UART register
+ *
+ * @v uart UART
+ * @v addr Register address
+ * @v data Data
+ */
+static inline __attribute__ (( always_inline )) void
+uart_write ( struct uart *uart, unsigned int addr, uint8_t data ) {
+ outb ( data, ( uart->base + addr ) );
+}
+
+/**
+ * Read from UART register
+ *
+ * @v uart UART
+ * @v addr Register address
+ * @ret data Data
+ */
+static inline __attribute__ (( always_inline )) uint8_t
+uart_read ( struct uart *uart, unsigned int addr ) {
+ return inb ( uart->base + addr );
+}
+
+extern int uart_select ( struct uart *uart, unsigned int port );
+
+#endif /* _BITS_UART_H */
diff --git a/qemu/roms/ipxe/src/arch/x86/include/bits/xen.h b/qemu/roms/ipxe/src/arch/x86/include/bits/xen.h
index dbccf1b77..fc065ea38 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/bits/xen.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/bits/xen.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/* Hypercall registers */
#ifdef __x86_64__
@@ -161,4 +161,23 @@ xen_hypercall_5 ( struct xen_hypervisor *xen, unsigned int hypercall,
return retval;
}
+/**
+ * Test and clear pending event
+ *
+ * @v xen Xen hypervisor
+ * @v port Event channel port
+ * @ret pending Event was pending
+ */
+static inline __attribute__ (( always_inline )) uint8_t
+xenevent_pending ( struct xen_hypervisor *xen, evtchn_port_t port ) {
+ uint8_t pending;
+
+ __asm__ __volatile__ ( "lock btr %2, %0\n\t"
+ "setc %1\n\t"
+ : "+m" ( xen->shared->evtchn_pending ),
+ "=a" ( pending )
+ : "Ir" ( port ) );
+ return pending;
+}
+
#endif /* _BITS_XEN_H */
diff --git a/qemu/roms/ipxe/src/arch/x86/include/ipxe/cpuid.h b/qemu/roms/ipxe/src/arch/x86/include/ipxe/cpuid.h
index 2f78dfca1..da85d0b88 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/ipxe/cpuid.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/ipxe/cpuid.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
@@ -39,6 +39,9 @@ struct x86_features {
/** Get standard features */
#define CPUID_FEATURES 0x00000001UL
+/** Hypervisor is present */
+#define CPUID_FEATURES_INTEL_ECX_HYPERVISOR 0x80000000UL
+
/** Get largest extended function */
#define CPUID_AMD_MAX_FN 0x80000000UL
diff --git a/qemu/roms/ipxe/src/arch/x86/include/ipxe/efi/efix86_nap.h b/qemu/roms/ipxe/src/arch/x86/include/ipxe/efi/efix86_nap.h
index e85a272b3..1a391c9b6 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/ipxe/efi/efix86_nap.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/ipxe/efi/efix86_nap.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef NAP_EFIX86
#define NAP_PREFIX_efix86
diff --git a/qemu/roms/ipxe/src/arch/x86/include/ipxe/pcibios.h b/qemu/roms/ipxe/src/arch/x86/include/ipxe/pcibios.h
index 36af7fcde..7e1bcd814 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/ipxe/pcibios.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/ipxe/pcibios.h
@@ -9,7 +9,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef PCIAPI_PCBIOS
#define PCIAPI_PREFIX_pcbios
diff --git a/qemu/roms/ipxe/src/arch/x86/include/ipxe/pcidirect.h b/qemu/roms/ipxe/src/arch/x86/include/ipxe/pcidirect.h
index 7fa7c4fa7..d924f2f20 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/ipxe/pcidirect.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/ipxe/pcidirect.h
@@ -1,7 +1,7 @@
#ifndef _PCIDIRECT_H
#define _PCIDIRECT_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
#include <ipxe/io.h>
diff --git a/qemu/roms/ipxe/src/arch/x86/include/ipxe/pit8254.h b/qemu/roms/ipxe/src/arch/x86/include/ipxe/pit8254.h
new file mode 100644
index 000000000..00b0ab164
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/x86/include/ipxe/pit8254.h
@@ -0,0 +1,81 @@
+#ifndef _IPXE_PIT8254_H
+#define _IPXE_PIT8254_H
+
+/** @file
+ *
+ * 8254 Programmable Interval Timer
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/** IRQ0 channel */
+#define PIT8254_CH_IRQ0 0
+
+/** PC speaker channel */
+#define PIT8254_CH_SPKR 2
+
+/** Timer frequency (1.193182MHz) */
+#define PIT8254_HZ 1193182UL
+
+/** Data port */
+#define PIT8254_DATA(channel) ( 0x40 + (channel) )
+
+/** Mode/command register */
+#define PIT8254_CMD 0x43
+
+/** Select channel */
+#define PIT8254_CMD_CHANNEL(channel) ( (channel) << 6 )
+
+/** Access modes */
+#define PIT8254_CMD_ACCESS_LATCH 0x00 /**< Latch count value command */
+#define PIT8254_CMD_ACCESS_LO 0x10 /**< Low byte only */
+#define PIT8254_CMD_ACCESS_HI 0x20 /**< High byte only */
+#define PIT8254_CMD_ACCESS_LOHI 0x30 /**< Low-byte, high-byte pair */
+
+/* Operating modes */
+#define PIT8254_CMD_OP_TERMINAL 0x00 /**< Interrupt on terminal count */
+#define PIT8254_CMD_OP_ONESHOT 0x02 /**< Hardware re-triggerable one-shot */
+#define PIT8254_CMD_OP_RATE 0x04 /**< Rate generator */
+#define PIT8254_CMD_OP_SQUARE 0x06 /**< Square wave generator */
+#define PIT8254_CMD_OP_SWSTROBE 0x08 /**< Software triggered strobe */
+#define PIT8254_CMD_OP_HWSTROBE 0x0a /**< Hardware triggered strobe */
+#define PIT8254_CMD_OP_RATE2 0x0c /**< Rate generator (duplicate) */
+#define PIT8254_CMD_OP_SQUARE2 0x0e /**< Square wave generator (duplicate)*/
+
+/** Binary mode */
+#define PIT8254_CMD_BINARY 0x00
+
+/** BCD mode */
+#define PIT8254_CMD_BCD 0x01
+
+/** PC speaker control register */
+#define PIT8254_SPKR 0x61
+
+/** PC speaker channel gate */
+#define PIT8254_SPKR_GATE 0x01
+
+/** PC speaker enabled */
+#define PIT8254_SPKR_ENABLE 0x02
+
+/** PC speaker channel output */
+#define PIT8254_SPKR_OUT 0x20
+
+extern void pit8254_speaker_delay ( unsigned int ticks );
+
+/**
+ * Delay for a fixed number of microseconds
+ *
+ * @v usecs Number of microseconds for which to delay
+ */
+static inline __attribute__ (( always_inline )) void
+pit8254_udelay ( unsigned long usecs ) {
+
+ /* Delays are invariably compile-time constants; force the
+ * multiplication and division to take place at compilation
+ * time rather than runtime.
+ */
+ pit8254_speaker_delay ( ( usecs * PIT8254_HZ ) / 1000000 );
+}
+
+#endif /* _IPXE_PIT8254_H */
diff --git a/qemu/roms/ipxe/src/arch/x86/include/ipxe/x86_io.h b/qemu/roms/ipxe/src/arch/x86/include/ipxe/x86_io.h
index 9e68f4e78..5214e9fbb 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/ipxe/x86_io.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/ipxe/x86_io.h
@@ -15,7 +15,7 @@
* physically fit into a machine with such an old CPU anyway.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifdef IOAPI_X86
#define IOAPI_PREFIX_x86
diff --git a/qemu/roms/ipxe/src/arch/x86/include/linux/ipxe/dhcp_arch.h b/qemu/roms/ipxe/src/arch/x86/include/linux/ipxe/dhcp_arch.h
index e83fd9d87..d60905f22 100644
--- a/qemu/roms/ipxe/src/arch/x86/include/linux/ipxe/dhcp_arch.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/linux/ipxe/dhcp_arch.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
+ * License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -13,7 +13,12 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
#ifndef _LINUX_DHCP_ARCH_H
@@ -24,7 +29,7 @@
* Architecture-specific DHCP options
*/
-FILE_LICENCE(GPL2_OR_LATER);
+FILE_LICENCE(GPL2_OR_LATER_OR_UBDL);
#include <ipxe/dhcp.h>
diff --git a/qemu/roms/ipxe/src/arch/i386/include/pic8259.h b/qemu/roms/ipxe/src/arch/x86/include/pic8259.h
index a07e97d30..f02e62909 100644
--- a/qemu/roms/ipxe/src/arch/i386/include/pic8259.h
+++ b/qemu/roms/ipxe/src/arch/x86/include/pic8259.h
@@ -4,16 +4,13 @@
* Initially written by Michael Brown (mcb30).
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#ifndef PIC8259_H
#define PIC8259_H
#include <ipxe/io.h>
-/* For segoff_t */
-#include "realmode.h"
-
#define IRQ_PIC_CUTOFF 8
/* 8259 register locations */
diff --git a/qemu/roms/ipxe/src/arch/x86/include/valgrind/memcheck.h b/qemu/roms/ipxe/src/arch/x86/include/valgrind/memcheck.h
deleted file mode 100644
index 7d4b56d31..000000000
--- a/qemu/roms/ipxe/src/arch/x86/include/valgrind/memcheck.h
+++ /dev/null
@@ -1,311 +0,0 @@
-
-/*
- ----------------------------------------------------------------
-
- Notice that the following BSD-style license applies to this one
- file (memcheck.h) only. The rest of Valgrind is licensed under the
- terms of the GNU General Public License, version 2, unless
- otherwise indicated. See the COPYING file in the source
- distribution for details.
-
- ----------------------------------------------------------------
-
- This file is part of MemCheck, a heavyweight Valgrind tool for
- detecting memory errors.
-
- Copyright (C) 2000-2010 Julian Seward. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. The origin of this software must not be misrepresented; you must
- not claim that you wrote the original software. If you use this
- software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
-
- 3. Altered source versions must be plainly marked as such, and must
- not be misrepresented as being the original software.
-
- 4. The name of the author may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- ----------------------------------------------------------------
-
- Notice that the above BSD-style license applies to this one file
- (memcheck.h) only. The entire rest of Valgrind is licensed under
- the terms of the GNU General Public License, version 2. See the
- COPYING file in the source distribution for details.
-
- ----------------------------------------------------------------
-*/
-
-
-#ifndef __MEMCHECK_H
-#define __MEMCHECK_H
-
-FILE_LICENCE ( BSD3 );
-
-
-/* This file is for inclusion into client (your!) code.
-
- You can use these macros to manipulate and query memory permissions
- inside your own programs.
-
- See comment near the top of valgrind.h on how to use them.
-*/
-
-#include "valgrind.h"
-
-/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
- This enum comprises an ABI exported by Valgrind to programs
- which use client requests. DO NOT CHANGE THE ORDER OF THESE
- ENTRIES, NOR DELETE ANY -- add new ones at the end. */
-typedef
- enum {
- VG_USERREQ__MAKE_MEM_NOACCESS = VG_USERREQ_TOOL_BASE('M','C'),
- VG_USERREQ__MAKE_MEM_UNDEFINED,
- VG_USERREQ__MAKE_MEM_DEFINED,
- VG_USERREQ__DISCARD,
- VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,
- VG_USERREQ__CHECK_MEM_IS_DEFINED,
- VG_USERREQ__DO_LEAK_CHECK,
- VG_USERREQ__COUNT_LEAKS,
-
- VG_USERREQ__GET_VBITS,
- VG_USERREQ__SET_VBITS,
-
- VG_USERREQ__CREATE_BLOCK,
-
- VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE,
-
- /* Not next to VG_USERREQ__COUNT_LEAKS because it was added later. */
- VG_USERREQ__COUNT_LEAK_BLOCKS,
-
- /* This is just for memcheck's internal use - don't use it */
- _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR
- = VG_USERREQ_TOOL_BASE('M','C') + 256
- } Vg_MemCheckClientRequest;
-
-
-
-/* Client-code macros to manipulate the state of memory. */
-
-/* Mark memory at _qzz_addr as unaddressable for _qzz_len bytes. */
-#define VALGRIND_MAKE_MEM_NOACCESS(_qzz_addr,_qzz_len) \
- (__extension__({unsigned long _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \
- VG_USERREQ__MAKE_MEM_NOACCESS, \
- _qzz_addr, _qzz_len, 0, 0, 0); \
- _qzz_res; \
- }))
-
-/* Similarly, mark memory at _qzz_addr as addressable but undefined
- for _qzz_len bytes. */
-#define VALGRIND_MAKE_MEM_UNDEFINED(_qzz_addr,_qzz_len) \
- (__extension__({unsigned long _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \
- VG_USERREQ__MAKE_MEM_UNDEFINED, \
- _qzz_addr, _qzz_len, 0, 0, 0); \
- _qzz_res; \
- }))
-
-/* Similarly, mark memory at _qzz_addr as addressable and defined
- for _qzz_len bytes. */
-#define VALGRIND_MAKE_MEM_DEFINED(_qzz_addr,_qzz_len) \
- (__extension__({unsigned long _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \
- VG_USERREQ__MAKE_MEM_DEFINED, \
- _qzz_addr, _qzz_len, 0, 0, 0); \
- _qzz_res; \
- }))
-
-/* Similar to VALGRIND_MAKE_MEM_DEFINED except that addressability is
- not altered: bytes which are addressable are marked as defined,
- but those which are not addressable are left unchanged. */
-#define VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(_qzz_addr,_qzz_len) \
- (__extension__({unsigned long _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \
- VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE, \
- _qzz_addr, _qzz_len, 0, 0, 0); \
- _qzz_res; \
- }))
-
-/* Create a block-description handle. The description is an ascii
- string which is included in any messages pertaining to addresses
- within the specified memory range. Has no other effect on the
- properties of the memory range. */
-#define VALGRIND_CREATE_BLOCK(_qzz_addr,_qzz_len, _qzz_desc) \
- (__extension__({unsigned long _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \
- VG_USERREQ__CREATE_BLOCK, \
- _qzz_addr, _qzz_len, _qzz_desc, \
- 0, 0); \
- _qzz_res; \
- }))
-
-/* Discard a block-description-handle. Returns 1 for an
- invalid handle, 0 for a valid handle. */
-#define VALGRIND_DISCARD(_qzz_blkindex) \
- (__extension__ ({unsigned long _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* default return */, \
- VG_USERREQ__DISCARD, \
- 0, _qzz_blkindex, 0, 0, 0); \
- _qzz_res; \
- }))
-
-
-/* Client-code macros to check the state of memory. */
-
-/* Check that memory at _qzz_addr is addressable for _qzz_len bytes.
- If suitable addressibility is not established, Valgrind prints an
- error message and returns the address of the first offending byte.
- Otherwise it returns zero. */
-#define VALGRIND_CHECK_MEM_IS_ADDRESSABLE(_qzz_addr,_qzz_len) \
- (__extension__({unsigned long _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE,\
- _qzz_addr, _qzz_len, 0, 0, 0); \
- _qzz_res; \
- }))
-
-/* Check that memory at _qzz_addr is addressable and defined for
- _qzz_len bytes. If suitable addressibility and definedness are not
- established, Valgrind prints an error message and returns the
- address of the first offending byte. Otherwise it returns zero. */
-#define VALGRIND_CHECK_MEM_IS_DEFINED(_qzz_addr,_qzz_len) \
- (__extension__({unsigned long _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__CHECK_MEM_IS_DEFINED, \
- _qzz_addr, _qzz_len, 0, 0, 0); \
- _qzz_res; \
- }))
-
-/* Use this macro to force the definedness and addressibility of an
- lvalue to be checked. If suitable addressibility and definedness
- are not established, Valgrind prints an error message and returns
- the address of the first offending byte. Otherwise it returns
- zero. */
-#define VALGRIND_CHECK_VALUE_IS_DEFINED(__lvalue) \
- VALGRIND_CHECK_MEM_IS_DEFINED( \
- (volatile unsigned char *)&(__lvalue), \
- (unsigned long)(sizeof (__lvalue)))
-
-
-/* Do a full memory leak check (like --leak-check=full) mid-execution. */
-#define VALGRIND_DO_LEAK_CHECK \
- {unsigned long _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__DO_LEAK_CHECK, \
- 0, 0, 0, 0, 0); \
- }
-
-/* Do a summary memory leak check (like --leak-check=summary) mid-execution. */
-#define VALGRIND_DO_QUICK_LEAK_CHECK \
- {unsigned long _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__DO_LEAK_CHECK, \
- 1, 0, 0, 0, 0); \
- }
-
-/* Return number of leaked, dubious, reachable and suppressed bytes found by
- all previous leak checks. They must be lvalues. */
-#define VALGRIND_COUNT_LEAKS(leaked, dubious, reachable, suppressed) \
- /* For safety on 64-bit platforms we assign the results to private
- unsigned long variables, then assign these to the lvalues the user
- specified, which works no matter what type 'leaked', 'dubious', etc
- are. We also initialise '_qzz_leaked', etc because
- VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as
- defined. */ \
- {unsigned long _qzz_res; \
- unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \
- unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__COUNT_LEAKS, \
- &_qzz_leaked, &_qzz_dubious, \
- &_qzz_reachable, &_qzz_suppressed, 0); \
- leaked = _qzz_leaked; \
- dubious = _qzz_dubious; \
- reachable = _qzz_reachable; \
- suppressed = _qzz_suppressed; \
- }
-
-/* Return number of leaked, dubious, reachable and suppressed bytes found by
- all previous leak checks. They must be lvalues. */
-#define VALGRIND_COUNT_LEAK_BLOCKS(leaked, dubious, reachable, suppressed) \
- /* For safety on 64-bit platforms we assign the results to private
- unsigned long variables, then assign these to the lvalues the user
- specified, which works no matter what type 'leaked', 'dubious', etc
- are. We also initialise '_qzz_leaked', etc because
- VG_USERREQ__COUNT_LEAKS doesn't mark the values returned as
- defined. */ \
- {unsigned long _qzz_res; \
- unsigned long _qzz_leaked = 0, _qzz_dubious = 0; \
- unsigned long _qzz_reachable = 0, _qzz_suppressed = 0; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__COUNT_LEAK_BLOCKS, \
- &_qzz_leaked, &_qzz_dubious, \
- &_qzz_reachable, &_qzz_suppressed, 0); \
- leaked = _qzz_leaked; \
- dubious = _qzz_dubious; \
- reachable = _qzz_reachable; \
- suppressed = _qzz_suppressed; \
- }
-
-
-/* Get the validity data for addresses [zza..zza+zznbytes-1] and copy it
- into the provided zzvbits array. Return values:
- 0 if not running on valgrind
- 1 success
- 2 [previously indicated unaligned arrays; these are now allowed]
- 3 if any parts of zzsrc/zzvbits are not addressable.
- The metadata is not copied in cases 0, 2 or 3 so it should be
- impossible to segfault your system by using this call.
-*/
-#define VALGRIND_GET_VBITS(zza,zzvbits,zznbytes) \
- (__extension__({unsigned long _qzz_res; \
- char* czza = (char*)zza; \
- char* czzvbits = (char*)zzvbits; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__GET_VBITS, \
- czza, czzvbits, zznbytes, 0, 0 ); \
- _qzz_res; \
- }))
-
-/* Set the validity data for addresses [zza..zza+zznbytes-1], copying it
- from the provided zzvbits array. Return values:
- 0 if not running on valgrind
- 1 success
- 2 [previously indicated unaligned arrays; these are now allowed]
- 3 if any parts of zza/zzvbits are not addressable.
- The metadata is not copied in cases 0, 2 or 3 so it should be
- impossible to segfault your system by using this call.
-*/
-#define VALGRIND_SET_VBITS(zza,zzvbits,zznbytes) \
- (__extension__({unsigned int _qzz_res; \
- char* czza = (char*)zza; \
- char* czzvbits = (char*)zzvbits; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__SET_VBITS, \
- czza, czzvbits, zznbytes, 0, 0 ); \
- _qzz_res; \
- }))
-
-#endif
-
diff --git a/qemu/roms/ipxe/src/arch/x86/include/valgrind/valgrind.h b/qemu/roms/ipxe/src/arch/x86/include/valgrind/valgrind.h
deleted file mode 100644
index d48bbccae..000000000
--- a/qemu/roms/ipxe/src/arch/x86/include/valgrind/valgrind.h
+++ /dev/null
@@ -1,4538 +0,0 @@
-/* -*- c -*-
- ----------------------------------------------------------------
-
- Notice that the following BSD-style license applies to this one
- file (valgrind.h) only. The rest of Valgrind is licensed under the
- terms of the GNU General Public License, version 2, unless
- otherwise indicated. See the COPYING file in the source
- distribution for details.
-
- ----------------------------------------------------------------
-
- This file is part of Valgrind, a dynamic binary instrumentation
- framework.
-
- Copyright (C) 2000-2010 Julian Seward. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- 2. The origin of this software must not be misrepresented; you must
- not claim that you wrote the original software. If you use this
- software in a product, an acknowledgment in the product
- documentation would be appreciated but is not required.
-
- 3. Altered source versions must be plainly marked as such, and must
- not be misrepresented as being the original software.
-
- 4. The name of the author may not be used to endorse or promote
- products derived from this software without specific prior written
- permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- ----------------------------------------------------------------
-
- Notice that the above BSD-style license applies to this one file
- (valgrind.h) only. The entire rest of Valgrind is licensed under
- the terms of the GNU General Public License, version 2. See the
- COPYING file in the source distribution for details.
-
- ----------------------------------------------------------------
-*/
-
-
-/* This file is for inclusion into client (your!) code.
-
- You can use these macros to manipulate and query Valgrind's
- execution inside your own programs.
-
- The resulting executables will still run without Valgrind, just a
- little bit more slowly than they otherwise would, but otherwise
- unchanged. When not running on valgrind, each client request
- consumes very few (eg. 7) instructions, so the resulting performance
- loss is negligible unless you plan to execute client requests
- millions of times per second. Nevertheless, if that is still a
- problem, you can compile with the NVALGRIND symbol defined (gcc
- -DNVALGRIND) so that client requests are not even compiled in. */
-
-#ifndef __VALGRIND_H
-#define __VALGRIND_H
-
-FILE_LICENCE ( BSD3 );
-
-
-/* ------------------------------------------------------------------ */
-/* VERSION NUMBER OF VALGRIND */
-/* ------------------------------------------------------------------ */
-
-/* Specify Valgrind's version number, so that user code can
- conditionally compile based on our version number. Note that these
- were introduced at version 3.6 and so do not exist in version 3.5
- or earlier. The recommended way to use them to check for "version
- X.Y or later" is (eg)
-
-#if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \
- && (__VALGRIND_MAJOR__ > 3 \
- || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6))
-*/
-#define __VALGRIND_MAJOR__ 3
-#define __VALGRIND_MINOR__ 6
-
-
-#include <stdarg.h>
-
-/* Nb: this file might be included in a file compiled with -ansi. So
- we can't use C++ style "//" comments nor the "asm" keyword (instead
- use "__asm__"). */
-
-/* Derive some tags indicating what the target platform is. Note
- that in this file we're using the compiler's CPP symbols for
- identifying architectures, which are different to the ones we use
- within the rest of Valgrind. Note, __powerpc__ is active for both
- 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
- latter (on Linux, that is).
-
- Misc note: how to find out what's predefined in gcc by default:
- gcc -Wp,-dM somefile.c
-*/
-#undef PLAT_ppc64_aix5
-#undef PLAT_ppc32_aix5
-#undef PLAT_x86_darwin
-#undef PLAT_amd64_darwin
-#undef PLAT_x86_linux
-#undef PLAT_amd64_linux
-#undef PLAT_ppc32_linux
-#undef PLAT_ppc64_linux
-#undef PLAT_arm_linux
-
-#if defined(_AIX) && defined(__64BIT__)
-# define PLAT_ppc64_aix5 1
-#elif defined(_AIX) && !defined(__64BIT__)
-# define PLAT_ppc32_aix5 1
-#elif defined(__APPLE__) && defined(__i386__)
-# define PLAT_x86_darwin 1
-#elif defined(__APPLE__) && defined(__x86_64__)
-# define PLAT_amd64_darwin 1
-#elif defined(__linux__) && defined(__i386__)
-# define PLAT_x86_linux 1
-#elif defined(__linux__) && defined(__x86_64__)
-# define PLAT_amd64_linux 1
-#elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__)
-# define PLAT_ppc32_linux 1
-#elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__)
-# define PLAT_ppc64_linux 1
-#elif defined(__linux__) && defined(__arm__)
-# define PLAT_arm_linux 1
-#else
-/* If we're not compiling for our target platform, don't generate
- any inline asms. */
-# if !defined(NVALGRIND)
-# define NVALGRIND 1
-# endif
-#endif
-
-
-/* ------------------------------------------------------------------ */
-/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
-/* in here of use to end-users -- skip to the next section. */
-/* ------------------------------------------------------------------ */
-
-#if defined(NVALGRIND)
-
-/* Define NVALGRIND to completely remove the Valgrind magic sequence
- from the compiled code (analogous to NDEBUG's effects on
- assert()) */
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- { \
- (_zzq_rlval) = (_zzq_default); \
- }
-
-#else /* ! NVALGRIND */
-
-/* The following defines the magic code sequences which the JITter
- spots and handles magically. Don't look too closely at them as
- they will rot your brain.
-
- The assembly code sequences for all architectures is in this one
- file. This is because this file must be stand-alone, and we don't
- want to have multiple files.
-
- For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
- value gets put in the return slot, so that everything works when
- this is executed not under Valgrind. Args are passed in a memory
- block, and so there's no intrinsic limit to the number that could
- be passed, but it's currently five.
-
- The macro args are:
- _zzq_rlval result lvalue
- _zzq_default default value (result returned when running on real CPU)
- _zzq_request request code
- _zzq_arg1..5 request params
-
- The other two macros are used to support function wrapping, and are
- a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
- guest's NRADDR pseudo-register and whatever other information is
- needed to safely run the call original from the wrapper: on
- ppc64-linux, the R2 value at the divert point is also needed. This
- information is abstracted into a user-visible type, OrigFn.
-
- VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
- guest, but guarantees that the branch instruction will not be
- redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
- branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
- complete inline asm, since it needs to be combined with more magic
- inline asm stuff to be useful.
-*/
-
-/* ------------------------- x86-{linux,darwin} ---------------- */
-
-#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
-
-typedef
- struct {
- unsigned int nraddr; /* where's the code? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "roll $3, %%edi ; roll $13, %%edi\n\t" \
- "roll $29, %%edi ; roll $19, %%edi\n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- { volatile unsigned int _zzq_args[6]; \
- volatile unsigned int _zzq_result; \
- _zzq_args[0] = (unsigned int)(_zzq_request); \
- _zzq_args[1] = (unsigned int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned int)(_zzq_arg5); \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %EDX = client_request ( %EAX ) */ \
- "xchgl %%ebx,%%ebx" \
- : "=d" (_zzq_result) \
- : "a" (&_zzq_args[0]), "0" (_zzq_default) \
- : "cc", "memory" \
- ); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- volatile unsigned int __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %EAX = guest_NRADDR */ \
- "xchgl %%ecx,%%ecx" \
- : "=a" (__addr) \
- : \
- : "cc", "memory" \
- ); \
- _zzq_orig->nraddr = __addr; \
- }
-
-#define VALGRIND_CALL_NOREDIR_EAX \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* call-noredir *%EAX */ \
- "xchgl %%edx,%%edx\n\t"
-#endif /* PLAT_x86_linux || PLAT_x86_darwin */
-
-/* ------------------------ amd64-{linux,darwin} --------------- */
-
-#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
-
-typedef
- struct {
- unsigned long long int nraddr; /* where's the code? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
- "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- { volatile unsigned long long int _zzq_args[6]; \
- volatile unsigned long long int _zzq_result; \
- _zzq_args[0] = (unsigned long long int)(_zzq_request); \
- _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %RDX = client_request ( %RAX ) */ \
- "xchgq %%rbx,%%rbx" \
- : "=d" (_zzq_result) \
- : "a" (&_zzq_args[0]), "0" (_zzq_default) \
- : "cc", "memory" \
- ); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- volatile unsigned long long int __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %RAX = guest_NRADDR */ \
- "xchgq %%rcx,%%rcx" \
- : "=a" (__addr) \
- : \
- : "cc", "memory" \
- ); \
- _zzq_orig->nraddr = __addr; \
- }
-
-#define VALGRIND_CALL_NOREDIR_RAX \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* call-noredir *%RAX */ \
- "xchgq %%rdx,%%rdx\n\t"
-#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
-
-/* ------------------------ ppc32-linux ------------------------ */
-
-#if defined(PLAT_ppc32_linux)
-
-typedef
- struct {
- unsigned int nraddr; /* where's the code? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
- "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- \
- { unsigned int _zzq_args[6]; \
- unsigned int _zzq_result; \
- unsigned int* _zzq_ptr; \
- _zzq_args[0] = (unsigned int)(_zzq_request); \
- _zzq_args[1] = (unsigned int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned int)(_zzq_arg5); \
- _zzq_ptr = _zzq_args; \
- __asm__ volatile("mr 3,%1\n\t" /*default*/ \
- "mr 4,%2\n\t" /*ptr*/ \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = client_request ( %R4 ) */ \
- "or 1,1,1\n\t" \
- "mr %0,3" /*result*/ \
- : "=b" (_zzq_result) \
- : "b" (_zzq_default), "b" (_zzq_ptr) \
- : "cc", "memory", "r3", "r4"); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- unsigned int __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR */ \
- "or 2,2,2\n\t" \
- "mr %0,3" \
- : "=b" (__addr) \
- : \
- : "cc", "memory", "r3" \
- ); \
- _zzq_orig->nraddr = __addr; \
- }
-
-#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* branch-and-link-to-noredir *%R11 */ \
- "or 3,3,3\n\t"
-#endif /* PLAT_ppc32_linux */
-
-/* ------------------------ ppc64-linux ------------------------ */
-
-#if defined(PLAT_ppc64_linux)
-
-typedef
- struct {
- unsigned long long int nraddr; /* where's the code? */
- unsigned long long int r2; /* what tocptr do we need? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
- "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- \
- { unsigned long long int _zzq_args[6]; \
- register unsigned long long int _zzq_result __asm__("r3"); \
- register unsigned long long int* _zzq_ptr __asm__("r4"); \
- _zzq_args[0] = (unsigned long long int)(_zzq_request); \
- _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
- _zzq_ptr = _zzq_args; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = client_request ( %R4 ) */ \
- "or 1,1,1" \
- : "=r" (_zzq_result) \
- : "0" (_zzq_default), "r" (_zzq_ptr) \
- : "cc", "memory"); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- register unsigned long long int __addr __asm__("r3"); \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR */ \
- "or 2,2,2" \
- : "=r" (__addr) \
- : \
- : "cc", "memory" \
- ); \
- _zzq_orig->nraddr = __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR_GPR2 */ \
- "or 4,4,4" \
- : "=r" (__addr) \
- : \
- : "cc", "memory" \
- ); \
- _zzq_orig->r2 = __addr; \
- }
-
-#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* branch-and-link-to-noredir *%R11 */ \
- "or 3,3,3\n\t"
-
-#endif /* PLAT_ppc64_linux */
-
-/* ------------------------- arm-linux ------------------------- */
-
-#if defined(PLAT_arm_linux)
-
-typedef
- struct {
- unsigned int nraddr; /* where's the code? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \
- "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- \
- { volatile unsigned int _zzq_args[6]; \
- volatile unsigned int _zzq_result; \
- _zzq_args[0] = (unsigned int)(_zzq_request); \
- _zzq_args[1] = (unsigned int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned int)(_zzq_arg5); \
- __asm__ volatile("mov r3, %1\n\t" /*default*/ \
- "mov r4, %2\n\t" /*ptr*/ \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* R3 = client_request ( R4 ) */ \
- "orr r10, r10, r10\n\t" \
- "mov %0, r3" /*result*/ \
- : "=r" (_zzq_result) \
- : "r" (_zzq_default), "r" (&_zzq_args[0]) \
- : "cc","memory", "r3", "r4"); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- unsigned int __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* R3 = guest_NRADDR */ \
- "orr r11, r11, r11\n\t" \
- "mov %0, r3" \
- : "=r" (__addr) \
- : \
- : "cc", "memory", "r3" \
- ); \
- _zzq_orig->nraddr = __addr; \
- }
-
-#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* branch-and-link-to-noredir *%R4 */ \
- "orr r12, r12, r12\n\t"
-
-#endif /* PLAT_arm_linux */
-
-/* ------------------------ ppc32-aix5 ------------------------- */
-
-#if defined(PLAT_ppc32_aix5)
-
-typedef
- struct {
- unsigned int nraddr; /* where's the code? */
- unsigned int r2; /* what tocptr do we need? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
- "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- \
- { unsigned int _zzq_args[7]; \
- register unsigned int _zzq_result; \
- register unsigned int* _zzq_ptr; \
- _zzq_args[0] = (unsigned int)(_zzq_request); \
- _zzq_args[1] = (unsigned int)(_zzq_arg1); \
- _zzq_args[2] = (unsigned int)(_zzq_arg2); \
- _zzq_args[3] = (unsigned int)(_zzq_arg3); \
- _zzq_args[4] = (unsigned int)(_zzq_arg4); \
- _zzq_args[5] = (unsigned int)(_zzq_arg5); \
- _zzq_args[6] = (unsigned int)(_zzq_default); \
- _zzq_ptr = _zzq_args; \
- __asm__ volatile("mr 4,%1\n\t" \
- "lwz 3, 24(4)\n\t" \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = client_request ( %R4 ) */ \
- "or 1,1,1\n\t" \
- "mr %0,3" \
- : "=b" (_zzq_result) \
- : "b" (_zzq_ptr) \
- : "r3", "r4", "cc", "memory"); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- register unsigned int __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR */ \
- "or 2,2,2\n\t" \
- "mr %0,3" \
- : "=b" (__addr) \
- : \
- : "r3", "cc", "memory" \
- ); \
- _zzq_orig->nraddr = __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR_GPR2 */ \
- "or 4,4,4\n\t" \
- "mr %0,3" \
- : "=b" (__addr) \
- : \
- : "r3", "cc", "memory" \
- ); \
- _zzq_orig->r2 = __addr; \
- }
-
-#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* branch-and-link-to-noredir *%R11 */ \
- "or 3,3,3\n\t"
-
-#endif /* PLAT_ppc32_aix5 */
-
-/* ------------------------ ppc64-aix5 ------------------------- */
-
-#if defined(PLAT_ppc64_aix5)
-
-typedef
- struct {
- unsigned long long int nraddr; /* where's the code? */
- unsigned long long int r2; /* what tocptr do we need? */
- }
- OrigFn;
-
-#define __SPECIAL_INSTRUCTION_PREAMBLE \
- "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
- "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
-
-#define VALGRIND_DO_CLIENT_REQUEST( \
- _zzq_rlval, _zzq_default, _zzq_request, \
- _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
- \
- { unsigned long long int _zzq_args[7]; \
- register unsigned long long int _zzq_result; \
- register unsigned long long int* _zzq_ptr; \
- _zzq_args[0] = (unsigned int long long)(_zzq_request); \
- _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
- _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
- _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
- _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
- _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
- _zzq_args[6] = (unsigned int long long)(_zzq_default); \
- _zzq_ptr = _zzq_args; \
- __asm__ volatile("mr 4,%1\n\t" \
- "ld 3, 48(4)\n\t" \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = client_request ( %R4 ) */ \
- "or 1,1,1\n\t" \
- "mr %0,3" \
- : "=b" (_zzq_result) \
- : "b" (_zzq_ptr) \
- : "r3", "r4", "cc", "memory"); \
- _zzq_rlval = _zzq_result; \
- }
-
-#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
- { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
- register unsigned long long int __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR */ \
- "or 2,2,2\n\t" \
- "mr %0,3" \
- : "=b" (__addr) \
- : \
- : "r3", "cc", "memory" \
- ); \
- _zzq_orig->nraddr = __addr; \
- __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
- /* %R3 = guest_NRADDR_GPR2 */ \
- "or 4,4,4\n\t" \
- "mr %0,3" \
- : "=b" (__addr) \
- : \
- : "r3", "cc", "memory" \
- ); \
- _zzq_orig->r2 = __addr; \
- }
-
-#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- __SPECIAL_INSTRUCTION_PREAMBLE \
- /* branch-and-link-to-noredir *%R11 */ \
- "or 3,3,3\n\t"
-
-#endif /* PLAT_ppc64_aix5 */
-
-/* Insert assembly code for other platforms here... */
-
-#endif /* NVALGRIND */
-
-
-/* ------------------------------------------------------------------ */
-/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
-/* ugly. It's the least-worst tradeoff I can think of. */
-/* ------------------------------------------------------------------ */
-
-/* This section defines magic (a.k.a appalling-hack) macros for doing
- guaranteed-no-redirection macros, so as to get from function
- wrappers to the functions they are wrapping. The whole point is to
- construct standard call sequences, but to do the call itself with a
- special no-redirect call pseudo-instruction that the JIT
- understands and handles specially. This section is long and
- repetitious, and I can't see a way to make it shorter.
-
- The naming scheme is as follows:
-
- CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
-
- 'W' stands for "word" and 'v' for "void". Hence there are
- different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
- and for each, the possibility of returning a word-typed result, or
- no result.
-*/
-
-/* Use these to write the name of your wrapper. NOTE: duplicates
- VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
-
-/* Use an extra level of macroisation so as to ensure the soname/fnname
- args are fully macro-expanded before pasting them together. */
-#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
-
-#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
- VG_CONCAT4(_vgwZU_,soname,_,fnname)
-
-#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
- VG_CONCAT4(_vgwZZ_,soname,_,fnname)
-
-/* Use this macro from within a wrapper function to collect the
- context (address and possibly other info) of the original function.
- Once you have that you can then use it in one of the CALL_FN_
- macros. The type of the argument _lval is OrigFn. */
-#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
-
-/* Derivatives of the main macros below, for calling functions
- returning void. */
-
-#define CALL_FN_v_v(fnptr) \
- do { volatile unsigned long _junk; \
- CALL_FN_W_v(_junk,fnptr); } while (0)
-
-#define CALL_FN_v_W(fnptr, arg1) \
- do { volatile unsigned long _junk; \
- CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
-
-#define CALL_FN_v_WW(fnptr, arg1,arg2) \
- do { volatile unsigned long _junk; \
- CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
-
-#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
- do { volatile unsigned long _junk; \
- CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
-
-#define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \
- do { volatile unsigned long _junk; \
- CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0)
-
-#define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \
- do { volatile unsigned long _junk; \
- CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0)
-
-#define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { volatile unsigned long _junk; \
- CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0)
-
-#define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \
- do { volatile unsigned long _junk; \
- CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0)
-
-/* ------------------------- x86-{linux,darwin} ---------------- */
-
-#if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin)
-
-/* These regs are trashed by the hidden call. No need to mention eax
- as gcc can already see that, plus causes gcc to bomb. */
-#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
-
-/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
- long) == 4. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[1]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[2]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- __asm__ volatile( \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $4, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- __asm__ volatile( \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $8, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[4]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- __asm__ volatile( \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $12, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[5]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- __asm__ volatile( \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $16, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[6]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- __asm__ volatile( \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $20, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[7]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- __asm__ volatile( \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $24, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[8]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- __asm__ volatile( \
- "pushl 28(%%eax)\n\t" \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $28, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[9]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- __asm__ volatile( \
- "pushl 32(%%eax)\n\t" \
- "pushl 28(%%eax)\n\t" \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $32, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[10]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- __asm__ volatile( \
- "pushl 36(%%eax)\n\t" \
- "pushl 32(%%eax)\n\t" \
- "pushl 28(%%eax)\n\t" \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $36, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[11]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- __asm__ volatile( \
- "pushl 40(%%eax)\n\t" \
- "pushl 36(%%eax)\n\t" \
- "pushl 32(%%eax)\n\t" \
- "pushl 28(%%eax)\n\t" \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $40, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
- arg6,arg7,arg8,arg9,arg10, \
- arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[12]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- _argvec[11] = (unsigned long)(arg11); \
- __asm__ volatile( \
- "pushl 44(%%eax)\n\t" \
- "pushl 40(%%eax)\n\t" \
- "pushl 36(%%eax)\n\t" \
- "pushl 32(%%eax)\n\t" \
- "pushl 28(%%eax)\n\t" \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $44, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
- arg6,arg7,arg8,arg9,arg10, \
- arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[13]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- _argvec[11] = (unsigned long)(arg11); \
- _argvec[12] = (unsigned long)(arg12); \
- __asm__ volatile( \
- "pushl 48(%%eax)\n\t" \
- "pushl 44(%%eax)\n\t" \
- "pushl 40(%%eax)\n\t" \
- "pushl 36(%%eax)\n\t" \
- "pushl 32(%%eax)\n\t" \
- "pushl 28(%%eax)\n\t" \
- "pushl 24(%%eax)\n\t" \
- "pushl 20(%%eax)\n\t" \
- "pushl 16(%%eax)\n\t" \
- "pushl 12(%%eax)\n\t" \
- "pushl 8(%%eax)\n\t" \
- "pushl 4(%%eax)\n\t" \
- "movl (%%eax), %%eax\n\t" /* target->%eax */ \
- VALGRIND_CALL_NOREDIR_EAX \
- "addl $48, %%esp\n" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_x86_linux || PLAT_x86_darwin */
-
-/* ------------------------ amd64-{linux,darwin} --------------- */
-
-#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
-
-/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
-
-/* These regs are trashed by the hidden call. */
-#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
- "rdi", "r8", "r9", "r10", "r11"
-
-/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
- long) == 8. */
-
-/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
- macros. In order not to trash the stack redzone, we need to drop
- %rsp by 128 before the hidden call, and restore afterwards. The
- nastyness is that it is only by luck that the stack still appears
- to be unwindable during the hidden call - since then the behaviour
- of any routine using this macro does not match what the CFI data
- says. Sigh.
-
- Why is this important? Imagine that a wrapper has a stack
- allocated local, and passes to the hidden call, a pointer to it.
- Because gcc does not know about the hidden call, it may allocate
- that local in the redzone. Unfortunately the hidden call may then
- trash it before it comes to use it. So we must step clear of the
- redzone, for the duration of the hidden call, to make it safe.
-
- Probably the same problem afflicts the other redzone-style ABIs too
- (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
- self describing (none of this CFI nonsense) so at least messing
- with the stack pointer doesn't give a danger of non-unwindable
- stack. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[1]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[2]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[4]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[5]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[6]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[7]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- "addq $128,%%rsp\n\t" \
- VALGRIND_CALL_NOREDIR_RAX \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[8]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $8, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[9]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $16, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[10]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 72(%%rax)\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $24, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[11]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 80(%%rax)\n\t" \
- "pushq 72(%%rax)\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $32, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[12]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- _argvec[11] = (unsigned long)(arg11); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 88(%%rax)\n\t" \
- "pushq 80(%%rax)\n\t" \
- "pushq 72(%%rax)\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $40, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[13]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- _argvec[11] = (unsigned long)(arg11); \
- _argvec[12] = (unsigned long)(arg12); \
- __asm__ volatile( \
- "subq $128,%%rsp\n\t" \
- "pushq 96(%%rax)\n\t" \
- "pushq 88(%%rax)\n\t" \
- "pushq 80(%%rax)\n\t" \
- "pushq 72(%%rax)\n\t" \
- "pushq 64(%%rax)\n\t" \
- "pushq 56(%%rax)\n\t" \
- "movq 48(%%rax), %%r9\n\t" \
- "movq 40(%%rax), %%r8\n\t" \
- "movq 32(%%rax), %%rcx\n\t" \
- "movq 24(%%rax), %%rdx\n\t" \
- "movq 16(%%rax), %%rsi\n\t" \
- "movq 8(%%rax), %%rdi\n\t" \
- "movq (%%rax), %%rax\n\t" /* target->%rax */ \
- VALGRIND_CALL_NOREDIR_RAX \
- "addq $48, %%rsp\n" \
- "addq $128,%%rsp\n\t" \
- : /*out*/ "=a" (_res) \
- : /*in*/ "a" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_amd64_linux || PLAT_amd64_darwin */
-
-/* ------------------------ ppc32-linux ------------------------ */
-
-#if defined(PLAT_ppc32_linux)
-
-/* This is useful for finding out about the on-stack stuff:
-
- extern int f9 ( int,int,int,int,int,int,int,int,int );
- extern int f10 ( int,int,int,int,int,int,int,int,int,int );
- extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
- extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
-
- int g9 ( void ) {
- return f9(11,22,33,44,55,66,77,88,99);
- }
- int g10 ( void ) {
- return f10(11,22,33,44,55,66,77,88,99,110);
- }
- int g11 ( void ) {
- return f11(11,22,33,44,55,66,77,88,99,110,121);
- }
- int g12 ( void ) {
- return f12(11,22,33,44,55,66,77,88,99,110,121,132);
- }
-*/
-
-/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
-
-/* These regs are trashed by the hidden call. */
-#define __CALLER_SAVED_REGS \
- "lr", "ctr", "xer", \
- "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
- "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
- "r11", "r12", "r13"
-
-/* These CALL_FN_ macros assume that on ppc32-linux,
- sizeof(unsigned long) == 4. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[1]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[2]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[4]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[5]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[6]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[7]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[8]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- _argvec[7] = (unsigned long)arg7; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 9,28(11)\n\t" \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[9]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- _argvec[7] = (unsigned long)arg7; \
- _argvec[8] = (unsigned long)arg8; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 9,28(11)\n\t" \
- "lwz 10,32(11)\n\t" /* arg8->r10 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[10]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- _argvec[7] = (unsigned long)arg7; \
- _argvec[8] = (unsigned long)arg8; \
- _argvec[9] = (unsigned long)arg9; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "addi 1,1,-16\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,8(1)\n\t" \
- /* args1-8 */ \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 9,28(11)\n\t" \
- "lwz 10,32(11)\n\t" /* arg8->r10 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "addi 1,1,16\n\t" \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[11]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- _argvec[7] = (unsigned long)arg7; \
- _argvec[8] = (unsigned long)arg8; \
- _argvec[9] = (unsigned long)arg9; \
- _argvec[10] = (unsigned long)arg10; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "addi 1,1,-16\n\t" \
- /* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,12(1)\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,8(1)\n\t" \
- /* args1-8 */ \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 9,28(11)\n\t" \
- "lwz 10,32(11)\n\t" /* arg8->r10 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "addi 1,1,16\n\t" \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[12]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- _argvec[7] = (unsigned long)arg7; \
- _argvec[8] = (unsigned long)arg8; \
- _argvec[9] = (unsigned long)arg9; \
- _argvec[10] = (unsigned long)arg10; \
- _argvec[11] = (unsigned long)arg11; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "addi 1,1,-32\n\t" \
- /* arg11 */ \
- "lwz 3,44(11)\n\t" \
- "stw 3,16(1)\n\t" \
- /* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,12(1)\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,8(1)\n\t" \
- /* args1-8 */ \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 9,28(11)\n\t" \
- "lwz 10,32(11)\n\t" /* arg8->r10 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "addi 1,1,32\n\t" \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[13]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)arg1; \
- _argvec[2] = (unsigned long)arg2; \
- _argvec[3] = (unsigned long)arg3; \
- _argvec[4] = (unsigned long)arg4; \
- _argvec[5] = (unsigned long)arg5; \
- _argvec[6] = (unsigned long)arg6; \
- _argvec[7] = (unsigned long)arg7; \
- _argvec[8] = (unsigned long)arg8; \
- _argvec[9] = (unsigned long)arg9; \
- _argvec[10] = (unsigned long)arg10; \
- _argvec[11] = (unsigned long)arg11; \
- _argvec[12] = (unsigned long)arg12; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "addi 1,1,-32\n\t" \
- /* arg12 */ \
- "lwz 3,48(11)\n\t" \
- "stw 3,20(1)\n\t" \
- /* arg11 */ \
- "lwz 3,44(11)\n\t" \
- "stw 3,16(1)\n\t" \
- /* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,12(1)\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,8(1)\n\t" \
- /* args1-8 */ \
- "lwz 3,4(11)\n\t" /* arg1->r3 */ \
- "lwz 4,8(11)\n\t" \
- "lwz 5,12(11)\n\t" \
- "lwz 6,16(11)\n\t" /* arg4->r6 */ \
- "lwz 7,20(11)\n\t" \
- "lwz 8,24(11)\n\t" \
- "lwz 9,28(11)\n\t" \
- "lwz 10,32(11)\n\t" /* arg8->r10 */ \
- "lwz 11,0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "addi 1,1,32\n\t" \
- "mr %0,3" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_ppc32_linux */
-
-/* ------------------------ ppc64-linux ------------------------ */
-
-#if defined(PLAT_ppc64_linux)
-
-/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
-
-/* These regs are trashed by the hidden call. */
-#define __CALLER_SAVED_REGS \
- "lr", "ctr", "xer", \
- "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
- "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
- "r11", "r12", "r13"
-
-/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
- long) == 8. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+0]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+1]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+2]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+3]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+4]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+5]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+6]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+7]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+8]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)" /* restore tocptr */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+9]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "addi 1,1,-128\n\t" /* expand stack frame */ \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- "addi 1,1,128" /* restore frame */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+10]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "addi 1,1,-128\n\t" /* expand stack frame */ \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- "addi 1,1,128" /* restore frame */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+11]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "addi 1,1,-144\n\t" /* expand stack frame */ \
- /* arg11 */ \
- "ld 3,88(11)\n\t" \
- "std 3,128(1)\n\t" \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- "addi 1,1,144" /* restore frame */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+12]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- _argvec[2+12] = (unsigned long)arg12; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "addi 1,1,-144\n\t" /* expand stack frame */ \
- /* arg12 */ \
- "ld 3,96(11)\n\t" \
- "std 3,136(1)\n\t" \
- /* arg11 */ \
- "ld 3,88(11)\n\t" \
- "std 3,128(1)\n\t" \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- "addi 1,1,144" /* restore frame */ \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_ppc64_linux */
-
-/* ------------------------- arm-linux ------------------------- */
-
-#if defined(PLAT_arm_linux)
-
-/* These regs are trashed by the hidden call. */
-#define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14"
-
-/* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned
- long) == 4. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[1]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "mov %0, r0\n" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[2]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- __asm__ volatile( \
- "ldr r0, [%1, #4] \n\t" \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "mov %0, r0\n" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- __asm__ volatile( \
- "ldr r0, [%1, #4] \n\t" \
- "ldr r1, [%1, #8] \n\t" \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "mov %0, r0\n" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[4]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- __asm__ volatile( \
- "ldr r0, [%1, #4] \n\t" \
- "ldr r1, [%1, #8] \n\t" \
- "ldr r2, [%1, #12] \n\t" \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "mov %0, r0\n" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[5]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- __asm__ volatile( \
- "ldr r0, [%1, #4] \n\t" \
- "ldr r1, [%1, #8] \n\t" \
- "ldr r2, [%1, #12] \n\t" \
- "ldr r3, [%1, #16] \n\t" \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "mov %0, r0" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[6]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- __asm__ volatile( \
- "ldr r0, [%1, #20] \n\t" \
- "push {r0} \n\t" \
- "ldr r0, [%1, #4] \n\t" \
- "ldr r1, [%1, #8] \n\t" \
- "ldr r2, [%1, #12] \n\t" \
- "ldr r3, [%1, #16] \n\t" \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "add sp, sp, #4 \n\t" \
- "mov %0, r0" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[7]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- __asm__ volatile( \
- "ldr r0, [%1, #20] \n\t" \
- "ldr r1, [%1, #24] \n\t" \
- "push {r0, r1} \n\t" \
- "ldr r0, [%1, #4] \n\t" \
- "ldr r1, [%1, #8] \n\t" \
- "ldr r2, [%1, #12] \n\t" \
- "ldr r3, [%1, #16] \n\t" \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "add sp, sp, #8 \n\t" \
- "mov %0, r0" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[8]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- __asm__ volatile( \
- "ldr r0, [%1, #20] \n\t" \
- "ldr r1, [%1, #24] \n\t" \
- "ldr r2, [%1, #28] \n\t" \
- "push {r0, r1, r2} \n\t" \
- "ldr r0, [%1, #4] \n\t" \
- "ldr r1, [%1, #8] \n\t" \
- "ldr r2, [%1, #12] \n\t" \
- "ldr r3, [%1, #16] \n\t" \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "add sp, sp, #12 \n\t" \
- "mov %0, r0" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[9]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- __asm__ volatile( \
- "ldr r0, [%1, #20] \n\t" \
- "ldr r1, [%1, #24] \n\t" \
- "ldr r2, [%1, #28] \n\t" \
- "ldr r3, [%1, #32] \n\t" \
- "push {r0, r1, r2, r3} \n\t" \
- "ldr r0, [%1, #4] \n\t" \
- "ldr r1, [%1, #8] \n\t" \
- "ldr r2, [%1, #12] \n\t" \
- "ldr r3, [%1, #16] \n\t" \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "add sp, sp, #16 \n\t" \
- "mov %0, r0" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[10]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- __asm__ volatile( \
- "ldr r0, [%1, #20] \n\t" \
- "ldr r1, [%1, #24] \n\t" \
- "ldr r2, [%1, #28] \n\t" \
- "ldr r3, [%1, #32] \n\t" \
- "ldr r4, [%1, #36] \n\t" \
- "push {r0, r1, r2, r3, r4} \n\t" \
- "ldr r0, [%1, #4] \n\t" \
- "ldr r1, [%1, #8] \n\t" \
- "ldr r2, [%1, #12] \n\t" \
- "ldr r3, [%1, #16] \n\t" \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "add sp, sp, #20 \n\t" \
- "mov %0, r0" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[11]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- __asm__ volatile( \
- "ldr r0, [%1, #40] \n\t" \
- "push {r0} \n\t" \
- "ldr r0, [%1, #20] \n\t" \
- "ldr r1, [%1, #24] \n\t" \
- "ldr r2, [%1, #28] \n\t" \
- "ldr r3, [%1, #32] \n\t" \
- "ldr r4, [%1, #36] \n\t" \
- "push {r0, r1, r2, r3, r4} \n\t" \
- "ldr r0, [%1, #4] \n\t" \
- "ldr r1, [%1, #8] \n\t" \
- "ldr r2, [%1, #12] \n\t" \
- "ldr r3, [%1, #16] \n\t" \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "add sp, sp, #24 \n\t" \
- "mov %0, r0" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
- arg6,arg7,arg8,arg9,arg10, \
- arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[12]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- _argvec[11] = (unsigned long)(arg11); \
- __asm__ volatile( \
- "ldr r0, [%1, #40] \n\t" \
- "ldr r1, [%1, #44] \n\t" \
- "push {r0, r1} \n\t" \
- "ldr r0, [%1, #20] \n\t" \
- "ldr r1, [%1, #24] \n\t" \
- "ldr r2, [%1, #28] \n\t" \
- "ldr r3, [%1, #32] \n\t" \
- "ldr r4, [%1, #36] \n\t" \
- "push {r0, r1, r2, r3, r4} \n\t" \
- "ldr r0, [%1, #4] \n\t" \
- "ldr r1, [%1, #8] \n\t" \
- "ldr r2, [%1, #12] \n\t" \
- "ldr r3, [%1, #16] \n\t" \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "add sp, sp, #28 \n\t" \
- "mov %0, r0" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
- arg6,arg7,arg8,arg9,arg10, \
- arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[13]; \
- volatile unsigned long _res; \
- _argvec[0] = (unsigned long)_orig.nraddr; \
- _argvec[1] = (unsigned long)(arg1); \
- _argvec[2] = (unsigned long)(arg2); \
- _argvec[3] = (unsigned long)(arg3); \
- _argvec[4] = (unsigned long)(arg4); \
- _argvec[5] = (unsigned long)(arg5); \
- _argvec[6] = (unsigned long)(arg6); \
- _argvec[7] = (unsigned long)(arg7); \
- _argvec[8] = (unsigned long)(arg8); \
- _argvec[9] = (unsigned long)(arg9); \
- _argvec[10] = (unsigned long)(arg10); \
- _argvec[11] = (unsigned long)(arg11); \
- _argvec[12] = (unsigned long)(arg12); \
- __asm__ volatile( \
- "ldr r0, [%1, #40] \n\t" \
- "ldr r1, [%1, #44] \n\t" \
- "ldr r2, [%1, #48] \n\t" \
- "push {r0, r1, r2} \n\t" \
- "ldr r0, [%1, #20] \n\t" \
- "ldr r1, [%1, #24] \n\t" \
- "ldr r2, [%1, #28] \n\t" \
- "ldr r3, [%1, #32] \n\t" \
- "ldr r4, [%1, #36] \n\t" \
- "push {r0, r1, r2, r3, r4} \n\t" \
- "ldr r0, [%1, #4] \n\t" \
- "ldr r1, [%1, #8] \n\t" \
- "ldr r2, [%1, #12] \n\t" \
- "ldr r3, [%1, #16] \n\t" \
- "ldr r4, [%1] \n\t" /* target->r4 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \
- "add sp, sp, #32 \n\t" \
- "mov %0, r0" \
- : /*out*/ "=r" (_res) \
- : /*in*/ "0" (&_argvec[0]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_arm_linux */
-
-/* ------------------------ ppc32-aix5 ------------------------- */
-
-#if defined(PLAT_ppc32_aix5)
-
-/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
-
-/* These regs are trashed by the hidden call. */
-#define __CALLER_SAVED_REGS \
- "lr", "ctr", "xer", \
- "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
- "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
- "r11", "r12", "r13"
-
-/* Expand the stack frame, copying enough info that unwinding
- still works. Trashes r3. */
-
-#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
- "addi 1,1,-" #_n_fr "\n\t" \
- "lwz 3," #_n_fr "(1)\n\t" \
- "stw 3,0(1)\n\t"
-
-#define VG_CONTRACT_FRAME_BY(_n_fr) \
- "addi 1,1," #_n_fr "\n\t"
-
-/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
- long) == 4. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+0]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+1]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+2]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+3]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+4]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+5]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+6]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+7]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+8]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+9]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(64) \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,56(1)\n\t" \
- /* args1-8 */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(64) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+10]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(64) \
- /* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,60(1)\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,56(1)\n\t" \
- /* args1-8 */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(64) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+11]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(72) \
- /* arg11 */ \
- "lwz 3,44(11)\n\t" \
- "stw 3,64(1)\n\t" \
- /* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,60(1)\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,56(1)\n\t" \
- /* args1-8 */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(72) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+12]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- _argvec[2+12] = (unsigned long)arg12; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "stw 2,-8(11)\n\t" /* save tocptr */ \
- "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(72) \
- /* arg12 */ \
- "lwz 3,48(11)\n\t" \
- "stw 3,68(1)\n\t" \
- /* arg11 */ \
- "lwz 3,44(11)\n\t" \
- "stw 3,64(1)\n\t" \
- /* arg10 */ \
- "lwz 3,40(11)\n\t" \
- "stw 3,60(1)\n\t" \
- /* arg9 */ \
- "lwz 3,36(11)\n\t" \
- "stw 3,56(1)\n\t" \
- /* args1-8 */ \
- "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
- "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
- "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
- "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
- "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
- "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
- "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
- "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
- "lwz 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "lwz 2,-8(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(72) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_ppc32_aix5 */
-
-/* ------------------------ ppc64-aix5 ------------------------- */
-
-#if defined(PLAT_ppc64_aix5)
-
-/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
-
-/* These regs are trashed by the hidden call. */
-#define __CALLER_SAVED_REGS \
- "lr", "ctr", "xer", \
- "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
- "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
- "r11", "r12", "r13"
-
-/* Expand the stack frame, copying enough info that unwinding
- still works. Trashes r3. */
-
-#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
- "addi 1,1,-" #_n_fr "\n\t" \
- "ld 3," #_n_fr "(1)\n\t" \
- "std 3,0(1)\n\t"
-
-#define VG_CONTRACT_FRAME_BY(_n_fr) \
- "addi 1,1," #_n_fr "\n\t"
-
-/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
- long) == 8. */
-
-#define CALL_FN_W_v(lval, orig) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+0]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_W(lval, orig, arg1) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+1]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+2]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+3]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+4]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+5]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+6]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+7]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+8]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+9]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(128) \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(128) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+10]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(128) \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(128) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+11]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(144) \
- /* arg11 */ \
- "ld 3,88(11)\n\t" \
- "std 3,128(1)\n\t" \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(144) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
- arg7,arg8,arg9,arg10,arg11,arg12) \
- do { \
- volatile OrigFn _orig = (orig); \
- volatile unsigned long _argvec[3+12]; \
- volatile unsigned long _res; \
- /* _argvec[0] holds current r2 across the call */ \
- _argvec[1] = (unsigned long)_orig.r2; \
- _argvec[2] = (unsigned long)_orig.nraddr; \
- _argvec[2+1] = (unsigned long)arg1; \
- _argvec[2+2] = (unsigned long)arg2; \
- _argvec[2+3] = (unsigned long)arg3; \
- _argvec[2+4] = (unsigned long)arg4; \
- _argvec[2+5] = (unsigned long)arg5; \
- _argvec[2+6] = (unsigned long)arg6; \
- _argvec[2+7] = (unsigned long)arg7; \
- _argvec[2+8] = (unsigned long)arg8; \
- _argvec[2+9] = (unsigned long)arg9; \
- _argvec[2+10] = (unsigned long)arg10; \
- _argvec[2+11] = (unsigned long)arg11; \
- _argvec[2+12] = (unsigned long)arg12; \
- __asm__ volatile( \
- "mr 11,%1\n\t" \
- VG_EXPAND_FRAME_BY_trashes_r3(512) \
- "std 2,-16(11)\n\t" /* save tocptr */ \
- "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
- VG_EXPAND_FRAME_BY_trashes_r3(144) \
- /* arg12 */ \
- "ld 3,96(11)\n\t" \
- "std 3,136(1)\n\t" \
- /* arg11 */ \
- "ld 3,88(11)\n\t" \
- "std 3,128(1)\n\t" \
- /* arg10 */ \
- "ld 3,80(11)\n\t" \
- "std 3,120(1)\n\t" \
- /* arg9 */ \
- "ld 3,72(11)\n\t" \
- "std 3,112(1)\n\t" \
- /* args1-8 */ \
- "ld 3, 8(11)\n\t" /* arg1->r3 */ \
- "ld 4, 16(11)\n\t" /* arg2->r4 */ \
- "ld 5, 24(11)\n\t" /* arg3->r5 */ \
- "ld 6, 32(11)\n\t" /* arg4->r6 */ \
- "ld 7, 40(11)\n\t" /* arg5->r7 */ \
- "ld 8, 48(11)\n\t" /* arg6->r8 */ \
- "ld 9, 56(11)\n\t" /* arg7->r9 */ \
- "ld 10, 64(11)\n\t" /* arg8->r10 */ \
- "ld 11, 0(11)\n\t" /* target->r11 */ \
- VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
- "mr 11,%1\n\t" \
- "mr %0,3\n\t" \
- "ld 2,-16(11)\n\t" /* restore tocptr */ \
- VG_CONTRACT_FRAME_BY(144) \
- VG_CONTRACT_FRAME_BY(512) \
- : /*out*/ "=r" (_res) \
- : /*in*/ "r" (&_argvec[2]) \
- : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
- ); \
- lval = (__typeof__(lval)) _res; \
- } while (0)
-
-#endif /* PLAT_ppc64_aix5 */
-
-
-/* ------------------------------------------------------------------ */
-/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
-/* */
-/* ------------------------------------------------------------------ */
-
-/* Some request codes. There are many more of these, but most are not
- exposed to end-user view. These are the public ones, all of the
- form 0x1000 + small_number.
-
- Core ones are in the range 0x00000000--0x0000ffff. The non-public
- ones start at 0x2000.
-*/
-
-/* These macros are used by tools -- they must be public, but don't
- embed them into other programs. */
-#define VG_USERREQ_TOOL_BASE(a,b) \
- ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
-#define VG_IS_TOOL_USERREQ(a, b, v) \
- (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
-
-/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
- This enum comprises an ABI exported by Valgrind to programs
- which use client requests. DO NOT CHANGE THE ORDER OF THESE
- ENTRIES, NOR DELETE ANY -- add new ones at the end. */
-typedef
- enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
- VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
-
- /* These allow any function to be called from the simulated
- CPU but run on the real CPU. Nb: the first arg passed to
- the function is always the ThreadId of the running
- thread! So CLIENT_CALL0 actually requires a 1 arg
- function, etc. */
- VG_USERREQ__CLIENT_CALL0 = 0x1101,
- VG_USERREQ__CLIENT_CALL1 = 0x1102,
- VG_USERREQ__CLIENT_CALL2 = 0x1103,
- VG_USERREQ__CLIENT_CALL3 = 0x1104,
-
- /* Can be useful in regression testing suites -- eg. can
- send Valgrind's output to /dev/null and still count
- errors. */
- VG_USERREQ__COUNT_ERRORS = 0x1201,
-
- /* These are useful and can be interpreted by any tool that
- tracks malloc() et al, by using vg_replace_malloc.c. */
- VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
- VG_USERREQ__FREELIKE_BLOCK = 0x1302,
- /* Memory pool support. */
- VG_USERREQ__CREATE_MEMPOOL = 0x1303,
- VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
- VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
- VG_USERREQ__MEMPOOL_FREE = 0x1306,
- VG_USERREQ__MEMPOOL_TRIM = 0x1307,
- VG_USERREQ__MOVE_MEMPOOL = 0x1308,
- VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
- VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
-
- /* Allow printfs to valgrind log. */
- /* The first two pass the va_list argument by value, which
- assumes it is the same size as or smaller than a UWord,
- which generally isn't the case. Hence are deprecated.
- The second two pass the vargs by reference and so are
- immune to this problem. */
- /* both :: char* fmt, va_list vargs (DEPRECATED) */
- VG_USERREQ__PRINTF = 0x1401,
- VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
- /* both :: char* fmt, va_list* vargs */
- VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403,
- VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404,
-
- /* Stack support. */
- VG_USERREQ__STACK_REGISTER = 0x1501,
- VG_USERREQ__STACK_DEREGISTER = 0x1502,
- VG_USERREQ__STACK_CHANGE = 0x1503,
-
- /* Wine support */
- VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601
- } Vg_ClientRequest;
-
-#if !defined(__GNUC__)
-# define __extension__ /* */
-#endif
-
-/* Returns the number of Valgrinds this code is running under. That
- is, 0 if running natively, 1 if running under Valgrind, 2 if
- running under Valgrind which is running under another Valgrind,
- etc. */
-#define RUNNING_ON_VALGRIND __extension__ \
- ({unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
- VG_USERREQ__RUNNING_ON_VALGRIND, \
- 0, 0, 0, 0, 0); \
- _qzz_res; \
- })
-
-
-/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
- _qzz_len - 1]. Useful if you are debugging a JITter or some such,
- since it provides a way to make sure valgrind will retranslate the
- invalidated area. Returns no value. */
-#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__DISCARD_TRANSLATIONS, \
- _qzz_addr, _qzz_len, 0, 0, 0); \
- }
-
-
-/* These requests are for getting Valgrind itself to print something.
- Possibly with a backtrace. This is a really ugly hack. The return value
- is the number of characters printed, excluding the "**<pid>** " part at the
- start and the backtrace (if present). */
-
-#if defined(NVALGRIND)
-
-# define VALGRIND_PRINTF(...)
-# define VALGRIND_PRINTF_BACKTRACE(...)
-
-#else /* NVALGRIND */
-
-/* Modern GCC will optimize the static routine out if unused,
- and unused attribute will shut down warnings about it. */
-static int VALGRIND_PRINTF(const char *format, ...)
- __attribute__((format(__printf__, 1, 2), __unused__));
-static int
-VALGRIND_PRINTF(const char *format, ...)
-{
- unsigned long _qzz_res;
- va_list vargs;
- va_start(vargs, format);
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
- VG_USERREQ__PRINTF_VALIST_BY_REF,
- (unsigned long)format,
- (unsigned long)&vargs,
- 0, 0, 0);
- va_end(vargs);
- return (int)_qzz_res;
-}
-
-static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
- __attribute__((format(__printf__, 1, 2), __unused__));
-static int
-VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
-{
- unsigned long _qzz_res;
- va_list vargs;
- va_start(vargs, format);
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0,
- VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
- (unsigned long)format,
- (unsigned long)&vargs,
- 0, 0, 0);
- va_end(vargs);
- return (int)_qzz_res;
-}
-
-#endif /* NVALGRIND */
-
-
-/* These requests allow control to move from the simulated CPU to the
- real CPU, calling an arbitary function.
-
- Note that the current ThreadId is inserted as the first argument.
- So this call:
-
- VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
-
- requires f to have this signature:
-
- Word f(Word tid, Word arg1, Word arg2)
-
- where "Word" is a word-sized type.
-
- Note that these client requests are not entirely reliable. For example,
- if you call a function with them that subsequently calls printf(),
- there's a high chance Valgrind will crash. Generally, your prospects of
- these working are made higher if the called function does not refer to
- any global variables, and does not refer to any libc or other functions
- (printf et al). Any kind of entanglement with libc or dynamic linking is
- likely to have a bad outcome, for tricky reasons which we've grappled
- with a lot in the past.
-*/
-#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
- __extension__ \
- ({unsigned long _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL0, \
- _qyy_fn, \
- 0, 0, 0, 0); \
- _qyy_res; \
- })
-
-#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
- __extension__ \
- ({unsigned long _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL1, \
- _qyy_fn, \
- _qyy_arg1, 0, 0, 0); \
- _qyy_res; \
- })
-
-#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
- __extension__ \
- ({unsigned long _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL2, \
- _qyy_fn, \
- _qyy_arg1, _qyy_arg2, 0, 0); \
- _qyy_res; \
- })
-
-#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
- __extension__ \
- ({unsigned long _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__CLIENT_CALL3, \
- _qyy_fn, \
- _qyy_arg1, _qyy_arg2, \
- _qyy_arg3, 0); \
- _qyy_res; \
- })
-
-
-/* Counts the number of errors that have been recorded by a tool. Nb:
- the tool must record the errors with VG_(maybe_record_error)() or
- VG_(unique_error)() for them to be counted. */
-#define VALGRIND_COUNT_ERRORS \
- __extension__ \
- ({unsigned int _qyy_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
- VG_USERREQ__COUNT_ERRORS, \
- 0, 0, 0, 0, 0); \
- _qyy_res; \
- })
-
-/* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing
- when heap blocks are allocated in order to give accurate results. This
- happens automatically for the standard allocator functions such as
- malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete,
- delete[], etc.
-
- But if your program uses a custom allocator, this doesn't automatically
- happen, and Valgrind will not do as well. For example, if you allocate
- superblocks with mmap() and then allocates chunks of the superblocks, all
- Valgrind's observations will be at the mmap() level and it won't know that
- the chunks should be considered separate entities. In Memcheck's case,
- that means you probably won't get heap block overrun detection (because
- there won't be redzones marked as unaddressable) and you definitely won't
- get any leak detection.
-
- The following client requests allow a custom allocator to be annotated so
- that it can be handled accurately by Valgrind.
-
- VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated
- by a malloc()-like function. For Memcheck (an illustrative case), this
- does two things:
-
- - It records that the block has been allocated. This means any addresses
- within the block mentioned in error messages will be
- identified as belonging to the block. It also means that if the block
- isn't freed it will be detected by the leak checker.
-
- - It marks the block as being addressable and undefined (if 'is_zeroed' is
- not set), or addressable and defined (if 'is_zeroed' is set). This
- controls how accesses to the block by the program are handled.
-
- 'addr' is the start of the usable block (ie. after any
- redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator
- can apply redzones -- these are blocks of padding at the start and end of
- each block. Adding redzones is recommended as it makes it much more likely
- Valgrind will spot block overruns. `is_zeroed' indicates if the memory is
- zeroed (or filled with another predictable value), as is the case for
- calloc().
-
- VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a
- heap block -- that will be used by the client program -- is allocated.
- It's best to put it at the outermost level of the allocator if possible;
- for example, if you have a function my_alloc() which calls
- internal_alloc(), and the client request is put inside internal_alloc(),
- stack traces relating to the heap block will contain entries for both
- my_alloc() and internal_alloc(), which is probably not what you want.
-
- For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out
- custom blocks from within a heap block, B, that has been allocated with
- malloc/calloc/new/etc, then block B will be *ignored* during leak-checking
- -- the custom blocks will take precedence.
-
- VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For
- Memcheck, it does two things:
-
- - It records that the block has been deallocated. This assumes that the
- block was annotated as having been allocated via
- VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued.
-
- - It marks the block as being unaddressable.
-
- VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a
- heap block is deallocated.
-
- In many cases, these two client requests will not be enough to get your
- allocator working well with Memcheck. More specifically, if your allocator
- writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call
- will be necessary to mark the memory as addressable just before the zeroing
- occurs, otherwise you'll get a lot of invalid write errors. For example,
- you'll need to do this if your allocator recycles freed blocks, but it
- zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK).
- Alternatively, if your allocator reuses freed blocks for allocator-internal
- data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary.
-
- Really, what's happening is a blurring of the lines between the client
- program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the
- memory should be considered unaddressable to the client program, but the
- allocator knows more than the rest of the client program and so may be able
- to safely access it. Extra client requests are necessary for Valgrind to
- understand the distinction between the allocator and the rest of the
- program.
-
- Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it
- has to be emulated with MALLOCLIKE/FREELIKE and memory copying.
-
- Ignored if addr == 0.
-*/
-#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
- {unsigned int __unused _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MALLOCLIKE_BLOCK, \
- addr, sizeB, rzB, is_zeroed, 0); \
- }
-
-/* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details.
- Ignored if addr == 0.
-*/
-#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
- {unsigned int __unused _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__FREELIKE_BLOCK, \
- addr, rzB, 0, 0, 0); \
- }
-
-/* Create a memory pool. */
-#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__CREATE_MEMPOOL, \
- pool, rzB, is_zeroed, 0, 0); \
- }
-
-/* Destroy a memory pool. */
-#define VALGRIND_DESTROY_MEMPOOL(pool) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__DESTROY_MEMPOOL, \
- pool, 0, 0, 0, 0); \
- }
-
-/* Associate a piece of memory with a memory pool. */
-#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_ALLOC, \
- pool, addr, size, 0, 0); \
- }
-
-/* Disassociate a piece of memory from a memory pool. */
-#define VALGRIND_MEMPOOL_FREE(pool, addr) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_FREE, \
- pool, addr, 0, 0, 0); \
- }
-
-/* Disassociate any pieces outside a particular range. */
-#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_TRIM, \
- pool, addr, size, 0, 0); \
- }
-
-/* Resize and/or move a piece associated with a memory pool. */
-#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MOVE_MEMPOOL, \
- poolA, poolB, 0, 0, 0); \
- }
-
-/* Resize and/or move a piece associated with a memory pool. */
-#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_CHANGE, \
- pool, addrA, addrB, size, 0); \
- }
-
-/* Return 1 if a mempool exists, else 0. */
-#define VALGRIND_MEMPOOL_EXISTS(pool) \
- __extension__ \
- ({unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__MEMPOOL_EXISTS, \
- pool, 0, 0, 0, 0); \
- _qzz_res; \
- })
-
-/* Mark a piece of memory as being a stack. Returns a stack id. */
-#define VALGRIND_STACK_REGISTER(start, end) \
- __extension__ \
- ({unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__STACK_REGISTER, \
- start, end, 0, 0, 0); \
- _qzz_res; \
- })
-
-/* Unmark the piece of memory associated with a stack id as being a
- stack. */
-#define VALGRIND_STACK_DEREGISTER(id) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__STACK_DEREGISTER, \
- id, 0, 0, 0, 0); \
- }
-
-/* Change the start and end address of the stack id. */
-#define VALGRIND_STACK_CHANGE(id, start, end) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__STACK_CHANGE, \
- id, start, end, 0, 0); \
- }
-
-/* Load PDB debug info for Wine PE image_map. */
-#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
- {unsigned int _qzz_res; \
- VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
- VG_USERREQ__LOAD_PDB_DEBUGINFO, \
- fd, ptr, total_size, delta, 0); \
- }
-
-
-#undef PLAT_x86_linux
-#undef PLAT_amd64_linux
-#undef PLAT_ppc32_linux
-#undef PLAT_ppc64_linux
-#undef PLAT_arm_linux
-#undef PLAT_ppc32_aix5
-#undef PLAT_ppc64_aix5
-
-#endif /* __VALGRIND_H */
diff --git a/qemu/roms/ipxe/src/arch/x86/interface/efi/efi_entropy.c b/qemu/roms/ipxe/src/arch/x86/interface/efi/efi_entropy.c
new file mode 100644
index 000000000..a54bd12e6
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/x86/interface/efi/efi_entropy.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <errno.h>
+#include <ipxe/entropy.h>
+#include <ipxe/crc32.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/Protocol/Rng.h>
+
+/** @file
+ *
+ * EFI entropy source
+ *
+ */
+
+/** Random number generator protocol */
+static EFI_RNG_PROTOCOL *efirng;
+EFI_REQUEST_PROTOCOL ( EFI_RNG_PROTOCOL, &efirng );
+
+/** Minimum number of bytes to request from RNG
+ *
+ * The UEFI spec states (for no apparently good reason) that "When a
+ * Deterministic Random Bit Generator (DRBG) is used on the output of
+ * a (raw) entropy source, its security level must be at least 256
+ * bits." The EDK2 codebase (mis)interprets this to mean that the
+ * call to GetRNG() should fail if given a buffer less than 32 bytes.
+ *
+ * Incidentally, nothing in the EFI RNG protocol provides any way to
+ * report the actual amount of entropy returned by GetRNG().
+ */
+#define EFI_ENTROPY_RNG_LEN 32
+
+/** Time (in 100ns units) to delay waiting for timer tick
+ *
+ * In theory, UEFI allows us to specify a trigger time of zero to
+ * simply wait for the next timer tick. In practice, specifying zero
+ * seems to often return immediately, which produces almost no
+ * entropy. Specify a delay of 1000ns to try to force an existent
+ * delay.
+ */
+#define EFI_ENTROPY_TRIGGER_TIME 10
+
+/** Event used to wait for timer tick */
+static EFI_EVENT tick;
+
+/**
+ * Enable entropy gathering
+ *
+ * @ret rc Return status code
+ */
+static int efi_entropy_enable ( void ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_STATUS efirc;
+ int rc;
+
+ DBGC ( &tick, "ENTROPY %s RNG protocol\n",
+ ( efirng ? "has" : "has no" ) );
+
+ /* Create timer tick event */
+ if ( ( efirc = bs->CreateEvent ( EVT_TIMER, TPL_NOTIFY, NULL, NULL,
+ &tick ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( &tick, "ENTROPY could not create event: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Disable entropy gathering
+ *
+ */
+static void efi_entropy_disable ( void ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+
+ /* Close timer tick event */
+ bs->CloseEvent ( tick );
+}
+
+/**
+ * Wait for a timer tick
+ *
+ * @ret low TSC low-order bits, or negative error
+ */
+static int efi_entropy_tick ( void ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ UINTN index;
+ uint16_t low;
+ uint32_t discard_d;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Wait for next timer tick */
+ if ( ( efirc = bs->SetTimer ( tick, TimerRelative,
+ EFI_ENTROPY_TRIGGER_TIME ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( &tick, "ENTROPY could not set timer: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+ if ( ( efirc = bs->WaitForEvent ( 1, &tick, &index ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( &tick, "ENTROPY could not wait for timer tick: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Get current TSC low-order bits */
+ __asm__ __volatile__ ( "rdtsc" : "=a" ( low ), "=d" ( discard_d ) );
+
+ return low;
+}
+
+/**
+ * Get noise sample from timer ticks
+ *
+ * @ret noise Noise sample
+ * @ret rc Return status code
+ */
+static int efi_get_noise_ticks ( noise_sample_t *noise ) {
+ int before;
+ int after;
+ int rc;
+
+ /* Wait for a timer tick */
+ before = efi_entropy_tick();
+ if ( before < 0 ) {
+ rc = before;
+ return rc;
+ }
+
+ /* Wait for another timer tick */
+ after = efi_entropy_tick();
+ if ( after < 0 ) {
+ rc = after;
+ return rc;
+ }
+
+ /* Use TSC delta as noise sample */
+ *noise = ( after - before );
+
+ return 0;
+}
+
+/**
+ * Get noise sample from RNG protocol
+ *
+ * @ret noise Noise sample
+ * @ret rc Return status code
+ */
+static int efi_get_noise_rng ( noise_sample_t *noise ) {
+ uint8_t buf[EFI_ENTROPY_RNG_LEN];
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Fail if we have no EFI RNG protocol */
+ if ( ! efirng )
+ return -ENOTSUP;
+
+ /* Get the minimum allowed number of random bytes */
+ if ( ( efirc = efirng->GetRNG ( efirng, NULL, EFI_ENTROPY_RNG_LEN,
+ buf ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( &tick, "ENTROPY could not read from RNG: %s\n",
+ strerror ( rc ) );
+ return rc;
+ }
+
+ /* Reduce random bytes to a single noise sample. This seems
+ * like overkill, but we have no way of knowing how much
+ * entropy is actually present in the bytes returned by the
+ * RNG protocol.
+ */
+ *noise = crc32_le ( 0, buf, sizeof ( buf ) );
+
+ return 0;
+}
+
+/**
+ * Get noise sample
+ *
+ * @ret noise Noise sample
+ * @ret rc Return status code
+ */
+static int efi_get_noise ( noise_sample_t *noise ) {
+ int rc;
+
+ /* Try RNG first, falling back to timer ticks */
+ if ( ( ( rc = efi_get_noise_rng ( noise ) ) != 0 ) &&
+ ( ( rc = efi_get_noise_ticks ( noise ) ) != 0 ) )
+ return rc;
+
+ return 0;
+}
+
+PROVIDE_ENTROPY_INLINE ( efi, min_entropy_per_sample );
+PROVIDE_ENTROPY ( efi, entropy_enable, efi_entropy_enable );
+PROVIDE_ENTROPY ( efi, entropy_disable, efi_entropy_disable );
+PROVIDE_ENTROPY ( efi, get_noise, efi_get_noise );
diff --git a/qemu/roms/ipxe/src/arch/x86/interface/efi/efix86_nap.c b/qemu/roms/ipxe/src/arch/x86/interface/efi/efix86_nap.c
index b05421fab..3ebf0bd68 100644
--- a/qemu/roms/ipxe/src/arch/x86/interface/efi/efix86_nap.c
+++ b/qemu/roms/ipxe/src/arch/x86/interface/efi/efix86_nap.c
@@ -15,9 +15,13 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/nap.h>
#include <ipxe/efi/efi.h>
diff --git a/qemu/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c b/qemu/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c
index 3daefd00a..4fbb19ff7 100644
--- a/qemu/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c
+++ b/qemu/roms/ipxe/src/arch/x86/prefix/efidrvprefix.c
@@ -21,7 +21,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <stdlib.h>
#include <ipxe/init.h>
+#include <ipxe/device.h>
#include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_driver.h>
/**
* EFI entry point
@@ -44,3 +46,36 @@ EFI_STATUS EFIAPI _efidrv_start ( EFI_HANDLE image_handle,
return 0;
}
+
+/**
+ * Probe EFI root bus
+ *
+ * @v rootdev EFI root device
+ */
+static int efi_probe ( struct root_device *rootdev __unused ) {
+
+ /* Do nothing */
+ return 0;
+}
+
+/**
+ * Remove EFI root bus
+ *
+ * @v rootdev EFI root device
+ */
+static void efi_remove ( struct root_device *rootdev __unused ) {
+
+ efi_driver_disconnect_all();
+}
+
+/** EFI root device driver */
+static struct root_driver efi_root_driver = {
+ .probe = efi_probe,
+ .remove = efi_remove,
+};
+
+/** EFI root device */
+struct root_device efi_root_device __root_device = {
+ .dev = { .name = "EFI" },
+ .driver = &efi_root_driver,
+};
diff --git a/qemu/roms/ipxe/src/arch/x86/prefix/efiprefix.c b/qemu/roms/ipxe/src/arch/x86/prefix/efiprefix.c
index b0bf99c65..18b931e68 100644
--- a/qemu/roms/ipxe/src/arch/x86/prefix/efiprefix.c
+++ b/qemu/roms/ipxe/src/arch/x86/prefix/efiprefix.c
@@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/efi/efi_driver.h>
#include <ipxe/efi/efi_snp.h>
#include <ipxe/efi/efi_autoboot.h>
+#include <ipxe/efi/efi_watchdog.h>
/**
* EFI entry point
@@ -49,6 +50,9 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle,
/* Claim SNP devices for use by iPXE */
efi_snp_claim();
+ /* Start watchdog holdoff timer */
+ efi_watchdog_start();
+
/* Call to main() */
if ( ( rc = main() ) != 0 ) {
efirc = EFIRC ( rc );
@@ -56,6 +60,7 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle,
}
err_main:
+ efi_watchdog_stop();
efi_snp_release();
efi_loaded_image->Unload ( image_handle );
efi_driver_reconnect_all();
diff --git a/qemu/roms/ipxe/src/arch/x86_64/Makefile b/qemu/roms/ipxe/src/arch/x86_64/Makefile
index b687f3407..48c0aa1af 100644
--- a/qemu/roms/ipxe/src/arch/x86_64/Makefile
+++ b/qemu/roms/ipxe/src/arch/x86_64/Makefile
@@ -40,6 +40,7 @@ endif
# x86_64-specific directories containing source files
#
+SRCDIRS += arch/x86_64/core
SRCDIRS += arch/x86_64/prefix
# Include common x86 Makefile
diff --git a/qemu/roms/ipxe/src/arch/x86_64/core/setjmp.S b/qemu/roms/ipxe/src/arch/x86_64/core/setjmp.S
new file mode 100644
index 000000000..e43200d7b
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/x86_64/core/setjmp.S
@@ -0,0 +1,65 @@
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+
+ .text
+ .code64
+
+ /* Must match jmp_buf structure layout */
+ .struct 0
+env_retaddr: .quad 0
+env_stack: .quad 0
+env_rbx: .quad 0
+env_rbp: .quad 0
+env_r12: .quad 0
+env_r13: .quad 0
+env_r14: .quad 0
+env_r15: .quad 0
+ .previous
+
+/*
+ * Save stack context for non-local goto
+ */
+ .globl setjmp
+setjmp:
+ /* Save return address */
+ movq 0(%rsp), %rax
+ movq %rax, env_retaddr(%rdi)
+ /* Save stack pointer */
+ movq %rsp, env_stack(%rdi)
+ /* Save other registers */
+ movq %rbx, env_rbx(%rdi)
+ movq %rbp, env_rbp(%rdi)
+ movq %r12, env_r12(%rdi)
+ movq %r13, env_r13(%rdi)
+ movq %r14, env_r14(%rdi)
+ movq %r15, env_r15(%rdi)
+ /* Return 0 when returning as setjmp() */
+ xorq %rax, %rax
+ ret
+ .size setjmp, . - setjmp
+
+/*
+ * Non-local jump to a saved stack context
+ */
+ .globl longjmp
+longjmp:
+ /* Get result in %rax */
+ movq %rsi, %rax
+ /* Force result to non-zero */
+ testq %rax, %rax
+ jnz 1f
+ incq %rax
+1: /* Restore stack pointer */
+ movq env_stack(%rdi), %rsp
+ /* Restore other registers */
+ movq env_rbx(%rdi), %rbx
+ movq env_rbp(%rdi), %rbp
+ movq env_r12(%rdi), %r12
+ movq env_r13(%rdi), %r13
+ movq env_r14(%rdi), %r14
+ movq env_r15(%rdi), %r15
+ /* Replace return address on the new stack */
+ popq %rcx /* discard */
+ pushq env_retaddr(%rdi)
+ /* Return to setjmp() caller */
+ ret
+ .size longjmp, . - longjmp
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/bits/byteswap.h b/qemu/roms/ipxe/src/arch/x86_64/include/bits/byteswap.h
index 2e472d98a..d8c5098ef 100644
--- a/qemu/roms/ipxe/src/arch/x86_64/include/bits/byteswap.h
+++ b/qemu/roms/ipxe/src/arch/x86_64/include/bits/byteswap.h
@@ -9,7 +9,7 @@
#include <stdint.h>
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
static inline __attribute__ (( always_inline, const )) uint16_t
__bswap_variable_16 ( uint16_t x ) {
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/bits/compiler.h b/qemu/roms/ipxe/src/arch/x86_64/include/bits/compiler.h
index 51a7eaae2..f70b2e517 100644
--- a/qemu/roms/ipxe/src/arch/x86_64/include/bits/compiler.h
+++ b/qemu/roms/ipxe/src/arch/x86_64/include/bits/compiler.h
@@ -1,6 +1,9 @@
#ifndef _BITS_COMPILER_H
#define _BITS_COMPILER_H
+/** Dummy relocation type */
+#define RELOC_TYPE_NONE R_X86_64_NONE
+
#ifndef ASSEMBLY
/** Declare a function with standard calling conventions */
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/bits/endian.h b/qemu/roms/ipxe/src/arch/x86_64/include/bits/endian.h
deleted file mode 100644
index 413e702db..000000000
--- a/qemu/roms/ipxe/src/arch/x86_64/include/bits/endian.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef ETHERBOOT_BITS_ENDIAN_H
-#define ETHERBOOT_BITS_ENDIAN_H
-
-#define __BYTE_ORDER __LITTLE_ENDIAN
-
-#endif /* ETHERBOOT_BITS_ENDIAN_H */
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/bits/entropy.h b/qemu/roms/ipxe/src/arch/x86_64/include/bits/entropy.h
index 9c64c833b..a9b3bc10e 100644
--- a/qemu/roms/ipxe/src/arch/x86_64/include/bits/entropy.h
+++ b/qemu/roms/ipxe/src/arch/x86_64/include/bits/entropy.h
@@ -7,6 +7,6 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_ENTROPY_H */
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/bits/hyperv.h b/qemu/roms/ipxe/src/arch/x86_64/include/bits/hyperv.h
new file mode 100644
index 000000000..845c182f7
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/x86_64/include/bits/hyperv.h
@@ -0,0 +1,75 @@
+#ifndef _BITS_HYPERV_H
+#define _BITS_HYPERV_H
+
+/** @file
+ *
+ * Hyper-V interface
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stddef.h>
+#include <stdint.h>
+#include <ipxe/io.h>
+
+/**
+ * Issue hypercall
+ *
+ * @v hv Hyper-V hypervisor
+ * @v code Call code
+ * @v in Input parameters
+ * @v out Output parameters
+ * @ret status Status code
+ */
+static inline __attribute__ (( always_inline )) int
+hv_call ( struct hv_hypervisor *hv, unsigned int code, const void *in,
+ void *out ) {
+ void *hypercall = hv->hypercall;
+ register uint64_t rcx asm ( "rcx" );
+ register uint64_t rdx asm ( "rdx" );
+ register uint64_t r8 asm ( "r8" );
+ uint64_t in_phys;
+ uint64_t out_phys;
+ uint16_t result;
+
+ in_phys = ( ( __builtin_constant_p ( in ) && ( in == NULL ) )
+ ? 0 : virt_to_phys ( in ) );
+ out_phys = ( ( __builtin_constant_p ( out ) && ( out == NULL ) )
+ ? 0 : virt_to_phys ( out ) );
+ rcx = code;
+ rdx = in_phys;
+ r8 = out_phys;
+ __asm__ __volatile__ ( "call *%4"
+ : "=a" ( result ), "+r" ( rcx ), "+r" ( rdx ),
+ "+r" ( r8 )
+ : "m" ( hypercall )
+ : "r9", "r10", "r11", "xmm0", "xmm1", "xmm2",
+ "xmm3", "xmm4", "xmm5" );
+ return result;
+}
+
+/**
+ * Set bit atomically
+ *
+ * @v bits Bit field
+ * @v bit Bit to set
+ */
+static inline __attribute__ (( always_inline )) void
+hv_set_bit ( void *bits, unsigned int bit ) {
+ struct {
+ uint64_t qword[ ( bit / 64 ) + 1 ];
+ } *qwords = bits;
+
+ /* Set bit using "lock bts". Inform compiler that any memory
+ * from the start of the bit field up to and including the
+ * qword containing this bit may be modified. (This is
+ * overkill but shouldn't matter in practice since we're
+ * unlikely to subsequently read other bits from the same bit
+ * field.)
+ */
+ __asm__ __volatile__ ( "lock bts %1, %0"
+ : "+m" ( *qwords ) : "Ir" ( bit ) );
+}
+
+#endif /* _BITS_HYPERV_H */
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/bits/profile.h b/qemu/roms/ipxe/src/arch/x86_64/include/bits/profile.h
index 6fc16d84b..b7c74fbe7 100644
--- a/qemu/roms/ipxe/src/arch/x86_64/include/bits/profile.h
+++ b/qemu/roms/ipxe/src/arch/x86_64/include/bits/profile.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <stdint.h>
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/bits/reboot.h b/qemu/roms/ipxe/src/arch/x86_64/include/bits/reboot.h
index f1bce0540..f9bcd6a7b 100644
--- a/qemu/roms/ipxe/src/arch/x86_64/include/bits/reboot.h
+++ b/qemu/roms/ipxe/src/arch/x86_64/include/bits/reboot.h
@@ -7,6 +7,6 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_REBOOT_H */
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/bits/sanboot.h b/qemu/roms/ipxe/src/arch/x86_64/include/bits/sanboot.h
index d33d03cbe..dcab830f6 100644
--- a/qemu/roms/ipxe/src/arch/x86_64/include/bits/sanboot.h
+++ b/qemu/roms/ipxe/src/arch/x86_64/include/bits/sanboot.h
@@ -7,6 +7,6 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_SANBOOT_H */
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/bits/strings.h b/qemu/roms/ipxe/src/arch/x86_64/include/bits/strings.h
index 6ee99a500..3b7911f3b 100644
--- a/qemu/roms/ipxe/src/arch/x86_64/include/bits/strings.h
+++ b/qemu/roms/ipxe/src/arch/x86_64/include/bits/strings.h
@@ -1,7 +1,43 @@
#ifndef _BITS_STRINGS_H
#define _BITS_STRINGS_H
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/**
+ * Find first (i.e. least significant) set bit
+ *
+ * @v value Value
+ * @ret lsb Least significant bit set in value (LSB=1), or zero
+ */
+static inline __attribute__ (( always_inline )) int __ffsll ( long long value ){
+ long long lsb_minus_one;
+
+ /* If the input value is zero, the BSF instruction returns
+ * ZF=0 and leaves an undefined value in the output register.
+ * Perform this check in C rather than asm so that it can be
+ * omitted in cases where the compiler is able to prove that
+ * the input is non-zero.
+ */
+ if ( value ) {
+ __asm__ ( "bsfq %1, %0"
+ : "=r" ( lsb_minus_one )
+ : "rm" ( value ) );
+ return ( lsb_minus_one + 1 );
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * Find first (i.e. least significant) set bit
+ *
+ * @v value Value
+ * @ret lsb Least significant bit set in value (LSB=1), or zero
+ */
+static inline __attribute__ (( always_inline )) int __ffsl ( long value ) {
+
+ return __ffsll ( value );
+}
/**
* Find last (i.e. most significant) set bit
@@ -13,7 +49,7 @@ static inline __attribute__ (( always_inline )) int __flsll ( long long value ){
long long msb_minus_one;
/* If the input value is zero, the BSR instruction returns
- * ZF=1 and leaves an undefined value in the output register.
+ * ZF=0 and leaves an undefined value in the output register.
* Perform this check in C rather than asm so that it can be
* omitted in cases where the compiler is able to prove that
* the input is non-zero.
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/bits/time.h b/qemu/roms/ipxe/src/arch/x86_64/include/bits/time.h
index 59b355359..aa74fac8c 100644
--- a/qemu/roms/ipxe/src/arch/x86_64/include/bits/time.h
+++ b/qemu/roms/ipxe/src/arch/x86_64/include/bits/time.h
@@ -7,6 +7,6 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#endif /* _BITS_TIME_H */
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h b/qemu/roms/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h
index 9a4790fdc..6511c1ad3 100644
--- a/qemu/roms/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h
+++ b/qemu/roms/ipxe/src/arch/x86_64/include/efi/ipxe/dhcp_arch.h
@@ -4,7 +4,7 @@
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
+ * License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -13,7 +13,12 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
*/
#ifndef _DHCP_ARCH_H
@@ -24,7 +29,7 @@
* Architecture-specific DHCP options
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/dhcp.h>
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/ipxe/msr.h b/qemu/roms/ipxe/src/arch/x86_64/include/ipxe/msr.h
index a5816ac35..316243b69 100644
--- a/qemu/roms/ipxe/src/arch/x86_64/include/ipxe/msr.h
+++ b/qemu/roms/ipxe/src/arch/x86_64/include/ipxe/msr.h
@@ -7,7 +7,7 @@
*
*/
-FILE_LICENCE ( GPL2_OR_LATER );
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/**
* Read model-specific register
diff --git a/qemu/roms/ipxe/src/arch/x86_64/include/setjmp.h b/qemu/roms/ipxe/src/arch/x86_64/include/setjmp.h
new file mode 100644
index 000000000..69835d9fa
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/x86_64/include/setjmp.h
@@ -0,0 +1,34 @@
+#ifndef _SETJMP_H
+#define _SETJMP_H
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stdint.h>
+
+/** A jump buffer */
+typedef struct {
+ /** Saved return address */
+ uint64_t retaddr;
+ /** Saved stack pointer */
+ uint64_t stack;
+ /** Saved %rbx */
+ uint64_t rbx;
+ /** Saved %rbp */
+ uint64_t rbp;
+ /** Saved %r12 */
+ uint64_t r12;
+ /** Saved %r13 */
+ uint64_t r13;
+ /** Saved %r14 */
+ uint64_t r14;
+ /** Saved %r15 */
+ uint64_t r15;
+} jmp_buf[1];
+
+extern int __asmcall __attribute__ (( returns_twice ))
+setjmp ( jmp_buf env );
+
+extern void __asmcall __attribute__ (( noreturn ))
+longjmp ( jmp_buf env, int val );
+
+#endif /* _SETJMP_H */