summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.inc12
-rw-r--r--ObsoleteFiles.inc2
-rw-r--r--contrib/elftoolchain/addr2line/addr2line.c8
-rw-r--r--contrib/elftoolchain/addr2line/os.NetBSD.mk2
-rw-r--r--contrib/elftoolchain/ar/ar.c4
-rw-r--r--contrib/elftoolchain/brandelf/brandelf.c4
-rw-r--r--contrib/elftoolchain/common/elfdefinitions.h139
-rwxr-xr-xcontrib/elftoolchain/common/native-elf-format4
-rw-r--r--contrib/elftoolchain/cxxfilt/cxxfilt.c21
-rw-r--r--contrib/elftoolchain/elfcopy/Makefile23
-rw-r--r--contrib/elftoolchain/elfcopy/archive.c6
-rw-r--r--contrib/elftoolchain/elfcopy/elfcopy.119
-rw-r--r--contrib/elftoolchain/elfcopy/elfcopy.h3
-rw-r--r--contrib/elftoolchain/elfcopy/main.c20
-rw-r--r--contrib/elftoolchain/elfcopy/pe.c233
-rw-r--r--contrib/elftoolchain/elfcopy/sections.c107
-rw-r--r--contrib/elftoolchain/elfcopy/segments.c18
-rw-r--r--contrib/elftoolchain/elfcopy/symbols.c126
-rw-r--r--contrib/elftoolchain/elfdump/elfdump.c370
-rw-r--r--contrib/elftoolchain/elfdump/os.NetBSD.mk2
-rw-r--r--contrib/elftoolchain/libdwarf/_libdwarf.h10
-rw-r--r--contrib/elftoolchain/libdwarf/dwarf.36
-rw-r--r--contrib/elftoolchain/libdwarf/dwarf_str.c8
-rw-r--r--contrib/elftoolchain/libdwarf/libdwarf.h4
-rw-r--r--contrib/elftoolchain/libdwarf/libdwarf_rw.c14
-rw-r--r--contrib/elftoolchain/libdwarf/os.NetBSD.mk2
-rw-r--r--contrib/elftoolchain/libelf/_libelf_config.h2
-rw-r--r--contrib/elftoolchain/libelftc/Makefile13
-rw-r--r--contrib/elftoolchain/libelftc/elftc_bfd_find_target.310
-rw-r--r--contrib/elftoolchain/libelftc/elftc_copyfile.c24
-rw-r--r--contrib/elftoolchain/libelftc/elftc_demangle.c10
-rw-r--r--contrib/elftoolchain/libelftc/elftc_symbol_table_create.3529
-rw-r--r--contrib/elftoolchain/libelftc/libelftc.h6
-rw-r--r--contrib/elftoolchain/libelftc/libelftc_bfdtarget.c26
-rw-r--r--contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c22
-rwxr-xr-xcontrib/elftoolchain/libelftc/make-toolchain-version4
-rw-r--r--contrib/elftoolchain/libelftc/os.NetBSD.mk2
-rw-r--r--contrib/elftoolchain/libpe/Makefile32
-rw-r--r--contrib/elftoolchain/libpe/_libpe.h213
-rw-r--r--contrib/elftoolchain/libpe/libpe.h121
-rw-r--r--contrib/elftoolchain/libpe/libpe_buffer.c185
-rw-r--r--contrib/elftoolchain/libpe/libpe_coff.c535
-rw-r--r--contrib/elftoolchain/libpe/libpe_dos.c403
-rw-r--r--contrib/elftoolchain/libpe/libpe_init.c145
-rw-r--r--contrib/elftoolchain/libpe/libpe_rich.c128
-rw-r--r--contrib/elftoolchain/libpe/libpe_section.c518
-rw-r--r--contrib/elftoolchain/libpe/libpe_utils.c69
-rw-r--r--contrib/elftoolchain/libpe/os.Linux.mk6
-rw-r--r--contrib/elftoolchain/libpe/os.NetBSD.mk2
-rw-r--r--contrib/elftoolchain/libpe/pe.h292
-rw-r--r--contrib/elftoolchain/libpe/pe_buffer.c100
-rw-r--r--contrib/elftoolchain/libpe/pe_cntl.c62
-rw-r--r--contrib/elftoolchain/libpe/pe_coff.c157
-rw-r--r--contrib/elftoolchain/libpe/pe_dos.c119
-rw-r--r--contrib/elftoolchain/libpe/pe_flag.c187
-rw-r--r--contrib/elftoolchain/libpe/pe_init.c95
-rw-r--r--contrib/elftoolchain/libpe/pe_rich.c107
-rw-r--r--contrib/elftoolchain/libpe/pe_section.c213
-rw-r--r--contrib/elftoolchain/libpe/pe_symtab.c86
-rw-r--r--contrib/elftoolchain/libpe/pe_update.c86
-rw-r--r--contrib/elftoolchain/nm/os.NetBSD.mk2
-rw-r--r--contrib/elftoolchain/readelf/os.NetBSD.mk2
-rw-r--r--contrib/elftoolchain/readelf/readelf.c78
-rw-r--r--contrib/elftoolchain/size/os.NetBSD.mk2
-rw-r--r--contrib/elftoolchain/strings/os.NetBSD.mk2
-rw-r--r--contrib/elftoolchain/strings/strings.17
-rw-r--r--contrib/elftoolchain/strings/strings.c12
-rw-r--r--contrib/unbound/Makefile.in9
-rw-r--r--contrib/unbound/doc/example.conf6
-rw-r--r--contrib/unbound/doc/example.conf.in6
-rw-r--r--contrib/unbound/doc/unbound.conf.55
-rw-r--r--contrib/unbound/doc/unbound.conf.5.in5
-rw-r--r--contrib/unbound/services/localzone.c114
-rw-r--r--contrib/unbound/util/as112.c143
-rw-r--r--contrib/unbound/util/as112.h57
-rw-r--r--contrib/unbound/util/config_file.c3
-rw-r--r--contrib/unbound/util/config_file.h4
-rw-r--r--contrib/unbound/util/configlexer.lex1
-rw-r--r--contrib/unbound/util/configparser.y16
-rw-r--r--contrib/unbound/validator/val_anchor.c11
-rw-r--r--etc/defaults/rc.conf1
-rwxr-xr-xetc/rc.d/jail29
-rwxr-xr-xetc/rc.d/ntpd8
-rw-r--r--include/signal.h5
-rw-r--r--lib/Makefile2
-rw-r--r--lib/libc/stdio/fgetln.35
-rw-r--r--lib/libc/stdio/fgetln.c9
-rw-r--r--lib/libc/stdio/fputs.c3
-rw-r--r--lib/libc/sys/jail.21
-rw-r--r--lib/libelftc/elftc_version.c2
-rw-r--r--lib/libfetch/http.c1
-rw-r--r--lib/libpe/Makefile34
-rw-r--r--lib/libunbound/Makefile2
-rw-r--r--share/examples/jails/README8
-rw-r--r--share/examples/jails/VIMAGE59
-rwxr-xr-xshare/examples/jails/jib196
-rwxr-xr-xshare/examples/jails/jng228
-rw-r--r--share/man/man4/ds3231.413
-rw-r--r--share/man/man5/rc.conf.530
-rw-r--r--share/man/man8/uefi.850
-rw-r--r--share/mk/src.libnames.mk4
-rw-r--r--sys/arm/allwinner/a10_clk.c28
-rw-r--r--sys/arm/allwinner/a10_clk.h4
-rw-r--r--sys/arm/allwinner/a10_common.c2
-rw-r--r--sys/arm/allwinner/a10_dmac.c453
-rw-r--r--sys/arm/allwinner/a10_dmac.h158
-rw-r--r--sys/arm/allwinner/a10_ehci.c12
-rw-r--r--sys/arm/allwinner/a10_gpio.c12
-rw-r--r--sys/arm/allwinner/a10_mmc.c9
-rw-r--r--sys/arm/allwinner/a10_wdog.c2
-rw-r--r--sys/arm/allwinner/a20/a20_cpu_cfg.c3
-rw-r--r--sys/arm/allwinner/aintc.c11
-rw-r--r--sys/arm/allwinner/axp209.c182
-rw-r--r--sys/arm/allwinner/files.a101
-rw-r--r--sys/arm/allwinner/files.allwinner5
-rw-r--r--sys/arm/allwinner/if_emac.c2
-rw-r--r--sys/arm/allwinner/sunxi_dma_if.m98
-rw-r--r--sys/arm/allwinner/timer.c22
-rw-r--r--sys/arm/altera/socfpga/socfpga_common.c2
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_machdep.c2
-rw-r--r--sys/arm/annapurna/alpine/common.c2
-rw-r--r--sys/arm/arm/generic_timer.c7
-rw-r--r--sys/arm/arm/syscall.c11
-rw-r--r--sys/arm/at91/at91_common.c2
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_common.c2
-rw-r--r--sys/arm/conf/A10107
-rw-r--r--sys/arm/conf/A2012
-rw-r--r--sys/arm/conf/ALPINE1
-rw-r--r--sys/arm/conf/ARMADA38X2
-rw-r--r--sys/arm/conf/ARMADAXP1
-rw-r--r--sys/arm/conf/DB-78XXX1
-rw-r--r--sys/arm/conf/DB-88F5XXX1
-rw-r--r--sys/arm/conf/DB-88F6XXX1
-rw-r--r--sys/arm/conf/DOCKSTAR1
-rw-r--r--sys/arm/conf/DREAMPLUG-10011
-rw-r--r--sys/arm/conf/EXYNOS5.common2
-rw-r--r--sys/arm/conf/NOTES3
-rw-r--r--sys/arm/conf/ODROIDC11
-rw-r--r--sys/arm/conf/PANDABOARD4
-rw-r--r--sys/arm/conf/RK31882
-rw-r--r--sys/arm/conf/SOCKIT.common2
-rw-r--r--sys/arm/conf/VIRT2
-rw-r--r--sys/arm/conf/VSATV1021
-rw-r--r--sys/arm/conf/VYBRID2
-rw-r--r--sys/arm/conf/ZEDBOARD4
-rw-r--r--sys/arm/freescale/imx/imx_common.c2
-rw-r--r--sys/arm/freescale/vybrid/vf_common.c2
-rw-r--r--sys/arm/include/intr.h88
-rw-r--r--sys/arm/lpc/lpc_intc.c2
-rw-r--r--sys/arm/mv/files.mv2
-rw-r--r--sys/arm/mv/mv_common.c2
-rw-r--r--sys/arm/mv/twsi.c647
-rw-r--r--sys/arm/qemu/virt_common.c2
-rw-r--r--sys/arm/rockchip/rk30xx_common.c2
-rw-r--r--sys/arm/samsung/exynos/exynos5_common.c2
-rw-r--r--sys/arm/ti/omap4/files.omap41
-rw-r--r--sys/arm/ti/omap4/omap4_wugen.c228
-rw-r--r--sys/arm/versatile/versatile_common.c2
-rw-r--r--sys/arm/xilinx/zedboard/files.zedboard9
-rw-r--r--sys/arm/xilinx/zedboard/std.zedboard8
-rw-r--r--sys/arm/xilinx/zy7_machdep.c3
-rw-r--r--sys/arm64/arm64/disassem.c233
-rw-r--r--sys/arm64/arm64/gic.c23
-rw-r--r--sys/arm64/arm64/gic_v3.c37
-rw-r--r--sys/arm64/arm64/gic_v3_its.c209
-rw-r--r--sys/arm64/arm64/gic_v3_reg.h6
-rw-r--r--sys/arm64/arm64/gic_v3_var.h22
-rw-r--r--sys/arm64/arm64/intr_machdep.c153
-rw-r--r--sys/arm64/arm64/nexus.c16
-rw-r--r--sys/arm64/arm64/pic_if.m12
-rw-r--r--sys/arm64/arm64/swtch.S12
-rw-r--r--sys/arm64/include/armreg.h9
-rw-r--r--sys/arm64/include/intr.h1
-rw-r--r--sys/boot/fdt/dts/arm/bananapi.dts5
-rw-r--r--sys/boot/fdt/dts/arm/cubieboard2.dts76
-rw-r--r--sys/boot/fdt/dts/arm/olimex-a20-som-evb.dts40
-rw-r--r--sys/boot/fdt/dts/arm/olinuxino-lime.dts40
-rw-r--r--sys/boot/fdt/dts/arm/sun4i-a10.dtsi12
-rw-r--r--sys/boot/fdt/dts/arm/sun7i-a20.dtsi65
-rw-r--r--sys/boot/fdt/dts/riscv/qemu.dts92
-rw-r--r--sys/cam/ctl/ctl.c4
-rw-r--r--sys/conf/files.arm1
-rw-r--r--sys/conf/files.mips1
-rw-r--r--sys/dev/cxgb/cxgb_sge.c8
-rw-r--r--sys/dev/cxgbe/common/t4_msg.h1
-rw-r--r--sys/dev/cxgbe/t4_main.c2
-rw-r--r--sys/dev/cxgbe/t4_sge.c2
-rw-r--r--sys/dev/hwpmc/hwpmc_core.c36
-rw-r--r--sys/dev/hwpmc/hwpmc_core.h9
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c2
-rw-r--r--sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c2
-rw-r--r--sys/dev/iicbus/twsi/a10_twsi.c131
-rw-r--r--sys/dev/iicbus/twsi/mv_twsi.c251
-rw-r--r--sys/dev/iicbus/twsi/twsi.c481
-rw-r--r--sys/dev/iicbus/twsi/twsi.h67
-rw-r--r--sys/dev/ioat/ioat.c35
-rw-r--r--sys/dev/ioat/ioat_hw.h8
-rw-r--r--sys/dev/ioat/ioat_internal.h19
-rw-r--r--sys/dev/iscsi/icl.c34
-rw-r--r--sys/dev/iscsi/iscsi.h2
-rw-r--r--sys/dev/ntb/ntb_hw/ntb_hw.c526
-rw-r--r--sys/dev/ntb/ntb_hw/ntb_hw.h1
-rw-r--r--sys/dev/ntb/ntb_hw/ntb_regs.h1
-rw-r--r--sys/dev/nvme/nvme_ctrlr.c18
-rw-r--r--sys/dev/sfxge/common/efx.h8
-rw-r--r--sys/dev/sfxge/common/efx_mcdi.c212
-rw-r--r--sys/dev/sfxge/common/efx_mcdi.h8
-rw-r--r--sys/dev/sfxge/common/efx_phy.c32
-rw-r--r--sys/dev/sfxge/sfxge.c24
-rw-r--r--sys/dev/uart/uart_bus_fdt.c1
-rw-r--r--sys/dev/uart/uart_dev_lpc.c5
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c5
-rw-r--r--sys/dev/usb/controller/ehci_pci.c2
-rw-r--r--sys/dev/usb/net/if_smsc.c2
-rw-r--r--sys/dev/usb/wlan/if_rum.c6
-rw-r--r--sys/dev/usb/wlan/if_rumreg.h2
-rw-r--r--sys/dev/xen/blkfront/blkfront.c2
-rw-r--r--sys/dev/xen/netfront/netfront.c14
-rw-r--r--sys/fs/cd9660/cd9660_vfsops.c18
-rw-r--r--sys/fs/ext2fs/ext2_bmap.c4
-rw-r--r--sys/fs/ext2fs/ext2_extents.c61
-rw-r--r--sys/fs/ext2fs/ext2_extents.h2
-rw-r--r--sys/fs/ext2fs/ext2_vnops.c13
-rw-r--r--sys/fs/tmpfs/tmpfs_vnops.c5
-rw-r--r--sys/kern/kern_mbuf.c345
-rw-r--r--sys/kern/link_elf.c27
-rw-r--r--sys/kern/link_elf_obj.c57
-rw-r--r--sys/kern/subr_intr.c4
-rw-r--r--sys/kern/subr_turnstile.c9
-rw-r--r--sys/kern/uipc_mbuf.c285
-rw-r--r--sys/mips/conf/AR71XX_BASE2
-rw-r--r--sys/mips/conf/AR724X_BASE2
-rw-r--r--sys/mips/conf/AR91XX_BASE2
-rw-r--r--sys/mips/conf/QCA953X_BASE2
-rw-r--r--sys/mips/include/bus.h1
-rw-r--r--sys/mips/include/fdt.h2
-rw-r--r--sys/mips/include/intr.h67
-rw-r--r--sys/mips/include/smp.h5
-rw-r--r--sys/mips/include/ucontext.h10
-rw-r--r--sys/mips/mips/bus_space_fdt.c205
-rw-r--r--sys/mips/mips/bus_space_generic.c11
-rw-r--r--sys/mips/mips/exception.S10
-rw-r--r--sys/mips/mips/mips_pic.c514
-rw-r--r--sys/mips/mips/nexus.c116
-rw-r--r--sys/mips/mips/tick.c11
-rw-r--r--sys/modules/dtb/allwinner/Makefile4
-rw-r--r--sys/net/route.c14
-rw-r--r--sys/netinet/in_rmx.c3
-rw-r--r--sys/netinet/sctp_constants.h5
-rw-r--r--sys/netinet/sctp_sysctl.c8
-rw-r--r--sys/netinet/tcp_lro.c7
-rw-r--r--sys/netinet/tcp_pcap.c2
-rw-r--r--sys/netinet6/in6_rmx.c4
-rw-r--r--sys/netinet6/nd6.c10
-rw-r--r--sys/netinet6/nd6.h8
-rw-r--r--sys/netinet6/nd6_nbr.c8
-rw-r--r--sys/netinet6/nd6_rtr.c73
-rw-r--r--sys/netinet6/scope6.c2
-rw-r--r--sys/powerpc/booke/pmap.c64
-rw-r--r--sys/powerpc/booke/trap_subr.S13
-rw-r--r--sys/powerpc/include/pte.h46
-rw-r--r--sys/powerpc/include/ucontext.h10
-rw-r--r--sys/powerpc/powerpc/genassym.c8
-rw-r--r--sys/riscv/conf/GENERIC3
-rw-r--r--sys/riscv/conf/QEMU26
-rw-r--r--sys/riscv/conf/SPIKE26
-rw-r--r--sys/riscv/htif/htif.c5
-rw-r--r--sys/riscv/include/ucontext.h2
-rw-r--r--sys/sparc64/include/ucontext.h10
-rw-r--r--sys/sys/_ucontext.h52
-rw-r--r--sys/sys/intr.h130
-rw-r--r--sys/sys/mbuf.h148
-rw-r--r--sys/sys/pmc.h2
-rw-r--r--sys/sys/signal.h23
-rw-r--r--sys/sys/ucontext.h18
-rw-r--r--sys/x86/include/ucontext.h5
-rw-r--r--tests/sys/geom/class/gate/3_test.sh1
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc1
-rw-r--r--tools/build/options/WITHOUT_BINUTILS_BOOTSTRAP3
-rw-r--r--tools/build/options/WITHOUT_ELFTOOLCHAIN_BOOTSTRAP7
-rw-r--r--tools/build/options/WITH_BINUTILS3
-rw-r--r--tools/build/options/WITH_BINUTILS_BOOTSTRAP3
-rw-r--r--tools/build/options/WITH_GDB3
-rw-r--r--usr.bin/elfcopy/Makefile7
-rw-r--r--usr.bin/hexdump/display.c2
-rw-r--r--usr.bin/truss/amd64-linux32.c2
-rw-r--r--usr.bin/truss/i386-linux.c2
-rw-r--r--usr.sbin/ctld/login.c7
-rw-r--r--usr.sbin/jail/jail.81
-rw-r--r--usr.sbin/jail/jail.conf.51
-rw-r--r--usr.sbin/services_mkdb/services_mkdb.c2
-rw-r--r--usr.sbin/unbound/control/Makefile1
-rwxr-xr-xusr.sbin/unbound/local-setup/local-unbound-setup.sh26
293 files changed, 11338 insertions, 3317 deletions
diff --git a/Makefile.inc1 b/Makefile.inc1
index ffc4996..48a41e4 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -1804,6 +1804,7 @@ _binutils= gnu/usr.bin/binutils
.endif
.if ${MK_ELFTOOLCHAIN_BOOTSTRAP} != "no"
_elftctools= lib/libelftc \
+ lib/libpe \
usr.bin/elfcopy \
usr.bin/nm \
usr.bin/size \
@@ -1816,6 +1817,7 @@ _elftctools+= usr.bin/addr2line
# If cross-building with an external binutils we still need to build strip for
# the target (for at least crunchide).
_elftctools= lib/libelftc \
+ lib/libpe \
usr.bin/elfcopy
.endif
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index 2f2505a..a5a7e3c 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -38,6 +38,8 @@
# xargs -n1 | sort | uniq -d;
# done
+# 20160211: Remove obsolete unbound-control-setup
+OLD_FILES+=usr/sbin/unbound-control-setup
# 20160116: Update mandoc to cvs snapshot 20160116
OLD_FILES+=usr/share/mdocml/example.style.css
OLD_FILES+=usr/share/mdocml/style.css
diff --git a/contrib/elftoolchain/addr2line/addr2line.c b/contrib/elftoolchain/addr2line/addr2line.c
index 5310576..3cd8cb5 100644
--- a/contrib/elftoolchain/addr2line/addr2line.c
+++ b/contrib/elftoolchain/addr2line/addr2line.c
@@ -40,7 +40,7 @@
#include "uthash.h"
#include "_elftc.h"
-ELFTC_VCSID("$Id: addr2line.c 3264 2015-11-30 05:38:14Z kaiwang27 $");
+ELFTC_VCSID("$Id: addr2line.c 3273 2015-12-11 21:38:57Z kaiwang27 $");
struct Func {
char *name;
@@ -368,7 +368,8 @@ print_inlines(struct CU *cu, struct Func *f, Dwarf_Unsigned call_file,
printf("%s\n", f->name);
}
}
- (void) printf("%s:%ju\n", base ? basename(file) : file, call_line);
+ (void) printf("%s:%ju\n", base ? basename(file) : file,
+ (uintmax_t) call_line);
if (f->inlined_caller != NULL)
print_inlines(cu, f->inlined_caller, f->call_file,
@@ -562,7 +563,8 @@ out:
}
}
- (void) printf("%s:%ju\n", base ? basename(file) : file, lineno);
+ (void) printf("%s:%ju\n", base ? basename(file) : file,
+ (uintmax_t) lineno);
if (ret == DW_DLV_OK && inlines && cu != NULL &&
cu->srcfiles != NULL && f != NULL && f->inlined_caller != NULL)
diff --git a/contrib/elftoolchain/addr2line/os.NetBSD.mk b/contrib/elftoolchain/addr2line/os.NetBSD.mk
new file mode 100644
index 0000000..ae214e3
--- /dev/null
+++ b/contrib/elftoolchain/addr2line/os.NetBSD.mk
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
diff --git a/contrib/elftoolchain/ar/ar.c b/contrib/elftoolchain/ar/ar.c
index 62f0e55..1b60a12 100644
--- a/contrib/elftoolchain/ar/ar.c
+++ b/contrib/elftoolchain/ar/ar.c
@@ -72,7 +72,7 @@
#include "ar.h"
-ELFTC_VCSID("$Id: ar.c 3243 2015-08-31 19:28:45Z emaste $");
+ELFTC_VCSID("$Id: ar.c 3319 2016-01-13 21:37:53Z jkoshy $");
enum options
{
@@ -407,7 +407,7 @@ Usage: %s <command> [options] archive file...\n\
-F FORMAT | --flavor=FORMAT\n\
Create archives with the specified format.\n\
-S Do not generate an archive symbol table.\n\
- -U Use original metadata, for unique archive checksums.\n"
+ -U Use original metadata for archive members.\n"
static void
bsdar_usage(void)
diff --git a/contrib/elftoolchain/brandelf/brandelf.c b/contrib/elftoolchain/brandelf/brandelf.c
index cbe5d6c..22166f7 100644
--- a/contrib/elftoolchain/brandelf/brandelf.c
+++ b/contrib/elftoolchain/brandelf/brandelf.c
@@ -44,7 +44,7 @@
#include "_elftc.h"
-ELFTC_VCSID("$Id: brandelf.c 3234 2015-07-31 12:35:09Z emaste $");
+ELFTC_VCSID("$Id: brandelf.c 3354 2016-01-18 21:50:15Z jkoshy $");
static int elftype(const char *);
static const char *iselftype(int);
@@ -212,7 +212,7 @@ main(int argc, char **argv)
/*
* Update the ABI type.
*/
- ehdr.e_ident[EI_OSABI] = type;
+ ehdr.e_ident[EI_OSABI] = (unsigned char) type;
if (gelf_update_ehdr(elf, &ehdr) == 0) {
warnx("gelf_update_ehdr error: %s",
elf_errmsg(-1));
diff --git a/contrib/elftoolchain/common/elfdefinitions.h b/contrib/elftoolchain/common/elfdefinitions.h
index e953c92..fa6132d 100644
--- a/contrib/elftoolchain/common/elfdefinitions.h
+++ b/contrib/elftoolchain/common/elfdefinitions.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: elfdefinitions.h 3253 2015-10-10 18:31:33Z kaiwang27 $
+ * $Id: elfdefinitions.h 3392 2016-02-05 19:51:22Z emaste $
*/
/*
@@ -1228,6 +1228,7 @@ _ELF_DEFINE_STB(STB_GLOBAL, 1, \
_ELF_DEFINE_STB(STB_WEAK, 2, \
"visible across all object files but with low precedence") \
_ELF_DEFINE_STB(STB_LOOS, 10, "start of OS-specific range") \
+_ELF_DEFINE_STB(STB_GNU_UNIQUE, 10, "unique symbol (GNU)") \
_ELF_DEFINE_STB(STB_HIOS, 12, "end of OS-specific range") \
_ELF_DEFINE_STB(STB_LOPROC, 13, \
"start of processor-specific range") \
@@ -1259,6 +1260,7 @@ _ELF_DEFINE_STT(STT_LOPROC, 13, \
"start of processor-specific types") \
_ELF_DEFINE_STT(STT_ARM_TFUNC, 13, "Thumb function (GNU)") \
_ELF_DEFINE_STT(STT_ARM_16BIT, 15, "Thumb label (GNU)") \
+_ELF_DEFINE_STT(STT_SPARC_REGISTER, 13, "SPARC register information") \
_ELF_DEFINE_STT(STT_HIPROC, 15, \
"end of processor-specific types")
@@ -1395,7 +1397,7 @@ _ELF_DEFINE_RELOC(R_386_GOT32, 3) \
_ELF_DEFINE_RELOC(R_386_PLT32, 4) \
_ELF_DEFINE_RELOC(R_386_COPY, 5) \
_ELF_DEFINE_RELOC(R_386_GLOB_DAT, 6) \
-_ELF_DEFINE_RELOC(R_386_JMP_SLOT, 7) \
+_ELF_DEFINE_RELOC(R_386_JUMP_SLOT, 7) \
_ELF_DEFINE_RELOC(R_386_RELATIVE, 8) \
_ELF_DEFINE_RELOC(R_386_GOTOFF, 9) \
_ELF_DEFINE_RELOC(R_386_GOTPC, 10) \
@@ -1407,9 +1409,129 @@ _ELF_DEFINE_RELOC(R_386_PC8, 23)
/*
*/
-#define _ELF_DEFINE_AARCH64_RELOCATIONS() \
-_ELF_DEFINE_RELOC(R_AARCH64_ABS64, 257) \
-_ELF_DEFINE_RELOC(R_AARCH64_ABS32, 258) \
+#define _ELF_DEFINE_AARCH64_RELOCATIONS() \
+_ELF_DEFINE_RELOC(R_AARCH64_NONE, 0) \
+_ELF_DEFINE_RELOC(R_AARCH64_ABS64, 257) \
+_ELF_DEFINE_RELOC(R_AARCH64_ABS32, 258) \
+_ELF_DEFINE_RELOC(R_AARCH64_ABS16, 259) \
+_ELF_DEFINE_RELOC(R_AARCH64_PREL64, 260) \
+_ELF_DEFINE_RELOC(R_AARCH64_PREL32, 261) \
+_ELF_DEFINE_RELOC(R_AARCH64_PREL16, 262) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G0, 263) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G0_NC, 264) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G1, 265) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G1_NC, 266) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G2, 267) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G2_NC, 268) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_UABS_G3, 269) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_SABS_G0, 270) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_SABS_G1, 271) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_SABS_G2, 272) \
+_ELF_DEFINE_RELOC(R_AARCH64_LD_PREL_LO19, 273) \
+_ELF_DEFINE_RELOC(R_AARCH64_ADR_PREL_LO21, 274) \
+_ELF_DEFINE_RELOC(R_AARCH64_ADR_PREL_PG_HI21, 275) \
+_ELF_DEFINE_RELOC(R_AARCH64_ADR_PREL_PG_HI21_NC, 276) \
+_ELF_DEFINE_RELOC(R_AARCH64_ADD_ABS_LO12_NC, 277) \
+_ELF_DEFINE_RELOC(R_AARCH64_LDST8_ABS_LO12_NC, 278) \
+_ELF_DEFINE_RELOC(R_AARCH64_TSTBR14, 279) \
+_ELF_DEFINE_RELOC(R_AARCH64_CONDBR19, 280) \
+_ELF_DEFINE_RELOC(R_AARCH64_JUMP26, 282) \
+_ELF_DEFINE_RELOC(R_AARCH64_CALL26, 283) \
+_ELF_DEFINE_RELOC(R_AARCH64_LDST16_ABS_LO12_NC, 284) \
+_ELF_DEFINE_RELOC(R_AARCH64_LDST32_ABS_LO12_NC, 285) \
+_ELF_DEFINE_RELOC(R_AARCH64_LDST64_ABS_LO12_NC, 286) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G0, 287) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G0_NC, 288) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G1, 289) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G1_NC, 290) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G2, 291) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G2_NC, 292) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_PREL_G3, 293) \
+_ELF_DEFINE_RELOC(R_AARCH64_LDST128_ABS_LO12_NC, 299) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G0, 300) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G0_NC, 301) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G1, 302) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G1_NC, 303) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G2, 304) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G2_NC, 305) \
+_ELF_DEFINE_RELOC(R_AARCH64_MOVW_GOTOFF_G3, 306) \
+_ELF_DEFINE_RELOC(R_AARCH64_GOTREL64, 307) \
+_ELF_DEFINE_RELOC(R_AARCH64_GOTREL32, 308) \
+_ELF_DEFINE_RELOC(R_AARCH64_GOT_LD_PREL19, 309) \
+_ELF_DEFINE_RELOC(R_AARCH64_LD64_GOTOFF_LO15, 310) \
+_ELF_DEFINE_RELOC(R_AARCH64_ADR_GOT_PAGE, 311) \
+_ELF_DEFINE_RELOC(R_AARCH64_LD64_GOT_LO12_NC, 312) \
+_ELF_DEFINE_RELOC(R_AARCH64_LD64_GOTPAGE_LO15, 313) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_ADR_PREL21, 512) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_ADR_PAGE21, 513) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_ADD_LO12_NC, 514) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_MOVW_G1, 515) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSGD_MOVW_G0_NC, 516) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADR_PREL21, 517) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADR_PAGE21, 518) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADD_LO12_NC, 519) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_G1, 520) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_G0_NC, 521) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LD_PREL19, 522) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G2, 523) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1, 524) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC, 525) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0, 526) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC, 527) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_HI12, 529) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC, 530) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12, 531) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC, 532) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12, 533) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC, 534) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12, 535) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC, 536) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12, 537) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC, 538) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1, 539) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC, 540) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, 541) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, 542) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19, 543) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G2, 544) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1, 545) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC, 546) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0, 547) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC, 548) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_ADD_TPREL_HI12, 549) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12, 550) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, 551) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12, 552) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC, 553) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12, 554) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC, 555) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12, 556) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC, 557) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12, 558) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC, 559) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_LD_PREL19, 560) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADR_PREL21, 561) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADR_PAGE21, 562) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_LD64_LO12, 563) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADD_LO12, 564) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_OFF_G1, 565) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_OFF_G0_NC, 566) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_LDR, 567) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_ADD, 568) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC_CALL, 569) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12, 570) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC, 571) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12, 572) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC, 573) \
+_ELF_DEFINE_RELOC(R_AARCH64_COPY, 1024) \
+_ELF_DEFINE_RELOC(R_AARCH64_GLOB_DAT, 1025) \
+_ELF_DEFINE_RELOC(R_AARCH64_JUMP_SLOT, 1026) \
+_ELF_DEFINE_RELOC(R_AARCH64_RELATIVE, 1027) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLS_DTPREL64, 1028) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLS_DTPMOD64, 1029) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLS_TPREL64, 1030) \
+_ELF_DEFINE_RELOC(R_AARCH64_TLSDESC, 1031) \
+_ELF_DEFINE_RELOC(R_AARCH64_IRELATIVE, 1032)
/*
* These are the symbols used in the Sun ``Linkers and Loaders
@@ -1633,7 +1755,7 @@ _ELF_DEFINE_RELOC(R_IA_64_LTV32MSB, 0x74) \
_ELF_DEFINE_RELOC(R_IA_64_LTV32LSB, 0x75) \
_ELF_DEFINE_RELOC(R_IA_64_LTV64MSB, 0x76) \
_ELF_DEFINE_RELOC(R_IA_64_LTV64LSB, 0x77) \
-_ELF_DEFINE_RELOC(R_IA_64_PCREL21BIa, 0x79) \
+_ELF_DEFINE_RELOC(R_IA_64_PCREL21BI, 0x79) \
_ELF_DEFINE_RELOC(R_IA_64_PCREL22, 0x7A) \
_ELF_DEFINE_RELOC(R_IA_64_PCREL64I, 0x7B) \
_ELF_DEFINE_RELOC(R_IA_64_IPLTMSB, 0x80) \
@@ -1723,7 +1845,7 @@ _ELF_DEFINE_RELOC(R_PPC_REL32, 26) \
_ELF_DEFINE_RELOC(R_PPC_PLT32, 27) \
_ELF_DEFINE_RELOC(R_PPC_PLTREL32, 28) \
_ELF_DEFINE_RELOC(R_PPC_PLT16_LO, 29) \
-_ELF_DEFINE_RELOC(R_PPL_PLT16_HI, 30) \
+_ELF_DEFINE_RELOC(R_PPC_PLT16_HI, 30) \
_ELF_DEFINE_RELOC(R_PPC_PLT16_HA, 31) \
_ELF_DEFINE_RELOC(R_PPC_SDAREL16, 32) \
_ELF_DEFINE_RELOC(R_PPC_SECTOFF, 33) \
@@ -1926,7 +2048,7 @@ _ELF_DEFINE_RELOC(R_RISCV_SUB32, 39) \
_ELF_DEFINE_RELOC(R_RISCV_SUB64, 40) \
_ELF_DEFINE_RELOC(R_RISCV_GNU_VTINHERIT, 41) \
_ELF_DEFINE_RELOC(R_RISCV_GNU_VTENTRY, 42) \
-_ELF_DEFINE_RELOC(R_RISCV_ALIGN 43) \
+_ELF_DEFINE_RELOC(R_RISCV_ALIGN, 43) \
_ELF_DEFINE_RELOC(R_RISCV_RVC_BRANCH, 44) \
_ELF_DEFINE_RELOC(R_RISCV_RVC_JUMP, 45)
@@ -2042,6 +2164,7 @@ _ELF_DEFINE_IA64_RELOCATIONS() \
_ELF_DEFINE_MIPS_RELOCATIONS() \
_ELF_DEFINE_PPC32_RELOCATIONS() \
_ELF_DEFINE_PPC64_RELOCATIONS() \
+_ELF_DEFINE_RISCV_RELOCATIONS() \
_ELF_DEFINE_SPARC_RELOCATIONS() \
_ELF_DEFINE_X86_64_RELOCATIONS()
diff --git a/contrib/elftoolchain/common/native-elf-format b/contrib/elftoolchain/common/native-elf-format
index d36ab53..2bdd914 100755
--- a/contrib/elftoolchain/common/native-elf-format
+++ b/contrib/elftoolchain/common/native-elf-format
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# $Id: native-elf-format 3186 2015-04-16 22:16:40Z emaste $
+# $Id: native-elf-format 3293 2016-01-07 19:26:27Z emaste $
#
# Find the native ELF format for a host platform by compiling a
# test object and examining the resulting object.
@@ -33,6 +33,8 @@ $1 ~ "Data:" {
$1 ~ "Machine:" {
if (match($0, "Intel.*386")) {
elfarch = "EM_386";
+ } else if (match($0, "MIPS")) {
+ elfarch = "EM_MIPS";
} else if (match($0, ".*[xX]86-64")) {
elfarch = "EM_X86_64";
} else {
diff --git a/contrib/elftoolchain/cxxfilt/cxxfilt.c b/contrib/elftoolchain/cxxfilt/cxxfilt.c
index 4efa45b..9318c64 100644
--- a/contrib/elftoolchain/cxxfilt/cxxfilt.c
+++ b/contrib/elftoolchain/cxxfilt/cxxfilt.c
@@ -35,7 +35,7 @@
#include "_elftc.h"
-ELFTC_VCSID("$Id: cxxfilt.c 3174 2015-03-27 17:13:41Z emaste $");
+ELFTC_VCSID("$Id: cxxfilt.c 3356 2016-01-22 22:31:38Z jkoshy $");
#define STRBUFSZ 8192
@@ -112,11 +112,11 @@ find_format(const char *fstr)
}
static char *
-demangle(char *name, int strict, int *pos)
+demangle(char *name, int strict, size_t *pos)
{
static char dem[STRBUFSZ];
char nb[STRBUFSZ];
- int p, t;
+ size_t p, t;
if (stripus && *name == '_') {
strncpy(nb, name + 1, sizeof(nb) - 1);
@@ -128,10 +128,10 @@ demangle(char *name, int strict, int *pos)
nb[sizeof(nb) - 1] = '\0';
p = strlen(nb);
- if (p <= 0)
+ if (p == 0)
return NULL;
- while (elftc_demangle(nb, dem, sizeof(dem), format) < 0) {
+ while (elftc_demangle(nb, dem, sizeof(dem), (unsigned) format) < 0) {
if (!strict && p > 1) {
nb[--p] = '\0';
continue;
@@ -149,7 +149,8 @@ int
main(int argc, char **argv)
{
char *dem, buf[STRBUFSZ];
- int c, i, p, s, opt;
+ size_t i, p, s;
+ int c, n, opt;
while ((opt = getopt_long(argc, argv, "_nps:V", longopts, NULL)) !=
-1) {
@@ -182,9 +183,9 @@ main(int argc, char **argv)
argc -= optind;
if (*argv != NULL) {
- for (i = 0; i < argc; i++) {
- if ((dem = demangle(argv[i], 1, NULL)) == NULL)
- fprintf(stderr, "Failed: %s\n", argv[i]);
+ for (n = 0; n < argc; n++) {
+ if ((dem = demangle(argv[n], 1, NULL)) == NULL)
+ fprintf(stderr, "Failed: %s\n", argv[n]);
else
printf("%s\n", dem);
}
@@ -213,7 +214,7 @@ main(int argc, char **argv)
if ((size_t) p >= sizeof(buf) - 1)
warnx("buffer overflowed");
else
- buf[p++] = c;
+ buf[p++] = (char) c;
}
}
diff --git a/contrib/elftoolchain/elfcopy/Makefile b/contrib/elftoolchain/elfcopy/Makefile
index cb1a31b..8b208e0 100644
--- a/contrib/elftoolchain/elfcopy/Makefile
+++ b/contrib/elftoolchain/elfcopy/Makefile
@@ -1,10 +1,13 @@
-# $Id: Makefile 2290 2011-12-04 07:20:46Z jkoshy $
+# $Id: Makefile 3381 2016-01-30 19:39:47Z jkoshy $
TOP= ..
+.include "${TOP}/mk/elftoolchain.components.mk"
+
PROG= elfcopy
-SRCS= archive.c ascii.c binary.c main.c sections.c segments.c symbols.c
+SRCS= archive.c ascii.c binary.c main.c sections.c segments.c \
+ symbols.c
WARNS?= 5
@@ -15,14 +18,24 @@ LDADD= -lelf -lelftc
LDADD+= -larchive
.endif
+.if defined(WITH_PE) && ${WITH_PE:tl} == "yes"
+SRCS+= pe.c
+CFLAGS+= -DWITH_PE=1
+
+DPADD+= ${LIBPE}
+LDADD+= -lpe
+.endif
+
MAN= elfcopy.1 mcs.1 strip.1
+MLINKS= elfcopy.1 objcopy.1
NO_SHARED?= yes
-LINKS= ${BINDIR}/elfcopy ${BINDIR}/strip \
- ${BINDIR}/elfcopy ${BINDIR}/mcs
+LINKS= ${BINDIR}/elfcopy ${BINDIR}/mcs \
+ ${BINDIR}/elfcopy ${BINDIR}/objcopy \
+ ${BINDIR}/elfcopy ${BINDIR}/strip
-EXTRA_TARGETS= strip mcs
+EXTRA_TARGETS= mcs strip objcopy
CLEANFILES+= ${EXTRA_TARGETS}
diff --git a/contrib/elftoolchain/elfcopy/archive.c b/contrib/elftoolchain/elfcopy/archive.c
index 682a1df..97e2498 100644
--- a/contrib/elftoolchain/elfcopy/archive.c
+++ b/contrib/elftoolchain/elfcopy/archive.c
@@ -38,7 +38,7 @@
#include "elfcopy.h"
-ELFTC_VCSID("$Id: archive.c 3174 2015-03-27 17:13:41Z emaste $");
+ELFTC_VCSID("$Id: archive.c 3287 2015-12-31 16:58:48Z emaste $");
#define _ARMAG_LEN 8 /* length of ar magic string */
#define _ARHDR_LEN 60 /* length of ar header */
@@ -382,7 +382,7 @@ ac_read_objs(struct elfcopy *ecp, int ifd)
if (lseek(ifd, 0, SEEK_SET) == -1)
err(EXIT_FAILURE, "lseek failed");
if ((a = archive_read_new()) == NULL)
- errx(EXIT_FAILURE, "%s", archive_error_string(a));
+ errx(EXIT_FAILURE, "archive_read_new failed");
archive_read_support_format_ar(a);
AC(archive_read_open_fd(a, ifd, 10240));
for(;;) {
@@ -443,7 +443,7 @@ ac_write_objs(struct elfcopy *ecp, int ofd)
int nr;
if ((a = archive_write_new()) == NULL)
- errx(EXIT_FAILURE, "%s", archive_error_string(a));
+ errx(EXIT_FAILURE, "archive_write_new failed");
archive_write_set_format_ar_svr4(a);
AC(archive_write_open_fd(a, ofd));
diff --git a/contrib/elftoolchain/elfcopy/elfcopy.1 b/contrib/elftoolchain/elfcopy/elfcopy.1
index 83cda5d..b7b0ce4 100644
--- a/contrib/elftoolchain/elfcopy/elfcopy.1
+++ b/contrib/elftoolchain/elfcopy/elfcopy.1
@@ -21,13 +21,14 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
-.\" $Id: elfcopy.1 3266 2015-12-07 15:38:26Z emaste $
+.\" $Id: elfcopy.1 3381 2016-01-30 19:39:47Z jkoshy $
.\"
-.Dd December 7, 2015
+.Dd January 29, 2016
.Os
.Dt ELFCOPY 1
.Sh NAME
-.Nm elfcopy
+.Nm elfcopy ,
+.Nm objcopy
.Nd copy and translate object files
.Sh SYNOPSIS
.Nm
@@ -85,7 +86,7 @@
.Sh DESCRIPTION
The
.Nm
-utility copies the content of the ELF object named by argument
+utility copies the content of the binary object named by argument
.Ar infile
to that named by argument
.Ar outfile ,
@@ -121,6 +122,10 @@ to the output.
.It Fl O Ar objformat | Fl -output-target= Ns Ar objformat
Write the output file using the object format specified in argument
.Ar objformat .
+The argument
+.Ar objformat
+should be one of the target names recognized by
+.Xr elftc_bfd_find_target 3 .
.It Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname
Remove any section with name
.Ar sectionname
@@ -330,8 +335,14 @@ Do not copy symbols that are not needed for relocation processing.
.Xr mcs 1 ,
.Xr strip 1 ,
.Xr elf 3 ,
+.Xr elftc_bfd_find_target 3 ,
.Xr ar 5 ,
.Xr elf 5
+.Sh COMPATIBILITY
+The
+.Nm
+utility is expected to be option compatible with GNU
+.Nm objcopy .
.Sh HISTORY
.Nm
has been implemented by
diff --git a/contrib/elftoolchain/elfcopy/elfcopy.h b/contrib/elftoolchain/elfcopy/elfcopy.h
index 48574b5..614c0e7 100644
--- a/contrib/elftoolchain/elfcopy/elfcopy.h
+++ b/contrib/elftoolchain/elfcopy/elfcopy.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: elfcopy.h 3221 2015-05-24 23:42:43Z kaiwang27 $
+ * $Id: elfcopy.h 3310 2016-01-10 09:10:54Z kaiwang27 $
*/
#include <sys/queue.h>
@@ -287,6 +287,7 @@ struct section *create_external_section(struct elfcopy *_ecp, const char *_name,
int _loadable);
void create_external_symtab(struct elfcopy *_ecp);
void create_ihex(int _ifd, int _ofd);
+void create_pe(struct elfcopy *_ecp, int _ifd, int _ofd);
void create_scn(struct elfcopy *_ecp);
void create_srec(struct elfcopy *_ecp, int _ifd, int _ofd, const char *_ofn);
void create_symtab(struct elfcopy *_ecp);
diff --git a/contrib/elftoolchain/elfcopy/main.c b/contrib/elftoolchain/elfcopy/main.c
index e2685b4..b51ba4e 100644
--- a/contrib/elftoolchain/elfcopy/main.c
+++ b/contrib/elftoolchain/elfcopy/main.c
@@ -39,7 +39,7 @@
#include "elfcopy.h"
-ELFTC_VCSID("$Id: main.c 3268 2015-12-07 20:30:55Z emaste $");
+ELFTC_VCSID("$Id: main.c 3399 2016-02-12 18:07:56Z emaste $");
enum options
{
@@ -316,6 +316,7 @@ create_elf(struct elfcopy *ecp)
oeh.e_entry = ieh.e_entry;
oeh.e_version = ieh.e_version;
+ ecp->flags &= ~(EXECUTABLE | DYNAMIC | RELOCATABLE);
if (ieh.e_type == ET_EXEC)
ecp->flags |= EXECUTABLE;
else if (ieh.e_type == ET_DYN)
@@ -722,6 +723,15 @@ create_file(struct elfcopy *ecp, const char *src, const char *dst)
create_srec(ecp, ofd, ofd0,
dst != NULL ? dst : src);
break;
+ case ETF_PE:
+ case ETF_EFI:
+#if WITH_PE
+ create_pe(ecp, ofd, ofd0);
+#else
+ errx(EXIT_FAILURE, "PE/EFI support not enabled"
+ " at compile time");
+#endif
+ break;
default:
errx(EXIT_FAILURE, "Internal: unsupported"
" output flavour %d", ecp->oec);
@@ -1345,6 +1355,9 @@ set_output_target(struct elfcopy *ecp, const char *target_name)
ecp->oed = elftc_bfd_target_byteorder(tgt);
ecp->oem = elftc_bfd_target_machine(tgt);
}
+ if (ecp->otf == ETF_EFI || ecp->otf == ETF_PE)
+ ecp->oem = elftc_bfd_target_machine(tgt);
+
ecp->otgt = target_name;
}
@@ -1366,7 +1379,7 @@ set_osabi(struct elfcopy *ecp, const char *abi)
#define ELFCOPY_USAGE_MESSAGE "\
Usage: %s [options] infile [outfile]\n\
- Transform an ELF object.\n\n\
+ Transform object files.\n\n\
Options:\n\
-d | -g | --strip-debug Remove debugging information from the output.\n\
-j SECTION | --only-section=SECTION\n\
@@ -1382,6 +1395,8 @@ Usage: %s [options] infile [outfile]\n\
-N SYM | --strip-symbol=SYM Do not copy symbol SYM to the output.\n\
-O FORMAT | --output-target=FORMAT\n\
Specify object format for the output file.\n\
+ FORMAT should be a target name understood by\n\
+ elftc_bfd_find_target(3).\n\
-R NAME | --remove-section=NAME\n\
Remove the named section.\n\
-S | --strip-all Remove all symbol and relocation information\n\
@@ -1471,6 +1486,7 @@ Usage: %s [options] file...\n\
Options:\n\
-d | -g | -S | --strip-debug Remove debugging symbols.\n\
-h | --help Print a help message.\n\
+ -o FILE | --output-file FILE Write output to FILE.\n\
--only-keep-debug Keep debugging information only.\n\
-p | --preserve-dates Preserve access and modification times.\n\
-s | --strip-all Remove all symbols.\n\
diff --git a/contrib/elftoolchain/elfcopy/pe.c b/contrib/elftoolchain/elfcopy/pe.c
new file mode 100644
index 0000000..0d075c5
--- /dev/null
+++ b/contrib/elftoolchain/elfcopy/pe.c
@@ -0,0 +1,233 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/param.h>
+#include <err.h>
+#include <gelf.h>
+#include <libpe.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "elfcopy.h"
+
+ELFTC_VCSID("$Id: pe.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+/* Convert ELF object to Portable Executable (PE). */
+void
+create_pe(struct elfcopy *ecp, int ifd, int ofd)
+{
+ Elf *e;
+ Elf_Scn *scn;
+ Elf_Data *d;
+ GElf_Ehdr eh;
+ GElf_Shdr sh;
+ PE *pe;
+ PE_Scn *ps;
+ PE_SecHdr psh;
+ PE_CoffHdr pch;
+ PE_OptHdr poh;
+ PE_Object po;
+ PE_Buffer *pb;
+ const char *name;
+ size_t indx;
+ int elferr, i;
+
+ if (ecp->otf == ETF_EFI || ecp->oem == EM_X86_64)
+ po = PE_O_PE32P;
+ else
+ po = PE_O_PE32;
+
+ if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL)
+ errx(EXIT_FAILURE, "elf_begin() failed: %s",
+ elf_errmsg(-1));
+
+ if (gelf_getehdr(e, &eh) == NULL)
+ errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
+ elf_errmsg(-1));
+
+ if (elf_getshstrndx(ecp->ein, &indx) == 0)
+ errx(EXIT_FAILURE, "elf_getshstrndx() failed: %s",
+ elf_errmsg(-1));
+
+ if ((pe = pe_init(ofd, PE_C_WRITE, po)) == NULL)
+ err(EXIT_FAILURE, "pe_init() failed");
+
+ /* Setup PE COFF header. */
+ memset(&pch, 0, sizeof(pch));
+ switch (ecp->oem) {
+ case EM_386:
+ pch.ch_machine = IMAGE_FILE_MACHINE_I386;
+ break;
+ case EM_X86_64:
+ pch.ch_machine = IMAGE_FILE_MACHINE_AMD64;
+ break;
+ default:
+ pch.ch_machine = IMAGE_FILE_MACHINE_UNKNOWN;
+ break;
+ }
+ pch.ch_timestamp = (uint32_t) time(NULL);
+ if (pe_update_coff_header(pe, &pch) < 0)
+ err(EXIT_FAILURE, "pe_update_coff_header() failed");
+
+ /* Setup PE optional header. */
+ memset(&poh, 0, sizeof(poh));
+ if (ecp->otf == ETF_EFI)
+ poh.oh_subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION;
+ poh.oh_entry = (uint32_t) eh.e_entry;
+
+ /*
+ * Default section alignment and file alignment. (Here the
+ * section alignment is set to the default page size of the
+ * archs supported. We should use different section alignment
+ * for some arch. (e.g. IA64)
+ */
+ poh.oh_secalign = 0x1000;
+ poh.oh_filealign = 0x200;
+
+ /* Copy sections. */
+ scn = NULL;
+ while ((scn = elf_nextscn(e, scn)) != NULL) {
+
+ /*
+ * Read in ELF section.
+ */
+
+ if (gelf_getshdr(scn, &sh) == NULL) {
+ warnx("gelf_getshdr() failed: %s", elf_errmsg(-1));
+ (void) elf_errno();
+ continue;
+ }
+ if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) ==
+ NULL) {
+ warnx("elf_strptr() failed: %s", elf_errmsg(-1));
+ (void) elf_errno();
+ continue;
+ }
+
+ /* Skip sections unneeded. */
+ if (strcmp(name, ".shstrtab") == 0 ||
+ strcmp(name, ".symtab") == 0 ||
+ strcmp(name, ".strtab") == 0)
+ continue;
+
+ if ((d = elf_getdata(scn, NULL)) == NULL) {
+ warnx("elf_getdata() failed: %s", elf_errmsg(-1));
+ (void) elf_errno();
+ continue;
+ }
+
+ if (strcmp(name, ".text") == 0) {
+ poh.oh_textbase = (uint32_t) sh.sh_addr;
+ poh.oh_textsize = (uint32_t) roundup(sh.sh_size,
+ poh.oh_filealign);
+ } else {
+ if (po == PE_O_PE32 && strcmp(name, ".data") == 0)
+ poh.oh_database = sh.sh_addr;
+ if (sh.sh_type == SHT_NOBITS)
+ poh.oh_bsssize += (uint32_t)
+ roundup(sh.sh_size, poh.oh_filealign);
+ else if (sh.sh_flags & SHF_ALLOC)
+ poh.oh_datasize += (uint32_t)
+ roundup(sh.sh_size, poh.oh_filealign);
+ }
+
+ /*
+ * Create PE/COFF section.
+ */
+
+ if ((ps = pe_newscn(pe)) == NULL) {
+ warn("pe_newscn() failed");
+ continue;
+ }
+
+ /*
+ * Setup PE/COFF section header. The section name is not
+ * NUL-terminated if its length happens to be 8. Long
+ * section name should be truncated for PE image according
+ * to the PE/COFF specification.
+ */
+ memset(&psh, 0, sizeof(psh));
+ strncpy(psh.sh_name, name, sizeof(psh.sh_name));
+ psh.sh_addr = sh.sh_addr;
+ psh.sh_virtsize = sh.sh_size;
+ if (sh.sh_type != SHT_NOBITS)
+ psh.sh_rawsize = sh.sh_size;
+ else
+ psh.sh_char |= IMAGE_SCN_CNT_UNINITIALIZED_DATA;
+
+ /*
+ * Translate ELF section flags to PE/COFF section flags.
+ */
+ psh.sh_char |= IMAGE_SCN_MEM_READ;
+ if (sh.sh_flags & SHF_WRITE)
+ psh.sh_char |= IMAGE_SCN_MEM_WRITE;
+ if (sh.sh_flags & SHF_EXECINSTR)
+ psh.sh_char |= IMAGE_SCN_MEM_EXECUTE |
+ IMAGE_SCN_CNT_CODE;
+ if ((sh.sh_flags & SHF_ALLOC) && (psh.sh_char & 0xF0) == 0)
+ psh.sh_char |= IMAGE_SCN_CNT_INITIALIZED_DATA;
+ for (i = 0xE; i > 0; i--) {
+ if (sh.sh_addralign & (1U << (i - 1))) {
+ psh.sh_char |= i << 20;
+ break;
+ }
+ }
+
+ /* Mark relocation section "discardable". */
+ if (strcmp(name, ".reloc") == 0)
+ psh.sh_char |= IMAGE_SCN_MEM_DISCARDABLE;
+
+ if (pe_update_section_header(ps, &psh) < 0) {
+ warn("pe_update_section_header() failed");
+ continue;
+ }
+
+ /* Copy section content. */
+ if ((pb = pe_newbuffer(ps)) == NULL) {
+ warn("pe_newbuffer() failed");
+ continue;
+ }
+ pb->pb_align = 1;
+ pb->pb_off = 0;
+ pb->pb_size = sh.sh_size;
+ pb->pb_buf = d->d_buf;
+ }
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_nextscn() failed: %s", elf_errmsg(elferr));
+
+ /* Update PE optional header. */
+ if (pe_update_opt_header(pe, &poh) < 0)
+ err(EXIT_FAILURE, "pe_update_opt_header() failed");
+
+ /* Write out PE/COFF object. */
+ if (pe_update(pe) < 0)
+ err(EXIT_FAILURE, "pe_update() failed");
+
+ pe_finish(pe);
+ elf_end(e);
+}
diff --git a/contrib/elftoolchain/elfcopy/sections.c b/contrib/elftoolchain/elfcopy/sections.c
index a17c9ab..2ba3d48 100644
--- a/contrib/elftoolchain/elfcopy/sections.c
+++ b/contrib/elftoolchain/elfcopy/sections.c
@@ -34,7 +34,7 @@
#include "elfcopy.h"
-ELFTC_VCSID("$Id: sections.c 3272 2015-12-11 20:00:54Z kaiwang27 $");
+ELFTC_VCSID("$Id: sections.c 3346 2016-01-17 20:09:15Z kaiwang27 $");
static void add_gnu_debuglink(struct elfcopy *ecp);
static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc);
@@ -223,6 +223,7 @@ static int
is_debug_section(const char *name)
{
const char *dbg_sec[] = {
+ ".apple_",
".debug",
".gnu.linkonce.wi.",
".line",
@@ -369,7 +370,7 @@ create_scn(struct elfcopy *ecp)
is = NULL;
while ((is = elf_nextscn(ecp->ein, is)) != NULL) {
if (gelf_getshdr(is, &ish) == NULL)
- errx(EXIT_FAILURE, "219 gelf_getshdr failed: %s",
+ errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
elf_errmsg(-1));
if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL)
errx(EXIT_FAILURE, "elf_strptr failed: %s",
@@ -416,12 +417,19 @@ create_scn(struct elfcopy *ecp)
* is loadable, but if user explicitly set section flags
* while neither "load" nor "alloc" is set, we make the
* section unloadable.
+ *
+ * Sections in relocatable object is loadable if
+ * section flag SHF_ALLOC is set.
*/
if (sec_flags &&
(sec_flags & (SF_LOAD | SF_ALLOC)) == 0)
s->loadable = 0;
- else
+ else {
s->loadable = add_to_inseg_list(ecp, s);
+ if ((ecp->flags & RELOCATABLE) &&
+ (ish.sh_flags & SHF_ALLOC))
+ s->loadable = 1;
+ }
} else {
/* Assuming .shstrtab is "unloadable". */
s = ecp->shstrtab;
@@ -875,10 +883,10 @@ resync_sections(struct elfcopy *ecp)
if (s->align == 0)
s->align = 1;
if (off <= s->off) {
- if (!s->loadable)
+ if (!s->loadable || (ecp->flags & RELOCATABLE))
s->off = roundup(off, s->align);
} else {
- if (s->loadable)
+ if (s->loadable && (ecp->flags & RELOCATABLE) == 0)
warnx("moving loadable section %s, "
"is this intentional?", s->name);
s->off = roundup(off, s->align);
@@ -1028,8 +1036,11 @@ print_section(struct section *s)
print_data(s->buf, s->sz);
} else {
id = NULL;
- while ((id = elf_getdata(s->is, id)) != NULL)
+ while ((id = elf_getdata(s->is, id)) != NULL ||
+ (id = elf_rawdata(s->is, id)) != NULL) {
+ (void) elf_errno();
print_data(id->d_buf, id->d_size);
+ }
elferr = elf_errno();
if (elferr != 0)
errx(EXIT_FAILURE, "elf_getdata() failed: %s",
@@ -1049,7 +1060,9 @@ read_section(struct section *s, size_t *size)
sz = 0;
b = NULL;
id = NULL;
- while ((id = elf_getdata(s->is, id)) != NULL) {
+ while ((id = elf_getdata(s->is, id)) != NULL ||
+ (id = elf_rawdata(s->is, id)) != NULL) {
+ (void) elf_errno();
if (b == NULL)
b = malloc(id->d_size);
else
@@ -1077,10 +1090,10 @@ copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy,
GElf_Shdr ish, osh;
if (gelf_getshdr(s->is, &ish) == NULL)
- errx(EXIT_FAILURE, "526 gelf_getshdr() failed: %s",
+ errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
elf_errmsg(-1));
if (gelf_getshdr(s->os, &osh) == NULL)
- errx(EXIT_FAILURE, "529 gelf_getshdr() failed: %s",
+ errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
elf_errmsg(-1));
if (copy)
@@ -1097,19 +1110,32 @@ copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy,
if (sec_flags) {
osh.sh_flags = 0;
- if (sec_flags & SF_ALLOC) {
+ if (sec_flags & SF_ALLOC)
osh.sh_flags |= SHF_ALLOC;
- if (!s->loadable)
- warnx("set SHF_ALLOC flag for "
- "unloadable section %s",
- s->name);
- }
if ((sec_flags & SF_READONLY) == 0)
osh.sh_flags |= SHF_WRITE;
if (sec_flags & SF_CODE)
osh.sh_flags |= SHF_EXECINSTR;
+ if ((sec_flags & SF_CONTENTS) &&
+ s->type == SHT_NOBITS && s->sz > 0) {
+ /*
+ * Convert SHT_NOBITS section to section with
+ * (zero'ed) content on file.
+ */
+ osh.sh_type = s->type = SHT_PROGBITS;
+ if ((s->buf = calloc(1, s->sz)) == NULL)
+ err(EXIT_FAILURE, "malloc failed");
+ s->nocopy = 1;
+ }
} else {
osh.sh_flags = ish.sh_flags;
+ /*
+ * Newer binutils as(1) emits the section flag
+ * SHF_INFO_LINK for relocation sections. elfcopy
+ * emits this flag in the output section if it's
+ * missing in the input section, to remain compatible
+ * with binutils.
+ */
if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA)
osh.sh_flags |= SHF_INFO_LINK;
}
@@ -1135,11 +1161,14 @@ copy_data(struct section *s)
return;
if ((id = elf_getdata(s->is, NULL)) == NULL) {
- elferr = elf_errno();
- if (elferr != 0)
- errx(EXIT_FAILURE, "elf_getdata() failed: %s",
- elf_errmsg(elferr));
- return;
+ (void) elf_errno();
+ if ((id = elf_rawdata(s->is, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ errx(EXIT_FAILURE, "failed to read section:"
+ " %s", s->name);
+ return;
+ }
}
if ((od = elf_newdata(s->os)) == NULL)
@@ -1245,6 +1274,7 @@ insert_sections(struct elfcopy *ecp)
struct sec_add *sa;
struct section *s;
size_t off;
+ uint64_t stype;
/* Put these sections in the end of current list. */
off = 0;
@@ -1259,8 +1289,20 @@ insert_sections(struct elfcopy *ecp)
/* TODO: Add section header vma/lma, flag changes here */
+ /*
+ * The default section type for user added section is
+ * SHT_PROGBITS. If the section name match certain patterns,
+ * elfcopy will try to set a more appropriate section type.
+ * However, data type is always set to ELF_T_BYTE and no
+ * translation is performed by libelf.
+ */
+ stype = SHT_PROGBITS;
+ if (strcmp(sa->name, ".note") == 0 ||
+ strncmp(sa->name, ".note.", strlen(".note.")) == 0)
+ stype = SHT_NOTE;
+
(void) create_external_section(ecp, sa->name, NULL, sa->content,
- sa->size, off, SHT_PROGBITS, ELF_T_BYTE, 0, 1, 0, 0);
+ sa->size, off, stype, ELF_T_BYTE, 0, 1, 0, 0);
}
}
@@ -1285,7 +1327,7 @@ update_shdr(struct elfcopy *ecp, int update_link)
continue;
if (gelf_getshdr(s->os, &osh) == NULL)
- errx(EXIT_FAILURE, "668 gelf_getshdr failed: %s",
+ errx(EXIT_FAILURE, "gelf_getshdr failed: %s",
elf_errmsg(-1));
/* Find section name in string table and set sh_name. */
@@ -1364,7 +1406,7 @@ set_shstrtab(struct elfcopy *ecp)
}
if (gelf_getshdr(s->os, &sh) == NULL)
- errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s",
+ errx(EXIT_FAILURE, "gelf_getshdr() failed: %s",
elf_errmsg(-1));
sh.sh_addr = 0;
sh.sh_addralign = 1;
@@ -1431,14 +1473,17 @@ add_section(struct elfcopy *ecp, const char *arg)
if (stat(fn, &sb) == -1)
err(EXIT_FAILURE, "stat failed");
sa->size = sb.st_size;
- if ((sa->content = malloc(sa->size)) == NULL)
- err(EXIT_FAILURE, "malloc failed");
- if ((fp = fopen(fn, "r")) == NULL)
- err(EXIT_FAILURE, "can not open %s", fn);
- if (fread(sa->content, 1, sa->size, fp) == 0 ||
- ferror(fp))
- err(EXIT_FAILURE, "fread failed");
- fclose(fp);
+ if (sa->size > 0) {
+ if ((sa->content = malloc(sa->size)) == NULL)
+ err(EXIT_FAILURE, "malloc failed");
+ if ((fp = fopen(fn, "r")) == NULL)
+ err(EXIT_FAILURE, "can not open %s", fn);
+ if (fread(sa->content, 1, sa->size, fp) == 0 ||
+ ferror(fp))
+ err(EXIT_FAILURE, "fread failed");
+ fclose(fp);
+ } else
+ sa->content = NULL;
STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list);
ecp->flags |= SEC_ADD;
diff --git a/contrib/elftoolchain/elfcopy/segments.c b/contrib/elftoolchain/elfcopy/segments.c
index 837cea5..8ce0b83 100644
--- a/contrib/elftoolchain/elfcopy/segments.c
+++ b/contrib/elftoolchain/elfcopy/segments.c
@@ -34,7 +34,7 @@
#include "elfcopy.h"
-ELFTC_VCSID("$Id: segments.c 3269 2015-12-11 18:38:43Z kaiwang27 $");
+ELFTC_VCSID("$Id: segments.c 3397 2016-02-12 14:35:19Z emaste $");
static void insert_to_inseg_list(struct segment *seg, struct section *sec);
@@ -107,11 +107,11 @@ adjust_addr(struct elfcopy *ecp)
TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
/* Only adjust loadable section's address. */
- if (!s->loadable || s->seg == NULL)
+ if (!s->loadable)
continue;
/* Apply global LMA adjustment. */
- if (ecp->change_addr != 0)
+ if (ecp->change_addr != 0 && s->seg != NULL)
s->lma += ecp->change_addr;
if (!s->pseudo) {
@@ -135,7 +135,10 @@ adjust_addr(struct elfcopy *ecp)
*/
TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
- /* Only adjust loadable section's LMA. */
+ /*
+ * Only loadable section that's inside a segment can have
+ * LMA adjusted.
+ */
if (!s->loadable || s->seg == NULL)
continue;
@@ -173,7 +176,7 @@ adjust_addr(struct elfcopy *ecp)
if (lma % s->align != 0)
errx(EXIT_FAILURE, "The load address %#jx for "
"section %s is not aligned to %ju",
- (uintmax_t) lma, s->name, s->align);
+ (uintmax_t) lma, s->name, (uintmax_t) s->align);
if (lma < s->lma) {
/* Move section to lower address. */
@@ -214,7 +217,8 @@ adjust_addr(struct elfcopy *ecp)
continue;
errx(EXIT_FAILURE, "The extent of segment containing "
"section %s overlaps with segment(%#jx,%#jx)",
- s->name, seg->addr, seg->addr + seg->msz);
+ s->name, (uintmax_t) seg->addr,
+ (uintmax_t) (seg->addr + seg->msz));
}
/*
@@ -485,7 +489,7 @@ copy_phdr(struct elfcopy *ecp)
ophdr.p_filesz = seg->fsz;
ophdr.p_memsz = seg->msz;
if (!gelf_update_phdr(ecp->eout, i, &ophdr))
- err(EXIT_FAILURE, "gelf_update_phdr failed :%s",
+ errx(EXIT_FAILURE, "gelf_update_phdr failed: %s",
elf_errmsg(-1));
i++;
diff --git a/contrib/elftoolchain/elfcopy/symbols.c b/contrib/elftoolchain/elfcopy/symbols.c
index 05bcd7a..4423ca2 100644
--- a/contrib/elftoolchain/elfcopy/symbols.c
+++ b/contrib/elftoolchain/elfcopy/symbols.c
@@ -25,6 +25,7 @@
*/
#include <sys/param.h>
+#include <assert.h>
#include <err.h>
#include <fnmatch.h>
#include <stdio.h>
@@ -33,7 +34,13 @@
#include "elfcopy.h"
-ELFTC_VCSID("$Id: symbols.c 3222 2015-05-24 23:47:23Z kaiwang27 $");
+ELFTC_VCSID("$Id: symbols.c 3376 2016-01-26 18:41:39Z emaste $");
+
+/* Backwards compatibility for systems with older ELF definitions. */
+#ifndef STB_GNU_UNIQUE
+#define STB_GNU_UNIQUE 10
+#endif
+
/* Symbol table buffer structure. */
struct symbuf {
@@ -79,7 +86,6 @@ static int lookup_exact_string(hash_head *hash, const char *buf,
static int generate_symbols(struct elfcopy *ecp);
static void mark_reloc_symbols(struct elfcopy *ecp, size_t sc);
static void mark_section_group_symbols(struct elfcopy *ecp, size_t sc);
-static int match_wildcard(const char *name, const char *pattern);
uint32_t str_hash(const char *s);
/* Convenient bit vector operation macros. */
@@ -102,7 +108,8 @@ static int
is_global_symbol(unsigned char st_info)
{
- if (GELF_ST_BIND(st_info) == STB_GLOBAL)
+ if (GELF_ST_BIND(st_info) == STB_GLOBAL ||
+ GELF_ST_BIND(st_info) == STB_GNU_UNIQUE)
return (1);
return (0);
@@ -190,12 +197,6 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
SHN_UNDEF, /* st_shndx */
};
- if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL)
- return (0);
-
- if (lookup_symop_list(ecp, name, SYMOP_STRIP) != NULL)
- return (1);
-
/*
* Keep the first symbol if it is the special reserved symbol.
* XXX Should we generate one if it's missing?
@@ -208,15 +209,34 @@ is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s,
ecp->secndx[s->st_shndx] == 0)
return (1);
+ /* Keep the symbol if specified by command line option -K. */
+ if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL)
+ return (0);
+
if (ecp->strip == STRIP_ALL)
return (1);
+ /* Mark symbols used in relocation. */
if (ecp->v_rel == NULL)
mark_reloc_symbols(ecp, sc);
+ /* Mark symbols used in section groups. */
if (ecp->v_grp == NULL)
mark_section_group_symbols(ecp, sc);
+ /*
+ * Strip the symbol if specified by command line option -N,
+ * unless it's used in relocation.
+ */
+ if (lookup_symop_list(ecp, name, SYMOP_STRIP) != NULL) {
+ if (BIT_ISSET(ecp->v_rel, i)) {
+ warnx("not stripping symbol `%s' because it is named"
+ " in a relocation", name);
+ return (0);
+ }
+ return (1);
+ }
+
if (is_needed_symbol(ecp, i, s))
return (0);
@@ -565,8 +585,11 @@ generate_symbols(struct elfcopy *ecp)
* If the symbol is a STT_SECTION symbol, mark the section
* it points to.
*/
- if (GELF_ST_TYPE(sym.st_info) == STT_SECTION)
+ if (GELF_ST_TYPE(sym.st_info) == STT_SECTION &&
+ sym.st_shndx < SHN_LORESERVE) {
+ assert(ecp->secndx[sym.st_shndx] < (uint64_t)ecp->nos);
BIT_SET(ecp->v_secsym, ecp->secndx[sym.st_shndx]);
+ }
}
/*
@@ -861,6 +884,8 @@ add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value,
* It handles buffer growing, st_name calculating and st_shndx
* updating for symbols with non-special section index.
*/
+#define _ST_NAME_EMPTY_l 0
+#define _ST_NAME_EMPTY_g -1
#define _ADDSYM(B, SZ) do { \
if (sy_buf->B##SZ == NULL) { \
sy_buf->B##SZ = malloc(sy_buf->B##cap * \
@@ -920,7 +945,8 @@ add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value,
st_buf->B.sz += strlen(name) + 1; \
} \
} else \
- sy_buf->B##SZ[sy_buf->n##B##s].st_name = 0; \
+ sy_buf->B##SZ[sy_buf->n##B##s].st_name = \
+ (Elf##SZ##_Word)_ST_NAME_EMPTY_##B; \
sy_buf->n##B##s++; \
} while (0)
@@ -945,6 +971,8 @@ add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value,
ecp->strtab->sz = st_buf->l.sz + st_buf->g.sz;
#undef _ADDSYM
+#undef _ST_NAME_EMPTY_l
+#undef _ST_NAME_EMPTY_g
}
void
@@ -961,10 +989,17 @@ finalize_external_symtab(struct elfcopy *ecp)
sy_buf = ecp->symtab->buf;
st_buf = ecp->strtab->buf;
for (i = 0; (size_t) i < sy_buf->ngs; i++) {
- if (ecp->oec == ELFCLASS32)
- sy_buf->g32[i].st_name += st_buf->l.sz;
- else
- sy_buf->g64[i].st_name += st_buf->l.sz;
+ if (ecp->oec == ELFCLASS32) {
+ if (sy_buf->g32[i].st_name == (Elf32_Word)-1)
+ sy_buf->g32[i].st_name = 0;
+ else
+ sy_buf->g32[i].st_name += st_buf->l.sz;
+ } else {
+ if (sy_buf->g64[i].st_name == (Elf64_Word)-1)
+ sy_buf->g64[i].st_name = 0;
+ else
+ sy_buf->g64[i].st_name += st_buf->l.sz;
+ }
}
}
@@ -1105,46 +1140,47 @@ add_to_symop_list(struct elfcopy *ecp, const char *name, const char *newname,
{
struct symop *s;
- if ((s = lookup_symop_list(ecp, name, ~0U)) == NULL) {
- if ((s = calloc(1, sizeof(*s))) == NULL)
- errx(EXIT_FAILURE, "not enough memory");
- s->name = name;
- if (op == SYMOP_REDEF)
- s->newname = newname;
- }
+ assert (name != NULL);
+ STAILQ_FOREACH(s, &ecp->v_symop, symop_list)
+ if (!strcmp(name, s->name))
+ goto found;
- s->op |= op;
+ if ((s = calloc(1, sizeof(*s))) == NULL)
+ errx(EXIT_FAILURE, "not enough memory");
STAILQ_INSERT_TAIL(&ecp->v_symop, s, symop_list);
-}
-
-static int
-match_wildcard(const char *name, const char *pattern)
-{
- int reverse, match;
-
- reverse = 0;
- if (*pattern == '!') {
- reverse = 1;
- pattern++;
- }
-
- match = 0;
- if (!fnmatch(pattern, name, 0))
- match = 1;
-
- return (reverse ? !match : match);
+ s->name = name;
+found:
+ if (op == SYMOP_REDEF)
+ s->newname = newname;
+ s->op |= op;
}
struct symop *
lookup_symop_list(struct elfcopy *ecp, const char *name, unsigned int op)
{
- struct symop *s;
+ struct symop *s, *ret;
+ const char *pattern;
STAILQ_FOREACH(s, &ecp->v_symop, symop_list) {
- if (name == NULL || !strcmp(name, s->name) ||
- ((ecp->flags & WILDCARD) && match_wildcard(name, s->name)))
- if ((s->op & op) != 0)
+ if ((s->op & op) == 0)
+ continue;
+ if (name == NULL || !strcmp(name, s->name))
return (s);
+ if ((ecp->flags & WILDCARD) == 0)
+ continue;
+
+ /* Handle wildcards. */
+ pattern = s->name;
+ if (pattern[0] == '!') {
+ /* Negative match. */
+ pattern++;
+ ret = NULL;
+ } else {
+ /* Regular wildcard match. */
+ ret = s;
+ }
+ if (!fnmatch(pattern, name, 0))
+ return (ret);
}
return (NULL);
diff --git a/contrib/elftoolchain/elfdump/elfdump.c b/contrib/elftoolchain/elfdump/elfdump.c
index baf99ee..334d285 100644
--- a/contrib/elftoolchain/elfdump/elfdump.c
+++ b/contrib/elftoolchain/elfdump/elfdump.c
@@ -50,7 +50,7 @@
#include "_elftc.h"
-ELFTC_VCSID("$Id: elfdump.c 3250 2015-10-06 13:56:15Z emaste $");
+ELFTC_VCSID("$Id: elfdump.c 3391 2016-02-05 19:43:01Z emaste $");
#if defined(ELFTC_NEED_ELF_NOTE_DEFINITION)
#include "native-elf-format.h"
@@ -155,77 +155,82 @@ le32dec(const void *pp)
static const char *
d_tags(uint64_t tag)
{
+ static char unknown_buf[64];
+
switch (tag) {
- case 0: return "DT_NULL";
- case 1: return "DT_NEEDED";
- case 2: return "DT_PLTRELSZ";
- case 3: return "DT_PLTGOT";
- case 4: return "DT_HASH";
- case 5: return "DT_STRTAB";
- case 6: return "DT_SYMTAB";
- case 7: return "DT_RELA";
- case 8: return "DT_RELASZ";
- case 9: return "DT_RELAENT";
- case 10: return "DT_STRSZ";
- case 11: return "DT_SYMENT";
- case 12: return "DT_INIT";
- case 13: return "DT_FINI";
- case 14: return "DT_SONAME";
- case 15: return "DT_RPATH";
- case 16: return "DT_SYMBOLIC";
- case 17: return "DT_REL";
- case 18: return "DT_RELSZ";
- case 19: return "DT_RELENT";
- case 20: return "DT_PLTREL";
- case 21: return "DT_DEBUG";
- case 22: return "DT_TEXTREL";
- case 23: return "DT_JMPREL";
- case 24: return "DT_BIND_NOW";
- case 25: return "DT_INIT_ARRAY";
- case 26: return "DT_FINI_ARRAY";
- case 27: return "DT_INIT_ARRAYSZ";
- case 28: return "DT_FINI_ARRAYSZ";
- case 29: return "DT_RUNPATH";
- case 30: return "DT_FLAGS";
- case 32: return "DT_PREINIT_ARRAY"; /* XXX: DT_ENCODING */
- case 33: return "DT_PREINIT_ARRAYSZ";
+ case DT_NULL: return "DT_NULL";
+ case DT_NEEDED: return "DT_NEEDED";
+ case DT_PLTRELSZ: return "DT_PLTRELSZ";
+ case DT_PLTGOT: return "DT_PLTGOT";
+ case DT_HASH: return "DT_HASH";
+ case DT_STRTAB: return "DT_STRTAB";
+ case DT_SYMTAB: return "DT_SYMTAB";
+ case DT_RELA: return "DT_RELA";
+ case DT_RELASZ: return "DT_RELASZ";
+ case DT_RELAENT: return "DT_RELAENT";
+ case DT_STRSZ: return "DT_STRSZ";
+ case DT_SYMENT: return "DT_SYMENT";
+ case DT_INIT: return "DT_INIT";
+ case DT_FINI: return "DT_FINI";
+ case DT_SONAME: return "DT_SONAME";
+ case DT_RPATH: return "DT_RPATH";
+ case DT_SYMBOLIC: return "DT_SYMBOLIC";
+ case DT_REL: return "DT_REL";
+ case DT_RELSZ: return "DT_RELSZ";
+ case DT_RELENT: return "DT_RELENT";
+ case DT_PLTREL: return "DT_PLTREL";
+ case DT_DEBUG: return "DT_DEBUG";
+ case DT_TEXTREL: return "DT_TEXTREL";
+ case DT_JMPREL: return "DT_JMPREL";
+ case DT_BIND_NOW: return "DT_BIND_NOW";
+ case DT_INIT_ARRAY: return "DT_INIT_ARRAY";
+ case DT_FINI_ARRAY: return "DT_FINI_ARRAY";
+ case DT_INIT_ARRAYSZ: return "DT_INIT_ARRAYSZ";
+ case DT_FINI_ARRAYSZ: return "DT_FINI_ARRAYSZ";
+ case DT_RUNPATH: return "DT_RUNPATH";
+ case DT_FLAGS: return "DT_FLAGS";
+ case DT_PREINIT_ARRAY: return "DT_PREINIT_ARRAY"; /* XXX DT_ENCODING */
+ case DT_PREINIT_ARRAYSZ:return "DT_PREINIT_ARRAYSZ";
/* 0x6000000D - 0x6ffff000 operating system-specific semantics */
- case 0x6ffffdf5: return "DT_GNU_PRELINKED";
- case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ";
- case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ";
- case 0x6ffffdf8: return "DT_SUNW_CHECKSUM";
- case 0x6ffffdf9: return "DT_PLTPADSZ";
- case 0x6ffffdfa: return "DT_MOVEENT";
- case 0x6ffffdfb: return "DT_MOVESZ";
- case 0x6ffffdfc: return "DT_FEATURE";
- case 0x6ffffdfd: return "DT_POSFLAG_1";
- case 0x6ffffdfe: return "DT_SYMINSZ";
- case 0x6ffffdff: return "DT_SYMINENT (DT_VALRNGHI)";
- case 0x6ffffe00: return "DT_ADDRRNGLO";
- case 0x6ffffef5: return "DT_GNU_HASH";
- case 0x6ffffef8: return "DT_GNU_CONFLICT";
- case 0x6ffffef9: return "DT_GNU_LIBLIST";
- case 0x6ffffefa: return "DT_CONFIG";
- case 0x6ffffefb: return "DT_DEPAUDIT";
- case 0x6ffffefc: return "DT_AUDIT";
- case 0x6ffffefd: return "DT_PLTPAD";
- case 0x6ffffefe: return "DT_MOVETAB";
- case 0x6ffffeff: return "DT_SYMINFO (DT_ADDRRNGHI)";
- case 0x6ffffff9: return "DT_RELACOUNT";
- case 0x6ffffffa: return "DT_RELCOUNT";
- case 0x6ffffffb: return "DT_FLAGS_1";
- case 0x6ffffffc: return "DT_VERDEF";
- case 0x6ffffffd: return "DT_VERDEFNUM";
- case 0x6ffffffe: return "DT_VERNEED";
- case 0x6fffffff: return "DT_VERNEEDNUM";
- case 0x6ffffff0: return "DT_GNU_VERSYM";
+ case 0x6ffffdf5: return "DT_GNU_PRELINKED";
+ case 0x6ffffdf6: return "DT_GNU_CONFLICTSZ";
+ case 0x6ffffdf7: return "DT_GNU_LIBLISTSZ";
+ case 0x6ffffdf8: return "DT_SUNW_CHECKSUM";
+ case DT_PLTPADSZ: return "DT_PLTPADSZ";
+ case DT_MOVEENT: return "DT_MOVEENT";
+ case DT_MOVESZ: return "DT_MOVESZ";
+ case 0x6ffffdfc: return "DT_FEATURE";
+ case DT_POSFLAG_1: return "DT_POSFLAG_1";
+ case DT_SYMINSZ: return "DT_SYMINSZ";
+ case DT_SYMINENT: return "DT_SYMINENT (DT_VALRNGHI)";
+ case DT_ADDRRNGLO: return "DT_ADDRRNGLO";
+ case DT_GNU_HASH: return "DT_GNU_HASH";
+ case 0x6ffffef8: return "DT_GNU_CONFLICT";
+ case 0x6ffffef9: return "DT_GNU_LIBLIST";
+ case 0x6ffffefa: return "DT_CONFIG";
+ case 0x6ffffefb: return "DT_DEPAUDIT";
+ case 0x6ffffefc: return "DT_AUDIT";
+ case 0x6ffffefd: return "DT_PLTPAD";
+ case 0x6ffffefe: return "DT_MOVETAB";
+ case DT_SYMINFO: return "DT_SYMINFO (DT_ADDRRNGHI)";
+ case DT_RELACOUNT: return "DT_RELACOUNT";
+ case DT_RELCOUNT: return "DT_RELCOUNT";
+ case DT_FLAGS_1: return "DT_FLAGS_1";
+ case DT_VERDEF: return "DT_VERDEF";
+ case DT_VERDEFNUM: return "DT_VERDEFNUM";
+ case DT_VERNEED: return "DT_VERNEED";
+ case DT_VERNEEDNUM: return "DT_VERNEEDNUM";
+ case 0x6ffffff0: return "DT_GNU_VERSYM";
/* 0x70000000 - 0x7fffffff processor-specific semantics */
- case 0x70000000: return "DT_IA_64_PLT_RESERVE";
- case 0x7ffffffd: return "DT_SUNW_AUXILIARY";
- case 0x7ffffffe: return "DT_SUNW_USED";
- case 0x7fffffff: return "DT_SUNW_FILTER";
- default: return "ERROR: TAG NOT DEFINED";
+ case 0x70000000: return "DT_IA_64_PLT_RESERVE";
+ case 0x7ffffffd: return "DT_SUNW_AUXILIARY";
+ case 0x7ffffffe: return "DT_SUNW_USED";
+ case 0x7fffffff: return "DT_SUNW_FILTER";
}
+
+ snprintf(unknown_buf, sizeof(unknown_buf),
+ "<unknown: %#llx>", (unsigned long long)tag);
+ return (unknown_buf);
}
static const char *
@@ -313,42 +318,79 @@ sh_name(struct elfdump *ed, int ndx)
/* http://www.sco.com/developers/gabi/latest/ch4.sheader.html#sh_type */
static const char *
-sh_types(u_int64_t sht) {
- switch (sht) {
- case 0: return "SHT_NULL";
- case 1: return "SHT_PROGBITS";
- case 2: return "SHT_SYMTAB";
- case 3: return "SHT_STRTAB";
- case 4: return "SHT_RELA";
- case 5: return "SHT_HASH";
- case 6: return "SHT_DYNAMIC";
- case 7: return "SHT_NOTE";
- case 8: return "SHT_NOBITS";
- case 9: return "SHT_REL";
- case 10: return "SHT_SHLIB";
- case 11: return "SHT_DYNSYM";
- case 14: return "SHT_INIT_ARRAY";
- case 15: return "SHT_FINI_ARRAY";
- case 16: return "SHT_PREINIT_ARRAY";
- case 17: return "SHT_GROUP";
- case 18: return "SHT_SYMTAB_SHNDX";
- /* 0x60000000 - 0x6fffffff operating system-specific semantics */
- case 0x6ffffff0: return "XXX:VERSYM";
- case 0x6ffffff4: return "SHT_SUNW_dof";
- case 0x6ffffff6: return "SHT_GNU_HASH";
- case 0x6ffffff7: return "SHT_GNU_LIBLIST";
- case 0x6ffffffc: return "XXX:VERDEF";
- case 0x6ffffffd: return "SHT_SUNW(GNU)_verdef";
- case 0x6ffffffe: return "SHT_SUNW(GNU)_verneed";
- case 0x6fffffff: return "SHT_SUNW(GNU)_versym";
- /* 0x70000000 - 0x7fffffff processor-specific semantics */
- case 0x70000000: return "SHT_IA_64_EXT";
- case 0x70000001: return "SHT_IA_64_UNWIND";
- case 0x7ffffffd: return "XXX:AUXILIARY";
- case 0x7fffffff: return "XXX:FILTER";
- /* 0x80000000 - 0xffffffff application programs */
- default: return "ERROR: SHT NOT DEFINED";
+sh_types(uint64_t mach, uint64_t sht) {
+ static char unknown_buf[64];
+
+ if (sht < 0x60000000) {
+ switch (sht) {
+ case SHT_NULL: return "SHT_NULL";
+ case SHT_PROGBITS: return "SHT_PROGBITS";
+ case SHT_SYMTAB: return "SHT_SYMTAB";
+ case SHT_STRTAB: return "SHT_STRTAB";
+ case SHT_RELA: return "SHT_RELA";
+ case SHT_HASH: return "SHT_HASH";
+ case SHT_DYNAMIC: return "SHT_DYNAMIC";
+ case SHT_NOTE: return "SHT_NOTE";
+ case SHT_NOBITS: return "SHT_NOBITS";
+ case SHT_REL: return "SHT_REL";
+ case SHT_SHLIB: return "SHT_SHLIB";
+ case SHT_DYNSYM: return "SHT_DYNSYM";
+ case SHT_INIT_ARRAY: return "SHT_INIT_ARRAY";
+ case SHT_FINI_ARRAY: return "SHT_FINI_ARRAY";
+ case SHT_PREINIT_ARRAY: return "SHT_PREINIT_ARRAY";
+ case SHT_GROUP: return "SHT_GROUP";
+ case SHT_SYMTAB_SHNDX: return "SHT_SYMTAB_SHNDX";
+ }
+ } else if (sht < 0x70000000) {
+ /* 0x60000000-0x6fffffff operating system-specific semantics */
+ switch (sht) {
+ case 0x6ffffff0: return "XXX:VERSYM";
+ case SHT_SUNW_dof: return "SHT_SUNW_dof";
+ case SHT_GNU_HASH: return "SHT_GNU_HASH";
+ case 0x6ffffff7: return "SHT_GNU_LIBLIST";
+ case 0x6ffffffc: return "XXX:VERDEF";
+ case SHT_SUNW_verdef: return "SHT_SUNW(GNU)_verdef";
+ case SHT_SUNW_verneed: return "SHT_SUNW(GNU)_verneed";
+ case SHT_SUNW_versym: return "SHT_SUNW(GNU)_versym";
+ }
+ } else if (sht < 0x80000000) {
+ /* 0x70000000 - 0x7fffffff processor-specific semantics */
+ switch (mach) {
+ case EM_ARM:
+ switch (sht) {
+ case SHT_ARM_EXIDX: return "SHT_ARM_EXIDX";
+ case SHT_ARM_PREEMPTMAP: return "SHT_ARM_PREEMPTMAP";
+ case SHT_ARM_ATTRIBUTES: return "SHT_ARM_ATTRIBUTES";
+ case SHT_ARM_DEBUGOVERLAY:
+ return "SHT_ARM_DEBUGOVERLAY";
+ case SHT_ARM_OVERLAYSECTION:
+ return "SHT_ARM_OVERLAYSECTION";
+ }
+ break;
+ case EM_IA_64:
+ switch (sht) {
+ case 0x70000000: return "SHT_IA_64_EXT";
+ case 0x70000001: return "SHT_IA_64_UNWIND";
+ }
+ break;
+ case EM_MIPS:
+ switch (sht) {
+ case SHT_MIPS_REGINFO: return "SHT_MIPS_REGINFO";
+ case SHT_MIPS_OPTIONS: return "SHT_MIPS_OPTIONS";
+ case SHT_MIPS_ABIFLAGS: return "SHT_MIPS_ABIFLAGS";
+ }
+ break;
+ }
+ switch (sht) {
+ case 0x7ffffffd: return "XXX:AUXILIARY";
+ case 0x7fffffff: return "XXX:FILTER";
+ }
}
+ /* 0x80000000 - 0xffffffff application programs */
+
+ snprintf(unknown_buf, sizeof(unknown_buf),
+ "<unknown: %#llx>", (unsigned long long)sht);
+ return (unknown_buf);
}
/*
@@ -390,22 +432,87 @@ sh_flags(uint64_t shf)
return (flg);
}
-static const char *st_types[] = {
- "STT_NOTYPE", "STT_OBJECT", "STT_FUNC", "STT_SECTION", "STT_FILE",
- "STT_COMMON", "STT_TLS"
-};
+static const char *
+st_type(unsigned int mach, unsigned int type)
+{
+ static char s_type[32];
+
+ switch (type) {
+ case STT_NOTYPE: return "STT_NOTYPE";
+ case STT_OBJECT: return "STT_OBJECT";
+ case STT_FUNC: return "STT_FUNC";
+ case STT_SECTION: return "STT_SECTION";
+ case STT_FILE: return "STT_FILE";
+ case STT_COMMON: return "STT_COMMON";
+ case STT_TLS: return "STT_TLS";
+ case 13:
+ if (mach == EM_SPARCV9)
+ return "STT_SPARC_REGISTER";
+ break;
+ }
+ snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type);
+ return (s_type);
+}
-static const char *st_types_S[] = {
- "NOTY", "OBJT", "FUNC", "SECT", "FILE"
-};
+static const char *
+st_type_S(unsigned int type)
+{
+ static char s_type[32];
-static const char *st_bindings[] = {
- "STB_LOCAL", "STB_GLOBAL", "STB_WEAK"
-};
+ switch (type) {
+ case STT_NOTYPE: return "NOTY";
+ case STT_OBJECT: return "OBJT";
+ case STT_FUNC: return "FUNC";
+ case STT_SECTION: return "SECT";
+ case STT_FILE: return "FILE";
+ }
+ snprintf(s_type, sizeof(s_type), "<unknown: %#x>", type);
+ return (s_type);
+}
-static const char *st_bindings_S[] = {
- "LOCL", "GLOB", "WEAK"
-};
+static const char *
+st_bindings(unsigned int sbind)
+{
+ static char s_sbind[32];
+
+ switch (sbind) {
+ case STB_LOCAL: return "STB_LOCAL";
+ case STB_GLOBAL: return "STB_GLOBAL";
+ case STB_WEAK: return "STB_WEAK";
+ case STB_GNU_UNIQUE: return "STB_GNU_UNIQUE";
+ default:
+ if (sbind >= STB_LOOS && sbind <= STB_HIOS)
+ return "OS";
+ else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC)
+ return "PROC";
+ else
+ snprintf(s_sbind, sizeof(s_sbind), "<unknown: %#x>",
+ sbind);
+ return (s_sbind);
+ }
+}
+
+static const char *
+st_bindings_S(unsigned int sbind)
+{
+ static char s_sbind[32];
+
+ switch (sbind) {
+ case STB_LOCAL: return "LOCL";
+ case STB_GLOBAL: return "GLOB";
+ case STB_WEAK: return "WEAK";
+ case STB_GNU_UNIQUE: return "UNIQ";
+ default:
+ if (sbind >= STB_LOOS && sbind <= STB_HIOS)
+ return "OS";
+ else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC)
+ return "PROC";
+ else
+ snprintf(s_sbind, sizeof(s_sbind), "<%#x>",
+ sbind);
+ return (s_sbind);
+ }
+}
static unsigned char st_others[] = {
'D', 'I', 'H', 'P'
@@ -426,7 +533,7 @@ r_type(unsigned int mach, unsigned int type)
case 4: return "R_386_PLT32";
case 5: return "R_386_COPY";
case 6: return "R_386_GLOB_DAT";
- case 7: return "R_386_JMP_SLOT";
+ case 7: return "R_386_JUMP_SLOT";
case 8: return "R_386_RELATIVE";
case 9: return "R_386_GOTOFF";
case 10: return "R_386_GOTPC";
@@ -769,7 +876,7 @@ r_type(unsigned int mach, unsigned int type)
case 4: return "R_X86_64_PLT32";
case 5: return "R_X86_64_COPY";
case 6: return "R_X86_64_GLOB_DAT";
- case 7: return "R_X86_64_JMP_SLOT";
+ case 7: return "R_X86_64_JUMP_SLOT";
case 8: return "R_X86_64_RELATIVE";
case 9: return "R_X86_64_GOTPCREL";
case 10: return "R_X86_64_32";
@@ -1608,7 +1715,8 @@ elf_print_shdr(struct elfdump *ed)
else
PRT(" sh_flags: 0\n");
PRT(" sh_size: %#-14jx", (uintmax_t)s->sz);
- PRT(" sh_type: [ %s ]\n", sh_types(s->type));
+ PRT(" sh_type: [ %s ]\n",
+ sh_types(ed->ehdr.e_machine, s->type));
PRT(" sh_offset: %#-14jx", (uintmax_t)s->off);
PRT(" sh_entsize: %#jx\n", (uintmax_t)s->entsize);
PRT(" sh_link: %-14u", s->link);
@@ -1618,7 +1726,8 @@ elf_print_shdr(struct elfdump *ed)
PRT("\n");
PRT("entry: %ju\n", (uintmax_t)i);
PRT("\tsh_name: %s\n", s->name);
- PRT("\tsh_type: %s\n", sh_types(s->type));
+ PRT("\tsh_type: %s\n",
+ sh_types(ed->ehdr.e_machine, s->type));
PRT("\tsh_flags: %s\n", sh_flags(s->flags));
PRT("\tsh_addr: %#jx\n", (uintmax_t)s->addr);
PRT("\tsh_offset: %ju\n", (uintmax_t)s->off);
@@ -1745,8 +1854,8 @@ elf_print_symtab(struct elfdump *ed, int i)
PRT("0x%8.8jx ", (uintmax_t)sym.st_size);
else
PRT("0x%12.12jx ", (uintmax_t)sym.st_size);
- PRT("%s ", st_types_S[GELF_ST_TYPE(sym.st_info)]);
- PRT("%s ", st_bindings_S[GELF_ST_BIND(sym.st_info)]);
+ PRT("%s ", st_type_S(GELF_ST_TYPE(sym.st_info)));
+ PRT("%s ", st_bindings_S(GELF_ST_BIND(sym.st_info)));
PRT("%c ", st_others[sym.st_other]);
PRT("%3u ", (vs == NULL ? 0 : vs[j]));
PRT("%-11.11s ", sh_name(ed, sym.st_shndx));
@@ -1757,8 +1866,9 @@ elf_print_symtab(struct elfdump *ed, int i)
PRT("\tst_value: %#jx\n", (uintmax_t)sym.st_value);
PRT("\tst_size: %ju\n", (uintmax_t)sym.st_size);
PRT("\tst_info: %s %s\n",
- st_types[GELF_ST_TYPE(sym.st_info)],
- st_bindings[GELF_ST_BIND(sym.st_info)]);
+ st_type(ed->ehdr.e_machine,
+ GELF_ST_TYPE(sym.st_info)),
+ st_bindings(GELF_ST_BIND(sym.st_info)));
PRT("\tst_shndx: %ju\n", (uintmax_t)sym.st_shndx);
}
}
@@ -2173,11 +2283,14 @@ elf_print_got_section(struct elfdump *ed, struct section *s)
for(i = 0; i < len; i++) {
PRT("[%5.5d] ", i);
if (ed->ec == ELFCLASS32) {
- PRT("%-8.8jx ", s->addr + i * s->entsize);
+ PRT("%-8.8jx ",
+ (uintmax_t) (s->addr + i * s->entsize));
PRT("%-8.8x ", *((uint32_t *)dst.d_buf + i));
} else {
- PRT("%-16.16jx ", s->addr + i * s->entsize);
- PRT("%-16.16jx ", *((uint64_t *)dst.d_buf + i));
+ PRT("%-16.16jx ",
+ (uintmax_t) (s->addr + i * s->entsize));
+ PRT("%-16.16jx ",
+ (uintmax_t) *((uint64_t *)dst.d_buf + i));
}
PRT("%-18s ", r_type(ed->ehdr.e_machine,
GELF_R_TYPE(got[i].u_r.rel.r_info)));
@@ -2198,7 +2311,8 @@ elf_print_got_section(struct elfdump *ed, struct section *s)
if (ed->ec == ELFCLASS32)
PRT("\t%#x\n", *((uint32_t *)dst.d_buf + i));
else
- PRT("\t%#jx\n", *((uint64_t *)dst.d_buf + i));
+ PRT("\t%#jx\n",
+ (uintmax_t) *((uint64_t *)dst.d_buf + i));
}
}
}
diff --git a/contrib/elftoolchain/elfdump/os.NetBSD.mk b/contrib/elftoolchain/elfdump/os.NetBSD.mk
new file mode 100644
index 0000000..ae214e3
--- /dev/null
+++ b/contrib/elftoolchain/elfdump/os.NetBSD.mk
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
diff --git a/contrib/elftoolchain/libdwarf/_libdwarf.h b/contrib/elftoolchain/libdwarf/_libdwarf.h
index e6eb496..6658d2d 100644
--- a/contrib/elftoolchain/libdwarf/_libdwarf.h
+++ b/contrib/elftoolchain/libdwarf/_libdwarf.h
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: _libdwarf.h 3164 2015-02-19 01:20:12Z kaiwang27 $
+ * $Id: _libdwarf.h 3298 2016-01-09 15:43:31Z jkoshy $
*/
#ifndef __LIBDWARF_H_
@@ -92,8 +92,8 @@ extern struct _libdwarf_globals _libdwarf;
typedef struct _Dwarf_CU *Dwarf_CU;
struct _Dwarf_AttrDef {
- uint64_t ad_attrib; /* DW_AT_XXX */
- uint64_t ad_form; /* DW_FORM_XXX */
+ Dwarf_Half ad_attrib; /* DW_AT_XXX */
+ Dwarf_Half ad_form; /* DW_FORM_XXX */
uint64_t ad_offset; /* Offset in abbrev section. */
STAILQ_ENTRY(_Dwarf_AttrDef) ad_next; /* Next attribute define. */
};
@@ -102,8 +102,8 @@ struct _Dwarf_Attribute {
Dwarf_Die at_die; /* Ptr to containing DIE. */
Dwarf_Die at_refdie; /* Ptr to reference DIE. */
uint64_t at_offset; /* Offset in info section. */
- uint64_t at_attrib; /* DW_AT_XXX */
- uint64_t at_form; /* DW_FORM_XXX */
+ Dwarf_Half at_attrib; /* DW_AT_XXX */
+ Dwarf_Half at_form; /* DW_FORM_XXX */
int at_indirect; /* Has indirect form. */
union {
uint64_t u64; /* Unsigned value. */
diff --git a/contrib/elftoolchain/libdwarf/dwarf.3 b/contrib/elftoolchain/libdwarf/dwarf.3
index dbb4179..863bee6 100644
--- a/contrib/elftoolchain/libdwarf/dwarf.3
+++ b/contrib/elftoolchain/libdwarf/dwarf.3
@@ -21,7 +21,7 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
-.\" $Id: dwarf.3 3195 2015-05-12 17:22:19Z emaste $
+.\" $Id: dwarf.3 3295 2016-01-08 22:08:10Z jkoshy $
.\"
.Dd December 21, 2014
.Os
@@ -110,9 +110,7 @@ A pointer to an error handling function.
.It Vt Dwarf_Line
A descriptor for a source line.
.It Vt Dwarf_Off
-An unsigned file offset, corresponding to an
-.Vt off_t
-type supported by the underlying operating system.
+An unsigned file offset.
.It Vt Dwarf_P_Expr
A descriptor for a location expression.
.It Vt Dwarf_Ptr
diff --git a/contrib/elftoolchain/libdwarf/dwarf_str.c b/contrib/elftoolchain/libdwarf/dwarf_str.c
index 71a7f75..c402f21 100644
--- a/contrib/elftoolchain/libdwarf/dwarf_str.c
+++ b/contrib/elftoolchain/libdwarf/dwarf_str.c
@@ -26,7 +26,7 @@
#include "_libdwarf.h"
-ELFTC_VCSID("$Id: dwarf_str.c 2075 2011-10-27 03:47:28Z jkoshy $");
+ELFTC_VCSID("$Id: dwarf_str.c 3295 2016-01-08 22:08:10Z jkoshy $");
int
dwarf_get_str(Dwarf_Debug dbg, Dwarf_Off offset, char **string,
@@ -34,7 +34,7 @@ dwarf_get_str(Dwarf_Debug dbg, Dwarf_Off offset, char **string,
{
Dwarf_Section *ds;
- if (dbg == NULL || offset < 0 || string == NULL || ret_strlen == NULL) {
+ if (dbg == NULL || string == NULL || ret_strlen == NULL) {
DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
return (DW_DLV_ERROR);
}
@@ -45,12 +45,12 @@ dwarf_get_str(Dwarf_Debug dbg, Dwarf_Off offset, char **string,
return (DW_DLV_NO_ENTRY);
}
- if ((Dwarf_Unsigned) offset > ds->ds_size) {
+ if (offset > ds->ds_size) {
DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
return (DW_DLV_ERROR);
}
- if ((Dwarf_Unsigned) offset == ds->ds_size) {
+ if (offset == ds->ds_size) {
DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
return (DW_DLV_NO_ENTRY);
}
diff --git a/contrib/elftoolchain/libdwarf/libdwarf.h b/contrib/elftoolchain/libdwarf/libdwarf.h
index 0cb8b1a..02f0ce5 100644
--- a/contrib/elftoolchain/libdwarf/libdwarf.h
+++ b/contrib/elftoolchain/libdwarf/libdwarf.h
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: libdwarf.h 3174 2015-03-27 17:13:41Z emaste $
+ * $Id: libdwarf.h 3295 2016-01-08 22:08:10Z jkoshy $
*/
#ifndef _LIBDWARF_H_
@@ -33,7 +33,7 @@
#include <libelf.h>
typedef int Dwarf_Bool;
-typedef off_t Dwarf_Off;
+typedef uint64_t Dwarf_Off;
typedef uint64_t Dwarf_Unsigned;
typedef uint16_t Dwarf_Half;
typedef uint8_t Dwarf_Small;
diff --git a/contrib/elftoolchain/libdwarf/libdwarf_rw.c b/contrib/elftoolchain/libdwarf/libdwarf_rw.c
index 8cb4551..f0286d5 100644
--- a/contrib/elftoolchain/libdwarf/libdwarf_rw.c
+++ b/contrib/elftoolchain/libdwarf/libdwarf_rw.c
@@ -27,7 +27,7 @@
#include "_libdwarf.h"
-ELFTC_VCSID("$Id: libdwarf_rw.c 2952 2013-06-26 19:09:40Z kaiwang27 $");
+ELFTC_VCSID("$Id: libdwarf_rw.c 3286 2015-12-31 16:45:46Z emaste $");
uint64_t
_dwarf_read_lsb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
@@ -42,10 +42,13 @@ _dwarf_read_lsb(uint8_t *data, uint64_t *offsetp, int bytes_to_read)
case 8:
ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
+ /* FALLTHROUGH */
case 4:
ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
+ /* FALLTHROUGH */
case 2:
ret |= ((uint64_t) src[1]) << 8;
+ /* FALLTHROUGH */
case 1:
ret |= src[0];
break;
@@ -71,10 +74,13 @@ _dwarf_decode_lsb(uint8_t **data, int bytes_to_read)
case 8:
ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
+ /* FALLTHROUGH */
case 4:
ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
+ /* FALLTHROUGH */
case 2:
ret |= ((uint64_t) src[1]) << 8;
+ /* FALLTHROUGH */
case 1:
ret |= src[0];
break;
@@ -171,11 +177,14 @@ _dwarf_write_lsb(uint8_t *data, uint64_t *offsetp, uint64_t value,
dst[6] = (value >> 48) & 0xff;
dst[5] = (value >> 40) & 0xff;
dst[4] = (value >> 32) & 0xff;
+ /* FALLTHROUGH */
case 4:
dst[3] = (value >> 24) & 0xff;
dst[2] = (value >> 16) & 0xff;
+ /* FALLTHROUGH */
case 2:
dst[1] = (value >> 8) & 0xff;
+ /* FALLTHROUGH */
case 1:
dst[0] = value & 0xff;
break;
@@ -222,13 +231,16 @@ _dwarf_write_msb(uint8_t *data, uint64_t *offsetp, uint64_t value,
dst[5] = (value >> 16) & 0xff;
dst[4] = (value >> 24) & 0xff;
value >>= 32;
+ /* FALLTHROUGH */
case 4:
dst[3] = value & 0xff;
dst[2] = (value >> 8) & 0xff;
value >>= 16;
+ /* FALLTHROUGH */
case 2:
dst[1] = value & 0xff;
value >>= 8;
+ /* FALLTHROUGH */
case 1:
dst[0] = value & 0xff;
break;
diff --git a/contrib/elftoolchain/libdwarf/os.NetBSD.mk b/contrib/elftoolchain/libdwarf/os.NetBSD.mk
new file mode 100644
index 0000000..ae214e3
--- /dev/null
+++ b/contrib/elftoolchain/libdwarf/os.NetBSD.mk
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
diff --git a/contrib/elftoolchain/libelf/_libelf_config.h b/contrib/elftoolchain/libelf/_libelf_config.h
index 602eb89..1bcf333 100644
--- a/contrib/elftoolchain/libelf/_libelf_config.h
+++ b/contrib/elftoolchain/libelf/_libelf_config.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: _libelf_config.h 3168 2015-02-24 19:17:47Z emaste $
+ * $Id: _libelf_config.h 3396 2016-02-10 21:50:05Z emaste $
*/
#if defined(__APPLE__) || defined(__DragonFly__)
diff --git a/contrib/elftoolchain/libelftc/Makefile b/contrib/elftoolchain/libelftc/Makefile
index a5fc297..4af496b 100644
--- a/contrib/elftoolchain/libelftc/Makefile
+++ b/contrib/elftoolchain/libelftc/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile 2859 2013-01-05 09:21:54Z jkoshy $
+# $Id: Makefile 3292 2016-01-06 21:46:32Z jkoshy $
TOP= ${.CURDIR}/..
@@ -45,16 +45,7 @@ MLINKS= elftc_bfd_find_target.3 elftc_bfd_target_byteorder.3 \
elftc_string_table_create.3 elftc_string_table_destroy.3 \
elftc_string_table_create.3 elftc_string_table_image.3 \
elftc_string_table_create.3 elftc_string_table_insert.3 \
- elftc_string_table_create.3 elftc_string_table_lookup.3 \
- elftc_symbol_table_create.3 elftc_symbol_table_create_nested.3 \
- elftc_symbol_table_create.3 elftc_symbol_table_delete_name.3 \
- elftc_symbol_table_create.3 elftc_symbol_table_delete_entry.3 \
- elftc_symbol_table_create.3 elftc_symbol_table_destroy.3 \
- elftc_symbol_table_create.3 elftc_symbol_table_from_section.3 \
- elftc_symbol_table_create.3 elftc_symbol_table_insert.3 \
- elftc_symbol_table_create.3 elftc_symbol_table_iterate.3 \
- elftc_symbol_table_create.3 elftc_symbol_table_lookup.3 \
- elftc_symbol_table_create.3 elftc_symbol_table_to_image.3
+ elftc_string_table_create.3 elftc_string_table_lookup.3
.if !make(clean) && !make(clobber)
.BEGIN: .SILENT
diff --git a/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3 b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3
index 851ae31..20dea3c 100644
--- a/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3
+++ b/contrib/elftoolchain/libelftc/elftc_bfd_find_target.3
@@ -21,7 +21,7 @@
.\" out of the use of this software, even if advised of the possibility of
.\" such damage.
.\"
-.\" $Id: elftc_bfd_find_target.3 2251 2011-11-30 16:50:06Z jkoshy $
+.\" $Id: elftc_bfd_find_target.3 3348 2016-01-18 14:18:50Z emaste $
.\"
.Dd November 30, 2011
.Os
@@ -58,9 +58,11 @@ Binary object descriptors encapsulate properties of an object format
such as its file representation, ELF class, and byte endianness.
.Pp
Known descriptor names and their properties include:
-.Bl -column -offset "XXXX" ".Li elf32-x86-64-freebsd" "Object format" "Byte Order" "ELF Class"
-.It Em Name Ta Em "Object Format" Ta Em "Byte Order" Ta Em "ELF Class"
+.Bl -column -offset "XXXX" ".Li elf32-x86-64-freebsd" "Object format" "Byte Order" "Bit Width"
+.It Em Name Ta Em "Object Format" Ta Em "Byte Order" Ta Em "Bit Width"
.It Li binary Ta Binary Ta - Ta -
+.It Li efi-app-ia32 Ta PE Ta LSB Ta 32
+.It Li efi-app-x86_64 Ta PE Ta LSB Ta 64
.It Li elf32-avr Ta ELF Ta LSB Ta 32
.It Li elf32-big Ta ELF Ta MSB Ta 32
.It Li elf32-bigarm Ta ELF Ta MSB Ta 32
@@ -101,6 +103,8 @@ Known descriptor names and their properties include:
.It Li elf64-x86-64 Ta ELF Ta LSB Ta 64
.It Li elf64-x86-64-freebsd Ta ELF Ta LSB Ta 64
.It Li ihex Ta IHEX Ta - Ta -
+.It Li pei-i386 Ta PE Ta LSB Ta 32
+.It Li pei-x86-64 Ta PE Ta LSB Ta 64
.It Li srec Ta SREC Ta - Ta -
.It Li symbolsrec Ta SREC Ta - Ta -
.El
diff --git a/contrib/elftoolchain/libelftc/elftc_copyfile.c b/contrib/elftoolchain/libelftc/elftc_copyfile.c
index 7df1678..dac9c14 100644
--- a/contrib/elftoolchain/libelftc/elftc_copyfile.c
+++ b/contrib/elftoolchain/libelftc/elftc_copyfile.c
@@ -37,7 +37,7 @@
#include <sys/mman.h>
#endif
-ELFTC_VCSID("$Id: elftc_copyfile.c 2981 2014-02-01 02:41:13Z jkoshy $");
+ELFTC_VCSID("$Id: elftc_copyfile.c 3297 2016-01-09 15:26:34Z jkoshy $");
/*
* Copy the contents referenced by 'ifd' to 'ofd'. Returns 0 on
@@ -47,11 +47,11 @@ ELFTC_VCSID("$Id: elftc_copyfile.c 2981 2014-02-01 02:41:13Z jkoshy $");
int
elftc_copyfile(int ifd, int ofd)
{
+ size_t file_size, n;
int buf_mmapped;
struct stat sb;
char *b, *buf;
- ssize_t nw;
- size_t n;
+ ssize_t nr, nw;
/* Determine the input file's size. */
if (fstat(ifd, &sb) < 0)
@@ -63,12 +63,13 @@ elftc_copyfile(int ifd, int ofd)
buf = NULL;
buf_mmapped = 0;
+ file_size = (size_t) sb.st_size;
#if ELFTC_HAVE_MMAP
/*
* Prefer mmap() if it is available.
*/
- buf = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, ifd, (off_t) 0);
+ buf = mmap(NULL, file_size, PROT_READ, MAP_SHARED, ifd, (off_t) 0);
if (buf != MAP_FAILED)
buf_mmapped = 1;
else
@@ -80,24 +81,27 @@ elftc_copyfile(int ifd, int ofd)
* failed, allocate a buffer, and read in input data.
*/
if (buf_mmapped == false) {
- if ((buf = malloc(sb.st_size)) == NULL)
- return (-1);
- if (read(ifd, buf, sb.st_size) != sb.st_size) {
- free(buf);
+ if ((buf = malloc(file_size)) == NULL)
return (-1);
+ b = buf;
+ for (n = file_size; n > 0; n -= (size_t) nr, b += nr) {
+ if ((nr = read(ifd, b, n)) < 0) {
+ free(buf);
+ return (-1);
+ }
}
}
/*
* Write data to the output file descriptor.
*/
- for (n = sb.st_size, b = buf; n > 0; n -= nw, b += nw)
+ for (n = file_size, b = buf; n > 0; n -= (size_t) nw, b += nw)
if ((nw = write(ofd, b, n)) <= 0)
break;
/* Release the input buffer. */
#if ELFTC_HAVE_MMAP
- if (buf_mmapped && munmap(buf, sb.st_size) < 0)
+ if (buf_mmapped && munmap(buf, file_size) < 0)
return (-1);
#endif
diff --git a/contrib/elftoolchain/libelftc/elftc_demangle.c b/contrib/elftoolchain/libelftc/elftc_demangle.c
index ff30955..945f777 100644
--- a/contrib/elftoolchain/libelftc/elftc_demangle.c
+++ b/contrib/elftoolchain/libelftc/elftc_demangle.c
@@ -33,10 +33,10 @@
#include "_libelftc.h"
-ELFTC_VCSID("$Id: elftc_demangle.c 3174 2015-03-27 17:13:41Z emaste $");
+ELFTC_VCSID("$Id: elftc_demangle.c 3296 2016-01-09 14:17:28Z jkoshy $");
-static int
-is_mangled(const char *s, int style)
+static unsigned int
+is_mangled(const char *s, unsigned int style)
{
switch (style) {
@@ -58,7 +58,7 @@ is_mangled(const char *s, int style)
}
static char *
-demangle(const char *s, int style, int rc)
+demangle(const char *s, unsigned int style, unsigned int rc)
{
(void) rc; /* XXX */
@@ -76,7 +76,7 @@ int
elftc_demangle(const char *mangledname, char *buffer, size_t bufsize,
unsigned int flags)
{
- int style, rc;
+ unsigned int style, rc;
char *rlt;
style = flags & 0xFFFF;
diff --git a/contrib/elftoolchain/libelftc/elftc_symbol_table_create.3 b/contrib/elftoolchain/libelftc/elftc_symbol_table_create.3
deleted file mode 100644
index 76f90e9..0000000
--- a/contrib/elftoolchain/libelftc/elftc_symbol_table_create.3
+++ /dev/null
@@ -1,529 +0,0 @@
-.\" Copyright (c) 2012 Joseph Koshy. 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. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" This software is provided by Joseph Koshy ``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 Joseph Koshy 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.
-.\"
-.\" $Id: elftc_symbol_table_create.3 3182 2015-04-10 16:08:10Z emaste $
-.\"
-.Dd December 29, 2012
-.Os
-.Dt ELFTC_SYMBOL_TABLE_CREATE 3
-.Sh NAME
-.Nm elftc_elf_symbol_table_from_section ,
-.Nm elftc_symbol_table_count ,
-.Nm elftc_symbol_table_create ,
-.Nm elftc_symbol_table_create_nested ,
-.Nm elftc_symbol_table_delete_name ,
-.Nm elftc_symbol_table_delete_entry ,
-.Nm elftc_symbol_table_destroy ,
-.Nm elftc_symbol_table_insert ,
-.Nm elftc_symbol_table_iterate ,
-.Nm elftc_symbol_table_lookup ,
-.Nm elftc_symbol_table_lookup_value ,
-.Nm elftc_symbol_table_replace ,
-.Nm elftc_symbol_table_sort ,
-.Nm elftc_symbol_table_step
-.Nd symbol table management routines
-.Sh SYNOPSIS
-.In libelftc.h
-.Bd -literal
-typedef struct _Elftc_Symbol_Table Elftc_Symbol_Table;
-
-typedef struct _Elftc_Symbol {
- ... library private fields ...
- const char *sym_name;
- uintptr_t sym_value;
-} Elftc_Symbol;
-.Ed
-.Ft size_t
-.Fn elftc_symbol_table_count "Elftc_Symbol_Table *table"
-.Ft "Elftc_Symbol_Table *"
-.Fo elftc_symbol_table_create
-.Fa "size_t entrysize"
-.Fa "int sizehint"
-.Fc
-.Ft "Elftc_Symbol_Table *"
-.Fo elftc_symbol_table_create_nested
-.Fa "Elftc_Symbol_Table *table"
-.Fa "int sizehint"
-.Fc
-.Ft int
-.Fo elftc_symbol_table_delete_name
-.Fa "Elftc_Symbol_Table *table"
-.Fa "const char *name"
-.Fc
-.Ft int
-.Fo elftc_symbol_table_delete_entry
-.Fa "Elftc_Symbol_Table *table"
-.Fa "Elftc_Symbol *entry"
-.Fc
-.Ft int
-.Fn elftc_symbol_table_destroy "Elftc_Symbol_Table *table"
-.Ft "Elftc_Symbol *entry"
-.Fo elftc_symbol_table_insert
-.Fa "Elftc_Symbol_Table *table"
-.Fa "const char *symbolname"
-.Fa "int *status"
-.Fc
-.Ft int
-.Fo elftc_symbol_table_iterate
-.Fa "Elftc_Symbol_Table *table"
-.Fa "int (*iterfn)(Elftc_Symbol *entry, void *cookie)"
-.Fa "void *cookie"
-.Fc
-.Ft "Elftc_Symbol *"
-.Fo elftc_symbol_table_lookup
-.Fa "Elftc_Symbol_Table *table"
-.Fa "const char *symbolname"
-.Fc
-.Ft "Elftc_Elf_Symbol *"
-.Fo elftc_symbol_table_lookup_value
-.Fa "Elftc_Symbol_Table *table"
-.Fa "uintptr_t value"
-.Fa "int searchflags"
-.Fc
-.Ft int
-.Fo elftc_symbol_table_replace
-.Fa "Elftc_Symbol_Table *table"
-.Fa "Elftc_Symbol *sym1"
-.Fa "Elftc_Symbol *sym2"
-.Fc
-.Ft int
-.Fo elftc_symbol_table_sort
-.Fa "Elftc_Symbol_Table *table"
-.Fa "int (*cmpfn)(Elftc_Symbol *s1, Elftc_Symbol *s2)"
-.Fc
-.Ft "Elftc_Symbol *"
-.Fo elftc_symbol_table_step
-.Fa "Elftc_Symbol_Table *table"
-.Fa "Elftc_Symbol *cursym"
-.Fa "int direction"
-.Fc
-.Bd -literal
-typedef struct _Elftc_Elf_Symbol {
- ... library private fields ...
- const char *sym_name;
- Gelf_Sym sym_elf;
-} Elftc_Elf_Symbol;
-.Ed
-.Ft "Elftc_Symbol_Table *"
-.Fo elftc_elf_symbol_table_from_section
-.Fa "Elf_Scn *symscn"
-.Fa "Elf_Scn *strscn"
-.Fc
-.Sh DESCRIPTION
-This manual page documents convenience routines for handling symbol
-tables.
-Two flavors of symbol tables are supported:
-.Bl -bullet -compact
-.It
-.Dq Regular
-symbol tables supporting insertion, deletion and lookup of entries by
-name or by value, sorting of entries, and stepping through entries in
-the table's current traversal order.
-.It
-.Dq ELF-centric
-symbol tables support additional operations for conversions to and
-from the symbol table format understood by
-.Lb libelf .
-.El
-The default traversal order for a symbol table is the order in which
-entries were inserted into it.
-This traversal order may be changed using function
-.Fn elftc_symbol_table_sort .
-.Ss Operations on Regular Symbol Tables
-Regular symbol tables use symbols that are subtypes of
-.Vt Elftc_Symbol ,
-as described in the section
-.Sx "Structure of a Symbol Table Entry"
-below.
-.Pp
-Function
-.Fn elftc_symbol_table_count
-returns the number of entries currently in the symbol table.
-.Pp
-Function
-.Fn elftc_symbol_table_create
-creates a new, empty symbol table.
-The argument
-.Ar entrysize
-specifies the size of each symbol table entry, as described
-in the section
-.Sx "Structure of a Symbol Table Entry"
-below.
-The argument
-.Ar sizehint
-specifies the expected number of symbol table entries.
-If
-.Ar sizehint
-is zero, an implementation-defined default will be used.
-.Pp
-Function
-.Fn elftc_symbol_table_create_nested
-creates a symbol table whose search scope nests inside that of a
-parent symbol table.
-The argument
-.Ar parent
-specifies the parent symbol table to nest under.
-The argument
-.Ar sizehint
-specifies the expected number of symbol table entries.
-If
-.Ar sizehint
-is zero, an implementation-defined default will be used instead.
-.Pp
-The function
-.Fn elftc_symbol_table_delete_name
-removes the symbol entry named by the argument
-.Ar name
-from the symbol table specified by argument
-.Ar table ,
-according to the rules described in section
-.Sx "Symbol Search Rules" .
-.Pp
-The function
-.Fn elftc_symbol_table_delete_entry
-removes the symbol table entry specified by argument
-.Ar entry
-from the symbol table specified by argument
-.Ar table .
-.Pp
-Function
-.Fn elftc_symbol_table_destroy
-is used to destroy a symbol table and free up its internal
-resources.
-.Pp
-The function
-.Fn elftc_symbol_table_insert
-inserts a symbol entry for the name specified by argument
-.Ar symbolname
-into the symbol table specified by argument
-.Ar table ,
-returning a pointer to a symbol table entry.
-The argument
-.Ar status
-should point to a location that will be updated with one of
-the following values:
-.Bl -tag -width indent -compact -offset indent
-.It Dv ELFTC_INSERT_ERROR
-An error occurred during insertion of the symbol.
-.It Dv ELFTC_INSERT_EXISTING
-The name in argument
-.Ar symbolname
-was already in the symbol table, and a pointer to the existing
-symbol table entry is being returned.
-.It Dv ELFTC_INSERT_NEW
-A new symbol table entry was allocated for the symbol name
-in
-.Ar symbolname .
-The application will need to initialize the application-specific
-fields of the symbol table entry.
-.El
-Insertion obeys the scoping rules described in section
-.Sx "Symbol Search Rules" .
-.Pp
-The function
-.Fn elftc_symbol_table_iterate
-iterates over the symbol table specifed by argument
-.Ar table ,
-applying the function pointed to by argument
-.Ar iterfn
-to each symbol table entry.
-The return value from the function
-.Ar iterfn
-controls progress of the iteration:
-.Bl -tag -width indent -compact -offset indent
-.It Dv ELFTC_ITERATE_ABORT
-Terminates the iteration.
-.It Dv ELFTC_ITERATE_CONTINUE
-Iteration will continue on to the next element in the symbol table.
-.El
-Argument
-.Ar cookie
-will be passed to each invocation of
-.Ar iterfn ,
-and may be used to track persistent state.
-The ordering of symbol table entries presented to function
-.Ar iterfn
-is not defined.
-The behavior of the iteration is undefined if
-.Ar iterfn
-adds or deletes symbol entries from a symbol table that currently
-being iterated through.
-.Pp
-Function
-.Fn elftc_symbol_table_lookup
-returns the symbol entry corresponding to the name of the symbol
-in argument
-.Ar symbolname .
-.Pp
-Function
-.Fn elftc_symbol_table_lookup_value
-returns the symbol entry that has a
-.Va sym_value
-field that is closest to the value specified in argument
-.Ar value .
-The argument
-.Ar table
-should point to a symbol table, that has been sorted
-by a prior call to
-.Fn elftc_symbol_table_sort .
-The argument
-.Ar searchflags
-can be a combination of the following flags:
-.Bl -tag -width indent -compact -offset indent
-.It Dv ELFTC_SEARCH_FORWARD
-Find the symbol entry with the next higher value in its
-.Va sym_value
-field.
-.It Dv ELFTC_SEARCH_BACKWARD
-Find the symbol entry with next lower value in its
-.Va sym_value
-field.
-.El
-If both
-.Dv ELFTC_SEARCH_FORWARD
-and
-.Dv ELFTC_SEARCH_BACKWARD
-are specified, then this function will return the symbol that is
-closest to the argument
-.Ar value .
-.Pp
-Function
-.Fn elftc_symbol_table_replace
-moves the symbol table entry pointed to by argument
-.Ar sym2
-into the traversal position for the entry pointed to by
-.Ar sym1 ,
-and implicitly deletes the entry pointed to by argument
-.Ar sym1 .
-Argument
-.Ar table
-should point to a valid symbol table.
-.Pp
-Function
-.Fn elftc_symbol_table_sort
-is used to define an ordering of symbol entries in a symbol
-table.
-This ordering will be associated with the symbol table till the next
-call to function
-.Fn elftc_symbol_table_insert ,
-.Fn elftc_symbol_table_delete_name
-or
-.Fn elftc_symbol_table_delete_entry .
-The argument
-.Ar cmpfn
-should point to a function that compares two symbol entries pointed
-to by
-.Ar s1
-and
-.Ar s2
-and returns -1, 0, or 1, depending whether
-.Ar s1
-is less, equal to, or greater than
-.Ar s2
-respectively.
-.Pp
-Function
-.Fn elftc_symbol_table_step
-is used to step to the next symbol in a sorted symbol table.
-Argument
-.Ar table
-should point to a symbol table.
-The argument
-.Ar cursym
-specifies the current symbol.
-The argument
-.Ar direction
-specifies the direction to step:
-.Bl -tag -width indent -compact -offset ident
-.It Dv ELFTC_STEP_NEXT
-Return the symbol which follows the argument
-.Ar cursym
-in the current traversal order.
-If argument
-.Ar cursym
-is NULL, return the first symbol in the current
-traversal order.
-.It Dv ELFTC_STEP_PREVIOUS
-Return the symbol which precedes the argument
-.Ar cursym
-in the current traversal order.
-If argument
-.Ar cursym
-is NULL, return the last symbol in the current
-traversal order.
-.El
-.Ss Operations on ELF-centric symbol tables
-ELF-centric symbol tables use symbols that are subtypes of
-.Vt Elftc_Elf_Symbol ,
-as described in the section
-.Sx "Structure of a Symbol Table Entry"
-below.
-.Pp
-In addition to the operations on regular symbol tables listed above,
-these symbol tables may be used with the following additional
-functions.
-.Pp
-The function
-.Fn elftc_elf_symbol_table_from_section
-builds a symbol table from the contents of an ELF section.
-The argument
-.Ar symscn
-should reference an ELF section of type
-.Dv SHT_SYMTAB
-or
-.Dv SHT_DYNSYM .
-The argument
-.Ar strscn
-should reference an ELF section of type
-.Dv SHT_STRTAB
-containing the string table associated wit section
-.Ar symscn .
-.Ss Structure of a Symbol Table Entry
-The symbol tables managed by
-.Lb libelftc
-are collections of symbol table entries.
-Each entry should be a subtype of one of the
-.Vt Elftc_Symbol
-or
-.Vt Elftc_Elf_Symbol
-types.
-In other words, each entry should have an
-.Vt Elftc_Symbol
-or
-.Vt Elftc_Elf_Symbol
-structure as its first member, before any application specific
-fields.
-For example:
-.Bd -literal -offset indent
-struct _MySymbol {
- Elftc_Symbol sym_base;
- ... other application-specific fields ...
-};
-.Ed
-.Pp
-The size of the combined entry is indicated to the library
-at the time of creating a new symbol table.
-Applications may then cast the returned pointers from these
-routines to the appropriate type:
-.Bd -literal -offset indent
-struct _MySymbol *mysym;
-
-mysym = (struct _MySymbol *) elftc_symbol_table_lookup(table,
- name);
-.Ed
-.Pp
-The
-.Vt Elftc_Symbol
-type has two public fields:
-.Bl -tag -width ".Va sym_value" -compact -offset indent
-.It Va sym_name
-Points to a NUL-terminated string containing the symbol's name.
-The application should not change the value of this field.
-.It Va sym_value
-The value associated with this symbol.
-This field is entirely under the application's control.
-.El
-.Pp
-The
-.Vt Elftc_Elf_Symbol
-type has two public fields:
-.Bl -tag -width ".Va sym_value" -compact -offset indent
-.It Va sym_name
-Points to a NUL-terminated string containing the symbol's name.
-The application should not change the value of this field.
-.It Va sym_elf
-A structure of type
-.Vt Gelf_Sym
-containing ELF symbol information.
-This field is entirely under the application's control.
-.El
-.Ss Symbol Search Rules
-During lookups, symbols are looked up first in the symbol table passed in
-to the
-.Fn elftc_symbol_table_lookup
-function.
-If the specified symbol is not found, and if the symbol table has a
-parent, then the search continues recursively up the chain of parent
-symbol tables till either a matching symbol is found or till there are
-no more parent symbol tables to search in.
-.Pp
-Insertions and deletion only work on the specified symbol table and
-do not recurse into parent symbol tables.
-.Ss Memory Management
-The
-.Lb libelftc
-manages its memory allocations.
-Applications should not free the pointers returned by the
-API documented in this manual page.
-.Sh RETURN VALUES
-Function
-.Fn elftc_symbol_table_count
-returns a count of the number of symbol table entries as an unsigned
-value.
-.Pp
-Functions
-.Fn elftc_symbol_table_create ,
-.Fn elftc_symbol_table_create_nested
-and
-.Fn elftc_symbol_table_from_section
-return a pointer to an opaque structure of type
-.Vt Elftc_Symbol_Table
-on success, or return NULL in case of an error.
-.Pp
-Functions
-.Fn elftc_symbol_table_delete_name ,
-.Fn elftc_symbol_table_delete_name
-.Fn elftc_symbol_table_destroy ,
-.Fn elftc_symbol_table_replace
-and
-.Fn elftc_symbol_table_sort
-return a non-zero value on success, or return zero in case of an error.
-.Pp
-Functions
-.Fn elftc_symbol_table_insert ,
-.Fn elftc_symbol_table_lookup
-and
-.Fn elftc_symbol_table_lookup_value
-return a pointer to a structure that is a subtype of
-.Vt Elftc_Symbol
-on success, or return NULL in case of an error.
-.Pp
-The function
-.Fn elftc_symbol_table_step
-return a pointer to a structure that is a subtype of
-.Vt Elftc_Symbol
-on success.
-The function returns NULL if there are no more elements in the
-specified traversal direction.
-.Pp
-The function
-.Fn elftc_symbol_table_iterate
-returns
-.Dv ELFTC_ITERATE_SUCCESS
-if the symbol table was successfully traversed, or
-.Dv ELFTC_ITERATE_ABORT
-in case the iteration function aborted the traversal.
-.Sh SEE ALSO
-.Xr dwarf 3 ,
-.Xr elf 3 ,
-.Xr elftc 3
diff --git a/contrib/elftoolchain/libelftc/libelftc.h b/contrib/elftoolchain/libelftc/libelftc.h
index 062db31..e3adaf2 100644
--- a/contrib/elftoolchain/libelftc/libelftc.h
+++ b/contrib/elftoolchain/libelftc/libelftc.h
@@ -24,7 +24,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: users/kaiwang27/elftc/libelftc.h 392 2009-05-31 19:17:46Z kaiwang27 $
- * $Id: libelftc.h 3174 2015-03-27 17:13:41Z emaste $
+ * $Id: libelftc.h 3309 2016-01-10 09:10:51Z kaiwang27 $
*/
#ifndef _LIBELFTC_H_
@@ -46,7 +46,9 @@ typedef enum {
ETF_ELF,
ETF_BINARY,
ETF_SREC,
- ETF_IHEX
+ ETF_IHEX,
+ ETF_PE,
+ ETF_EFI,
} Elftc_Bfd_Target_Flavor;
/*
diff --git a/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c
index 00ba225..88f3220 100644
--- a/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c
+++ b/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c
@@ -30,7 +30,7 @@
#include "_libelftc.h"
-ELFTC_VCSID("$Id: libelftc_bfdtarget.c 3174 2015-03-27 17:13:41Z emaste $");
+ELFTC_VCSID("$Id: libelftc_bfdtarget.c 3309 2016-01-10 09:10:51Z kaiwang27 $");
struct _Elftc_Bfd_Target _libelftc_targets[] = {
@@ -375,6 +375,30 @@ struct _Elftc_Bfd_Target _libelftc_targets[] = {
},
{
+ .bt_name = "efi-app-ia32",
+ .bt_type = ETF_EFI,
+ .bt_machine = EM_386,
+ },
+
+ {
+ .bt_name = "efi-app-x86_64",
+ .bt_type = ETF_EFI,
+ .bt_machine = EM_X86_64,
+ },
+
+ {
+ .bt_name = "pei-i386",
+ .bt_type = ETF_PE,
+ .bt_machine = EM_386,
+ },
+
+ {
+ .bt_name = "pei-x86-64",
+ .bt_type = ETF_PE,
+ .bt_machine = EM_X86_64,
+ },
+
+ {
.bt_name = NULL,
.bt_type = ETF_NONE,
},
diff --git a/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c b/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c
index e8fd78f..f5ca7b3 100644
--- a/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c
+++ b/contrib/elftoolchain/libelftc/libelftc_dem_gnu3.c
@@ -36,7 +36,7 @@
#include "_libelftc.h"
-ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3212 2015-05-17 13:40:55Z kaiwang27 $");
+ELFTC_VCSID("$Id: libelftc_dem_gnu3.c 3291 2016-01-04 02:36:38Z emaste $");
/**
* @file cpp_demangle.c
@@ -1262,11 +1262,13 @@ cpp_demangle_read_encoding(struct cpp_demangle_data *ddata)
if (!cpp_demangle_push_str(ddata,
"non-transaction clone for ", 26))
return (0);
+ break;
case 't':
default:
if (!cpp_demangle_push_str(ddata,
"transaction clone for ", 22))
return (0);
+ break;
}
++ddata->cur;
return (cpp_demangle_read_encoding(ddata));
@@ -1895,35 +1897,35 @@ cpp_demangle_read_subst(struct cpp_demangle_data *ddata)
case SIMPLE_HASH('S', 'd'):
/* std::basic_iostream<char, std::char_traits<char> > */
- if (!cpp_demangle_push_str(ddata, "std::iostream", 19))
+ if (!cpp_demangle_push_str(ddata, "std::basic_iostream", 19))
return (0);
- ddata->last_sname = "iostream";
+ ddata->last_sname = "basic_iostream";
ddata->cur += 2;
if (*ddata->cur == 'I')
return (cpp_demangle_read_subst_stdtmpl(ddata,
- "std::iostream", 19));
+ "std::basic_iostream", 19));
return (1);
case SIMPLE_HASH('S', 'i'):
/* std::basic_istream<char, std::char_traits<char> > */
- if (!cpp_demangle_push_str(ddata, "std::istream", 18))
+ if (!cpp_demangle_push_str(ddata, "std::basic_istream", 18))
return (0);
- ddata->last_sname = "istream";
+ ddata->last_sname = "basic_istream";
ddata->cur += 2;
if (*ddata->cur == 'I')
return (cpp_demangle_read_subst_stdtmpl(ddata,
- "std::istream", 18));
+ "std::basic_istream", 18));
return (1);
case SIMPLE_HASH('S', 'o'):
/* std::basic_ostream<char, std::char_traits<char> > */
- if (!cpp_demangle_push_str(ddata, "std::ostream", 18))
+ if (!cpp_demangle_push_str(ddata, "std::basic_ostream", 18))
return (0);
- ddata->last_sname = "istream";
+ ddata->last_sname = "basic_ostream";
ddata->cur += 2;
if (*ddata->cur == 'I')
return (cpp_demangle_read_subst_stdtmpl(ddata,
- "std::ostream", 18));
+ "std::basic_ostream", 18));
return (1);
case SIMPLE_HASH('S', 's'):
diff --git a/contrib/elftoolchain/libelftc/make-toolchain-version b/contrib/elftoolchain/libelftc/make-toolchain-version
index ac6155a..8891258 100755
--- a/contrib/elftoolchain/libelftc/make-toolchain-version
+++ b/contrib/elftoolchain/libelftc/make-toolchain-version
@@ -3,7 +3,7 @@
# This script generates a project-wide version identifier for use by
# the `elftc_version()' API.
#
-# $Id: make-toolchain-version 2583 2012-09-14 09:49:25Z jkoshy $
+# $Id: make-toolchain-version 3299 2016-01-09 19:58:46Z jkoshy $
#
# Defaults.
@@ -64,7 +64,7 @@ done
curdir=`pwd`
cd ${top} || usage "ERROR: Cannot change directory to \"${top}\"."
-if [ -d .svn ]; then # FreeBSD and SF.Net sources.
+if [ -d .svn -o -d ../.svn ]; then # FreeBSD and SF.Net sources.
versionstring=" svn:"$(svnversion)
elif [ -d CVS ]; then # NetBSD.
versionstring=" cvs:unknown"
diff --git a/contrib/elftoolchain/libelftc/os.NetBSD.mk b/contrib/elftoolchain/libelftc/os.NetBSD.mk
new file mode 100644
index 0000000..ae214e3
--- /dev/null
+++ b/contrib/elftoolchain/libelftc/os.NetBSD.mk
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
diff --git a/contrib/elftoolchain/libpe/Makefile b/contrib/elftoolchain/libpe/Makefile
new file mode 100644
index 0000000..d02fb50
--- /dev/null
+++ b/contrib/elftoolchain/libpe/Makefile
@@ -0,0 +1,32 @@
+# $Id: Makefile 3349 2016-01-18 21:09:16Z jkoshy $
+
+TOP= ${.CURDIR}/..
+
+LIB= pe
+
+SRCS= libpe_buffer.c \
+ libpe_coff.c \
+ libpe_dos.c \
+ libpe_init.c \
+ libpe_rich.c \
+ libpe_section.c \
+ libpe_utils.c \
+ pe_buffer.c \
+ pe_cntl.c \
+ pe_coff.c \
+ pe_dos.c \
+ pe_flag.c \
+ pe_init.c \
+ pe_rich.c \
+ pe_section.c \
+ pe_symtab.c \
+ pe_update.c
+
+INCS= libpe.h pe.h
+INCSDIR= /usr/include
+
+SHLIB_MAJOR= 1
+
+WARNS?= 6
+
+.include "${TOP}/mk/elftoolchain.lib.mk"
diff --git a/contrib/elftoolchain/libpe/_libpe.h b/contrib/elftoolchain/libpe/_libpe.h
new file mode 100644
index 0000000..1a83a67
--- /dev/null
+++ b/contrib/elftoolchain/libpe/_libpe.h
@@ -0,0 +1,213 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $Id: _libpe.h 3312 2016-01-10 09:23:51Z kaiwang27 $
+ */
+
+#ifndef __LIBPE_H_
+#define __LIBPE_H_
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include "libpe.h"
+
+#include "_elftc.h"
+
+typedef struct _PE_SecBuf {
+ PE_Buffer sb_pb; /* application buffer */
+ PE_Scn *sb_ps; /* PE_Scn pointer */
+ unsigned int sb_flags; /* buffer flags */
+ STAILQ_ENTRY(_PE_SecBuf) sb_next;
+} PE_SecBuf;
+
+struct _PE_Scn {
+ PE *ps_pe; /* PE descriptor */
+ PE_SecHdr ps_sh; /* section header */
+ unsigned int ps_ndx; /* 1-based section index */
+ unsigned int ps_flags; /* section flags */
+ unsigned int ps_falign; /* section file alignment */
+ STAILQ_HEAD(, _PE_SecBuf) ps_b; /* buffer list */
+ STAILQ_ENTRY(_PE_Scn) ps_next;
+};
+
+struct _PE {
+ int pe_fd; /* file descriptor */
+ PE_Cmd pe_cmd; /* open mode */
+ PE_Object pe_obj; /* PE32/PE32+/COFF */
+ size_t pe_fsize; /* file size */
+ unsigned int pe_flags; /* library flags */
+ PE_DosHdr *pe_dh; /* MS-DOS header */
+ char *pe_stub; /* MS-DOS stub */
+ size_t pe_stub_ex; /* MS-DOS stub len (exclude hdr) */
+ char *pe_stub_app; /* MS-DOS stub (app supplied) */
+ size_t pe_stub_app_sz; /* MS-DOS stub len (app supplied) */
+ PE_RichHdr *pe_rh; /* rich header */
+ char *pe_rh_start; /* pointer to rich header */
+ PE_CoffHdr *pe_ch; /* COFF header */
+ PE_OptHdr *pe_oh; /* optional header */
+ PE_DataDir *pe_dd; /* data directories */
+ unsigned int pe_nscn; /* num. of sections */
+ char *pe_symtab; /* COFF symbol table */
+ size_t pe_symbtab_sz; /* size of symbol table */
+ unsigned int pe_nsym; /* num. of symbols */
+ unsigned int pe_rvamax; /* maximum RVA */
+ STAILQ_HEAD(, _PE_Scn) pe_scn; /* section list */
+};
+
+/* Library internal flags */
+#define LIBPE_F_API_MASK 0x000FFFU
+#define LIBPE_F_SPECIAL_FILE 0x001000U
+#define LIBPE_F_BAD_DOS_HEADER 0x002000U
+#define LIBPE_F_BAD_PE_HEADER 0x004000U
+#define LIBPE_F_BAD_COFF_HEADER 0x008000U
+#define LIBPE_F_BAD_OPT_HEADER 0x010000U
+#define LIBPE_F_BAD_SEC_HEADER 0x020000U
+#define LIBPE_F_LOAD_DOS_STUB 0x040000U
+#define LIBPE_F_FD_DONE 0x080000U
+#define LIBPE_F_DIRTY_DOS_HEADER 0x100000U
+#define LIBPE_F_DIRTY_COFF_HEADER 0x200000U
+#define LIBPE_F_DIRTY_OPT_HEADER 0x400000U
+#define LIBPE_F_DIRTY_SEC_HEADER 0x800000U
+
+/* Internal section flags */
+#define LIBPE_F_LOAD_SECTION 0x1000U
+#define LIBPE_F_STRIP_SECTION 0x2000U
+
+/* Internal buffer flags */
+#define LIBPE_F_BUFFER_MALLOCED 0x1000U
+
+/* Library internal defines */
+#define PE_DOS_MAGIC 0x5a4dU
+#define PE_RICH_TEXT "Rich"
+#define PE_RICH_HIDDEN 0x536e6144U /* DanS */
+#define PE_SIGNATURE 0x4550U /* PE\0\0 */
+#define PE_COFF_OPT_SIZE_32 224
+#define PE_COFF_OPT_SIZE_32P 240
+#define PE_SYM_ENTRY_SIZE 18
+
+/* Encode/Decode macros */
+#if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS)
+static __inline uint16_t
+le16dec(const void *pp)
+{
+ unsigned char const *p = (unsigned char const *)pp;
+
+ return ((p[1] << 8) | p[0]);
+}
+
+static __inline uint32_t
+le32dec(const void *pp)
+{
+ unsigned char const *p = (unsigned char const *)pp;
+
+ return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]);
+}
+
+static __inline uint64_t
+le64dec(const void *pp)
+{
+ unsigned char const *p = (unsigned char const *)pp;
+
+ return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p));
+}
+
+static __inline void
+le16enc(void *pp, uint16_t u)
+{
+ unsigned char *p = (unsigned char *)pp;
+
+ p[0] = u & 0xff;
+ p[1] = (u >> 8) & 0xff;
+}
+
+static __inline void
+le32enc(void *pp, uint32_t u)
+{
+ unsigned char *p = (unsigned char *)pp;
+
+ p[0] = u & 0xff;
+ p[1] = (u >> 8) & 0xff;
+ p[2] = (u >> 16) & 0xff;
+ p[3] = (u >> 24) & 0xff;
+}
+
+static __inline void
+le64enc(void *pp, uint64_t u)
+{
+ unsigned char *p = (unsigned char *)pp;
+
+ le32enc(p, (uint32_t)(u & 0xffffffffU));
+ le32enc(p + 4, (uint32_t)(u >> 32));
+}
+#endif /* ELFTC_NEED_BYTEORDER_EXTENSIONS */
+
+#define PE_READ16(p,v) do { \
+ (v) = le16dec((p)); \
+ (p) += 2; \
+} while(0)
+
+#define PE_READ32(p,v) do { \
+ (v) = le32dec((p)); \
+ (p) += 4; \
+} while(0)
+
+#define PE_WRITE16(p,v) do { \
+ le16enc((p), (v)); \
+ (p) += 2; \
+} while(0)
+
+#define PE_WRITE32(p,v) do { \
+ le32enc((p), (v)); \
+ (p) += 4; \
+} while(0)
+
+
+/* Internal function declarations */
+off_t libpe_align(PE *, off_t, size_t);
+PE_SecBuf *libpe_alloc_buffer(PE_Scn *, size_t);
+PE_Scn *libpe_alloc_scn(PE *);
+int libpe_load_all_sections(PE *);
+int libpe_load_section(PE *, PE_Scn *);
+int libpe_open_object(PE *);
+int libpe_pad(PE *, size_t);
+int libpe_parse_msdos_header(PE *, char *);
+int libpe_parse_coff_header(PE *, char *);
+int libpe_parse_rich_header(PE *);
+int libpe_parse_section_headers(PE *);
+int libpe_read_msdos_stub(PE *);
+void libpe_release_buffer(PE_SecBuf *);
+void libpe_release_object(PE *);
+void libpe_release_scn(PE_Scn *);
+size_t libpe_resync_buffers(PE_Scn *);
+int libpe_resync_sections(PE *, off_t);
+int libpe_write_buffers(PE_Scn *);
+off_t libpe_write_coff_header(PE *, off_t);
+off_t libpe_write_msdos_stub(PE *, off_t);
+off_t libpe_write_pe_header(PE *, off_t);
+off_t libpe_write_sections(PE *, off_t);
+off_t libpe_write_section_headers(PE *, off_t);
+
+#endif /* !__LIBPE_H_ */
diff --git a/contrib/elftoolchain/libpe/libpe.h b/contrib/elftoolchain/libpe/libpe.h
new file mode 100644
index 0000000..3cec39a
--- /dev/null
+++ b/contrib/elftoolchain/libpe/libpe.h
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $Id: libpe.h 3312 2016-01-10 09:23:51Z kaiwang27 $
+ */
+
+#ifndef _LIBPE_H_
+#define _LIBPE_H_
+
+#include <sys/types.h>
+
+#include "pe.h"
+
+/* Library private data structures */
+typedef struct _PE PE;
+typedef struct _PE_Scn PE_Scn;
+
+/* Section buffers */
+typedef struct PE_Buffer {
+ unsigned int pb_align;
+ off_t pb_off;
+ size_t pb_size;
+ void *pb_buf;
+} PE_Buffer;
+
+/* Object types */
+typedef enum {
+ PE_O_UNKNOWN = 0,
+ PE_O_PE32,
+ PE_O_PE32P,
+ PE_O_COFF,
+} PE_Object;
+
+/* Commands */
+typedef enum {
+ PE_C_NULL = 0,
+ PE_C_CLR,
+ PE_C_FDDONE,
+ PE_C_FDREAD,
+ PE_C_RDWR,
+ PE_C_READ,
+ PE_C_SET,
+ PE_C_WRITE,
+ PE_C_NUM
+} PE_Cmd;
+
+/* Flags defined by the API. */
+#define PE_F_DIRTY 0x001U
+#define PE_F_STRIP_DOS_STUB 0x002U
+#define PE_F_STRIP_RICH_HEADER 0x004U
+#define PE_F_STRIP_SYMTAB 0x008U
+#define PE_F_STRIP_DEBUG 0x010U
+#define PE_F_STRIP_SECTION 0x020U
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+PE_CoffHdr *pe_coff_header(PE *);
+int pe_cntl(PE *, PE_Cmd);
+PE_DataDir *pe_data_dir(PE *);
+void pe_finish(PE *);
+int pe_flag(PE *, PE_Cmd, unsigned int);
+int pe_flag_buffer(PE_Buffer *, PE_Cmd, unsigned int);
+int pe_flag_coff_header(PE *, PE_Cmd, unsigned int);
+int pe_flag_data_dir(PE *, PE_Cmd, unsigned int);
+int pe_flag_dos_header(PE *, PE_Cmd, unsigned int);
+int pe_flag_opt_header(PE *, PE_Cmd, unsigned int);
+int pe_flag_section_header(PE_Scn *, PE_Cmd, unsigned int);
+int pe_flag_scn(PE_Scn *, PE_Cmd, unsigned int);
+PE_Buffer *pe_getbuffer(PE_Scn *, PE_Buffer *);
+PE_Scn *pe_getscn(PE *, size_t);
+PE *pe_init(int, PE_Cmd, PE_Object);
+PE_Scn *pe_insertscn(PE *, size_t);
+PE_DosHdr *pe_msdos_header(PE *);
+char *pe_msdos_stub(PE *, size_t *);
+size_t pe_ndxscn(PE_Scn *);
+PE_Buffer *pe_newbuffer(PE_Scn *);
+PE_Scn *pe_newscn(PE *);
+PE_Scn *pe_nextscn(PE *, PE_Scn *);
+PE_Object pe_object(PE *);
+PE_OptHdr *pe_opt_header(PE *);
+PE_RichHdr *pe_rich_header(PE *);
+int pe_rich_header_validate(PE *);
+PE_SecHdr *pe_section_header(PE_Scn *);
+off_t pe_update(PE *);
+int pe_update_coff_header(PE *, PE_CoffHdr *);
+int pe_update_opt_header(PE *, PE_OptHdr *);
+int pe_update_data_dir(PE *, PE_DataDir *);
+int ps_update_msdos_header(PE *, PE_DosHdr *);
+int ps_update_msdos_stub(PE *, char *, size_t);
+int pe_update_section_header(PE_Scn *, PE_SecHdr *);
+int pe_update_symtab(PE *, char *, size_t, unsigned int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_LIBPE_H_ */
diff --git a/contrib/elftoolchain/libpe/libpe_buffer.c b/contrib/elftoolchain/libpe/libpe_buffer.c
new file mode 100644
index 0000000..cc633dd
--- /dev/null
+++ b/contrib/elftoolchain/libpe/libpe_buffer.c
@@ -0,0 +1,185 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/param.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_buffer.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_SecBuf *
+libpe_alloc_buffer(PE_Scn *ps, size_t sz)
+{
+ PE_SecBuf *sb;
+
+ if ((sb = malloc(sizeof(PE_SecBuf))) == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+
+ sb->sb_ps = ps;
+ sb->sb_flags = 0;
+ sb->sb_pb.pb_align = 1;
+ sb->sb_pb.pb_off = 0;
+ sb->sb_pb.pb_size = sz;
+ if (sz > 0) {
+ if ((sb->sb_pb.pb_buf = malloc(sz)) == NULL) {
+ free(sb);
+ errno = ENOMEM;
+ return (NULL);
+ }
+ sb->sb_flags |= LIBPE_F_BUFFER_MALLOCED;
+ } else
+ sb->sb_pb.pb_buf = NULL;
+
+ STAILQ_INSERT_TAIL(&ps->ps_b, sb, sb_next);
+
+ return (sb);
+}
+
+void
+libpe_release_buffer(PE_SecBuf *sb)
+{
+ PE_Scn *ps;
+
+ assert(sb != NULL);
+
+ ps = sb->sb_ps;
+
+ STAILQ_REMOVE(&ps->ps_b, sb, _PE_SecBuf, sb_next);
+
+ if (sb->sb_flags & LIBPE_F_BUFFER_MALLOCED)
+ free(sb->sb_pb.pb_buf);
+
+ free(sb);
+}
+
+static int
+cmp_sb(PE_SecBuf *a, PE_SecBuf *b)
+{
+
+ if (a->sb_pb.pb_off < b->sb_pb.pb_off)
+ return (-1);
+ else if (a->sb_pb.pb_off == b->sb_pb.pb_off)
+ return (0);
+ else
+ return (1);
+}
+
+static void
+sort_buffers(PE_Scn *ps)
+{
+
+ if (STAILQ_EMPTY(&ps->ps_b))
+ return;
+
+ STAILQ_SORT(&ps->ps_b, _PE_SecBuf, sb_next, cmp_sb);
+}
+
+size_t
+libpe_resync_buffers(PE_Scn *ps)
+{
+ PE_SecBuf *sb;
+ PE_Buffer *pb;
+ size_t sz;
+
+ assert(ps->ps_flags & LIBPE_F_LOAD_SECTION);
+
+ sort_buffers(ps);
+
+ sz = 0;
+ STAILQ_FOREACH(sb, &ps->ps_b, sb_next) {
+ if (ps->ps_flags & PE_F_DIRTY)
+ sb->sb_flags |= PE_F_DIRTY;
+
+ pb = (PE_Buffer *) sb;
+ if (pb->pb_align > ps->ps_falign)
+ pb->pb_align = ps->ps_falign;
+ if (pb->pb_buf == NULL || pb->pb_size == 0)
+ continue;
+
+ sz = roundup(sz, pb->pb_align);
+
+ if (pb->pb_off != (off_t) sz) {
+ pb->pb_off = sz;
+ sb->sb_flags |= PE_F_DIRTY;
+ }
+ sz += pb->pb_size;
+ }
+
+ return (sz);
+}
+
+int
+libpe_write_buffers(PE_Scn *ps)
+{
+ PE *pe;
+ PE_SecBuf *sb;
+ PE_Buffer *pb;
+ off_t off;
+
+ assert(ps->ps_flags & LIBPE_F_LOAD_SECTION);
+
+ pe = ps->ps_pe;
+
+ off = 0;
+ STAILQ_FOREACH(sb, &ps->ps_b, sb_next) {
+ pb = &sb->sb_pb;
+ if (pb->pb_buf == NULL || pb->pb_size == 0)
+ continue;
+
+ if ((sb->sb_flags & PE_F_DIRTY) == 0) {
+ assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+ if (lseek(pe->pe_fd, (off_t) pb->pb_size, SEEK_CUR) <
+ 0) {
+ errno = EIO;
+ return (-1);
+ }
+ goto next_buf;
+ }
+
+ if (pb->pb_off > off) {
+ if (libpe_pad(pe, pb->pb_off - off) < 0)
+ return (-1);
+ off = pb->pb_off;
+ }
+
+ if (write(pe->pe_fd, pb->pb_buf, pb->pb_size) !=
+ (ssize_t) pb->pb_size) {
+ errno = EIO;
+ return (-1);
+ }
+
+ next_buf:
+ off += pb->pb_size;
+ }
+
+ return (0);
+}
diff --git a/contrib/elftoolchain/libpe/libpe_coff.c b/contrib/elftoolchain/libpe/libpe_coff.c
new file mode 100644
index 0000000..e161f7c
--- /dev/null
+++ b/contrib/elftoolchain/libpe/libpe_coff.c
@@ -0,0 +1,535 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/param.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_coff.c 3326 2016-01-16 17:46:17Z kaiwang27 $");
+
+int
+libpe_parse_coff_header(PE *pe, char *hdr)
+{
+ char tmp[128];
+ PE_CoffHdr *ch;
+ PE_OptHdr *oh;
+ PE_DataDir *dd;
+ unsigned p, r, s;
+ int i;
+
+ if ((ch = malloc(sizeof(PE_CoffHdr))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ PE_READ16(hdr, ch->ch_machine);
+ PE_READ16(hdr, ch->ch_nsec);
+ PE_READ32(hdr, ch->ch_timestamp);
+ PE_READ32(hdr, ch->ch_symptr);
+ PE_READ32(hdr, ch->ch_nsym);
+ PE_READ16(hdr, ch->ch_optsize);
+ PE_READ16(hdr, ch->ch_char);
+
+ pe->pe_ch = ch;
+
+ /*
+ * The Optional header is omitted for object files.
+ */
+ if (ch->ch_optsize == 0)
+ return (libpe_parse_section_headers(pe));
+
+ if ((oh = calloc(1, sizeof(PE_OptHdr))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ pe->pe_oh = oh;
+
+#define READ_OPT(n) \
+ do { \
+ /* \
+ * Since the Optional Header size is variable, we must \
+ * check if the requested read size will overrun the \
+ * remaining header bytes. \
+ */ \
+ if (p + (n) > ch->ch_optsize) { \
+ /* Consume the "extra" bytes */ \
+ r = ch->ch_optsize - p; \
+ if (read(pe->pe_fd, tmp, r) != (ssize_t) r) { \
+ pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER;\
+ return (0); \
+ } \
+ return (libpe_parse_section_headers(pe)); \
+ } \
+ if (read(pe->pe_fd, tmp, (n)) != (ssize_t) (n)) { \
+ pe->pe_flags |= LIBPE_F_BAD_OPT_HEADER; \
+ return (0); \
+ } \
+ p += (n); \
+ } while (0)
+#define READ_OPT8(v) do { READ_OPT(1); (v) = *tmp; } while(0)
+#define READ_OPT16(v) do { READ_OPT(2); (v) = le16dec(tmp); } while(0)
+#define READ_OPT32(v) do { READ_OPT(4); (v) = le32dec(tmp); } while(0)
+#define READ_OPT64(v) do { READ_OPT(8); (v) = le64dec(tmp); } while(0)
+
+ /*
+ * Read in the Optional header. Size of some fields are depending
+ * on the PE format specified by the oh_magic field. (PE32 or PE32+)
+ */
+
+ p = 0;
+ READ_OPT16(oh->oh_magic);
+ if (oh->oh_magic == PE_FORMAT_32P)
+ pe->pe_obj = PE_O_PE32P;
+ READ_OPT8(oh->oh_ldvermajor);
+ READ_OPT8(oh->oh_ldverminor);
+ READ_OPT32(oh->oh_textsize);
+ READ_OPT32(oh->oh_datasize);
+ READ_OPT32(oh->oh_bsssize);
+ READ_OPT32(oh->oh_entry);
+ READ_OPT32(oh->oh_textbase);
+ if (oh->oh_magic != PE_FORMAT_32P) {
+ READ_OPT32(oh->oh_database);
+ READ_OPT32(oh->oh_imgbase);
+ } else
+ READ_OPT64(oh->oh_imgbase);
+ READ_OPT32(oh->oh_secalign);
+ READ_OPT32(oh->oh_filealign);
+ READ_OPT16(oh->oh_osvermajor);
+ READ_OPT16(oh->oh_osverminor);
+ READ_OPT16(oh->oh_imgvermajor);
+ READ_OPT16(oh->oh_imgverminor);
+ READ_OPT16(oh->oh_subvermajor);
+ READ_OPT16(oh->oh_subverminor);
+ READ_OPT32(oh->oh_win32ver);
+ READ_OPT32(oh->oh_imgsize);
+ READ_OPT32(oh->oh_hdrsize);
+ READ_OPT32(oh->oh_checksum);
+ READ_OPT16(oh->oh_subsystem);
+ READ_OPT16(oh->oh_dllchar);
+ if (oh->oh_magic != PE_FORMAT_32P) {
+ READ_OPT32(oh->oh_stacksizer);
+ READ_OPT32(oh->oh_stacksizec);
+ READ_OPT32(oh->oh_heapsizer);
+ READ_OPT32(oh->oh_heapsizec);
+ } else {
+ READ_OPT64(oh->oh_stacksizer);
+ READ_OPT64(oh->oh_stacksizec);
+ READ_OPT64(oh->oh_heapsizer);
+ READ_OPT64(oh->oh_heapsizec);
+ }
+ READ_OPT32(oh->oh_ldrflags);
+ READ_OPT32(oh->oh_ndatadir);
+
+ /*
+ * Read in the Data Directories.
+ */
+
+ if (oh->oh_ndatadir > 0) {
+ if ((dd = calloc(1, sizeof(PE_DataDir))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ pe->pe_dd = dd;
+
+ dd->dd_total = oh->oh_ndatadir < PE_DD_MAX ? oh->oh_ndatadir :
+ PE_DD_MAX;
+
+ for (i = 0; (uint32_t) i < dd->dd_total; i++) {
+ READ_OPT32(dd->dd_e[i].de_addr);
+ READ_OPT32(dd->dd_e[i].de_size);
+ }
+ }
+
+ /* Consume the remaining bytes in the Optional header, if any. */
+ if (ch->ch_optsize > p) {
+ r = ch->ch_optsize - p;
+ for (; r > 0; r -= s) {
+ s = r > sizeof(tmp) ? sizeof(tmp) : r;
+ if (read(pe->pe_fd, tmp, s) != (ssize_t) s) {
+ pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER;
+ return (0);
+ }
+ }
+ }
+
+ return (libpe_parse_section_headers(pe));
+}
+
+off_t
+libpe_write_pe_header(PE *pe, off_t off)
+{
+ char tmp[4];
+
+ if (pe->pe_cmd == PE_C_RDWR &&
+ (pe->pe_flags & LIBPE_F_BAD_PE_HEADER) == 0) {
+ assert(pe->pe_dh != NULL);
+ off = lseek(pe->pe_fd, (off_t) pe->pe_dh->dh_lfanew + 4,
+ SEEK_SET);
+ return (off);
+ }
+
+ /*
+ * PE Header should to be aligned on 8-byte boundary according to
+ * the PE/COFF specification.
+ */
+ if ((off = libpe_align(pe, off, 8)) < 0)
+ return (-1);
+
+ le32enc(tmp, PE_SIGNATURE);
+ if (write(pe->pe_fd, tmp, sizeof(tmp)) != (ssize_t) sizeof(tmp)) {
+ errno = EIO;
+ return (-1);
+ }
+
+ off += 4;
+
+ pe->pe_flags &= ~LIBPE_F_BAD_PE_HEADER;
+
+ /* Trigger rewrite for the following headers. */
+ pe->pe_flags |= LIBPE_F_DIRTY_COFF_HEADER;
+ pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
+
+ return (off);
+}
+
+off_t
+libpe_write_coff_header(PE *pe, off_t off)
+{
+ char tmp[128], *hdr;
+ PE_CoffHdr *ch;
+ PE_DataDir *dd;
+ PE_OptHdr *oh;
+ PE_Scn *ps;
+ PE_SecHdr *sh;
+ unsigned p;
+ uint32_t reloc_rva, reloc_sz;
+ int i, reloc;
+
+ reloc = 0;
+ reloc_rva = reloc_sz = 0;
+
+ if (pe->pe_cmd == PE_C_RDWR) {
+ assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+
+ if ((pe->pe_flags & LIBPE_F_DIRTY_COFF_HEADER) == 0 &&
+ (pe->pe_flags & LIBPE_F_BAD_COFF_HEADER) == 0) {
+ if (lseek(pe->pe_fd, (off_t) sizeof(PE_CoffHdr),
+ SEEK_CUR) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+ off += sizeof(PE_CoffHdr);
+ assert(pe->pe_ch != NULL);
+ ch = pe->pe_ch;
+ goto coff_done;
+ }
+
+ /* lseek(2) to the offset of the COFF header. */
+ if (lseek(pe->pe_fd, off, SEEK_SET) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+ }
+
+ if (pe->pe_ch == NULL) {
+ if ((ch = calloc(1, sizeof(PE_CoffHdr))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ pe->pe_ch = ch;
+
+ /*
+ * Default value for ch_machine if not provided by the
+ * application.
+ */
+ if (pe->pe_obj == PE_O_PE32P)
+ ch->ch_machine = IMAGE_FILE_MACHINE_AMD64;
+ else
+ ch->ch_machine = IMAGE_FILE_MACHINE_I386;
+
+ } else
+ ch = pe->pe_ch;
+
+ if (!ch->ch_timestamp)
+ ch->ch_timestamp = time(NULL);
+
+ if (pe->pe_obj == PE_O_PE32) {
+ if (!ch->ch_optsize)
+ ch->ch_optsize = PE_COFF_OPT_SIZE_32;
+ ch->ch_char |= IMAGE_FILE_EXECUTABLE_IMAGE |
+ IMAGE_FILE_32BIT_MACHINE;
+ } else if (pe->pe_obj == PE_O_PE32P) {
+ if (!ch->ch_optsize)
+ ch->ch_optsize = PE_COFF_OPT_SIZE_32P;
+ ch->ch_char |= IMAGE_FILE_EXECUTABLE_IMAGE |
+ IMAGE_FILE_LARGE_ADDRESS_AWARE;
+ } else
+ ch->ch_optsize = 0;
+
+ /*
+ * COFF line number is deprecated by the PE/COFF
+ * specification. COFF symbol table is deprecated
+ * for executables.
+ */
+ ch->ch_char |= IMAGE_FILE_LINE_NUMS_STRIPPED;
+ if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P)
+ ch->ch_char |= IMAGE_FILE_LOCAL_SYMS_STRIPPED;
+
+ ch->ch_nsec = pe->pe_nscn;
+
+ STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+ sh = &ps->ps_sh;
+
+ if (ps->ps_ndx == 0xFFFFFFFFU) {
+ ch->ch_symptr = sh->sh_rawptr;
+ ch->ch_nsym = pe->pe_nsym;
+ }
+
+ if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P) {
+ if (ps->ps_ndx == (0xFFFF0000 | PE_DD_BASERELOC) ||
+ strncmp(sh->sh_name, ".reloc", strlen(".reloc")) ==
+ 0) {
+ reloc = 1;
+ reloc_rva = sh->sh_addr;
+ reloc_sz = sh->sh_virtsize;
+ }
+ }
+ }
+
+ if (!reloc)
+ ch->ch_char |= IMAGE_FILE_RELOCS_STRIPPED;
+
+ if (pe->pe_flags & LIBPE_F_BAD_OPT_HEADER) {
+ if (pe->pe_obj == PE_O_PE32)
+ ch->ch_optsize = PE_COFF_OPT_SIZE_32;
+ else if (pe->pe_obj == PE_O_PE32P)
+ ch->ch_optsize = PE_COFF_OPT_SIZE_32P;
+ else
+ ch->ch_optsize = 0;
+ }
+
+ /*
+ * Write the COFF header.
+ */
+ hdr = tmp;
+ PE_WRITE16(hdr, ch->ch_machine);
+ PE_WRITE16(hdr, ch->ch_nsec);
+ PE_WRITE32(hdr, ch->ch_timestamp);
+ PE_WRITE32(hdr, ch->ch_symptr);
+ PE_WRITE32(hdr, ch->ch_nsym);
+ PE_WRITE16(hdr, ch->ch_optsize);
+ PE_WRITE16(hdr, ch->ch_char);
+ if (write(pe->pe_fd, tmp, sizeof(PE_CoffHdr)) !=
+ (ssize_t) sizeof(PE_CoffHdr)) {
+ errno = EIO;
+ return (-1);
+ }
+
+coff_done:
+ off += sizeof(PE_CoffHdr);
+ pe->pe_flags &= ~LIBPE_F_DIRTY_COFF_HEADER;
+ pe->pe_flags &= ~LIBPE_F_BAD_COFF_HEADER;
+ pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
+
+ if (ch->ch_optsize == 0)
+ return (off);
+
+ /*
+ * Write the Optional header.
+ */
+
+ if (pe->pe_cmd == PE_C_RDWR) {
+ if ((pe->pe_flags & LIBPE_F_DIRTY_OPT_HEADER) == 0 &&
+ (pe->pe_flags & LIBPE_F_BAD_OPT_HEADER) == 0) {
+ if (lseek(pe->pe_fd, (off_t) ch->ch_optsize,
+ SEEK_CUR) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+ off += ch->ch_optsize;
+ return (off);
+ }
+
+ }
+
+ if (pe->pe_oh == NULL) {
+ if ((oh = calloc(1, sizeof(PE_OptHdr))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ pe->pe_oh = oh;
+ } else
+ oh = pe->pe_oh;
+
+ if (pe->pe_obj == PE_O_PE32)
+ oh->oh_magic = PE_FORMAT_32;
+ else
+ oh->oh_magic = PE_FORMAT_32P;
+
+ /*
+ * LinkerVersion should not be less than 2.5, which will cause
+ * Windows to complain the executable is invalid in some case.
+ * By default we set LinkerVersion to 2.22 (binutils 2.22)
+ */
+ if (!oh->oh_ldvermajor && !oh->oh_ldverminor) {
+ oh->oh_ldvermajor = 2;
+ oh->oh_ldverminor = 22;
+ }
+
+ /*
+ * The library always tries to write out all 16 data directories
+ * but the actual data dir written will depend on ch_optsize.
+ */
+ oh->oh_ndatadir = PE_DD_MAX;
+
+ if (!oh->oh_filealign)
+ oh->oh_filealign = 0x200;
+ if (!oh->oh_secalign)
+ oh->oh_secalign = 0x1000;
+ oh->oh_hdrsize = roundup(off + ch->ch_optsize + pe->pe_nscn *
+ sizeof(PE_SecHdr), oh->oh_filealign);
+ oh->oh_imgsize = roundup(pe->pe_rvamax, oh->oh_secalign);
+
+#define WRITE_OPT(n) \
+ do { \
+ /* \
+ * Since the Optional Header size is variable, we must \
+ * check if the requested write size will overrun the \
+ * remaining header bytes. \
+ */ \
+ if (p + (n) > ch->ch_optsize) { \
+ /* Pad the "extra" bytes */ \
+ if (libpe_pad(pe, ch->ch_optsize - p) < 0) { \
+ errno = EIO; \
+ return (-1); \
+ } \
+ goto opt_done; \
+ } \
+ if (write(pe->pe_fd, tmp, (n)) != (ssize_t) (n)) { \
+ errno = EIO; \
+ return (-1); \
+ } \
+ p += (n); \
+ } while (0)
+#define WRITE_OPT8(v) do { *tmp = (v); WRITE_OPT(1); } while(0)
+#define WRITE_OPT16(v) do { le16enc(tmp, (v)); WRITE_OPT(2); } while(0)
+#define WRITE_OPT32(v) do { le32enc(tmp, (v)); WRITE_OPT(4); } while(0)
+#define WRITE_OPT64(v) do { le64enc(tmp, (v)); WRITE_OPT(8); } while(0)
+
+ p = 0;
+ WRITE_OPT16(oh->oh_magic);
+ if (oh->oh_magic == PE_FORMAT_32P)
+ pe->pe_obj = PE_O_PE32P;
+ WRITE_OPT8(oh->oh_ldvermajor);
+ WRITE_OPT8(oh->oh_ldverminor);
+ WRITE_OPT32(oh->oh_textsize);
+ WRITE_OPT32(oh->oh_datasize);
+ WRITE_OPT32(oh->oh_bsssize);
+ WRITE_OPT32(oh->oh_entry);
+ WRITE_OPT32(oh->oh_textbase);
+ if (oh->oh_magic != PE_FORMAT_32P) {
+ WRITE_OPT32(oh->oh_database);
+ WRITE_OPT32(oh->oh_imgbase);
+ } else
+ WRITE_OPT64(oh->oh_imgbase);
+ WRITE_OPT32(oh->oh_secalign);
+ WRITE_OPT32(oh->oh_filealign);
+ WRITE_OPT16(oh->oh_osvermajor);
+ WRITE_OPT16(oh->oh_osverminor);
+ WRITE_OPT16(oh->oh_imgvermajor);
+ WRITE_OPT16(oh->oh_imgverminor);
+ WRITE_OPT16(oh->oh_subvermajor);
+ WRITE_OPT16(oh->oh_subverminor);
+ WRITE_OPT32(oh->oh_win32ver);
+ WRITE_OPT32(oh->oh_imgsize);
+ WRITE_OPT32(oh->oh_hdrsize);
+ WRITE_OPT32(oh->oh_checksum);
+ WRITE_OPT16(oh->oh_subsystem);
+ WRITE_OPT16(oh->oh_dllchar);
+ if (oh->oh_magic != PE_FORMAT_32P) {
+ WRITE_OPT32(oh->oh_stacksizer);
+ WRITE_OPT32(oh->oh_stacksizec);
+ WRITE_OPT32(oh->oh_heapsizer);
+ WRITE_OPT32(oh->oh_heapsizec);
+ } else {
+ WRITE_OPT64(oh->oh_stacksizer);
+ WRITE_OPT64(oh->oh_stacksizec);
+ WRITE_OPT64(oh->oh_heapsizer);
+ WRITE_OPT64(oh->oh_heapsizec);
+ }
+ WRITE_OPT32(oh->oh_ldrflags);
+ WRITE_OPT32(oh->oh_ndatadir);
+
+ /*
+ * Write the Data Directories.
+ */
+
+ if (oh->oh_ndatadir > 0) {
+ if (pe->pe_dd == NULL) {
+ if ((dd = calloc(1, sizeof(PE_DataDir))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ pe->pe_dd = dd;
+ dd->dd_total = PE_DD_MAX;
+ } else
+ dd = pe->pe_dd;
+
+ assert(oh->oh_ndatadir <= PE_DD_MAX);
+
+ if (reloc) {
+ dd->dd_e[PE_DD_BASERELOC].de_addr = reloc_rva;
+ dd->dd_e[PE_DD_BASERELOC].de_size = reloc_sz;
+ }
+
+ for (i = 0; (uint32_t) i < dd->dd_total; i++) {
+ WRITE_OPT32(dd->dd_e[i].de_addr);
+ WRITE_OPT32(dd->dd_e[i].de_size);
+ }
+ }
+
+ /* Pad the remaining bytes in the Optional header, if any. */
+ if (ch->ch_optsize > p) {
+ if (libpe_pad(pe, ch->ch_optsize - p) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+ }
+
+opt_done:
+ off += ch->ch_optsize;
+ pe->pe_flags &= ~LIBPE_F_DIRTY_OPT_HEADER;
+ pe->pe_flags &= ~LIBPE_F_BAD_OPT_HEADER;
+ pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
+
+ return (off);
+}
diff --git a/contrib/elftoolchain/libpe/libpe_dos.c b/contrib/elftoolchain/libpe/libpe_dos.c
new file mode 100644
index 0000000..a48ad12
--- /dev/null
+++ b/contrib/elftoolchain/libpe/libpe_dos.c
@@ -0,0 +1,403 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_dos.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+int
+libpe_parse_msdos_header(PE *pe, char *hdr)
+{
+ PE_DosHdr *dh;
+ char coff[sizeof(PE_CoffHdr)];
+ uint32_t pe_magic;
+ int i;
+
+ if ((pe->pe_stub = malloc(sizeof(PE_DosHdr))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ memcpy(pe->pe_stub, hdr, sizeof(PE_DosHdr));
+
+ if ((dh = malloc(sizeof(*dh))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ pe->pe_dh = dh;
+
+ /* Read the conventional MS-DOS EXE header. */
+ memcpy(dh->dh_magic, hdr, 2);
+ hdr += 2;
+ PE_READ16(hdr, dh->dh_lastsize);
+ PE_READ16(hdr, dh->dh_nblock);
+ PE_READ16(hdr, dh->dh_nreloc);
+ PE_READ16(hdr, dh->dh_hdrsize);
+ PE_READ16(hdr, dh->dh_minalloc);
+ PE_READ16(hdr, dh->dh_maxalloc);
+ PE_READ16(hdr, dh->dh_ss);
+ PE_READ16(hdr, dh->dh_sp);
+ PE_READ16(hdr, dh->dh_checksum);
+ PE_READ16(hdr, dh->dh_ip);
+ PE_READ16(hdr, dh->dh_cs);
+ PE_READ16(hdr, dh->dh_relocpos);
+ PE_READ16(hdr, dh->dh_noverlay);
+
+ /* Do not continue if the EXE is not a PE/NE/... (new executable) */
+ if (dh->dh_relocpos != 0x40) {
+ pe->pe_flags |= LIBPE_F_BAD_DOS_HEADER;
+ return (0);
+ }
+
+ for (i = 0; i < 4; i++)
+ PE_READ16(hdr, dh->dh_reserved1[i]);
+ PE_READ16(hdr, dh->dh_oemid);
+ PE_READ16(hdr, dh->dh_oeminfo);
+ for (i = 0; i < 10; i++)
+ PE_READ16(hdr, dh->dh_reserved2[i]);
+ PE_READ32(hdr, dh->dh_lfanew);
+
+ /* Check if the e_lfanew pointer is valid. */
+ if (dh->dh_lfanew > pe->pe_fsize - 4) {
+ pe->pe_flags |= LIBPE_F_BAD_DOS_HEADER;
+ return (0);
+ }
+
+ if (dh->dh_lfanew < sizeof(PE_DosHdr) &&
+ (pe->pe_flags & LIBPE_F_SPECIAL_FILE)) {
+ pe->pe_flags |= LIBPE_F_BAD_DOS_HEADER;
+ return (0);
+ }
+
+ if (dh->dh_lfanew > sizeof(PE_DosHdr)) {
+ pe->pe_stub_ex = dh->dh_lfanew - sizeof(PE_DosHdr);
+ if (pe->pe_flags & LIBPE_F_SPECIAL_FILE) {
+ /* Read in DOS stub now. */
+ if (libpe_read_msdos_stub(pe) < 0) {
+ pe->pe_flags |= LIBPE_F_BAD_DOS_HEADER;
+ return (0);
+ }
+ }
+ }
+
+ if ((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0) {
+ /* Jump to the PE header. */
+ if (lseek(pe->pe_fd, (off_t) dh->dh_lfanew, SEEK_SET) < 0) {
+ pe->pe_flags |= LIBPE_F_BAD_PE_HEADER;
+ return (0);
+ }
+ }
+
+ if (read(pe->pe_fd, &pe_magic, 4) != 4 ||
+ htole32(pe_magic) != PE_SIGNATURE) {
+ pe->pe_flags |= LIBPE_F_BAD_PE_HEADER;
+ return (0);
+ }
+
+ if (read(pe->pe_fd, coff, sizeof(coff)) != (ssize_t) sizeof(coff)) {
+ pe->pe_flags |= LIBPE_F_BAD_COFF_HEADER;
+ return (0);
+ }
+
+ return (libpe_parse_coff_header(pe, coff));
+}
+
+int
+libpe_read_msdos_stub(PE *pe)
+{
+ void *m;
+
+ assert(pe->pe_stub_ex > 0 &&
+ (pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0);
+
+ if ((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0) {
+ if (lseek(pe->pe_fd, (off_t) sizeof(PE_DosHdr), SEEK_SET) <
+ 0) {
+ errno = EIO;
+ goto fail;
+ }
+ }
+
+ if ((m = realloc(pe->pe_stub, sizeof(PE_DosHdr) + pe->pe_stub_ex)) ==
+ NULL) {
+ errno = ENOMEM;
+ goto fail;
+ }
+ pe->pe_stub = m;
+
+ if (read(pe->pe_fd, pe->pe_stub + sizeof(PE_DosHdr), pe->pe_stub_ex) !=
+ (ssize_t) pe->pe_stub_ex) {
+ errno = EIO;
+ goto fail;
+ }
+
+ pe->pe_flags |= LIBPE_F_LOAD_DOS_STUB;
+
+ /* Search for the Rich header embedded just before the PE header. */
+ (void) libpe_parse_rich_header(pe);
+
+ return (0);
+
+fail:
+ pe->pe_stub_ex = 0;
+
+ return (-1);
+}
+
+/*
+ * The "standard" MS-DOS stub displaying "This program cannot be run in
+ * DOS mode".
+ */
+static const char msdos_stub[] = {
+ '\x0e','\x1f','\xba','\x0e','\x00','\xb4','\x09','\xcd',
+ '\x21','\xb8','\x01','\x4c','\xcd','\x21','\x54','\x68',
+ '\x69','\x73','\x20','\x70','\x72','\x6f','\x67','\x72',
+ '\x61','\x6d','\x20','\x63','\x61','\x6e','\x6e','\x6f',
+ '\x74','\x20','\x62','\x65','\x20','\x72','\x75','\x6e',
+ '\x20','\x69','\x6e','\x20','\x44','\x4f','\x53','\x20',
+ '\x6d','\x6f','\x64','\x65','\x2e','\x0d','\x0d','\x0a',
+ '\x24','\x00','\x00','\x00','\x00','\x00','\x00','\x00',
+};
+
+static void
+init_dos_header(PE_DosHdr *dh)
+{
+
+ dh->dh_magic[0] = 'M';
+ dh->dh_magic[1] = 'Z';
+ dh->dh_lastsize = 144;
+ dh->dh_nblock = 3;
+ dh->dh_hdrsize = 4;
+ dh->dh_maxalloc = 65535;
+ dh->dh_sp = 184;
+ dh->dh_relocpos = 0x40;
+ dh->dh_lfanew = 0x80;
+}
+
+off_t
+libpe_write_msdos_stub(PE *pe, off_t off)
+{
+ PE_DosHdr *dh;
+ char tmp[sizeof(PE_DosHdr)], *hdr;
+ off_t d;
+ int i, strip_rich;
+
+ strip_rich = 0;
+
+ if (pe->pe_cmd == PE_C_RDWR) {
+ assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+
+ if (pe->pe_dh != NULL &&
+ (pe->pe_flags & PE_F_STRIP_DOS_STUB)) {
+ /*
+ * If we strip MS-DOS stub, everything after it
+ * needs rewritten.
+ */
+ pe->pe_flags |= LIBPE_F_BAD_PE_HEADER;
+ goto done;
+ }
+
+ /*
+ * lseek(2) to the PE signature if MS-DOS stub is not
+ * modified.
+ */
+ if (pe->pe_dh != NULL &&
+ (pe->pe_flags & LIBPE_F_DIRTY_DOS_HEADER) == 0 &&
+ (pe->pe_flags & LIBPE_F_BAD_DOS_HEADER) == 0 &&
+ (pe->pe_flags & PE_F_STRIP_RICH_HEADER) == 0) {
+ if (lseek(pe->pe_fd,
+ (off_t) (sizeof(PE_DosHdr) + pe->pe_stub_ex),
+ SEEK_CUR) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+ off = sizeof(PE_DosHdr) + pe->pe_stub_ex;
+ goto done;
+ }
+
+ /* Check if we should strip the Rich header. */
+ if (pe->pe_dh != NULL && pe->pe_stub_app == NULL &&
+ (pe->pe_flags & LIBPE_F_BAD_DOS_HEADER) == 0 &&
+ (pe->pe_flags & PE_F_STRIP_RICH_HEADER)) {
+ if ((pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0) {
+ (void) libpe_read_msdos_stub(pe);
+ if (lseek(pe->pe_fd, off, SEEK_SET) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+ }
+ if (pe->pe_rh != NULL) {
+ strip_rich = 1;
+ pe->pe_flags |= LIBPE_F_DIRTY_DOS_HEADER;
+ }
+ }
+
+ /*
+ * If length of MS-DOS stub will change, Mark the PE
+ * signature is broken so that the PE signature and the
+ * headers follow it will be rewritten.
+ *
+ * The sections should be loaded now since the stub might
+ * overwrite the section data.
+ */
+ if ((pe->pe_flags & LIBPE_F_BAD_DOS_HEADER) ||
+ (pe->pe_stub_app != NULL && pe->pe_stub_app_sz !=
+ sizeof(PE_DosHdr) + pe->pe_stub_ex) || strip_rich) {
+ if (libpe_load_all_sections(pe) < 0)
+ return (-1);
+ if (lseek(pe->pe_fd, off, SEEK_SET) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+ pe->pe_flags |= LIBPE_F_BAD_PE_HEADER;
+ }
+ }
+
+ if (pe->pe_flags & PE_F_STRIP_DOS_STUB)
+ goto done;
+
+ /* Always use application supplied MS-DOS stub, if exists. */
+ if (pe->pe_stub_app != NULL && pe->pe_stub_app_sz > 0) {
+ if (write(pe->pe_fd, pe->pe_stub_app, pe->pe_stub_app_sz) !=
+ (ssize_t) pe->pe_stub_app_sz) {
+ errno = EIO;
+ return (-1);
+ }
+ off = pe->pe_stub_app_sz;
+ goto done;
+ }
+
+ /*
+ * Write MS-DOS header.
+ */
+
+ if (pe->pe_dh == NULL) {
+ if ((dh = calloc(1, sizeof(PE_DosHdr))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ pe->pe_dh = dh;
+
+ init_dos_header(dh);
+
+ pe->pe_flags |= LIBPE_F_DIRTY_DOS_HEADER;
+ } else
+ dh = pe->pe_dh;
+
+ if (pe->pe_flags & LIBPE_F_BAD_DOS_HEADER)
+ init_dos_header(dh);
+
+ if (strip_rich) {
+ d = pe->pe_rh_start - pe->pe_stub;
+ dh->dh_lfanew = roundup(d, 8);
+ }
+
+ if ((pe->pe_flags & LIBPE_F_DIRTY_DOS_HEADER) ||
+ (pe->pe_flags & LIBPE_F_BAD_DOS_HEADER)) {
+ memcpy(tmp, dh->dh_magic, 2);
+ hdr = tmp + 2;
+ PE_WRITE16(hdr, dh->dh_lastsize);
+ PE_WRITE16(hdr, dh->dh_nblock);
+ PE_WRITE16(hdr, dh->dh_nreloc);
+ PE_WRITE16(hdr, dh->dh_hdrsize);
+ PE_WRITE16(hdr, dh->dh_minalloc);
+ PE_WRITE16(hdr, dh->dh_maxalloc);
+ PE_WRITE16(hdr, dh->dh_ss);
+ PE_WRITE16(hdr, dh->dh_sp);
+ PE_WRITE16(hdr, dh->dh_checksum);
+ PE_WRITE16(hdr, dh->dh_ip);
+ PE_WRITE16(hdr, dh->dh_cs);
+ PE_WRITE16(hdr, dh->dh_relocpos);
+ PE_WRITE16(hdr, dh->dh_noverlay);
+ for (i = 0; i < 4; i++)
+ PE_WRITE16(hdr, dh->dh_reserved1[i]);
+ PE_WRITE16(hdr, dh->dh_oemid);
+ PE_WRITE16(hdr, dh->dh_oeminfo);
+ for (i = 0; i < 10; i++)
+ PE_WRITE16(hdr, dh->dh_reserved2[i]);
+ PE_WRITE32(hdr, dh->dh_lfanew);
+
+ if (write(pe->pe_fd, tmp, sizeof(tmp)) !=
+ (ssize_t) sizeof(tmp)) {
+ errno = EIO;
+ return (-1);
+ }
+ } else {
+ assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+ if (lseek(pe->pe_fd, (off_t) sizeof(PE_DosHdr), SEEK_CUR) <
+ 0) {
+ errno = EIO;
+ return (-1);
+ }
+ }
+
+ off = sizeof(PE_DosHdr);
+
+ /*
+ * Write the MS-DOS stub.
+ */
+
+ if (strip_rich) {
+ assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+ assert(pe->pe_stub != NULL && pe->pe_rh_start != NULL);
+ d = pe->pe_rh_start - pe->pe_stub;
+ if (lseek(pe->pe_fd, d, SEEK_SET) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+ off = d;
+ goto done;
+ }
+
+ if (pe->pe_cmd == PE_C_RDWR) {
+ if (lseek(pe->pe_fd, (off_t) pe->pe_stub_ex, SEEK_CUR) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+ off += pe->pe_stub_ex;
+ goto done;
+ }
+
+ if (write(pe->pe_fd, msdos_stub, sizeof(msdos_stub)) !=
+ (ssize_t) sizeof(msdos_stub)) {
+ errno = EIO;
+ return (-1);
+ }
+ off += sizeof(msdos_stub);
+
+done:
+ pe->pe_flags &= ~LIBPE_F_DIRTY_DOS_HEADER;
+ pe->pe_flags &= ~LIBPE_F_BAD_DOS_HEADER;
+
+ return (off);
+}
diff --git a/contrib/elftoolchain/libpe/libpe_init.c b/contrib/elftoolchain/libpe/libpe_init.c
new file mode 100644
index 0000000..2579774
--- /dev/null
+++ b/contrib/elftoolchain/libpe/libpe_init.c
@@ -0,0 +1,145 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/stat.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_init.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+int
+libpe_open_object(PE *pe)
+{
+ struct stat sb;
+ mode_t mode;
+ char magic[sizeof(PE_DosHdr)];
+
+ if (fstat(pe->pe_fd, &sb) < 0)
+ return (-1);
+
+ mode = sb.st_mode;
+ pe->pe_fsize = (size_t) sb.st_size;
+
+ /* Reject unsupported file types. */
+ if (!S_ISREG(mode) && !S_ISCHR(mode) && !S_ISFIFO(mode) &&
+ !S_ISSOCK(mode)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* Read/Write mode is not supported for non-regular file. */
+ if (pe->pe_cmd == PE_C_RDWR && !S_ISREG(mode)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* The minimal file should at least contain a COFF header. */
+ if (S_ISREG(mode) && pe->pe_fsize < sizeof(PE_CoffHdr)) {
+ errno = ENOENT;
+ return (-1);
+ }
+
+ /*
+ * Search for MS-DOS header or COFF header.
+ */
+
+ if (read(pe->pe_fd, magic, 2) != 2) {
+ errno = EIO;
+ return (-1);
+ }
+
+ if (magic[0] == 'M' && magic[1] == 'Z') {
+ pe->pe_obj = PE_O_PE32;
+ if (read(pe->pe_fd, &magic[2], sizeof(PE_DosHdr) - 2) !=
+ (ssize_t) sizeof(PE_DosHdr) - 2) {
+ errno = EIO;
+ return (-1);
+ }
+ return (libpe_parse_msdos_header(pe, magic));
+
+ } else if (magic[0] == 'P' && magic[1] == 'E') {
+ if (read(pe->pe_fd, magic, 2) != 2) {
+ errno = EIO;
+ return (-1);
+ }
+ if (magic[0] == '\0' && magic[1] == '\0') {
+ pe->pe_obj = PE_O_PE32;
+ if (read(pe->pe_fd, magic, sizeof(PE_CoffHdr)) !=
+ (ssize_t) sizeof(PE_CoffHdr)) {
+ errno = EIO;
+ return (-1);
+ }
+ return (libpe_parse_coff_header(pe, magic));
+ }
+ errno = ENOENT;
+ return (-1);
+
+ } else {
+ pe->pe_obj = PE_O_COFF;
+ if (read(pe->pe_fd, &magic[2], sizeof(PE_CoffHdr) - 2) !=
+ (ssize_t) sizeof(PE_CoffHdr) - 2) {
+ errno = EIO;
+ return (-1);
+ }
+ return (libpe_parse_coff_header(pe, magic));
+ }
+}
+
+void
+libpe_release_object(PE *pe)
+{
+ PE_Scn *ps, *_ps;
+
+ if (pe->pe_dh)
+ free(pe->pe_dh);
+
+ if (pe->pe_rh) {
+ free(pe->pe_rh->rh_compid);
+ free(pe->pe_rh->rh_cnt);
+ free(pe->pe_rh);
+ }
+
+ if (pe->pe_ch)
+ free(pe->pe_ch);
+
+ if (pe->pe_oh)
+ free(pe->pe_oh);
+
+ if (pe->pe_dd)
+ free(pe->pe_dd);
+
+ if (pe->pe_stub)
+ free(pe->pe_stub);
+
+ STAILQ_FOREACH_SAFE(ps, &pe->pe_scn, ps_next, _ps)
+ libpe_release_scn(ps);
+
+ free(pe);
+}
diff --git a/contrib/elftoolchain/libpe/libpe_rich.c b/contrib/elftoolchain/libpe/libpe_rich.c
new file mode 100644
index 0000000..4669a22
--- /dev/null
+++ b/contrib/elftoolchain/libpe/libpe_rich.c
@@ -0,0 +1,128 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_rich.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+static char *
+memfind(char *s, const char *find, size_t slen, size_t flen)
+{
+ int i;
+
+ if (slen == 0 || flen == 0 || flen > slen)
+ return (NULL);
+
+ for (i = 0; (size_t) i <= slen - flen; i++) {
+ if (s[i] != find[0])
+ continue;
+ if (flen == 1)
+ return (&s[i]);
+ if (memcmp(&s[i + 1], &find[1], flen - 1) == 0)
+ return (&s[i]);
+ }
+
+ return (NULL);
+}
+
+int
+libpe_parse_rich_header(PE *pe)
+{
+ PE_RichHdr *rh;
+ char *p, *r, *s;
+ uint32_t x;
+ int found, i;
+
+ assert(pe->pe_stub != NULL && pe->pe_stub_ex > 0);
+
+ /* Search for the "Rich" keyword to locate the Rich header. */
+ s = pe->pe_stub + sizeof(PE_DosHdr);
+ r = memfind(s, PE_RICH_TEXT, pe->pe_stub_ex, 4);
+ if (r == NULL || r + 8 > s + pe->pe_stub_ex) {
+ errno = ENOENT;
+ return (-1);
+ }
+
+ if ((rh = calloc(1, sizeof(*rh))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ rh->rh_xor = le32dec(r + 4); /* Retrieve the "XOR mask" */
+
+ /*
+ * Search for the hidden keyword "DanS" by XOR the dwords before
+ * the "Rich" keyword with the XOR mask.
+ */
+ found = 0;
+ for (p = r - 4; p >= s; p -= 4) {
+ x = le32dec(p) ^ rh->rh_xor;
+ if (x == PE_RICH_HIDDEN) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ free(rh);
+ errno = ENOENT;
+ return (-1);
+ }
+
+ /*
+ * Found the "DanS" keyword, which is the start of the Rich header.
+ * The next step is to skip the first 16 bytes (DanS, XOR mask,
+ * XOR mask, XOR mask) and read the (compid,cnt) tuples.
+ */
+ pe->pe_rh_start = p;
+ p += 16;
+ rh->rh_total = (r - p) / 8;
+ if ((rh->rh_compid = malloc(rh->rh_total * sizeof(*rh->rh_compid))) ==
+ NULL) {
+ free(rh);
+ errno = ENOMEM;
+ return (-1);
+ }
+ if ((rh->rh_cnt = malloc(rh->rh_total * sizeof(*rh->rh_cnt))) ==
+ NULL) {
+ free(rh->rh_compid);
+ free(rh);
+ errno = ENOMEM;
+ return (-1);
+ }
+ for (i = 0; (uint32_t) i < rh->rh_total; i++, p += 8) {
+ rh->rh_compid[i] = le32dec(p) ^ rh->rh_xor;
+ rh->rh_cnt[i] = le32dec(p + 4) ^ rh->rh_xor;
+ }
+
+ pe->pe_rh = rh;
+
+ return (0);
+}
diff --git a/contrib/elftoolchain/libpe/libpe_section.c b/contrib/elftoolchain/libpe/libpe_section.c
new file mode 100644
index 0000000..7ff63fb
--- /dev/null
+++ b/contrib/elftoolchain/libpe/libpe_section.c
@@ -0,0 +1,518 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/param.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_section.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_Scn *
+libpe_alloc_scn(PE *pe)
+{
+ PE_Scn *ps;
+
+ if ((ps = calloc(1, sizeof(PE_Scn))) == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ STAILQ_INIT(&ps->ps_b);
+ ps->ps_pe = pe;
+
+ return (ps);
+}
+
+void
+libpe_release_scn(PE_Scn *ps)
+{
+ PE *pe;
+ PE_SecBuf *sb, *_sb;
+
+ assert(ps != NULL);
+
+ pe = ps->ps_pe;
+
+ STAILQ_REMOVE(&pe->pe_scn, ps, _PE_Scn, ps_next);
+
+ STAILQ_FOREACH_SAFE(sb, &ps->ps_b, sb_next, _sb)
+ libpe_release_buffer(sb);
+
+ free(ps);
+}
+
+static int
+cmp_scn(PE_Scn *a, PE_Scn *b)
+{
+
+ if (a->ps_sh.sh_addr < b->ps_sh.sh_addr)
+ return (-1);
+ else if (a->ps_sh.sh_addr == b->ps_sh.sh_addr)
+ return (0);
+ else
+ return (1);
+}
+
+static void
+sort_sections(PE *pe)
+{
+
+ if (STAILQ_EMPTY(&pe->pe_scn))
+ return;
+
+ /* Sort the list of Scn by RVA in ascending order. */
+ STAILQ_SORT(&pe->pe_scn, _PE_Scn, ps_next, cmp_scn);
+}
+
+int
+libpe_parse_section_headers(PE *pe)
+{
+ char tmp[sizeof(PE_SecHdr)], *hdr;
+ PE_Scn *ps;
+ PE_SecHdr *sh;
+ PE_CoffHdr *ch;
+ PE_DataDir *dd;
+ int found, i;
+
+ assert(pe->pe_ch != NULL);
+
+ for (i = 0; (uint16_t) i < pe->pe_ch->ch_nsec; i++) {
+ if (read(pe->pe_fd, tmp, sizeof(PE_SecHdr)) !=
+ (ssize_t) sizeof(PE_SecHdr)) {
+ pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER;
+ return (0);
+ }
+
+ if ((ps = libpe_alloc_scn(pe)) == NULL)
+ return (-1);
+ STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next);
+ ps->ps_ndx = ++pe->pe_nscn; /* Setion index is 1-based */
+ sh = &ps->ps_sh;
+
+ /*
+ * Note that the section name won't be NUL-terminated if
+ * its length happens to be 8.
+ */
+ memcpy(sh->sh_name, tmp, sizeof(sh->sh_name));
+ hdr = tmp + 8;
+ PE_READ32(hdr, sh->sh_virtsize);
+ PE_READ32(hdr, sh->sh_addr);
+ PE_READ32(hdr, sh->sh_rawsize);
+ PE_READ32(hdr, sh->sh_rawptr);
+ PE_READ32(hdr, sh->sh_relocptr);
+ PE_READ32(hdr, sh->sh_lineptr);
+ PE_READ16(hdr, sh->sh_nreloc);
+ PE_READ16(hdr, sh->sh_nline);
+ PE_READ32(hdr, sh->sh_char);
+ }
+
+ /*
+ * For all the data directories that don't belong to any section,
+ * we create pseudo sections for them to make layout easier.
+ */
+ dd = pe->pe_dd;
+ if (dd != NULL && dd->dd_total > 0) {
+ for (i = 0; (uint32_t) i < pe->pe_dd->dd_total; i++) {
+ if (dd->dd_e[i].de_size == 0)
+ continue;
+ found = 0;
+ STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+ sh = &ps->ps_sh;
+ if (dd->dd_e[i].de_addr >= sh->sh_addr &&
+ dd->dd_e[i].de_addr + dd->dd_e[i].de_size <=
+ sh->sh_addr + sh->sh_virtsize) {
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ continue;
+
+ if ((ps = libpe_alloc_scn(pe)) == NULL)
+ return (-1);
+ STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next);
+ ps->ps_ndx = 0xFFFF0000U | i;
+ sh = &ps->ps_sh;
+ sh->sh_rawptr = dd->dd_e[i].de_addr; /* FIXME */
+ sh->sh_rawsize = dd->dd_e[i].de_size;
+ }
+ }
+
+ /*
+ * Also consider the COFF symbol table as a pseudo section.
+ */
+ ch = pe->pe_ch;
+ if (ch->ch_nsym > 0) {
+ if ((ps = libpe_alloc_scn(pe)) == NULL)
+ return (-1);
+ STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next);
+ ps->ps_ndx = 0xFFFFFFFFU;
+ sh = &ps->ps_sh;
+ sh->sh_rawptr = ch->ch_symptr;
+ sh->sh_rawsize = ch->ch_nsym * PE_SYM_ENTRY_SIZE;
+ pe->pe_nsym = ch->ch_nsym;
+ }
+
+ /* PE file headers initialization is complete if we reach here. */
+ return (0);
+}
+
+int
+libpe_load_section(PE *pe, PE_Scn *ps)
+{
+ PE_SecHdr *sh;
+ PE_SecBuf *sb;
+ size_t sz;
+ char tmp[4];
+
+ assert(pe != NULL && ps != NULL);
+ assert((ps->ps_flags & LIBPE_F_LOAD_SECTION) == 0);
+
+ sh = &ps->ps_sh;
+
+ /* Allocate a PE_SecBuf struct without buffer for empty sections. */
+ if (sh->sh_rawsize == 0) {
+ (void) libpe_alloc_buffer(ps, 0);
+ ps->ps_flags |= LIBPE_F_LOAD_SECTION;
+ return (0);
+ }
+
+ if ((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0) {
+ if (lseek(pe->pe_fd, (off_t) sh->sh_rawptr, SEEK_SET) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+ }
+
+ if ((sb = libpe_alloc_buffer(ps, sh->sh_rawsize)) == NULL)
+ return (-1);
+
+ if (read(pe->pe_fd, sb->sb_pb.pb_buf, sh->sh_rawsize) !=
+ (ssize_t) sh->sh_rawsize) {
+ errno = EIO;
+ return (-1);
+ }
+
+ if (ps->ps_ndx == 0xFFFFFFFFU) {
+ /*
+ * Index 0xFFFFFFFF indicates this section is a pseudo
+ * section that contains the COFF symbol table. We should
+ * read in the string table right after it.
+ */
+ if (read(pe->pe_fd, tmp, sizeof(tmp)) !=
+ (ssize_t) sizeof(tmp)) {
+ errno = EIO;
+ return (-1);
+ }
+ sz = le32dec(tmp);
+
+ /*
+ * The minimum value for the size field is 4, which indicates
+ * there is no string table.
+ */
+ if (sz > 4) {
+ sz -= 4;
+ if ((sb = libpe_alloc_buffer(ps, sz)) == NULL)
+ return (-1);
+ if (read(pe->pe_fd, sb->sb_pb.pb_buf, sz) !=
+ (ssize_t) sz) {
+ errno = EIO;
+ return (-1);
+ }
+ }
+ }
+
+ ps->ps_flags |= LIBPE_F_LOAD_SECTION;
+
+ return (0);
+}
+
+int
+libpe_load_all_sections(PE *pe)
+{
+ PE_Scn *ps;
+ PE_SecHdr *sh;
+ unsigned r, s;
+ off_t off;
+ char tmp[256];
+
+ /* Calculate the current offset into the file. */
+ off = 0;
+ if (pe->pe_dh != NULL)
+ off += pe->pe_dh->dh_lfanew + 4;
+ if (pe->pe_ch != NULL)
+ off += sizeof(PE_CoffHdr) + pe->pe_ch->ch_optsize;
+
+ STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+ if (ps->ps_flags & LIBPE_F_LOAD_SECTION)
+ continue;
+ sh = &ps->ps_sh;
+
+ /*
+ * For special files, we consume the padding in between
+ * and advance to the section offset.
+ */
+ if (pe->pe_flags & LIBPE_F_SPECIAL_FILE) {
+ /* Can't go backwards. */
+ if (off > sh->sh_rawptr) {
+ errno = EIO;
+ return (-1);
+ }
+ if (off < sh->sh_rawptr) {
+ r = sh->sh_rawptr - off;
+ for (; r > 0; r -= s) {
+ s = r > sizeof(tmp) ? sizeof(tmp) : r;
+ if (read(pe->pe_fd, tmp, s) !=
+ (ssize_t) s) {
+ errno = EIO;
+ return (-1);
+ }
+ }
+ }
+ }
+
+ /* Load the section content. */
+ if (libpe_load_section(pe, ps) < 0)
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+libpe_resync_sections(PE *pe, off_t off)
+{
+ PE_Scn *ps;
+ PE_SecHdr *sh;
+ size_t falign, nsec;
+
+ /* Firstly, sort all sections by their file offsets. */
+ sort_sections(pe);
+
+ /* Count the number of sections. */
+ nsec = 0;
+ STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+ if (ps->ps_flags & LIBPE_F_STRIP_SECTION)
+ continue;
+ if (ps->ps_ndx & 0xFFFF0000U)
+ continue;
+ nsec++;
+ }
+ pe->pe_nscn = nsec;
+
+ /*
+ * Calculate the file offset for the first section. (`off' is
+ * currently pointing to the COFF header.)
+ */
+ off += sizeof(PE_CoffHdr);
+ if (pe->pe_ch != NULL && pe->pe_ch->ch_optsize > 0)
+ off += pe->pe_ch->ch_optsize;
+ else {
+ switch (pe->pe_obj) {
+ case PE_O_PE32:
+ off += PE_COFF_OPT_SIZE_32;
+ break;
+ case PE_O_PE32P:
+ off += PE_COFF_OPT_SIZE_32P;
+ break;
+ case PE_O_COFF:
+ default:
+ break;
+ }
+ }
+ off += nsec * sizeof(PE_SecHdr);
+
+ /*
+ * Determine the file alignment for sections.
+ */
+ if (pe->pe_oh != NULL && pe->pe_oh->oh_filealign > 0)
+ falign = pe->pe_oh->oh_filealign;
+ else {
+ /*
+ * Use the default file alignment defined by the
+ * PE/COFF specification.
+ */
+ if (pe->pe_obj == PE_O_COFF)
+ falign = 4;
+ else
+ falign = 512;
+ }
+
+ /*
+ * Step through each section (and pseduo section) and verify
+ * alignment constraint and overlapping, make adjustment if need.
+ */
+ pe->pe_rvamax = 0;
+ STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+ if (ps->ps_flags & LIBPE_F_STRIP_SECTION)
+ continue;
+
+ sh = &ps->ps_sh;
+
+ if (sh->sh_addr + sh->sh_virtsize > pe->pe_rvamax)
+ pe->pe_rvamax = sh->sh_addr + sh->sh_virtsize;
+
+ if (ps->ps_ndx & 0xFFFF0000U)
+ ps->ps_falign = 4;
+ else
+ ps->ps_falign = falign;
+
+ off = roundup(off, ps->ps_falign);
+
+ if (off != sh->sh_rawptr)
+ ps->ps_flags |= PE_F_DIRTY;
+
+ if (ps->ps_flags & PE_F_DIRTY) {
+ if ((ps->ps_flags & LIBPE_F_LOAD_SECTION) == 0) {
+ if (libpe_load_section(pe, ps) < 0)
+ return (-1);
+ }
+ sh->sh_rawsize = libpe_resync_buffers(ps);
+ }
+
+ /*
+ * Sections only contains uninitialized data should set
+ * PointerToRawData to zero according to the PE/COFF
+ * specification.
+ */
+ if (sh->sh_rawsize == 0)
+ sh->sh_rawptr = 0;
+ else
+ sh->sh_rawptr = off;
+
+ off += sh->sh_rawsize;
+ }
+
+ return (0);
+}
+
+off_t
+libpe_write_section_headers(PE *pe, off_t off)
+{
+ char tmp[sizeof(PE_SecHdr)], *hdr;
+ PE_Scn *ps;
+ PE_SecHdr *sh;
+
+ if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER || pe->pe_nscn == 0)
+ return (off);
+
+ if ((pe->pe_flags & LIBPE_F_DIRTY_SEC_HEADER) == 0) {
+ off += sizeof(PE_SecHdr) * pe->pe_ch->ch_nsec;
+ return (off);
+ }
+
+ STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+ if (ps->ps_flags & LIBPE_F_STRIP_SECTION)
+ continue;
+ if (ps->ps_ndx & 0xFFFF0000U)
+ continue;
+ if ((pe->pe_flags & LIBPE_F_DIRTY_SEC_HEADER) == 0 &&
+ (ps->ps_flags & PE_F_DIRTY) == 0)
+ goto next_header;
+
+ sh = &ps->ps_sh;
+
+ memcpy(tmp, sh->sh_name, sizeof(sh->sh_name));
+ hdr = tmp + 8;
+ PE_WRITE32(hdr, sh->sh_virtsize);
+ PE_WRITE32(hdr, sh->sh_addr);
+ PE_WRITE32(hdr, sh->sh_rawsize);
+ PE_WRITE32(hdr, sh->sh_rawptr);
+ PE_WRITE32(hdr, sh->sh_relocptr);
+ PE_WRITE32(hdr, sh->sh_lineptr);
+ PE_WRITE16(hdr, sh->sh_nreloc);
+ PE_WRITE16(hdr, sh->sh_nline);
+ PE_WRITE32(hdr, sh->sh_char);
+
+ if (write(pe->pe_fd, tmp, sizeof(PE_SecHdr)) !=
+ (ssize_t) sizeof(PE_SecHdr)) {
+ errno = EIO;
+ return (-1);
+ }
+
+ next_header:
+ off += sizeof(PE_SecHdr);
+ }
+
+ return (off);
+}
+
+off_t
+libpe_write_sections(PE *pe, off_t off)
+{
+ PE_Scn *ps;
+ PE_SecHdr *sh;
+
+ if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER)
+ return (off);
+
+ STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+ sh = &ps->ps_sh;
+
+ if (ps->ps_flags & LIBPE_F_STRIP_SECTION)
+ continue;
+
+ /* Skip empty sections. */
+ if (sh->sh_rawptr == 0 || sh->sh_rawsize == 0)
+ continue;
+
+ /*
+ * Padding between sections. (padding always written
+ * in case the the section headers or sections are
+ * moved or shrinked.)
+ */
+ assert(off <= sh->sh_rawptr);
+ if (off < sh->sh_rawptr)
+ libpe_pad(pe, sh->sh_rawptr - off);
+
+ if ((ps->ps_flags & PE_F_DIRTY) == 0) {
+ assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+ if (lseek(pe->pe_fd,
+ (off_t) (sh->sh_rawptr + sh->sh_rawsize),
+ SEEK_SET) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+ off = sh->sh_rawptr + sh->sh_rawsize;
+ continue;
+ }
+
+ off = sh->sh_rawptr;
+
+ if (libpe_write_buffers(ps) < 0)
+ return (-1);
+
+ off += sh->sh_rawsize;
+
+ ps->ps_flags &= ~PE_F_DIRTY;
+ }
+
+ return (off);
+}
diff --git a/contrib/elftoolchain/libpe/libpe_utils.c b/contrib/elftoolchain/libpe/libpe_utils.c
new file mode 100644
index 0000000..9bc9a54
--- /dev/null
+++ b/contrib/elftoolchain/libpe/libpe_utils.c
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/param.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: libpe_utils.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+off_t
+libpe_align(PE *pe, off_t off, size_t align)
+{
+ off_t n;
+
+ assert(align > 0 && (align & (align - 1)) == 0);
+
+ n = roundup(off, align);
+ if (n > off) {
+ if (libpe_pad(pe, n - off) < 0)
+ return (-1);
+ }
+
+ return (n);
+}
+
+int
+libpe_pad(PE *pe, size_t pad)
+{
+ char tmp[128];
+ size_t s;
+
+ memset(tmp, 0, sizeof(tmp));
+ for (; pad > 0; pad -= s) {
+ s = pad > sizeof(tmp) ? sizeof(tmp) : pad;
+ if (write(pe->pe_fd, tmp, s) != (ssize_t) s) {
+ errno = EIO;
+ return (-1);
+ }
+ }
+
+ return (0);
+}
diff --git a/contrib/elftoolchain/libpe/os.Linux.mk b/contrib/elftoolchain/libpe/os.Linux.mk
new file mode 100644
index 0000000..ed5bdf0
--- /dev/null
+++ b/contrib/elftoolchain/libpe/os.Linux.mk
@@ -0,0 +1,6 @@
+# $Id: os.Linux.mk 3312 2016-01-10 09:23:51Z kaiwang27 $
+
+CFLAGS+= -Wall -Wno-unused-parameter -Wstrict-prototypes \
+ -Wmissing-prototypes -Wpointer-arith -Wreturn-type \
+ -Wcast-qual -Wwrite-strings -Wswitch -Wshadow \
+ -Wcast-align -Wunused-parameter
diff --git a/contrib/elftoolchain/libpe/os.NetBSD.mk b/contrib/elftoolchain/libpe/os.NetBSD.mk
new file mode 100644
index 0000000..ae214e3
--- /dev/null
+++ b/contrib/elftoolchain/libpe/os.NetBSD.mk
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
diff --git a/contrib/elftoolchain/libpe/pe.h b/contrib/elftoolchain/libpe/pe.h
new file mode 100644
index 0000000..5b6130e
--- /dev/null
+++ b/contrib/elftoolchain/libpe/pe.h
@@ -0,0 +1,292 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $Id: pe.h 3312 2016-01-10 09:23:51Z kaiwang27 $
+ */
+
+#ifndef _PE_H_
+#define _PE_H_
+
+#include <stdint.h>
+
+/*
+ * MS-DOS header.
+ */
+
+typedef struct _PE_DosHdr {
+ char dh_magic[2];
+ uint16_t dh_lastsize;
+ uint16_t dh_nblock;
+ uint16_t dh_nreloc;
+ uint16_t dh_hdrsize;
+ uint16_t dh_minalloc;
+ uint16_t dh_maxalloc;
+ uint16_t dh_ss;
+ uint16_t dh_sp;
+ uint16_t dh_checksum;
+ uint16_t dh_ip;
+ uint16_t dh_cs;
+ uint16_t dh_relocpos;
+ uint16_t dh_noverlay;
+ uint16_t dh_reserved1[4];
+ uint16_t dh_oemid;
+ uint16_t dh_oeminfo;
+ uint16_t dh_reserved2[10];
+ uint32_t dh_lfanew;
+} PE_DosHdr;
+
+/*
+ * Rich header.
+ */
+
+typedef struct _PE_RichHdr {
+ uint32_t rh_xor;
+ uint32_t rh_total;
+ uint32_t *rh_compid;
+ uint32_t *rh_cnt;
+} PE_RichHdr;
+
+/*
+ * COFF header: Machine Types.
+ */
+
+#define IMAGE_FILE_MACHINE_UNKNOWN 0x0 /* not specified */
+#define IMAGE_FILE_MACHINE_AM33 0x1d3 /* Matsushita AM33 */
+#define IMAGE_FILE_MACHINE_AMD64 0x8664 /* x86-64 */
+#define IMAGE_FILE_MACHINE_ARM 0x1c0 /* ARM LE */
+#define IMAGE_FILE_MACHINE_ARMNT 0x1c4 /* ARMv7(or higher) Thumb */
+#define IMAGE_FILE_MACHINE_ARM64 0xaa64 /* ARMv8 64-bit */
+#define IMAGE_FILE_MACHINE_EBC 0xebc /* EFI byte code */
+#define IMAGE_FILE_MACHINE_I386 0x14c /* x86 */
+#define IMAGE_FILE_MACHINE_IA64 0x200 /* IA64 */
+#define IMAGE_FILE_MACHINE_M32R 0x9041 /* Mitsubishi M32R LE */
+#define IMAGE_FILE_MACHINE_MIPS16 0x266 /* MIPS16 */
+#define IMAGE_FILE_MACHINE_MIPSFPU 0x366 /* MIPS with FPU */
+#define IMAGE_FILE_MACHINE_MIPSFPU16 0x466 /* MIPS16 with FPU */
+#define IMAGE_FILE_MACHINE_POWERPC 0x1f0 /* Power PC LE */
+#define IMAGE_FILE_MACHINE_POWERPCFP 0x1f1 /* Power PC floating point */
+#define IMAGE_FILE_MACHINE_R4000 0x166 /* MIPS R4000 LE */
+#define IMAGE_FILE_MACHINE_SH3 0x1a2 /* Hitachi SH3 */
+#define IMAGE_FILE_MACHINE_SH3DSP 0x1a3 /* Hitachi SH3 DSP */
+#define IMAGE_FILE_MACHINE_SH4 0x1a6 /* Hitachi SH4 */
+#define IMAGE_FILE_MACHINE_SH5 0x1a8 /* Hitachi SH5 */
+#define IMAGE_FILE_MACHINE_THUMB 0x1c2 /* ARM or Thumb interworking */
+#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x169 /* MIPS LE WCE v2 */
+
+/*
+ * COFF header: Characteristics
+ */
+
+#define IMAGE_FILE_RELOCS_STRIPPED 0x0001
+#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
+#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
+#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010
+#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020
+#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
+#define IMAGE_FILE_32BIT_MACHINE 0x0100
+#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
+#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400
+#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800
+#define IMAGE_FILE_SYSTEM 0x1000
+#define IMAGE_FILE_DLL 0x2000
+#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000
+#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
+
+/*
+ * COFF Header.
+ */
+
+typedef struct _PE_CoffHdr {
+ uint16_t ch_machine;
+ uint16_t ch_nsec;
+ uint32_t ch_timestamp;
+ uint32_t ch_symptr;
+ uint32_t ch_nsym;
+ uint16_t ch_optsize;
+ uint16_t ch_char;
+} PE_CoffHdr;
+
+
+/*
+ * Optional Header: Subsystem.
+ */
+
+#define IMAGE_SUBSYSTEM_UNKNOWN 0
+#define IMAGE_SUBSYSTEM_NATIVE 1
+#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2
+#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3
+#define IMAGE_SUBSYSTEM_POSIX_CUI 7
+#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9
+#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10
+#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11
+#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12
+#define IMAGE_SUBSYSTEM_EFI_ROM 13
+#define IMAGE_SUBSYSTEM_XBOX 14
+
+/*
+ * Optional Header: DLL Characteristics
+ */
+
+#define IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 0x0040
+#define IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY 0x0080
+#define IMAGE_DLL_CHARACTERISTICS_NX_COMPAT 0x0100
+#define IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION 0x0200
+#define IMAGE_DLL_CHARACTERISTICS_NO_SEH 0x0400
+#define IMAGE_DLL_CHARACTERISTICS_NO_BIND 0x0800
+#define IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER 0x2000
+#define IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000
+
+/*
+ * Optional Header.
+ */
+
+#define PE_FORMAT_ROM 0x107
+#define PE_FORMAT_32 0x10b
+#define PE_FORMAT_32P 0x20b
+
+typedef struct _PE_OptHdr {
+ uint16_t oh_magic;
+ uint8_t oh_ldvermajor;
+ uint8_t oh_ldverminor;
+ uint32_t oh_textsize;
+ uint32_t oh_datasize;
+ uint32_t oh_bsssize;
+ uint32_t oh_entry;
+ uint32_t oh_textbase;
+ uint32_t oh_database;
+ uint64_t oh_imgbase;
+ uint32_t oh_secalign;
+ uint32_t oh_filealign;
+ uint16_t oh_osvermajor;
+ uint16_t oh_osverminor;
+ uint16_t oh_imgvermajor;
+ uint16_t oh_imgverminor;
+ uint16_t oh_subvermajor;
+ uint16_t oh_subverminor;
+ uint32_t oh_win32ver;
+ uint32_t oh_imgsize;
+ uint32_t oh_hdrsize;
+ uint32_t oh_checksum;
+ uint16_t oh_subsystem;
+ uint16_t oh_dllchar;
+ uint64_t oh_stacksizer;
+ uint64_t oh_stacksizec;
+ uint64_t oh_heapsizer;
+ uint64_t oh_heapsizec;
+ uint32_t oh_ldrflags;
+ uint32_t oh_ndatadir;
+} PE_OptHdr;
+
+/*
+ * Optional Header: Data Directories.
+ */
+
+#define PE_DD_EXPORT 0
+#define PE_DD_IMPORT 1
+#define PE_DD_RESROUCE 2
+#define PE_DD_EXCEPTION 3
+#define PE_DD_CERTIFICATE 4
+#define PE_DD_BASERELOC 5
+#define PE_DD_DEBUG 6
+#define PE_DD_ARCH 7
+#define PE_DD_GLOBALPTR 8
+#define PE_DD_TLS 9
+#define PE_DD_LOADCONFIG 10
+#define PE_DD_BOUNDIMPORT 11
+#define PE_DD_IAT 12
+#define PE_DD_DELAYIMPORT 13
+#define PE_DD_CLRRUNTIME 14
+#define PE_DD_RESERVED 15
+#define PE_DD_MAX 16
+
+typedef struct _PE_DataDirEntry {
+ uint32_t de_addr;
+ uint32_t de_size;
+} PE_DataDirEntry;
+
+typedef struct _PE_DataDir {
+ PE_DataDirEntry dd_e[PE_DD_MAX];
+ uint32_t dd_total;
+} PE_DataDir;
+
+/*
+ * Section Headers: Section flags.
+ */
+
+#define IMAGE_SCN_TYPE_NO_PAD 0x00000008
+#define IMAGE_SCN_CNT_CODE 0x00000020
+#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
+#define IMAGE_SCN_LNK_OTHER 0x00000100
+#define IMAGE_SCN_LNK_INFO 0x00000200
+#define IMAGE_SCN_LNK_REMOVE 0x00000800
+#define IMAGE_SCN_LNK_COMDAT 0x00001000
+#define IMAGE_SCN_GPREL 0x00008000
+#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
+#define IMAGE_SCN_MEM_16BIT 0x00020000
+#define IMAGE_SCN_MEM_LOCKED 0x00040000
+#define IMAGE_SCN_MEM_PRELOAD 0x00080000
+#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
+#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
+#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
+#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
+#define IMAGE_SCN_ALIGN_16BYTES 0x00500000
+#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
+#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
+#define IMAGE_SCN_ALIGN_128BYTES 0x00800000
+#define IMAGE_SCN_ALIGN_256BYTES 0x00900000
+#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000
+#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000
+#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000
+#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000
+#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000
+#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000
+#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
+#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000
+#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000
+#define IMAGE_SCN_MEM_SHARED 0x10000000
+#define IMAGE_SCN_MEM_EXECUTE 0x20000000
+#define IMAGE_SCN_MEM_READ 0x40000000
+#define IMAGE_SCN_MEM_WRITE 0x80000000
+
+/*
+ * Section Headers.
+ */
+
+typedef struct _PE_SecHdr {
+ char sh_name[8];
+ uint32_t sh_virtsize;
+ uint32_t sh_addr;
+ uint32_t sh_rawsize;
+ uint32_t sh_rawptr;
+ uint32_t sh_relocptr;
+ uint32_t sh_lineptr;
+ uint16_t sh_nreloc;
+ uint16_t sh_nline;
+ uint32_t sh_char;
+} PE_SecHdr;
+
+#endif /* !_PE_H_ */
diff --git a/contrib/elftoolchain/libpe/pe_buffer.c b/contrib/elftoolchain/libpe/pe_buffer.c
new file mode 100644
index 0000000..e4ac19f
--- /dev/null
+++ b/contrib/elftoolchain/libpe/pe_buffer.c
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <errno.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_buffer.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_Buffer *
+pe_getbuffer(PE_Scn *ps, PE_Buffer *pb)
+{
+ PE *pe;
+ PE_SecBuf *sb;
+
+ if (ps == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ pe = ps->ps_pe;
+
+ if ((ps->ps_flags & LIBPE_F_LOAD_SECTION) == 0) {
+ if (pe->pe_flags & LIBPE_F_FD_DONE) {
+ errno = EACCES;
+ return (NULL);
+ }
+ if (pe->pe_flags & LIBPE_F_SPECIAL_FILE) {
+ if (libpe_load_all_sections(pe) < 0)
+ return (NULL);
+ } else {
+ if (libpe_load_section(pe, ps) < 0)
+ return (NULL);
+ }
+ }
+
+ sb = (PE_SecBuf *) pb;
+
+ if (sb == NULL)
+ sb = STAILQ_FIRST(&ps->ps_b);
+ else
+ sb = STAILQ_NEXT(sb, sb_next);
+
+ return ((PE_Buffer *) sb);
+}
+
+PE_Buffer *
+pe_newbuffer(PE_Scn *ps)
+{
+ PE *pe;
+ PE_SecBuf *sb;
+
+ if (ps == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ pe = ps->ps_pe;
+
+ if (pe->pe_flags & LIBPE_F_FD_DONE) {
+ errno = EACCES;
+ return (NULL);
+ }
+
+ if ((ps->ps_flags & LIBPE_F_LOAD_SECTION) == 0) {
+ if (libpe_load_section(pe, ps) < 0)
+ return (NULL);
+ }
+
+ if ((sb = libpe_alloc_buffer(ps, 0)) == NULL)
+ return (NULL);
+
+ sb->sb_flags |= PE_F_DIRTY;
+ ps->ps_flags |= PE_F_DIRTY;
+
+ return ((PE_Buffer *) sb);
+}
diff --git a/contrib/elftoolchain/libpe/pe_cntl.c b/contrib/elftoolchain/libpe/pe_cntl.c
new file mode 100644
index 0000000..1fc8c47
--- /dev/null
+++ b/contrib/elftoolchain/libpe/pe_cntl.c
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <errno.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_cntl.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+int
+pe_cntl(PE *pe, PE_Cmd cmd)
+{
+
+ if (pe == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ switch (cmd) {
+ case PE_C_FDDONE:
+ pe->pe_flags |= LIBPE_F_FD_DONE;
+ break;
+
+ case PE_C_FDREAD:
+ if (pe->pe_cmd == PE_C_WRITE) {
+ errno = EACCES;
+ return (-1);
+ }
+ if (libpe_load_all_sections(pe) < 0)
+ return (-1);
+ break;
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (0);
+}
diff --git a/contrib/elftoolchain/libpe/pe_coff.c b/contrib/elftoolchain/libpe/pe_coff.c
new file mode 100644
index 0000000..d5cd833
--- /dev/null
+++ b/contrib/elftoolchain/libpe/pe_coff.c
@@ -0,0 +1,157 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_coff.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_CoffHdr *
+pe_coff_header(PE *pe)
+{
+
+ if (pe->pe_ch == NULL) {
+ errno = ENOENT;
+ return (NULL);
+ }
+
+ return (pe->pe_ch);
+}
+
+PE_OptHdr *
+pe_opt_header(PE *pe)
+{
+
+ if (pe->pe_oh == NULL) {
+ errno = ENOENT;
+ return (NULL);
+ }
+
+ return (pe->pe_oh);
+}
+
+PE_DataDir *
+pe_data_dir(PE *pe)
+{
+
+ if (pe->pe_dd == NULL) {
+ errno = ENOENT;
+ return (NULL);
+ }
+
+ return (pe->pe_dd);
+}
+
+int
+pe_update_coff_header(PE *pe, PE_CoffHdr *ch)
+{
+
+ if (pe == NULL || ch == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+ errno = EACCES;
+ return (-1);
+ }
+
+ if (pe->pe_ch == NULL) {
+ if ((pe->pe_ch = malloc(sizeof(PE_CoffHdr))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ } else {
+ /* Rewrite optional header if `optsize' field changed. */
+ if (pe->pe_ch->ch_optsize != ch->ch_optsize)
+ pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
+ }
+
+ *pe->pe_ch = *ch;
+
+ pe->pe_flags |= LIBPE_F_DIRTY_COFF_HEADER;
+
+ return (0);
+}
+
+int
+pe_update_opt_header(PE *pe, PE_OptHdr *oh)
+{
+
+ if (pe == NULL || oh == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+ errno = EACCES;
+ return (-1);
+ }
+
+ if (pe->pe_oh == NULL) {
+ if ((pe->pe_oh = malloc(sizeof(PE_OptHdr))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ }
+
+ *pe->pe_oh = *oh;
+
+ pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
+
+ return (0);
+}
+
+int
+pe_update_data_dir(PE *pe, PE_DataDir *dd)
+{
+
+ if (pe == NULL || dd == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+ errno = EACCES;
+ return (-1);
+ }
+
+ if (pe->pe_dd == NULL) {
+ if ((pe->pe_dd = malloc(sizeof(PE_DataDir))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ }
+
+ *pe->pe_dd = *dd;
+
+ pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
+
+ return (0);
+}
diff --git a/contrib/elftoolchain/libpe/pe_dos.c b/contrib/elftoolchain/libpe/pe_dos.c
new file mode 100644
index 0000000..01ba42f
--- /dev/null
+++ b/contrib/elftoolchain/libpe/pe_dos.c
@@ -0,0 +1,119 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_dos.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_DosHdr *
+pe_msdos_header(PE *pe)
+{
+
+ if (pe == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (pe->pe_dh == NULL) {
+ errno = ENOENT;
+ return (NULL);
+ }
+
+ return (pe->pe_dh);
+}
+
+char *
+pe_msdos_stub(PE *pe, size_t *len)
+{
+
+ if (pe == NULL || len == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (pe->pe_stub_ex > 0 &&
+ (pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0) {
+ assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+ (void) libpe_read_msdos_stub(pe);
+ }
+
+ *len = sizeof(PE_DosHdr) + pe->pe_stub_ex;
+
+ return (pe->pe_stub);
+}
+
+int
+ps_update_msdos_header(PE *pe, PE_DosHdr *dh)
+{
+
+ if (pe == NULL || dh == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+ errno = EACCES;
+ return (-1);
+ }
+
+ if (pe->pe_dh == NULL) {
+ if ((pe->pe_dh = malloc(sizeof(PE_DosHdr))) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ }
+
+ *pe->pe_dh = *dh;
+
+ pe->pe_flags |= LIBPE_F_DIRTY_DOS_HEADER;
+
+ return (0);
+}
+
+int
+ps_update_msdos_stub(PE *pe, char *dos_stub, size_t sz)
+{
+
+ if (pe == NULL || dos_stub == NULL || sz == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+ errno = EACCES;
+ return (-1);
+ }
+
+ pe->pe_stub_app = dos_stub;
+ pe->pe_stub_app_sz = sz;
+
+ return (0);
+}
diff --git a/contrib/elftoolchain/libpe/pe_flag.c b/contrib/elftoolchain/libpe/pe_flag.c
new file mode 100644
index 0000000..c392a4d
--- /dev/null
+++ b/contrib/elftoolchain/libpe/pe_flag.c
@@ -0,0 +1,187 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <errno.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_flag.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+int
+pe_flag(PE *pe, PE_Cmd c, unsigned int flags)
+{
+
+ if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((flags & ~(PE_F_STRIP_DOS_STUB | PE_F_STRIP_RICH_HEADER |
+ PE_F_STRIP_SYMTAB | PE_F_STRIP_DEBUG)) != 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (c == PE_C_SET)
+ pe->pe_flags |= flags;
+ else
+ pe->pe_flags &= ~flags;
+
+ return (0);
+}
+
+int
+pe_flag_dos_header(PE *pe, PE_Cmd c, unsigned int flags)
+{
+
+ if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+ (flags & ~PE_F_DIRTY) != 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (c == PE_C_SET)
+ pe->pe_flags |= LIBPE_F_DIRTY_DOS_HEADER;
+ else
+ pe->pe_flags &= ~LIBPE_F_DIRTY_DOS_HEADER;
+
+ return (0);
+}
+
+int
+pe_flag_coff_header(PE *pe, PE_Cmd c, unsigned int flags)
+{
+
+ if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+ (flags & ~PE_F_DIRTY) != 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (c == PE_C_SET)
+ pe->pe_flags |= LIBPE_F_DIRTY_COFF_HEADER;
+ else
+ pe->pe_flags &= ~LIBPE_F_DIRTY_COFF_HEADER;
+
+ return (0);
+}
+
+int
+pe_flag_opt_header(PE *pe, PE_Cmd c, unsigned int flags)
+{
+
+ if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+ (flags & ~PE_F_DIRTY) != 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (c == PE_C_SET)
+ pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
+ else
+ pe->pe_flags &= ~LIBPE_F_DIRTY_OPT_HEADER;
+
+ return (0);
+}
+
+int
+pe_flag_data_dir(PE *pe, PE_Cmd c, unsigned int flags)
+{
+
+ if (pe == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+ (flags & ~PE_F_DIRTY) != 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (c == PE_C_SET)
+ pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER;
+ else
+ pe->pe_flags &= ~LIBPE_F_DIRTY_OPT_HEADER;
+
+ return (0);
+}
+
+int
+pe_flag_scn(PE_Scn *ps, PE_Cmd c, unsigned int flags)
+{
+
+ if (ps == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+ (flags & ~(PE_F_DIRTY | PE_F_STRIP_SECTION)) == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (c == PE_C_SET)
+ ps->ps_flags |= flags;
+ else
+ ps->ps_flags &= ~flags;
+
+ return (0);
+}
+
+int
+pe_flag_section_header(PE_Scn *ps, PE_Cmd c, unsigned int flags)
+{
+ PE *pe;
+
+ if (ps == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+ (flags & ~PE_F_DIRTY) != 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ pe = ps->ps_pe;
+
+ /* The library doesn't support per section header dirty flag. */
+ if (c == PE_C_SET)
+ pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
+ else
+ pe->pe_flags &= ~LIBPE_F_DIRTY_SEC_HEADER;
+
+ return (0);
+}
+
+int
+pe_flag_buffer(PE_Buffer *pb, PE_Cmd c, unsigned int flags)
+{
+ PE_SecBuf *sb;
+
+ if (pb == NULL || (c != PE_C_SET && c != PE_C_CLR) ||
+ (flags & ~PE_F_DIRTY) != 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ sb = (PE_SecBuf *) pb;
+
+ if (c == PE_C_SET)
+ sb->sb_flags |= flags;
+ else
+ sb->sb_flags &= ~flags;
+
+ return (0);
+}
diff --git a/contrib/elftoolchain/libpe/pe_init.c b/contrib/elftoolchain/libpe/pe_init.c
new file mode 100644
index 0000000..4e2f22a
--- /dev/null
+++ b/contrib/elftoolchain/libpe/pe_init.c
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 2015 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/queue.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_init.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE *
+pe_init(int fd, PE_Cmd c, PE_Object o)
+{
+ PE *pe;
+
+ if ((pe = calloc(1, sizeof(*pe))) == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ pe->pe_fd = fd;
+ pe->pe_cmd = c;
+ pe->pe_obj = o;
+ STAILQ_INIT(&pe->pe_scn);
+
+ switch (c) {
+ case PE_C_READ:
+ case PE_C_RDWR:
+ if (libpe_open_object(pe) < 0)
+ goto init_fail;
+ break;
+
+ case PE_C_WRITE:
+ if (o < PE_O_PE32 || o > PE_O_COFF) {
+ errno = EINVAL;
+ goto init_fail;
+ }
+ break;
+
+ default:
+ errno = EINVAL;
+ goto init_fail;
+ }
+
+ return (pe);
+
+init_fail:
+ pe_finish(pe);
+ return (NULL);
+}
+
+void
+pe_finish(PE *pe)
+{
+
+ if (pe == NULL)
+ return;
+
+ libpe_release_object(pe);
+}
+
+PE_Object
+pe_object(PE *pe)
+{
+
+ if (pe == NULL) {
+ errno = EINVAL;
+ return (PE_O_UNKNOWN);
+ }
+
+ return (pe->pe_obj);
+}
diff --git a/contrib/elftoolchain/libpe/pe_rich.c b/contrib/elftoolchain/libpe/pe_rich.c
new file mode 100644
index 0000000..ea1029e
--- /dev/null
+++ b/contrib/elftoolchain/libpe/pe_rich.c
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_rich.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_RichHdr *
+pe_rich_header(PE *pe)
+{
+
+ if (pe == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (pe->pe_rh == NULL && pe->pe_stub_ex > 0 &&
+ (pe->pe_flags & LIBPE_F_LOAD_DOS_STUB) == 0) {
+ assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0);
+ (void) libpe_read_msdos_stub(pe);
+ }
+
+ if (pe->pe_rh == NULL) {
+ errno = ENOENT;
+ return (NULL);
+ }
+
+ return (pe->pe_rh);
+}
+
+static uint32_t
+rol32(uint32_t n, int c)
+{
+
+ c &= 0x1f;
+
+ return ((n << c) | (n >> (0x20 - c)));
+}
+
+int
+pe_rich_header_validate(PE *pe)
+{
+ PE_RichHdr *rh;
+ uint32_t cksum;
+ char *p;
+ int i, off;
+
+ if (pe_rich_header(pe) == NULL)
+ return (-1);
+
+ assert(pe->pe_rh_start != NULL);
+
+ /*
+ * Initial value of the checksum is the offset to the begin of
+ * the Rich header.
+ */
+ cksum = pe->pe_rh_start - pe->pe_stub;
+
+ /*
+ * Add the bytes before the Rich header to the checksum, rotated
+ * left by the offset.
+ */
+ for (p = pe->pe_stub; p < pe->pe_rh_start; p++) {
+ /* Skip dh_lfanew. */
+ off = p - pe->pe_stub;
+ if (off >= 0x3c && off < 0x40)
+ continue;
+ cksum += rol32((unsigned char) *p, off);
+ }
+
+ /* Add each compid rotated left by its count to the checksum. */
+ rh = pe->pe_rh;
+ for (i = 0; (uint32_t) i < rh->rh_total; i++)
+ cksum += rol32(rh->rh_compid[i], rh->rh_cnt[i]);
+
+ /* Validate the checksum with the XOR mask stored after "Rich". */
+ if (cksum == rh->rh_xor)
+ return (1);
+
+ return (0);
+}
diff --git a/contrib/elftoolchain/libpe/pe_section.c b/contrib/elftoolchain/libpe/pe_section.c
new file mode 100644
index 0000000..3e82d84
--- /dev/null
+++ b/contrib/elftoolchain/libpe/pe_section.c
@@ -0,0 +1,213 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <errno.h>
+#include <string.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_section.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+PE_Scn *
+pe_getscn(PE *pe, size_t ndx)
+{
+ PE_Scn *ps;
+
+ if (pe == NULL || ndx < 1 || ndx > 0xFFFFU) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+ if (ps->ps_ndx == ndx)
+ return (ps);
+ }
+
+ errno = ENOENT;
+
+ return (NULL);
+}
+
+size_t
+pe_ndxscn(PE_Scn *ps)
+{
+
+ if (ps == NULL) {
+ errno = EINVAL;
+ return (0);
+ }
+
+ return (ps->ps_ndx);
+}
+
+PE_Scn *
+pe_nextscn(PE *pe, PE_Scn *ps)
+{
+
+ if (pe == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (ps == NULL)
+ ps = STAILQ_FIRST(&pe->pe_scn);
+ else
+ ps = STAILQ_NEXT(ps, ps_next);
+
+ while (ps != NULL) {
+ if (ps->ps_ndx >= 1 && ps->ps_ndx <= 0xFFFFU)
+ return (ps);
+ ps = STAILQ_NEXT(ps, ps_next);
+ }
+
+ return (NULL);
+}
+
+PE_Scn *
+pe_newscn(PE *pe)
+{
+ PE_Scn *ps, *tps, *_tps;
+
+ if (pe == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+ errno = EACCES;
+ return (NULL);
+ }
+
+ if ((ps = libpe_alloc_scn(pe)) == NULL)
+ return (NULL);
+
+ if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER) {
+ STAILQ_FOREACH_SAFE(tps, &pe->pe_scn, ps_next, _tps)
+ libpe_release_scn(tps);
+ pe->pe_flags &= ~LIBPE_F_BAD_SEC_HEADER;
+ }
+
+ STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next);
+
+ ps->ps_flags |= PE_F_DIRTY | LIBPE_F_LOAD_SECTION;
+ pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
+
+ return (ps);
+}
+
+PE_Scn *
+pe_insertscn(PE *pe, size_t ndx)
+{
+ PE_Scn *ps, *a, *b;
+
+ if (pe == NULL || ndx < 1 || ndx > 0xFFFFU) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+ errno = EACCES;
+ return (NULL);
+ }
+
+ if ((ps = libpe_alloc_scn(pe)) == NULL)
+ return (NULL);
+
+ if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER) {
+ STAILQ_FOREACH_SAFE(a, &pe->pe_scn, ps_next, b)
+ libpe_release_scn(a);
+ pe->pe_flags &= ~LIBPE_F_BAD_SEC_HEADER;
+ }
+
+ b = NULL;
+ STAILQ_FOREACH(a, &pe->pe_scn, ps_next) {
+ if (a->ps_ndx & 0xFFFF0000U)
+ continue;
+ if (a->ps_ndx == ndx)
+ break;
+ b = a;
+ }
+
+ if (a == NULL) {
+ STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next);
+ if (b == NULL)
+ ps->ps_ndx = 1;
+ else
+ ps->ps_ndx = b->ps_ndx + 1;
+ } else if (b == NULL) {
+ STAILQ_INSERT_HEAD(&pe->pe_scn, ps, ps_next);
+ ps->ps_ndx = 1;
+ } else {
+ STAILQ_INSERT_AFTER(&pe->pe_scn, b, ps, ps_next);
+ ps->ps_ndx = ndx;
+ }
+
+ a = ps;
+ while ((a = STAILQ_NEXT(a, ps_next)) != NULL) {
+ if ((a->ps_ndx & 0xFFFF0000U) == 0)
+ a->ps_ndx++;
+ }
+
+ ps->ps_flags |= PE_F_DIRTY | LIBPE_F_LOAD_SECTION;
+ pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
+
+ return (ps);
+}
+
+PE_SecHdr *
+pe_section_header(PE_Scn *ps)
+{
+
+ if (ps == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ return (&ps->ps_sh);
+}
+
+int
+pe_update_section_header(PE_Scn *ps, PE_SecHdr *sh)
+{
+ PE *pe;
+
+ if (ps == NULL || sh == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ pe = ps->ps_pe;
+
+ if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+ errno = EACCES;
+ return (-1);
+ }
+
+ ps->ps_sh = *sh;
+ pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER;
+
+ return (0);
+}
diff --git a/contrib/elftoolchain/libpe/pe_symtab.c b/contrib/elftoolchain/libpe/pe_symtab.c
new file mode 100644
index 0000000..d0e90d1
--- /dev/null
+++ b/contrib/elftoolchain/libpe/pe_symtab.c
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <errno.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_symtab.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+int
+pe_update_symtab(PE *pe, char *symtab, size_t sz, unsigned int nsym)
+{
+ PE_Scn *ps;
+ PE_SecBuf *sb;
+ PE_SecHdr *sh;
+
+ if (pe == NULL || symtab == NULL || sz == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+ errno = EACCES;
+ return (-1);
+ }
+
+ /* Remove the old symbol table. */
+ STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) {
+ if (ps->ps_ndx == 0xFFFFFFFFU)
+ libpe_release_scn(ps);
+ }
+
+ /*
+ * Insert the new symbol table.
+ */
+
+ if ((ps = libpe_alloc_scn(pe)) == NULL)
+ return (-1);
+
+ STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next);
+ ps->ps_ndx = 0xFFFFFFFFU;
+ ps->ps_flags |= PE_F_DIRTY;
+
+ /*
+ * Set the symbol table section offset to the maximum to make sure
+ * that it will be placed in the end of the file during section
+ * layout.
+ */
+ sh = &ps->ps_sh;
+ sh->sh_rawptr = 0xFFFFFFFFU;
+ sh->sh_rawsize = sz;
+
+ /* Allocate the buffer. */
+ if ((sb = libpe_alloc_buffer(ps, 0)) == NULL)
+ return (-1);
+ sb->sb_flags |= PE_F_DIRTY;
+ sb->sb_pb.pb_size = sz;
+ sb->sb_pb.pb_buf = symtab;
+
+ pe->pe_nsym = nsym;
+
+ return (0);
+}
diff --git a/contrib/elftoolchain/libpe/pe_update.c b/contrib/elftoolchain/libpe/pe_update.c
new file mode 100644
index 0000000..ec2b2e5
--- /dev/null
+++ b/contrib/elftoolchain/libpe/pe_update.c
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 2016 Kai Wang
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "_libpe.h"
+
+ELFTC_VCSID("$Id: pe_update.c 3312 2016-01-10 09:23:51Z kaiwang27 $");
+
+off_t
+pe_update(PE *pe)
+{
+ off_t off;
+
+ if (pe == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) {
+ errno = EACCES;
+ return (-1);
+ }
+
+ if (pe->pe_cmd == PE_C_RDWR || (pe->pe_cmd == PE_C_WRITE &&
+ (pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0)) {
+ if (lseek(pe->pe_fd, 0, SEEK_SET) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+ }
+
+ off = 0;
+
+ if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P) {
+ if ((off = libpe_write_msdos_stub(pe, off)) < 0)
+ return (-1);
+
+ if ((off = libpe_write_pe_header(pe, off)) < 0)
+ return (-1);
+ }
+
+ if (libpe_resync_sections(pe, off) < 0)
+ return (-1);
+
+ if ((off = libpe_write_coff_header(pe, off)) < 0)
+ return (-1);
+
+ if ((off = libpe_write_section_headers(pe, off)) < 0)
+ return (-1);
+
+ if ((off = libpe_write_sections(pe, off)) < 0)
+ return (-1);
+
+ if (ftruncate(pe->pe_fd, off) < 0) {
+ errno = EIO;
+ return (-1);
+ }
+
+ return (off);
+}
diff --git a/contrib/elftoolchain/nm/os.NetBSD.mk b/contrib/elftoolchain/nm/os.NetBSD.mk
new file mode 100644
index 0000000..ae214e3
--- /dev/null
+++ b/contrib/elftoolchain/nm/os.NetBSD.mk
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
diff --git a/contrib/elftoolchain/readelf/os.NetBSD.mk b/contrib/elftoolchain/readelf/os.NetBSD.mk
new file mode 100644
index 0000000..ae214e3
--- /dev/null
+++ b/contrib/elftoolchain/readelf/os.NetBSD.mk
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c
index a017023..d8e44dd 100644
--- a/contrib/elftoolchain/readelf/readelf.c
+++ b/contrib/elftoolchain/readelf/readelf.c
@@ -47,7 +47,16 @@
#include "_elftc.h"
-ELFTC_VCSID("$Id: readelf.c 3271 2015-12-11 18:53:08Z kaiwang27 $");
+ELFTC_VCSID("$Id: readelf.c 3395 2016-02-10 16:29:44Z emaste $");
+
+/* Backwards compatability for older FreeBSD releases. */
+#ifndef STB_GNU_UNIQUE
+#define STB_GNU_UNIQUE 10
+#endif
+#ifndef STT_SPARC_REGISTER
+#define STT_SPARC_REGISTER 13
+#endif
+
/*
* readelf(1) options.
@@ -338,7 +347,7 @@ static const char *phdr_type(unsigned int ptype);
static const char *ppc_abi_fp(uint64_t fp);
static const char *ppc_abi_vector(uint64_t vec);
static const char *r_type(unsigned int mach, unsigned int type);
-static void readelf_usage(void);
+static void readelf_usage(int status);
static void readelf_version(void);
static void search_loclist_at(struct readelf *re, Dwarf_Die die,
Dwarf_Unsigned lowpc);
@@ -348,7 +357,7 @@ static void set_cu_context(struct readelf *re, Dwarf_Half psize,
Dwarf_Half osize, Dwarf_Half ver);
static const char *st_bind(unsigned int sbind);
static const char *st_shndx(unsigned int shndx);
-static const char *st_type(unsigned int stype);
+static const char *st_type(unsigned int mach, unsigned int stype);
static const char *st_vis(unsigned int svis);
static const char *top_tag(unsigned int tag);
static void unload_sections(struct readelf *re);
@@ -958,6 +967,7 @@ st_bind(unsigned int sbind)
case STB_LOCAL: return "LOCAL";
case STB_GLOBAL: return "GLOBAL";
case STB_WEAK: return "WEAK";
+ case STB_GNU_UNIQUE: return "UNIQUE";
default:
if (sbind >= STB_LOOS && sbind <= STB_HIOS)
return "OS";
@@ -971,7 +981,7 @@ st_bind(unsigned int sbind)
}
static const char *
-st_type(unsigned int stype)
+st_type(unsigned int mach, unsigned int stype)
{
static char s_stype[32];
@@ -987,10 +997,12 @@ st_type(unsigned int stype)
if (stype >= STT_LOOS && stype <= STT_HIOS)
snprintf(s_stype, sizeof(s_stype), "OS+%#x",
stype - STT_LOOS);
- else if (stype >= STT_LOPROC && stype <= STT_HIPROC)
+ else if (stype >= STT_LOPROC && stype <= STT_HIPROC) {
+ if (mach == EM_SPARCV9 && stype == STT_SPARC_REGISTER)
+ return "REGISTER";
snprintf(s_stype, sizeof(s_stype), "PROC+%#x",
stype - STT_LOPROC);
- else
+ } else
snprintf(s_stype, sizeof(s_stype), "<unknown: %#x>",
stype);
return (s_stype);
@@ -1066,7 +1078,7 @@ r_type(unsigned int mach, unsigned int type)
case 4: return "R_386_PLT32";
case 5: return "R_386_COPY";
case 6: return "R_386_GLOB_DAT";
- case 7: return "R_386_JMP_SLOT";
+ case 7: return "R_386_JUMP_SLOT";
case 8: return "R_386_RELATIVE";
case 9: return "R_386_GOTOFF";
case 10: return "R_386_GOTPC";
@@ -1558,7 +1570,7 @@ r_type(unsigned int mach, unsigned int type)
case 4: return "R_X86_64_PLT32";
case 5: return "R_X86_64_COPY";
case 6: return "R_X86_64_GLOB_DAT";
- case 7: return "R_X86_64_JMP_SLOT";
+ case 7: return "R_X86_64_JUMP_SLOT";
case 8: return "R_X86_64_RELATIVE";
case 9: return "R_X86_64_GOTPCREL";
case 10: return "R_X86_64_32";
@@ -3465,9 +3477,10 @@ dump_symtab(struct readelf *re, int i)
continue;
}
printf("%6d:", j);
- printf(" %16.16jx", (uintmax_t)sym.st_value);
- printf(" %5ju", sym.st_size);
- printf(" %-7s", st_type(GELF_ST_TYPE(sym.st_info)));
+ printf(" %16.16jx", (uintmax_t) sym.st_value);
+ printf(" %5ju", (uintmax_t) sym.st_size);
+ printf(" %-7s", st_type(re->ehdr.e_machine,
+ GELF_ST_TYPE(sym.st_info)));
printf(" %-6s", st_bind(GELF_ST_BIND(sym.st_info)));
printf(" %-8s", st_vis(GELF_ST_VISIBILITY(sym.st_other)));
printf(" %3s", st_shndx(sym.st_shndx));
@@ -4303,7 +4316,7 @@ dump_compatibility_tag(uint8_t *p, uint8_t *pe)
uint64_t val;
val = _decode_uleb128(&p, pe);
- printf("flag = %ju, vendor = %s\n", val, p);
+ printf("flag = %ju, vendor = %s\n", (uintmax_t) val, p);
p += strlen((char *) p) + 1;
return (p);
@@ -4997,7 +5010,8 @@ dump_dwarf_line(struct readelf *re)
break;
case DW_LNS_set_isa:
isa = _decode_uleb128(&p, pe);
- printf(" Set isa to %ju\n", isa);
+ printf(" Set isa to %ju\n",
+ (uintmax_t) isa);
break;
default:
/* Unrecognized extended opcodes. */
@@ -5749,12 +5763,12 @@ dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die, Dwarf_Addr base)
}
if (re->ec == ELFCLASS32)
printf("%08jx %08jx\n",
- ranges[j].dwr_addr1 + base0,
- ranges[j].dwr_addr2 + base0);
+ (uintmax_t) (ranges[j].dwr_addr1 + base0),
+ (uintmax_t) (ranges[j].dwr_addr2 + base0));
else
printf("%016jx %016jx\n",
- ranges[j].dwr_addr1 + base0,
- ranges[j].dwr_addr2 + base0);
+ (uintmax_t) (ranges[j].dwr_addr1 + base0),
+ (uintmax_t) (ranges[j].dwr_addr2 + base0));
}
}
@@ -6728,7 +6742,7 @@ dump_dwarf_loclist(struct readelf *re)
set_cu_context(re, la->la_cu_psize, la->la_cu_osize,
la->la_cu_ver);
for (i = 0; i < lcnt; i++) {
- printf(" %8.8jx ", la->la_off);
+ printf(" %8.8jx ", (uintmax_t) la->la_off);
if (llbuf[i]->ld_lopc == 0 && llbuf[i]->ld_hipc == 0) {
printf("<End of list>\n");
continue;
@@ -6850,13 +6864,15 @@ hex_dump(struct readelf *re)
if (find_dumpop(re, (size_t) i, s->name, HEX_DUMP, -1) == NULL)
continue;
(void) elf_errno();
- if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+ if ((d = elf_getdata(s->scn, NULL)) == NULL &&
+ (d = elf_rawdata(s->scn, NULL)) == NULL) {
elferr = elf_errno();
if (elferr != 0)
warnx("elf_getdata failed: %s",
elf_errmsg(elferr));
continue;
}
+ (void) elf_errno();
if (d->d_size <= 0 || d->d_buf == NULL) {
printf("\nSection '%s' has no data to dump.\n",
s->name);
@@ -6905,13 +6921,15 @@ str_dump(struct readelf *re)
if (find_dumpop(re, (size_t) i, s->name, STR_DUMP, -1) == NULL)
continue;
(void) elf_errno();
- if ((d = elf_getdata(s->scn, NULL)) == NULL) {
+ if ((d = elf_getdata(s->scn, NULL)) == NULL &&
+ (d = elf_rawdata(s->scn, NULL)) == NULL) {
elferr = elf_errno();
if (elferr != 0)
warnx("elf_getdata failed: %s",
elf_errmsg(elferr));
continue;
}
+ (void) elf_errno();
if (d->d_size <= 0 || d->d_buf == NULL) {
printf("\nSection '%s' has no data to dump.\n",
s->name);
@@ -7370,10 +7388,13 @@ _read_lsb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read)
case 8:
ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
+ /* FALLTHROUGH */
case 4:
ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
+ /* FALLTHROUGH */
case 2:
ret |= ((uint64_t) src[1]) << 8;
+ /* FALLTHROUGH */
case 1:
ret |= src[0];
break;
@@ -7433,10 +7454,13 @@ _decode_lsb(uint8_t **data, int bytes_to_read)
case 8:
ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40;
ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56;
+ /* FALLTHROUGH */
case 4:
ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24;
+ /* FALLTHROUGH */
case 2:
ret |= ((uint64_t) src[1]) << 8;
+ /* FALLTHROUGH */
case 1:
ret |= src[0];
break;
@@ -7558,6 +7582,10 @@ Usage: %s [options] file...\n\
-s | --syms | --symbols Print symbol tables.\n\
-t | --section-details Print additional information about sections.\n\
-v | --version Print a version identifier and exit.\n\
+ -w[afilmoprsFLR] | --debug-dump={abbrev,aranges,decodedline,frames,\n\
+ frames-interp,info,loc,macro,pubnames,\n\
+ ranges,Ranges,rawline,str}\n\
+ Display DWARF information.\n\
-x INDEX | --hex-dump=INDEX\n\
Display contents of a section as hexadecimal.\n\
-A | --arch-specific (accepted, but ignored)\n\
@@ -7574,10 +7602,10 @@ Usage: %s [options] file...\n\
static void
-readelf_usage(void)
+readelf_usage(int status)
{
fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
- exit(EXIT_FAILURE);
+ exit(status);
}
int
@@ -7596,7 +7624,7 @@ main(int argc, char **argv)
longopts, NULL)) != -1) {
switch(opt) {
case '?':
- readelf_usage();
+ readelf_usage(EXIT_SUCCESS);
break;
case 'A':
re->options |= RE_AA;
@@ -7621,7 +7649,7 @@ main(int argc, char **argv)
re->options |= RE_G;
break;
case 'H':
- readelf_usage();
+ readelf_usage(EXIT_SUCCESS);
break;
case 'h':
re->options |= RE_H;
@@ -7699,7 +7727,7 @@ main(int argc, char **argv)
argc -= optind;
if (argc == 0 || re->options == 0)
- readelf_usage();
+ readelf_usage(EXIT_FAILURE);
if (argc > 1)
re->flags |= DISPLAY_FILENAME;
diff --git a/contrib/elftoolchain/size/os.NetBSD.mk b/contrib/elftoolchain/size/os.NetBSD.mk
new file mode 100644
index 0000000..ae214e3
--- /dev/null
+++ b/contrib/elftoolchain/size/os.NetBSD.mk
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
diff --git a/contrib/elftoolchain/strings/os.NetBSD.mk b/contrib/elftoolchain/strings/os.NetBSD.mk
new file mode 100644
index 0000000..ae214e3
--- /dev/null
+++ b/contrib/elftoolchain/strings/os.NetBSD.mk
@@ -0,0 +1,2 @@
+# TODO(#511): Revert after the source tree is -Wconversion clean.
+WARNS=5
diff --git a/contrib/elftoolchain/strings/strings.1 b/contrib/elftoolchain/strings/strings.1
index 15ad7a7..205afdf 100644
--- a/contrib/elftoolchain/strings/strings.1
+++ b/contrib/elftoolchain/strings/strings.1
@@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $Id: strings.1 3195 2015-05-12 17:22:19Z emaste $
+.\" $Id: strings.1 3360 2016-01-24 18:34:06Z jkoshy $
.\"
-.Dd December 19, 2011
+.Dd January 24, 2016
.Dt STRINGS 1
.Os
.Sh NAME
@@ -100,6 +100,9 @@ Print a usage summary and exit.
Print the contiguous character sequence of at least
.Ar number
characters long, instead of the default of 4 characters.
+Argument
+.Ar number
+should specify a positive decimal integer.
.It Fl o
Equivalent to specifying
.Fl t Ar o .
diff --git a/contrib/elftoolchain/strings/strings.c b/contrib/elftoolchain/strings/strings.c
index 6eab165..f122eba 100644
--- a/contrib/elftoolchain/strings/strings.c
+++ b/contrib/elftoolchain/strings/strings.c
@@ -37,6 +37,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sysexits.h>
#include <unistd.h>
#include <libelf.h>
@@ -45,7 +46,7 @@
#include "_elftc.h"
-ELFTC_VCSID("$Id: strings.c 3174 2015-03-27 17:13:41Z emaste $");
+ELFTC_VCSID("$Id: strings.c 3360 2016-01-24 18:34:06Z jkoshy $");
enum return_code {
RETURN_OK,
@@ -73,10 +74,10 @@ enum encoding_style {
((c) == '\t' || isprint((c)) || \
(encoding == ENCODING_8BIT && (c) > 127)))
-
-static int encoding_size, entire_file, min_len, show_filename, show_loc;
+static int encoding_size, entire_file, show_filename, show_loc;
static enum encoding_style encoding;
static enum radix_style radix;
+static intmax_t min_len;
static struct option strings_longopts[] = {
{ "all", no_argument, NULL, 'a'},
@@ -144,7 +145,10 @@ main(int argc, char **argv)
show_filename = 1;
break;
case 'n':
- min_len = (int)strtoimax(optarg, (char**)NULL, 10);
+ min_len = strtoimax(optarg, (char**)NULL, 10);
+ if (min_len <= 0)
+ errx(EX_USAGE, "option -n should specify a "
+ "positive decimal integer.");
break;
case 'o':
show_loc = 1;
diff --git a/contrib/unbound/Makefile.in b/contrib/unbound/Makefile.in
index 282c7d6..381c383 100644
--- a/contrib/unbound/Makefile.in
+++ b/contrib/unbound/Makefile.in
@@ -95,7 +95,7 @@ PYUNBOUND_SRC=
# libunbound_wrap.lo if python libunbound wrapper enabled.
PYUNBOUND_OBJ=@PYUNBOUND_OBJ@
COMMON_SRC=services/cache/dns.c services/cache/infra.c services/cache/rrset.c \
-util/data/dname.c util/data/msgencode.c util/data/msgparse.c \
+util/as112.c util/data/dname.c util/data/msgencode.c util/data/msgparse.c \
util/data/msgreply.c util/data/packed_rrset.c iterator/iterator.c \
iterator/iter_delegpt.c iterator/iter_donotq.c iterator/iter_fwd.c \
iterator/iter_hints.c iterator/iter_priv.c iterator/iter_resptype.c \
@@ -113,7 +113,7 @@ validator/val_neg.c validator/val_nsec3.c validator/val_nsec.c \
validator/val_secalgo.c validator/val_sigcrypt.c \
validator/val_utils.c dns64/dns64.c $(CHECKLOCK_SRC) $(DNSTAP_SRC)
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
-msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
+as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
iter_scrub.lo iter_utils.lo localzone.lo mesh.lo modstack.lo \
outbound_list.lo alloc.lo config_file.lo configlexer.lo configparser.lo \
@@ -595,6 +595,7 @@ depend:
rm -f $(DEPEND_TMP) $(DEPEND_TMP2)
# Dependencies
+as112.lo as112.o: $(srcdir)/util/as112.c $(srcdir)/util/as112.h
dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
$(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
$(srcdir)/util/locks.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/msgreply.h \
@@ -702,7 +703,7 @@ localzone.lo localzone.o: $(srcdir)/services/localzone.c config.h $(srcdir)/serv
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h \
$(srcdir)/util/net_help.h $(srcdir)/util/netevent.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/util/as112.h
mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/netevent.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
$(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \
@@ -821,7 +822,7 @@ val_anchor.lo val_anchor.o: $(srcdir)/validator/val_anchor.c config.h $(srcdir)/
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_sigcrypt.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/validator/autotrust.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
+ $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h $(srcdir)/util/as112.h
validator.lo validator.o: $(srcdir)/validator/validator.c config.h $(srcdir)/validator/validator.h \
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
diff --git a/contrib/unbound/doc/example.conf b/contrib/unbound/doc/example.conf
index 11c3ba9..37d58e4 100644
--- a/contrib/unbound/doc/example.conf
+++ b/contrib/unbound/doc/example.conf
@@ -508,13 +508,17 @@ server:
# local-zone: "8.b.d.0.1.0.0.2.ip6.arpa." nodefault
# And for 64.100.in-addr.arpa. to 127.100.in-addr.arpa.
- # if unbound is running service for the local host then it is useful
+ # If unbound is running service for the local host then it is useful
# to perform lan-wide lookups to the upstream, and unblock the
# long list of local-zones above. If this unbound is a dns server
# for a network of computers, disabled is better and stops information
# leakage of local lan information.
# unblock-lan-zones: no
+ # The insecure-lan-zones option disables validation for
+ # these zones, as if they were all listed as domain-insecure.
+ # insecure-lan-zones: no
+
# a number of locally served zones can be configured.
# local-zone: <zone> <type>
# local-data: "<resource record string>"
diff --git a/contrib/unbound/doc/example.conf.in b/contrib/unbound/doc/example.conf.in
index ff90e3b..cf9a4ee 100644
--- a/contrib/unbound/doc/example.conf.in
+++ b/contrib/unbound/doc/example.conf.in
@@ -508,13 +508,17 @@ server:
# local-zone: "8.b.d.0.1.0.0.2.ip6.arpa." nodefault
# And for 64.100.in-addr.arpa. to 127.100.in-addr.arpa.
- # if unbound is running service for the local host then it is useful
+ # If unbound is running service for the local host then it is useful
# to perform lan-wide lookups to the upstream, and unblock the
# long list of local-zones above. If this unbound is a dns server
# for a network of computers, disabled is better and stops information
# leakage of local lan information.
# unblock-lan-zones: no
+ # The insecure-lan-zones option disables validation for
+ # these zones, as if they were all listed as domain-insecure.
+ # insecure-lan-zones: no
+
# a number of locally served zones can be configured.
# local-zone: <zone> <type>
# local-data: "<resource record string>"
diff --git a/contrib/unbound/doc/unbound.conf.5 b/contrib/unbound/doc/unbound.conf.5
index 16155de..24a1b4e 100644
--- a/contrib/unbound/doc/unbound.conf.5
+++ b/contrib/unbound/doc/unbound.conf.5
@@ -841,6 +841,11 @@ as a (DHCP-) DNS network resolver for a group of machines, where such
lookups should be filtered (RFC compliance), this also stops potential
data leakage about the local network to the upstream DNS servers.
.TP
+.B insecure\-lan\-zones: \fI<yesno>
+Default is disabled. If enabled, then reverse lookups in private
+address space are not validated. This is usually required whenever
+\fIunblock\-lan\-zones\fR is used.
+.TP
.B local\-zone: \fI<zone> <type>
Configure a local zone. The type determines the answer to give if
there is no match from local\-data. The types are deny, refuse, static,
diff --git a/contrib/unbound/doc/unbound.conf.5.in b/contrib/unbound/doc/unbound.conf.5.in
index 51f7c4e..cc4c1df 100644
--- a/contrib/unbound/doc/unbound.conf.5.in
+++ b/contrib/unbound/doc/unbound.conf.5.in
@@ -841,6 +841,11 @@ as a (DHCP-) DNS network resolver for a group of machines, where such
lookups should be filtered (RFC compliance), this also stops potential
data leakage about the local network to the upstream DNS servers.
.TP
+.B insecure\-lan\-zones: \fI<yesno>
+Default is disabled. If enabled, then reverse lookups in private
+address space are not validated. This is usually required whenever
+\fIunblock\-lan\-zones\fR is used.
+.TP
.B local\-zone: \fI<zone> <type>
Configure a local zone. The type determines the answer to give if
there is no match from local\-data. The types are deny, refuse, static,
diff --git a/contrib/unbound/services/localzone.c b/contrib/unbound/services/localzone.c
index c50ad0f..f3b30ae 100644
--- a/contrib/unbound/services/localzone.c
+++ b/contrib/unbound/services/localzone.c
@@ -51,6 +51,7 @@
#include "util/netevent.h"
#include "util/data/msgreply.h"
#include "util/data/msgparse.h"
+#include "util/as112.h"
struct local_zones*
local_zones_create(void)
@@ -592,6 +593,7 @@ static int
lz_enter_defaults(struct local_zones* zones, struct config_file* cfg)
{
struct local_zone* z;
+ const char** zstr;
/* this list of zones is from RFC 6303 */
@@ -654,110 +656,14 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg)
lock_rw_unlock(&z->lock);
}
- /* if unblock lan-zones, then do not add the zones below.
- * we do add the zones above, about 127.0.0.1, because localhost is
- * not on the lan. */
- if(cfg->unblock_lan_zones)
- return 1;
-
- /* block LAN level zones */
- if ( !add_as112_default(zones, cfg, "10.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "16.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "17.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "18.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "19.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "20.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "21.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "22.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "23.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "24.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "25.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "26.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "27.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "28.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "29.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "30.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "31.172.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "168.192.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "0.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "64.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "65.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "66.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "67.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "68.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "69.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "70.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "71.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "72.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "73.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "74.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "75.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "76.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "77.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "78.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "79.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "80.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "81.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "82.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "83.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "84.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "85.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "86.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "87.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "88.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "89.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "90.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "91.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "92.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "93.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "94.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "95.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "96.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "97.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "98.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "99.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "100.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "101.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "102.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "103.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "104.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "105.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "106.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "107.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "108.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "109.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "110.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "111.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "112.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "113.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "114.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "115.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "116.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "117.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "118.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "119.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "120.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "121.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "122.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "123.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "124.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "125.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "126.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "127.100.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "254.169.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "2.0.192.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "100.51.198.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "113.0.203.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "255.255.255.255.in-addr.arpa.") ||
- !add_as112_default(zones, cfg, "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.") ||
- !add_as112_default(zones, cfg, "d.f.ip6.arpa.") ||
- !add_as112_default(zones, cfg, "8.e.f.ip6.arpa.") ||
- !add_as112_default(zones, cfg, "9.e.f.ip6.arpa.") ||
- !add_as112_default(zones, cfg, "a.e.f.ip6.arpa.") ||
- !add_as112_default(zones, cfg, "b.e.f.ip6.arpa.") ||
- !add_as112_default(zones, cfg, "8.b.d.0.1.0.0.2.ip6.arpa.")) {
- log_err("out of memory adding default zone");
- return 0;
+ /* block AS112 zones, unless asked not to */
+ if(!cfg->unblock_lan_zones) {
+ for(zstr = as112_zones; *zstr; zstr++) {
+ if(!add_as112_default(zones, cfg, *zstr)) {
+ log_err("out of memory adding default zone");
+ return 0;
+ }
+ }
}
return 1;
}
diff --git a/contrib/unbound/util/as112.c b/contrib/unbound/util/as112.c
new file mode 100644
index 0000000..6ee6940
--- /dev/null
+++ b/contrib/unbound/util/as112.c
@@ -0,0 +1,143 @@
+/*
+ * util/as112.c - list of local zones.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * HOLDER OR CONTRIBUTORS 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.
+ */
+
+/**
+ * \file
+ *
+ * This file provides a list of lan zones.
+ */
+
+#include "util/as112.h"
+
+static const char* as112_zone_array[] = {
+ "10.in-addr.arpa.",
+ "16.172.in-addr.arpa.",
+ "17.172.in-addr.arpa.",
+ "18.172.in-addr.arpa.",
+ "19.172.in-addr.arpa.",
+ "20.172.in-addr.arpa.",
+ "21.172.in-addr.arpa.",
+ "22.172.in-addr.arpa.",
+ "23.172.in-addr.arpa.",
+ "24.172.in-addr.arpa.",
+ "25.172.in-addr.arpa.",
+ "26.172.in-addr.arpa.",
+ "27.172.in-addr.arpa.",
+ "28.172.in-addr.arpa.",
+ "29.172.in-addr.arpa.",
+ "30.172.in-addr.arpa.",
+ "31.172.in-addr.arpa.",
+ "168.192.in-addr.arpa.",
+ "0.in-addr.arpa.",
+ "64.100.in-addr.arpa.",
+ "65.100.in-addr.arpa.",
+ "66.100.in-addr.arpa.",
+ "67.100.in-addr.arpa.",
+ "68.100.in-addr.arpa.",
+ "69.100.in-addr.arpa.",
+ "70.100.in-addr.arpa.",
+ "71.100.in-addr.arpa.",
+ "72.100.in-addr.arpa.",
+ "73.100.in-addr.arpa.",
+ "74.100.in-addr.arpa.",
+ "75.100.in-addr.arpa.",
+ "76.100.in-addr.arpa.",
+ "77.100.in-addr.arpa.",
+ "78.100.in-addr.arpa.",
+ "79.100.in-addr.arpa.",
+ "80.100.in-addr.arpa.",
+ "81.100.in-addr.arpa.",
+ "82.100.in-addr.arpa.",
+ "83.100.in-addr.arpa.",
+ "84.100.in-addr.arpa.",
+ "85.100.in-addr.arpa.",
+ "86.100.in-addr.arpa.",
+ "87.100.in-addr.arpa.",
+ "88.100.in-addr.arpa.",
+ "89.100.in-addr.arpa.",
+ "90.100.in-addr.arpa.",
+ "91.100.in-addr.arpa.",
+ "92.100.in-addr.arpa.",
+ "93.100.in-addr.arpa.",
+ "94.100.in-addr.arpa.",
+ "95.100.in-addr.arpa.",
+ "96.100.in-addr.arpa.",
+ "97.100.in-addr.arpa.",
+ "98.100.in-addr.arpa.",
+ "99.100.in-addr.arpa.",
+ "100.100.in-addr.arpa.",
+ "101.100.in-addr.arpa.",
+ "102.100.in-addr.arpa.",
+ "103.100.in-addr.arpa.",
+ "104.100.in-addr.arpa.",
+ "105.100.in-addr.arpa.",
+ "106.100.in-addr.arpa.",
+ "107.100.in-addr.arpa.",
+ "108.100.in-addr.arpa.",
+ "109.100.in-addr.arpa.",
+ "110.100.in-addr.arpa.",
+ "111.100.in-addr.arpa.",
+ "112.100.in-addr.arpa.",
+ "113.100.in-addr.arpa.",
+ "114.100.in-addr.arpa.",
+ "115.100.in-addr.arpa.",
+ "116.100.in-addr.arpa.",
+ "117.100.in-addr.arpa.",
+ "118.100.in-addr.arpa.",
+ "119.100.in-addr.arpa.",
+ "120.100.in-addr.arpa.",
+ "121.100.in-addr.arpa.",
+ "122.100.in-addr.arpa.",
+ "123.100.in-addr.arpa.",
+ "124.100.in-addr.arpa.",
+ "125.100.in-addr.arpa.",
+ "126.100.in-addr.arpa.",
+ "127.100.in-addr.arpa.",
+ "254.169.in-addr.arpa.",
+ "2.0.192.in-addr.arpa.",
+ "100.51.198.in-addr.arpa.",
+ "113.0.203.in-addr.arpa.",
+ "255.255.255.255.in-addr.arpa.",
+ "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.",
+ "d.f.ip6.arpa.",
+ "8.e.f.ip6.arpa.",
+ "9.e.f.ip6.arpa.",
+ "a.e.f.ip6.arpa.",
+ "b.e.f.ip6.arpa.",
+ "8.b.d.0.1.0.0.2.ip6.arpa.",
+ 0
+};
+
+const char** as112_zones = as112_zone_array;
diff --git a/contrib/unbound/util/as112.h b/contrib/unbound/util/as112.h
new file mode 100644
index 0000000..7d0329e
--- /dev/null
+++ b/contrib/unbound/util/as112.h
@@ -0,0 +1,57 @@
+/*
+ * util/as112.c - list of local zones.
+ *
+ * Copyright (c) 2007, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * HOLDER OR CONTRIBUTORS 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.
+ */
+
+/**
+ * \file
+ *
+ * This file provides a list of lan zones
+ */
+
+#ifndef UTIL_AS112_H
+#define UTIL_AS112_H
+
+/**
+ * Array of text-format domain names of the AS112 zones.
+ * The array ends with NULL. "AS112" is a service on the internet that
+ * that this array is named after. The names in this list (or some of them)
+ * are null-routed by this service to avoid load on central servers caused by
+ * mistaken lookups for local content on the global internet.
+ *
+ * This is the list of names that unbound should not normally be sending
+ * on towards the internet, because they are local-use.
+ */
+extern const char** as112_zones;
+
+#endif
diff --git a/contrib/unbound/util/config_file.c b/contrib/unbound/util/config_file.c
index 6354e99..4d8f806 100644
--- a/contrib/unbound/util/config_file.c
+++ b/contrib/unbound/util/config_file.c
@@ -210,6 +210,7 @@ config_create(void)
cfg->local_zones_nodefault = NULL;
cfg->local_data = NULL;
cfg->unblock_lan_zones = 0;
+ cfg->insecure_lan_zones = 0;
cfg->python_script = NULL;
cfg->remote_control_enable = 0;
cfg->control_ifs = NULL;
@@ -458,6 +459,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("rrset-roundrobin:", rrset_roundrobin)
else S_STRLIST("local-data:", local_data)
else S_YNO("unblock-lan-zones:", unblock_lan_zones)
+ else S_YNO("insecure-lan-zones:", insecure_lan_zones)
else S_YNO("control-enable:", remote_control_enable)
else S_STRLIST("control-interface:", control_ifs)
else S_NUMBER_NONZERO("control-port:", control_port)
@@ -739,6 +741,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "minimal-responses", minimal_responses)
else O_YNO(opt, "rrset-roundrobin", rrset_roundrobin)
else O_YNO(opt, "unblock-lan-zones", unblock_lan_zones)
+ else O_YNO(opt, "insecure-lan-zones", insecure_lan_zones)
else O_DEC(opt, "max-udp-size", max_udp_size)
else O_STR(opt, "python-script", python_script)
else O_DEC(opt, "ratelimit", ratelimit)
diff --git a/contrib/unbound/util/config_file.h b/contrib/unbound/util/config_file.h
index 8fa163e..c758d64 100644
--- a/contrib/unbound/util/config_file.h
+++ b/contrib/unbound/util/config_file.h
@@ -285,8 +285,10 @@ struct config_file {
struct config_strlist* local_zones_nodefault;
/** local data RRs configured */
struct config_strlist* local_data;
- /** unblock lan zones (reverse lookups for 10/8 and so on) */
+ /** unblock lan zones (reverse lookups for AS112 zones) */
int unblock_lan_zones;
+ /** insecure lan zones (don't validate AS112 zones) */
+ int insecure_lan_zones;
/** remote control section. enable toggle. */
int remote_control_enable;
diff --git a/contrib/unbound/util/configlexer.lex b/contrib/unbound/util/configlexer.lex
index a368066..5b25ef5 100644
--- a/contrib/unbound/util/configlexer.lex
+++ b/contrib/unbound/util/configlexer.lex
@@ -321,6 +321,7 @@ local-zone{COLON} { YDVAR(2, VAR_LOCAL_ZONE) }
local-data{COLON} { YDVAR(1, VAR_LOCAL_DATA) }
local-data-ptr{COLON} { YDVAR(1, VAR_LOCAL_DATA_PTR) }
unblock-lan-zones{COLON} { YDVAR(1, VAR_UNBLOCK_LAN_ZONES) }
+insecure-lan-zones{COLON} { YDVAR(1, VAR_INSECURE_LAN_ZONES) }
statistics-interval{COLON} { YDVAR(1, VAR_STATISTICS_INTERVAL) }
statistics-cumulative{COLON} { YDVAR(1, VAR_STATISTICS_CUMULATIVE) }
extended-statistics{COLON} { YDVAR(1, VAR_EXTENDED_STATISTICS) }
diff --git a/contrib/unbound/util/configparser.y b/contrib/unbound/util/configparser.y
index abc0bb0..a276fae 100644
--- a/contrib/unbound/util/configparser.y
+++ b/contrib/unbound/util/configparser.y
@@ -106,7 +106,8 @@ extern struct config_parser_state* cfg_parser;
%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM
%token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST
%token VAR_STUB_FIRST VAR_MINIMAL_RESPONSES VAR_RRSET_ROUNDROBIN
-%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE VAR_UNBLOCK_LAN_ZONES
+%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE
+%token VAR_UNBLOCK_LAN_ZONES VAR_INSECURE_LAN_ZONES
%token VAR_INFRA_CACHE_MIN_RTT
%token VAR_DNS64_PREFIX VAR_DNS64_SYNTHALL
%token VAR_DNSTAP VAR_DNSTAP_ENABLE VAR_DNSTAP_SOCKET_PATH
@@ -180,7 +181,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_log_queries | server_tcp_upstream | server_ssl_upstream |
server_ssl_service_key | server_ssl_service_pem | server_ssl_port |
server_minimal_responses | server_rrset_roundrobin | server_max_udp_size |
- server_so_reuseport | server_delay_close | server_unblock_lan_zones |
+ server_so_reuseport | server_delay_close |
+ server_unblock_lan_zones | server_insecure_lan_zones |
server_dns64_prefix | server_dns64_synthall |
server_infra_cache_min_rtt | server_harden_algo_downgrade |
server_ip_transparent | server_ratelimit | server_ratelimit_slabs |
@@ -722,6 +724,16 @@ server_unblock_lan_zones: VAR_UNBLOCK_LAN_ZONES STRING_ARG
free($2);
}
;
+server_insecure_lan_zones: VAR_INSECURE_LAN_ZONES STRING_ARG
+ {
+ OUTYY(("P(server_insecure_lan_zones:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->insecure_lan_zones =
+ (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
server_rrset_cache_size: VAR_RRSET_CACHE_SIZE STRING_ARG
{
OUTYY(("P(server_rrset_cache_size:%s)\n", $2));
diff --git a/contrib/unbound/validator/val_anchor.c b/contrib/unbound/validator/val_anchor.c
index 845b54a..bc9f8b8 100644
--- a/contrib/unbound/validator/val_anchor.c
+++ b/contrib/unbound/validator/val_anchor.c
@@ -48,6 +48,7 @@
#include "util/log.h"
#include "util/net_help.h"
#include "util/config_file.h"
+#include "util/as112.h"
#include "sldns/sbuffer.h"
#include "sldns/rrdef.h"
#include "sldns/str2wire.h"
@@ -1044,8 +1045,18 @@ int
anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg)
{
struct config_strlist* f;
+ const char** zstr;
char* nm;
sldns_buffer* parsebuf = sldns_buffer_new(65535);
+ if(cfg->insecure_lan_zones) {
+ for(zstr = as112_zones; *zstr; zstr++) {
+ if(!anchor_insert_insecure(anchors, *zstr)) {
+ log_err("error in insecure-lan-zones: %s", *zstr);
+ sldns_buffer_free(parsebuf);
+ return 0;
+ }
+ }
+ }
for(f = cfg->domain_insecure; f; f = f->next) {
if(!f->str || f->str[0] == 0) /* empty "" */
continue;
diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf
index 69b6d0f..b9c6b5c 100644
--- a/etc/defaults/rc.conf
+++ b/etc/defaults/rc.conf
@@ -694,6 +694,7 @@ iovctl_files="" # Config files for iovctl(8)
jail_enable="NO" # Set to NO to disable starting of any jails
jail_parallel_start="NO" # Start jails in the background
jail_list="" # Space separated list of names of jails
+jail_reverse_stop="NO" # Stop jails in reverse order
##############################################################
### Define source_rc_confs, the mechanism used by /etc/rc.* ##
diff --git a/etc/rc.d/jail b/etc/rc.d/jail
index b33f1b9..f7d6d3d 100755
--- a/etc/rc.d/jail
+++ b/etc/rc.d/jail
@@ -33,7 +33,8 @@ need_dad_wait=
# set it to $param. If not defined, $defval is used.
# When $num is [0-9]*, ${jail_$jv_$name$num} are looked up and
# $param is set by using +=. $num=0 is optional (params may start at 1).
-# When $num is YN or NY, the value is interpret as boolean.
+# When $num is YN or NY, the value is interpreted as boolean.
+# When $num is @, the value is interpreted as an array separted by IFS.
extract_var()
{
local i _jv _name _param _num _def _name1 _name2
@@ -78,6 +79,20 @@ extract_var()
i=$(($i + 1))
done
;;
+ @)
+ _name1=jail_${_jv}_${_name}
+ _name2=jail_${_name}
+ eval _tmpargs=\"\${$_name1:-\${$_name2:-$_def}}\"
+ set -- $_tmpargs
+ if [ $# -gt 0 ]; then
+ echo -n " $_param = "
+ while [ $# -gt 1 ]; do
+ echo -n "\"$1\", "
+ shift
+ done
+ echo "\"$1\";"
+ fi
+ ;;
*)
_name1=jail_${_jv}_${_name}
_name2=jail_${_name}
@@ -190,7 +205,7 @@ parse_options()
allow.raw_sockets NY YES
else
echo " vnet;"
- extract_var $_jv vnet_interface vnet.interface - ""
+ extract_var $_jv vnet_interface vnet.interface @ ""
fi
echo " exec.clean;"
@@ -521,7 +536,11 @@ jail_stop()
command=$jail_program
rc_flags=$jail_flags
command_args="-f $jail_conf -r"
- $jail_jls name | while read _j; do
+ if checkyesno jail_reverse_stop; then
+ $jail_jls name | tail -r
+ else
+ $jail_jls name
+ fi | while read _j; do
echo -n " $_j"
_tmp=`mktemp -t jail` || exit 3
$command $rc_flags $command_args $_j >> $_tmp 2>&1
@@ -536,6 +555,7 @@ jail_stop()
return
;;
esac
+ checkyesno jail_reverse_stop && set -- $(reverse_list $@)
for _j in $@; do
_j=$(echo $_j | tr /. _)
_jv=$(echo -n $_j | tr -c '[:alnum:]' _)
@@ -571,5 +591,6 @@ jail_warn()
load_rc_config $name
case $# in
1) run_rc_command $@ ${jail_list:-_ALL} ;;
-*) run_rc_command $@ ;;
+*) jail_reverse_stop="no"
+ run_rc_command $@ ;;
esac
diff --git a/etc/rc.d/ntpd b/etc/rc.d/ntpd
index 7f28358..fe2fc4b 100755
--- a/etc/rc.d/ntpd
+++ b/etc/rc.d/ntpd
@@ -28,14 +28,14 @@ ntpd_precmd()
rc_flags="-g $rc_flags"
fi
- if [ -z "$ntpd_chrootdir" ]; then
- return 0;
- fi
-
if [ ! -f $ntp_db_leapfile ]; then
ntpd_fetch_leapfile
fi
+ if [ -z "$ntpd_chrootdir" ]; then
+ return 0;
+ fi
+
# If running in a chroot cage, ensure that the appropriate files
# exist inside the cage, as well as helper symlinks into the cage
# from outside.
diff --git a/include/signal.h b/include/signal.h
index 895ccc3..217fadd 100644
--- a/include/signal.h
+++ b/include/signal.h
@@ -36,6 +36,10 @@
#include <sys/cdefs.h>
#include <sys/_types.h>
#include <sys/signal.h>
+#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE
+#include <machine/ucontext.h>
+#include <sys/_ucontext.h>
+#endif
#if __BSD_VISIBLE
/*
@@ -114,7 +118,6 @@ void psignal(unsigned int, const char *);
#if __BSD_VISIBLE
int sigblock(int);
-struct __ucontext; /* XXX spec requires a complete declaration. */
int sigreturn(const struct __ucontext *);
int sigsetmask(int);
int sigstack(const struct sigstack *, struct sigstack *);
diff --git a/lib/Makefile b/lib/Makefile
index 4b2a59c..3b1a952 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -80,6 +80,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
libopie \
libpam \
libpcap \
+ ${_libpe} \
libpjdlog \
${_libpmc} \
${_libproc} \
@@ -185,6 +186,7 @@ _cuse= libcuse
.if ${MK_TOOLCHAIN} != "no"
_libelftc= libelftc
+_libpe= libpe
.endif
.if ${MK_FILE} != "no"
diff --git a/lib/libc/stdio/fgetln.3 b/lib/libc/stdio/fgetln.3
index 4b83664..7d4b89a5 100644
--- a/lib/libc/stdio/fgetln.3
+++ b/lib/libc/stdio/fgetln.3
@@ -28,7 +28,7 @@
.\" @(#)fgetln.3 8.3 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
-.Dd April 19, 1994
+.Dd February 15, 2016
.Dt FGETLN 3
.Os
.Sh NAME
@@ -97,6 +97,9 @@ These changes are lost as soon as the pointer becomes invalid.
The argument
.Fa stream
is not a stream open for reading.
+.It Bq Er ENOMEM
+The internal line buffer could not be expanded due to lack of available memory,
+or because it would need to expand beyond INT_MAX in size.
.El
.Pp
The
diff --git a/lib/libc/stdio/fgetln.c b/lib/libc/stdio/fgetln.c
index 1779de2..1509bc8 100644
--- a/lib/libc/stdio/fgetln.c
+++ b/lib/libc/stdio/fgetln.c
@@ -37,6 +37,8 @@ static char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94";
__FBSDID("$FreeBSD$");
#include "namespace.h"
+#include <errno.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -61,6 +63,10 @@ __slbexpand(FILE *fp, size_t newsize)
#endif
if (fp->_lb._size >= newsize)
return (0);
+ if (newsize > INT_MAX) {
+ errno = ENOMEM;
+ return (-1);
+ }
if ((p = realloc(fp->_lb._base, newsize)) == NULL)
return (-1);
fp->_lb._base = p;
@@ -152,13 +158,14 @@ fgetln(FILE *fp, size_t *lenp)
}
*lenp = len;
#ifdef notdef
- fp->_lb._base[len] = 0;
+ fp->_lb._base[len] = '\0';
#endif
FUNLOCKFILE(fp);
return ((char *)fp->_lb._base);
error:
*lenp = 0; /* ??? */
+ fp->_flags |= __SERR;
FUNLOCKFILE(fp);
return (NULL); /* ??? */
}
diff --git a/lib/libc/stdio/fputs.c b/lib/libc/stdio/fputs.c
index 32e5764..1f9795a 100644
--- a/lib/libc/stdio/fputs.c
+++ b/lib/libc/stdio/fputs.c
@@ -37,6 +37,7 @@ static char sccsid[] = "@(#)fputs.c 8.1 (Berkeley) 6/4/93";
__FBSDID("$FreeBSD$");
#include "namespace.h"
+#include <limits.h>
#include <stdio.h>
#include <string.h>
#include "un-namespace.h"
@@ -62,5 +63,7 @@ fputs(const char * __restrict s, FILE * __restrict fp)
ORIENT(fp, -1);
retval = __sfvwrite(fp, &uio);
FUNLOCKFILE(fp);
+ if (retval == 0)
+ return (iov.iov_len > INT_MAX ? INT_MAX : iov.iov_len);
return (retval);
}
diff --git a/lib/libc/sys/jail.2 b/lib/libc/sys/jail.2
index a2d692a..8b6add9 100644
--- a/lib/libc/sys/jail.2
+++ b/lib/libc/sys/jail.2
@@ -405,7 +405,6 @@ system calls appeared in
The jail feature was written by
.An Poul-Henning Kamp
for R&D Associates
-.Dq Li http://www.rndassociates.com/
who contributed it to
.Fx .
.An James Gritton
diff --git a/lib/libelftc/elftc_version.c b/lib/libelftc/elftc_version.c
index 0a1dd12..d5e1d28 100644
--- a/lib/libelftc/elftc_version.c
+++ b/lib/libelftc/elftc_version.c
@@ -6,5 +6,5 @@
const char *
elftc_version(void)
{
- return "elftoolchain r3272M";
+ return "elftoolchain r3400M";
}
diff --git a/lib/libfetch/http.c b/lib/libfetch/http.c
index 206648d..ca522a6 100644
--- a/lib/libfetch/http.c
+++ b/lib/libfetch/http.c
@@ -1435,7 +1435,6 @@ http_connect(struct url *URL, struct url *purl, const char *flags)
}
if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0 &&
fetch_ssl(conn, URL, verbose) == -1) {
- fetch_close(conn);
/* grrr */
errno = EAUTH;
fetch_syserr();
diff --git a/lib/libpe/Makefile b/lib/libpe/Makefile
new file mode 100644
index 0000000..877b331
--- /dev/null
+++ b/lib/libpe/Makefile
@@ -0,0 +1,34 @@
+# $FreeBSD$
+.include <bsd.own.mk>
+
+INTERNALLIB=
+
+ELFTCDIR= ${.CURDIR}/../../contrib/elftoolchain
+
+.PATH: ${ELFTCDIR}/libpe
+
+LIB= pe
+
+SRCS= libpe_buffer.c \
+ libpe_coff.c \
+ libpe_dos.c \
+ libpe_init.c \
+ libpe_rich.c \
+ libpe_section.c \
+ libpe_utils.c \
+ pe_buffer.c \
+ pe_cntl.c \
+ pe_coff.c \
+ pe_dos.c \
+ pe_flag.c \
+ pe_init.c \
+ pe_rich.c \
+ pe_section.c \
+ pe_symtab.c \
+ pe_update.c
+
+CFLAGS+=-I${ELFTCDIR}/libpe -I${ELFTCDIR}/common
+
+MAN=
+
+.include <bsd.lib.mk>
diff --git a/lib/libunbound/Makefile b/lib/libunbound/Makefile
index 9a7838d..f168244 100644
--- a/lib/libunbound/Makefile
+++ b/lib/libunbound/Makefile
@@ -14,7 +14,7 @@ PACKAGE= unbound
CFLAGS= -I${UNBOUNDDIR} -I${LDNSDIR} -I${.OBJDIR}
-SRCS= alloc.c autotrust.c config_file.c configlexer.l configparser.y \
+SRCS= alloc.c as112.c autotrust.c config_file.c configlexer.l configparser.y \
context.c dname.c dns.c dns64.c dnstree.c fptr_wlist.c infra.c \
iter_delegpt.c iter_donotq.c iter_fwd.c iter_hints.c iter_priv.c \
iter_resptype.c iter_scrub.c iter_utils.c iterator.c keyraw.c \
diff --git a/share/examples/jails/README b/share/examples/jails/README
index ccff12c..36268a9 100644
--- a/share/examples/jails/README
+++ b/share/examples/jails/README
@@ -1,5 +1,13 @@
# $FreeBSD$
+The below 4 samples require a VIMAGE enabled kernel:
+
+ # (as root)
+ $ cp VIMAGE /usr/src/sys/amd64/conf/
+ $ cd /usr/src
+ $ make KERNCONF=VIMAGE kernel
+ $ reboot
+
Sample 1: jail.conf(5)
$ cp jib jng /usr/sbin/
diff --git a/share/examples/jails/VIMAGE b/share/examples/jails/VIMAGE
new file mode 100644
index 0000000..82edaa2
--- /dev/null
+++ b/share/examples/jails/VIMAGE
@@ -0,0 +1,59 @@
+# $FreeBSD$
+
+################################################################################
+######################### VIMAGE KERNEL CONFIGURATION ##########################
+################################################################################
+
+#################### Inheritance
+
+#
+# Inherit from, and override `GENERIC'
+#
+include GENERIC # Base configuration file
+ident VIMAGE # Kernel name
+
+################################################################################
+##################### ENABLE NON-INHERITED OPTIONS/DEVICES #####################
+################################################################################
+
+#################### Non-GENERIC options
+
+#
+# Network Virtualization for Jails
+#
+options VIMAGE # vnet paravirtualization
+
+#
+# Netgraph based bridging for vnet jails
+# NB: Not strictly necessary; will load automatically via KLD when needed
+#
+options NETGRAPH # netgraph(4) system
+options NETGRAPH_BRIDGE # ng_bridge(4)
+options NETGRAPH_EIFACE # ng_eiface(4)
+options NETGRAPH_ETHER # ng_ether(4)
+options NETGRAPH_SOCKET # ng_socket(4)
+
+#################### Non-GENERIC devices
+
+#
+# if_bridge based bridging for vnet jails
+# NB: Not strictly necessary; will load automatically via KLD when needed
+#
+device epair # epair(4)
+device if_bridge # if_bridge(4)
+
+################################################################################
+################ DISABLE UNNECESSARY INHERITED OPTIONS/DEVICES ################
+################################################################################
+
+#################### Disable select inherited options
+
+# none
+
+#################### Disable select inherited devices
+
+# none
+
+################################################################################
+# END
+################################################################################
diff --git a/share/examples/jails/jib b/share/examples/jails/jib
index a93d2f2..b7d50f5 100755
--- a/share/examples/jails/jib
+++ b/share/examples/jails/jib
@@ -164,12 +164,93 @@ usage()
action_usage()
{
- local usage action="$1"
+ local usage descr action="$1"
eval usage=\"\$jib_${action}_usage\"
echo "Usage: $pgm $usage" >&2
+ eval descr=\"\$jib_${action}_descr\"
+ printf "\t%s\n" "$descr"
exit $FAILURE
}
+derive_mac()
+{
+ local OPTIND=1 OPTARG __flag
+ local __mac_num= __make_pair=
+ while getopts 2n: __flag; do
+ case "$__flag" in
+ 2) __make_pair=1 ;;
+ n) __mac_num=${OPTARG%%[^0-9]*} ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+
+ if [ ! "$__mac_num" ]; then
+ eval __mac_num=\${_${iface}_num:--1}
+ __mac_num=$(( $__mac_num + 1 ))
+ eval _${iface}_num=\$__mac_num
+ fi
+
+ local __iface="$1" __name="$2" __var_to_set="$3" __var_to_set_b="$4"
+ local __iface_devid __new_devid __num __new_devid_b
+ #
+ # Calculate MAC address derived from given iface.
+ #
+ # The formula I'm using is ``NP:SS:SS:II:II:II'' where:
+ # + N denotes 4 bits used as a counter to support branching
+ # each parent interface up to 15 times under the same jail
+ # name (see S below).
+ # + P denotes the special nibble whose value, if one of
+ # 2, 6, A, or E (but usually 2) denotes a privately
+ # administered MAC address (while remaining routable).
+ # + S denotes 16 bits, the sum(1) value of the jail name.
+ # + I denotes bits that are inherited from parent interface.
+ #
+ # The S bits are a CRC-16 checksum of NAME, allowing the jail
+ # to change link numbers in ng_bridge(4) without affecting the
+ # MAC address. Meanwhile, if...
+ # + the jail NAME changes (e.g., it was duplicated and given
+ # a new name with no other changes)
+ # + the underlying network interface changes
+ # + the jail is moved to another host
+ # the MAC address will be recalculated to a new, similarly
+ # unique value preventing conflict.
+ #
+ __iface_devid=$( ifconfig $__iface ether | awk '/ether/,$0=$2' )
+ # ??:??:??:II:II:II
+ __new_devid=${__iface_devid#??:??:??} # => :II:II:II
+ # => :SS:SS:II:II:II
+ __num=$( set -- `echo -n "$__name" | sum` && echo $1 )
+ __new_devid=$( printf :%02x:%02x \
+ $(( $__num >> 8 & 255 )) $(( $__num & 255 )) )$__new_devid
+ # => P:SS:SS:II:II:II
+ case "$__iface_devid" in
+ ?2:*) __new_devid=a$__new_devid __new_devid_b=e$__new_devid ;;
+ ?[Ee]:*) __new_devid=2$__new_devid __new_devid_b=6$__new_devid ;;
+ *) __new_devid=2$__new_devid __new_devid_b=e$__new_devid
+ esac
+ # => NP:SS:SS:II:II:II
+ __new_devid=$( printf %x $(( $__mac_num & 15 )) )$__new_devid
+ __new_devid_b=$( printf %x $(( $__mac_num & 15 )) )$__new_devid_b
+
+ #
+ # Return derivative MAC address(es)
+ #
+ if [ "$__make_pair" ]; then
+ if [ "$__var_to_set" -a "$__var_to_set_b" ]; then
+ eval $__var_to_set=\$__new_devid
+ eval $__var_to_set_b=\$__new_devid_b
+ else
+ echo $__new_devid $__new_devid_b
+ fi
+ else
+ if [ "$__var_to_set" ]; then
+ eval $__var_to_set=\$__new_devid
+ else
+ echo $__new_devid
+ fi
+ fi
+}
+
mustberoot_to_continue()
{
if [ "$( id -u )" -ne 0 ]; then
@@ -178,7 +259,7 @@ mustberoot_to_continue()
fi
}
-jib_addm_usage="addm [-b BRIDGE_NAME] NAME interface0 [interface1 ...]"
+jib_addm_usage="addm [-b BRIDGE_NAME] NAME [!]iface0 [[!]iface1 ...]"
jib_addm_descr="Creates e0b_NAME [e1b_NAME ...]"
jib_addm()
{
@@ -198,18 +279,25 @@ jib_addm()
mustberoot_to_continue
- local iface iface_devid eiface_devid
- local eiface_devid_a eiface_devid_b
- local new num quad i=0
+ local iface eiface_devid_a eiface_devid_b
+ local new no_derive num quad i=0
for iface in $*; do
- # 1. Make sure the interface doesn't exist already
- ifconfig "e${i}a_$name" > /dev/null 2>&1 && continue
+ no_derive=
+ case "$iface" in
+ !*) iface=${iface#!} no_derive=1 ;;
+ esac
+
+ # Make sure the interface doesn't exist already
+ if ifconfig "e${i}a_$name" > /dev/null 2>&1; then
+ i=$(( $i + 1 ))
+ continue
+ fi
- # 2. Bring the interface up
+ # Bring the interface up
ifconfig $iface up || return
- # 3. Make sure the interface has been bridged
+ # Make sure the interface has been bridged
if ! ifconfig "$iface$bridge" > /dev/null 2>&1; then
new=$( ifconfig bridge create ) || return
ifconfig $new addm $iface || return
@@ -217,97 +305,29 @@ jib_addm()
ifconfig "$iface$bridge" up || return
fi
- # 4. Create a new interface to the bridge
+ # Create a new interface to the bridge
new=$( ifconfig epair create ) || return
ifconfig "$iface$bridge" addm $new || return
- # 5. Rename the new interface
+ # Rename the new interface
ifconfig $new name "e${i}a_$name" || return
ifconfig ${new%a}b name "e${i}b_$name" || return
ifconfig "e${i}a_$name" up || return
ifconfig "e${i}b_$name" up || return
#
- # 6. Set the MAC address of the new interface using a sensible
+ # Set the MAC address of the new interface using a sensible
# algorithm to prevent conflicts on the network.
#
- # The formula I'm using is ``NP:SS:SS:II:II:II'' where:
- # + N denotes 4 bits used as a counter to support branching
- # each parent interface up to 15 times under the same jail
- # name (see S below).
- # + P denotes the special nibble whose value, if one of
- # 2, 6, A, or E (but usually 2) denotes a privately
- # administered MAC address (while remaining routable).
- # + S denotes 16 bits, the sum(1) value of the jail name.
- # + I denotes bits that are inherited from parent interface.
- #
- # The S bits are a CRC-16 checksum of NAME, allowing the jail
- # to change the epair(4) generation order without affecting the
- # MAC address. Meanwhile, if...
- # + the jail NAME changes (e.g., it was duplicated and given
- # a new name with no other changes)
- # + the underlying network interface changes
- # + the jail is moved to another host
- # the MAC address will be recalculated to a new, similarly
- # unique value preventing conflict.
- #
- iface_devid=$( ifconfig $iface ether | awk '/ether/,$0=$2' )
- eiface_devid=${iface_devid#??:??:??}
- num=$( set -- `echo -n $name | sum` && echo $1 )
- quad=$(( $num & 15 ))
- case "$quad" in
- 10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
- 13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
- esac
- eiface_devid=$quad$eiface_devid
- num=$(( $num >> 4 ))
- quad=$(( $num & 15 ))
- case "$quad" in
- 10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
- 13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
- esac
- eiface_devid=$quad$eiface_devid
- num=$(( $num >> 4 ))
- quad=$(( $num & 15 ))
- case "$quad" in
- 10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
- 13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
- esac
- eiface_devid=$quad:$eiface_devid
- num=$(( $num >> 4 ))
- quad=$(( $num & 15 ))
- case "$quad" in
- 10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
- 13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
- esac
- case "$iface_devid" in
- ?[Ee]:*)
- eiface_devid_a=2:$quad$eiface_devid
- eiface_devid_b=6:$quad$eiface_devid
- ;;
- *)
- eiface_devid_a=2:$quad$eiface_devid
- eiface_devid_b=e:$quad$eiface_devid
- esac
- eval num=\$_${iface}_num
- if [ "$num" ]; then
- num=$(( $num + 1 ))
- eval _${iface}_num=$num
- else
- num=0
- local _${iface}_num=$num
- fi
- quad=$(( $num & 15 ))
- case "$quad" in
- 10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
- 13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
- esac
- eiface_devid_a=$quad$eiface_devid_a
- eiface_devid_b=$quad$eiface_devid_b
- ifconfig "e${i}a_$name" ether $eiface_devid_a > /dev/null 2>&1
- ifconfig "e${i}b_$name" ether $eiface_devid_b > /dev/null 2>&1
+ eiface_devid_a= eiface_devid_b=
+ [ "$no_derive" ] || derive_mac -2 $iface "$name" \
+ eiface_devid_a eiface_devid_b
+ if [ "$eiface_devid_a" -a "$eiface_devid_b" ]; then
+ ifconfig "e${i}a_$name" ether $eiface_devid_a
+ ifconfig "e${i}b_$name" ether $eiface_devid_b
+ fi > /dev/null 2>&1
- i=$(( $i + 1 )) # on to next e{i}b_name
+ i=$(( $i + 1 ))
done # for iface
}
diff --git a/share/examples/jails/jng b/share/examples/jails/jng
index 445803d..c243001 100755
--- a/share/examples/jails/jng
+++ b/share/examples/jails/jng
@@ -154,6 +154,7 @@ usage()
show \
show1 \
shutdown \
+ stats \
; do
eval usage=\"\$jng_${action}_usage\"
[ "$usage" ] || continue
@@ -165,12 +166,93 @@ usage()
action_usage()
{
- local usage action="$1"
+ local usage descr action="$1"
eval usage=\"\$jng_${action}_usage\"
echo "Usage: $pgm $usage" >&2
+ eval descr=\"\$jng_${action}_descr\"
+ printf "\t%s\n" "$descr"
exit $FAILURE
}
+derive_mac()
+{
+ local OPTIND=1 OPTARG __flag
+ local __mac_num= __make_pair=
+ while getopts 2n: __flag; do
+ case "$__flag" in
+ 2) __make_pair=1 ;;
+ n) __mac_num=${OPTARG%%[^0-9]*} ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+
+ if [ ! "$__mac_num" ]; then
+ eval __mac_num=\${_${iface}_num:--1}
+ __mac_num=$(( $__mac_num + 1 ))
+ eval _${iface}_num=\$__mac_num
+ fi
+
+ local __iface="$1" __name="$2" __var_to_set="$3" __var_to_set_b="$4"
+ local __iface_devid __new_devid __num __new_devid_b
+ #
+ # Calculate MAC address derived from given iface.
+ #
+ # The formula I'm using is ``NP:SS:SS:II:II:II'' where:
+ # + N denotes 4 bits used as a counter to support branching
+ # each parent interface up to 15 times under the same jail
+ # name (see S below).
+ # + P denotes the special nibble whose value, if one of
+ # 2, 6, A, or E (but usually 2) denotes a privately
+ # administered MAC address (while remaining routable).
+ # + S denotes 16 bits, the sum(1) value of the jail name.
+ # + I denotes bits that are inherited from parent interface.
+ #
+ # The S bits are a CRC-16 checksum of NAME, allowing the jail
+ # to change link numbers in ng_bridge(4) without affecting the
+ # MAC address. Meanwhile, if...
+ # + the jail NAME changes (e.g., it was duplicated and given
+ # a new name with no other changes)
+ # + the underlying network interface changes
+ # + the jail is moved to another host
+ # the MAC address will be recalculated to a new, similarly
+ # unique value preventing conflict.
+ #
+ __iface_devid=$( ifconfig $__iface ether | awk '/ether/,$0=$2' )
+ # ??:??:??:II:II:II
+ __new_devid=${__iface_devid#??:??:??} # => :II:II:II
+ # => :SS:SS:II:II:II
+ __num=$( set -- `echo -n "$__name" | sum` && echo $1 )
+ __new_devid=$( printf :%02x:%02x \
+ $(( $__num >> 8 & 255 )) $(( $__num & 255 )) )$__new_devid
+ # => P:SS:SS:II:II:II
+ case "$__iface_devid" in
+ ?2:*) __new_devid=a$__new_devid __new_devid_b=e$__new_devid ;;
+ ?[Ee]:*) __new_devid=2$__new_devid __new_devid_b=6$__new_devid ;;
+ *) __new_devid=2$__new_devid __new_devid_b=e$__new_devid
+ esac
+ # => NP:SS:SS:II:II:II
+ __new_devid=$( printf %x $(( $__mac_num & 15 )) )$__new_devid
+ __new_devid_b=$( printf %x $(( $__mac_num & 15 )) )$__new_devid_b
+
+ #
+ # Return derivative MAC address(es)
+ #
+ if [ "$__make_pair" ]; then
+ if [ "$__var_to_set" -a "$__var_to_set_b" ]; then
+ eval $__var_to_set=\$__new_devid
+ eval $__var_to_set_b=\$__new_devid_b
+ else
+ echo $__new_devid $__new_devid_b
+ fi
+ else
+ if [ "$__var_to_set" ]; then
+ eval $__var_to_set=\$__new_devid
+ else
+ echo $__new_devid
+ fi
+ fi
+}
+
mustberoot_to_continue()
{
if [ "$( id -u )" -ne 0 ]; then
@@ -179,7 +261,7 @@ mustberoot_to_continue()
fi
}
-jng_bridge_usage="bridge [-b BRIDGE_NAME] NAME interface0 [interface1 ...]"
+jng_bridge_usage="bridge [-b BRIDGE_NAME] NAME [!|=]iface0 [[!|=]iface1 ...]"
jng_bridge_descr="Create ng0_NAME [ng1_NAME ...]"
jng_bridge()
{
@@ -200,22 +282,32 @@ jng_bridge()
mustberoot_to_continue
- local iface iface_devid eiface eiface_devid
- local new num quad i=0
+ local iface parent eiface eiface_devid
+ local new clone_mac no_derive num quad i=0
for iface in $*; do
- # 0. Make sure the interface doesn't exist already
+ clone_mac=
+ no_derive=
+ case "$iface" in
+ =*) iface=${iface#=} clone_mac=1 ;;
+ !*) iface=${iface#!} no_derive=1 ;;
+ esac
+
+ # Make sure the interface doesn't exist already
eiface=ng${i}_$name
- ngctl msg "$eiface:" getifname > /dev/null 2>&1 && continue
+ if ngctl msg "$eiface:" getifname > /dev/null 2>&1; then
+ i=$(( $i + 1 ))
+ continue
+ fi
- # 1. Bring the interface up
+ # Bring the interface up
ifconfig $iface up || return
- # 2. Set promiscuous mode and don't overwrite src addr
+ # Set promiscuous mode and don't overwrite src addr
ngctl msg $iface: setpromisc 1 || return
ngctl msg $iface: setautosrc 0 || return
- # 3. Make sure the interface has been bridged
+ # Make sure the interface has been bridged
if ! ngctl info ${iface}bridge: > /dev/null 2>&1; then
ngctl mkpeer $iface: bridge lower link0 || return
ngctl connect $iface: $iface:lower upper link1 ||
@@ -223,7 +315,7 @@ jng_bridge()
ngctl name $iface:lower ${iface}bridge || return
fi
- # 3.5. Optionally create a secondary bridge
+ # Optionally create a secondary bridge
if [ "$bridge" != "bridge" ] &&
! ngctl info "$iface$bridge:" > /dev/null 2>&1
then
@@ -239,7 +331,7 @@ jng_bridge()
return
fi
- # 4. Create a new interface to the bridge
+ # Create a new interface to the bridge
num=2
while ngctl msg "$iface$bridge:" getstats $num > /dev/null 2>&1
do
@@ -247,7 +339,7 @@ jng_bridge()
done
ngctl mkpeer "$iface$bridge:" eiface link$num ether || return
- # 5. Rename the new interface
+ # Rename the new interface
while [ ${#eiface} -gt 15 ]; do # OS limitation
eiface=${eiface%?}
done
@@ -258,79 +350,20 @@ jng_bridge()
ifconfig $eiface up || return
#
- # 6. Set the MAC address of the new interface using a sensible
+ # Set the MAC address of the new interface using a sensible
# algorithm to prevent conflicts on the network.
#
- # The formula I'm using is ``NP:SS:SS:II:II:II'' where:
- # + N denotes 4 bits used as a counter to support branching
- # each parent interface up to 15 times under the same jail
- # name (see S below).
- # + P denotes the special nibble whose value, if one of
- # 2, 6, A, or E (but usually 2) denotes a privately
- # administered MAC address (while remaining routable).
- # + S denotes 16 bits, the sum(1) value of the jail name.
- # + I denotes bits that are inherited from parent interface.
- #
- # The S bits are a CRC-16 checksum of NAME, allowing the jail
- # to change link numbers in ng_bridge(4) without affecting the
- # MAC address. Meanwhile, if...
- # + the jail NAME changes (e.g., it was duplicated and given
- # a new name with no other changes)
- # + the underlying network interface changes
- # + the jail is moved to another host
- # the MAC address will be recalculated to a new, similarly
- # unique value preventing conflict.
- #
- iface_devid=$( ifconfig $iface ether | awk '/ether/,$0=$2' )
- eiface_devid=${iface_devid#??:??:??}
- num=$( set -- `echo -n $name | sum` && echo $1 )
- quad=$(( $num & 15 ))
- case "$quad" in
- 10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
- 13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
- esac
- eiface_devid=$quad$eiface_devid
- num=$(( $num >> 4 ))
- quad=$(( $num & 15 ))
- case "$quad" in
- 10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
- 13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
- esac
- eiface_devid=$quad$eiface_devid
- num=$(( $num >> 4 ))
- quad=$(( $num & 15 ))
- case "$quad" in
- 10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
- 13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
- esac
- eiface_devid=$quad:$eiface_devid
- num=$(( $num >> 4 ))
- quad=$(( $num & 15 ))
- case "$quad" in
- 10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
- 13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
- esac
- case "$iface_devid" in
- ?2:*) eiface_devid=a:$quad$eiface_devid ;;
- *) eiface_devid=2:$quad$eiface_devid
- esac
- eval num=\$_${iface}_num
- if [ "$num" ]; then
- num=$(( $num + 1 ))
- eval _${iface}_num=$num
- else
- num=0
- local _${iface}_num=$num
+ eiface_devid=
+ if [ "$clone_mac" ]; then
+ eiface_devid=$( ifconfig $iface ether |
+ awk '/ether/,$0=$2' )
+ elif [ ! "$no_derive" ]; then
+ derive_mac $iface "$name" eiface_devid
fi
- quad=$(( $num & 15 ))
- case "$quad" in
- 10) quad=a ;; 11) quad=b ;; 12) quad=c ;;
- 13) quad=d ;; 14) quad=e ;; 15) quad=f ;;
- esac
- eiface_devid=$quad$eiface_devid
- ifconfig $eiface ether $eiface_devid > /dev/null 2>&1
+ [ "$eiface_devid" ] &&
+ ifconfig $eiface ether $eiface_devid > /dev/null 2>&1
- i=$(( $i + 1 )) # on to next ng{i}_name
+ i=$(( $i + 1 ))
done # for iface
}
@@ -414,6 +447,39 @@ jng_shutdown()
jng_show "$name" | xargs -rn1 -I eiface ngctl shutdown eiface:
}
+jng_stats_usage="stats NAME"
+jng_stats_descr="Show ng_bridge link statistics for NAME interfaces"
+jng_stats()
+{
+ local OPTIND=1 OPTARG flag
+ while getopts "" flag; do
+ case "$flag" in
+ *) action_usage stats # NOTREACHED
+ esac
+ done
+ shift $(( $OPTIND -1 ))
+ local name="$1"
+ [ "${name:-x}" = "${name#*[!0-9a-zA-Z_]}" -a $# -eq 1 ] ||
+ action_usage stats # NOTREACHED
+ mustberoot_to_continue
+ for eiface in $( jng_show "$name" ); do
+ echo "$eiface:"
+ ngctl show $eiface: | awk '
+ $3 == "bridge" && $5 ~ /^link/ {
+ bridge = $2
+ link = substr($5, 5)
+ system(sprintf("ngctl msg %s: getstats %u",
+ bridge, link))
+ }' | fmt 2 | awk '
+ /=/ && fl = index($0, "=") {
+ printf "%20s = %s\n",
+ substr($0, 0, fl-1),
+ substr($0, 0, fl+1)
+ }
+ ' # END-QUOTE
+ done
+}
+
############################################################ MAIN
#
diff --git a/share/man/man4/ds3231.4 b/share/man/man4/ds3231.4
index 348860a..6fdcccc 100644
--- a/share/man/man4/ds3231.4
+++ b/share/man/man4/ds3231.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 6, 2015
+.Dd February 12, 2016
.Dt DS3231 4
.Os
.Sh NAME
@@ -110,8 +110,11 @@ that the
.Nm
is connected to.
.It Va hint.ds3231.%d.addr
-The i2c address of
+The 8-bit i2c address of
.Nm .
+The default 8-bit address for
+.Nm
+is 0xd0.
.El
.Pp
On a
@@ -121,11 +124,11 @@ based system the following properties must be set:
.It Va compatible
Must always be set to "maxim,ds3231".
.It Va reg
-The i2c address of
+The 7-bit i2c address of
.Nm .
-The default address for
+The default 7-bit address for
.Nm
-is 0xd0.
+is 0x68.
.El
.Sh SEE ALSO
.Xr fdt 4 ,
diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5
index c66edeb..9b1b68c 100644
--- a/share/man/man5/rc.conf.5
+++ b/share/man/man5/rc.conf.5
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 9, 2015
+.Dd February 12, 2016
.Dt RC.CONF 5
.Os
.Sh NAME
@@ -3853,20 +3853,22 @@ for every jail in
.Va jail_list .
.It Va jail_list
.Pq Vt str
-A space separated list of names for jails.
-If this variable is empty,
-all of
+A space-delimited list of jail names.
+When left empty, all of the
.Xr jail 8
-instances in the configuration file will be configured.
-This is purely a configuration aid to help identify and
-configure multiple jails.
-The names specified in this list will be used to
-identify settings common to an instance of a jail,
-and should contain alphanumeric characters only.
-The literal jail name of
-.Dq Li 0
-.Pq zero
-is not allowed.
+instances defined in the configuration file are started.
+The names specified in this list control the jail startup order.
+.Xr jail 8
+instances missing from
+.Va jail_list
+must be started manually.
+.It Va jail_reverse_stop
+.Pq Vt bool
+When set to
+.Dq Li YES ,
+all configured jails in
+.Va jail_list
+are stopped in reverse order.
.It Va jail_* variables
Note that older releases supported per-jail configuration via
.Xr rc.conf 5
diff --git a/share/man/man8/uefi.8 b/share/man/man8/uefi.8
index c4ee882..4f7935e 100644
--- a/share/man/man8/uefi.8
+++ b/share/man/man8/uefi.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 26, 2015
+.Dd February 11, 2016
.Dt UEFI 8
.Os
.Sh NAME
@@ -73,9 +73,34 @@ as
.Pa /EFI/BOOT/BOOTX64.EFI .
.It
.Pa boot1.efi
-locates the first partition with the type
-.Li freebsd-ufs ,
-and from it loads
+reads boot configuration from
+.Pa /boot.config
+or
+.Pa /boot/config .
+Unlike other first-stage boot loaders,
+.Pa boot1.efi
+passes the configuration to the next stage boot loader and does not
+itself act on the contents of the file.
+.It
+.Pa boot1.efi
+searches partitions of type
+.Li freebsd-ufs
+and
+.Li freebsd-zfs
+for
+.Pa loader.efi .
+The search begins with partitions on the device from which
+.Pa boot1.efi
+was loaded, and continues with other available partitions.
+If both
+.Li freebsd-ufs
+and
+.Li freebsd-zfs
+partitions exist on the same device the
+.Li freebsd-zfs
+partition is preferred.
+.Pa boot1.efi
+then loads and executes
.Pa loader.efi .
.It
.Pa loader.efi
@@ -112,6 +137,7 @@ typical non-default kernel (optional)
.El
.Sh SEE ALSO
.Xr vt 4 ,
+.Xr boot.config 5 ,
.Xr msdosfs 5 ,
.Xr boot 8 ,
.Xr gpart 8 ,
@@ -135,19 +161,3 @@ Foundation sponsored portions of the work.
EFI environment variables are not supported by
.Xr loader 8
or the kernel.
-.Pp
-.Pa boot1.efi
-loads
-.Pa loader.efi
-from the first FreeBSD-UFS file system it locates, even if it is on a
-different disk.
-.Pp
-.Pa boot1.efi
-cannot load
-.Pa loader.efi
-from a
-.Xr ZFS 8
-file system.
-As a result,
-.Nm
-does not support a typical root file system on ZFS configuration.
diff --git a/share/mk/src.libnames.mk b/share/mk/src.libnames.mk
index 28c2368..d27597f 100644
--- a/share/mk/src.libnames.mk
+++ b/share/mk/src.libnames.mk
@@ -39,6 +39,7 @@ _INTERNALLIBS= \
openbsd \
opts \
parse \
+ pe \
readline \
sl \
sm \
@@ -367,6 +368,9 @@ LDADD+= ${LDADD_${_l}}
LIBELFTCDIR= ${OBJTOP}/lib/libelftc
LIBELFTC?= ${LIBELFTCDIR}/libelftc.a
+LIBPEDIR= ${OBJTOP}/lib/libpe
+LIBPE?= ${LIBPEDIR}/libpe.a
+
LIBREADLINEDIR= ${OBJTOP}/gnu/lib/libreadline/readline
LIBREADLINE?= ${LIBREADLINEDIR}/libreadline.a
diff --git a/sys/arm/allwinner/a10_clk.c b/sys/arm/allwinner/a10_clk.c
index eab95b0..177e5a3 100644
--- a/sys/arm/allwinner/a10_clk.c
+++ b/sys/arm/allwinner/a10_clk.c
@@ -109,7 +109,8 @@ static driver_t a10_ccm_driver = {
static devclass_t a10_ccm_devclass;
-DRIVER_MODULE(a10_ccm, simplebus, a10_ccm_driver, a10_ccm_devclass, 0, 0);
+EARLY_DRIVER_MODULE(a10_ccm, simplebus, a10_ccm_driver, a10_ccm_devclass, 0, 0,
+ BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
int
a10_clk_usb_activate(void)
@@ -200,7 +201,7 @@ a10_clk_gmac_activate(phandle_t node)
/* Set GMAC mode. */
reg_value = CCM_GMAC_CLK_MII;
- if (OF_getprop_alloc(node, "phy-type", 1, (void **)&phy_type) > 0) {
+ if (OF_getprop_alloc(node, "phy-mode", 1, (void **)&phy_type) > 0) {
if (strcasecmp(phy_type, "rgmii") == 0)
reg_value = CCM_GMAC_CLK_RGMII | CCM_GMAC_MODE_RGMII;
else if (strcasecmp(phy_type, "rgmii-bpi") == 0) {
@@ -400,6 +401,29 @@ a10_clk_mmc_cfg(int devid, int freq)
}
int
+a10_clk_i2c_activate(int devid)
+{
+ struct a10_ccm_softc *sc;
+ uint32_t reg_value;
+
+ sc = a10_ccm_sc;
+ if (sc == NULL)
+ return (ENXIO);
+
+ a10_clk_pll6_enable();
+
+ /* Gating APB clock for I2C/TWI */
+ reg_value = ccm_read_4(sc, CCM_APB1_GATING);
+ if (devid == 4)
+ reg_value |= CCM_APB1_GATING_TWI << 15;
+ else
+ reg_value |= CCM_APB1_GATING_TWI << devid;
+ ccm_write_4(sc, CCM_APB1_GATING, reg_value);
+
+ return (0);
+}
+
+int
a10_clk_dmac_activate(void)
{
struct a10_ccm_softc *sc;
diff --git a/sys/arm/allwinner/a10_clk.h b/sys/arm/allwinner/a10_clk.h
index 4df87cc..5cc8863 100644
--- a/sys/arm/allwinner/a10_clk.h
+++ b/sys/arm/allwinner/a10_clk.h
@@ -121,6 +121,9 @@
/* AHB_GATING_REG1 */
#define CCM_AHB_GATING_GMAC (1 << 17)
+/* APB1_GATING_REG */
+#define CCM_APB1_GATING_TWI (1 << 0)
+
#define CCM_USB_PHY (1 << 8)
#define CCM_USB0_RESET (1 << 0)
#define CCM_USB1_RESET (1 << 1)
@@ -166,6 +169,7 @@ int a10_clk_gmac_activate(phandle_t);
int a10_clk_ahci_activate(void);
int a10_clk_mmc_activate(int);
int a10_clk_mmc_cfg(int, int);
+int a10_clk_i2c_activate(int);
int a10_clk_dmac_activate(void);
int a10_clk_codec_activate(unsigned int);
diff --git a/sys/arm/allwinner/a10_common.c b/sys/arm/allwinner/a10_common.c
index dacb97e..d20853a 100644
--- a/sys/arm/allwinner/a10_common.c
+++ b/sys/arm/allwinner/a10_common.c
@@ -50,7 +50,7 @@ fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
{
int offset;
- if (fdt_is_compatible(node, "allwinner,sun4i-ic"))
+ if (fdt_is_compatible(node, "allwinner,sun4i-a10-ic"))
offset = 0;
else if (fdt_is_compatible(node, "arm,gic"))
offset = 32;
diff --git a/sys/arm/allwinner/a10_dmac.c b/sys/arm/allwinner/a10_dmac.c
new file mode 100644
index 0000000..fefe27d
--- /dev/null
+++ b/sys/arm/allwinner/a10_dmac.c
@@ -0,0 +1,453 @@
+/*-
+ * Copyright (c) 2014-2016 Jared D. McNeill <jmcneill@invisible.ca>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * Allwinner A10/A20 DMA controller
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/condvar.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/allwinner/a10_dmac.h>
+#include <arm/allwinner/a10_clk.h>
+
+#include "sunxi_dma_if.h"
+
+#define NDMA_CHANNELS 8
+#define DDMA_CHANNELS 8
+
+enum a10dmac_type {
+ CH_NDMA,
+ CH_DDMA
+};
+
+struct a10dmac_softc;
+
+struct a10dmac_channel {
+ struct a10dmac_softc * ch_sc;
+ uint8_t ch_index;
+ enum a10dmac_type ch_type;
+ void (*ch_callback)(void *);
+ void * ch_callbackarg;
+ uint32_t ch_regoff;
+};
+
+struct a10dmac_softc {
+ struct resource * sc_res[2];
+ struct mtx sc_mtx;
+ void * sc_ih;
+
+ struct a10dmac_channel sc_ndma_channels[NDMA_CHANNELS];
+ struct a10dmac_channel sc_ddma_channels[DDMA_CHANNELS];
+};
+
+static struct resource_spec a10dmac_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+#define DMA_READ(sc, reg) bus_read_4((sc)->sc_res[0], (reg))
+#define DMA_WRITE(sc, reg, val) bus_write_4((sc)->sc_res[0], (reg), (val))
+#define DMACH_READ(ch, reg) \
+ DMA_READ((ch)->ch_sc, (reg) + (ch)->ch_regoff)
+#define DMACH_WRITE(ch, reg, val) \
+ DMA_WRITE((ch)->ch_sc, (reg) + (ch)->ch_regoff, (val))
+
+static void a10dmac_intr(void *);
+
+static int
+a10dmac_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-dma"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Allwinner DMA controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a10dmac_attach(device_t dev)
+{
+ struct a10dmac_softc *sc;
+ unsigned int index;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ if (bus_alloc_resources(dev, a10dmac_spec, sc->sc_res)) {
+ device_printf(dev, "cannot allocate resources for device\n");
+ return (ENXIO);
+ }
+
+ mtx_init(&sc->sc_mtx, "a10 dmac", NULL, MTX_SPIN);
+
+ /* Activate DMA controller clock */
+ a10_clk_dmac_activate();
+
+ /* Disable all interrupts and clear pending status */
+ DMA_WRITE(sc, AWIN_DMA_IRQ_EN_REG, 0);
+ DMA_WRITE(sc, AWIN_DMA_IRQ_PEND_STA_REG, ~0);
+
+ /* Initialize channels */
+ for (index = 0; index < NDMA_CHANNELS; index++) {
+ sc->sc_ndma_channels[index].ch_sc = sc;
+ sc->sc_ndma_channels[index].ch_index = index;
+ sc->sc_ndma_channels[index].ch_type = CH_NDMA;
+ sc->sc_ndma_channels[index].ch_callback = NULL;
+ sc->sc_ndma_channels[index].ch_callbackarg = NULL;
+ sc->sc_ndma_channels[index].ch_regoff = AWIN_NDMA_REG(index);
+ DMACH_WRITE(&sc->sc_ndma_channels[index], AWIN_NDMA_CTL_REG, 0);
+ }
+ for (index = 0; index < DDMA_CHANNELS; index++) {
+ sc->sc_ddma_channels[index].ch_sc = sc;
+ sc->sc_ddma_channels[index].ch_index = index;
+ sc->sc_ddma_channels[index].ch_type = CH_DDMA;
+ sc->sc_ddma_channels[index].ch_callback = NULL;
+ sc->sc_ddma_channels[index].ch_callbackarg = NULL;
+ sc->sc_ddma_channels[index].ch_regoff = AWIN_DDMA_REG(index);
+ DMACH_WRITE(&sc->sc_ddma_channels[index], AWIN_DDMA_CTL_REG, 0);
+ }
+
+ error = bus_setup_intr(dev, sc->sc_res[1], INTR_MPSAFE | INTR_TYPE_MISC,
+ NULL, a10dmac_intr, sc, &sc->sc_ih);
+ if (error != 0) {
+ device_printf(dev, "could not setup interrupt handler\n");
+ bus_release_resources(dev, a10dmac_spec, sc->sc_res);
+ mtx_destroy(&sc->sc_mtx);
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static void
+a10dmac_intr(void *priv)
+{
+ struct a10dmac_softc *sc = priv;
+ uint32_t sta, bit, mask;
+ uint8_t index;
+
+ sta = DMA_READ(sc, AWIN_DMA_IRQ_PEND_STA_REG);
+ DMA_WRITE(sc, AWIN_DMA_IRQ_PEND_STA_REG, sta);
+
+ while ((bit = ffs(sta & AWIN_DMA_IRQ_END_MASK)) != 0) {
+ mask = (1U << (bit - 1));
+ sta &= ~mask;
+ /*
+ * Map status bit to channel number. The status register is
+ * encoded with two bits of status per channel (lowest bit
+ * is half transfer pending, highest bit is end transfer
+ * pending). The 8 normal DMA channel status are in the lower
+ * 16 bits and the 8 dedicated DMA channel status are in
+ * the upper 16 bits. The output is a channel number from 0-7.
+ */
+ index = ((bit - 1) / 2) & 7;
+ if (mask & AWIN_DMA_IRQ_NDMA) {
+ if (sc->sc_ndma_channels[index].ch_callback == NULL)
+ continue;
+ sc->sc_ndma_channels[index].ch_callback(
+ sc->sc_ndma_channels[index].ch_callbackarg);
+ } else {
+ if (sc->sc_ddma_channels[index].ch_callback == NULL)
+ continue;
+ sc->sc_ddma_channels[index].ch_callback(
+ sc->sc_ddma_channels[index].ch_callbackarg);
+ }
+ }
+}
+
+static uint32_t
+a10dmac_read_ctl(struct a10dmac_channel *ch)
+{
+ if (ch->ch_type == CH_NDMA) {
+ return (DMACH_READ(ch, AWIN_NDMA_CTL_REG));
+ } else {
+ return (DMACH_READ(ch, AWIN_DDMA_CTL_REG));
+ }
+}
+
+static void
+a10dmac_write_ctl(struct a10dmac_channel *ch, uint32_t val)
+{
+ if (ch->ch_type == CH_NDMA) {
+ DMACH_WRITE(ch, AWIN_NDMA_CTL_REG, val);
+ } else {
+ DMACH_WRITE(ch, AWIN_DDMA_CTL_REG, val);
+ }
+}
+
+static int
+a10dmac_set_config(device_t dev, void *priv, const struct sunxi_dma_config *cfg)
+{
+ struct a10dmac_channel *ch = priv;
+ uint32_t val;
+ unsigned int dst_dw, dst_bl, dst_bs, dst_wc;
+ unsigned int src_dw, src_bl, src_bs, src_wc;
+
+ switch (cfg->dst_width) {
+ case 8:
+ dst_dw = AWIN_DMA_CTL_DATA_WIDTH_8;
+ break;
+ case 16:
+ dst_dw = AWIN_DMA_CTL_DATA_WIDTH_16;
+ break;
+ case 32:
+ dst_dw = AWIN_DMA_CTL_DATA_WIDTH_32;
+ break;
+ default:
+ return (EINVAL);
+ }
+ switch (cfg->dst_burst_len) {
+ case 1:
+ dst_bl = AWIN_DMA_CTL_BURST_LEN_1;
+ break;
+ case 4:
+ dst_bl = AWIN_DMA_CTL_BURST_LEN_4;
+ break;
+ case 8:
+ dst_bl = AWIN_DMA_CTL_BURST_LEN_8;
+ break;
+ default:
+ return (EINVAL);
+ }
+ switch (cfg->src_width) {
+ case 8:
+ src_dw = AWIN_DMA_CTL_DATA_WIDTH_8;
+ break;
+ case 16:
+ src_dw = AWIN_DMA_CTL_DATA_WIDTH_16;
+ break;
+ case 32:
+ src_dw = AWIN_DMA_CTL_DATA_WIDTH_32;
+ break;
+ default:
+ return (EINVAL);
+ }
+ switch (cfg->src_burst_len) {
+ case 1:
+ src_bl = AWIN_DMA_CTL_BURST_LEN_1;
+ break;
+ case 4:
+ src_bl = AWIN_DMA_CTL_BURST_LEN_4;
+ break;
+ case 8:
+ src_bl = AWIN_DMA_CTL_BURST_LEN_8;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ val = (dst_dw << AWIN_DMA_CTL_DST_DATA_WIDTH_SHIFT) |
+ (dst_bl << AWIN_DMA_CTL_DST_BURST_LEN_SHIFT) |
+ (cfg->dst_drqtype << AWIN_DMA_CTL_DST_DRQ_TYPE_SHIFT) |
+ (src_dw << AWIN_DMA_CTL_SRC_DATA_WIDTH_SHIFT) |
+ (src_bl << AWIN_DMA_CTL_SRC_BURST_LEN_SHIFT) |
+ (cfg->src_drqtype << AWIN_DMA_CTL_SRC_DRQ_TYPE_SHIFT);
+ if (cfg->dst_noincr) {
+ val |= AWIN_NDMA_CTL_DST_ADDR_NOINCR;
+ }
+ if (cfg->src_noincr) {
+ val |= AWIN_NDMA_CTL_SRC_ADDR_NOINCR;
+ }
+
+ if (ch->ch_type == CH_NDMA) {
+ DMACH_WRITE(ch, AWIN_NDMA_CTL_REG, val);
+ } else {
+ DMACH_WRITE(ch, AWIN_DDMA_CTL_REG, val);
+
+ dst_bs = cfg->dst_blksize - 1;
+ dst_wc = cfg->dst_wait_cyc - 1;
+ src_bs = cfg->src_blksize - 1;
+ src_wc = cfg->src_wait_cyc - 1;
+
+ DMACH_WRITE(ch, AWIN_DDMA_PARA_REG,
+ (dst_bs << AWIN_DDMA_PARA_DST_DATA_BLK_SIZ_SHIFT) |
+ (dst_wc << AWIN_DDMA_PARA_DST_WAIT_CYC_SHIFT) |
+ (src_bs << AWIN_DDMA_PARA_SRC_DATA_BLK_SIZ_SHIFT) |
+ (src_wc << AWIN_DDMA_PARA_SRC_WAIT_CYC_SHIFT));
+ }
+
+ return (0);
+}
+
+static void *
+a10dmac_alloc(device_t dev, bool dedicated, void (*cb)(void *), void *cbarg)
+{
+ struct a10dmac_softc *sc = device_get_softc(dev);
+ struct a10dmac_channel *ch_list;
+ struct a10dmac_channel *ch = NULL;
+ uint32_t irqen;
+ uint8_t ch_count, index;
+
+ if (dedicated) {
+ ch_list = sc->sc_ddma_channels;
+ ch_count = DDMA_CHANNELS;
+ } else {
+ ch_list = sc->sc_ndma_channels;
+ ch_count = NDMA_CHANNELS;
+ }
+
+ mtx_lock_spin(&sc->sc_mtx);
+ for (index = 0; index < ch_count; index++) {
+ if (ch_list[index].ch_callback == NULL) {
+ ch = &ch_list[index];
+ ch->ch_callback = cb;
+ ch->ch_callbackarg = cbarg;
+
+ irqen = DMA_READ(sc, AWIN_DMA_IRQ_EN_REG);
+ if (ch->ch_type == CH_NDMA)
+ irqen |= AWIN_DMA_IRQ_NDMA_END(index);
+ else
+ irqen |= AWIN_DMA_IRQ_DDMA_END(index);
+ DMA_WRITE(sc, AWIN_DMA_IRQ_EN_REG, irqen);
+
+ break;
+ }
+ }
+ mtx_unlock_spin(&sc->sc_mtx);
+
+ return (ch);
+}
+
+static void
+a10dmac_free(device_t dev, void *priv)
+{
+ struct a10dmac_channel *ch = priv;
+ struct a10dmac_softc *sc = ch->ch_sc;
+ uint32_t irqen, sta, cfg;
+
+ mtx_lock_spin(&sc->sc_mtx);
+
+ irqen = DMA_READ(sc, AWIN_DMA_IRQ_EN_REG);
+ cfg = a10dmac_read_ctl(ch);
+ if (ch->ch_type == CH_NDMA) {
+ sta = AWIN_DMA_IRQ_NDMA_END(ch->ch_index);
+ cfg &= ~AWIN_NDMA_CTL_DMA_LOADING;
+ } else {
+ sta = AWIN_DMA_IRQ_DDMA_END(ch->ch_index);
+ cfg &= ~AWIN_DDMA_CTL_DMA_LOADING;
+ }
+ irqen &= ~sta;
+ a10dmac_write_ctl(ch, cfg);
+ DMA_WRITE(sc, AWIN_DMA_IRQ_EN_REG, irqen);
+ DMA_WRITE(sc, AWIN_DMA_IRQ_PEND_STA_REG, sta);
+
+ ch->ch_callback = NULL;
+ ch->ch_callbackarg = NULL;
+
+ mtx_unlock_spin(&sc->sc_mtx);
+}
+
+static int
+a10dmac_transfer(device_t dev, void *priv, bus_addr_t src, bus_addr_t dst,
+ size_t nbytes)
+{
+ struct a10dmac_channel *ch = priv;
+ uint32_t cfg;
+
+ cfg = a10dmac_read_ctl(ch);
+ if (ch->ch_type == CH_NDMA) {
+ if (cfg & AWIN_NDMA_CTL_DMA_LOADING)
+ return (EBUSY);
+
+ DMACH_WRITE(ch, AWIN_NDMA_SRC_ADDR_REG, src);
+ DMACH_WRITE(ch, AWIN_NDMA_DEST_ADDR_REG, dst);
+ DMACH_WRITE(ch, AWIN_NDMA_BC_REG, nbytes);
+
+ cfg |= AWIN_NDMA_CTL_DMA_LOADING;
+ a10dmac_write_ctl(ch, cfg);
+ } else {
+ if (cfg & AWIN_DDMA_CTL_DMA_LOADING)
+ return (EBUSY);
+
+ DMACH_WRITE(ch, AWIN_DDMA_SRC_START_ADDR_REG, src);
+ DMACH_WRITE(ch, AWIN_DDMA_DEST_START_ADDR_REG, dst);
+ DMACH_WRITE(ch, AWIN_DDMA_BC_REG, nbytes);
+
+ cfg |= AWIN_DDMA_CTL_DMA_LOADING;
+ a10dmac_write_ctl(ch, cfg);
+ }
+
+ return (0);
+}
+
+static void
+a10dmac_halt(device_t dev, void *priv)
+{
+ struct a10dmac_channel *ch = priv;
+ uint32_t cfg;
+
+ cfg = a10dmac_read_ctl(ch);
+ if (ch->ch_type == CH_NDMA) {
+ cfg &= ~AWIN_NDMA_CTL_DMA_LOADING;
+ } else {
+ cfg &= ~AWIN_DDMA_CTL_DMA_LOADING;
+ }
+ a10dmac_write_ctl(ch, cfg);
+}
+
+static device_method_t a10dmac_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, a10dmac_probe),
+ DEVMETHOD(device_attach, a10dmac_attach),
+
+ /* sunxi DMA interface */
+ DEVMETHOD(sunxi_dma_alloc, a10dmac_alloc),
+ DEVMETHOD(sunxi_dma_free, a10dmac_free),
+ DEVMETHOD(sunxi_dma_set_config, a10dmac_set_config),
+ DEVMETHOD(sunxi_dma_transfer, a10dmac_transfer),
+ DEVMETHOD(sunxi_dma_halt, a10dmac_halt),
+
+ DEVMETHOD_END
+};
+
+static driver_t a10dmac_driver = {
+ "a10dmac",
+ a10dmac_methods,
+ sizeof(struct a10dmac_softc)
+};
+
+static devclass_t a10dmac_devclass;
+
+DRIVER_MODULE(a10dmac, simplebus, a10dmac_driver, a10dmac_devclass, 0, 0);
diff --git a/sys/arm/allwinner/a10_dmac.h b/sys/arm/allwinner/a10_dmac.h
new file mode 100644
index 0000000..7b337b3
--- /dev/null
+++ b/sys/arm/allwinner/a10_dmac.h
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 2014-2016 Jared D. McNeill <jmcneill@invisible.ca>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _A10_DMAC_H_
+#define _A10_DMAC_H_
+
+#define AWIN_DMA_IRQ_EN_REG 0x0000
+#define AWIN_DMA_IRQ_PEND_STA_REG 0x0004
+#define AWIN_NDMA_AUTO_GATE_REG 0x0008
+#define AWIN_NDMA_REG(n) (0x100+0x20*(n))
+#define AWIN_NDMA_CTL_REG 0x0000
+#define AWIN_NDMA_SRC_ADDR_REG 0x0004
+#define AWIN_NDMA_DEST_ADDR_REG 0x0008
+#define AWIN_NDMA_BC_REG 0x000c
+#define AWIN_DDMA_REG(n) (0x300+0x20*(n))
+#define AWIN_DDMA_CTL_REG 0x0000
+#define AWIN_DDMA_SRC_START_ADDR_REG 0x0004
+#define AWIN_DDMA_DEST_START_ADDR_REG 0x0008
+#define AWIN_DDMA_BC_REG 0x000c
+#define AWIN_DDMA_PARA_REG 0x0018
+#define AWIN_DMA_IRQ_END_MASK 0xaaaaaaaa
+#define AWIN_DMA_IRQ_HF_MASK 0x55555555
+#define AWIN_DMA_IRQ_DDMA 0xffff0000
+#define AWIN_DMA_IRQ_DDMA_END(n) (1U << (17+2*(n)))
+#define AWIN_DMA_IRQ_DDMA_HF(n) (1U << (16+2*(n)))
+#define AWIN_DMA_IRQ_NDMA 0x0000ffff
+#define AWIN_DMA_IRQ_NDMA_END(n) (1U << (1+2*(n)))
+#define AWIN_DMA_IRQ_NDMA_HF(n) (1U << (0+2*(n)))
+#define AWIN_NDMA_AUTO_GATING_DIS (1U << 16)
+#define AWIN_DMA_CTL_DST_DATA_WIDTH_SHIFT 25
+#define AWIN_DMA_CTL_DST_DATA_WIDTH_MASK (3U << AWIN_DMA_CTL_DST_DATA_WIDTH_SHIFT)
+#define AWIN_DMA_CTL_DATA_WIDTH_8 0
+#define AWIN_DMA_CTL_DATA_WIDTH_16 1
+#define AWIN_DMA_CTL_DATA_WIDTH_32 2
+#define AWIN_DMA_CTL_DST_BURST_LEN_SHIFT 23
+#define AWIN_DMA_CTL_DST_BURST_LEN_MASK (3 << AWIN_DMA_CTL_DST_BURST_LEN_SHIFT)
+#define AWIN_DMA_CTL_BURST_LEN_1 0
+#define AWIN_DMA_CTL_BURST_LEN_4 1
+#define AWIN_DMA_CTL_BURST_LEN_8 2
+#define AWIN_DMA_CTL_DST_DRQ_TYPE_SHIFT 16
+#define AWIN_DMA_CTL_DST_DRQ_TYPE_MASK (0x1f << AWIN_DMA_CTL_DST_DRQ_TYPE_SHIFT)
+#define AWIN_DMA_CTL_BC_REMAINING (1U << 15)
+#define AWIN_DMA_CTL_SRC_DATA_WIDTH_SHIFT 9
+#define AWIN_DMA_CTL_SRC_DATA_WIDTH_MASK (3U << AWIN_DMA_CTL_SRC_DATA_WIDTH_SHIFT)
+#define AWIN_DMA_CTL_SRC_BURST_LEN_SHIFT 7
+#define AWIN_DMA_CTL_SRC_BURST_LEN_MASK (3U << AWIN_DMA_CTL_SRC_BURST_LEN_SHIFT)
+#define AWIN_DMA_CTL_SRC_DRQ_TYPE_SHIFT 0
+#define AWIN_DMA_CTL_SRC_DRQ_TYPE_MASK (0x1f << AWIN_DMA_CTL_SRC_DRQ_TYPE_SHIFT)
+#define AWIN_NDMA_CTL_DMA_LOADING (1U << 31)
+#define AWIN_NDMA_CTL_DMA_CONTIN_MODE (1U << 30)
+#define AWIN_NDMA_CTL_WAIT_STATE_LOG2_SHIFT 27
+#define AWIN_NDMA_CTL_WAIT_STATE_LOG2_MASK (7U << AWIN_NDMA_CTL_WAIT_STATE_LOG2_SHIFT)
+#define AWIN_NDMA_CTL_DST_NON_SECURE (1U << 22)
+#define AWIN_NDMA_CTL_DST_ADDR_NOINCR (1U << 21)
+#define AWIN_NDMA_CTL_DRQ_IRO 0
+#define AWIN_NDMA_CTL_DRQ_IR1 1
+#define AWIN_NDMA_CTL_DRQ_SPDIF 2
+#define AWIN_NDMA_CTL_DRQ_IISO 3
+#define AWIN_NDMA_CTL_DRQ_IIS1 4
+#define AWIN_NDMA_CTL_DRQ_AC97 5
+#define AWIN_NDMA_CTL_DRQ_IIS2 6
+#define AWIN_NDMA_CTL_DRQ_UARTO 8
+#define AWIN_NDMA_CTL_DRQ_UART1 9
+#define AWIN_NDMA_CTL_DRQ_UART2 10
+#define AWIN_NDMA_CTL_DRQ_UART3 11
+#define AWIN_NDMA_CTL_DRQ_UART4 12
+#define AWIN_NDMA_CTL_DRQ_UART5 13
+#define AWIN_NDMA_CTL_DRQ_UART6 14
+#define AWIN_NDMA_CTL_DRQ_UART7 15
+#define AWIN_NDMA_CTL_DRQ_DDC 16
+#define AWIN_NDMA_CTL_DRQ_USB_EP1 17
+#define AWIN_NDMA_CTL_DRQ_CODEC 19
+#define AWIN_NDMA_CTL_DRQ_SRAM 21
+#define AWIN_NDMA_CTL_DRQ_SDRAM 22
+#define AWIN_NDMA_CTL_DRQ_TP_AD 23
+#define AWIN_NDMA_CTL_DRQ_SPI0 24
+#define AWIN_NDMA_CTL_DRQ_SPI1 25
+#define AWIN_NDMA_CTL_DRQ_SPI2 26
+#define AWIN_NDMA_CTL_DRQ_SPI3 27
+#define AWIN_NDMA_CTL_DRQ_USB_EP2 28
+#define AWIN_NDMA_CTL_DRQ_USB_EP3 29
+#define AWIN_NDMA_CTL_DRQ_USB_EP4 30
+#define AWIN_NDMA_CTL_DRQ_USB_EP5 31
+#define AWIN_NDMA_CTL_SRC_NON_SECURE (1U << 6)
+#define AWIN_NDMA_CTL_SRC_ADDR_NOINCR (1U << 5)
+#define AWIN_NDMA_BC_COUNT 0x0003ffff
+#define AWIN_DDMA_CTL_DMA_LOADING (1U << 31)
+#define AWIN_DDMA_CTL_BUSY (1U << 30)
+#define AWIN_DDMA_CTL_DMA_CONTIN_MODE (1U << 29)
+#define AWIN_DDMA_CTL_DST_NON_SECURE (1U << 28)
+#define AWIN_DDMA_CTL_DST_ADDR_MODE_SHIFT 21
+#define AWIN_DDMA_CTL_DST_ADDR_MODE_MASK (3U << AWIN_DDMA_CTL_DST_ADDR_MODE_SHIFT)
+#define AWIN_DDMA_CTL_DMA_ADDR_LINEAR 0
+#define AWIN_DDMA_CTL_DMA_ADDR_IO 1
+#define AWIN_DDMA_CTL_DMA_ADDR_HPAGE 2
+#define AWIN_DDMA_CTL_DMA_ADDR_VPAGE 3
+#define AWIN_DDMA_CTL_DST_DRQ_TYPE_SHIFT 16
+#define AWIN_DDMA_CTL_DST_DRQ_TYPE_MASK (0x1f << AWIN_DDMA_CTL_DST_DRQ_TYPE_SHIFT)
+#define AWIN_DDMA_CTL_DRQ_SRAM 0
+#define AWIN_DDMA_CTL_DRQ_SDRAM 1
+#define AWIN_DDMA_CTL_DRQ_NFC 3
+#define AWIN_DDMA_CTL_DRQ_USB0 4
+#define AWIN_DDMA_CTL_DRQ_EMAC_TX 6
+#define AWIN_DDMA_CTL_DRQ_EMAC_RX 7
+#define AWIN_DDMA_CTL_DRQ_SPI1_TX 8
+#define AWIN_DDMA_CTL_DRQ_SPI1_RX 9
+#define AWIN_DDMA_CTL_DRQ_SS_TX 10
+#define AWIN_DDMA_CTL_DRQ_SS_RX 11
+#define AWIN_DDMA_CTL_DRQ_TCON0 14
+#define AWIN_DDMA_CTL_DRQ_TCON1 15
+#define AWIN_DDMA_CTL_DRQ_MS_TX 23
+#define AWIN_DDMA_CTL_DRQ_MS_RX 23
+#define AWIN_DDMA_CTL_DRQ_HDMI_AUDIO 24
+#define AWIN_DDMA_CTL_DRQ_SPI0_TX 26
+#define AWIN_DDMA_CTL_DRQ_SPI0_RX 27
+#define AWIN_DDMA_CTL_DRQ_SPI2_TX 28
+#define AWIN_DDMA_CTL_DRQ_SPI2_RX 29
+#define AWIN_DDMA_CTL_DRQ_SPI3_TX 30
+#define AWIN_DDMA_CTL_DRQ_SPI3_RX 31
+#define AWIN_DDMA_CTL_SRC_NON_SECURE (1U << 12)
+#define AWIN_DDMA_CTL_SRC_ADDR_MODE_SHIFT 5
+#define AWIN_DDMA_CTL_SRC_ADDR_MODE_MASK (3U << AWIN_DDMA_CTL_SRC_ADDR_MODE_SHIFT)
+#define AWIN_DDMA_BC_COUNT 0x00003fff
+#define AWIN_DDMA_PARA_DST_DATA_BLK_SIZ_SHIFT 24
+#define AWIN_DDMA_PARA_DST_DATA_BLK_SIZ_MASK (0xff << AWIN_DDMA_PARA_DST_DATA_BLK_SIZ_SHIFT)
+#define AWIN_DDMA_PARA_DST_WAIT_CYC_SHIFT 16
+#define AWIN_DDMA_PARA_DST_WAIT_CYC_MASK (0xff << AWIN_DDMA_PARA_DST_WAIT_CYC_SHIFT)
+#define AWIN_DDMA_PARA_SRC_DATA_BLK_SIZ_SHIFT 8
+#define AWIN_DDMA_PARA_SRC_DATA_BLK_SIZ_MASK (0xff << AWIN_DDMA_PARA_SRC_DATA_BLK_SIZ_SHIFT)
+#define AWIN_DDMA_PARA_SRC_WAIT_CYC_SHIFT 0
+#define AWIN_DDMA_PARA_SRC_WAIT_CYC_MASK (0xff << AWIN_DDMA_PARA_SRC_WAIT_CYC_SHIFT)
+
+#endif /* !_A10_DMAC_H_ */
diff --git a/sys/arm/allwinner/a10_ehci.c b/sys/arm/allwinner/a10_ehci.c
index 91f79d3..5dbcdcb 100644
--- a/sys/arm/allwinner/a10_ehci.c
+++ b/sys/arm/allwinner/a10_ehci.c
@@ -43,10 +43,10 @@ __FBSDID("$FreeBSD$");
#include <sys/gpio.h>
#include <machine/bus.h>
-#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <dev/usb/usb.h>
+#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usb_core.h>
@@ -90,6 +90,12 @@ static device_detach_t a10_ehci_detach;
bs_r_1_proto(reversed);
bs_w_1_proto(reversed);
+static struct ofw_compat_data compat_data[] = {
+ {"allwinner,sun4i-a10-ehci", 1},
+ {"allwinner,sun7i-a20-ehci", 1},
+ {NULL, 0}
+};
+
static int
a10_ehci_probe(device_t self)
{
@@ -97,7 +103,7 @@ a10_ehci_probe(device_t self)
if (!ofw_bus_status_okay(self))
return (ENXIO);
- if (!ofw_bus_is_compatible(self, "allwinner,usb-ehci"))
+ if (ofw_bus_search_compatible(self, compat_data)->ocd_data == 0)
return (ENXIO);
device_set_desc(self, EHCI_HC_DEVSTR);
diff --git a/sys/arm/allwinner/a10_gpio.c b/sys/arm/allwinner/a10_gpio.c
index e3e247e..cda2c7b 100644
--- a/sys/arm/allwinner/a10_gpio.c
+++ b/sys/arm/allwinner/a10_gpio.c
@@ -73,6 +73,12 @@ __FBSDID("$FreeBSD$");
#define A10_GPIO_INPUT 0
#define A10_GPIO_OUTPUT 1
+static struct ofw_compat_data compat_data[] = {
+ {"allwinner,sun4i-a10-pinctrl", 1},
+ {"allwinner,sun7i-a20-pinctrl", 1},
+ {NULL, 0}
+};
+
struct a10_gpio_softc {
device_t sc_dev;
device_t sc_busdev;
@@ -373,7 +379,7 @@ a10_gpio_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-gpio"))
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
device_set_desc(dev, "Allwinner GPIO controller");
@@ -493,7 +499,9 @@ static driver_t a10_gpio_driver = {
sizeof(struct a10_gpio_softc),
};
-DRIVER_MODULE(a10_gpio, simplebus, a10_gpio_driver, a10_gpio_devclass, 0, 0);
+EARLY_DRIVER_MODULE(a10_gpio, simplebus, a10_gpio_driver, a10_gpio_devclass, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+
int
a10_gpio_ethernet_activate(uint32_t func)
diff --git a/sys/arm/allwinner/a10_mmc.c b/sys/arm/allwinner/a10_mmc.c
index eee1621..c4bb6df 100644
--- a/sys/arm/allwinner/a10_mmc.c
+++ b/sys/arm/allwinner/a10_mmc.c
@@ -62,6 +62,12 @@ static int a10_mmc_pio_mode = 0;
TUNABLE_INT("hw.a10.mmc.pio_mode", &a10_mmc_pio_mode);
+static struct ofw_compat_data compat_data[] = {
+ {"allwinner,sun4i-a10-mmc", 1},
+ {"allwinner,sun5i-a13-mmc", 1},
+ {NULL, 0}
+};
+
struct a10_mmc_softc {
bus_space_handle_t a10_bsh;
bus_space_tag_t a10_bst;
@@ -123,8 +129,9 @@ a10_mmc_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-mmc"))
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
+
device_set_desc(dev, "Allwinner Integrated MMC/SD controller");
return (BUS_PROBE_DEFAULT);
diff --git a/sys/arm/allwinner/a10_wdog.c b/sys/arm/allwinner/a10_wdog.c
index 40609b0..1c0dd00 100644
--- a/sys/arm/allwinner/a10_wdog.c
+++ b/sys/arm/allwinner/a10_wdog.c
@@ -95,7 +95,7 @@ a10wd_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (ofw_bus_is_compatible(dev, "allwinner,sun4i-wdt")) {
+ if (ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-wdt")) {
device_set_desc(dev, "Allwinner A10 Watchdog");
return (BUS_PROBE_DEFAULT);
}
diff --git a/sys/arm/allwinner/a20/a20_cpu_cfg.c b/sys/arm/allwinner/a20/a20_cpu_cfg.c
index ed0345a..a0bdb5a 100644
--- a/sys/arm/allwinner/a20/a20_cpu_cfg.c
+++ b/sys/arm/allwinner/a20/a20_cpu_cfg.c
@@ -117,7 +117,8 @@ static driver_t a20_cpu_cfg_driver = {
static devclass_t a20_cpu_cfg_devclass;
-DRIVER_MODULE(a20_cpu_cfg, simplebus, a20_cpu_cfg_driver, a20_cpu_cfg_devclass, 0, 0);
+EARLY_DRIVER_MODULE(a20_cpu_cfg, simplebus, a20_cpu_cfg_driver, a20_cpu_cfg_devclass, 0, 0,
+ BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
uint64_t
a20_read_counter64(void)
diff --git a/sys/arm/allwinner/aintc.c b/sys/arm/allwinner/aintc.c
index ed5f1fc..a15ead1 100644
--- a/sys/arm/allwinner/aintc.c
+++ b/sys/arm/allwinner/aintc.c
@@ -79,6 +79,12 @@ __FBSDID("$FreeBSD$");
#define SW_INT_ENABLE_REG(_b) (0x40 + ((_b) * 4))
#define SW_INT_MASK_REG(_b) (0x50 + ((_b) * 4))
+static struct ofw_compat_data compat_data[] = {
+ {"allwinner,sun4i-a10-ic", 1},
+ {"allwinner,sun7i-a20-sc-nmi", 1},
+ {NULL, 0}
+};
+
struct a10_aintc_softc {
device_t sc_dev;
struct resource * aintc_res;
@@ -101,7 +107,7 @@ a10_aintc_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-ic"))
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
device_set_desc(dev, "A10 AINTC Interrupt Controller");
return (BUS_PROBE_DEFAULT);
@@ -158,7 +164,8 @@ static driver_t a10_aintc_driver = {
static devclass_t a10_aintc_devclass;
-DRIVER_MODULE(aintc, simplebus, a10_aintc_driver, a10_aintc_devclass, 0, 0);
+EARLY_DRIVER_MODULE(aintc, simplebus, a10_aintc_driver, a10_aintc_devclass, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_FIRST);
int
arm_get_next_irq(int last_irq)
diff --git a/sys/arm/allwinner/axp209.c b/sys/arm/allwinner/axp209.c
new file mode 100644
index 0000000..11479fa
--- /dev/null
+++ b/sys/arm/allwinner/axp209.c
@@ -0,0 +1,182 @@
+/*-
+ * Copyright (c) 2015 Emmanuel Vadot <manu@bidouilliste.com>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+/*
+* X-Power AXP209 PMU for Allwinner SoCs
+*/
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/eventhandler.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/clock.h>
+#include <sys/time.h>
+#include <sys/bus.h>
+#include <sys/proc.h>
+#include <sys/reboot.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "iicbus_if.h"
+
+/* Power State Register */
+#define AXP209_PSR 0x00
+#define AXP209_PSR_ACIN 0x80
+#define AXP209_PSR_VBUS 0x20
+
+/* Shutdown and battery control */
+#define AXP209_SHUTBAT 0x32
+#define AXP209_SHUTBAT_SHUTDOWN 0x80
+
+struct axp209_softc {
+ uint32_t addr;
+ struct intr_config_hook enum_hook;
+};
+
+static int
+axp209_read(device_t dev, uint8_t reg, uint8_t *data, uint8_t size)
+{
+ struct axp209_softc *sc = device_get_softc(dev);
+ struct iic_msg msg[2];
+
+ msg[0].slave = sc->addr;
+ msg[0].flags = IIC_M_WR;
+ msg[0].len = 1;
+ msg[0].buf = &reg;
+
+ msg[1].slave = sc->addr;
+ msg[1].flags = IIC_M_RD;
+ msg[1].len = size;
+ msg[1].buf = data;
+
+ return (iicbus_transfer(dev, msg, 2));
+}
+
+static int
+axp209_write(device_t dev, uint8_t reg, uint8_t data)
+{
+ uint8_t buffer[2];
+ struct axp209_softc *sc = device_get_softc(dev);
+ struct iic_msg msg;
+
+ buffer[0] = reg;
+ buffer[1] = data;
+
+ msg.slave = sc->addr;
+ msg.flags = IIC_M_WR;
+ msg.len = 2;
+ msg.buf = buffer;
+
+ return (iicbus_transfer(dev, &msg, 1));
+}
+
+static void
+axp209_shutdown(void *devp, int howto)
+{
+ device_t dev;
+
+ if (!(howto & RB_POWEROFF))
+ return;
+ dev = (device_t)devp;
+
+ if (bootverbose)
+ device_printf(dev, "Shutdown AXP209\n");
+
+ axp209_write(dev, AXP209_SHUTBAT, AXP209_SHUTBAT_SHUTDOWN);
+}
+
+static int
+axp209_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "x-powers,axp209"))
+ return (ENXIO);
+
+ device_set_desc(dev, "X-Power AXP209 Power Management Unit");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+axp209_attach(device_t dev)
+{
+ struct axp209_softc *sc;
+ uint8_t data;
+ uint8_t pwr_src;
+ char pwr_name[4][11] = {"Battery", "AC", "USB", "AC and USB"};
+
+ sc = device_get_softc(dev);
+
+ sc->addr = iicbus_get_addr(dev);
+
+ /*
+ * Read the Power State register
+ * bit 7 is AC presence, bit 5 is VBUS presence.
+ * If none are set then we are running from battery (obviously).
+ */
+ axp209_read(dev, AXP209_PSR, &data, 1);
+ pwr_src = ((data & AXP209_PSR_ACIN) >> 7) |
+ ((data & AXP209_PSR_VBUS) >> 4);
+
+ if (bootverbose)
+ device_printf(dev, "AXP209 Powered by %s\n",
+ pwr_name[pwr_src]);
+
+ EVENTHANDLER_REGISTER(shutdown_final, axp209_shutdown, dev,
+ SHUTDOWN_PRI_LAST);
+
+ return (0);
+}
+
+static device_method_t axp209_methods[] = {
+ DEVMETHOD(device_probe, axp209_probe),
+ DEVMETHOD(device_attach, axp209_attach),
+ {0, 0},
+};
+
+static driver_t axp209_driver = {
+ "axp209_pmu",
+ axp209_methods,
+ sizeof(struct axp209_softc),
+};
+
+static devclass_t axp209_devclass;
+
+DRIVER_MODULE(axp209, iicbus, axp209_driver, axp209_devclass, 0, 0);
+MODULE_VERSION(axp209, 1);
+MODULE_DEPEND(axp209, iicbus, 1, 1, 1);
diff --git a/sys/arm/allwinner/files.a10 b/sys/arm/allwinner/files.a10
index 9f28fc4..44fe55f 100644
--- a/sys/arm/allwinner/files.a10
+++ b/sys/arm/allwinner/files.a10
@@ -1,3 +1,4 @@
# $FreeBSD$
arm/allwinner/aintc.c standard
+arm/allwinner/timer.c standard
diff --git a/sys/arm/allwinner/files.allwinner b/sys/arm/allwinner/files.allwinner
index 8606d91..0cdd7b3 100644
--- a/sys/arm/allwinner/files.allwinner
+++ b/sys/arm/allwinner/files.allwinner
@@ -4,6 +4,7 @@ kern/kern_clocksource.c standard
arm/allwinner/a10_ahci.c optional ahci
arm/allwinner/a10_clk.c standard
arm/allwinner/a10_common.c standard
+arm/allwinner/a10_dmac.c standard
arm/allwinner/a10_ehci.c optional ehci
arm/allwinner/a10_gpio.c optional gpio
arm/allwinner/a10_mmc.c optional mmc
@@ -11,6 +12,8 @@ arm/allwinner/a10_sramc.c standard
arm/allwinner/a10_wdog.c standard
arm/allwinner/a20/a20_cpu_cfg.c standard
arm/allwinner/allwinner_machdep.c standard
+arm/allwinner/axp209.c optional axp209
arm/allwinner/if_emac.c optional emac
-arm/allwinner/timer.c standard
+arm/allwinner/sunxi_dma_if.m standard
+dev/iicbus/twsi/a10_twsi.c optional twsi
#arm/allwinner/console.c standard
diff --git a/sys/arm/allwinner/if_emac.c b/sys/arm/allwinner/if_emac.c
index 18aeb8f..22422fe 100644
--- a/sys/arm/allwinner/if_emac.c
+++ b/sys/arm/allwinner/if_emac.c
@@ -756,7 +756,7 @@ static int
emac_probe(device_t dev)
{
- if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-emac"))
+ if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-emac"))
return (ENXIO);
device_set_desc(dev, "A10/A20 EMAC ethernet controller");
diff --git a/sys/arm/allwinner/sunxi_dma_if.m b/sys/arm/allwinner/sunxi_dma_if.m
new file mode 100644
index 0000000..6e283b9
--- /dev/null
+++ b/sys/arm/allwinner/sunxi_dma_if.m
@@ -0,0 +1,98 @@
+#-
+# Copyright (c) 2016 Jared D. McNeill <jmcneill@invisible.ca>
+# 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. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+#
+# $FreeBSD$
+#
+
+#include <sys/bus.h>
+
+INTERFACE sunxi_dma;
+
+HEADER {
+ #include <machine/bus.h>
+
+ struct sunxi_dma_config {
+ unsigned int dst_width;
+ unsigned int dst_burst_len;
+ unsigned int dst_drqtype;
+ bool dst_noincr;
+ unsigned int dst_blksize; /* DDMA-only */
+ unsigned int dst_wait_cyc; /* DDMA-only */
+ unsigned int src_width;
+ unsigned int src_burst_len;
+ unsigned int src_drqtype;
+ bool src_noincr;
+ unsigned int src_blksize; /* DDMA-only */
+ unsigned int src_wait_cyc; /* DDMA-only */
+ };
+
+ typedef void (*sunxi_dma_callback)(void *);
+}
+
+#
+# Allocate DMA channel
+#
+METHOD void * alloc {
+ device_t dev;
+ bool dedicated;
+ sunxi_dma_callback callback;
+ void *callback_arg;
+};
+
+#
+# Free DMA channel
+#
+METHOD void free {
+ device_t dev;
+ void *dmachan;
+};
+
+#
+# Set DMA channel configuration
+#
+METHOD int set_config {
+ device_t dev;
+ void *dmachan;
+ const struct sunxi_dma_config *cfg;
+};
+
+#
+# Start DMA channel transfer
+#
+METHOD int transfer {
+ device_t dev;
+ void *dmachan;
+ bus_addr_t src;
+ bus_addr_t dst;
+ size_t nbytes;
+};
+
+#
+# Halt DMA channel transfer
+#
+METHOD void halt {
+ device_t dev;
+ void *dmachan;
+};
diff --git a/sys/arm/allwinner/timer.c b/sys/arm/allwinner/timer.c
index 7c2a340..d25aa3c 100644
--- a/sys/arm/allwinner/timer.c
+++ b/sys/arm/allwinner/timer.c
@@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kdb.h>
-#include "a20/a20_cpu_cfg.h"
+#include <arm/allwinner/allwinner_machdep.h>
/**
* Timer registers addr
@@ -84,7 +84,6 @@ struct a10_timer_softc {
uint32_t sc_period;
uint32_t timer0_freq;
struct eventtimer et;
- uint8_t sc_timer_type; /* 0 for A10, 1 for A20 */
};
int a10_timer_get_timerfreq(struct a10_timer_softc *);
@@ -127,10 +126,6 @@ timer_read_counter64(void)
{
uint32_t lo, hi;
- /* In case of A20 get appropriate counter info */
- if (a10_timer_sc->sc_timer_type)
- return (a20_read_counter64());
-
/* Latch counter, wait for it to be ready to read. */
timer_write_4(a10_timer_sc, CNT64_CTRL_REG, CNT64_RL_EN);
while (timer_read_4(a10_timer_sc, CNT64_CTRL_REG) & CNT64_RL_EN)
@@ -146,14 +141,16 @@ static int
a10_timer_probe(device_t dev)
{
struct a10_timer_softc *sc;
+ u_int soc_family;
sc = device_get_softc(dev);
- if (ofw_bus_is_compatible(dev, "allwinner,sun4i-timer"))
- sc->sc_timer_type = 0;
- else if (ofw_bus_is_compatible(dev, "allwinner,sun7i-timer"))
- sc->sc_timer_type = 1;
- else
+ if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-timer"))
+ return (ENXIO);
+
+ soc_family = allwinner_soc_family();
+ if (soc_family != ALLWINNERSOC_SUN4I &&
+ soc_family != ALLWINNERSOC_SUN5I)
return (ENXIO);
device_set_desc(dev, "Allwinner A10/A20 timer");
@@ -352,7 +349,8 @@ static driver_t a10_timer_driver = {
static devclass_t a10_timer_devclass;
-DRIVER_MODULE(a10_timer, simplebus, a10_timer_driver, a10_timer_devclass, 0, 0);
+EARLY_DRIVER_MODULE(a10_timer, simplebus, a10_timer_driver, a10_timer_devclass, 0, 0,
+ BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
void
DELAY(int usec)
diff --git a/sys/arm/altera/socfpga/socfpga_common.c b/sys/arm/altera/socfpga/socfpga_common.c
index 6531a41..3615c94 100644
--- a/sys/arm/altera/socfpga/socfpga_common.c
+++ b/sys/arm/altera/socfpga/socfpga_common.c
@@ -74,6 +74,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
static int
fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
@@ -92,3 +93,4 @@ fdt_pic_decode_t fdt_pic_table[] = {
&fdt_pic_decode_ic,
NULL
};
+#endif
diff --git a/sys/arm/amlogic/aml8726/aml8726_machdep.c b/sys/arm/amlogic/aml8726/aml8726_machdep.c
index e1cd1b9..1ad25b4 100644
--- a/sys/arm/amlogic/aml8726/aml8726_machdep.c
+++ b/sys/arm/amlogic/aml8726/aml8726_machdep.c
@@ -184,6 +184,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
#ifndef DEV_GIC
static int
fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
@@ -212,3 +213,4 @@ fdt_pic_decode_t fdt_pic_table[] = {
#endif
NULL
};
+#endif /* ARM_INTRNG */
diff --git a/sys/arm/annapurna/alpine/common.c b/sys/arm/annapurna/alpine/common.c
index 774bf00..5d45b55 100644
--- a/sys/arm/annapurna/alpine/common.c
+++ b/sys/arm/annapurna/alpine/common.c
@@ -136,6 +136,7 @@ infinite:
while (1) {}
}
+#ifndef ARM_INTRNG
static int
alpine_pic_decode_fdt(uint32_t iparent, uint32_t *intr, int *interrupt,
int *trig, int *pol)
@@ -158,3 +159,4 @@ fdt_pic_decode_t fdt_pic_table[] = {
&alpine_pic_decode_fdt,
NULL
};
+#endif
diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c
index fd1f029..84e2cc3 100644
--- a/sys/arm/arm/generic_timer.c
+++ b/sys/arm/arm/generic_timer.c
@@ -361,11 +361,10 @@ arm_tmr_attach(device_t dev)
/* Get the base clock frequency */
node = ofw_bus_get_node(dev);
if (node > 0) {
- error = OF_getprop(node, "clock-frequency", &clock,
+ error = OF_getencprop(node, "clock-frequency", &clock,
sizeof(clock));
- if (error > 0) {
- sc->clkfreq = fdt32_to_cpu(clock);
- }
+ if (error > 0)
+ sc->clkfreq = clock;
}
#endif
diff --git a/sys/arm/arm/syscall.c b/sys/arm/arm/syscall.c
index 061fda4f..1ff48ab 100644
--- a/sys/arm/arm/syscall.c
+++ b/sys/arm/arm/syscall.c
@@ -98,17 +98,6 @@ __FBSDID("$FreeBSD$");
void swi_handler(struct trapframe *);
-static __inline void
-call_trapsignal(struct thread *td, int sig, u_long code)
-{
- ksiginfo_t ksi;
-
- ksiginfo_init_trap(&ksi);
- ksi.ksi_signo = sig;
- ksi.ksi_code = (int)code;
- trapsignal(td, &ksi);
-}
-
int
cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
{
diff --git a/sys/arm/at91/at91_common.c b/sys/arm/at91/at91_common.c
index 9f960f6..bc13196 100644
--- a/sys/arm/at91/at91_common.c
+++ b/sys/arm/at91/at91_common.c
@@ -53,6 +53,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
static int
fdt_aic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
@@ -75,6 +76,7 @@ fdt_pic_decode_t fdt_pic_table[] = {
&fdt_aic_decode_ic,
NULL
};
+#endif
static void
at91_eoi(void *unused)
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_common.c b/sys/arm/broadcom/bcm2835/bcm2835_common.c
index a558ac8..08f01a8 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_common.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_common.c
@@ -50,6 +50,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
static int
fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
@@ -70,3 +71,4 @@ fdt_pic_decode_t fdt_pic_table[] = {
&fdt_intc_decode_ic,
NULL
};
+#endif /* ARM_INTRNG */
diff --git a/sys/arm/conf/A10 b/sys/arm/conf/A10
new file mode 100644
index 0000000..2cb71d4
--- /dev/null
+++ b/sys/arm/conf/A10
@@ -0,0 +1,107 @@
+#
+# A10 -- Custom configuration for the AllWinner A10 SoC
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
+
+ident A10
+
+include "std.armv6"
+include "../allwinner/std.a10"
+
+options HZ=100
+options SCHED_4BSD # 4BSD scheduler
+options PLATFORM
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options ALT_BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+options INVARIANTS # Enable calls of extra sanity checking
+options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+options WITNESS # Enable checks to detect deadlocks and cycles
+options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+#options DIAGNOSTIC
+
+# NFS root from boopt/dhcp
+#options BOOTP
+#options BOOTP_NFSROOT
+#options BOOTP_COMPAT
+#options BOOTP_NFSV3
+#options BOOTP_WIRED_TO=emac0
+
+# MMC/SD/SDIO Card slot support
+device mmc # mmc/sd bus
+device mmcsd # mmc/sd flash cards
+
+# ATA controllers
+device ahci # AHCI-compatible SATA controllers
+#device ata # Legacy ATA/SATA controllers
+
+# Console and misc
+device uart
+device uart_ns8250
+device pty
+device snp
+device md
+device random # Entropy device
+
+# I2C support
+device iicbus
+device iic
+device twsi
+device axp209 # AXP209 Power Management Unit
+
+# GPIO
+device gpio
+device gpioled
+
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# USB support
+options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
+device usb
+options USB_DEBUG
+#options USB_REQ_DEBUG
+#options USB_VERBOSE
+#device uhci
+#device ohci
+device ehci
+
+device umass
+
+# Ethernet
+device loop
+device ether
+device mii
+device bpf
+
+device emac
+
+# USB ethernet support, requires miibus
+device miibus
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+makeoptions MODULES_EXTRA=dtb/allwinner
diff --git a/sys/arm/conf/A20 b/sys/arm/conf/A20
index 353c5ec..23519ff 100644
--- a/sys/arm/conf/A20
+++ b/sys/arm/conf/A20
@@ -52,12 +52,12 @@ options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
#options BOOTP_NFSV3
#options BOOTP_WIRED_TO=dwc0
-# Boot device is 2nd slice on MMC/SD card
-options ROOTDEVNAME=\"ufs:/dev/da0s2\"
-
# Interrupt controller
device gic
+# ARM Generic Timer
+device generic_timer
+
# MMC/SD/SDIO Card slot support
device mmc # mmc/sd bus
device mmcsd # mmc/sd flash cards
@@ -75,8 +75,10 @@ device md
device random # Entropy device
# I2C support
-#device iicbus
-#device iic
+device iicbus
+device iic
+device twsi
+device axp209 # AXP209 Power Management Unit
# GPIO
device gpio
diff --git a/sys/arm/conf/ALPINE b/sys/arm/conf/ALPINE
index bf1c42d..fa30865 100644
--- a/sys/arm/conf/ALPINE
+++ b/sys/arm/conf/ALPINE
@@ -37,6 +37,7 @@ options DDB #Enable the kernel debugger
# Interrupt controller
device gic
+options ARM_INTRNG
# Pseudo devices
device loop
diff --git a/sys/arm/conf/ARMADA38X b/sys/arm/conf/ARMADA38X
index 03fdf30..d6b3664 100644
--- a/sys/arm/conf/ARMADA38X
+++ b/sys/arm/conf/ARMADA38X
@@ -62,6 +62,7 @@ device pci
# Interrupt controllers
device gic
+options ARM_INTRNG
# Timers
device mpcore_timer
@@ -77,6 +78,7 @@ device da
# I2C
device iic
device iicbus
+device twsi
#FDT
options FDT
diff --git a/sys/arm/conf/ARMADAXP b/sys/arm/conf/ARMADAXP
index f1b2776..a57f783 100644
--- a/sys/arm/conf/ARMADAXP
+++ b/sys/arm/conf/ARMADAXP
@@ -90,6 +90,7 @@ device uart
# I2C (TWSI)
device iic
device iicbus
+device twsi
#Network
device ether
diff --git a/sys/arm/conf/DB-78XXX b/sys/arm/conf/DB-78XXX
index d40990b..d387ca3 100644
--- a/sys/arm/conf/DB-78XXX
+++ b/sys/arm/conf/DB-78XXX
@@ -82,6 +82,7 @@ device da
# I2C (TWSI)
device iic
device iicbus
+device twsi
device ds133x
# SATA
diff --git a/sys/arm/conf/DB-88F5XXX b/sys/arm/conf/DB-88F5XXX
index 28f448a..4e6f7f8 100644
--- a/sys/arm/conf/DB-88F5XXX
+++ b/sys/arm/conf/DB-88F5XXX
@@ -74,6 +74,7 @@ options HZ=1000
# I2C (TWSI)
device iic
device iicbus
+device twsi
device ds133x
# USB
diff --git a/sys/arm/conf/DB-88F6XXX b/sys/arm/conf/DB-88F6XXX
index 9dafb82..09e5f0b 100644
--- a/sys/arm/conf/DB-88F6XXX
+++ b/sys/arm/conf/DB-88F6XXX
@@ -87,6 +87,7 @@ device da
# I2C (TWSI)
device iic
device iicbus
+device twsi
# SATA
device mvs
diff --git a/sys/arm/conf/DOCKSTAR b/sys/arm/conf/DOCKSTAR
index c643b92..9a138bf 100644
--- a/sys/arm/conf/DOCKSTAR
+++ b/sys/arm/conf/DOCKSTAR
@@ -117,6 +117,7 @@ device u3g # USB-based 3G modems (Option, Huawei, Sierra)
# I2C (TWSI)
device iic
device iicbus
+device twsi
# Sound
device sound
diff --git a/sys/arm/conf/DREAMPLUG-1001 b/sys/arm/conf/DREAMPLUG-1001
index b5f4bd4..5391d18 100644
--- a/sys/arm/conf/DREAMPLUG-1001
+++ b/sys/arm/conf/DREAMPLUG-1001
@@ -121,6 +121,7 @@ device u3g # USB-based 3G modems (Option, Huawei, Sierra)
# I2C (TWSI)
device iic
device iicbus
+device twsi
# GPIO
device gpio
diff --git a/sys/arm/conf/EXYNOS5.common b/sys/arm/conf/EXYNOS5.common
index c1fa169..770a690 100644
--- a/sys/arm/conf/EXYNOS5.common
+++ b/sys/arm/conf/EXYNOS5.common
@@ -87,6 +87,8 @@ device dwmmc
# Interrupt controller
device gic
+options ARM_INTRNG
+
# ARM Generic Timer
device generic_timer
diff --git a/sys/arm/conf/NOTES b/sys/arm/conf/NOTES
index db64f8e..d32e6d6 100644
--- a/sys/arm/conf/NOTES
+++ b/sys/arm/conf/NOTES
@@ -51,6 +51,9 @@ device at91_board_tsc4370
device at91rm9200
device nand
+# IIC
+device twsi
+
nooptions SMP
nooptions MAXCPU
diff --git a/sys/arm/conf/ODROIDC1 b/sys/arm/conf/ODROIDC1
index 88836e3..550da87 100644
--- a/sys/arm/conf/ODROIDC1
+++ b/sys/arm/conf/ODROIDC1
@@ -26,6 +26,7 @@ options SMP # Enable multiple cores
# Interrupt controller
device gic
+options ARM_INTRNG
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=odroidc1.dts
diff --git a/sys/arm/conf/PANDABOARD b/sys/arm/conf/PANDABOARD
index 3177900..4eaa471 100644
--- a/sys/arm/conf/PANDABOARD
+++ b/sys/arm/conf/PANDABOARD
@@ -30,8 +30,6 @@ hints "PANDABOARD.hints"
include "std.armv6"
include "../ti/omap4/pandaboard/std.pandaboard"
-options ARM_INTRNG # new interrupt framework
-
options HZ=100
options SCHED_ULE # ULE scheduler
options PLATFORM
@@ -62,6 +60,8 @@ options DDB # Enable the kernel debugger
device fdt_pinctrl
# Interrupt controller
device gic
+options ARM_INTRNG
+
# ARM MPCore timer
device mpcore_timer
diff --git a/sys/arm/conf/RK3188 b/sys/arm/conf/RK3188
index 246a66a..49c8eae 100644
--- a/sys/arm/conf/RK3188
+++ b/sys/arm/conf/RK3188
@@ -47,6 +47,8 @@ options ROOTDEVNAME=\"ufs:/dev/mmcsd0\"
# Interrupt controller
device gic
+options ARM_INTRNG
+
# ARM MPCore timer
device mpcore_timer
diff --git a/sys/arm/conf/SOCKIT.common b/sys/arm/conf/SOCKIT.common
index 65be347..3365929 100644
--- a/sys/arm/conf/SOCKIT.common
+++ b/sys/arm/conf/SOCKIT.common
@@ -53,6 +53,8 @@ options INVARIANT_SUPPORT # Extra sanity checks of internal structures, require
# Interrupt controller
device gic
+options ARM_INTRNG
+
# ARM MPCore timer
device mpcore_timer
diff --git a/sys/arm/conf/VIRT b/sys/arm/conf/VIRT
index aa70fd5..ee652b2 100644
--- a/sys/arm/conf/VIRT
+++ b/sys/arm/conf/VIRT
@@ -46,6 +46,8 @@ options INVARIANT_SUPPORT # Extra sanity checks of internal structures, require
# Interrupt controller
device gic
+options ARM_INTRNG
+
# ARM Generic Timer
device generic_timer
diff --git a/sys/arm/conf/VSATV102 b/sys/arm/conf/VSATV102
index f845594..96e3ba4 100644
--- a/sys/arm/conf/VSATV102
+++ b/sys/arm/conf/VSATV102
@@ -26,6 +26,7 @@ options SMP # Enable multiple cores
# Interrupt controller
device gic
+options ARM_INTRNG
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=vsatv102-m6.dts
diff --git a/sys/arm/conf/VYBRID b/sys/arm/conf/VYBRID
index 0aa38ce..471b8d5 100644
--- a/sys/arm/conf/VYBRID
+++ b/sys/arm/conf/VYBRID
@@ -62,6 +62,8 @@ options NO_SWAPPING
# Interrupt controller
device gic
+options ARM_INTRNG
+
# ARM MPCore timer
device mpcore_timer
diff --git a/sys/arm/conf/ZEDBOARD b/sys/arm/conf/ZEDBOARD
index 6cdbf66..41ec23a 100644
--- a/sys/arm/conf/ZEDBOARD
+++ b/sys/arm/conf/ZEDBOARD
@@ -22,7 +22,7 @@
ident ZEDBOARD
include "std.armv6"
-include "../xilinx/zedboard/std.zedboard"
+include "../xilinx/std.zynq7"
options SCHED_ULE # ULE scheduler
#options NFSSD # Network Filesystem Server
@@ -52,6 +52,8 @@ options ROOTDEVNAME=\"ufs:mmcsd0s2a\"
# Interrupt controller
device gic
+options ARM_INTRNG
+
# Cache controller
device pl310 # PL310 L2 cache controller
# ARM MPCore timer
diff --git a/sys/arm/freescale/imx/imx_common.c b/sys/arm/freescale/imx/imx_common.c
index 0fe7082..50922e6 100644
--- a/sys/arm/freescale/imx/imx_common.c
+++ b/sys/arm/freescale/imx/imx_common.c
@@ -54,6 +54,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
static int
fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
@@ -70,3 +71,4 @@ fdt_pic_decode_t fdt_pic_table[] = {
&fdt_intc_decode_ic,
NULL
};
+#endif /* ARM_INTRNG */
diff --git a/sys/arm/freescale/vybrid/vf_common.c b/sys/arm/freescale/vybrid/vf_common.c
index ffec9a3..913902a 100644
--- a/sys/arm/freescale/vybrid/vf_common.c
+++ b/sys/arm/freescale/vybrid/vf_common.c
@@ -66,6 +66,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
static int
fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
@@ -84,3 +85,4 @@ fdt_pic_decode_t fdt_pic_table[] = {
&fdt_pic_decode_ic,
NULL
};
+#endif
diff --git a/sys/arm/include/intr.h b/sys/arm/include/intr.h
index 83a3937..2afda95 100644
--- a/sys/arm/include/intr.h
+++ b/sys/arm/include/intr.h
@@ -49,93 +49,7 @@
#define NIRQ 1024 /* XXX - It should be an option. */
#endif
-#ifdef notyet
-#define INTR_SOLO INTR_MD1
-typedef int intr_irq_filter_t(void *arg, struct trapframe *tf);
-#else
-typedef int intr_irq_filter_t(void *arg);
-#endif
-
-#define INTR_ISRC_NAMELEN (MAXCOMLEN + 1)
-
-typedef void intr_ipi_filter_t(void *arg);
-
-enum intr_isrc_type {
- INTR_ISRCT_NAMESPACE,
- INTR_ISRCT_FDT
-};
-
-#define INTR_ISRCF_REGISTERED 0x01 /* registered in a controller */
-#define INTR_ISRCF_PERCPU 0x02 /* per CPU interrupt */
-#define INTR_ISRCF_BOUND 0x04 /* bound to a CPU */
-
-/* Interrupt source definition. */
-struct intr_irqsrc {
- device_t isrc_dev; /* where isrc is mapped */
- intptr_t isrc_xref; /* device reference key */
- uintptr_t isrc_data; /* device data for isrc */
- u_int isrc_irq; /* unique identificator */
- enum intr_isrc_type isrc_type; /* how is isrc decribed */
- u_int isrc_flags;
- char isrc_name[INTR_ISRC_NAMELEN];
- uint16_t isrc_nspc_type;
- uint16_t isrc_nspc_num;
- enum intr_trigger isrc_trig;
- enum intr_polarity isrc_pol;
- cpuset_t isrc_cpu; /* on which CPUs is enabled */
- u_int isrc_index;
- u_long * isrc_count;
- u_int isrc_handlers;
- struct intr_event * isrc_event;
- intr_irq_filter_t * isrc_filter;
- intr_ipi_filter_t * isrc_ipifilter;
- void * isrc_arg;
-#ifdef FDT
- u_int isrc_ncells;
- pcell_t isrc_cells[]; /* leave it last */
-#endif
-};
-
-void intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...)
- __printflike(2, 3);
-
-void intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf);
-
-#define INTR_IRQ_NSPC_NONE 0
-#define INTR_IRQ_NSPC_PLAIN 1
-#define INTR_IRQ_NSPC_IRQ 2
-#define INTR_IRQ_NSPC_IPI 3
-
-u_int intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num);
-#ifdef FDT
-u_int intr_fdt_map_irq(phandle_t, pcell_t *, u_int);
-#endif
-
-int intr_pic_register(device_t dev, intptr_t xref);
-int intr_pic_unregister(device_t dev, intptr_t xref);
-int intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
- void *arg, u_int ipicount);
-
-int intr_irq_add_handler(device_t dev, driver_filter_t, driver_intr_t, void *,
- u_int, int, void **);
-int intr_irq_remove_handler(device_t dev, u_int, void *);
-int intr_irq_config(u_int, enum intr_trigger, enum intr_polarity);
-int intr_irq_describe(u_int, void *, const char *);
-
-u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask);
-
-#ifdef SMP
-int intr_irq_bind(u_int, int);
-
-void intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf);
-
-#define AISHF_NOALLOC 0x0001
-
-int intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter,
- void *arg, u_int flags);
-
-void intr_pic_init_secondary(void);
-#endif
+#include <sys/intr.h>
#else /* ARM_INTRNG */
diff --git a/sys/arm/lpc/lpc_intc.c b/sys/arm/lpc/lpc_intc.c
index bf26645..d4b2517 100644
--- a/sys/arm/lpc/lpc_intc.c
+++ b/sys/arm/lpc/lpc_intc.c
@@ -231,6 +231,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
static int
fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
@@ -248,3 +249,4 @@ fdt_pic_decode_t fdt_pic_table[] = {
&fdt_pic_decode_ic,
NULL
};
+#endif
diff --git a/sys/arm/mv/files.mv b/sys/arm/mv/files.mv
index 791ef00..29edffb 100644
--- a/sys/arm/mv/files.mv
+++ b/sys/arm/mv/files.mv
@@ -19,9 +19,9 @@ arm/mv/mv_machdep.c standard
arm/mv/mv_pci.c optional pci
arm/mv/mv_ts.c standard
arm/mv/timer.c standard
-arm/mv/twsi.c optional iicbus
dev/cesa/cesa.c optional cesa
+dev/iicbus/twsi/mv_twsi.c optional twsi
dev/mge/if_mge.c optional mge
dev/nand/nfc_mv.c optional nand
dev/mvs/mvs_soc.c optional mvs
diff --git a/sys/arm/mv/mv_common.c b/sys/arm/mv/mv_common.c
index afefc7f..ec55357 100644
--- a/sys/arm/mv/mv_common.c
+++ b/sys/arm/mv/mv_common.c
@@ -2181,6 +2181,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
static int
fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
@@ -2204,6 +2205,7 @@ fdt_pic_decode_t fdt_pic_table[] = {
&fdt_pic_decode_ic,
NULL
};
+#endif
uint64_t
get_sar_value(void)
diff --git a/sys/arm/mv/twsi.c b/sys/arm/mv/twsi.c
deleted file mode 100644
index dfd0243..0000000
--- a/sys/arm/mv/twsi.c
+++ /dev/null
@@ -1,647 +0,0 @@
-/*-
- * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
- * All rights reserved.
- *
- * Developed by Semihalf.
- *
- * 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. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of MARVELL nor the names of contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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.
- */
-
-/*
- * Driver for the TWSI (aka I2C, aka IIC) bus controller found on Marvell
- * SoCs. Supports master operation only, and works in polling mode.
- *
- * Calls to DELAY() are needed per Application Note AN-179 "TWSI Software
- * Guidelines for Discovery(TM), Horizon (TM) and Feroceon(TM) Devices".
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/resource.h>
-
-#include <machine/_inttypes.h>
-#include <machine/bus.h>
-#include <machine/resource.h>
-
-#include <sys/rman.h>
-
-#include <sys/lock.h>
-#include <sys/mutex.h>
-
-#include <dev/iicbus/iiconf.h>
-#include <dev/iicbus/iicbus.h>
-#include <dev/fdt/fdt_common.h>
-#include <dev/ofw/ofw_bus.h>
-#include <dev/ofw/ofw_bus_subr.h>
-
-#include <arm/mv/mvreg.h>
-#include <arm/mv/mvvar.h>
-
-#include "iicbus_if.h"
-
-#define MV_TWSI_NAME "twsi"
-#define IICBUS_DEVNAME "iicbus"
-
-#define TWSI_SLAVE_ADDR 0x00
-#define TWSI_EXT_SLAVE_ADDR 0x10
-#define TWSI_DATA 0x04
-
-#define TWSI_CONTROL 0x08
-#define TWSI_CONTROL_ACK (1 << 2)
-#define TWSI_CONTROL_IFLG (1 << 3)
-#define TWSI_CONTROL_STOP (1 << 4)
-#define TWSI_CONTROL_START (1 << 5)
-#define TWSI_CONTROL_TWSIEN (1 << 6)
-#define TWSI_CONTROL_INTEN (1 << 7)
-
-#define TWSI_STATUS 0x0c
-#define TWSI_STATUS_START 0x08
-#define TWSI_STATUS_RPTD_START 0x10
-#define TWSI_STATUS_ADDR_W_ACK 0x18
-#define TWSI_STATUS_DATA_WR_ACK 0x28
-#define TWSI_STATUS_ADDR_R_ACK 0x40
-#define TWSI_STATUS_DATA_RD_ACK 0x50
-#define TWSI_STATUS_DATA_RD_NOACK 0x58
-
-#define TWSI_BAUD_RATE 0x0c
-#define TWSI_BAUD_RATE_PARAM(M,N) ((((M) << 3) | ((N) & 0x7)) & 0x7f)
-#define TWSI_BAUD_RATE_RAW(C,M,N) ((C)/((10*(M+1))<<(N+1)))
-#define TWSI_BAUD_RATE_SLOW 50000 /* 50kHz */
-#define TWSI_BAUD_RATE_FAST 100000 /* 100kHz */
-
-#define TWSI_SOFT_RESET 0x1c
-
-#define TWSI_DEBUG
-#undef TWSI_DEBUG
-
-#ifdef TWSI_DEBUG
-#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
-#else
-#define debugf(fmt, args...)
-#endif
-
-struct mv_twsi_softc {
- device_t dev;
- struct resource *res[1]; /* SYS_RES_MEMORY */
- struct mtx mutex;
- device_t iicbus;
-};
-
-static struct mv_twsi_baud_rate {
- uint32_t raw;
- int param;
- int m;
- int n;
-} baud_rate[IIC_FASTEST + 1];
-
-static int mv_twsi_probe(device_t);
-static int mv_twsi_attach(device_t);
-static int mv_twsi_detach(device_t);
-
-static int mv_twsi_reset(device_t dev, u_char speed, u_char addr,
- u_char *oldaddr);
-static int mv_twsi_repeated_start(device_t dev, u_char slave, int timeout);
-static int mv_twsi_start(device_t dev, u_char slave, int timeout);
-static int mv_twsi_stop(device_t dev);
-static int mv_twsi_read(device_t dev, char *buf, int len, int *read, int last,
- int delay);
-static int mv_twsi_write(device_t dev, const char *buf, int len, int *sent,
- int timeout);
-
-static struct resource_spec res_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE },
- { -1, 0 }
-};
-
-static struct ofw_compat_data compat_data[] = {
- { "mrvl,twsi", true },
- { "marvell,mv64xxx-i2c", true },
- { NULL, false }
-};
-
-static device_method_t mv_twsi_methods[] = {
- /* device interface */
- DEVMETHOD(device_probe, mv_twsi_probe),
- DEVMETHOD(device_attach, mv_twsi_attach),
- DEVMETHOD(device_detach, mv_twsi_detach),
-
- /* iicbus interface */
- DEVMETHOD(iicbus_callback, iicbus_null_callback),
- DEVMETHOD(iicbus_repeated_start, mv_twsi_repeated_start),
- DEVMETHOD(iicbus_start, mv_twsi_start),
- DEVMETHOD(iicbus_stop, mv_twsi_stop),
- DEVMETHOD(iicbus_write, mv_twsi_write),
- DEVMETHOD(iicbus_read, mv_twsi_read),
- DEVMETHOD(iicbus_reset, mv_twsi_reset),
- DEVMETHOD(iicbus_transfer, iicbus_transfer_gen),
- { 0, 0 }
-};
-
-static devclass_t mv_twsi_devclass;
-
-static driver_t mv_twsi_driver = {
- MV_TWSI_NAME,
- mv_twsi_methods,
- sizeof(struct mv_twsi_softc),
-};
-
-DRIVER_MODULE(twsi, simplebus, mv_twsi_driver, mv_twsi_devclass, 0, 0);
-DRIVER_MODULE(iicbus, twsi, iicbus_driver, iicbus_devclass, 0, 0);
-MODULE_DEPEND(twsi, iicbus, 1, 1, 1);
-
-static __inline uint32_t
-TWSI_READ(struct mv_twsi_softc *sc, bus_size_t off)
-{
-
- return (bus_read_4(sc->res[0], off));
-}
-
-static __inline void
-TWSI_WRITE(struct mv_twsi_softc *sc, bus_size_t off, uint32_t val)
-{
-
- bus_write_4(sc->res[0], off, val);
-}
-
-static __inline void
-twsi_control_clear(struct mv_twsi_softc *sc, uint32_t mask)
-{
- uint32_t val;
-
- val = TWSI_READ(sc, TWSI_CONTROL);
- val &= ~mask;
- TWSI_WRITE(sc, TWSI_CONTROL, val);
-}
-
-static __inline void
-twsi_control_set(struct mv_twsi_softc *sc, uint32_t mask)
-{
- uint32_t val;
-
- val = TWSI_READ(sc, TWSI_CONTROL);
- val |= mask;
- TWSI_WRITE(sc, TWSI_CONTROL, val);
-}
-
-static __inline void
-twsi_clear_iflg(struct mv_twsi_softc *sc)
-{
-
- DELAY(1000);
- twsi_control_clear(sc, TWSI_CONTROL_IFLG);
- DELAY(1000);
-}
-
-
-/*
- * timeout given in us
- * returns
- * 0 on sucessfull mask change
- * non-zero on timeout
- */
-static int
-twsi_poll_ctrl(struct mv_twsi_softc *sc, int timeout, uint32_t mask)
-{
-
- timeout /= 10;
- while (!(TWSI_READ(sc, TWSI_CONTROL) & mask)) {
- DELAY(10);
- if (--timeout < 0)
- return (timeout);
- }
- return (0);
-}
-
-
-/*
- * 'timeout' is given in us. Note also that timeout handling is not exact --
- * twsi_locked_start() total wait can be more than 2 x timeout
- * (twsi_poll_ctrl() is called twice). 'mask' can be either TWSI_STATUS_START
- * or TWSI_STATUS_RPTD_START
- */
-static int
-twsi_locked_start(device_t dev, struct mv_twsi_softc *sc, int32_t mask,
- u_char slave, int timeout)
-{
- int read_access, iflg_set = 0;
- uint32_t status;
-
- mtx_assert(&sc->mutex, MA_OWNED);
-
- if (mask == TWSI_STATUS_RPTD_START)
- /* read IFLG to know if it should be cleared later; from NBSD */
- iflg_set = TWSI_READ(sc, TWSI_CONTROL) & TWSI_CONTROL_IFLG;
-
- twsi_control_set(sc, TWSI_CONTROL_START);
-
- if (mask == TWSI_STATUS_RPTD_START && iflg_set) {
- debugf("IFLG set, clearing\n");
- twsi_clear_iflg(sc);
- }
-
- /*
- * Without this delay we timeout checking IFLG if the timeout is 0.
- * NBSD driver always waits here too.
- */
- DELAY(1000);
-
- if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
- debugf("timeout sending %sSTART condition\n",
- mask == TWSI_STATUS_START ? "" : "repeated ");
- return (IIC_ETIMEOUT);
- }
-
- status = TWSI_READ(sc, TWSI_STATUS);
- if (status != mask) {
- debugf("wrong status (%02x) after sending %sSTART condition\n",
- status, mask == TWSI_STATUS_START ? "" : "repeated ");
- return (IIC_ESTATUS);
- }
-
- TWSI_WRITE(sc, TWSI_DATA, slave);
- DELAY(1000);
- twsi_clear_iflg(sc);
-
- if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
- debugf("timeout sending slave address\n");
- return (IIC_ETIMEOUT);
- }
-
- read_access = (slave & 0x1) ? 1 : 0;
- status = TWSI_READ(sc, TWSI_STATUS);
- if (status != (read_access ?
- TWSI_STATUS_ADDR_R_ACK : TWSI_STATUS_ADDR_W_ACK)) {
- debugf("no ACK (status: %02x) after sending slave address\n",
- status);
- return (IIC_ENOACK);
- }
-
- return (IIC_NOERR);
-}
-
-static int
-mv_twsi_probe(device_t dev)
-{
-
- if (!ofw_bus_status_okay(dev))
- return (ENXIO);
-
- if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
- return (ENXIO);
-
- device_set_desc(dev, "Marvell Integrated I2C Bus Controller");
- return (BUS_PROBE_DEFAULT);
-}
-
-#define ABSSUB(a,b) (((a) > (b)) ? (a) - (b) : (b) - (a))
-static void
-mv_twsi_cal_baud_rate(const uint32_t target, struct mv_twsi_baud_rate *rate)
-{
- uint32_t clk, cur, diff, diff0;
- int m, n, m0, n0;
-
- /* Calculate baud rate. */
- m0 = n0 = 4; /* Default values on reset */
- diff0 = 0xffffffff;
- clk = get_tclk();
-
- for (n = 0; n < 8; n++) {
- for (m = 0; m < 16; m++) {
- cur = TWSI_BAUD_RATE_RAW(clk,m,n);
- diff = ABSSUB(target, cur);
- if (diff < diff0) {
- m0 = m;
- n0 = n;
- diff0 = diff;
- }
- }
- }
- rate->raw = TWSI_BAUD_RATE_RAW(clk, m0, n0);
- rate->param = TWSI_BAUD_RATE_PARAM(m0, n0);
- rate->m = m0;
- rate->n = n0;
-}
-
-static int
-mv_twsi_attach(device_t dev)
-{
- struct mv_twsi_softc *sc;
- phandle_t child, iicbusnode;
- device_t childdev;
- struct iicbus_ivar *devi;
- char dname[32]; /* 32 is taken from struct u_device */
- uint32_t paddr;
- int len, error;
-
- sc = device_get_softc(dev);
- sc->dev = dev;
- bzero(baud_rate, sizeof(baud_rate));
-
- mtx_init(&sc->mutex, device_get_nameunit(dev), MV_TWSI_NAME, MTX_DEF);
-
- /* Allocate IO resources */
- if (bus_alloc_resources(dev, res_spec, sc->res)) {
- device_printf(dev, "could not allocate resources\n");
- mv_twsi_detach(dev);
- return (ENXIO);
- }
-
- mv_twsi_cal_baud_rate(TWSI_BAUD_RATE_SLOW, &baud_rate[IIC_SLOW]);
- mv_twsi_cal_baud_rate(TWSI_BAUD_RATE_FAST, &baud_rate[IIC_FAST]);
- if (bootverbose)
- device_printf(dev, "calculated baud rates are:\n"
- " %" PRIu32 " kHz (M=%d, N=%d) for slow,\n"
- " %" PRIu32 " kHz (M=%d, N=%d) for fast.\n",
- baud_rate[IIC_SLOW].raw / 1000,
- baud_rate[IIC_SLOW].m,
- baud_rate[IIC_SLOW].n,
- baud_rate[IIC_FAST].raw / 1000,
- baud_rate[IIC_FAST].m,
- baud_rate[IIC_FAST].n);
-
- sc->iicbus = device_add_child(dev, IICBUS_DEVNAME, -1);
- if (sc->iicbus == NULL) {
- device_printf(dev, "could not add iicbus child\n");
- mv_twsi_detach(dev);
- return (ENXIO);
- }
- /* Attach iicbus. */
- bus_generic_attach(dev);
-
- iicbusnode = 0;
- /* Find iicbus as the child devices in the device tree. */
- for (child = OF_child(ofw_bus_get_node(dev)); child != 0;
- child = OF_peer(child)) {
- len = OF_getproplen(child, "model");
- if (len <= 0 || len > sizeof(dname) - 1)
- continue;
- error = OF_getprop(child, "model", &dname, len);
- dname[len + 1] = '\0';
- if (error == -1)
- continue;
- len = strlen(dname);
- if (len == strlen(IICBUS_DEVNAME) &&
- strncasecmp(dname, IICBUS_DEVNAME, len) == 0) {
- iicbusnode = child;
- break;
- }
- }
- if (iicbusnode == 0)
- goto attach_end;
-
- /* Attach child devices onto iicbus. */
- for (child = OF_child(iicbusnode); child != 0; child = OF_peer(child)) {
- /* Get slave address. */
- error = OF_getprop(child, "i2c-address", &paddr, sizeof(paddr));
- if (error == -1)
- error = OF_getprop(child, "reg", &paddr, sizeof(paddr));
- if (error == -1)
- continue;
-
- /* Get device driver name. */
- len = OF_getproplen(child, "model");
- if (len <= 0 || len > sizeof(dname) - 1)
- continue;
- OF_getprop(child, "model", &dname, len);
- dname[len + 1] = '\0';
-
- if (bootverbose)
- device_printf(dev, "adding a device %s at %d.\n",
- dname, fdt32_to_cpu(paddr));
- childdev = BUS_ADD_CHILD(sc->iicbus, 0, dname, -1);
- devi = IICBUS_IVAR(childdev);
- devi->addr = fdt32_to_cpu(paddr);
- }
-
-attach_end:
- bus_generic_attach(sc->iicbus);
-
- return (0);
-}
-
-static int
-mv_twsi_detach(device_t dev)
-{
- struct mv_twsi_softc *sc;
- int rv;
-
- sc = device_get_softc(dev);
-
- if ((rv = bus_generic_detach(dev)) != 0)
- return (rv);
-
- if (sc->iicbus != NULL)
- if ((rv = device_delete_child(dev, sc->iicbus)) != 0)
- return (rv);
-
- bus_release_resources(dev, res_spec, sc->res);
-
- mtx_destroy(&sc->mutex);
- return (0);
-}
-
-/*
- * Only slave mode supported, disregard [old]addr
- */
-static int
-mv_twsi_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
-{
- struct mv_twsi_softc *sc;
- uint32_t param;
-
- sc = device_get_softc(dev);
-
- switch (speed) {
- case IIC_SLOW:
- case IIC_FAST:
- param = baud_rate[speed].param;
- break;
- case IIC_FASTEST:
- case IIC_UNKNOWN:
- default:
- param = baud_rate[IIC_FAST].param;
- break;
- }
-
- mtx_lock(&sc->mutex);
- TWSI_WRITE(sc, TWSI_SOFT_RESET, 0x0);
- DELAY(2000);
- TWSI_WRITE(sc, TWSI_BAUD_RATE, param);
- TWSI_WRITE(sc, TWSI_CONTROL, TWSI_CONTROL_TWSIEN | TWSI_CONTROL_ACK);
- DELAY(1000);
- mtx_unlock(&sc->mutex);
-
- return (0);
-}
-
-/*
- * timeout is given in us
- */
-static int
-mv_twsi_repeated_start(device_t dev, u_char slave, int timeout)
-{
- struct mv_twsi_softc *sc;
- int rv;
-
- sc = device_get_softc(dev);
-
- mtx_lock(&sc->mutex);
- rv = twsi_locked_start(dev, sc, TWSI_STATUS_RPTD_START, slave,
- timeout);
- mtx_unlock(&sc->mutex);
-
- if (rv) {
- mv_twsi_stop(dev);
- return (rv);
- } else
- return (IIC_NOERR);
-}
-
-/*
- * timeout is given in us
- */
-static int
-mv_twsi_start(device_t dev, u_char slave, int timeout)
-{
- struct mv_twsi_softc *sc;
- int rv;
-
- sc = device_get_softc(dev);
-
- mtx_lock(&sc->mutex);
- rv = twsi_locked_start(dev, sc, TWSI_STATUS_START, slave, timeout);
- mtx_unlock(&sc->mutex);
-
- if (rv) {
- mv_twsi_stop(dev);
- return (rv);
- } else
- return (IIC_NOERR);
-}
-
-static int
-mv_twsi_stop(device_t dev)
-{
- struct mv_twsi_softc *sc;
-
- sc = device_get_softc(dev);
-
- mtx_lock(&sc->mutex);
- twsi_control_set(sc, TWSI_CONTROL_STOP);
- DELAY(1000);
- twsi_clear_iflg(sc);
- mtx_unlock(&sc->mutex);
-
- return (IIC_NOERR);
-}
-
-static int
-mv_twsi_read(device_t dev, char *buf, int len, int *read, int last, int delay)
-{
- struct mv_twsi_softc *sc;
- uint32_t status;
- int last_byte, rv;
-
- sc = device_get_softc(dev);
-
- mtx_lock(&sc->mutex);
- *read = 0;
- while (*read < len) {
- /*
- * Check if we are reading last byte of the last buffer,
- * do not send ACK then, per I2C specs
- */
- last_byte = ((*read == len - 1) && last) ? 1 : 0;
- if (last_byte)
- twsi_control_clear(sc, TWSI_CONTROL_ACK);
- else
- twsi_control_set(sc, TWSI_CONTROL_ACK);
-
- DELAY (1000);
- twsi_clear_iflg(sc);
-
- if (twsi_poll_ctrl(sc, delay, TWSI_CONTROL_IFLG)) {
- debugf("timeout reading data\n");
- rv = IIC_ETIMEOUT;
- goto out;
- }
-
- status = TWSI_READ(sc, TWSI_STATUS);
- if (status != (last_byte ?
- TWSI_STATUS_DATA_RD_NOACK : TWSI_STATUS_DATA_RD_ACK)) {
- debugf("wrong status (%02x) while reading\n", status);
- rv = IIC_ESTATUS;
- goto out;
- }
-
- *buf++ = TWSI_READ(sc, TWSI_DATA);
- (*read)++;
- }
- rv = IIC_NOERR;
-out:
- mtx_unlock(&sc->mutex);
- return (rv);
-}
-
-static int
-mv_twsi_write(device_t dev, const char *buf, int len, int *sent, int timeout)
-{
- struct mv_twsi_softc *sc;
- uint32_t status;
- int rv;
-
- sc = device_get_softc(dev);
-
- mtx_lock(&sc->mutex);
- *sent = 0;
- while (*sent < len) {
- TWSI_WRITE(sc, TWSI_DATA, *buf++);
-
- twsi_clear_iflg(sc);
- if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
- debugf("timeout writing data\n");
- rv = IIC_ETIMEOUT;
- goto out;
- }
-
- status = TWSI_READ(sc, TWSI_STATUS);
- if (status != TWSI_STATUS_DATA_WR_ACK) {
- debugf("wrong status (%02x) while writing\n", status);
- rv = IIC_ESTATUS;
- goto out;
- }
- (*sent)++;
- }
- rv = IIC_NOERR;
-out:
- mtx_unlock(&sc->mutex);
- return (rv);
-}
diff --git a/sys/arm/qemu/virt_common.c b/sys/arm/qemu/virt_common.c
index 0f40724..572fee8 100644
--- a/sys/arm/qemu/virt_common.c
+++ b/sys/arm/qemu/virt_common.c
@@ -41,7 +41,9 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
fdt_pic_decode_t fdt_pic_table[] = {
&gic_decode_fdt,
NULL
};
+#endif
diff --git a/sys/arm/rockchip/rk30xx_common.c b/sys/arm/rockchip/rk30xx_common.c
index eff1824..723c429 100644
--- a/sys/arm/rockchip/rk30xx_common.c
+++ b/sys/arm/rockchip/rk30xx_common.c
@@ -42,6 +42,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
static int
fdt_aintc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
@@ -61,3 +62,4 @@ fdt_pic_decode_t fdt_pic_table[] = {
&fdt_aintc_decode_ic,
NULL
};
+#endif
diff --git a/sys/arm/samsung/exynos/exynos5_common.c b/sys/arm/samsung/exynos/exynos5_common.c
index 658efc4..8818f04 100644
--- a/sys/arm/samsung/exynos/exynos5_common.c
+++ b/sys/arm/samsung/exynos/exynos5_common.c
@@ -53,6 +53,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
static int
fdt_pic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
@@ -71,3 +72,4 @@ fdt_pic_decode_t fdt_pic_table[] = {
&fdt_pic_decode_ic,
NULL
};
+#endif
diff --git a/sys/arm/ti/omap4/files.omap4 b/sys/arm/ti/omap4/files.omap4
index 36e41fc..1f331fc 100644
--- a/sys/arm/ti/omap4/files.omap4
+++ b/sys/arm/ti/omap4/files.omap4
@@ -12,6 +12,7 @@ arm/ti/omap4/omap4_l2cache.c optional pl310
arm/ti/omap4/omap4_prcm_clks.c standard
arm/ti/omap4/omap4_scm_padconf.c standard
arm/ti/omap4/omap4_mp.c optional smp
+arm/ti/omap4/omap4_wugen.c standard
arm/ti/twl/twl.c optional twl
arm/ti/twl/twl_vreg.c optional twl twl_vreg
diff --git a/sys/arm/ti/omap4/omap4_wugen.c b/sys/arm/ti/omap4/omap4_wugen.c
new file mode 100644
index 0000000..2b24eaf
--- /dev/null
+++ b/sys/arm/ti/omap4/omap4_wugen.c
@@ -0,0 +1,228 @@
+/*-
+ * Copyright (c) 2016 Svatopluk Kraus
+ * Copyright (c) 2016 Michal Meloun
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/systm.h>
+
+#include <machine/fdt.h>
+#include <machine/intr.h>
+#include <machine/resource.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "pic_if.h"
+
+static struct ofw_compat_data compat_data[] = {
+ {"ti,omap4-wugen-mpu", 1},
+ {NULL, 0}
+};
+
+struct omap4_wugen_sc {
+ device_t sc_dev;
+ struct resource *sc_mem_res;
+ device_t sc_parent;
+};
+
+static int
+omap4_wugen_register(device_t dev, struct intr_irqsrc *isrc,
+ boolean_t *is_percpu)
+{
+ struct omap4_wugen_sc *sc = device_get_softc(dev);
+
+ return (PIC_REGISTER(sc->sc_parent, isrc, is_percpu));
+}
+
+static int
+omap4_wugen_unregister(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct omap4_wugen_sc *sc = device_get_softc(dev);
+
+ return (PIC_UNREGISTER(sc->sc_parent, isrc));
+}
+
+static void
+omap4_wugen_enable_source(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct omap4_wugen_sc *sc = device_get_softc(dev);
+
+ PIC_ENABLE_SOURCE(sc->sc_parent, isrc);
+}
+
+static void
+omap4_wugen_disable_source(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct omap4_wugen_sc *sc = device_get_softc(dev);
+
+ PIC_DISABLE_SOURCE(sc->sc_parent, isrc);
+}
+
+static void
+omap4_wugen_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct omap4_wugen_sc *sc = device_get_softc(dev);
+
+ PIC_ENABLE_INTR(sc->sc_parent, isrc);
+}
+
+static void
+omap4_wugen_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct omap4_wugen_sc *sc = device_get_softc(dev);
+
+ PIC_PRE_ITHREAD(sc->sc_parent, isrc);
+}
+
+
+static void
+omap4_wugen_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct omap4_wugen_sc *sc = device_get_softc(dev);
+
+ PIC_POST_ITHREAD(sc->sc_parent, isrc);
+}
+
+static void
+omap4_wugen_post_filter(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct omap4_wugen_sc *sc = device_get_softc(dev);
+
+ PIC_POST_FILTER(sc->sc_parent, isrc);
+}
+
+#ifdef SMP
+static int
+omap4_wugen_bind(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct omap4_wugen_sc *sc = device_get_softc(dev);
+
+ return (PIC_BIND(sc->sc_parent, isrc));
+}
+#endif
+
+static int
+omap4_wugen_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+omap4_wugen_detach(device_t dev)
+{
+ struct omap4_wugen_sc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->sc_mem_res != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ sc->sc_mem_res = NULL;
+ }
+ return (0);
+}
+
+static int
+omap4_wugen_attach(device_t dev)
+{
+ struct omap4_wugen_sc *sc;
+ phandle_t node;
+ phandle_t parent_xref;
+ int rid, rv;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ node = ofw_bus_get_node(dev);
+
+ rv = OF_getencprop(node, "interrupt-parent", &parent_xref,
+ sizeof(parent_xref));
+ if (rv <= 0) {
+ device_printf(dev, "can't read parent node property\n");
+ goto fail;
+ }
+ sc->sc_parent = OF_device_from_xref(parent_xref);
+ if (sc->sc_parent == NULL) {
+ device_printf(dev, "can't find parent controller\n");
+ goto fail;
+ }
+
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->sc_mem_res == NULL) {
+ device_printf(dev, "can't allocate resources\n");
+ return (ENXIO);
+ }
+
+ if (intr_pic_register(dev, OF_xref_from_node(node)) != 0) {
+ device_printf(dev, "can't register PIC\n");
+ goto fail;
+ }
+ return (0);
+
+fail:
+ omap4_wugen_detach(dev);
+ return (ENXIO);
+}
+
+static device_method_t omap4_wugen_methods[] = {
+ DEVMETHOD(device_probe, omap4_wugen_probe),
+ DEVMETHOD(device_attach, omap4_wugen_attach),
+ DEVMETHOD(device_detach, omap4_wugen_detach),
+
+ /* Interrupt controller interface */
+ DEVMETHOD(pic_register, omap4_wugen_register),
+ DEVMETHOD(pic_unregister, omap4_wugen_unregister),
+ DEVMETHOD(pic_enable_source, omap4_wugen_enable_source),
+ DEVMETHOD(pic_disable_source, omap4_wugen_disable_source),
+ DEVMETHOD(pic_enable_intr, omap4_wugen_enable_intr),
+ DEVMETHOD(pic_pre_ithread, omap4_wugen_pre_ithread),
+ DEVMETHOD(pic_post_ithread, omap4_wugen_post_ithread),
+ DEVMETHOD(pic_post_filter, omap4_wugen_post_filter),
+#ifdef SMP
+ DEVMETHOD(pic_bind, omap4_wugen_bind),
+#endif
+ DEVMETHOD_END
+};
+devclass_t omap4_wugen_devclass;
+DEFINE_CLASS_0(omap4_wugen, omap4_wugen_driver, omap4_wugen_methods,
+ sizeof(struct omap4_wugen_sc));
+EARLY_DRIVER_MODULE(omap4_wugen, simplebus, omap4_wugen_driver,
+ omap4_wugen_devclass, NULL, NULL,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE + 1);
diff --git a/sys/arm/versatile/versatile_common.c b/sys/arm/versatile/versatile_common.c
index bcb504a..c47c298 100644
--- a/sys/arm/versatile/versatile_common.c
+++ b/sys/arm/versatile/versatile_common.c
@@ -50,6 +50,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
static int
fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
@@ -70,3 +71,4 @@ fdt_pic_decode_t fdt_pic_table[] = {
&fdt_intc_decode_ic,
NULL
};
+#endif
diff --git a/sys/arm/xilinx/zedboard/files.zedboard b/sys/arm/xilinx/zedboard/files.zedboard
deleted file mode 100644
index 8a1af16..0000000
--- a/sys/arm/xilinx/zedboard/files.zedboard
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# files.zedboard
-#
-# $FreeBSD$
-
-# We'll need board specific files once we start implementing drivers
-# for Zedboard PL peripherals such as HDMI, VGA, or Audio Codecs. For
-# now, nothing is needed.
-#
diff --git a/sys/arm/xilinx/zedboard/std.zedboard b/sys/arm/xilinx/zedboard/std.zedboard
deleted file mode 100644
index 86f04f1..0000000
--- a/sys/arm/xilinx/zedboard/std.zedboard
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# std.zedboard
-#
-# $FreeBSD$
-
-include "../xilinx/std.zynq7"
-files "../xilinx/zedboard/files.zedboard"
-
diff --git a/sys/arm/xilinx/zy7_machdep.c b/sys/arm/xilinx/zy7_machdep.c
index f7080dc..4b43683 100644
--- a/sys/arm/xilinx/zy7_machdep.c
+++ b/sys/arm/xilinx/zy7_machdep.c
@@ -98,6 +98,7 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
+#ifndef ARM_INTRNG
static int
fdt_gic_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
@@ -117,7 +118,7 @@ fdt_pic_decode_t fdt_pic_table[] = {
&fdt_gic_decode_ic,
NULL
};
-
+#endif
struct arm32_dma_range *
bus_dma_get_range(void)
diff --git a/sys/arm64/arm64/disassem.c b/sys/arm64/arm64/disassem.c
index 46b6228..ce0bf76 100644
--- a/sys/arm64/arm64/disassem.c
+++ b/sys/arm64/arm64/disassem.c
@@ -38,6 +38,16 @@ __FBSDID("$FreeBSD$");
#define ARM64_MAX_TOKEN_LEN 8
#define ARM64_MAX_TOKEN_CNT 10
+#define ARM_INSN_SIZE_OFFSET 30
+#define ARM_INSN_SIZE_MASK 0x3
+
+/* Special options for instruction printing */
+#define OP_SIGN_EXT (1UL << 0) /* Sign-extend immediate value */
+#define OP_LITERAL (1UL << 1) /* Use literal (memory offset) */
+#define OP_MULT_4 (1UL << 2) /* Multiply immediate by 4 */
+#define OP_SF32 (1UL << 3) /* Force 32-bit access */
+#define OP_SF_INV (1UL << 6) /* SF is inverted (1 means 32 bit access) */
+
static const char *w_reg[] = {
"w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7",
"w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15",
@@ -74,6 +84,10 @@ struct arm64_insn_token {
enum arm64_format_type {
TYPE_01, /* OP <RD>, <RN>, <RM>{, <shift [LSL, LSR, ASR]> #<imm>} SF32/64
OP <RD>, <RN>, #<imm>{, <shift [0, 12]>} SF32/64 */
+ TYPE_02, /* OP <RT>, [<RN>, #<imm>]{!}] SF32/64
+ OP <RT>, [<RN>], #<imm>{!} SF32/64
+ OP <RT>, <RN>, <RM> {, EXTEND AMOUNT } */
+ TYPE_03, /* OP <RT>, #imm SF32/64 */
};
/*
@@ -112,12 +126,57 @@ struct arm64_insn {
* SHIFT - type of shift (instruction dependent)
* IMM - immediate value
* Rx - register number
+ * OPTION - command specific options
+ * SCALE - scaling of immediate value
*/
static struct arm64_insn arm64_i[] = {
- { "add", "SF(1)|0001011|SHIFT(2)|0|RM(5)|IMM(6)|RN(5)|RD(5)", TYPE_01, 0 },
- { "mov", "SF(1)|001000100000000000000|RN(5)|RD(5)", TYPE_01, 0 },
- { "add", "SF(1)|0010001|SHIFT(2)|IMM(12)|RN(5)|RD(5)", TYPE_01, 0 },
- { NULL, NULL }
+ { "add", "SF(1)|0001011|SHIFT(2)|0|RM(5)|IMM(6)|RN(5)|RD(5)",
+ TYPE_01, 0 },
+ { "mov", "SF(1)|001000100000000000000|RN(5)|RD(5)",
+ TYPE_01, 0 },
+ { "add", "SF(1)|0010001|SHIFT(2)|IMM(12)|RN(5)|RD(5)",
+ TYPE_01, 0 },
+ { "ldr", "1|SF(1)|111000010|IMM(9)|OPTION(2)|RN(5)|RT(5)",
+ TYPE_02, OP_SIGN_EXT }, /* ldr immediate post/pre index */
+ { "ldr", "1|SF(1)|11100101|IMM(12)|RN(5)|RT(5)",
+ TYPE_02, 0 }, /* ldr immediate unsigned */
+ { "ldr", "1|SF(1)|111000011|RM(5)|OPTION(3)|SCALE(1)|10|RN(5)|RT(5)",
+ TYPE_02, 0 }, /* ldr register */
+ { "ldr", "0|SF(1)|011000|IMM(19)|RT(5)",
+ TYPE_03, OP_SIGN_EXT | OP_LITERAL | OP_MULT_4 }, /* ldr literal */
+ { "ldrb", "00|111000010|IMM(9)|OPTION(2)|RN(5)|RT(5)",
+ TYPE_02, OP_SIGN_EXT | OP_SF32 }, /* ldrb immediate post/pre index */
+ { "ldrb", "00|11100101|IMM(12)|RN(5)|RT(5)",
+ TYPE_02, OP_SF32 }, /* ldrb immediate unsigned */
+ { "ldrb", "00|111000011|RM(5)|OPTION(3)|SCALE(1)|10|RN(5)|RT(5)",
+ TYPE_02, OP_SF32 }, /* ldrb register */
+ { "ldrh", "01|111000010|IMM(9)|OPTION(2)|RN(5)|RT(5)", TYPE_02,
+ OP_SIGN_EXT | OP_SF32 }, /* ldrh immediate post/pre index */
+ { "ldrh", "01|11100101|IMM(12)|RN(5)|RT(5)",
+ TYPE_02, OP_SF32 }, /* ldrh immediate unsigned */
+ { "ldrh", "01|111000011|RM(5)|OPTION(3)|SCALE(1)|10|RN(5)|RT(5)",
+ TYPE_02, OP_SF32 }, /* ldrh register */
+ { "ldrsb", "001110001|SF(1)|0|IMM(9)|OPTION(2)|RN(5)|RT(5)",
+ TYPE_02, OP_SIGN_EXT | OP_SF_INV }, /* ldrsb immediate post/pre index */
+ { "ldrsb", "001110011|SF(1)|IMM(12)|RN(5)|RT(5)",\
+ TYPE_02, OP_SF_INV}, /* ldrsb immediate unsigned */
+ { "ldrsb", "001110001|SF(1)|1|RM(5)|OPTION(3)|SCALE(1)|10|RN(5)|RT(5)",
+ TYPE_02, OP_SF_INV }, /* ldrsb register */
+ { "ldrsh", "011110001|SF(1)|0|IMM(9)|OPTION(2)|RN(5)|RT(5)",
+ TYPE_02, OP_SIGN_EXT | OP_SF_INV }, /* ldrsh immediate post/pre index */
+ { "ldrsh", "011110011|SF(1)|IMM(12)|RN(5)|RT(5)",
+ TYPE_02, OP_SF_INV}, /* ldrsh immediate unsigned */
+ { "ldrsh", "011110001|SF(1)|1|RM(5)|OPTION(3)|SCALE(1)|10|RN(5)|RT(5)",
+ TYPE_02, OP_SF_INV }, /* ldrsh register */
+ { "ldrsw", "10111000100|IMM(9)|OPTION(2)|RN(5)|RT(5)",
+ TYPE_02, OP_SIGN_EXT }, /* ldrsw immediate post/pre index */
+ { "ldrsw", "1011100110|IMM(12)|RN(5)|RT(5)",
+ TYPE_02, 0 }, /* ldrsw immediate unsigned */
+ { "ldrsw", "10111000101|RM(5)|OPTION(3)|SCALE(1)|10|RN(5)|RT(5)",
+ TYPE_02, 0 }, /* ldrsw register */
+ { "ldrsw", "10011000|IMM(19)|RT(5)",
+ TYPE_03, OP_SIGN_EXT | OP_LITERAL | OP_MULT_4 }, /* ldr literal */
+ { NULL, NULL }
};
static void
@@ -240,6 +299,29 @@ arm64_disasm_read_token(struct arm64_insn *insn, u_int opcode,
return (EINVAL);
}
+static int
+arm64_disasm_read_token_sign_ext(struct arm64_insn *insn, u_int opcode,
+ const char *token, int *val)
+{
+ int i;
+ int msk;
+
+ for (i = 0; i < ARM64_MAX_TOKEN_CNT; i++) {
+ if (strcmp(insn->tokens[i].name, token) == 0) {
+ msk = (1 << insn->tokens[i].len) - 1;
+ *val = ((opcode >> insn->tokens[i].pos) & msk);
+
+ /* If last bit is 1, sign-extend the value */
+ if (*val & (1 << (insn->tokens[i].len - 1)))
+ *val |= ~msk;
+
+ return (0);
+ }
+ }
+
+ return (EINVAL);
+}
+
static const char *
arm64_reg(int b64, int num)
{
@@ -257,11 +339,17 @@ disasm(const struct disasm_interface *di, vm_offset_t loc, int altfmt)
uint32_t insn;
int matchp;
int ret;
- int shift, rm, rd, rn, imm, sf;
+ int shift, rm, rt, rd, rn, imm, sf, idx, option, scale, amount;
+ int sign_ext;
int rm_absent;
+ /* Indicate if immediate should be outside or inside brackets */
+ int inside;
+ /* Print exclamation mark if pre-incremented */
+ int pre;
/* Initialize defaults, all are 0 except SF indicating 64bit access */
- shift = rd = rm = rn = imm = 0;
+ shift = rd = rm = rn = imm = idx = option = amount = scale = 0;
+ sign_ext = 0;
sf = 1;
matchp = 0;
@@ -278,14 +366,33 @@ disasm(const struct disasm_interface *di, vm_offset_t loc, int altfmt)
if (matchp == 0)
goto undefined;
+ /* Global options */
+ if (i_ptr->special_ops & OP_SF32)
+ sf = 0;
+
+ /* Global optional tokens */
+ arm64_disasm_read_token(i_ptr, insn, "SF", &sf);
+ if (i_ptr->special_ops & OP_SF_INV)
+ sf = 1 - sf;
+ if (arm64_disasm_read_token(i_ptr, insn, "SIGN", &sign_ext) == 0)
+ sign_ext = 1 - sign_ext;
+ if (i_ptr->special_ops & OP_SIGN_EXT)
+ sign_ext = 1;
+ if (sign_ext != 0)
+ arm64_disasm_read_token_sign_ext(i_ptr, insn, "IMM", &imm);
+ else
+ arm64_disasm_read_token(i_ptr, insn, "IMM", &imm);
+ if (i_ptr->special_ops & OP_MULT_4)
+ imm <<= 2;
+
+ /* Print opcode by type */
switch (i_ptr->type) {
case TYPE_01:
/* OP <RD>, <RN>, <RM>{, <shift [LSL, LSR, ASR]> #<imm>} SF32/64
OP <RD>, <RN>, #<imm>{, <shift [0, 12]>} SF32/64 */
/* Mandatory tokens */
- ret = arm64_disasm_read_token(i_ptr, insn, "SF", &sf);
- ret |= arm64_disasm_read_token(i_ptr, insn, "RD", &rd);
+ ret = arm64_disasm_read_token(i_ptr, insn, "RD", &rd);
ret |= arm64_disasm_read_token(i_ptr, insn, "RN", &rn);
if (ret != 0) {
printf("ERROR: Missing mandatory token for op %s type %d\n",
@@ -294,7 +401,6 @@ disasm(const struct disasm_interface *di, vm_offset_t loc, int altfmt)
}
/* Optional tokens */
- arm64_disasm_read_token(i_ptr, insn, "IMM", &imm);
arm64_disasm_read_token(i_ptr, insn, "SHIFT", &shift);
rm_absent = arm64_disasm_read_token(i_ptr, insn, "RM", &rm);
@@ -313,6 +419,115 @@ disasm(const struct disasm_interface *di, vm_offset_t loc, int altfmt)
di->di_printf(" LSL #12");
}
break;
+ case TYPE_02:
+ /* OP <RT>, [<RN>, #<imm>]{!}] SF32/64
+ OP <RT>, [<RN>], #<imm>{!} SF32/64
+ OP <RT>, <RN>, <RM> {, EXTEND AMOUNT } */
+
+ /* Mandatory tokens */
+ ret = arm64_disasm_read_token(i_ptr, insn, "RT", &rt);
+ ret |= arm64_disasm_read_token(i_ptr, insn, "RN", &rn);
+ if (ret != 0) {
+ printf("ERROR: Missing mandatory token for op %s type %d\n",
+ i_ptr->name, i_ptr->type);
+ goto undefined;
+ }
+
+ /* Optional tokens */
+ arm64_disasm_read_token(i_ptr, insn, "OPTION", &option);
+ arm64_disasm_read_token(i_ptr, insn, "SCALE", &scale);
+ rm_absent = arm64_disasm_read_token(i_ptr, insn, "RM", &rm);
+
+ if (rm_absent) {
+ /*
+ * In unsigned operation, shift immediate value
+ * and reset options to default.
+ */
+ if (sign_ext == 0) {
+ imm = imm << ((insn >> ARM_INSN_SIZE_OFFSET) &
+ ARM_INSN_SIZE_MASK);
+ option = 0;
+ }
+ switch (option) {
+ case 0x0:
+ pre = 0;
+ inside = 1;
+ break;
+ case 0x1:
+ pre = 0;
+ inside = 0;
+ break;
+ case 0x2:
+ default:
+ pre = 1;
+ inside = 1;
+ break;
+ }
+
+ di->di_printf("%s\t%s, ", i_ptr->name, arm64_reg(sf, rt));
+ if (inside != 0) {
+ di->di_printf("[%s", arm64_reg(1, rn));
+ if (imm != 0)
+ di->di_printf(", #%d", imm);
+ di->di_printf("]");
+ } else {
+ di->di_printf("[%s]", arm64_reg(1, rn));
+ if (imm != 0)
+ di->di_printf(", #%d", imm);
+ }
+ if (pre != 0)
+ di->di_printf("!");
+ } else {
+ /* Last bit of option field determines 32/64 bit offset */
+ di->di_printf("%s\t%s, [%s, %s", i_ptr->name,
+ arm64_reg(sf, rt), arm64_reg(1, rn),
+ arm64_reg(option & 1, rm));
+
+ /* Calculate amount, it's op(31:30) */
+ amount = (insn >> ARM_INSN_SIZE_OFFSET) &
+ ARM_INSN_SIZE_MASK;
+
+ switch (option) {
+ case 0x2:
+ di->di_printf(", uxtw #%d", amount);
+ break;
+ case 0x3:
+ if (scale != 0)
+ di->di_printf(", lsl #%d", amount);
+ break;
+ case 0x6:
+ di->di_printf(", sxtw #%d", amount);
+ break;
+ case 0x7:
+ di->di_printf(", sxts #%d", amount);
+ break;
+ default:
+ di->di_printf(", RSVD");
+ break;
+ }
+ di->di_printf("]");
+ }
+
+ break;
+
+ case TYPE_03:
+ /* OP <RT>, #imm SF32/64 */
+
+ /* Mandatory tokens */
+ ret = arm64_disasm_read_token(i_ptr, insn, "RT", &rt);
+ if (ret != 0) {
+ printf("ERROR: Missing mandatory token for op %s type %d\n",
+ i_ptr->name, i_ptr->type);
+ goto undefined;
+ }
+
+ di->di_printf("%s\t%s, ", i_ptr->name, arm64_reg(sf, rt));
+ if (i_ptr->special_ops & OP_LITERAL)
+ di->di_printf("0x%lx", loc + imm);
+ else
+ di->di_printf("#%d", imm);
+
+ break;
default:
goto undefined;
}
diff --git a/sys/arm64/arm64/gic.c b/sys/arm64/arm64/gic.c
index 823dd61..0a13b12 100644
--- a/sys/arm64/arm64/gic.c
+++ b/sys/arm64/arm64/gic.c
@@ -303,29 +303,6 @@ gic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi)
gic_d_write_4(sc, GICD_SGIR(0), val | ipi);
}
-
-static int
-arm_gic_ipi_read(device_t dev, int i)
-{
-
- if (i != -1) {
- /*
- * The intr code will automagically give the frame pointer
- * if the interrupt argument is 0.
- */
- if ((unsigned int)i > 16)
- return (0);
- return (i);
- }
-
- return (0x3ff);
-}
-
-static void
-arm_gic_ipi_clear(device_t dev, int ipi)
-{
- /* no-op */
-}
#endif
static device_method_t arm_gic_methods[] = {
diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c
index b74a56a..d8434cf 100644
--- a/sys/arm64/arm64/gic_v3.c
+++ b/sys/arm64/arm64/gic_v3.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include "gic_v3_var.h"
/* Device and PIC methods */
+static int gic_v3_bind(device_t, u_int, u_int);
static void gic_v3_dispatch(device_t, struct trapframe *);
static void gic_v3_eoi(device_t, u_int);
static void gic_v3_mask_irq(device_t, u_int);
@@ -72,6 +73,7 @@ static device_method_t gic_v3_methods[] = {
DEVMETHOD(device_detach, gic_v3_detach),
/* PIC interface */
+ DEVMETHOD(pic_bind, gic_v3_bind),
DEVMETHOD(pic_dispatch, gic_v3_dispatch),
DEVMETHOD(pic_eoi, gic_v3_eoi),
DEVMETHOD(pic_mask, gic_v3_mask_irq),
@@ -244,6 +246,28 @@ gic_v3_detach(device_t dev)
/*
* PIC interface.
*/
+
+static int
+gic_v3_bind(device_t dev, u_int irq, u_int cpuid)
+{
+ uint64_t aff;
+ struct gic_v3_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ if (irq <= GIC_LAST_PPI) {
+ /* Can't bind PPI to another CPU but it's not an error */
+ return (0);
+ } else if (irq >= GIC_FIRST_SPI && irq <= GIC_LAST_SPI) {
+ aff = CPU_AFFINITY(cpuid);
+ gic_d_write(sc, 4, GICD_IROUTER(irq), aff);
+ return (0);
+ } else if (irq >= GIC_FIRST_LPI)
+ return (lpi_migrate(dev, irq, cpuid));
+
+ return (EINVAL);
+}
+
static void
gic_v3_dispatch(device_t dev, struct trapframe *frame)
{
@@ -412,14 +436,15 @@ gic_v3_ipi_send(device_t dev, cpuset_t cpuset, u_int ipi)
}
}
if (tlist) {
- KASSERT((tlist & ~GICI_SGI_TLIST_MASK) == 0,
+ KASSERT((tlist & ~ICC_SGI1R_EL1_TL_MASK) == 0,
("Target list too long for GICv3 IPI"));
/* Send SGI to CPUs in target list */
val = tlist;
- val |= (uint64_t)CPU_AFF3(aff) << GICI_SGI_AFF3_SHIFT;
- val |= (uint64_t)CPU_AFF2(aff) << GICI_SGI_AFF2_SHIFT;
- val |= (uint64_t)CPU_AFF1(aff) << GICI_SGI_AFF1_SHIFT;
- val |= (uint64_t)(ipi & GICI_SGI_IPI_MASK) << GICI_SGI_IPI_SHIFT;
+ val |= (uint64_t)CPU_AFF3(aff) << ICC_SGI1R_EL1_AFF3_SHIFT;
+ val |= (uint64_t)CPU_AFF2(aff) << ICC_SGI1R_EL1_AFF2_SHIFT;
+ val |= (uint64_t)CPU_AFF1(aff) << ICC_SGI1R_EL1_AFF1_SHIFT;
+ val |= (uint64_t)(ipi & ICC_SGI1R_EL1_SGIID_MASK) <<
+ ICC_SGI1R_EL1_SGIID_SHIFT;
gic_icc_write(SGI1R, val);
}
}
@@ -564,7 +589,7 @@ gic_v3_dist_init(struct gic_v3_softc *sc)
/*
* 4. Route all interrupts to boot CPU.
*/
- aff = CPU_AFFINITY(PCPU_GET(cpuid));
+ aff = CPU_AFFINITY(0);
for (i = GIC_FIRST_SPI; i < sc->gic_nirqs; i++)
gic_d_write(sc, 4, GICD_IROUTER(i), aff);
diff --git a/sys/arm64/arm64/gic_v3_its.c b/sys/arm64/arm64/gic_v3_its.c
index 7daeabe..7a547c1 100644
--- a/sys/arm64/arm64/gic_v3_its.c
+++ b/sys/arm64/arm64/gic_v3_its.c
@@ -92,9 +92,13 @@ static void its_free_tables(struct gic_v3_its_softc *);
static void its_init_commandq(struct gic_v3_its_softc *);
static void its_init_cpu_collection(struct gic_v3_its_softc *);
static uint32_t its_get_devid(device_t);
+static struct its_dev * its_device_find_locked(struct gic_v3_its_softc *,
+ device_t, uint32_t);
static int its_cmd_send(struct gic_v3_its_softc *, struct its_cmd_desc *);
+static void its_cmd_movi(struct gic_v3_its_softc *, struct its_dev *,
+ struct its_col *, uint32_t);
static void its_cmd_mapc(struct gic_v3_its_softc *, struct its_col *, uint8_t);
static void its_cmd_mapvi(struct gic_v3_its_softc *, struct its_dev *, uint32_t,
uint32_t);
@@ -197,9 +201,9 @@ gic_v3_its_attach(device_t dev)
* Initialize sleep & spin mutex for ITS
*/
/* Protects ITS device list and assigned LPIs bitmaps. */
- mtx_init(&sc->its_mtx, "ITS sleep lock", NULL, MTX_DEF);
+ mtx_init(&sc->its_dev_lock, "ITS dev lock", NULL, MTX_SPIN);
/* Protects access to ITS command circular buffer. */
- mtx_init(&sc->its_spin_mtx, "ITS spin lock", NULL, MTX_SPIN);
+ mtx_init(&sc->its_cmd_lock, "ITS cmd lock", NULL, MTX_SPIN);
rid = 0;
sc->its_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
@@ -846,18 +850,28 @@ static int
lpi_alloc_chunk(struct gic_v3_its_softc *sc, struct lpi_chunk *lpic,
u_int nvecs)
{
+ u_int *col_ids;
int fclr; /* First cleared bit */
uint8_t *bitmap;
size_t nb, i;
+ col_ids = malloc(sizeof(*col_ids) * nvecs, M_GIC_V3_ITS,
+ (M_NOWAIT | M_ZERO));
+ if (col_ids == NULL)
+ return (ENOMEM);
+
+ mtx_lock_spin(&sc->its_dev_lock);
bitmap = (uint8_t *)sc->its_lpi_bitmap;
fclr = 0;
retry:
/* Check other bits - sloooow */
for (i = 0, nb = fclr; i < nvecs; i++, nb++) {
- if (nb > sc->its_lpi_maxid)
+ if (nb > sc->its_lpi_maxid) {
+ mtx_unlock_spin(&sc->its_dev_lock);
+ free(col_ids, M_GIC_V3_ITS);
return (EINVAL);
+ }
if (isset(bitmap, nb)) {
/* To little free bits in this area. Move on. */
@@ -870,6 +884,15 @@ retry:
lpic->lpi_base = fclr + GIC_FIRST_LPI;
lpic->lpi_num = nvecs;
lpic->lpi_free = lpic->lpi_num;
+ lpic->lpi_col_ids = col_ids;
+ for (i = 0; i < lpic->lpi_num; i++) {
+ /*
+ * Initially all interrupts go to CPU0 but can be moved
+ * to another CPU by bus_bind_intr() or interrupts shuffling.
+ */
+ lpic->lpi_col_ids[i] = 0;
+ }
+ mtx_unlock_spin(&sc->its_dev_lock);
return (0);
}
@@ -885,6 +908,7 @@ lpi_free_chunk(struct gic_v3_its_softc *sc, struct lpi_chunk *lpic)
KASSERT((lpic->lpi_free == lpic->lpi_num),
("Trying to free LPI chunk that is still in use.\n"));
+ mtx_lock_spin(&sc->its_dev_lock);
/* First bit of this chunk in a global bitmap */
start = lpic->lpi_base - GIC_FIRST_LPI;
/* and last bit of this chunk... */
@@ -892,6 +916,10 @@ lpi_free_chunk(struct gic_v3_its_softc *sc, struct lpi_chunk *lpic)
/* Finally free this chunk */
bit_nclear(bitmap, start, end);
+ mtx_unlock_spin(&sc->its_dev_lock);
+
+ free(lpic->lpi_col_ids, M_GIC_V3_ITS);
+ lpic->lpi_col_ids = NULL;
}
static void
@@ -953,6 +981,32 @@ lpi_xmask_irq(device_t parent, uint32_t irq, boolean_t unmask)
(unmask == TRUE) ? "unmask" : "mask", irq);
}
+int
+lpi_migrate(device_t parent, uint32_t irq, u_int cpuid)
+{
+ struct gic_v3_its_softc *sc;
+ struct its_dev *its_dev;
+ struct its_col *col;
+
+ sc = its_sc;
+ mtx_lock_spin(&sc->its_dev_lock);
+ its_dev = its_device_find_locked(sc, NULL, irq);
+ mtx_unlock_spin(&sc->its_dev_lock);
+ if (its_dev == NULL) {
+ /* Cannot migrate not configured LPI */
+ return (ENXIO);
+ }
+
+ /* Find local device's interrupt identifier */
+ irq = irq - its_dev->lpis.lpi_base;
+ /* Move interrupt to another collection */
+ col = sc->its_cols[cpuid];
+ its_cmd_movi(sc, its_dev, col, irq);
+ its_dev->lpis.lpi_col_ids[irq] = cpuid;
+
+ return (0);
+}
+
void
lpi_unmask_irq(device_t parent, uint32_t irq)
{
@@ -1053,6 +1107,20 @@ cmd_fix_endian(struct its_cmd *cmd)
}
static void
+its_cmd_movi(struct gic_v3_its_softc *sc, struct its_dev *its_dev,
+ struct its_col *col, uint32_t id)
+{
+ struct its_cmd_desc desc;
+
+ desc.cmd_type = ITS_CMD_MOVI;
+ desc.cmd_desc_movi.its_dev = its_dev;
+ desc.cmd_desc_movi.col = col;
+ desc.cmd_desc_movi.id = id;
+
+ its_cmd_send(sc, &desc);
+}
+
+static void
its_cmd_mapc(struct gic_v3_its_softc *sc, struct its_col *col, uint8_t valid)
{
struct its_cmd_desc desc;
@@ -1073,9 +1141,15 @@ its_cmd_mapvi(struct gic_v3_its_softc *sc, struct its_dev *its_dev,
uint32_t id, uint32_t pid)
{
struct its_cmd_desc desc;
+ struct its_col *col;
+ u_int col_id;
+
+ col_id = its_dev->lpis.lpi_col_ids[id];
+ col = sc->its_cols[col_id];
desc.cmd_type = ITS_CMD_MAPVI;
desc.cmd_desc_mapvi.its_dev = its_dev;
+ desc.cmd_desc_mapvi.col = col;
desc.cmd_desc_mapvi.id = id;
desc.cmd_desc_mapvi.pid = pid;
@@ -1083,14 +1157,23 @@ its_cmd_mapvi(struct gic_v3_its_softc *sc, struct its_dev *its_dev,
}
static void __unused
-its_cmd_mapi(struct gic_v3_its_softc *sc, struct its_dev *its_dev,
- uint32_t lpinum)
+its_cmd_mapi(struct gic_v3_its_softc *sc, struct its_dev *its_dev, uint32_t pid)
{
struct its_cmd_desc desc;
+ struct its_col *col;
+ u_int col_id;
+ uint32_t id;
+
+ KASSERT(pid >= its_dev->lpis.lpi_base,
+ ("%s: invalid pid: %d for the ITS device", __func__, pid));
+ id = pid - its_dev->lpis.lpi_base;
+ col_id = its_dev->lpis.lpi_col_ids[id];
+ col = sc->its_cols[col_id];
desc.cmd_type = ITS_CMD_MAPI;
desc.cmd_desc_mapi.its_dev = its_dev;
- desc.cmd_desc_mapi.lpinum = lpinum;
+ desc.cmd_desc_mapi.col = col;
+ desc.cmd_desc_mapi.pid = pid;
its_cmd_send(sc, &desc);
}
@@ -1109,14 +1192,23 @@ its_cmd_mapd(struct gic_v3_its_softc *sc, struct its_dev *its_dev,
}
static void
-its_cmd_inv(struct gic_v3_its_softc *sc, struct its_dev *its_dev,
- uint32_t lpinum)
+its_cmd_inv(struct gic_v3_its_softc *sc, struct its_dev *its_dev, uint32_t pid)
{
struct its_cmd_desc desc;
+ struct its_col *col;
+ u_int col_id;
+ uint32_t id;
+
+ KASSERT(pid >= its_dev->lpis.lpi_base,
+ ("%s: invalid pid: %d for the ITS device", __func__, pid));
+ id = pid - its_dev->lpis.lpi_base;
+ col_id = its_dev->lpis.lpi_col_ids[id];
+ col = sc->its_cols[col_id];
desc.cmd_type = ITS_CMD_INV;
- desc.cmd_desc_inv.lpinum = lpinum - its_dev->lpis.lpi_base;
+ desc.cmd_desc_inv.pid = pid - its_dev->lpis.lpi_base;
desc.cmd_desc_inv.its_dev = its_dev;
+ desc.cmd_desc_inv.col = col;
its_cmd_send(sc, &desc);
}
@@ -1181,7 +1273,7 @@ its_cmd_alloc_locked(struct gic_v3_its_softc *sc)
*/
us_left = 1000000;
- mtx_assert(&sc->its_spin_mtx, MA_OWNED);
+ mtx_assert(&sc->its_cmd_lock, MA_OWNED);
while (its_cmd_queue_full(sc)) {
if (us_left-- == 0) {
/* Timeout while waiting for free command */
@@ -1216,13 +1308,19 @@ its_cmd_prepare(struct its_cmd *cmd, struct its_cmd_desc *desc)
target = ITS_TARGET_NONE;
switch (cmd_type) {
+ case ITS_CMD_MOVI: /* Move interrupt ID to another collection */
+ target = desc->cmd_desc_movi.col->col_target;
+ cmd_format_command(cmd, ITS_CMD_MOVI);
+ cmd_format_id(cmd, desc->cmd_desc_movi.id);
+ cmd_format_col(cmd, desc->cmd_desc_movi.col->col_id);
+ cmd_format_devid(cmd, desc->cmd_desc_movi.its_dev->devid);
+ break;
case ITS_CMD_SYNC: /* Wait for previous commands completion */
target = desc->cmd_desc_sync.col->col_target;
cmd_format_command(cmd, ITS_CMD_SYNC);
cmd_format_target(cmd, target);
break;
case ITS_CMD_MAPD: /* Assign ITT to device */
- target = desc->cmd_desc_mapd.its_dev->col->col_target;
cmd_format_command(cmd, ITS_CMD_MAPD);
cmd_format_itt(cmd, vtophys(desc->cmd_desc_mapd.its_dev->itt));
/*
@@ -1249,25 +1347,25 @@ its_cmd_prepare(struct its_cmd *cmd, struct its_cmd_desc *desc)
cmd_format_target(cmd, target);
break;
case ITS_CMD_MAPVI:
- target = desc->cmd_desc_mapvi.its_dev->col->col_target;
+ target = desc->cmd_desc_mapvi.col->col_target;
cmd_format_command(cmd, ITS_CMD_MAPVI);
cmd_format_devid(cmd, desc->cmd_desc_mapvi.its_dev->devid);
cmd_format_id(cmd, desc->cmd_desc_mapvi.id);
cmd_format_pid(cmd, desc->cmd_desc_mapvi.pid);
- cmd_format_col(cmd, desc->cmd_desc_mapvi.its_dev->col->col_id);
+ cmd_format_col(cmd, desc->cmd_desc_mapvi.col->col_id);
break;
case ITS_CMD_MAPI:
- target = desc->cmd_desc_mapi.its_dev->col->col_target;
+ target = desc->cmd_desc_mapi.col->col_target;
cmd_format_command(cmd, ITS_CMD_MAPI);
cmd_format_devid(cmd, desc->cmd_desc_mapi.its_dev->devid);
- cmd_format_id(cmd, desc->cmd_desc_mapi.lpinum);
- cmd_format_col(cmd, desc->cmd_desc_mapi.its_dev->col->col_id);
+ cmd_format_id(cmd, desc->cmd_desc_mapi.pid);
+ cmd_format_col(cmd, desc->cmd_desc_mapi.col->col_id);
break;
case ITS_CMD_INV:
- target = desc->cmd_desc_inv.its_dev->col->col_target;
+ target = desc->cmd_desc_inv.col->col_target;
cmd_format_command(cmd, ITS_CMD_INV);
cmd_format_devid(cmd, desc->cmd_desc_inv.its_dev->devid);
- cmd_format_id(cmd, desc->cmd_desc_inv.lpinum);
+ cmd_format_id(cmd, desc->cmd_desc_inv.pid);
break;
case ITS_CMD_INVALL:
cmd_format_command(cmd, ITS_CMD_INVALL);
@@ -1334,11 +1432,11 @@ its_cmd_send(struct gic_v3_its_softc *sc, struct its_cmd_desc *desc)
struct its_cmd_desc desc_sync;
uint64_t target, cwriter;
- mtx_lock_spin(&sc->its_spin_mtx);
+ mtx_lock_spin(&sc->its_cmd_lock);
cmd = its_cmd_alloc_locked(sc);
if (cmd == NULL) {
device_printf(sc->dev, "could not allocate ITS command\n");
- mtx_unlock_spin(&sc->its_spin_mtx);
+ mtx_unlock_spin(&sc->its_cmd_lock);
return (EBUSY);
}
@@ -1360,41 +1458,54 @@ end:
cwriter = its_cmd_cwriter_offset(sc, sc->its_cmdq_write);
gic_its_write(sc, 8, GITS_CWRITER, cwriter);
cmd_write = sc->its_cmdq_write;
- mtx_unlock_spin(&sc->its_spin_mtx);
+ mtx_unlock_spin(&sc->its_cmd_lock);
its_cmd_wait_completion(sc, cmd, cmd_write);
return (0);
}
+/* Find ITS device descriptor by pci_dev or irq number */
static struct its_dev *
-its_device_find_locked(struct gic_v3_its_softc *sc, device_t pci_dev)
+its_device_find_locked(struct gic_v3_its_softc *sc, device_t pci_dev,
+ uint32_t irq)
{
struct its_dev *its_dev;
+ struct lpi_chunk *lpis;
- mtx_assert(&sc->its_mtx, MA_OWNED);
+ mtx_assert(&sc->its_dev_lock, MA_OWNED);
+ KASSERT((pci_dev == NULL || irq == 0),
+ ("%s: Can't search by both pci_dev and irq number", __func__));
/* Find existing device if any */
TAILQ_FOREACH(its_dev, &sc->its_dev_list, entry) {
- if (its_dev->pci_dev == pci_dev)
- return (its_dev);
+ if (pci_dev != NULL) {
+ if (its_dev->pci_dev == pci_dev)
+ return (its_dev);
+ } else if (irq != 0) {
+ lpis = &its_dev->lpis;
+ if ((irq >= lpis->lpi_base) &&
+ (irq < (lpis->lpi_base + lpis->lpi_num)))
+ return (its_dev);
+ }
}
return (NULL);
}
static struct its_dev *
-its_device_alloc_locked(struct gic_v3_its_softc *sc, device_t pci_dev,
+its_device_alloc(struct gic_v3_its_softc *sc, device_t pci_dev,
u_int nvecs)
{
struct its_dev *newdev;
uint64_t typer;
uint32_t devid;
- u_int cpuid;
size_t esize;
+ int err;
- mtx_assert(&sc->its_mtx, MA_OWNED);
+ mtx_lock_spin(&sc->its_dev_lock);
/* Find existing device if any */
- newdev = its_device_find_locked(sc, pci_dev);
+ newdev = its_device_find_locked(sc, pci_dev, 0);
+ mtx_unlock_spin(&sc->its_dev_lock);
if (newdev != NULL)
return (newdev);
@@ -1408,7 +1519,8 @@ its_device_alloc_locked(struct gic_v3_its_softc *sc, device_t pci_dev,
newdev->pci_dev = pci_dev;
newdev->devid = devid;
- if (lpi_alloc_chunk(sc, &newdev->lpis, nvecs) != 0) {
+ err = lpi_alloc_chunk(sc, &newdev->lpis, nvecs);
+ if (err != 0) {
free(newdev, M_GIC_V3_ITS);
return (NULL);
}
@@ -1429,14 +1541,9 @@ its_device_alloc_locked(struct gic_v3_its_softc *sc, device_t pci_dev,
return (NULL);
}
- /*
- * XXX ARM64TODO: Currently all interrupts are going
- * to be bound to the CPU that performs the configuration.
- */
- cpuid = PCPU_GET(cpuid);
- newdev->col = sc->its_cols[cpuid];
-
+ mtx_lock_spin(&sc->its_dev_lock);
TAILQ_INSERT_TAIL(&sc->its_dev_list, newdev, entry);
+ mtx_unlock_spin(&sc->its_dev_lock);
/* Map device to its ITT */
its_cmd_mapd(sc, newdev, 1);
@@ -1449,7 +1556,7 @@ its_device_asign_lpi_locked(struct gic_v3_its_softc *sc,
struct its_dev *its_dev, u_int *irq)
{
- mtx_assert(&sc->its_mtx, MA_OWNED);
+ mtx_assert(&sc->its_dev_lock, MA_OWNED);
if (its_dev->lpis.lpi_free == 0) {
panic("Requesting more LPIs than allocated for this device. "
"LPI num: %u, free %u", its_dev->lpis.lpi_num,
@@ -1612,21 +1719,19 @@ gic_v3_its_alloc_msix(device_t dev, device_t pci_dev, int *irq)
sc = device_get_softc(dev);
- mtx_lock(&sc->its_mtx);
nvecs = PCI_MSIX_NUM(pci_dev);
/*
* Allocate device as seen by ITS if not already available.
* Notice that MSI-X interrupts are allocated on one-by-one basis.
*/
- its_dev = its_device_alloc_locked(sc, pci_dev, nvecs);
- if (its_dev == NULL) {
- mtx_unlock(&sc->its_mtx);
+ its_dev = its_device_alloc(sc, pci_dev, nvecs);
+ if (its_dev == NULL)
return (ENOMEM);
- }
+ mtx_lock_spin(&sc->its_dev_lock);
its_device_asign_lpi_locked(sc, its_dev, irq);
- mtx_unlock(&sc->its_mtx);
+ mtx_unlock_spin(&sc->its_dev_lock);
return (0);
}
@@ -1640,18 +1745,16 @@ gic_v3_its_alloc_msi(device_t dev, device_t pci_dev, int count, int *irqs)
sc = device_get_softc(dev);
/* Allocate device as seen by ITS if not already available. */
- mtx_lock(&sc->its_mtx);
- its_dev = its_device_alloc_locked(sc, pci_dev, count);
- if (its_dev == NULL) {
- mtx_unlock(&sc->its_mtx);
+ its_dev = its_device_alloc(sc, pci_dev, count);
+ if (its_dev == NULL)
return (ENOMEM);
- }
+ mtx_lock_spin(&sc->its_dev_lock);
for (; count > 0; count--) {
its_device_asign_lpi_locked(sc, its_dev, irqs);
irqs++;
}
- mtx_unlock(&sc->its_mtx);
+ mtx_unlock_spin(&sc->its_dev_lock);
return (0);
}
@@ -1668,9 +1771,9 @@ gic_v3_its_map_msi(device_t dev, device_t pci_dev, int irq, uint64_t *addr,
sc = device_get_softc(dev);
/* Verify that this device is allocated and owns this LPI */
- mtx_lock(&sc->its_mtx);
- its_dev = its_device_find_locked(sc, pci_dev);
- mtx_unlock(&sc->its_mtx);
+ mtx_lock_spin(&sc->its_dev_lock);
+ its_dev = its_device_find_locked(sc, pci_dev, 0);
+ mtx_unlock_spin(&sc->its_dev_lock);
if (its_dev == NULL)
return (EINVAL);
diff --git a/sys/arm64/arm64/gic_v3_reg.h b/sys/arm64/arm64/gic_v3_reg.h
index 17173de..2a2072f 100644
--- a/sys/arm64/arm64/gic_v3_reg.h
+++ b/sys/arm64/arm64/gic_v3_reg.h
@@ -356,12 +356,6 @@
/*
* CPU interface
*/
-#define GICI_SGI_TLIST_MASK (0xffffUL)
-#define GICI_SGI_AFF1_SHIFT (16UL)
-#define GICI_SGI_AFF2_SHIFT (32UL)
-#define GICI_SGI_AFF3_SHIFT (48UL)
-#define GICI_SGI_IPI_MASK (0xfUL)
-#define GICI_SGI_IPI_SHIFT (24UL)
/*
* Registers list (ICC_xyz_EL1):
diff --git a/sys/arm64/arm64/gic_v3_var.h b/sys/arm64/arm64/gic_v3_var.h
index 8ebd144..b3c0e52 100644
--- a/sys/arm64/arm64/gic_v3_var.h
+++ b/sys/arm64/arm64/gic_v3_var.h
@@ -96,6 +96,7 @@ struct lpi_chunk {
u_int lpi_base;
u_int lpi_num;
u_int lpi_free; /* First free LPI in set */
+ u_int *lpi_col_ids;
};
/* ITS device */
@@ -109,8 +110,6 @@ struct its_dev {
struct lpi_chunk lpis;
/* Virtual address of ITT */
vm_offset_t itt;
- /* Interrupt collection */
- struct its_col * col;
};
TAILQ_HEAD(its_dev_list, its_dev);
@@ -133,6 +132,7 @@ struct its_cmd {
};
/* ITS commands encoding */
+#define ITS_CMD_MOVI (0x01)
#define ITS_CMD_SYNC (0x05)
#define ITS_CMD_MAPD (0x08)
#define ITS_CMD_MAPC (0x09)
@@ -172,6 +172,12 @@ struct its_cmd_desc {
union {
struct {
+ struct its_dev *its_dev;
+ struct its_col *col;
+ uint32_t id;
+ } cmd_desc_movi;
+
+ struct {
struct its_col *col;
} cmd_desc_sync;
@@ -182,13 +188,15 @@ struct its_cmd_desc {
struct {
struct its_dev *its_dev;
+ struct its_col *col;
uint32_t pid;
uint32_t id;
} cmd_desc_mapvi;
struct {
struct its_dev *its_dev;
- uint32_t lpinum;
+ struct its_col *col;
+ uint32_t pid;
} cmd_desc_mapi;
struct {
@@ -198,7 +206,8 @@ struct its_cmd_desc {
struct {
struct its_dev *its_dev;
- uint32_t lpinum;
+ struct its_col *col;
+ uint32_t pid;
} cmd_desc_inv;
struct {
@@ -230,8 +239,8 @@ struct gic_v3_its_softc {
unsigned long * its_lpi_bitmap;
uint32_t its_lpi_maxid;
- struct mtx its_mtx;
- struct mtx its_spin_mtx;
+ struct mtx its_dev_lock;
+ struct mtx its_cmd_lock;
uint32_t its_socket; /* Socket number ITS is attached to */
};
@@ -257,6 +266,7 @@ int gic_v3_its_map_msi(device_t, device_t, int, uint64_t *, uint32_t *);
int its_init_cpu(struct gic_v3_its_softc *);
+int lpi_migrate(device_t, uint32_t, u_int);
void lpi_unmask_irq(device_t, uint32_t);
void lpi_mask_irq(device_t, uint32_t);
/*
diff --git a/sys/arm64/arm64/intr_machdep.c b/sys/arm64/arm64/intr_machdep.c
index 3389c69..5994279 100644
--- a/sys/arm64/arm64/intr_machdep.c
+++ b/sys/arm64/arm64/intr_machdep.c
@@ -38,6 +38,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
@@ -84,6 +85,7 @@ struct arm64_intr_entry {
u_int i_hw_irq; /* Physical interrupt number */
u_int i_cntidx; /* Index in intrcnt table */
u_int i_handlers; /* Allocated handlers */
+ u_int i_cpu; /* Assigned CPU */
u_long *i_cntp; /* Interrupt hit counter */
};
@@ -105,7 +107,7 @@ static void
intr_init(void *dummy __unused)
{
- mtx_init(&intr_list_lock, "intr sources lock", NULL, MTX_DEF);
+ mtx_init(&intr_list_lock, "intr sources lock", NULL, MTX_SPIN);
}
SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL);
@@ -123,34 +125,47 @@ intrcnt_setname(const char *name, u_int idx)
}
/*
+ * Find the interrupt descriptor in the list
+ * based on the hardware IRQ number.
+ */
+static __inline struct arm64_intr_entry *
+intr_lookup_locked(u_int hw_irq)
+{
+ struct arm64_intr_entry *intr;
+
+ mtx_assert(&intr_list_lock, MA_OWNED);
+ SLIST_FOREACH(intr, &irq_slist_head, entries) {
+ if (intr->i_hw_irq == hw_irq)
+ return (intr);
+ }
+ return (NULL);
+}
+/*
* Get intr structure for the given interrupt number.
* Allocate one if this is the first time.
- * (Similar to ppc's intr_lookup() but without actual
- * lookup since irq number is an index in arm64_intrs[]).
*/
static struct arm64_intr_entry *
-intr_acquire(u_int hw_irq)
+intr_allocate(u_int hw_irq)
{
struct arm64_intr_entry *intr;
- mtx_lock(&intr_list_lock);
-
- SLIST_FOREACH(intr, &irq_slist_head, entries) {
- if (intr->i_hw_irq == hw_irq) {
- break;
- }
- }
+ /* Check if already allocated */
+ mtx_lock_spin(&intr_list_lock);
+ intr = intr_lookup_locked(hw_irq);
+ mtx_unlock_spin(&intr_list_lock);
if (intr != NULL)
- goto out;
+ return (intr);
/* Do not alloc another intr when max number of IRQs has been reached */
if (intrcntidx >= NIRQS)
- goto out;
+ return (NULL);
intr = malloc(sizeof(*intr), M_INTR, M_NOWAIT);
if (intr == NULL)
- goto out;
+ return (NULL);
+ /* The default CPU is 0 but can be changed later by bind or shuffle */
+ intr->i_cpu = 0;
intr->i_event = NULL;
intr->i_handlers = 0;
intr->i_trig = INTR_TRIGGER_CONFORM;
@@ -158,12 +173,51 @@ intr_acquire(u_int hw_irq)
intr->i_cntidx = atomic_fetchadd_int(&intrcntidx, 1);
intr->i_cntp = &intrcnt[intr->i_cntidx];
intr->i_hw_irq = hw_irq;
+ mtx_lock_spin(&intr_list_lock);
SLIST_INSERT_HEAD(&irq_slist_head, intr, entries);
-out:
- mtx_unlock(&intr_list_lock);
+ mtx_unlock_spin(&intr_list_lock);
+
return intr;
}
+static int
+intr_assign_cpu(void *arg, int cpu)
+{
+#ifdef SMP
+ struct arm64_intr_entry *intr;
+ int error;
+
+ if (root_pic == NULL)
+ panic("Cannot assing interrupt to CPU. No PIC configured");
+ /*
+ * Set the interrupt to CPU affinity.
+ * Do not configure this in hardware during early boot.
+ * We will pick up the assignment once the APs are started.
+ */
+ if (cpu != NOCPU) {
+ intr = arg;
+ if (!cold && smp_started) {
+ /*
+ * Bind the interrupt immediately
+ * if SMP is up and running.
+ */
+ error = PIC_BIND(root_pic, intr->i_hw_irq, cpu);
+ if (error == 0)
+ intr->i_cpu = cpu;
+ } else {
+ /* Postpone binding until SMP is operational */
+ intr->i_cpu = cpu;
+ error = 0;
+ }
+ } else
+ error = 0;
+
+ return (error);
+#else
+ return (EOPNOTSUPP);
+#endif
+}
+
static void
intr_pre_ithread(void *arg)
{
@@ -312,7 +366,7 @@ arm_setup_intr(const char *name, driver_filter_t *filt, driver_intr_t handler,
struct arm64_intr_entry *intr;
int error;
- intr = intr_acquire(hw_irq);
+ intr = intr_allocate(hw_irq);
if (intr == NULL)
return (ENOMEM);
@@ -327,7 +381,7 @@ arm_setup_intr(const char *name, driver_filter_t *filt, driver_intr_t handler,
if (intr->i_event == NULL) {
error = intr_event_create(&intr->i_event, (void *)intr, 0,
hw_irq, intr_pre_ithread, intr_post_ithread,
- intr_post_filter, NULL, "irq%u", hw_irq);
+ intr_post_filter, intr_assign_cpu, "irq%u", hw_irq);
if (error)
return (error);
}
@@ -336,7 +390,6 @@ arm_setup_intr(const char *name, driver_filter_t *filt, driver_intr_t handler,
intr_priority(flags), flags, cookiep);
if (!error) {
- mtx_lock(&intr_list_lock);
intrcnt_setname(intr->i_event->ie_fullname, intr->i_cntidx);
intr->i_handlers++;
@@ -349,7 +402,6 @@ arm_setup_intr(const char *name, driver_filter_t *filt, driver_intr_t handler,
PIC_UNMASK(root_pic, intr->i_hw_irq);
}
- mtx_unlock(&intr_list_lock);
}
return (error);
@@ -364,12 +416,10 @@ arm_teardown_intr(void *cookie)
intr = intr_handler_source(cookie);
error = intr_event_remove_handler(cookie);
if (!error) {
- mtx_lock(&intr_list_lock);
intr->i_handlers--;
if (intr->i_handlers == 0)
PIC_MASK(root_pic, intr->i_hw_irq);
intrcnt_setname(intr->i_event->ie_fullname, intr->i_cntidx);
- mtx_unlock(&intr_list_lock);
}
return (error);
@@ -380,9 +430,11 @@ arm_config_intr(u_int hw_irq, enum intr_trigger trig, enum intr_polarity pol)
{
struct arm64_intr_entry *intr;
- intr = intr_acquire(hw_irq);
+ mtx_lock_spin(&intr_list_lock);
+ intr = intr_lookup_locked(hw_irq);
+ mtx_unlock_spin(&intr_list_lock);
if (intr == NULL)
- return (ENOMEM);
+ return (EINVAL);
intr->i_trig = trig;
intr->i_pol = pol;
@@ -398,12 +450,9 @@ arm_dispatch_intr(u_int hw_irq, struct trapframe *tf)
{
struct arm64_intr_entry *intr;
- SLIST_FOREACH(intr, &irq_slist_head, entries) {
- if (intr->i_hw_irq == hw_irq) {
- break;
- }
- }
-
+ mtx_lock_spin(&intr_list_lock);
+ intr = intr_lookup_locked(hw_irq);
+ mtx_unlock_spin(&intr_list_lock);
if (intr == NULL)
goto stray;
@@ -424,10 +473,6 @@ stray:
if (intr != NULL)
PIC_MASK(root_pic, intr->i_hw_irq);
-#ifdef HWPMC_HOOKS
- if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
- pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf);
-#endif
}
void
@@ -437,9 +482,49 @@ arm_cpu_intr(struct trapframe *tf)
critical_enter();
PIC_DISPATCH(root_pic, tf);
critical_exit();
+#ifdef HWPMC_HOOKS
+ if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
+ pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf);
+#endif
}
#ifdef SMP
+static void
+arm_intr_smp_init(void *dummy __unused)
+{
+ struct arm64_intr_entry *intr;
+ int error;
+
+ if (root_pic == NULL)
+ panic("Cannot assing interrupts to CPUs. No PIC configured");
+
+ mtx_lock_spin(&intr_list_lock);
+ SLIST_FOREACH(intr, &irq_slist_head, entries) {
+ mtx_unlock_spin(&intr_list_lock);
+ error = PIC_BIND(root_pic, intr->i_hw_irq, intr->i_cpu);
+ if (error != 0)
+ intr->i_cpu = 0;
+ mtx_lock_spin(&intr_list_lock);
+ }
+ mtx_unlock_spin(&intr_list_lock);
+}
+SYSINIT(arm_intr_smp_init, SI_SUB_SMP, SI_ORDER_ANY, arm_intr_smp_init, NULL);
+
+/* Attempt to bind the specified IRQ to the specified CPU. */
+int
+arm_intr_bind(u_int hw_irq, int cpu)
+{
+ struct arm64_intr_entry *intr;
+
+ mtx_lock_spin(&intr_list_lock);
+ intr = intr_lookup_locked(hw_irq);
+ mtx_unlock_spin(&intr_list_lock);
+ if (intr == NULL)
+ return (EINVAL);
+
+ return (intr_event_bind(intr->i_event, cpu));
+}
+
void
arm_setup_ipihandler(driver_filter_t *filt, u_int ipi)
{
diff --git a/sys/arm64/arm64/nexus.c b/sys/arm64/arm64/nexus.c
index 8290cff..611addd 100644
--- a/sys/arm64/arm64/nexus.c
+++ b/sys/arm64/arm64/nexus.c
@@ -113,6 +113,9 @@ static int nexus_deactivate_resource(device_t, device_t, int, int,
static int nexus_setup_intr(device_t dev, device_t child, struct resource *res,
int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep);
static int nexus_teardown_intr(device_t, device_t, struct resource *, void *);
+#ifdef SMP
+static int nexus_bind_intr(device_t, device_t, struct resource *, int);
+#endif
#ifdef FDT
static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent,
@@ -131,7 +134,9 @@ static device_method_t nexus_methods[] = {
DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
DEVMETHOD(bus_setup_intr, nexus_setup_intr),
DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
-
+#ifdef SMP
+ DEVMETHOD(bus_bind_intr, nexus_bind_intr),
+#endif
{ 0, 0 }
};
@@ -293,6 +298,15 @@ nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
return (arm_teardown_intr(ih));
}
+#ifdef SMP
+static int
+nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu)
+{
+
+ return (arm_intr_bind(rman_get_start(irq), cpu));
+}
+#endif
+
static int
nexus_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
diff --git a/sys/arm64/arm64/pic_if.m b/sys/arm64/arm64/pic_if.m
index fe358c6..33d1bcd 100644
--- a/sys/arm64/arm64/pic_if.m
+++ b/sys/arm64/arm64/pic_if.m
@@ -34,7 +34,11 @@
INTERFACE pic;
CODE {
- static pic_translate_code_t pic_translate_code_default;
+ static int pic_bind_default(device_t dev, u_int irq, u_int cpu)
+ {
+
+ return (EOPNOTSUPP);
+ }
static void pic_translate_code_default(device_t dev, u_int irq,
int code, enum intr_trigger *trig, enum intr_polarity *pol)
@@ -60,11 +64,11 @@ CODE {
}
};
-METHOD void bind {
+METHOD int bind {
device_t dev;
u_int irq;
- cpuset_t cpumask;
-};
+ u_int cpu;
+} DEFAULT pic_bind_default;
METHOD void translate_code {
device_t dev;
diff --git a/sys/arm64/arm64/swtch.S b/sys/arm64/arm64/swtch.S
index 3175e87..35153c2 100644
--- a/sys/arm64/arm64/swtch.S
+++ b/sys/arm64/arm64/swtch.S
@@ -129,12 +129,6 @@ END(cpu_throw)
* x3 to x7, x16 and x17 are caller saved
*/
ENTRY(cpu_switch)
- /* Store the new curthread */
- str x1, [x18, #PC_CURTHREAD]
- /* And the new pcb */
- ldr x4, [x1, #TD_PCB]
- str x4, [x18, #PC_CURPCB]
-
/*
* Save the old context.
*/
@@ -174,10 +168,14 @@ ENTRY(cpu_switch)
mov x0, x19
#endif
+ /* Store the new curthread */
+ str x1, [x18, #PC_CURTHREAD]
+
/*
- * Restore the saved context.
+ * Restore the saved context and set it as curpcb.
*/
ldr x4, [x1, #TD_PCB]
+ str x4, [x18, #PC_CURPCB]
/*
* TODO: We may need to flush the cache here if switching
diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h
index 0c86462..405f3bb 100644
--- a/sys/arm64/include/armreg.h
+++ b/sys/arm64/include/armreg.h
@@ -118,6 +118,15 @@
/* ICC_PMR_EL1 */
#define ICC_PMR_EL1_PRIO_MASK (0xFFUL)
+/* ICC_SGI1R_EL1 */
+#define ICC_SGI1R_EL1_TL_MASK 0xffffUL
+#define ICC_SGI1R_EL1_AFF1_SHIFT 16
+#define ICC_SGI1R_EL1_SGIID_SHIFT 24
+#define ICC_SGI1R_EL1_AFF2_SHIFT 32
+#define ICC_SGI1R_EL1_AFF3_SHIFT 48
+#define ICC_SGI1R_EL1_SGIID_MASK 0xfUL
+#define ICC_SGI1R_EL1_IRM (0x1UL << 40)
+
/* ICC_SRE_EL1 */
#define ICC_SRE_EL1_SRE (1U << 0)
diff --git a/sys/arm64/include/intr.h b/sys/arm64/include/intr.h
index 067c69b..2d7da21 100644
--- a/sys/arm64/include/intr.h
+++ b/sys/arm64/include/intr.h
@@ -49,6 +49,7 @@ void arm_unmask_irq(u_int);
#ifdef SMP
void arm_init_secondary(void);
+int arm_intr_bind(u_int, int);
void arm_setup_ipihandler(driver_filter_t *, u_int);
void arm_unmask_ipi(u_int);
#endif
diff --git a/sys/boot/fdt/dts/arm/bananapi.dts b/sys/boot/fdt/dts/arm/bananapi.dts
index ee5ec76..b86da45 100644
--- a/sys/boot/fdt/dts/arm/bananapi.dts
+++ b/sys/boot/fdt/dts/arm/bananapi.dts
@@ -28,7 +28,8 @@
/dts-v1/;
-/include/ "sun7i-a20.dtsi"
+#include "sun7i-a20.dtsi"
+
#include <dt-bindings/gpio/gpio.h>
@@ -65,7 +66,7 @@
};
gmac@01c50000 {
- phy-type = "rgmii-bpi";
+ phy-mode = "rgmii-bpi";
status = "okay";
};
diff --git a/sys/boot/fdt/dts/arm/cubieboard2.dts b/sys/boot/fdt/dts/arm/cubieboard2.dts
index 480df66..35e3836 100644
--- a/sys/boot/fdt/dts/arm/cubieboard2.dts
+++ b/sys/boot/fdt/dts/arm/cubieboard2.dts
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@freebsd.org>
+ * Copyright (c) 2016 Emmanuel Vadot <manu@bidouilliste.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,78 +23,19 @@
* 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.
- *
+ *
* $FreeBSD$
*/
-/dts-v1/;
-
-/include/ "sun7i-a20.dtsi"
-
-#include <dt-bindings/gpio/gpio.h>
+#include "sun7i-a20-cubieboard2.dts"
/ {
- model = "Cubietech Cubieboard2";
-
- memory {
- device_type = "memory";
- reg = < 0x40000000 0x40000000 >; /* 1GB RAM */
- };
-
- aliases {
- soc = &SOC;
- UART0 = &UART0;
- };
-
- SOC: a20 {
-
- usb1: usb@01c14000 {
- status = "okay";
- };
-
- usb2: usb@01c1c000 {
- status = "okay";
- };
-
- UART0: serial@01c28000 {
- status = "okay";
- };
-
- mmc0: mmc@01c0f000 {
- status = "okay";
- };
-
- emac@01c0b000 {
- status = "okay";
- };
-
- gmac@01c50000 {
- status = "okay";
- };
-
- ahci: sata@01c18000 {
- status = "okay";
+ soc@01c00000 {
+ ccm@01c20000 {
+ compatible = "allwinner,sun4i-ccm";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = < 0x01c20000 0x400 >;
};
};
-
- leds {
- compatible = "gpio-leds";
-
- blue {
- label = "cubieboard2:blue:usr";
- gpios = <&pio 7 21 GPIO_ACTIVE_HIGH>;
- };
-
- green {
- label = "cubieboard2:green:usr";
- gpios = <&pio 7 20 GPIO_ACTIVE_HIGH>;
- };
- };
-
- chosen {
- bootargs = "-v";
- stdin = "UART0";
- stdout = "UART0";
- };
};
-
diff --git a/sys/boot/fdt/dts/arm/olimex-a20-som-evb.dts b/sys/boot/fdt/dts/arm/olimex-a20-som-evb.dts
new file mode 100644
index 0000000..ffe0777
--- /dev/null
+++ b/sys/boot/fdt/dts/arm/olimex-a20-som-evb.dts
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2015 Emmanuel Vadot <manu@bidouilliste.com>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+#include "sun7i-a20-olimex-som-evb.dts"
+
+/ {
+ soc@01c00000 {
+ ccm@01c20000 {
+ compatible = "allwinner,sun4i-ccm";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = < 0x01c20000 0x400 >;
+ };
+ };
+};
diff --git a/sys/boot/fdt/dts/arm/olinuxino-lime.dts b/sys/boot/fdt/dts/arm/olinuxino-lime.dts
new file mode 100644
index 0000000..b965788
--- /dev/null
+++ b/sys/boot/fdt/dts/arm/olinuxino-lime.dts
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2015 Emmanuel Vadot <manu@bidouilliste.com>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+#include "sun4i-a10-olinuxino-lime.dts"
+
+/ {
+ soc@01c00000 {
+ ccm@01c20000 {
+ compatible = "allwinner,sun4i-ccm";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = < 0x01c20000 0x400 >;
+ };
+ };
+};
diff --git a/sys/boot/fdt/dts/arm/sun4i-a10.dtsi b/sys/boot/fdt/dts/arm/sun4i-a10.dtsi
index 8b32725..6a53c59 100644
--- a/sys/boot/fdt/dts/arm/sun4i-a10.dtsi
+++ b/sys/boot/fdt/dts/arm/sun4i-a10.dtsi
@@ -45,7 +45,7 @@
bus-frequency = <0>;
AINTC: interrupt-controller@01c20400 {
- compatible = "allwinner,sun4i-ic";
+ compatible = "allwinner,sun4i-a10-ic";
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <1>;
@@ -67,7 +67,7 @@
};
timer@01c20c00 {
- compatible = "allwinner,sun4i-timer";
+ compatible = "allwinner,sun4i-a10-timer";
reg = <0x01c20c00 0x90>;
interrupts = < 22 >;
interrupt-parent = <&AINTC>;
@@ -82,7 +82,7 @@
GPIO: gpio@01c20800 {
#gpio-cells = <3>;
- compatible = "allwinner,sun4i-gpio";
+ compatible = "allwinner,sun4i-a10-pinctrl";
gpio-controller;
reg =< 0x01c20800 0x400 >;
interrupts = < 28 >;
@@ -90,14 +90,14 @@
};
usb1: usb@01c14000 {
- compatible = "allwinner,usb-ehci", "usb-ehci";
+ compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
reg = <0x01c14000 0x1000>;
interrupts = < 39 >;
interrupt-parent = <&AINTC>;
};
usb2: usb@01c1c000 {
- compatible = "allwinner,usb-ehci", "usb-ehci";
+ compatible = "allwinner,sun4i-a10-ehci", "generic-ehci";
reg = <0x01c1c000 0x1000>;
interrupts = < 40 >;
interrupt-parent = <&AINTC>;
@@ -130,7 +130,7 @@
};
emac@01c0b000 {
- compatible = "allwinner,sun4i-emac";
+ compatible = "allwinner,sun4i-a10-emac";
reg = <0x01c0b000 0x1000>;
interrupts = <55>;
interrupt-parent = <&AINTC>;
diff --git a/sys/boot/fdt/dts/arm/sun7i-a20.dtsi b/sys/boot/fdt/dts/arm/sun7i-a20.dtsi
index b559e5e..6070343 100644
--- a/sys/boot/fdt/dts/arm/sun7i-a20.dtsi
+++ b/sys/boot/fdt/dts/arm/sun7i-a20.dtsi
@@ -26,6 +26,8 @@
* $FreeBSD$
*/
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
/ {
compatible = "allwinner,sun7i-a20";
#address-cells = <1>;
@@ -37,6 +39,14 @@
soc = &SOC;
};
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+
SOC: a20 {
#address-cells = <1>;
#size-cells = <1>;
@@ -47,9 +57,12 @@
GIC: interrupt-controller@01c81000 {
compatible = "arm,gic";
reg = <0x01c81000 0x1000>, /* Distributor Registers */
- <0x01c82000 0x0100>; /* CPU Interface Registers */
+ <0x01c82000 0x0100>, /* CPU Interface Registers */
+ <0x01c84000 0x2000>,
+ <0x01c86000 0x2000>;
interrupt-controller;
- #interrupt-cells = <1>;
+ #interrupt-cells = <3>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
};
sramc@01c00000 {
@@ -74,53 +87,59 @@
};
timer@01c20c00 {
- compatible = "allwinner,sun7i-timer";
+ compatible = "allwinner,sun4i-a10-timer";
reg = <0x01c20c00 0x90>;
- interrupts = < 22 >;
+ interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&GIC>;
clock-frequency = < 24000000 >;
};
watchdog@01c20c90 {
- compatible = "allwinner,sun4i-wdt";
+ compatible = "allwinner,sun4i-a10-wdt";
reg = <0x01c20c90 0x10>;
};
pio: gpio@01c20800 {
#gpio-cells = <3>;
- compatible = "allwinner,sun4i-gpio";
+ compatible = "allwinner,sun7i-a20-pinctrl";
gpio-controller;
reg =< 0x01c20800 0x400 >;
- interrupts = < 28 >;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
interrupt-parent = <&GIC>;
};
usb1: usb@01c14000 {
- compatible = "allwinner,usb-ehci", "usb-ehci";
+ compatible = "allwinner,sun7i-a20-ehci", "generic-ehci";
reg = <0x01c14000 0x1000>;
- interrupts = < 39 >;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&GIC>;
};
usb2: usb@01c1c000 {
- compatible = "allwinner,usb-ehci", "usb-ehci";
+ compatible = "allwinner,sun7i-a20-ehci", "generic-ehci";
reg = <0x01c1c000 0x1000>;
- interrupts = < 40 >;
+ interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&GIC>;
};
mmc0: mmc@01c0f000 {
- compatible = "allwinner,sun4i-a10-mmc";
+ compatible = "allwinner,sun5i-a13-mmc";
reg = <0x01c0f000 0x1000>;
- interrupts = <32>;
- interrupt-parent = <&GIC>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
};
sata@01c18000 {
compatible = "allwinner,sun4i-a10-ahci";
reg = <0x01c18000 0x1000>;
- interrupts = <56>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&GIC>;
status = "disabled";
};
@@ -129,16 +148,15 @@
compatible = "snps,dw-apb-uart";
reg = <0x01c28000 0x400>;
reg-shift = <2>;
- interrupts = <1>;
- interrupt-parent = <&GIC>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
current-speed = <115200>;
clock-frequency = < 24000000 >;
};
emac@01c0b000 {
- compatible = "allwinner,sun4i-emac";
+ compatible = "allwinner,sun4i-a10-emac";
reg = <0x01c0b000 0x1000>;
- interrupts = <55>;
+ interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&GIC>;
status = "disabled";
};
@@ -146,7 +164,7 @@
gmac@01c50000 {
compatible = "allwinner,sun7i-a20-gmac";
reg = <0x01c50000 0x10000>;
- interrupts = <85>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&GIC>;
snps,pbl = <2>;
snps,fixed-burst;
@@ -155,6 +173,13 @@
#address-cells = <1>;
#size-cells = <0>;
};
+
+ dma: dma-controller@01c02000 {
+ compatible = "allwinner,sun4i-a10-dma";
+ reg = <0x01c02000 0x1000>;
+ interrupts = <27>;
+ interrupt-parent = <&GIC>;
+ };
};
};
diff --git a/sys/boot/fdt/dts/riscv/qemu.dts b/sys/boot/fdt/dts/riscv/qemu.dts
new file mode 100644
index 0000000..b9590a9
--- /dev/null
+++ b/sys/boot/fdt/dts/riscv/qemu.dts
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2016 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * Portions of this software were developed by SRI International and the
+ * University of Cambridge Computer Laboratory under DARPA/AFRL contract
+ * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * Portions of this software were developed by the University of Cambridge
+ * Computer Laboratory as part of the CTSRD Project, with support from the
+ * UK Higher Education Innovation Fund (HEIF).
+ *
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+/dts-v1/;
+
+/ {
+ model = "QEMU RV64I";
+ compatible = "riscv,rv64i";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #interrupt-cells = <1>;
+
+ aliases {
+ console0 = &console0;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x8000000>; /* 128MB at 0x0 */
+ };
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+
+ compatible = "simple-bus";
+ ranges;
+
+ pic0: pic@0 {
+ compatible = "riscv,pic";
+ interrupt-controller;
+ };
+
+ timer0: timer@0 {
+ compatible = "riscv,timer";
+ interrupts = < 1 >;
+ interrupt-parent = < &pic0 >;
+ clock-frequency = < 400000000 >;
+ };
+
+ htif0: htif@0 {
+ compatible = "riscv,htif";
+ interrupts = < 0 >;
+ interrupt-parent = < &pic0 >;
+
+ console0: console@0 {
+ compatible = "htif,console";
+ status = "okay";
+ };
+ };
+ };
+
+ chosen {
+ bootargs = "-v";
+ stdin = "console0";
+ stdout = "console0";
+ };
+};
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 4fdaa05..1101d02 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -5694,7 +5694,7 @@ ctl_write_same(struct ctl_scsiio *ctsio)
*/
if ((byte2 & SWS_NDOB) == 0 &&
(ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) == 0) {
- ctsio->kern_data_ptr = malloc(len, M_CTL, M_WAITOK);;
+ ctsio->kern_data_ptr = malloc(len, M_CTL, M_WAITOK);
ctsio->kern_data_len = len;
ctsio->kern_total_len = len;
ctsio->kern_data_resid = 0;
@@ -5742,7 +5742,7 @@ ctl_unmap(struct ctl_scsiio *ctsio)
* malloc it and tell the caller the data buffer is here.
*/
if ((ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) == 0) {
- ctsio->kern_data_ptr = malloc(len, M_CTL, M_WAITOK);;
+ ctsio->kern_data_ptr = malloc(len, M_CTL, M_WAITOK);
ctsio->kern_data_len = len;
ctsio->kern_total_len = len;
ctsio->kern_data_resid = 0;
diff --git a/sys/conf/files.arm b/sys/conf/files.arm
index bc5d8a3..ac8b4e89 100644
--- a/sys/conf/files.arm
+++ b/sys/conf/files.arm
@@ -101,6 +101,7 @@ dev/fb/fb.c optional sc
dev/fdt/fdt_arm_platform.c optional platform fdt
dev/hwpmc/hwpmc_arm.c optional hwpmc
dev/hwpmc/hwpmc_armv7.c optional hwpmc armv6
+dev/iicbus/twsi/twsi.c optional twsi
dev/psci/psci.c optional psci
dev/psci/psci_arm.S optional psci
dev/syscons/scgfbrndr.c optional sc
diff --git a/sys/conf/files.mips b/sys/conf/files.mips
index 0bd6938..91d53aa 100644
--- a/sys/conf/files.mips
+++ b/sys/conf/files.mips
@@ -7,7 +7,6 @@
# Arch dependent files
mips/mips/autoconf.c standard
mips/mips/bus_space_generic.c standard
-mips/mips/bus_space_fdt.c optional fdt
mips/mips/busdma_machdep.c standard
mips/mips/cache.c standard
mips/mips/cache_mipsNN.c standard
diff --git a/sys/dev/cxgb/cxgb_sge.c b/sys/dev/cxgb/cxgb_sge.c
index 2cfad26..a622fcf 100644
--- a/sys/dev/cxgb/cxgb_sge.c
+++ b/sys/dev/cxgb/cxgb_sge.c
@@ -795,12 +795,10 @@ free_rx_bufs(adapter_t *sc, struct sge_fl *q)
bus_dmamap_unload(q->entry_tag, d->map);
bus_dmamap_destroy(q->entry_tag, d->map);
if (q->zone == zone_pack) {
- m_init(d->m, zone_pack, MCLBYTES,
- M_NOWAIT, MT_DATA, M_EXT);
+ m_init(d->m, M_NOWAIT, MT_DATA, M_EXT);
uma_zfree(zone_pack, d->m);
} else {
- m_init(d->m, zone_mbuf, MLEN,
- M_NOWAIT, MT_DATA, 0);
+ m_init(d->m, M_NOWAIT, MT_DATA, 0);
uma_zfree(zone_mbuf, d->m);
uma_zfree(q->zone, d->rxsd_cl);
}
@@ -2725,7 +2723,7 @@ get_packet(adapter_t *adap, unsigned int drop_thres, struct sge_qset *qs,
if ((sopeop == RSPQ_SOP_EOP) ||
(sopeop == RSPQ_SOP))
flags |= M_PKTHDR;
- m_init(m, fl->zone, fl->buf_size, M_NOWAIT, MT_DATA, flags);
+ m_init(m, M_NOWAIT, MT_DATA, flags);
if (fl->zone == zone_pack) {
/*
* restore clobbered data pointer
diff --git a/sys/dev/cxgbe/common/t4_msg.h b/sys/dev/cxgbe/common/t4_msg.h
index c30b6f1f..2d84604 100644
--- a/sys/dev/cxgbe/common/t4_msg.h
+++ b/sys/dev/cxgbe/common/t4_msg.h
@@ -126,7 +126,6 @@ enum {
CPL_RDMA_IMM_DATA_SE = 0xAD,
CPL_TRACE_PKT = 0xB0,
- CPL_TRACE_PKT_T5 = 0x48,
CPL_RX2TX_DATA = 0xB1,
CPL_ISCSI_DATA = 0xB2,
CPL_FCOE_DATA = 0xB3,
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 21d0cb8..a3d83bd 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -708,7 +708,7 @@ t4_attach(device_t dev)
sc->fw_msg_handler[i] = fw_msg_not_handled;
t4_register_cpl_handler(sc, CPL_SET_TCB_RPL, t4_filter_rpl);
t4_register_cpl_handler(sc, CPL_TRACE_PKT, t4_trace_pkt);
- t4_register_cpl_handler(sc, CPL_TRACE_PKT_T5, t5_trace_pkt);
+ t4_register_cpl_handler(sc, CPL_T5_TRACE_PKT, t5_trace_pkt);
t4_init_sge_cpl_handlers(sc);
/* Prepare the adapter for operation */
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index b43cd5f..0c3644d 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -1570,7 +1570,7 @@ get_scatter_segment(struct adapter *sc, struct sge_fl *fl, int fr_offset,
MPASS(clm != NULL);
m = (struct mbuf *)(sd->cl + sd->nmbuf * MSIZE);
/* No bzero required */
- if (m_init(m, NULL, 0, M_NOWAIT, MT_DATA,
+ if (m_init(m, M_NOWAIT, MT_DATA,
fr_offset == 0 ? M_PKTHDR | M_NOFREE : M_NOFREE))
return (NULL);
fl->mbuf_inlined++;
diff --git a/sys/dev/hwpmc/hwpmc_core.c b/sys/dev/hwpmc/hwpmc_core.c
index d26c965..f092a21 100644
--- a/sys/dev/hwpmc/hwpmc_core.c
+++ b/sys/dev/hwpmc/hwpmc_core.c
@@ -103,6 +103,7 @@ static int core_iaf_npmc;
static int core_iap_width;
static int core_iap_npmc;
+static int core_iap_wroffset;
static int
core_pcpu_noop(struct pmc_mdep *md, int cpu)
@@ -2473,7 +2474,7 @@ iap_read_pmc(int cpu, int ri, pmc_value_t *v)
*v = tmp & ((1ULL << core_iap_width) - 1);
PMCDBG4(MDP,REA,1, "iap-read cpu=%d ri=%d msr=0x%x -> v=%jx", cpu, ri,
- ri, *v);
+ IAP_PMC0 + ri, *v);
return (0);
}
@@ -2605,19 +2606,20 @@ iap_write_pmc(int cpu, int ri, pmc_value_t v)
("[core,%d] cpu%d ri%d no configured PMC to stop", __LINE__,
cpu, ri));
- PMCDBG4(MDP,WRI,1, "iap-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri,
- IAP_PMC0 + ri, v);
-
if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
v = iap_reload_count_to_perfctr_value(v);
- /*
- * Write the new value to the counter. The counter will be in
- * a stopped state when the pcd_write() entry point is called.
- */
+ v &= (1ULL << core_iap_width) - 1;
- wrmsr(IAP_PMC0 + ri, v & ((1ULL << core_iap_width) - 1));
+ PMCDBG4(MDP,WRI,1, "iap-write cpu=%d ri=%d msr=0x%x v=%jx", cpu, ri,
+ IAP_PMC0 + ri, v);
+ /*
+ * Write the new value to the counter (or it's alias). The
+ * counter will be in a stopped state when the pcd_write()
+ * entry point is called.
+ */
+ wrmsr(core_iap_wroffset + IAP_PMC0 + ri, v);
return (0);
}
@@ -2700,7 +2702,7 @@ core_intr(int cpu, struct trapframe *tf)
*/
msr = rdmsr(IAP_EVSEL0 + ri) & ~IAP_EVSEL_MASK;
wrmsr(IAP_EVSEL0 + ri, msr);
- wrmsr(IAP_PMC0 + ri, v);
+ wrmsr(core_iap_wroffset + IAP_PMC0 + ri, v);
if (error)
continue;
@@ -2814,7 +2816,7 @@ core2_intr(int cpu, struct trapframe *tf)
(uintmax_t) v);
/* Reload sampling count. */
- wrmsr(IAP_PMC0 + n, v);
+ wrmsr(core_iap_wroffset + IAP_PMC0 + n, v);
}
/*
@@ -2865,6 +2867,18 @@ pmc_core_initialize(struct pmc_mdep *md, int maxcpu, int version_override)
return (EPROGMISMATCH);
}
+ core_iap_wroffset = 0;
+ if (cpu_feature2 & CPUID2_PDCM) {
+ if (rdmsr(IA32_PERF_CAPABILITIES) & PERFCAP_FW_WRITE) {
+ PMCDBG0(MDP, INI, 1,
+ "core-init full-width write supported");
+ core_iap_wroffset = IAP_A_PMC0 - IAP_PMC0;
+ } else
+ PMCDBG0(MDP, INI, 1,
+ "core-init full-width write NOT supported");
+ } else
+ PMCDBG0(MDP, INI, 1, "core-init pdcm not supported");
+
core_pmcmask = 0;
/*
diff --git a/sys/dev/hwpmc/hwpmc_core.h b/sys/dev/hwpmc/hwpmc_core.h
index 63b6d02..7196d9d 100644
--- a/sys/dev/hwpmc/hwpmc_core.h
+++ b/sys/dev/hwpmc/hwpmc_core.h
@@ -29,6 +29,14 @@
#ifndef _DEV_HWPMC_CORE_H_
#define _DEV_HWPMC_CORE_H_ 1
+#define IA32_PERF_CAPABILITIES 0x345
+#define PERFCAP_LBR_FORMAT 0x003f
+#define PERFCAP_PEBS_TRAP 0x0040
+#define PERFCAP_PEBS_SAVEARCH 0x0080
+#define PERFCAP_PEBS_RECFORMAT 0x0f00
+#define PERFCAP_SMM_FREEZE 0x1000
+#define PERFCAP_FW_WRITE 0x2000 /* full width write aliases */
+
/*
* Fixed-function PMCs.
*/
@@ -101,6 +109,7 @@ struct pmc_md_iap_op_pmcallocate {
*/
#define IAP_PMC0 0x0C1
+#define IAP_A_PMC0 0x4C1
/*
* IAP_EVSEL(n) is laid out in the following way.
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index 3a1d52a..4a5586c 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -1483,7 +1483,7 @@ pmc_process_csw_out(struct thread *td)
* increasing monotonically, modulo a 64
* bit wraparound.
*/
- KASSERT((int64_t) tmp >= 0,
+ KASSERT(tmp >= 0,
("[pmc,%d] negative increment cpu=%d "
"ri=%d newvalue=%jx saved=%jx "
"incr=%jx", __LINE__, cpu, ri,
diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
index be43bf4..b2a2079 100644
--- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
+++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
@@ -787,7 +787,7 @@ netvsc_channel_rollup(struct hv_device *device_ctx)
/*
* NOTE:
- * This this function fails, then both txd and m_head0 will be freed
+ * If this function fails, then both txd and m_head0 will be freed.
*/
static int
hn_encap(struct hn_softc *sc, struct hn_txdesc *txd, struct mbuf **m_head0)
diff --git a/sys/dev/iicbus/twsi/a10_twsi.c b/sys/dev/iicbus/twsi/a10_twsi.c
new file mode 100644
index 0000000..f07973e
--- /dev/null
+++ b/sys/dev/iicbus/twsi/a10_twsi.c
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 2016 Emmanuel Vadot <manu@bidouilliste.com>
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <sys/rman.h>
+
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/twsi/twsi.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/allwinner/a10_clk.h>
+
+#include "iicbus_if.h"
+
+#define TWI_ADDR 0x0
+#define TWI_XADDR 0x4
+#define TWI_DATA 0x8
+#define TWI_CNTR 0xC
+#define TWI_STAT 0x10
+#define TWI_CCR 0x14
+#define TWI_SRST 0x18
+#define TWI_EFR 0x1C
+#define TWI_LCR 0x20
+
+static int
+a10_twsi_probe(device_t dev)
+{
+ struct twsi_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-a10-i2c"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Allwinner Integrated I2C Bus Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+a10_twsi_attach(device_t dev)
+{
+ struct twsi_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ /* Activate clock */
+ a10_clk_i2c_activate(device_get_unit(dev));
+
+ sc->reg_data = TWI_DATA;
+ sc->reg_slave_addr = TWI_ADDR;
+ sc->reg_slave_ext_addr = TWI_XADDR;
+ sc->reg_control = TWI_CNTR;
+ sc->reg_status = TWI_STAT;
+ sc->reg_baud_rate = TWI_CCR;
+ sc->reg_soft_reset = TWI_SRST;
+
+ /* Setup baud rate params */
+ sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(11, 2);
+ sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(11, 2);
+ sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 2);
+
+ return (twsi_attach(dev));
+}
+
+static phandle_t
+a10_twsi_get_node(device_t bus, device_t dev)
+{
+ return (ofw_bus_get_node(bus));
+}
+
+static device_method_t a10_twsi_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, a10_twsi_probe),
+ DEVMETHOD(device_attach, a10_twsi_attach),
+
+ /* OFW methods */
+ DEVMETHOD(ofw_bus_get_node, a10_twsi_get_node),
+
+ { 0, 0 }
+};
+
+DEFINE_CLASS_1(iichb, a10_twsi_driver, a10_twsi_methods,
+ sizeof(struct twsi_softc), twsi_driver);
+
+static devclass_t a10_twsi_devclass;
+
+DRIVER_MODULE(a10_twsi, simplebus, a10_twsi_driver, a10_twsi_devclass, 0, 0);
+DRIVER_MODULE(iicbus, a10_twsi, iicbus_driver, iicbus_devclass, 0, 0);
+MODULE_DEPEND(a10_twsi, iicbus, 1, 1, 1);
diff --git a/sys/dev/iicbus/twsi/mv_twsi.c b/sys/dev/iicbus/twsi/mv_twsi.c
new file mode 100644
index 0000000..998a197
--- /dev/null
+++ b/sys/dev/iicbus/twsi/mv_twsi.c
@@ -0,0 +1,251 @@
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Driver for the TWSI (aka I2C, aka IIC) bus controller found on Marvell
+ * and Allwinner SoCs. Supports master operation only, and works in polling mode.
+ *
+ * Calls to DELAY() are needed per Application Note AN-179 "TWSI Software
+ * Guidelines for Discovery(TM), Horizon (TM) and Feroceon(TM) Devices".
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+
+#include <machine/_inttypes.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <sys/rman.h>
+
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/mv/mvreg.h>
+#include <arm/mv/mvvar.h>
+#include <dev/iicbus/twsi/twsi.h>
+
+#include "iicbus_if.h"
+
+#define MV_TWSI_NAME "twsi"
+#define IICBUS_DEVNAME "iicbus"
+
+#define TWSI_ADDR 0x00
+#define TWSI_DATA 0x04
+#define TWSI_CNTR 0x08
+#define TWSI_XADDR 0x10
+#define TWSI_STAT 0x0c
+#define TWSI_BAUD_RATE 0x0c
+#define TWSI_SRST 0x1c
+
+#define TWSI_BAUD_RATE_RAW(C,M,N) ((C)/((10*(M+1))<<(N+1)))
+#define TWSI_BAUD_RATE_SLOW 50000 /* 50kHz */
+#define TWSI_BAUD_RATE_FAST 100000 /* 100kHz */
+
+#define TWSI_DEBUG
+#undef TWSI_DEBUG
+
+#ifdef TWSI_DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+static int mv_twsi_probe(device_t);
+static int mv_twsi_attach(device_t);
+
+static struct ofw_compat_data compat_data[] = {
+ { "mrvl,twsi", true },
+ { "marvell,mv64xxx-i2c", true },
+ { NULL, false }
+};
+
+static device_method_t mv_twsi_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, mv_twsi_probe),
+ DEVMETHOD(device_attach, mv_twsi_attach),
+
+ { 0, 0 }
+};
+
+DEFINE_CLASS_1(twsi, mv_twsi_driver, mv_twsi_methods,
+ sizeof(struct twsi_softc), twsi_driver);
+
+static devclass_t mv_twsi_devclass;
+
+DRIVER_MODULE(twsi, simplebus, mv_twsi_driver, mv_twsi_devclass, 0, 0);
+DRIVER_MODULE(iicbus, twsi, iicbus_driver, iicbus_devclass, 0, 0);
+MODULE_DEPEND(twsi, iicbus, 1, 1, 1);
+
+static int
+mv_twsi_probe(device_t dev)
+{
+ struct twsi_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+
+ sc->reg_data = TWSI_DATA;
+ sc->reg_slave_addr = TWSI_ADDR;
+ sc->reg_slave_ext_addr = TWSI_XADDR;
+ sc->reg_control = TWSI_CNTR;
+ sc->reg_status = TWSI_STAT;
+ sc->reg_baud_rate = TWSI_BAUD_RATE;
+ sc->reg_soft_reset = TWSI_SRST;
+
+ device_set_desc(dev, "Marvell Integrated I2C Bus Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+#define ABSSUB(a,b) (((a) > (b)) ? (a) - (b) : (b) - (a))
+static void
+mv_twsi_cal_baud_rate(const uint32_t target, struct twsi_baud_rate *rate)
+{
+ uint32_t clk, cur, diff, diff0;
+ int m, n, m0, n0;
+
+ /* Calculate baud rate. */
+ m0 = n0 = 4; /* Default values on reset */
+ diff0 = 0xffffffff;
+ clk = get_tclk();
+
+ for (n = 0; n < 8; n++) {
+ for (m = 0; m < 16; m++) {
+ cur = TWSI_BAUD_RATE_RAW(clk,m,n);
+ diff = ABSSUB(target, cur);
+ if (diff < diff0) {
+ m0 = m;
+ n0 = n;
+ diff0 = diff;
+ }
+ }
+ }
+ rate->raw = TWSI_BAUD_RATE_RAW(clk, m0, n0);
+ rate->param = TWSI_BAUD_RATE_PARAM(m0, n0);
+ rate->m = m0;
+ rate->n = n0;
+}
+
+static int
+mv_twsi_attach(device_t dev)
+{
+ struct twsi_softc *sc;
+ phandle_t child, iicbusnode;
+ device_t childdev;
+ struct iicbus_ivar *devi;
+ char dname[32]; /* 32 is taken from struct u_device */
+ uint32_t paddr;
+ int len, error, ret;
+
+ sc = device_get_softc(dev);
+
+ mv_twsi_cal_baud_rate(TWSI_BAUD_RATE_SLOW, &sc->baud_rate[IIC_SLOW]);
+ mv_twsi_cal_baud_rate(TWSI_BAUD_RATE_FAST, &sc->baud_rate[IIC_FAST]);
+ if (bootverbose)
+ device_printf(dev, "calculated baud rates are:\n"
+ " %" PRIu32 " kHz (M=%d, N=%d) for slow,\n"
+ " %" PRIu32 " kHz (M=%d, N=%d) for fast.\n",
+ sc->baud_rate[IIC_SLOW].raw / 1000,
+ sc->baud_rate[IIC_SLOW].m,
+ sc->baud_rate[IIC_SLOW].n,
+ sc->baud_rate[IIC_FAST].raw / 1000,
+ sc->baud_rate[IIC_FAST].m,
+ sc->baud_rate[IIC_FAST].n);
+
+
+ ret = twsi_attach(dev);
+ if (ret != 0)
+ return (ret);
+
+ iicbusnode = 0;
+ /* Find iicbus as the child devices in the device tree. */
+ for (child = OF_child(ofw_bus_get_node(dev)); child != 0;
+ child = OF_peer(child)) {
+ len = OF_getproplen(child, "model");
+ if (len <= 0 || len > sizeof(dname))
+ continue;
+ error = OF_getprop(child, "model", &dname, len);
+ if (error == -1)
+ continue;
+ len = strlen(dname);
+ if (len == strlen(IICBUS_DEVNAME) &&
+ strncasecmp(dname, IICBUS_DEVNAME, len) == 0) {
+ iicbusnode = child;
+ break;
+ }
+ }
+ if (iicbusnode == 0)
+ goto attach_end;
+
+ /* Attach child devices onto iicbus. */
+ for (child = OF_child(iicbusnode); child != 0; child = OF_peer(child)) {
+ /* Get slave address. */
+ error = OF_getencprop(child, "i2c-address", &paddr, sizeof(paddr));
+ if (error == -1)
+ error = OF_getencprop(child, "reg", &paddr, sizeof(paddr));
+ if (error == -1)
+ continue;
+
+ /* Get device driver name. */
+ len = OF_getproplen(child, "model");
+ if (len <= 0 || len > sizeof(dname))
+ continue;
+ OF_getprop(child, "model", &dname, len);
+
+ if (bootverbose)
+ device_printf(dev, "adding a device %s at %d.\n",
+ dname, paddr);
+ childdev = BUS_ADD_CHILD(sc->iicbus, 0, dname, -1);
+ devi = IICBUS_IVAR(childdev);
+ devi->addr = paddr;
+ }
+
+attach_end:
+ bus_generic_attach(sc->iicbus);
+
+ return (0);
+}
diff --git a/sys/dev/iicbus/twsi/twsi.c b/sys/dev/iicbus/twsi/twsi.c
new file mode 100644
index 0000000..1b27956
--- /dev/null
+++ b/sys/dev/iicbus/twsi/twsi.c
@@ -0,0 +1,481 @@
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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.
+ */
+
+/*
+ * Driver for the TWSI (aka I2C, aka IIC) bus controller found on Marvell
+ * and Allwinner SoCs. Supports master operation only, and works in polling mode.
+ *
+ * Calls to DELAY() are needed per Application Note AN-179 "TWSI Software
+ * Guidelines for Discovery(TM), Horizon (TM) and Feroceon(TM) Devices".
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+
+#include <machine/_inttypes.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <sys/rman.h>
+
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/iicbus/twsi/twsi.h>
+
+#include "iicbus_if.h"
+
+#define TWSI_CONTROL_ACK (1 << 2)
+#define TWSI_CONTROL_IFLG (1 << 3)
+#define TWSI_CONTROL_STOP (1 << 4)
+#define TWSI_CONTROL_START (1 << 5)
+#define TWSI_CONTROL_TWSIEN (1 << 6)
+#define TWSI_CONTROL_INTEN (1 << 7)
+
+#define TWSI_STATUS_START 0x08
+#define TWSI_STATUS_RPTD_START 0x10
+#define TWSI_STATUS_ADDR_W_ACK 0x18
+#define TWSI_STATUS_DATA_WR_ACK 0x28
+#define TWSI_STATUS_ADDR_R_ACK 0x40
+#define TWSI_STATUS_DATA_RD_ACK 0x50
+#define TWSI_STATUS_DATA_RD_NOACK 0x58
+
+#define TWSI_DEBUG
+#undef TWSI_DEBUG
+
+#ifdef TWSI_DEBUG
+#define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+static struct resource_spec res_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static __inline uint32_t
+TWSI_READ(struct twsi_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->res[0], off));
+}
+
+static __inline void
+TWSI_WRITE(struct twsi_softc *sc, bus_size_t off, uint32_t val)
+{
+
+ bus_write_4(sc->res[0], off, val);
+}
+
+static __inline void
+twsi_control_clear(struct twsi_softc *sc, uint32_t mask)
+{
+ uint32_t val;
+
+ val = TWSI_READ(sc, sc->reg_control);
+ val &= ~mask;
+ TWSI_WRITE(sc, sc->reg_control, val);
+}
+
+static __inline void
+twsi_control_set(struct twsi_softc *sc, uint32_t mask)
+{
+ uint32_t val;
+
+ val = TWSI_READ(sc, sc->reg_control);
+ val |= mask;
+ TWSI_WRITE(sc, sc->reg_control, val);
+}
+
+static __inline void
+twsi_clear_iflg(struct twsi_softc *sc)
+{
+
+ DELAY(1000);
+ twsi_control_clear(sc, TWSI_CONTROL_IFLG);
+ DELAY(1000);
+}
+
+
+/*
+ * timeout given in us
+ * returns
+ * 0 on sucessfull mask change
+ * non-zero on timeout
+ */
+static int
+twsi_poll_ctrl(struct twsi_softc *sc, int timeout, uint32_t mask)
+{
+
+ timeout /= 10;
+ while (!(TWSI_READ(sc, sc->reg_control) & mask)) {
+ DELAY(10);
+ if (--timeout < 0)
+ return (timeout);
+ }
+ return (0);
+}
+
+
+/*
+ * 'timeout' is given in us. Note also that timeout handling is not exact --
+ * twsi_locked_start() total wait can be more than 2 x timeout
+ * (twsi_poll_ctrl() is called twice). 'mask' can be either TWSI_STATUS_START
+ * or TWSI_STATUS_RPTD_START
+ */
+static int
+twsi_locked_start(device_t dev, struct twsi_softc *sc, int32_t mask,
+ u_char slave, int timeout)
+{
+ int read_access, iflg_set = 0;
+ uint32_t status;
+
+ mtx_assert(&sc->mutex, MA_OWNED);
+
+ if (mask == TWSI_STATUS_RPTD_START)
+ /* read IFLG to know if it should be cleared later; from NBSD */
+ iflg_set = TWSI_READ(sc, sc->reg_control) & TWSI_CONTROL_IFLG;
+
+ twsi_control_set(sc, TWSI_CONTROL_START);
+
+ if (mask == TWSI_STATUS_RPTD_START && iflg_set) {
+ debugf("IFLG set, clearing\n");
+ twsi_clear_iflg(sc);
+ }
+
+ /*
+ * Without this delay we timeout checking IFLG if the timeout is 0.
+ * NBSD driver always waits here too.
+ */
+ DELAY(1000);
+
+ if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
+ debugf("timeout sending %sSTART condition\n",
+ mask == TWSI_STATUS_START ? "" : "repeated ");
+ return (IIC_ETIMEOUT);
+ }
+
+ status = TWSI_READ(sc, sc->reg_status);
+ if (status != mask) {
+ debugf("wrong status (%02x) after sending %sSTART condition\n",
+ status, mask == TWSI_STATUS_START ? "" : "repeated ");
+ return (IIC_ESTATUS);
+ }
+
+ TWSI_WRITE(sc, sc->reg_data, slave);
+ DELAY(1000);
+ twsi_clear_iflg(sc);
+
+ if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
+ debugf("timeout sending slave address\n");
+ return (IIC_ETIMEOUT);
+ }
+
+ read_access = (slave & 0x1) ? 1 : 0;
+ status = TWSI_READ(sc, sc->reg_status);
+ if (status != (read_access ?
+ TWSI_STATUS_ADDR_R_ACK : TWSI_STATUS_ADDR_W_ACK)) {
+ debugf("no ACK (status: %02x) after sending slave address\n",
+ status);
+ return (IIC_ENOACK);
+ }
+
+ return (IIC_NOERR);
+}
+
+/*
+ * Only slave mode supported, disregard [old]addr
+ */
+static int
+twsi_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
+{
+ struct twsi_softc *sc;
+ uint32_t param;
+
+ sc = device_get_softc(dev);
+
+ switch (speed) {
+ case IIC_SLOW:
+ case IIC_FAST:
+ param = sc->baud_rate[speed].param;
+ break;
+ case IIC_FASTEST:
+ case IIC_UNKNOWN:
+ default:
+ param = sc->baud_rate[IIC_FAST].param;
+ break;
+ }
+
+ mtx_lock(&sc->mutex);
+ TWSI_WRITE(sc, sc->reg_soft_reset, 0x0);
+ DELAY(2000);
+ TWSI_WRITE(sc, sc->reg_baud_rate, param);
+ TWSI_WRITE(sc, sc->reg_control, TWSI_CONTROL_TWSIEN | TWSI_CONTROL_ACK);
+ DELAY(1000);
+ mtx_unlock(&sc->mutex);
+
+ return (0);
+}
+
+static int
+twsi_stop(device_t dev)
+{
+ struct twsi_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ mtx_lock(&sc->mutex);
+ twsi_control_set(sc, TWSI_CONTROL_STOP);
+ DELAY(1000);
+ twsi_clear_iflg(sc);
+ mtx_unlock(&sc->mutex);
+
+ return (IIC_NOERR);
+}
+
+/*
+ * timeout is given in us
+ */
+static int
+twsi_repeated_start(device_t dev, u_char slave, int timeout)
+{
+ struct twsi_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+
+ mtx_lock(&sc->mutex);
+ rv = twsi_locked_start(dev, sc, TWSI_STATUS_RPTD_START, slave,
+ timeout);
+ mtx_unlock(&sc->mutex);
+
+ if (rv) {
+ twsi_stop(dev);
+ return (rv);
+ } else
+ return (IIC_NOERR);
+}
+
+/*
+ * timeout is given in us
+ */
+static int
+twsi_start(device_t dev, u_char slave, int timeout)
+{
+ struct twsi_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+
+ mtx_lock(&sc->mutex);
+ rv = twsi_locked_start(dev, sc, TWSI_STATUS_START, slave, timeout);
+ mtx_unlock(&sc->mutex);
+
+ if (rv) {
+ twsi_stop(dev);
+ return (rv);
+ } else
+ return (IIC_NOERR);
+}
+
+static int
+twsi_read(device_t dev, char *buf, int len, int *read, int last, int delay)
+{
+ struct twsi_softc *sc;
+ uint32_t status;
+ int last_byte, rv;
+
+ sc = device_get_softc(dev);
+
+ mtx_lock(&sc->mutex);
+ *read = 0;
+ while (*read < len) {
+ /*
+ * Check if we are reading last byte of the last buffer,
+ * do not send ACK then, per I2C specs
+ */
+ last_byte = ((*read == len - 1) && last) ? 1 : 0;
+ if (last_byte)
+ twsi_control_clear(sc, TWSI_CONTROL_ACK);
+ else
+ twsi_control_set(sc, TWSI_CONTROL_ACK);
+
+ DELAY (1000);
+ twsi_clear_iflg(sc);
+
+ if (twsi_poll_ctrl(sc, delay, TWSI_CONTROL_IFLG)) {
+ debugf("timeout reading data\n");
+ rv = IIC_ETIMEOUT;
+ goto out;
+ }
+
+ status = TWSI_READ(sc, sc->reg_status);
+ if (status != (last_byte ?
+ TWSI_STATUS_DATA_RD_NOACK : TWSI_STATUS_DATA_RD_ACK)) {
+ debugf("wrong status (%02x) while reading\n", status);
+ rv = IIC_ESTATUS;
+ goto out;
+ }
+
+ *buf++ = TWSI_READ(sc, sc->reg_data);
+ (*read)++;
+ }
+ rv = IIC_NOERR;
+out:
+ mtx_unlock(&sc->mutex);
+ return (rv);
+}
+
+static int
+twsi_write(device_t dev, const char *buf, int len, int *sent, int timeout)
+{
+ struct twsi_softc *sc;
+ uint32_t status;
+ int rv;
+
+ sc = device_get_softc(dev);
+
+ mtx_lock(&sc->mutex);
+ *sent = 0;
+ while (*sent < len) {
+ TWSI_WRITE(sc, sc->reg_data, *buf++);
+
+ twsi_clear_iflg(sc);
+ if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
+ debugf("timeout writing data\n");
+ rv = IIC_ETIMEOUT;
+ goto out;
+ }
+
+ status = TWSI_READ(sc, sc->reg_status);
+ if (status != TWSI_STATUS_DATA_WR_ACK) {
+ debugf("wrong status (%02x) while writing\n", status);
+ rv = IIC_ESTATUS;
+ goto out;
+ }
+ (*sent)++;
+ }
+ rv = IIC_NOERR;
+out:
+ mtx_unlock(&sc->mutex);
+ return (rv);
+}
+
+int
+twsi_attach(device_t dev)
+{
+ struct twsi_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ mtx_init(&sc->mutex, device_get_nameunit(dev), "twsi", MTX_DEF);
+
+ if (bus_alloc_resources(dev, res_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ twsi_detach(dev);
+ return (ENXIO);
+ }
+
+ /* Attach the iicbus. */
+ if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) {
+ device_printf(dev, "could not allocate iicbus instance\n");
+ twsi_detach(dev);
+ return (ENXIO);
+ }
+ bus_generic_attach(dev);
+
+ return (0);
+}
+
+int
+twsi_detach(device_t dev)
+{
+ struct twsi_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+
+ if ((rv = bus_generic_detach(dev)) != 0)
+ return (rv);
+
+ if (sc->iicbus != NULL)
+ if ((rv = device_delete_child(dev, sc->iicbus)) != 0)
+ return (rv);
+
+ bus_release_resources(dev, res_spec, sc->res);
+
+ mtx_destroy(&sc->mutex);
+ return (0);
+}
+
+static device_method_t twsi_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_detach, twsi_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
+ DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
+ DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+
+ /* iicbus interface */
+ DEVMETHOD(iicbus_callback, iicbus_null_callback),
+ DEVMETHOD(iicbus_repeated_start, twsi_repeated_start),
+ DEVMETHOD(iicbus_start, twsi_start),
+ DEVMETHOD(iicbus_stop, twsi_stop),
+ DEVMETHOD(iicbus_write, twsi_write),
+ DEVMETHOD(iicbus_read, twsi_read),
+ DEVMETHOD(iicbus_reset, twsi_reset),
+ DEVMETHOD(iicbus_transfer, iicbus_transfer_gen),
+ { 0, 0 }
+};
+
+DEFINE_CLASS_0(twsi, twsi_driver, twsi_methods,
+ sizeof(struct twsi_softc));
diff --git a/sys/dev/iicbus/twsi/twsi.h b/sys/dev/iicbus/twsi/twsi.h
new file mode 100644
index 0000000..a95db82
--- /dev/null
+++ b/sys/dev/iicbus/twsi/twsi.h
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of MARVELL nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _TWSI_H_
+#define _TWSI_H_
+
+struct twsi_baud_rate {
+ uint32_t raw;
+ int param;
+ int m;
+ int n;
+};
+
+struct twsi_softc {
+ device_t dev;
+ struct resource *res[1]; /* SYS_RES_MEMORY */
+ struct mtx mutex;
+ device_t iicbus;
+
+ bus_size_t reg_data;
+ bus_size_t reg_slave_addr;
+ bus_size_t reg_slave_ext_addr;
+ bus_size_t reg_control;
+ bus_size_t reg_status;
+ bus_size_t reg_baud_rate;
+ bus_size_t reg_soft_reset;
+ struct twsi_baud_rate baud_rate[IIC_FASTEST + 1];
+};
+
+DECLARE_CLASS(twsi_driver);
+
+#define TWSI_BAUD_RATE_PARAM(M,N) ((((M) << 3) | ((N) & 0x7)) & 0x7f)
+
+int twsi_attach(device_t);
+int twsi_detach(device_t);
+
+#endif /* _TWSI_H_ */
diff --git a/sys/dev/ioat/ioat.c b/sys/dev/ioat/ioat.c
index 956e8d1..bcc4e9a 100644
--- a/sys/dev/ioat/ioat.c
+++ b/sys/dev/ioat/ioat.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
#include <sys/sbuf.h>
#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
#include <sys/time.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
@@ -92,6 +93,7 @@ static void ioat_submit_single(struct ioat_softc *ioat);
static void ioat_comp_update_map(void *arg, bus_dma_segment_t *seg, int nseg,
int error);
static int ioat_reset_hw(struct ioat_softc *ioat);
+static void ioat_reset_hw_task(void *, int);
static void ioat_setup_sysctl(device_t device);
static int sysctl_handle_reset(SYSCTL_HANDLER_ARGS);
static inline struct ioat_softc *ioat_get(struct ioat_softc *,
@@ -308,6 +310,7 @@ ioat_detach(device_t device)
ioat = DEVICE2SOFTC(device);
ioat_test_detach();
+ taskqueue_drain(taskqueue_thread, &ioat->reset_task);
mtx_lock(IOAT_REFLK);
ioat->quiescing = TRUE;
@@ -414,6 +417,7 @@ ioat3_attach(device_t device)
mtx_init(&ioat->submit_lock, "ioat_submit", NULL, MTX_DEF);
mtx_init(&ioat->cleanup_lock, "ioat_cleanup", NULL, MTX_DEF);
callout_init(&ioat->timer, 1);
+ TASK_INIT(&ioat->reset_task, 0, ioat_reset_hw_task, ioat);
/* Establish lock order for Witness */
mtx_lock(&ioat->submit_lock);
@@ -630,8 +634,14 @@ ioat_process_events(struct ioat_softc *ioat)
CTR0(KTR_IOAT, __func__);
- if (status == ioat->last_seen)
+ if (status == ioat->last_seen) {
+ /*
+ * If we landed in process_events and nothing has been
+ * completed, check for a timeout due to channel halt.
+ */
+ comp_update = ioat_get_chansts(ioat);
goto out;
+ }
while (1) {
desc = ioat_get_ring_entry(ioat, ioat->tail);
@@ -661,10 +671,12 @@ out:
ioat_write_chanctrl(ioat, IOAT_CHANCTRL_RUN);
mtx_unlock(&ioat->cleanup_lock);
- ioat_putn(ioat, completed, IOAT_ACTIVE_DESCR_REF);
- wakeup(&ioat->tail);
+ if (completed != 0) {
+ ioat_putn(ioat, completed, IOAT_ACTIVE_DESCR_REF);
+ wakeup(&ioat->tail);
+ }
- if (!is_ioat_halted(comp_update))
+ if (!is_ioat_halted(comp_update) && !is_ioat_suspended(comp_update))
return;
ioat->stats.channel_halts++;
@@ -704,8 +716,23 @@ out:
mtx_unlock(&ioat->submit_lock);
ioat_log_message(0, "Resetting channel to recover from error\n");
+ error = taskqueue_enqueue(taskqueue_thread, &ioat->reset_task);
+ KASSERT(error == 0,
+ ("%s: taskqueue_enqueue failed: %d", __func__, error));
+}
+
+static void
+ioat_reset_hw_task(void *ctx, int pending __unused)
+{
+ struct ioat_softc *ioat;
+ int error;
+
+ ioat = ctx;
+ ioat_log_message(1, "%s: Resetting channel\n", __func__);
+
error = ioat_reset_hw(ioat);
KASSERT(error == 0, ("%s: reset failed: %d", __func__, error));
+ (void)error;
}
/*
diff --git a/sys/dev/ioat/ioat_hw.h b/sys/dev/ioat/ioat_hw.h
index 46ffaeb..6dfe9a6 100644
--- a/sys/dev/ioat/ioat_hw.h
+++ b/sys/dev/ioat/ioat_hw.h
@@ -56,8 +56,13 @@ __FBSDID("$FreeBSD$");
#define IOAT_DMACAPABILITY_OFFSET 0x10
#define IOAT_DMACAP_PB (1 << 0)
+#define IOAT_DMACAP_CRC (1 << 1)
+#define IOAT_DMACAP_MARKER_SKIP (1 << 2)
+#define IOAT_DMACAP_OLD_XOR (1 << 3)
#define IOAT_DMACAP_DCA (1 << 4)
+#define IOAT_DMACAP_MOVECRC (1 << 5)
#define IOAT_DMACAP_BFILL (1 << 6)
+#define IOAT_DMACAP_EXT_APIC (1 << 7)
#define IOAT_DMACAP_XOR (1 << 8)
#define IOAT_DMACAP_PQ (1 << 9)
#define IOAT_DMACAP_DMA_DIF (1 << 10)
@@ -69,7 +74,8 @@ __FBSDID("$FreeBSD$");
#define IOAT_DMACAP_STR \
"\20\24Completion_Timeout_Support\23DMA_with_Multicasting_Support" \
"\22RAID_Super_descriptors\16Descriptor_Write_Back_Error_Support" \
- "\13DMA_with_DIF\12PQ\11XOR\07Block_Fill\05DCA\01Page_Break"
+ "\13DMA_with_DIF\12PQ\11XOR\10Extended_APIC_ID\07Block_Fill\06Move_CRC" \
+ "\05DCA\04Old_XOR\03Marker_Skipping\02CRC\01Page_Break"
/* DMA Channel Registers */
#define IOAT_CHANCTRL_OFFSET 0x80
diff --git a/sys/dev/ioat/ioat_internal.h b/sys/dev/ioat/ioat_internal.h
index 1b24851..b33faea 100644
--- a/sys/dev/ioat/ioat_internal.h
+++ b/sys/dev/ioat/ioat_internal.h
@@ -29,6 +29,8 @@ __FBSDID("$FreeBSD$");
#ifndef __IOAT_INTERNAL_H__
#define __IOAT_INTERNAL_H__
+#include <sys/_task.h>
+
#define DEVICE2SOFTC(dev) ((struct ioat_softc *) device_get_softc(dev))
#define KTR_IOAT KTR_SPARE3
@@ -346,6 +348,22 @@ struct ioat_descriptor {
bus_addr_t hw_desc_bus_addr;
};
+/* Unsupported by this driver at this time. */
+#define IOAT_OP_MOVECRC 0x41
+#define IOAT_OP_MOVECRC_TEST 0x42
+#define IOAT_OP_MOVECRC_STORE 0x43
+#define IOAT_OP_CRC 0x81
+#define IOAT_OP_CRC_TEST 0x82
+#define IOAT_OP_CRC_STORE 0x83
+#define IOAT_OP_MARKER 0x84
+
+/*
+ * Deprecated OPs -- v3 DMA generates an abort if given these. And this driver
+ * doesn't support anything older than v3.
+ */
+#define IOAT_OP_OLD_XOR 0x85
+#define IOAT_OP_OLD_XOR_VAL 0x86
+
enum ioat_ref_kind {
IOAT_DMAENGINE_REF = 0,
IOAT_ACTIVE_DESCR_REF,
@@ -389,6 +407,7 @@ struct ioat_softc {
bus_addr_t comp_update_bus_addr;
struct callout timer;
+ struct task reset_task;
boolean_t quiescing;
boolean_t is_resize_pending;
diff --git a/sys/dev/iscsi/icl.c b/sys/dev/iscsi/icl.c
index 2e92f2a..c679523 100644
--- a/sys/dev/iscsi/icl.c
+++ b/sys/dev/iscsi/icl.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/queue.h>
+#include <sys/sbuf.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/sx.h>
@@ -66,13 +67,42 @@ struct icl_softc {
TAILQ_HEAD(, icl_module) sc_modules;
};
+static int sysctl_kern_icl_drivers(SYSCTL_HANDLER_ARGS);
+static MALLOC_DEFINE(M_ICL, "icl", "iSCSI Common Layer");
+static struct icl_softc *sc;
+
SYSCTL_NODE(_kern, OID_AUTO, icl, CTLFLAG_RD, 0, "iSCSI Common Layer");
int icl_debug = 1;
SYSCTL_INT(_kern_icl, OID_AUTO, debug, CTLFLAG_RWTUN,
&icl_debug, 0, "Enable debug messages");
+SYSCTL_PROC(_kern_icl, OID_AUTO, drivers,
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ NULL, 0, sysctl_kern_icl_drivers, "A",
+ "List of ICL drivers");
-static MALLOC_DEFINE(M_ICL, "icl", "iSCSI Common Layer");
-static struct icl_softc *sc;
+static int
+sysctl_kern_icl_drivers(SYSCTL_HANDLER_ARGS)
+{
+ const struct icl_module *im;
+ struct sbuf sb;
+ int error;
+
+ sbuf_new(&sb, NULL, 256, SBUF_AUTOEXTEND | SBUF_INCLUDENUL);
+
+ sx_slock(&sc->sc_lock);
+ TAILQ_FOREACH(im, &sc->sc_modules, im_next) {
+ if (im != TAILQ_FIRST(&sc->sc_modules))
+ sbuf_putc(&sb, ' ');
+ sbuf_printf(&sb, "%s", im->im_name);
+ }
+ sx_sunlock(&sc->sc_lock);
+
+ error = sbuf_finish(&sb);
+ if (error == 0)
+ error = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb));
+ sbuf_delete(&sb);
+ return (error);
+}
static struct icl_module *
icl_find(const char *name)
diff --git a/sys/dev/iscsi/iscsi.h b/sys/dev/iscsi/iscsi.h
index a2475f4..3225649 100644
--- a/sys/dev/iscsi/iscsi.h
+++ b/sys/dev/iscsi/iscsi.h
@@ -119,7 +119,7 @@ struct iscsi_session {
char is_reason[ISCSI_REASON_LEN];
#ifdef ICL_KERNEL_PROXY
- struct cv is_login_cv;;
+ struct cv is_login_cv;
struct icl_pdu *is_login_pdu;
#endif
};
diff --git a/sys/dev/ntb/ntb_hw/ntb_hw.c b/sys/dev/ntb/ntb_hw/ntb_hw.c
index f71d9e4..90b27a3 100644
--- a/sys/dev/ntb/ntb_hw/ntb_hw.c
+++ b/sys/dev/ntb/ntb_hw/ntb_hw.c
@@ -35,6 +35,8 @@ __FBSDID("$FreeBSD$");
#include <sys/endian.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/pciio.h>
#include <sys/queue.h>
#include <sys/rman.h>
#include <sys/sbuf.h>
@@ -42,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/bus.h>
+#include <machine/intr_machdep.h>
#include <machine/pmap.h>
#include <machine/resource.h>
#include <dev/pci/pcireg.h>
@@ -70,6 +73,19 @@ __FBSDID("$FreeBSD$");
#define DEVICE2SOFTC(dev) ((struct ntb_softc *) device_get_softc(dev))
+#define NTB_MSIX_VER_GUARD 0xaabbccdd
+#define NTB_MSIX_RECEIVED 0xe0f0e0f0
+#define ONE_MB (1024u * 1024)
+
+/*
+ * PCI constants could be somewhere more generic, but aren't defined/used in
+ * pci.c.
+ */
+#define PCI_MSIX_ENTRY_SIZE 16
+#define PCI_MSIX_ENTRY_LOWER_ADDR 0
+#define PCI_MSIX_ENTRY_UPPER_ADDR 4
+#define PCI_MSIX_ENTRY_DATA 8
+
enum ntb_device_type {
NTB_XEON,
NTB_ATOM
@@ -95,6 +111,18 @@ enum ntb_bar {
NTB_MAX_BARS
};
+enum {
+ NTB_MSIX_GUARD = 0,
+ NTB_MSIX_DATA0,
+ NTB_MSIX_DATA1,
+ NTB_MSIX_DATA2,
+ NTB_MSIX_OFS0,
+ NTB_MSIX_OFS1,
+ NTB_MSIX_OFS2,
+ NTB_MSIX_DONE,
+ NTB_MAX_MSIX_SPAD
+};
+
/* Device features and workarounds */
#define HAS_FEATURE(feature) \
((ntb->features & (feature)) != 0)
@@ -131,6 +159,7 @@ struct ntb_int_info {
struct ntb_vec {
struct ntb_softc *ntb;
uint32_t num;
+ unsigned masked;
};
struct ntb_reg {
@@ -169,6 +198,11 @@ struct ntb_b2b_addr {
uint64_t bar5_addr32;
};
+struct ntb_msix_data {
+ uint32_t nmd_ofs;
+ uint32_t nmd_data;
+};
+
struct ntb_softc {
device_t device;
enum ntb_device_type type;
@@ -178,6 +212,13 @@ struct ntb_softc {
struct ntb_int_info int_info[MAX_MSIX_INTERRUPTS];
uint32_t allocated_interrupts;
+ struct ntb_msix_data peer_msix_data[XEON_NONLINK_DB_MSIX_BITS];
+ struct ntb_msix_data msix_data[XEON_NONLINK_DB_MSIX_BITS];
+ bool peer_msix_good;
+ bool peer_msix_done;
+ struct ntb_pci_bar_info *peer_lapic_bar;
+ struct callout peer_msix_work;
+
struct callout heartbeat_timer;
struct callout lr_timer;
@@ -198,6 +239,7 @@ struct ntb_softc {
/* Memory window used to access peer bar0 */
#define B2B_MW_DISABLED UINT8_MAX
uint8_t b2b_mw_idx;
+ uint8_t msix_mw_idx;
uint8_t mw_count;
uint8_t spad_count;
@@ -292,6 +334,8 @@ static inline void db_iowrite(struct ntb_softc *, uint64_t regoff, uint64_t);
static inline void db_iowrite_raw(struct ntb_softc *, uint64_t regoff, uint64_t);
static int ntb_create_msix_vec(struct ntb_softc *ntb, uint32_t num_vectors);
static void ntb_free_msix_vec(struct ntb_softc *ntb);
+static void ntb_get_msix_info(struct ntb_softc *ntb, uint32_t num_vectors);
+static void ntb_exchange_msix(void *);
static struct ntb_hw_info *ntb_get_device_info(uint32_t device_id);
static void ntb_detect_max_mw(struct ntb_softc *ntb);
static int ntb_detect_xeon(struct ntb_softc *ntb);
@@ -308,7 +352,9 @@ static void xeon_set_pbar_xlat(struct ntb_softc *, uint64_t base_addr,
enum ntb_bar idx);
static int xeon_setup_b2b_mw(struct ntb_softc *,
const struct ntb_b2b_addr *addr, const struct ntb_b2b_addr *peer_addr);
+static int xeon_setup_msix_bar(struct ntb_softc *);
static inline bool link_is_up(struct ntb_softc *ntb);
+static inline bool _xeon_link_is_up(struct ntb_softc *ntb);
static inline bool atom_link_is_err(struct ntb_softc *ntb);
static inline enum ntb_speed ntb_link_sta_speed(struct ntb_softc *);
static inline enum ntb_width ntb_link_sta_width(struct ntb_softc *);
@@ -331,9 +377,76 @@ SYSCTL_UINT(_hw_ntb, OID_AUTO, debug_level, CTLFLAG_RWTUN,
} \
} while (0)
-static unsigned g_ntb_enable_wc = 1;
-SYSCTL_UINT(_hw_ntb, OID_AUTO, enable_writecombine, CTLFLAG_RDTUN,
- &g_ntb_enable_wc, 0, "Set to 1 to map memory windows write combining");
+#define _NTB_PAT_UC 0
+#define _NTB_PAT_WC 1
+#define _NTB_PAT_WT 4
+#define _NTB_PAT_WP 5
+#define _NTB_PAT_WB 6
+#define _NTB_PAT_UCM 7
+static unsigned g_ntb_mw_pat = _NTB_PAT_UC;
+SYSCTL_UINT(_hw_ntb, OID_AUTO, default_mw_pat, CTLFLAG_RDTUN,
+ &g_ntb_mw_pat, 0, "Configure the default memory window cache flags (PAT): "
+ "UC: " __XSTRING(_NTB_PAT_UC) ", "
+ "WC: " __XSTRING(_NTB_PAT_WC) ", "
+ "WT: " __XSTRING(_NTB_PAT_WT) ", "
+ "WP: " __XSTRING(_NTB_PAT_WP) ", "
+ "WB: " __XSTRING(_NTB_PAT_WB) ", "
+ "UC-: " __XSTRING(_NTB_PAT_UCM));
+
+static inline vm_memattr_t
+ntb_pat_flags(void)
+{
+
+ switch (g_ntb_mw_pat) {
+ case _NTB_PAT_WC:
+ return (VM_MEMATTR_WRITE_COMBINING);
+ case _NTB_PAT_WT:
+ return (VM_MEMATTR_WRITE_THROUGH);
+ case _NTB_PAT_WP:
+ return (VM_MEMATTR_WRITE_PROTECTED);
+ case _NTB_PAT_WB:
+ return (VM_MEMATTR_WRITE_BACK);
+ case _NTB_PAT_UCM:
+ return (VM_MEMATTR_WEAK_UNCACHEABLE);
+ case _NTB_PAT_UC:
+ /* FALLTHROUGH */
+ default:
+ return (VM_MEMATTR_UNCACHEABLE);
+ }
+}
+
+/*
+ * Well, this obviously doesn't belong here, but it doesn't seem to exist
+ * anywhere better yet.
+ */
+static inline const char *
+ntb_vm_memattr_to_str(vm_memattr_t pat)
+{
+
+ switch (pat) {
+ case VM_MEMATTR_WRITE_COMBINING:
+ return ("WRITE_COMBINING");
+ case VM_MEMATTR_WRITE_THROUGH:
+ return ("WRITE_THROUGH");
+ case VM_MEMATTR_WRITE_PROTECTED:
+ return ("WRITE_PROTECTED");
+ case VM_MEMATTR_WRITE_BACK:
+ return ("WRITE_BACK");
+ case VM_MEMATTR_WEAK_UNCACHEABLE:
+ return ("UNCACHED");
+ case VM_MEMATTR_UNCACHEABLE:
+ return ("UNCACHEABLE");
+ default:
+ return ("UNKNOWN");
+ }
+}
+
+static int g_ntb_msix_idx = 0;
+SYSCTL_INT(_hw_ntb, OID_AUTO, msix_mw_idx, CTLFLAG_RDTUN, &g_ntb_msix_idx,
+ 0, "Use this memory window to access the peer MSIX message complex on "
+ "certain Xeon-based NTB systems, as a workaround for a hardware errata. "
+ "Like b2b_mw_idx, negative values index from the last available memory "
+ "window. (Applies on Xeon platforms with SB01BASE_LOCKUP errata.)");
static int g_ntb_mw_idx = -1;
SYSCTL_INT(_hw_ntb, OID_AUTO, b2b_mw_idx, CTLFLAG_RDTUN, &g_ntb_mw_idx,
@@ -533,10 +646,12 @@ ntb_attach(device_t device)
ntb->type = p->type;
ntb->features = p->features;
ntb->b2b_mw_idx = B2B_MW_DISABLED;
+ ntb->msix_mw_idx = B2B_MW_DISABLED;
/* Heartbeat timer for NTB_ATOM since there is no link interrupt */
callout_init(&ntb->heartbeat_timer, 1);
callout_init(&ntb->lr_timer, 1);
+ callout_init(&ntb->peer_msix_work, 1);
mtx_init(&ntb->db_mask_lock, "ntb hw bits", NULL, MTX_SPIN);
mtx_init(&ntb->ctx_lock, "ntb ctx", NULL, MTX_DEF);
@@ -561,6 +676,8 @@ ntb_attach(device_t device)
if (error != 0)
goto out;
+ ntb_spad_clear(ntb);
+
ntb_poll_link(ntb);
ntb_sysctl_init(ntb);
@@ -578,10 +695,14 @@ ntb_detach(device_t device)
ntb = DEVICE2SOFTC(device);
- if (ntb->self_reg != NULL)
- ntb_db_set_mask(ntb, ntb->db_valid_mask);
+ if (ntb->self_reg != NULL) {
+ DB_MASK_LOCK(ntb);
+ db_iowrite(ntb, ntb->self_reg->db_mask, ntb->db_valid_mask);
+ DB_MASK_UNLOCK(ntb);
+ }
callout_drain(&ntb->heartbeat_timer);
callout_drain(&ntb->lr_timer);
+ callout_drain(&ntb->peer_msix_work);
pci_disable_busmaster(ntb->device);
if (ntb->type == NTB_XEON)
ntb_teardown_xeon(ntb);
@@ -777,10 +898,13 @@ map_memory_window_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar)
bar->map_mode = VM_MEMATTR_UNCACHEABLE;
print_map_success(ntb, bar, "mw");
- /* Mark bar region as write combining to improve performance. */
- mapmode = VM_MEMATTR_WRITE_COMBINING;
- if (g_ntb_enable_wc == 0)
- mapmode = VM_MEMATTR_WRITE_BACK;
+ /*
+ * Optionally, mark MW BARs as anything other than UC to improve
+ * performance.
+ */
+ mapmode = ntb_pat_flags();
+ if (mapmode == bar->map_mode)
+ return (0);
rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size, mapmode);
if (rc == 0) {
@@ -791,8 +915,7 @@ map_memory_window_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar)
PCI_RID2BAR(bar->pci_resource_id), bar->vbase,
(char *)bar->vbase + bar->size - 1,
(void *)bar->pbase, (void *)(bar->pbase + bar->size - 1),
- (mapmode == VM_MEMATTR_WRITE_COMBINING) ? "WRITE_COMBINING"
- : "WRITE_BACK");
+ ntb_vm_memattr_to_str(mapmode));
} else
device_printf(ntb->device,
"Unable to mark BAR%d v:[%p-%p] p:[%p-%p] as "
@@ -800,8 +923,7 @@ map_memory_window_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar)
PCI_RID2BAR(bar->pci_resource_id), bar->vbase,
(char *)bar->vbase + bar->size - 1,
(void *)bar->pbase, (void *)(bar->pbase + bar->size - 1),
- (mapmode == VM_MEMATTR_WRITE_COMBINING) ? "WRITE_COMBINING"
- : "WRITE_BACK", rc);
+ ntb_vm_memattr_to_str(mapmode), rc);
/* Proceed anyway */
return (0);
}
@@ -904,9 +1026,12 @@ ntb_init_isr(struct ntb_softc *ntb)
ntb->last_ts = ticks;
/*
- * Mask all doorbell interrupts.
+ * Mask all doorbell interrupts. (Except link events!)
*/
- ntb_db_set_mask(ntb, ntb->db_valid_mask);
+ DB_MASK_LOCK(ntb);
+ ntb->db_mask = ntb->db_valid_mask;
+ db_iowrite(ntb, ntb->self_reg->db_mask, ntb->db_mask);
+ DB_MASK_UNLOCK(ntb);
num_vectors = desired_vectors = MIN(pci_msix_count(ntb->device),
ntb->db_count);
@@ -931,12 +1056,20 @@ ntb_init_isr(struct ntb_softc *ntb)
num_vectors = 1;
if (ntb->type == NTB_XEON && num_vectors < ntb->db_vec_count) {
+ if (HAS_FEATURE(NTB_SB01BASE_LOCKUP)) {
+ device_printf(ntb->device,
+ "Errata workaround does not support MSI or INTX\n");
+ return (EINVAL);
+ }
+
ntb->db_vec_count = 1;
ntb->db_vec_shift = XEON_DB_TOTAL_SHIFT;
rc = ntb_setup_legacy_interrupt(ntb);
} else {
ntb_create_msix_vec(ntb, num_vectors);
rc = ntb_setup_msix(ntb, num_vectors);
+ if (rc == 0 && HAS_FEATURE(NTB_SB01BASE_LOCKUP))
+ ntb_get_msix_info(ntb, num_vectors);
}
if (rc != 0) {
device_printf(ntb->device,
@@ -1042,6 +1175,9 @@ void
ntb_db_set_mask(struct ntb_softc *ntb, uint64_t bits)
{
+ if (HAS_FEATURE(NTB_SB01BASE_LOCKUP))
+ return;
+
DB_MASK_LOCK(ntb);
ntb->db_mask |= bits;
db_iowrite(ntb, ntb->self_reg->db_mask, ntb->db_mask);
@@ -1057,6 +1193,9 @@ ntb_db_clear_mask(struct ntb_softc *ntb, uint64_t bits)
(uintmax_t)(bits & ~ntb->db_valid_mask),
(uintmax_t)ntb->db_valid_mask));
+ if (HAS_FEATURE(NTB_SB01BASE_LOCKUP))
+ return;
+
DB_MASK_LOCK(ntb);
ntb->db_mask &= ~bits;
db_iowrite(ntb, ntb->self_reg->db_mask, ntb->db_mask);
@@ -1067,6 +1206,18 @@ uint64_t
ntb_db_read(struct ntb_softc *ntb)
{
+ if (HAS_FEATURE(NTB_SB01BASE_LOCKUP)) {
+ uint64_t res;
+ unsigned i;
+
+ res = 0;
+ for (i = 0; i < XEON_NONLINK_DB_MSIX_BITS; i++) {
+ if (ntb->msix_vec[i].masked != 0)
+ res |= ntb_db_vector_mask(ntb, i);
+ }
+ return (res);
+ }
+
return (db_ioread(ntb, ntb->self_reg->db_bell));
}
@@ -1079,6 +1230,25 @@ ntb_db_clear(struct ntb_softc *ntb, uint64_t bits)
(uintmax_t)(bits & ~ntb->db_valid_mask),
(uintmax_t)ntb->db_valid_mask));
+ if (HAS_FEATURE(NTB_SB01BASE_LOCKUP)) {
+ unsigned i;
+
+ for (i = 0; i < XEON_NONLINK_DB_MSIX_BITS; i++) {
+ if ((bits & ntb_db_vector_mask(ntb, i)) != 0) {
+ DB_MASK_LOCK(ntb);
+ if (ntb->msix_vec[i].masked != 0) {
+ /* XXX These need a public API. */
+#if 0
+ pci_unmask_msix(ntb->device, i);
+#endif
+ ntb->msix_vec[i].masked = 0;
+ }
+ DB_MASK_UNLOCK(ntb);
+ }
+ }
+ return;
+ }
+
db_iowrite(ntb, ntb->self_reg->db_bell, bits);
}
@@ -1105,6 +1275,19 @@ ntb_interrupt(struct ntb_softc *ntb, uint32_t vec)
ntb_link_event(ntb);
}
+ if (HAS_FEATURE(NTB_SB01BASE_LOCKUP) &&
+ (vec_mask & ntb->db_link_mask) == 0) {
+ DB_MASK_LOCK(ntb);
+ if (ntb->msix_vec[vec].masked == 0) {
+ /* XXX These need a public API. */
+#if 0
+ pci_mask_msix(ntb->device, vec);
+#endif
+ ntb->msix_vec[vec].masked = 1;
+ }
+ DB_MASK_UNLOCK(ntb);
+ }
+
if ((vec_mask & ntb->db_valid_mask) != 0)
ntb_db_event(ntb, vec);
}
@@ -1150,6 +1333,38 @@ ntb_free_msix_vec(struct ntb_softc *ntb)
ntb->msix_vec = NULL;
}
+static void
+ntb_get_msix_info(struct ntb_softc *ntb, uint32_t num_vectors)
+{
+ struct pci_devinfo *dinfo;
+ struct pcicfg_msix *msix;
+ uint32_t laddr, data, i, offset;
+
+ dinfo = device_get_ivars(ntb->device);
+ msix = &dinfo->cfg.msix;
+
+ laddr = data = 0;
+
+ for (i = 0; i < num_vectors; i++) {
+ offset = msix->msix_table_offset + i * PCI_MSIX_ENTRY_SIZE;
+
+ laddr = bus_read_4(msix->msix_table_res, offset +
+ PCI_MSIX_ENTRY_LOWER_ADDR);
+ ntb_printf(2, "local lower MSIX addr(%u): 0x%x\n", i, laddr);
+
+ KASSERT((laddr & MSI_INTEL_ADDR_BASE) == MSI_INTEL_ADDR_BASE,
+ ("local MSIX addr 0x%x not in MSI base 0x%x", laddr,
+ MSI_INTEL_ADDR_BASE));
+ ntb->msix_data[i].nmd_ofs = laddr & ~MSI_INTEL_ADDR_BASE;
+
+ data = bus_read_4(msix->msix_table_res, offset +
+ PCI_MSIX_ENTRY_DATA);
+ ntb_printf(2, "local MSIX data(%u): 0x%x\n", i, data);
+
+ ntb->msix_data[i].nmd_data = data;
+ }
+}
+
static struct ntb_hw_info *
ntb_get_device_info(uint32_t device_id)
{
@@ -1202,9 +1417,12 @@ ntb_detect_xeon(struct ntb_softc *ntb)
if ((ppd & XEON_PPD_SPLIT_BAR) != 0)
ntb->features |= NTB_SPLIT_BAR;
- /* SB01BASE_LOCKUP errata is a superset of SDOORBELL errata */
+ /*
+ * SDOORBELL errata workaround gets in the way of SB01BASE_LOCKUP
+ * errata workaround; only do one at a time.
+ */
if (HAS_FEATURE(NTB_SB01BASE_LOCKUP))
- ntb->features |= NTB_SDOORBELL_LOCKUP;
+ ntb->features &= ~NTB_SDOORBELL_LOCKUP;
conn_type = ppd & XEON_PPD_CONN_TYPE;
switch (conn_type) {
@@ -1268,19 +1486,28 @@ ntb_xeon_init_dev(struct ntb_softc *ntb)
ntb->peer_reg = &xeon_b2b_reg;
ntb->xlat_reg = &xeon_sec_xlat;
- /*
- * There is a Xeon hardware errata related to writes to SDOORBELL or
- * B2BDOORBELL in conjunction with inbound access to NTB MMIO space,
- * which may hang the system. To workaround this, use a memory
- * window to access the interrupt and scratch pad registers on the
- * remote system.
- */
- if (HAS_FEATURE(NTB_SDOORBELL_LOCKUP)) {
+ if (HAS_FEATURE(NTB_SB01BASE_LOCKUP)) {
+ ntb->msix_mw_idx = (ntb->mw_count + g_ntb_msix_idx) %
+ ntb->mw_count;
+ ntb_printf(2, "Setting up MSIX mw idx %d means %u\n",
+ g_ntb_msix_idx, ntb->msix_mw_idx);
+ rc = ntb_mw_set_wc_internal(ntb, ntb->msix_mw_idx,
+ VM_MEMATTR_UNCACHEABLE);
+ KASSERT(rc == 0, ("shouldn't fail"));
+ } else if (HAS_FEATURE(NTB_SDOORBELL_LOCKUP)) {
+ /*
+ * There is a Xeon hardware errata related to writes to SDOORBELL or
+ * B2BDOORBELL in conjunction with inbound access to NTB MMIO space,
+ * which may hang the system. To workaround this, use a memory
+ * window to access the interrupt and scratch pad registers on the
+ * remote system.
+ */
ntb->b2b_mw_idx = (ntb->mw_count + g_ntb_mw_idx) %
ntb->mw_count;
ntb_printf(2, "Setting up b2b mw idx %d means %u\n",
g_ntb_mw_idx, ntb->b2b_mw_idx);
- rc = ntb_mw_set_wc_internal(ntb, ntb->b2b_mw_idx, VM_MEMATTR_UNCACHEABLE);
+ rc = ntb_mw_set_wc_internal(ntb, ntb->b2b_mw_idx,
+ VM_MEMATTR_UNCACHEABLE);
KASSERT(rc == 0, ("shouldn't fail"));
} else if (HAS_FEATURE(NTB_B2BDOORBELL_BIT14))
/*
@@ -1311,7 +1538,14 @@ ntb_xeon_init_dev(struct ntb_softc *ntb)
/*
* Mask all doorbell interrupts.
*/
- ntb_db_set_mask(ntb, ntb->db_valid_mask);
+ DB_MASK_LOCK(ntb);
+ ntb->db_mask = ntb->db_valid_mask;
+ db_iowrite(ntb, ntb->self_reg->db_mask, ntb->db_mask);
+ DB_MASK_UNLOCK(ntb);
+
+ rc = xeon_setup_msix_bar(ntb);
+ if (rc != 0)
+ return (rc);
rc = ntb_init_isr(ntb);
return (rc);
@@ -1414,6 +1648,15 @@ xeon_reset_sbar_size(struct ntb_softc *ntb, enum ntb_bar idx,
bar_sz--;
else
bar_sz = 0;
+ } else if (HAS_FEATURE(NTB_SB01BASE_LOCKUP) &&
+ ntb_mw_to_bar(ntb, ntb->msix_mw_idx) == idx) {
+ /* Restrict LAPIC BAR to 1MB */
+ pci_write_config(ntb->device, bar->psz_off, 20, 1);
+ pci_write_config(ntb->device, bar->ssz_off, 20, 1);
+ bar_sz = pci_read_config(ntb->device, bar->psz_off, 1);
+ bar_sz = pci_read_config(ntb->device, bar->ssz_off, 1);
+ (void)bar_sz;
+ return;
}
pci_write_config(ntb->device, bar->ssz_off, bar_sz, 1);
bar_sz = pci_read_config(ntb->device, bar->ssz_off, 1);
@@ -1424,28 +1667,37 @@ static void
xeon_set_sbar_base_and_limit(struct ntb_softc *ntb, uint64_t bar_addr,
enum ntb_bar idx, enum ntb_bar regbar)
{
- uint64_t reg_val;
+ uint64_t reg_val, lmt_addr;
uint32_t base_reg, lmt_reg;
bar_get_xlat_params(ntb, idx, &base_reg, NULL, &lmt_reg);
if (idx == regbar)
bar_addr += ntb->b2b_off;
+ lmt_addr = bar_addr;
+
+ if (HAS_FEATURE(NTB_SB01BASE_LOCKUP) &&
+ ntb_mw_to_bar(ntb, ntb->msix_mw_idx) == idx)
+ lmt_addr += ONE_MB;
+ /*
+ * Set limit registers first to avoid an errata where setting the base
+ * registers locks the limit registers.
+ */
if (!bar_is_64bit(ntb, idx)) {
- ntb_reg_write(4, base_reg, bar_addr);
- reg_val = ntb_reg_read(4, base_reg);
+ ntb_reg_write(4, lmt_reg, lmt_addr);
+ reg_val = ntb_reg_read(4, lmt_reg);
(void)reg_val;
- ntb_reg_write(4, lmt_reg, bar_addr);
- reg_val = ntb_reg_read(4, lmt_reg);
+ ntb_reg_write(4, base_reg, bar_addr);
+ reg_val = ntb_reg_read(4, base_reg);
(void)reg_val;
} else {
- ntb_reg_write(8, base_reg, bar_addr);
- reg_val = ntb_reg_read(8, base_reg);
+ ntb_reg_write(8, lmt_reg, lmt_addr);
+ reg_val = ntb_reg_read(8, lmt_reg);
(void)reg_val;
- ntb_reg_write(8, lmt_reg, bar_addr);
- reg_val = ntb_reg_read(8, lmt_reg);
+ ntb_reg_write(8, base_reg, bar_addr);
+ reg_val = ntb_reg_read(8, base_reg);
(void)reg_val;
}
}
@@ -1467,6 +1719,37 @@ xeon_set_pbar_xlat(struct ntb_softc *ntb, uint64_t base_addr, enum ntb_bar idx)
}
static int
+xeon_setup_msix_bar(struct ntb_softc *ntb)
+{
+ struct ntb_pci_bar_info *lapic_bar;
+ enum ntb_bar bar_num;
+ int rc;
+
+ if (!HAS_FEATURE(NTB_SB01BASE_LOCKUP))
+ return (0);
+
+ bar_num = ntb_mw_to_bar(ntb, ntb->msix_mw_idx);
+ lapic_bar = &ntb->bar_info[bar_num];
+
+ /* Restrict LAPIC BAR to 1MB */
+ if (lapic_bar->size > ONE_MB) {
+ rc = bus_adjust_resource(ntb->device, SYS_RES_MEMORY,
+ lapic_bar->pci_resource, lapic_bar->pbase,
+ lapic_bar->pbase + ONE_MB - 1);
+ if (rc == 0)
+ lapic_bar->size = ONE_MB;
+ else {
+ ntb_printf(0, "Failed to shrink LAPIC BAR resource to "
+ "1 MB: %d\n", rc);
+ /* Ignore error */
+ }
+ }
+
+ ntb->peer_lapic_bar = lapic_bar;
+ return (0);
+}
+
+static int
xeon_setup_b2b_mw(struct ntb_softc *ntb, const struct ntb_b2b_addr *addr,
const struct ntb_b2b_addr *peer_addr)
{
@@ -1544,6 +1827,43 @@ xeon_setup_b2b_mw(struct ntb_softc *ntb, const struct ntb_b2b_addr *addr,
ntb_reg_write(8, XEON_SBAR2XLAT_OFFSET, 0);
ntb_reg_write(8, XEON_SBAR4XLAT_OFFSET, 0);
+ if (HAS_FEATURE(NTB_SB01BASE_LOCKUP)) {
+ size_t size, xlatoffset;
+
+ switch (ntb_mw_to_bar(ntb, ntb->msix_mw_idx)) {
+ case NTB_B2B_BAR_1:
+ size = 8;
+ xlatoffset = XEON_SBAR2XLAT_OFFSET;
+ break;
+ case NTB_B2B_BAR_2:
+ xlatoffset = XEON_SBAR4XLAT_OFFSET;
+ if (HAS_FEATURE(NTB_SPLIT_BAR))
+ size = 4;
+ else
+ size = 8;
+ break;
+ case NTB_B2B_BAR_3:
+ xlatoffset = XEON_SBAR5XLAT_OFFSET;
+ size = 4;
+ break;
+ default:
+ KASSERT(false, ("Bogus msix mw idx: %u",
+ ntb->msix_mw_idx));
+ return (EINVAL);
+ }
+
+ /*
+ * We point the chosen MSIX MW BAR xlat to remote LAPIC for
+ * workaround
+ */
+ if (size == 4)
+ ntb_reg_write(4, xlatoffset, MSI_INTEL_ADDR_BASE);
+ else
+ ntb_reg_write(8, xlatoffset, MSI_INTEL_ADDR_BASE);
+ }
+ (void)ntb_reg_read(8, XEON_SBAR2XLAT_OFFSET);
+ (void)ntb_reg_read(8, XEON_SBAR4XLAT_OFFSET);
+
/* Zero outgoing translation limits (whole bar size windows) */
ntb_reg_write(8, XEON_PBAR2LMT_OFFSET, 0);
ntb_reg_write(8, XEON_PBAR4LMT_OFFSET, 0);
@@ -1581,14 +1901,21 @@ xeon_setup_b2b_mw(struct ntb_softc *ntb, const struct ntb_b2b_addr *addr,
}
static inline bool
+_xeon_link_is_up(struct ntb_softc *ntb)
+{
+
+ if (ntb->conn_type == NTB_CONN_TRANSPARENT)
+ return (true);
+ return ((ntb->lnk_sta & NTB_LINK_STATUS_ACTIVE) != 0);
+}
+
+static inline bool
link_is_up(struct ntb_softc *ntb)
{
- if (ntb->type == NTB_XEON) {
- if (ntb->conn_type == NTB_CONN_TRANSPARENT)
- return (true);
- return ((ntb->lnk_sta & NTB_LINK_STATUS_ACTIVE) != 0);
- }
+ if (ntb->type == NTB_XEON)
+ return (_xeon_link_is_up(ntb) && (ntb->peer_msix_good ||
+ !HAS_FEATURE(NTB_SB01BASE_LOCKUP)));
KASSERT(ntb->type == NTB_ATOM, ("ntb type"));
return ((ntb->ntb_ctl & ATOM_CNTL_LINK_DOWN) == 0);
@@ -1927,6 +2254,19 @@ ntb_poll_link(struct ntb_softc *ntb)
return (false);
ntb->lnk_sta = reg_val;
+
+ if (HAS_FEATURE(NTB_SB01BASE_LOCKUP)) {
+ if (_xeon_link_is_up(ntb)) {
+ if (!ntb->peer_msix_good) {
+ callout_reset(&ntb->peer_msix_work, 0,
+ ntb_exchange_msix, ntb);
+ return (false);
+ }
+ } else {
+ ntb->peer_msix_good = false;
+ ntb->peer_msix_done = false;
+ }
+ }
}
return (true);
}
@@ -2355,12 +2695,70 @@ static unsigned
ntb_user_mw_to_idx(struct ntb_softc *ntb, unsigned uidx)
{
- if (ntb->b2b_mw_idx != B2B_MW_DISABLED && ntb->b2b_off == 0 &&
- uidx >= ntb->b2b_mw_idx)
- return (uidx + 1);
+ if ((ntb->b2b_mw_idx != B2B_MW_DISABLED && ntb->b2b_off == 0 &&
+ uidx >= ntb->b2b_mw_idx) ||
+ (ntb->msix_mw_idx != B2B_MW_DISABLED && uidx >= ntb->msix_mw_idx))
+ uidx++;
+ if ((ntb->b2b_mw_idx != B2B_MW_DISABLED && ntb->b2b_off == 0 &&
+ uidx >= ntb->b2b_mw_idx) &&
+ (ntb->msix_mw_idx != B2B_MW_DISABLED && uidx >= ntb->msix_mw_idx))
+ uidx++;
return (uidx);
}
+static void
+ntb_exchange_msix(void *ctx)
+{
+ struct ntb_softc *ntb;
+ uint32_t val;
+ unsigned i;
+
+ ntb = ctx;
+
+ if (ntb->peer_msix_done)
+ goto msix_done;
+
+ for (i = 0; i < XEON_NONLINK_DB_MSIX_BITS; i++) {
+ ntb_peer_spad_write(ntb, NTB_MSIX_DATA0 + i,
+ ntb->msix_data[i].nmd_data);
+ ntb_peer_spad_write(ntb, NTB_MSIX_OFS0 + i,
+ ntb->msix_data[i].nmd_ofs);
+ }
+ ntb_peer_spad_write(ntb, NTB_MSIX_GUARD, NTB_MSIX_VER_GUARD);
+
+ ntb_spad_read(ntb, NTB_MSIX_GUARD, &val);
+ if (val != NTB_MSIX_VER_GUARD)
+ goto reschedule;
+
+ for (i = 0; i < XEON_NONLINK_DB_MSIX_BITS; i++) {
+ ntb_spad_read(ntb, NTB_MSIX_DATA0 + i, &val);
+ ntb->peer_msix_data[i].nmd_data = val;
+ ntb_spad_read(ntb, NTB_MSIX_OFS0 + i, &val);
+ ntb->peer_msix_data[i].nmd_ofs = val;
+ }
+
+ ntb->peer_msix_done = true;
+
+msix_done:
+ ntb_peer_spad_write(ntb, NTB_MSIX_DONE, NTB_MSIX_RECEIVED);
+ ntb_spad_read(ntb, NTB_MSIX_DONE, &val);
+ if (val != NTB_MSIX_RECEIVED)
+ goto reschedule;
+
+ ntb->peer_msix_good = true;
+
+ ntb_poll_link(ntb);
+ ntb_link_event(ntb);
+ return;
+
+reschedule:
+ ntb->lnk_sta = pci_read_config(ntb->device, ntb->reg->lnk_sta, 2);
+ if (_xeon_link_is_up(ntb))
+ callout_reset(&ntb->peer_msix_work, hz / 100, ntb_exchange_msix, ntb);
+ else
+ ntb_spad_clear(ntb);
+}
+
/*
* Public API to the rest of the OS
*/
@@ -2390,10 +2788,14 @@ ntb_get_max_spads(struct ntb_softc *ntb)
uint8_t
ntb_mw_count(struct ntb_softc *ntb)
{
+ uint8_t res;
+ res = ntb->mw_count;
if (ntb->b2b_mw_idx != B2B_MW_DISABLED && ntb->b2b_off == 0)
- return (ntb->mw_count - 1);
- return (ntb->mw_count);
+ res--;
+ if (ntb->msix_mw_idx != B2B_MW_DISABLED)
+ res--;
+ return (res);
}
/**
@@ -2419,6 +2821,18 @@ ntb_spad_write(struct ntb_softc *ntb, unsigned int idx, uint32_t val)
return (0);
}
+/*
+ * Zeros the local scratchpad.
+ */
+void
+ntb_spad_clear(struct ntb_softc *ntb)
+{
+ unsigned i;
+
+ for (i = 0; i < ntb->spad_count; i++)
+ ntb_spad_write(ntb, i, 0);
+}
+
/**
* ntb_spad_read() - read from the primary scratchpad register
* @ntb: pointer to ntb_softc instance
@@ -2728,10 +3142,6 @@ ntb_mw_set_wc_internal(struct ntb_softc *ntb, unsigned idx, vm_memattr_t mode)
if (bar->map_mode == mode)
return (0);
- if (mode != VM_MEMATTR_UNCACHEABLE && mode != VM_MEMATTR_DEFAULT &&
- mode != VM_MEMATTR_WRITE_COMBINING)
- return (EINVAL);
-
rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size, mode);
if (rc == 0)
bar->map_mode = mode;
@@ -2751,6 +3161,22 @@ void
ntb_peer_db_set(struct ntb_softc *ntb, uint64_t bit)
{
+ if (HAS_FEATURE(NTB_SB01BASE_LOCKUP)) {
+ struct ntb_pci_bar_info *lapic;
+ unsigned i;
+
+ lapic = ntb->peer_lapic_bar;
+
+ for (i = 0; i < XEON_NONLINK_DB_MSIX_BITS; i++) {
+ if ((bit & ntb_db_vector_mask(ntb, i)) != 0)
+ bus_space_write_4(lapic->pci_bus_tag,
+ lapic->pci_bus_handle,
+ ntb->peer_msix_data[i].nmd_ofs,
+ ntb->peer_msix_data[i].nmd_data);
+ }
+ return;
+ }
+
if (HAS_FEATURE(NTB_SDOORBELL_LOCKUP)) {
ntb_mw_write(2, XEON_PDOORBELL_OFFSET, bit);
return;
diff --git a/sys/dev/ntb/ntb_hw/ntb_hw.h b/sys/dev/ntb/ntb_hw/ntb_hw.h
index c35166c..e2f45b2 100644
--- a/sys/dev/ntb/ntb_hw/ntb_hw.h
+++ b/sys/dev/ntb/ntb_hw/ntb_hw.h
@@ -86,6 +86,7 @@ int ntb_mw_get_wc(struct ntb_softc *, unsigned mw_idx, vm_memattr_t *mode);
int ntb_mw_set_wc(struct ntb_softc *, unsigned mw_idx, vm_memattr_t mode);
uint8_t ntb_get_max_spads(struct ntb_softc *ntb);
+void ntb_spad_clear(struct ntb_softc *ntb);
int ntb_spad_write(struct ntb_softc *ntb, unsigned int idx, uint32_t val);
int ntb_spad_read(struct ntb_softc *ntb, unsigned int idx, uint32_t *val);
int ntb_peer_spad_write(struct ntb_softc *ntb, unsigned int idx,
diff --git a/sys/dev/ntb/ntb_hw/ntb_regs.h b/sys/dev/ntb/ntb_hw/ntb_regs.h
index f50fd93..fb445d7 100644
--- a/sys/dev/ntb/ntb_hw/ntb_regs.h
+++ b/sys/dev/ntb/ntb_hw/ntb_regs.h
@@ -44,6 +44,7 @@
#define XEON_DB_MSIX_VECTOR_COUNT 4
#define XEON_DB_MSIX_VECTOR_SHIFT 5
#define XEON_DB_LINK_BIT (1 << XEON_DB_LINK)
+#define XEON_NONLINK_DB_MSIX_BITS 3
#define XEON_SPCICMD_OFFSET 0x0504
#define XEON_DEVCTRL_OFFSET 0x0598
diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
index e400f52..4c8adc0 100644
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -725,15 +725,17 @@ nvme_ctrlr_start(void *ctrlr_arg)
* explicit specify how many queues it will use. This value should
* never change between resets, so panic if somehow that does happen.
*/
- old_num_io_queues = ctrlr->num_io_queues;
- if (nvme_ctrlr_set_num_qpairs(ctrlr) != 0) {
- nvme_ctrlr_fail(ctrlr);
- return;
- }
+ if (ctrlr->is_resetting) {
+ old_num_io_queues = ctrlr->num_io_queues;
+ if (nvme_ctrlr_set_num_qpairs(ctrlr) != 0) {
+ nvme_ctrlr_fail(ctrlr);
+ return;
+ }
- if (old_num_io_queues != ctrlr->num_io_queues) {
- panic("num_io_queues changed from %u to %u", old_num_io_queues,
- ctrlr->num_io_queues);
+ if (old_num_io_queues != ctrlr->num_io_queues) {
+ panic("num_io_queues changed from %u to %u",
+ old_num_io_queues, ctrlr->num_io_queues);
+ }
}
if (nvme_ctrlr_create_qpairs(ctrlr) != 0) {
diff --git a/sys/dev/sfxge/common/efx.h b/sys/dev/sfxge/common/efx.h
index ce70546..14374cf 100644
--- a/sys/dev/sfxge/common/efx.h
+++ b/sys/dev/sfxge/common/efx.h
@@ -879,6 +879,14 @@ efx_phy_media_type_get(
__in efx_nic_t *enp,
__out efx_phy_media_type_t *typep);
+extern efx_rc_t
+efx_phy_module_get_info(
+ __in efx_nic_t *enp,
+ __in uint8_t dev_addr,
+ __in uint8_t offset,
+ __in uint8_t len,
+ __out_bcount(len) uint8_t *data);
+
#if EFSYS_OPT_PHY_STATS
/* START MKCONFIG GENERATED PhyHeaderStatsBlock 30ed56ad501f8e36 */
diff --git a/sys/dev/sfxge/common/efx_mcdi.c b/sys/dev/sfxge/common/efx_mcdi.c
index 9f7a9ff..bb9d9cf 100644
--- a/sys/dev/sfxge/common/efx_mcdi.c
+++ b/sys/dev/sfxge/common/efx_mcdi.c
@@ -2078,5 +2078,217 @@ fail1:
return (rc);
}
+/*
+ * Size of media information page in accordance with SFF-8472 and SFF-8436.
+ * It is used in MCDI interface as well.
+ */
+#define EFX_PHY_MEDIA_INFO_PAGE_SIZE 0x80
+
+static __checkReturn efx_rc_t
+efx_mcdi_get_phy_media_info(
+ __in efx_nic_t *enp,
+ __in uint32_t mcdi_page,
+ __in uint8_t offset,
+ __in uint8_t len,
+ __out_bcount(len) uint8_t *data)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MAX(MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN,
+ MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(
+ EFX_PHY_MEDIA_INFO_PAGE_SIZE))];
+ efx_rc_t rc;
+
+ EFSYS_ASSERT((uint32_t)offset + len <= EFX_PHY_MEDIA_INFO_PAGE_SIZE);
+
+ (void) memset(payload, 0, sizeof (payload));
+ req.emr_cmd = MC_CMD_GET_PHY_MEDIA_INFO;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length =
+ MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(EFX_PHY_MEDIA_INFO_PAGE_SIZE);
+
+ MCDI_IN_SET_DWORD(req, GET_PHY_MEDIA_INFO_IN_PAGE, mcdi_page);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ if (req.emr_out_length_used !=
+ MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(EFX_PHY_MEDIA_INFO_PAGE_SIZE)) {
+ rc = EMSGSIZE;
+ goto fail2;
+ }
+
+ if (MCDI_OUT_DWORD(req, GET_PHY_MEDIA_INFO_OUT_DATALEN) !=
+ EFX_PHY_MEDIA_INFO_PAGE_SIZE) {
+ rc = EIO;
+ goto fail3;
+ }
+
+ memcpy(data,
+ MCDI_OUT2(req, uint8_t, GET_PHY_MEDIA_INFO_OUT_DATA) + offset,
+ len);
+
+ return (0);
+
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+/*
+ * 2-wire device address of the base information in accordance with SFF-8472
+ * Diagnostic Monitoring Interface for Optical Transceivers section
+ * 4 Memory Organization.
+ */
+#define EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_BASE 0xA0
+
+/*
+ * 2-wire device address of the digital diagnostics monitoring interface
+ * in accordance with SFF-8472 Diagnostic Monitoring Interface for Optical
+ * Transceivers section 4 Memory Organization.
+ */
+#define EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_DDM 0xA2
+
+/*
+ * Hard wired 2-wire device address for QSFP+ in accordance with SFF-8436
+ * QSFP+ 10 Gbs 4X PLUGGABLE TRANSCEIVER section 7.4 Device Addressing and
+ * Operation.
+ */
+#define EFX_PHY_MEDIA_INFO_DEV_ADDR_QSFP 0xA0
+
+ __checkReturn efx_rc_t
+efx_mcdi_phy_module_get_info(
+ __in efx_nic_t *enp,
+ __in uint8_t dev_addr,
+ __in uint8_t offset,
+ __in uint8_t len,
+ __out_bcount(len) uint8_t *data)
+{
+ efx_port_t *epp = &(enp->en_port);
+ efx_rc_t rc;
+ uint32_t mcdi_lower_page;
+ uint32_t mcdi_upper_page;
+
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+
+ /*
+ * Map device address to MC_CMD_GET_PHY_MEDIA_INFO pages.
+ * Offset plus length interface allows to access page 0 only.
+ * I.e. non-zero upper pages are not accessible.
+ * See SFF-8472 section 4 Memory Organization and SFF-8436 section 7.6
+ * QSFP+ Memory Map for details on how information is structured
+ * and accessible.
+ */
+ switch (epp->ep_fixed_port_type) {
+ case EFX_PHY_MEDIA_SFP_PLUS:
+ /*
+ * In accordance with SFF-8472 Diagnostic Monitoring
+ * Interface for Optical Transceivers section 4 Memory
+ * Organization two 2-wire addresses are defined.
+ */
+ switch (dev_addr) {
+ /* Base information */
+ case EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_BASE:
+ /*
+ * MCDI page 0 should be used to access lower
+ * page 0 (0x00 - 0x7f) at the device address 0xA0.
+ */
+ mcdi_lower_page = 0;
+ /*
+ * MCDI page 1 should be used to access upper
+ * page 0 (0x80 - 0xff) at the device address 0xA0.
+ */
+ mcdi_upper_page = 1;
+ break;
+ /* Diagnostics */
+ case EFX_PHY_MEDIA_INFO_DEV_ADDR_SFP_DDM:
+ /*
+ * MCDI page 2 should be used to access lower
+ * page 0 (0x00 - 0x7f) at the device address 0xA2.
+ */
+ mcdi_lower_page = 2;
+ /*
+ * MCDI page 3 should be used to access upper
+ * page 0 (0x80 - 0xff) at the device address 0xA2.
+ */
+ mcdi_upper_page = 3;
+ break;
+ default:
+ rc = ENOTSUP;
+ goto fail1;
+ }
+ break;
+ case EFX_PHY_MEDIA_QSFP_PLUS:
+ switch (dev_addr) {
+ case EFX_PHY_MEDIA_INFO_DEV_ADDR_QSFP:
+ /*
+ * MCDI page -1 should be used to access lower page 0
+ * (0x00 - 0x7f).
+ */
+ mcdi_lower_page = (uint32_t)-1;
+ /*
+ * MCDI page 0 should be used to access upper page 0
+ * (0x80h - 0xff).
+ */
+ mcdi_upper_page = 0;
+ break;
+ default:
+ rc = ENOTSUP;
+ goto fail1;
+ }
+ break;
+ default:
+ rc = ENOTSUP;
+ goto fail1;
+ }
+
+ if (offset < EFX_PHY_MEDIA_INFO_PAGE_SIZE) {
+ uint8_t read_len =
+ MIN(len, EFX_PHY_MEDIA_INFO_PAGE_SIZE - offset);
+
+ rc = efx_mcdi_get_phy_media_info(enp,
+ mcdi_lower_page, offset, read_len, data);
+ if (rc != 0)
+ goto fail2;
+
+ data += read_len;
+ len -= read_len;
+
+ offset = 0;
+ } else {
+ offset -= EFX_PHY_MEDIA_INFO_PAGE_SIZE;
+ }
+
+ if (len > 0) {
+ EFSYS_ASSERT3U(len, <=, EFX_PHY_MEDIA_INFO_PAGE_SIZE);
+ EFSYS_ASSERT3U(offset, <, EFX_PHY_MEDIA_INFO_PAGE_SIZE);
+
+ rc = efx_mcdi_get_phy_media_info(enp,
+ mcdi_upper_page, offset, len, data);
+ if (rc != 0)
+ goto fail3;
+ }
+
+ return (0);
+
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
#endif /* EFSYS_OPT_MCDI */
diff --git a/sys/dev/sfxge/common/efx_mcdi.h b/sys/dev/sfxge/common/efx_mcdi.h
index dd1d76e..a96bd77 100644
--- a/sys/dev/sfxge/common/efx_mcdi.h
+++ b/sys/dev/sfxge/common/efx_mcdi.h
@@ -228,6 +228,14 @@ efx_mcdi_get_loopback_modes(
__in efx_nic_t *enp);
#endif /* EFSYS_OPT_LOOPBACK */
+extern __checkReturn efx_rc_t
+efx_mcdi_phy_module_get_info(
+ __in efx_nic_t *enp,
+ __in uint8_t dev_addr,
+ __in uint8_t offset,
+ __in uint8_t len,
+ __out_bcount(len) uint8_t *data);
+
#define MCDI_IN(_emr, _type, _ofst) \
((_type *)((_emr).emr_in_buf + (_ofst)))
diff --git a/sys/dev/sfxge/common/efx_phy.c b/sys/dev/sfxge/common/efx_phy.c
index 51e1ccb..3fd4e08 100644
--- a/sys/dev/sfxge/common/efx_phy.c
+++ b/sys/dev/sfxge/common/efx_phy.c
@@ -560,6 +560,38 @@ efx_phy_media_type_get(
*typep = epp->ep_fixed_port_type;
}
+ __checkReturn efx_rc_t
+efx_phy_module_get_info(
+ __in efx_nic_t *enp,
+ __in uint8_t dev_addr,
+ __in uint8_t offset,
+ __in uint8_t len,
+ __out_bcount(len) uint8_t *data)
+{
+ efx_rc_t rc;
+
+ EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+ EFSYS_ASSERT(data != NULL);
+
+ if ((uint32_t)offset + len > 0xff) {
+ rc = EINVAL;
+ goto fail1;
+ }
+
+ if ((rc = efx_mcdi_phy_module_get_info(enp, dev_addr,
+ offset, len, data)) != 0)
+ goto fail2;
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
#if EFSYS_OPT_PHY_STATS
#if EFSYS_OPT_NAMES
diff --git a/sys/dev/sfxge/sfxge.c b/sys/dev/sfxge/sfxge.c
index db6225d..88e56bc 100644
--- a/sys/dev/sfxge/sfxge.c
+++ b/sys/dev/sfxge/sfxge.c
@@ -500,6 +500,30 @@ sfxge_if_ioctl(struct ifnet *ifp, unsigned long command, caddr_t data)
case SIOCGIFMEDIA:
error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
break;
+#ifdef SIOCGI2C
+ case SIOCGI2C:
+ {
+ struct ifi2creq i2c;
+
+ error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
+ if (error != 0)
+ break;
+
+ if (i2c.len > sizeof(i2c.data)) {
+ error = EINVAL;
+ break;
+ }
+
+ SFXGE_ADAPTER_LOCK(sc);
+ error = efx_phy_module_get_info(sc->enp, i2c.dev_addr,
+ i2c.offset, i2c.len,
+ &i2c.data[0]);
+ SFXGE_ADAPTER_UNLOCK(sc);
+ if (error == 0)
+ error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
+ break;
+ }
+#endif
case SIOCGPRIVATE_0:
error = priv_check(curthread, PRIV_DRIVER);
if (error != 0)
diff --git a/sys/dev/uart/uart_bus_fdt.c b/sys/dev/uart/uart_bus_fdt.c
index 1498eb8..5308a2e 100644
--- a/sys/dev/uart/uart_bus_fdt.c
+++ b/sys/dev/uart/uart_bus_fdt.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include "opt_platform.h"
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
diff --git a/sys/dev/uart/uart_dev_lpc.c b/sys/dev/uart/uart_dev_lpc.c
index 6cd10f1..9a3e12b 100644
--- a/sys/dev/uart/uart_dev_lpc.c
+++ b/sys/dev/uart/uart_dev_lpc.c
@@ -659,6 +659,7 @@ lpc_ns8250_bus_ipend(struct uart_softc *sc)
if (iir & IIR_TXRDY) {
ipend |= SER_INT_TXIDLE;
uart_setreg(bas, REG_IER, lpc_ns8250->ier);
+ uart_barrier(bas);
} else
ipend |= SER_INT_SIGCHG;
}
@@ -892,12 +893,12 @@ lpc_ns8250_bus_transmit(struct uart_softc *sc)
uart_lock(sc->sc_hwmtx);
while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0)
;
- uart_setreg(bas, REG_IER, lpc_ns8250->ier | IER_ETXRDY);
- uart_barrier(bas);
for (i = 0; i < sc->sc_txdatasz; i++) {
uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
uart_barrier(bas);
}
+ uart_setreg(bas, REG_IER, lpc_ns8250->ier | IER_ETXRDY);
+ uart_barrier(bas);
sc->sc_txbusy = 1;
uart_unlock(sc->sc_hwmtx);
return (0);
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 3bba676..9802294 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -708,6 +708,7 @@ ns8250_bus_ipend(struct uart_softc *sc)
if (iir & IIR_TXRDY) {
ipend |= SER_INT_TXIDLE;
uart_setreg(bas, REG_IER, ns8250->ier);
+ uart_barrier(bas);
} else
ipend |= SER_INT_SIGCHG;
}
@@ -979,12 +980,12 @@ ns8250_bus_transmit(struct uart_softc *sc)
uart_lock(sc->sc_hwmtx);
while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0)
;
- uart_setreg(bas, REG_IER, ns8250->ier | IER_ETXRDY);
- uart_barrier(bas);
for (i = 0; i < sc->sc_txdatasz; i++) {
uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
uart_barrier(bas);
}
+ uart_setreg(bas, REG_IER, ns8250->ier | IER_ETXRDY);
+ uart_barrier(bas);
if (broken_txfifo)
ns8250_drain(bas, UART_DRAIN_TRANSMITTER);
else
diff --git a/sys/dev/usb/controller/ehci_pci.c b/sys/dev/usb/controller/ehci_pci.c
index 9b862a5..3a6f725 100644
--- a/sys/dev/usb/controller/ehci_pci.c
+++ b/sys/dev/usb/controller/ehci_pci.c
@@ -172,7 +172,7 @@ ehci_pci_match(device_t self)
return ("Intel Lynx Point LP USB 2.0 controller USB");
case 0x00e01033:
- return ("NEC uPD 720100 USB 2.0 controller");
+ return ("NEC uPD 72010x USB 2.0 controller");
case 0x006810de:
return "NVIDIA nForce2 USB 2.0 controller";
diff --git a/sys/dev/usb/net/if_smsc.c b/sys/dev/usb/net/if_smsc.c
index 19c4615..e90e753 100644
--- a/sys/dev/usb/net/if_smsc.c
+++ b/sys/dev/usb/net/if_smsc.c
@@ -1362,7 +1362,7 @@ smsc_chip_init(struct smsc_softc *sc)
/* Reset the PHY */
smsc_write_reg(sc, SMSC_PM_CTRL, SMSC_PM_CTRL_PHY_RST);
- if ((err = smsc_wait_for_bits(sc, SMSC_PM_CTRL, SMSC_PM_CTRL_PHY_RST) != 0)) {
+ if ((err = smsc_wait_for_bits(sc, SMSC_PM_CTRL, SMSC_PM_CTRL_PHY_RST)) != 0) {
smsc_warn_printf(sc, "timed-out waiting for phy reset to complete\n");
goto init_failed;
}
diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c
index 3fada69..e428a8f 100644
--- a/sys/dev/usb/wlan/if_rum.c
+++ b/sys/dev/usb/wlan/if_rum.c
@@ -2732,7 +2732,7 @@ rum_pair_key_del_cb(struct rum_softc *sc, union sec_param *data,
DPRINTF("%s: removing key %d\n", __func__, k->wk_keyix);
rum_clrbits(sc, (k->wk_keyix < 32) ? RT2573_SEC_CSR2 : RT2573_SEC_CSR3,
1 << (k->wk_keyix % 32));
- sc->keys_bmap &= ~(1 << k->wk_keyix);
+ sc->keys_bmap &= ~(1ULL << k->wk_keyix);
if (--sc->vap_key_count[rvp_id] == 0)
rum_clrbits(sc, RT2573_SEC_CSR4, 1 << rvp_id);
}
@@ -2749,8 +2749,8 @@ rum_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) {
RUM_LOCK(sc);
for (i = 0; i < RT2573_ADDR_MAX; i++) {
- if ((sc->keys_bmap & (1 << i)) == 0) {
- sc->keys_bmap |= 1 << i;
+ if ((sc->keys_bmap & (1ULL << i)) == 0) {
+ sc->keys_bmap |= (1ULL << i);
*keyix = i;
break;
}
diff --git a/sys/dev/usb/wlan/if_rumreg.h b/sys/dev/usb/wlan/if_rumreg.h
index c673fd7..06c0a81 100644
--- a/sys/dev/usb/wlan/if_rumreg.h
+++ b/sys/dev/usb/wlan/if_rumreg.h
@@ -47,7 +47,7 @@
* H/w encryption/decryption support
*/
#define KEY_SIZE (IEEE80211_KEYBUF_SIZE + IEEE80211_MICBUF_SIZE)
-#define RT2573_ADDR_MAX 64
+#define RT2573_ADDR_MAX 64
#define RT2573_SKEY_MAX 4
#define RT2573_SKEY(vap, kidx) (0x1000 + ((vap) * RT2573_SKEY_MAX + \
diff --git a/sys/dev/xen/blkfront/blkfront.c b/sys/dev/xen/blkfront/blkfront.c
index c193d84..d35e04a 100644
--- a/sys/dev/xen/blkfront/blkfront.c
+++ b/sys/dev/xen/blkfront/blkfront.c
@@ -674,7 +674,7 @@ xbd_open(struct disk *dp)
struct xbd_softc *sc = dp->d_drv1;
if (sc == NULL) {
- printf("xb%d: not found", sc->xbd_unit);
+ printf("xbd%d: not found", dp->d_unit);
return (ENXIO);
}
diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c
index e940d93..41c70f1 100644
--- a/sys/dev/xen/netfront/netfront.c
+++ b/sys/dev/xen/netfront/netfront.c
@@ -906,11 +906,9 @@ setup_txqs(device_t dev, struct netfront_info *info,
fail_bind_port:
taskqueue_drain_all(txq->tq);
fail_start_thread:
- gnttab_free_grant_references(txq->gref_head);
- free(txq->ring.sring, M_DEVBUF);
- gnttab_end_foreign_access_ref(txq->ring_ref);
buf_ring_free(txq->br, M_DEVBUF);
taskqueue_free(txq->tq);
+ gnttab_end_foreign_access_ref(txq->ring_ref);
fail_grant_ring:
gnttab_free_grant_references(txq->gref_head);
free(txq->ring.sring, M_DEVBUF);
@@ -1863,7 +1861,6 @@ xn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
sc->xn_if_flags = ifp->if_flags;
XN_UNLOCK(sc);
- error = 0;
break;
case SIOCSIFCAP:
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
@@ -1898,7 +1895,6 @@ xn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
ifp->if_capenable ^= IFCAP_LRO;
}
- error = 0;
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
@@ -2284,11 +2280,9 @@ netif_free(struct netfront_info *np)
netif_disconnect_backend(np);
free(np->rxq, M_DEVBUF);
free(np->txq, M_DEVBUF);
- if (np->xn_ifp != NULL) {
- ether_ifdetach(np->xn_ifp);
- if_free(np->xn_ifp);
- np->xn_ifp = NULL;
- }
+ ether_ifdetach(np->xn_ifp);
+ if_free(np->xn_ifp);
+ np->xn_ifp = NULL;
ifmedia_removeall(&np->sc_media);
}
diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c
index 983b869..bf18094 100644
--- a/sys/fs/cd9660/cd9660_vfsops.c
+++ b/sys/fs/cd9660/cd9660_vfsops.c
@@ -309,13 +309,13 @@ iso_mountfs(devvp, mp)
default:
break;
}
- if (bp) {
+ if (bp != NULL) {
brelse(bp);
bp = NULL;
}
}
vd_end:
- if (bp) {
+ if (bp != NULL) {
brelse(bp);
bp = NULL;
}
@@ -474,11 +474,11 @@ iso_mountfs(devvp, mp)
return 0;
out:
- if (bp)
+ if (bp != NULL)
brelse(bp);
- if (pribp)
+ if (pribp != NULL)
brelse(pribp);
- if (supbp)
+ if (supbp != NULL)
brelse(supbp);
if (cp != NULL) {
DROP_GIANT();
@@ -751,8 +751,7 @@ cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir)
#if 0
if (isonum_733(isodir->extent) +
isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
- if (bp != 0)
- brelse(bp);
+ brelse(bp);
printf("fhtovp: file start miss %d vs %d\n",
isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length),
ifhp->ifid_start);
@@ -770,7 +769,7 @@ cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir)
* read the `.' entry out of a dir.
*/
ip->iso_start = ino >> imp->im_bshift;
- if (bp != 0)
+ if (bp != NULL)
brelse(bp);
if ((error = cd9660_blkatoff(vp, (off_t)0, NULL, &bp)) != 0) {
vput(vp);
@@ -809,8 +808,7 @@ cd9660_vget_internal(mp, ino, flags, vpp, relocated, isodir)
break;
}
- if (bp != 0)
- brelse(bp);
+ brelse(bp);
/*
* Initialize the associated vnode
diff --git a/sys/fs/ext2fs/ext2_bmap.c b/sys/fs/ext2fs/ext2_bmap.c
index 8656e59..8e5e986 100644
--- a/sys/fs/ext2fs/ext2_bmap.c
+++ b/sys/fs/ext2fs/ext2_bmap.c
@@ -114,6 +114,8 @@ ext4_bmapext(struct vnode *vp, int32_t bn, int64_t *bnp, int *runp, int *runb)
if (runp != NULL)
*runp = path.ep_sparse_ext.e_len -
(lbn - path.ep_sparse_ext.e_blk) - 1;
+ if (runb != NULL)
+ *runb = lbn - path.ep_sparse_ext.e_blk;
} else {
ep = path.ep_ext;
if (ep == NULL)
@@ -127,6 +129,8 @@ ext4_bmapext(struct vnode *vp, int32_t bn, int64_t *bnp, int *runp, int *runb)
if (runp != NULL)
*runp = ep->e_len - (lbn - ep->e_blk) - 1;
+ if (runb != NULL)
+ *runb = lbn - ep->e_blk;
}
}
diff --git a/sys/fs/ext2fs/ext2_extents.c b/sys/fs/ext2fs/ext2_extents.c
index 1317fdc..a66f682 100644
--- a/sys/fs/ext2fs/ext2_extents.c
+++ b/sys/fs/ext2fs/ext2_extents.c
@@ -43,14 +43,17 @@
#include <fs/ext2fs/ext2_extents.h>
#include <fs/ext2fs/ext2_extern.h>
-static void ext4_ext_binsearch_index(struct inode *ip, struct ext4_extent_path
- *path, daddr_t lbn)
+static bool
+ext4_ext_binsearch_index(struct inode *ip, struct ext4_extent_path *path,
+ daddr_t lbn, daddr_t *first_lbn, daddr_t *last_lbn)
{
struct ext4_extent_header *ehp = path->ep_header;
- struct ext4_extent_index *l, *r, *m;
+ struct ext4_extent_index *first, *last, *l, *r, *m;
- l = (struct ext4_extent_index *)(char *)(ehp + 1);
- r = (struct ext4_extent_index *)(char *)(ehp + 1) + ehp->eh_ecount - 1;
+ first = (struct ext4_extent_index *)(char *)(ehp + 1);
+ last = first + ehp->eh_ecount - 1;
+ l = first;
+ r = last;
while (l <= r) {
m = l + (r - l) / 2;
if (lbn < m->ei_blk)
@@ -59,11 +62,24 @@ static void ext4_ext_binsearch_index(struct inode *ip, struct ext4_extent_path
l = m + 1;
}
+ if (l == first) {
+ path->ep_sparse_ext.e_blk = *first_lbn;
+ path->ep_sparse_ext.e_len = first->ei_blk - *first_lbn;
+ path->ep_sparse_ext.e_start_hi = 0;
+ path->ep_sparse_ext.e_start_lo = 0;
+ path->ep_is_sparse = true;
+ return (true);
+ }
path->ep_index = l - 1;
+ *first_lbn = path->ep_index->ei_blk;
+ if (path->ep_index < last)
+ *last_lbn = l->ei_blk - 1;
+ return (false);
}
static void
-ext4_ext_binsearch(struct inode *ip, struct ext4_extent_path *path, daddr_t lbn)
+ext4_ext_binsearch(struct inode *ip, struct ext4_extent_path *path, daddr_t lbn,
+ daddr_t first_lbn, daddr_t last_lbn)
{
struct ext4_extent_header *ehp = path->ep_header;
struct ext4_extent *first, *l, *r, *m;
@@ -83,23 +99,26 @@ ext4_ext_binsearch(struct inode *ip, struct ext4_extent_path *path, daddr_t lbn)
}
if (l == first) {
- path->ep_sparse_ext.e_blk = lbn;
- path->ep_sparse_ext.e_len = first->e_blk - lbn;
+ path->ep_sparse_ext.e_blk = first_lbn;
+ path->ep_sparse_ext.e_len = first->e_blk - first_lbn;
path->ep_sparse_ext.e_start_hi = 0;
path->ep_sparse_ext.e_start_lo = 0;
- path->ep_is_sparse = 1;
+ path->ep_is_sparse = true;
return;
}
path->ep_ext = l - 1;
if (path->ep_ext->e_blk + path->ep_ext->e_len <= lbn) {
- path->ep_sparse_ext.e_blk = lbn;
+ path->ep_sparse_ext.e_blk = path->ep_ext->e_blk +
+ path->ep_ext->e_len;
if (l <= (first + ehp->eh_ecount - 1))
- path->ep_sparse_ext.e_len = l->e_blk - lbn;
- else // XXX: where does it end?
- path->ep_sparse_ext.e_len = 1;
+ path->ep_sparse_ext.e_len = l->e_blk -
+ path->ep_sparse_ext.e_blk;
+ else
+ path->ep_sparse_ext.e_len = last_lbn -
+ path->ep_sparse_ext.e_blk + 1;
path->ep_sparse_ext.e_start_hi = 0;
path->ep_sparse_ext.e_start_lo = 0;
- path->ep_is_sparse = 1;
+ path->ep_is_sparse = true;
}
}
@@ -162,10 +181,16 @@ ext4_ext_find_extent(struct m_ext2fs *fs, struct inode *ip,
path->ep_header = ehp;
+ daddr_t first_lbn = 0;
+ daddr_t last_lbn = lblkno(ip->i_e2fs, ip->i_size);
+
for (i = ehp->eh_depth; i != 0; --i) {
- ext4_ext_binsearch_index(ip, path, lbn);
- path->ep_depth = 0;
+ path->ep_depth = i;
path->ep_ext = NULL;
+ if (ext4_ext_binsearch_index(ip, path, lbn, &first_lbn,
+ &last_lbn)) {
+ return (path);
+ }
nblk = (daddr_t)path->ep_index->ei_leaf_hi << 32 |
path->ep_index->ei_leaf_lo;
@@ -188,8 +213,8 @@ ext4_ext_find_extent(struct m_ext2fs *fs, struct inode *ip,
path->ep_depth = i;
path->ep_ext = NULL;
path->ep_index = NULL;
- path->ep_is_sparse = 0;
+ path->ep_is_sparse = false;
- ext4_ext_binsearch(ip, path, lbn);
+ ext4_ext_binsearch(ip, path, lbn, first_lbn, last_lbn);
return (path);
}
diff --git a/sys/fs/ext2fs/ext2_extents.h b/sys/fs/ext2fs/ext2_extents.h
index 4ce16f3..70eb685 100644
--- a/sys/fs/ext2fs/ext2_extents.h
+++ b/sys/fs/ext2fs/ext2_extents.h
@@ -84,7 +84,7 @@ struct ext4_extent_cache {
struct ext4_extent_path {
uint16_t ep_depth;
struct buf *ep_bp;
- int ep_is_sparse;
+ bool ep_is_sparse;
union {
struct ext4_extent ep_sparse_ext;
struct ext4_extent *ep_ext;
diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c
index bc239b8..42e11c7 100644
--- a/sys/fs/ext2fs/ext2_vnops.c
+++ b/sys/fs/ext2fs/ext2_vnops.c
@@ -985,10 +985,10 @@ abortit:
dp = VTOI(fdvp);
} else {
/*
- * From name has disappeared.
+ * From name has disappeared. IN_RENAME is not sufficient
+ * to protect against directory races due to timing windows,
+ * so we can't panic here.
*/
- if (doingdirectory)
- panic("ext2_rename: lost dir entry");
vrele(ap->a_fvp);
return (0);
}
@@ -1003,8 +1003,11 @@ abortit:
* rename.
*/
if (xp != ip) {
- if (doingdirectory)
- panic("ext2_rename: lost dir entry");
+ /*
+ * From name resolves to a different inode. IN_RENAME is
+ * not sufficient protection against timing window races
+ * so we can't panic here.
+ */
} else {
/*
* If the source is a directory with a
diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
index 9bdb1e9..bf42ffe 100644
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -1191,8 +1191,11 @@ tmpfs_readdir(struct vop_readdir_args *v)
if (error == EJUSTRETURN)
error = (uio->uio_resid != startresid) ? 0 : EINVAL;
- if (error != 0 && cookies != NULL)
+ if (error != 0 && cookies != NULL && ncookies != NULL) {
free(*cookies, M_TEMP);
+ *cookies = NULL;
+ *ncookies = 0;
+ }
if (eofflag != NULL)
*eofflag =
diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c
index 5596439..1586c16 100644
--- a/sys/kern/kern_mbuf.c
+++ b/sys/kern/kern_mbuf.c
@@ -44,8 +44,6 @@ __FBSDID("$FreeBSD$");
#include <sys/smp.h>
#include <sys/sysctl.h>
-#include <security/mac/mac_framework.h>
-
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/vm_kern.h>
@@ -284,7 +282,6 @@ static void mb_dtor_clust(void *, int, void *);
static void mb_dtor_pack(void *, int, void *);
static int mb_zinit_pack(void *, int, int);
static void mb_zfini_pack(void *, int);
-
static void mb_reclaim(uma_zone_t, int);
static void *mbuf_jumbo_alloc(uma_zone_t, vm_size_t, uint8_t *, int);
@@ -435,7 +432,7 @@ mb_ctor_mbuf(void *mem, int size, void *arg, int how)
m = (struct mbuf *)mem;
flags = args->flags;
- error = m_init(m, NULL, size, how, type, flags);
+ error = m_init(m, how, type, flags);
return (error);
}
@@ -635,7 +632,7 @@ mb_ctor_pack(void *mem, int size, void *arg, int how)
trash_ctor(m->m_ext.ext_buf, MCLBYTES, arg, how);
#endif
- error = m_init(m, NULL, size, how, type, flags);
+ error = m_init(m, how, type, flags);
/* m_ext is already initialized. */
m->m_data = m->m_ext.ext_buf;
@@ -644,24 +641,6 @@ mb_ctor_pack(void *mem, int size, void *arg, int how)
return (error);
}
-int
-m_pkthdr_init(struct mbuf *m, int how)
-{
-#ifdef MAC
- int error;
-#endif
- m->m_data = m->m_pktdat;
- bzero(&m->m_pkthdr, sizeof(m->m_pkthdr));
-#ifdef MAC
- /* If the label init fails, fail the alloc */
- error = mac_mbuf_init(m, how);
- if (error)
- return (error);
-#endif
-
- return (0);
-}
-
/*
* This is the protocol drain routine. Called by UMA whenever any of the
* mbuf zones is closed to its limit.
@@ -683,3 +662,323 @@ mb_reclaim(uma_zone_t zone __unused, int pending __unused)
if (pr->pr_drain != NULL)
(*pr->pr_drain)();
}
+
+/*
+ * Clean up after mbufs with M_EXT storage attached to them if the
+ * reference count hits 1.
+ */
+void
+mb_free_ext(struct mbuf *m)
+{
+ int freembuf;
+
+ KASSERT(m->m_flags & M_EXT, ("%s: M_EXT not set on %p", __func__, m));
+
+ /*
+ * Check if the header is embedded in the cluster.
+ */
+ freembuf = (m->m_flags & M_NOFREE) ? 0 : 1;
+
+ switch (m->m_ext.ext_type) {
+ case EXT_SFBUF:
+ sf_ext_free(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
+ break;
+ case EXT_SFBUF_NOCACHE:
+ sf_ext_free_nocache(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
+ break;
+ default:
+ KASSERT(m->m_ext.ext_cnt != NULL,
+ ("%s: no refcounting pointer on %p", __func__, m));
+ /*
+ * Free attached storage if this mbuf is the only
+ * reference to it.
+ */
+ if (*(m->m_ext.ext_cnt) != 1) {
+ if (atomic_fetchadd_int(m->m_ext.ext_cnt, -1) != 1)
+ break;
+ }
+
+ switch (m->m_ext.ext_type) {
+ case EXT_PACKET: /* The packet zone is special. */
+ if (*(m->m_ext.ext_cnt) == 0)
+ *(m->m_ext.ext_cnt) = 1;
+ uma_zfree(zone_pack, m);
+ return; /* Job done. */
+ case EXT_CLUSTER:
+ uma_zfree(zone_clust, m->m_ext.ext_buf);
+ break;
+ case EXT_JUMBOP:
+ uma_zfree(zone_jumbop, m->m_ext.ext_buf);
+ break;
+ case EXT_JUMBO9:
+ uma_zfree(zone_jumbo9, m->m_ext.ext_buf);
+ break;
+ case EXT_JUMBO16:
+ uma_zfree(zone_jumbo16, m->m_ext.ext_buf);
+ break;
+ case EXT_NET_DRV:
+ case EXT_MOD_TYPE:
+ case EXT_DISPOSABLE:
+ *(m->m_ext.ext_cnt) = 0;
+ uma_zfree(zone_ext_refcnt, __DEVOLATILE(u_int *,
+ m->m_ext.ext_cnt));
+ /* FALLTHROUGH */
+ case EXT_EXTREF:
+ KASSERT(m->m_ext.ext_free != NULL,
+ ("%s: ext_free not set", __func__));
+ (*(m->m_ext.ext_free))(m, m->m_ext.ext_arg1,
+ m->m_ext.ext_arg2);
+ break;
+ default:
+ KASSERT(m->m_ext.ext_type == 0,
+ ("%s: unknown ext_type", __func__));
+ }
+ }
+
+ if (freembuf)
+ uma_zfree(zone_mbuf, m);
+}
+
+/*
+ * Official mbuf(9) allocation KPI for stack and drivers:
+ *
+ * m_get() - a single mbuf without any attachments, sys/mbuf.h.
+ * m_gethdr() - a single mbuf initialized as M_PKTHDR, sys/mbuf.h.
+ * m_getcl() - an mbuf + 2k cluster, sys/mbuf.h.
+ * m_clget() - attach cluster to already allocated mbuf.
+ * m_cljget() - attach jumbo cluster to already allocated mbuf.
+ * m_get2() - allocate minimum mbuf that would fit size argument.
+ * m_getm2() - allocate a chain of mbufs/clusters.
+ * m_extadd() - attach external cluster to mbuf.
+ *
+ * m_free() - free single mbuf with its tags and ext, sys/mbuf.h.
+ * m_freem() - free chain of mbufs.
+ */
+
+int
+m_clget(struct mbuf *m, int how)
+{
+
+ KASSERT((m->m_flags & M_EXT) == 0, ("%s: mbuf %p has M_EXT",
+ __func__, m));
+ m->m_ext.ext_buf = (char *)NULL;
+ uma_zalloc_arg(zone_clust, m, how);
+ /*
+ * On a cluster allocation failure, drain the packet zone and retry,
+ * we might be able to loosen a few clusters up on the drain.
+ */
+ if ((how & M_NOWAIT) && (m->m_ext.ext_buf == NULL)) {
+ zone_drain(zone_pack);
+ uma_zalloc_arg(zone_clust, m, how);
+ }
+ return (m->m_flags & M_EXT);
+}
+
+/*
+ * m_cljget() is different from m_clget() as it can allocate clusters without
+ * attaching them to an mbuf. In that case the return value is the pointer
+ * to the cluster of the requested size. If an mbuf was specified, it gets
+ * the cluster attached to it and the return value can be safely ignored.
+ * For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES.
+ */
+void *
+m_cljget(struct mbuf *m, int how, int size)
+{
+ uma_zone_t zone;
+
+ if (m != NULL) {
+ KASSERT((m->m_flags & M_EXT) == 0, ("%s: mbuf %p has M_EXT",
+ __func__, m));
+ m->m_ext.ext_buf = NULL;
+ }
+
+ zone = m_getzone(size);
+ return (uma_zalloc_arg(zone, m, how));
+}
+
+/*
+ * m_get2() allocates minimum mbuf that would fit "size" argument.
+ */
+struct mbuf *
+m_get2(int size, int how, short type, int flags)
+{
+ struct mb_args args;
+ struct mbuf *m, *n;
+
+ args.flags = flags;
+ args.type = type;
+
+ if (size <= MHLEN || (size <= MLEN && (flags & M_PKTHDR) == 0))
+ return (uma_zalloc_arg(zone_mbuf, &args, how));
+ if (size <= MCLBYTES)
+ return (uma_zalloc_arg(zone_pack, &args, how));
+
+ if (size > MJUMPAGESIZE)
+ return (NULL);
+
+ m = uma_zalloc_arg(zone_mbuf, &args, how);
+ if (m == NULL)
+ return (NULL);
+
+ n = uma_zalloc_arg(zone_jumbop, m, how);
+ if (n == NULL) {
+ uma_zfree(zone_mbuf, m);
+ return (NULL);
+ }
+
+ return (m);
+}
+
+/*
+ * m_getjcl() returns an mbuf with a cluster of the specified size attached.
+ * For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES.
+ */
+struct mbuf *
+m_getjcl(int how, short type, int flags, int size)
+{
+ struct mb_args args;
+ struct mbuf *m, *n;
+ uma_zone_t zone;
+
+ if (size == MCLBYTES)
+ return m_getcl(how, type, flags);
+
+ args.flags = flags;
+ args.type = type;
+
+ m = uma_zalloc_arg(zone_mbuf, &args, how);
+ if (m == NULL)
+ return (NULL);
+
+ zone = m_getzone(size);
+ n = uma_zalloc_arg(zone, m, how);
+ if (n == NULL) {
+ uma_zfree(zone_mbuf, m);
+ return (NULL);
+ }
+ return (m);
+}
+
+/*
+ * Allocate a given length worth of mbufs and/or clusters (whatever fits
+ * best) and return a pointer to the top of the allocated chain. If an
+ * existing mbuf chain is provided, then we will append the new chain
+ * to the existing one but still return the top of the newly allocated
+ * chain.
+ */
+struct mbuf *
+m_getm2(struct mbuf *m, int len, int how, short type, int flags)
+{
+ struct mbuf *mb, *nm = NULL, *mtail = NULL;
+
+ KASSERT(len >= 0, ("%s: len is < 0", __func__));
+
+ /* Validate flags. */
+ flags &= (M_PKTHDR | M_EOR);
+
+ /* Packet header mbuf must be first in chain. */
+ if ((flags & M_PKTHDR) && m != NULL)
+ flags &= ~M_PKTHDR;
+
+ /* Loop and append maximum sized mbufs to the chain tail. */
+ while (len > 0) {
+ if (len > MCLBYTES)
+ mb = m_getjcl(how, type, (flags & M_PKTHDR),
+ MJUMPAGESIZE);
+ else if (len >= MINCLSIZE)
+ mb = m_getcl(how, type, (flags & M_PKTHDR));
+ else if (flags & M_PKTHDR)
+ mb = m_gethdr(how, type);
+ else
+ mb = m_get(how, type);
+
+ /* Fail the whole operation if one mbuf can't be allocated. */
+ if (mb == NULL) {
+ if (nm != NULL)
+ m_freem(nm);
+ return (NULL);
+ }
+
+ /* Book keeping. */
+ len -= M_SIZE(mb);
+ if (mtail != NULL)
+ mtail->m_next = mb;
+ else
+ nm = mb;
+ mtail = mb;
+ flags &= ~M_PKTHDR; /* Only valid on the first mbuf. */
+ }
+ if (flags & M_EOR)
+ mtail->m_flags |= M_EOR; /* Only valid on the last mbuf. */
+
+ /* If mbuf was supplied, append new chain to the end of it. */
+ if (m != NULL) {
+ for (mtail = m; mtail->m_next != NULL; mtail = mtail->m_next)
+ ;
+ mtail->m_next = nm;
+ mtail->m_flags &= ~M_EOR;
+ } else
+ m = nm;
+
+ return (m);
+}
+
+/*-
+ * Configure a provided mbuf to refer to the provided external storage
+ * buffer and setup a reference count for said buffer. If the setting
+ * up of the reference count fails, the M_EXT bit will not be set. If
+ * successfull, the M_EXT bit is set in the mbuf's flags.
+ *
+ * Arguments:
+ * mb The existing mbuf to which to attach the provided buffer.
+ * buf The address of the provided external storage buffer.
+ * size The size of the provided buffer.
+ * freef A pointer to a routine that is responsible for freeing the
+ * provided external storage buffer.
+ * args A pointer to an argument structure (of any type) to be passed
+ * to the provided freef routine (may be NULL).
+ * flags Any other flags to be passed to the provided mbuf.
+ * type The type that the external storage buffer should be
+ * labeled with.
+ *
+ * Returns:
+ * Nothing.
+ */
+int
+m_extadd(struct mbuf *mb, caddr_t buf, u_int size,
+ void (*freef)(struct mbuf *, void *, void *), void *arg1, void *arg2,
+ int flags, int type, int wait)
+{
+ KASSERT(type != EXT_CLUSTER, ("%s: EXT_CLUSTER not allowed", __func__));
+
+ if (type != EXT_EXTREF)
+ mb->m_ext.ext_cnt = uma_zalloc(zone_ext_refcnt, wait);
+
+ if (mb->m_ext.ext_cnt == NULL)
+ return (ENOMEM);
+
+ *(mb->m_ext.ext_cnt) = 1;
+ mb->m_flags |= (M_EXT | flags);
+ mb->m_ext.ext_buf = buf;
+ mb->m_data = mb->m_ext.ext_buf;
+ mb->m_ext.ext_size = size;
+ mb->m_ext.ext_free = freef;
+ mb->m_ext.ext_arg1 = arg1;
+ mb->m_ext.ext_arg2 = arg2;
+ mb->m_ext.ext_type = type;
+ mb->m_ext.ext_flags = 0;
+
+ return (0);
+}
+
+/*
+ * Free an entire chain of mbufs and associated external buffers, if
+ * applicable.
+ */
+void
+m_freem(struct mbuf *mb)
+{
+
+ while (mb != NULL)
+ mb = m_free(mb);
+}
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
index bf2dfd0..1579c28 100644
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -1090,12 +1090,9 @@ out:
vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
if (error != 0 && lf != NULL)
linker_file_unload(lf, LINKER_UNLOAD_FORCE);
- if (shdr != NULL)
- free(shdr, M_LINKER);
- if (firstpage != NULL)
- free(firstpage, M_LINKER);
- if (shstrs != NULL)
- free(shstrs, M_LINKER);
+ free(shdr, M_LINKER);
+ free(firstpage, M_LINKER);
+ free(shstrs, M_LINKER);
return (error);
}
@@ -1157,19 +1154,13 @@ link_elf_unload_file(linker_file_t file)
+ (ef->object->size << PAGE_SHIFT));
}
#else
- if (ef->address != NULL)
- free(ef->address, M_LINKER);
+ free(ef->address, M_LINKER);
#endif
- if (ef->symbase != NULL)
- free(ef->symbase, M_LINKER);
- if (ef->strbase != NULL)
- free(ef->strbase, M_LINKER);
- if (ef->ctftab != NULL)
- free(ef->ctftab, M_LINKER);
- if (ef->ctfoff != NULL)
- free(ef->ctfoff, M_LINKER);
- if (ef->typoff != NULL)
- free(ef->typoff, M_LINKER);
+ free(ef->symbase, M_LINKER);
+ free(ef->strbase, M_LINKER);
+ free(ef->ctftab, M_LINKER);
+ free(ef->ctfoff, M_LINKER);
+ free(ef->typoff, M_LINKER);
}
static void
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
index 00fe1e4..4d08aba 100644
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -898,8 +898,7 @@ out:
vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
if (error && lf)
linker_file_unload(lf, LINKER_UNLOAD_FORCE);
- if (hdr)
- free(hdr, M_LINKER);
+ free(hdr, M_LINKER);
return error;
}
@@ -930,18 +929,12 @@ link_elf_unload_file(linker_file_t file)
}
}
if (ef->preloaded) {
- if (ef->reltab)
- free(ef->reltab, M_LINKER);
- if (ef->relatab)
- free(ef->relatab, M_LINKER);
- if (ef->progtab)
- free(ef->progtab, M_LINKER);
- if (ef->ctftab)
- free(ef->ctftab, M_LINKER);
- if (ef->ctfoff)
- free(ef->ctfoff, M_LINKER);
- if (ef->typoff)
- free(ef->typoff, M_LINKER);
+ free(ef->reltab, M_LINKER);
+ free(ef->relatab, M_LINKER);
+ free(ef->progtab, M_LINKER);
+ free(ef->ctftab, M_LINKER);
+ free(ef->ctfoff, M_LINKER);
+ free(ef->typoff, M_LINKER);
if (file->filename != NULL)
preload_delete_name(file->filename);
/* XXX reclaim module memory? */
@@ -949,37 +942,25 @@ link_elf_unload_file(linker_file_t file)
}
for (i = 0; i < ef->nreltab; i++)
- if (ef->reltab[i].rel)
- free(ef->reltab[i].rel, M_LINKER);
+ free(ef->reltab[i].rel, M_LINKER);
for (i = 0; i < ef->nrelatab; i++)
- if (ef->relatab[i].rela)
- free(ef->relatab[i].rela, M_LINKER);
- if (ef->reltab)
- free(ef->reltab, M_LINKER);
- if (ef->relatab)
- free(ef->relatab, M_LINKER);
- if (ef->progtab)
- free(ef->progtab, M_LINKER);
+ free(ef->relatab[i].rela, M_LINKER);
+ free(ef->reltab, M_LINKER);
+ free(ef->relatab, M_LINKER);
+ free(ef->progtab, M_LINKER);
if (ef->object) {
vm_map_remove(kernel_map, (vm_offset_t) ef->address,
(vm_offset_t) ef->address +
(ef->object->size << PAGE_SHIFT));
}
- if (ef->e_shdr)
- free(ef->e_shdr, M_LINKER);
- if (ef->ddbsymtab)
- free(ef->ddbsymtab, M_LINKER);
- if (ef->ddbstrtab)
- free(ef->ddbstrtab, M_LINKER);
- if (ef->shstrtab)
- free(ef->shstrtab, M_LINKER);
- if (ef->ctftab)
- free(ef->ctftab, M_LINKER);
- if (ef->ctfoff)
- free(ef->ctfoff, M_LINKER);
- if (ef->typoff)
- free(ef->typoff, M_LINKER);
+ free(ef->e_shdr, M_LINKER);
+ free(ef->ddbsymtab, M_LINKER);
+ free(ef->ddbstrtab, M_LINKER);
+ free(ef->shstrtab, M_LINKER);
+ free(ef->ctftab, M_LINKER);
+ free(ef->ctfoff, M_LINKER);
+ free(ef->typoff, M_LINKER);
}
static const char *
diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c
index 813f9ec..7b5b77d 100644
--- a/sys/kern/subr_intr.c
+++ b/sys/kern/subr_intr.c
@@ -60,11 +60,11 @@ __FBSDID("$FreeBSD$");
#include <machine/smp.h>
#include <machine/stdarg.h>
+#ifdef FDT
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-
-#include <dev/fdt/fdt_common.h>
+#endif
#ifdef DDB
#include <ddb/ddb.h>
diff --git a/sys/kern/subr_turnstile.c b/sys/kern/subr_turnstile.c
index 7765cbf..57d9f09 100644
--- a/sys/kern/subr_turnstile.c
+++ b/sys/kern/subr_turnstile.c
@@ -1026,8 +1026,7 @@ print_thread(struct thread *td, const char *prefix)
{
db_printf("%s%p (tid %d, pid %d, \"%s\")\n", prefix, td, td->td_tid,
- td->td_proc->p_pid, td->td_name[0] != '\0' ? td->td_name :
- td->td_name);
+ td->td_proc->p_pid, td->td_name);
}
static void
@@ -1109,8 +1108,7 @@ print_lockchain(struct thread *td, const char *prefix)
*/
while (!db_pager_quit) {
db_printf("%sthread %d (pid %d, %s) ", prefix, td->td_tid,
- td->td_proc->p_pid, td->td_name[0] != '\0' ? td->td_name :
- td->td_name);
+ td->td_proc->p_pid, td->td_name);
switch (td->td_state) {
case TDS_INACTIVE:
db_printf("is inactive\n");
@@ -1193,8 +1191,7 @@ print_sleepchain(struct thread *td, const char *prefix)
*/
while (!db_pager_quit) {
db_printf("%sthread %d (pid %d, %s) ", prefix, td->td_tid,
- td->td_proc->p_pid, td->td_name[0] != '\0' ? td->td_name :
- td->td_name);
+ td->td_proc->p_pid, td->td_name);
switch (td->td_state) {
case TDS_INACTIVE:
db_printf("is inactive\n");
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 0b0b697..143aea7 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$");
#include <sys/protosw.h>
#include <sys/uio.h>
+#include <security/mac/mac_framework.h>
+
int max_linkhdr;
int max_protohdr;
int max_hdr;
@@ -132,269 +134,6 @@ CTASSERT(sizeof(m_assertbuf.m_stailqpkt) == sizeof(m_assertbuf.m_nextpkt));
#endif
/*
- * m_get2() allocates minimum mbuf that would fit "size" argument.
- */
-struct mbuf *
-m_get2(int size, int how, short type, int flags)
-{
- struct mb_args args;
- struct mbuf *m, *n;
-
- args.flags = flags;
- args.type = type;
-
- if (size <= MHLEN || (size <= MLEN && (flags & M_PKTHDR) == 0))
- return (uma_zalloc_arg(zone_mbuf, &args, how));
- if (size <= MCLBYTES)
- return (uma_zalloc_arg(zone_pack, &args, how));
-
- if (size > MJUMPAGESIZE)
- return (NULL);
-
- m = uma_zalloc_arg(zone_mbuf, &args, how);
- if (m == NULL)
- return (NULL);
-
- n = uma_zalloc_arg(zone_jumbop, m, how);
- if (n == NULL) {
- uma_zfree(zone_mbuf, m);
- return (NULL);
- }
-
- return (m);
-}
-
-/*
- * m_getjcl() returns an mbuf with a cluster of the specified size attached.
- * For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES.
- */
-struct mbuf *
-m_getjcl(int how, short type, int flags, int size)
-{
- struct mb_args args;
- struct mbuf *m, *n;
- uma_zone_t zone;
-
- if (size == MCLBYTES)
- return m_getcl(how, type, flags);
-
- args.flags = flags;
- args.type = type;
-
- m = uma_zalloc_arg(zone_mbuf, &args, how);
- if (m == NULL)
- return (NULL);
-
- zone = m_getzone(size);
- n = uma_zalloc_arg(zone, m, how);
- if (n == NULL) {
- uma_zfree(zone_mbuf, m);
- return (NULL);
- }
- return (m);
-}
-
-/*
- * Allocate a given length worth of mbufs and/or clusters (whatever fits
- * best) and return a pointer to the top of the allocated chain. If an
- * existing mbuf chain is provided, then we will append the new chain
- * to the existing one but still return the top of the newly allocated
- * chain.
- */
-struct mbuf *
-m_getm2(struct mbuf *m, int len, int how, short type, int flags)
-{
- struct mbuf *mb, *nm = NULL, *mtail = NULL;
-
- KASSERT(len >= 0, ("%s: len is < 0", __func__));
-
- /* Validate flags. */
- flags &= (M_PKTHDR | M_EOR);
-
- /* Packet header mbuf must be first in chain. */
- if ((flags & M_PKTHDR) && m != NULL)
- flags &= ~M_PKTHDR;
-
- /* Loop and append maximum sized mbufs to the chain tail. */
- while (len > 0) {
- if (len > MCLBYTES)
- mb = m_getjcl(how, type, (flags & M_PKTHDR),
- MJUMPAGESIZE);
- else if (len >= MINCLSIZE)
- mb = m_getcl(how, type, (flags & M_PKTHDR));
- else if (flags & M_PKTHDR)
- mb = m_gethdr(how, type);
- else
- mb = m_get(how, type);
-
- /* Fail the whole operation if one mbuf can't be allocated. */
- if (mb == NULL) {
- if (nm != NULL)
- m_freem(nm);
- return (NULL);
- }
-
- /* Book keeping. */
- len -= M_SIZE(mb);
- if (mtail != NULL)
- mtail->m_next = mb;
- else
- nm = mb;
- mtail = mb;
- flags &= ~M_PKTHDR; /* Only valid on the first mbuf. */
- }
- if (flags & M_EOR)
- mtail->m_flags |= M_EOR; /* Only valid on the last mbuf. */
-
- /* If mbuf was supplied, append new chain to the end of it. */
- if (m != NULL) {
- for (mtail = m; mtail->m_next != NULL; mtail = mtail->m_next)
- ;
- mtail->m_next = nm;
- mtail->m_flags &= ~M_EOR;
- } else
- m = nm;
-
- return (m);
-}
-
-/*
- * Free an entire chain of mbufs and associated external buffers, if
- * applicable.
- */
-void
-m_freem(struct mbuf *mb)
-{
-
- while (mb != NULL)
- mb = m_free(mb);
-}
-
-/*-
- * Configure a provided mbuf to refer to the provided external storage
- * buffer and setup a reference count for said buffer. If the setting
- * up of the reference count fails, the M_EXT bit will not be set. If
- * successfull, the M_EXT bit is set in the mbuf's flags.
- *
- * Arguments:
- * mb The existing mbuf to which to attach the provided buffer.
- * buf The address of the provided external storage buffer.
- * size The size of the provided buffer.
- * freef A pointer to a routine that is responsible for freeing the
- * provided external storage buffer.
- * args A pointer to an argument structure (of any type) to be passed
- * to the provided freef routine (may be NULL).
- * flags Any other flags to be passed to the provided mbuf.
- * type The type that the external storage buffer should be
- * labeled with.
- *
- * Returns:
- * Nothing.
- */
-int
-m_extadd(struct mbuf *mb, caddr_t buf, u_int size,
- void (*freef)(struct mbuf *, void *, void *), void *arg1, void *arg2,
- int flags, int type, int wait)
-{
- KASSERT(type != EXT_CLUSTER, ("%s: EXT_CLUSTER not allowed", __func__));
-
- if (type != EXT_EXTREF)
- mb->m_ext.ext_cnt = uma_zalloc(zone_ext_refcnt, wait);
-
- if (mb->m_ext.ext_cnt == NULL)
- return (ENOMEM);
-
- *(mb->m_ext.ext_cnt) = 1;
- mb->m_flags |= (M_EXT | flags);
- mb->m_ext.ext_buf = buf;
- mb->m_data = mb->m_ext.ext_buf;
- mb->m_ext.ext_size = size;
- mb->m_ext.ext_free = freef;
- mb->m_ext.ext_arg1 = arg1;
- mb->m_ext.ext_arg2 = arg2;
- mb->m_ext.ext_type = type;
- mb->m_ext.ext_flags = 0;
-
- return (0);
-}
-
-/*
- * Non-directly-exported function to clean up after mbufs with M_EXT
- * storage attached to them if the reference count hits 1.
- */
-void
-mb_free_ext(struct mbuf *m)
-{
- int freembuf;
-
- KASSERT(m->m_flags & M_EXT, ("%s: M_EXT not set on %p", __func__, m));
-
- /*
- * Check if the header is embedded in the cluster.
- */
- freembuf = (m->m_flags & M_NOFREE) ? 0 : 1;
-
- switch (m->m_ext.ext_type) {
- case EXT_SFBUF:
- sf_ext_free(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
- break;
- case EXT_SFBUF_NOCACHE:
- sf_ext_free_nocache(m->m_ext.ext_arg1, m->m_ext.ext_arg2);
- break;
- default:
- KASSERT(m->m_ext.ext_cnt != NULL,
- ("%s: no refcounting pointer on %p", __func__, m));
- /*
- * Free attached storage if this mbuf is the only
- * reference to it.
- */
- if (*(m->m_ext.ext_cnt) != 1) {
- if (atomic_fetchadd_int(m->m_ext.ext_cnt, -1) != 1)
- break;
- }
-
- switch (m->m_ext.ext_type) {
- case EXT_PACKET: /* The packet zone is special. */
- if (*(m->m_ext.ext_cnt) == 0)
- *(m->m_ext.ext_cnt) = 1;
- uma_zfree(zone_pack, m);
- return; /* Job done. */
- case EXT_CLUSTER:
- uma_zfree(zone_clust, m->m_ext.ext_buf);
- break;
- case EXT_JUMBOP:
- uma_zfree(zone_jumbop, m->m_ext.ext_buf);
- break;
- case EXT_JUMBO9:
- uma_zfree(zone_jumbo9, m->m_ext.ext_buf);
- break;
- case EXT_JUMBO16:
- uma_zfree(zone_jumbo16, m->m_ext.ext_buf);
- break;
- case EXT_NET_DRV:
- case EXT_MOD_TYPE:
- case EXT_DISPOSABLE:
- *(m->m_ext.ext_cnt) = 0;
- uma_zfree(zone_ext_refcnt, __DEVOLATILE(u_int *,
- m->m_ext.ext_cnt));
- /* FALLTHROUGH */
- case EXT_EXTREF:
- KASSERT(m->m_ext.ext_free != NULL,
- ("%s: ext_free not set", __func__));
- (*(m->m_ext.ext_free))(m, m->m_ext.ext_arg1,
- m->m_ext.ext_arg2);
- break;
- default:
- KASSERT(m->m_ext.ext_type == 0,
- ("%s: unknown ext_type", __func__));
- }
- }
-
- if (freembuf)
- uma_zfree(zone_mbuf, m);
-}
-
-/*
* Attach the cluster from *m to *n, set up m_ext in *n
* and bump the refcount of the cluster.
*/
@@ -534,6 +273,26 @@ m_sanity(struct mbuf *m0, int sanitize)
#undef M_SANITY_ACTION
}
+/*
+ * Non-inlined part of m_init().
+ */
+int
+m_pkthdr_init(struct mbuf *m, int how)
+{
+#ifdef MAC
+ int error;
+#endif
+ m->m_data = m->m_pktdat;
+ bzero(&m->m_pkthdr, sizeof(m->m_pkthdr));
+#ifdef MAC
+ /* If the label init fails, fail the alloc */
+ error = mac_mbuf_init(m, how);
+ if (error)
+ return (error);
+#endif
+
+ return (0);
+}
/*
* "Move" mbuf pkthdr from "from" to "to".
diff --git a/sys/mips/conf/AR71XX_BASE b/sys/mips/conf/AR71XX_BASE
index 2b9d075..a296eab 100644
--- a/sys/mips/conf/AR71XX_BASE
+++ b/sys/mips/conf/AR71XX_BASE
@@ -9,7 +9,7 @@
machine mips mips
ident AR71XX_BASE
-cpu CPU_MIPS4KC
+cpu CPU_MIPS24K
makeoptions KERNLOADADDR=0x80050000
options HZ=1000
options HWPMC_HOOKS
diff --git a/sys/mips/conf/AR724X_BASE b/sys/mips/conf/AR724X_BASE
index c1145b7..662e801 100644
--- a/sys/mips/conf/AR724X_BASE
+++ b/sys/mips/conf/AR724X_BASE
@@ -10,7 +10,7 @@
machine mips mips
ident AR724X_BASE
-cpu CPU_MIPS4KC
+cpu CPU_MIPS24K
makeoptions KERNLOADADDR=0x80050000
options HZ=1000
options HWPMC_HOOKS
diff --git a/sys/mips/conf/AR91XX_BASE b/sys/mips/conf/AR91XX_BASE
index 07e5121..982c386 100644
--- a/sys/mips/conf/AR91XX_BASE
+++ b/sys/mips/conf/AR91XX_BASE
@@ -12,7 +12,7 @@
machine mips mips
ident AR91XX_BASE
-cpu CPU_MIPS4KC
+cpu CPU_MIPS24K
makeoptions KERNLOADADDR=0x80050000
options HZ=1000
diff --git a/sys/mips/conf/QCA953X_BASE b/sys/mips/conf/QCA953X_BASE
index 3126f71..08de505 100644
--- a/sys/mips/conf/QCA953X_BASE
+++ b/sys/mips/conf/QCA953X_BASE
@@ -12,7 +12,7 @@
machine mips mips
ident QCA953X_BASE
-cpu CPU_MIPS4KC
+cpu CPU_MIPS24K
makeoptions KERNLOADADDR=0x80050000
options HZ=1000
diff --git a/sys/mips/include/bus.h b/sys/mips/include/bus.h
index 370d52f..5e85b17 100644
--- a/sys/mips/include/bus.h
+++ b/sys/mips/include/bus.h
@@ -721,7 +721,6 @@ void __bs_c(f,_bs_c_8) (void *t, bus_space_handle_t bsh1, \
*/
DECLARE_BUS_SPACE_PROTOTYPES(generic);
extern bus_space_tag_t mips_bus_space_generic;
-extern bus_space_tag_t mips_bus_space_fdt;
/* Special bus space for RMI processors */
#if defined(CPU_RMI) || defined (CPU_NLM)
diff --git a/sys/mips/include/fdt.h b/sys/mips/include/fdt.h
index 72cc485..62356b8 100644
--- a/sys/mips/include/fdt.h
+++ b/sys/mips/include/fdt.h
@@ -40,7 +40,7 @@
#if defined(CPU_RMI) || defined(CPU_NLM)
#define fdtbus_bs_tag rmi_uart_bus_space
#else
-#define fdtbus_bs_tag mips_bus_space_fdt
+#define fdtbus_bs_tag mips_bus_space_generic
#endif
#endif /* _MACHINE_FDT_H_ */
diff --git a/sys/mips/include/intr.h b/sys/mips/include/intr.h
new file mode 100644
index 0000000..28f798f
--- /dev/null
+++ b/sys/mips/include/intr.h
@@ -0,0 +1,67 @@
+/* $NetBSD: intr.h,v 1.7 2003/06/16 20:01:00 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1997 Mark Brinicombe.
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the company nor the name of the author may 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 OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ *
+ */
+
+#ifndef _MACHINE_INTR_H_
+#define _MACHINE_INTR_H_
+
+#ifdef MIPS_INTRNG
+
+#ifdef FDT
+#include <dev/ofw/openfirm.h>
+#endif
+
+#include <sys/intr.h>
+
+#ifndef NIRQ
+#define NIRQ 128
+#endif
+
+#define INTR_IRQ_NSPC_SWI 4
+
+/* MIPS compatibility for legacy mips code */
+void cpu_init_interrupts(void);
+void cpu_establish_hardintr(const char *, driver_filter_t *, driver_intr_t *,
+ void *, int, int, void **);
+void cpu_establish_softintr(const char *, driver_filter_t *, void (*)(void*),
+ void *, int, int, void **);
+/* MIPS interrupt C entry point */
+void cpu_intr(struct trapframe *);
+
+#endif /* MIPS_INTRNG */
+
+#endif /* _MACHINE_INTR_H */
diff --git a/sys/mips/include/smp.h b/sys/mips/include/smp.h
index 0fcca9a..fa4cb5c 100644
--- a/sys/mips/include/smp.h
+++ b/sys/mips/include/smp.h
@@ -21,6 +21,11 @@
#include <machine/pcb.h>
+#ifdef MIPS_INTRNG
+# define MIPS_IPI_COUNT 1
+# define INTR_IPI_COUNT MIPS_IPI_COUNT
+#endif
+
/*
* Interprocessor interrupts for SMP.
*/
diff --git a/sys/mips/include/ucontext.h b/sys/mips/include/ucontext.h
index a37fe7e..2b1a952 100644
--- a/sys/mips/include/ucontext.h
+++ b/sys/mips/include/ucontext.h
@@ -50,13 +50,13 @@ typedef struct __mcontext {
* struct sigcontext and ucontext_t at the same time.
*/
int mc_onstack; /* sigstack state to restore */
- register_t mc_pc; /* pc at time of signal */
- register_t mc_regs[32]; /* processor regs 0 to 31 */
- register_t sr; /* status register */
- register_t mullo, mulhi; /* mullo and mulhi registers... */
+ __register_t mc_pc; /* pc at time of signal */
+ __register_t mc_regs[32]; /* processor regs 0 to 31 */
+ __register_t sr; /* status register */
+ __register_t mullo, mulhi; /* mullo and mulhi registers... */
int mc_fpused; /* fp has been used */
f_register_t mc_fpregs[33]; /* fp regs 0 to 31 and csr */
- register_t mc_fpc_eir; /* fp exception instruction reg */
+ __register_t mc_fpc_eir; /* fp exception instruction reg */
void *mc_tls; /* pointer to TLS area */
int __spare__[8]; /* XXX reserved */
} mcontext_t;
diff --git a/sys/mips/mips/bus_space_fdt.c b/sys/mips/mips/bus_space_fdt.c
deleted file mode 100644
index 0b14718..0000000
--- a/sys/mips/mips/bus_space_fdt.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */
-/*-
- * $Id: bus.h,v 1.6 2007/08/09 11:23:32 katta Exp $
- *
- * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
- * NASA Ames Research Center.
- *
- * 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. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``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 FOUNDATION OR CONTRIBUTORS
- * 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.
- */
-
-/*
- * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
- * Copyright (c) 1996 Christopher G. Demetriou. 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. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Christopher G. Demetriou
- * for the NetBSD Project.
- * 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.
- *
- * from: src/sys/alpha/include/bus.h,v 1.5 1999/08/28 00:38:40 peter
- * $FreeBSD$
- */
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/ktr.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_kern.h>
-#include <vm/vm_extern.h>
-
-#include <machine/bus.h>
-#include <machine/cache.h>
-
-static int fdt_bs_map(void *, bus_addr_t, bus_size_t, int,
- bus_space_handle_t *);
-
-static struct bus_space fdt_space = {
- /* cookie */
- .bs_cookie = (void *) 0,
-
- /* mapping/unmapping */
- .bs_map = fdt_bs_map,
- .bs_unmap = generic_bs_unmap,
- .bs_subregion = generic_bs_subregion,
-
- /* allocation/deallocation */
- .bs_alloc = generic_bs_alloc,
- .bs_free = generic_bs_free,
-
- /* barrier */
- .bs_barrier = generic_bs_barrier,
-
- /* read (single) */
- .bs_r_1 = generic_bs_r_1,
- .bs_r_2 = generic_bs_r_2,
- .bs_r_4 = generic_bs_r_4,
- .bs_r_8 = generic_bs_r_8,
-
- /* read multiple */
- .bs_rm_1 = generic_bs_rm_1,
- .bs_rm_2 = generic_bs_rm_2,
- .bs_rm_4 = generic_bs_rm_4,
- .bs_rm_8 = generic_bs_rm_8,
-
- /* read region */
- .bs_rr_1 = generic_bs_rr_1,
- .bs_rr_2 = generic_bs_rr_2,
- .bs_rr_4 = generic_bs_rr_4,
- .bs_rr_8 = generic_bs_rr_8,
-
- /* write (single) */
- .bs_w_1 = generic_bs_w_1,
- .bs_w_2 = generic_bs_w_2,
- .bs_w_4 = generic_bs_w_4,
- .bs_w_8 = generic_bs_w_8,
-
- /* write multiple */
- .bs_wm_1 = generic_bs_wm_1,
- .bs_wm_2 = generic_bs_wm_2,
- .bs_wm_4 = generic_bs_wm_4,
- .bs_wm_8 = generic_bs_wm_8,
-
- /* write region */
- .bs_wr_1 = generic_bs_wr_1,
- .bs_wr_2 = generic_bs_wr_2,
- .bs_wr_4 = generic_bs_wr_4,
- .bs_wr_8 = generic_bs_wr_8,
-
- /* set multiple */
- .bs_sm_1 = generic_bs_sm_1,
- .bs_sm_2 = generic_bs_sm_2,
- .bs_sm_4 = generic_bs_sm_4,
- .bs_sm_8 = generic_bs_sm_8,
-
- /* set region */
- .bs_sr_1 = generic_bs_sr_1,
- .bs_sr_2 = generic_bs_sr_2,
- .bs_sr_4 = generic_bs_sr_4,
- .bs_sr_8 = generic_bs_sr_8,
-
- /* copy */
- .bs_c_1 = generic_bs_c_1,
- .bs_c_2 = generic_bs_c_2,
- .bs_c_4 = generic_bs_c_4,
- .bs_c_8 = generic_bs_c_8,
-
- /* read (single) stream */
- .bs_r_1_s = generic_bs_r_1,
- .bs_r_2_s = generic_bs_r_2,
- .bs_r_4_s = generic_bs_r_4,
- .bs_r_8_s = generic_bs_r_8,
-
- /* read multiple stream */
- .bs_rm_1_s = generic_bs_rm_1,
- .bs_rm_2_s = generic_bs_rm_2,
- .bs_rm_4_s = generic_bs_rm_4,
- .bs_rm_8_s = generic_bs_rm_8,
-
- /* read region stream */
- .bs_rr_1_s = generic_bs_rr_1,
- .bs_rr_2_s = generic_bs_rr_2,
- .bs_rr_4_s = generic_bs_rr_4,
- .bs_rr_8_s = generic_bs_rr_8,
-
- /* write (single) stream */
- .bs_w_1_s = generic_bs_w_1,
- .bs_w_2_s = generic_bs_w_2,
- .bs_w_4_s = generic_bs_w_4,
- .bs_w_8_s = generic_bs_w_8,
-
- /* write multiple stream */
- .bs_wm_1_s = generic_bs_wm_1,
- .bs_wm_2_s = generic_bs_wm_2,
- .bs_wm_4_s = generic_bs_wm_4,
- .bs_wm_8_s = generic_bs_wm_8,
-
- /* write region stream */
- .bs_wr_1_s = generic_bs_wr_1,
- .bs_wr_2_s = generic_bs_wr_2,
- .bs_wr_4_s = generic_bs_wr_4,
- .bs_wr_8_s = generic_bs_wr_8,
-};
-
-/* generic bus_space tag */
-bus_space_tag_t mips_bus_space_fdt = &fdt_space;
-
-static int
-fdt_bs_map(void *t __unused, bus_addr_t addr, bus_size_t size __unused,
- int flags __unused, bus_space_handle_t *bshp)
-{
-
- *bshp = MIPS_PHYS_TO_DIRECT_UNCACHED(addr);
- return (0);
-}
diff --git a/sys/mips/mips/bus_space_generic.c b/sys/mips/mips/bus_space_generic.c
index d82d97e..b57a739 100644
--- a/sys/mips/mips/bus_space_generic.c
+++ b/sys/mips/mips/bus_space_generic.c
@@ -228,20 +228,21 @@ bus_space_tag_t mips_bus_space_generic = &generic_space;
int
generic_bs_map(void *t __unused, bus_addr_t addr,
- bus_size_t size __unused, int flags __unused,
+ bus_size_t size, int flags __unused,
bus_space_handle_t *bshp)
{
- *bshp = addr;
+ *bshp = (bus_space_handle_t)pmap_mapdev((vm_paddr_t)addr,
+ (vm_size_t)size);
return (0);
}
void
-generic_bs_unmap(void *t __unused, bus_space_handle_t bh __unused,
- bus_size_t size __unused)
+generic_bs_unmap(void *t __unused, bus_space_handle_t bh,
+ bus_size_t size)
{
- /* Do nothing */
+ pmap_unmapdev((vm_offset_t)bh, (vm_size_t)size);
}
int
diff --git a/sys/mips/mips/exception.S b/sys/mips/mips/exception.S
index 01fd210..ebfd84d 100644
--- a/sys/mips/mips/exception.S
+++ b/sys/mips/mips/exception.S
@@ -646,7 +646,11 @@ NESTED_NOPROFILE(MipsKernIntr, KERN_EXC_FRAME_SIZE, ra)
* Call the interrupt handler. a0 points at the saved frame.
*/
PTR_LA gp, _C_LABEL(_gp)
+#ifdef MIPS_INTRNG
+ PTR_LA k0, _C_LABEL(intr_irq_handler)
+#else
PTR_LA k0, _C_LABEL(cpu_intr)
+#endif
jalr k0
REG_S a3, CALLFRAME_RA + KERN_REG_SIZE(sp) # for debugging
@@ -758,7 +762,11 @@ NESTED_NOPROFILE(MipsUserIntr, CALLFRAME_SIZ, ra)
/*
* Call the interrupt handler.
*/
+#ifdef MIPS_INTRNG
+ PTR_LA k0, _C_LABEL(intr_irq_handler)
+#else
PTR_LA k0, _C_LABEL(cpu_intr)
+#endif
jalr k0
REG_S a3, CALLFRAME_RA(sp) # for debugging
@@ -1190,6 +1198,7 @@ FPReturn:
PTR_ADDU sp, sp, CALLFRAME_SIZ
END(MipsFPTrap)
+#ifndef MIPS_INTRNG
/*
* Interrupt counters for vmstat.
*/
@@ -1216,6 +1225,7 @@ sintrcnt:
#else
.int INTRCNT_COUNT * (_MIPS_SZLONG / 8) * 2
#endif
+#endif /* MIPS_INTRNG */
/*
diff --git a/sys/mips/mips/mips_pic.c b/sys/mips/mips/mips_pic.c
new file mode 100644
index 0000000..250f8cf
--- /dev/null
+++ b/sys/mips/mips/mips_pic.c
@@ -0,0 +1,514 @@
+/*-
+ * Copyright (c) 2015 Alexander Kabaev
+ * Copyright (c) 2006 Oleksandr Tymoshenko
+ * Copyright (c) 2002-2004 Juli Mallett <jmallett@FreeBSD.org>
+ * 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,
+ * without modification, immediately at the beginning of the file.
+ * 2. 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_platform.h"
+#include "opt_hwpmc_hooks.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/pcpu.h>
+#include <sys/proc.h>
+#include <sys/cpuset.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+#include <sys/sched.h>
+
+#include <machine/bus.h>
+#include <machine/hwfunc.h>
+#include <machine/intr.h>
+#include <machine/smp.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+#include "pic_if.h"
+
+#define NHARD_IRQS 6
+#define NSOFT_IRQS 2
+#define NREAL_IRQS (NHARD_IRQS + NSOFT_IRQS)
+
+static int mips_pic_intr(void *);
+
+struct mips_pic_softc {
+ device_t pic_dev;
+ struct intr_irqsrc * pic_irqs[NREAL_IRQS];
+ struct mtx mutex;
+ uint32_t nirqs;
+};
+
+static struct mips_pic_softc *pic_sc;
+
+#ifdef FDT
+static struct ofw_compat_data compat_data[] = {
+ {"mti,cpu-interrupt-controller", true},
+ {NULL, false}
+};
+#endif
+
+#ifndef FDT
+static void
+mips_pic_identify(driver_t *drv, device_t parent)
+{
+
+ BUS_ADD_CHILD(parent, 0, "cpupic", 0);
+}
+#endif
+
+static int
+mips_pic_probe(device_t dev)
+{
+
+#ifdef FDT
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+#endif
+ device_set_desc(dev, "MIPS32 Interrupt Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static inline void
+pic_irq_unmask(struct mips_pic_softc *sc, u_int irq)
+{
+
+ mips_wr_status(mips_rd_status() | ((1 << irq) << 8));
+}
+
+static inline void
+pic_irq_mask(struct mips_pic_softc *sc, u_int irq)
+{
+
+ mips_wr_status(mips_rd_status() & ~((1 << irq) << 8));
+}
+
+#ifdef SMP
+static void
+mips_pic_init_secondary(device_t dev)
+{
+}
+#endif /* SMP */
+
+static inline intptr_t
+pic_xref(device_t dev)
+{
+#ifdef FDT
+ return (OF_xref_from_node(ofw_bus_get_node(dev)));
+#else
+ return (0);
+#endif
+}
+
+static int
+mips_pic_attach(device_t dev)
+{
+ struct mips_pic_softc *sc;
+ intptr_t xref = pic_xref(dev);
+
+ if (pic_sc)
+ return (ENXIO);
+
+ sc = device_get_softc(dev);
+
+ sc->pic_dev = dev;
+ pic_sc = sc;
+
+ /* Initialize mutex */
+ mtx_init(&sc->mutex, "PIC lock", "", MTX_SPIN);
+
+ /* Set the number of interrupts */
+ sc->nirqs = nitems(sc->pic_irqs);
+
+ /*
+ * Now, when everything is initialized, it's right time to
+ * register interrupt controller to interrupt framefork.
+ */
+ if (intr_pic_register(dev, xref) != 0) {
+ device_printf(dev, "could not register PIC\n");
+ goto cleanup;
+ }
+
+ /* Claim our root controller role */
+ if (intr_pic_claim_root(dev, xref, mips_pic_intr, sc, 0) != 0) {
+ device_printf(dev, "could not set PIC as a root\n");
+ intr_pic_unregister(dev, xref);
+ goto cleanup;
+ }
+
+ return (0);
+
+cleanup:
+ return(ENXIO);
+}
+
+int
+mips_pic_intr(void *arg)
+{
+ struct mips_pic_softc *sc = arg;
+ register_t cause, status;
+ struct intr_irqsrc *isrc;
+ int i, intr;
+
+ cause = mips_rd_cause();
+ status = mips_rd_status();
+ intr = (cause & MIPS_INT_MASK) >> 8;
+ /*
+ * Do not handle masked interrupts. They were masked by
+ * pre_ithread function (mips_mask_XXX_intr) and will be
+ * unmasked once ithread is through with handler
+ */
+ intr &= (status & MIPS_INT_MASK) >> 8;
+ while ((i = fls(intr)) != 0) {
+ i--; /* Get a 0-offset interrupt. */
+ intr &= ~(1 << i);
+
+ isrc = sc->pic_irqs[i];
+ if (isrc == NULL) {
+ device_printf(sc->pic_dev,
+ "Stray interrupt %u detected\n", i);
+ pic_irq_mask(sc, i);
+ continue;
+ }
+
+ intr_irq_dispatch(isrc, curthread->td_intr_frame);
+ }
+
+ KASSERT(i == 0, ("all interrupts handled"));
+
+#ifdef HWPMC_HOOKS
+ if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
+ pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf);
+#endif
+ return (FILTER_HANDLED);
+}
+
+static int
+pic_attach_isrc(struct mips_pic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
+{
+
+ /*
+ * 1. The link between ISRC and controller must be set atomically.
+ * 2. Just do things only once in rare case when consumers
+ * of shared interrupt came here at the same moment.
+ */
+ mtx_lock_spin(&sc->mutex);
+ if (sc->pic_irqs[irq] != NULL) {
+ mtx_unlock_spin(&sc->mutex);
+ return (sc->pic_irqs[irq] == isrc ? 0 : EEXIST);
+ }
+ sc->pic_irqs[irq] = isrc;
+ isrc->isrc_data = irq;
+ mtx_unlock_spin(&sc->mutex);
+
+ if (irq < NSOFT_IRQS)
+ intr_irq_set_name(isrc, "sint%u", irq);
+ else if (irq < NREAL_IRQS)
+ intr_irq_set_name(isrc, "int%u", irq - NSOFT_IRQS);
+ else
+ panic("Invalid irq %u", irq);
+ return (0);
+}
+
+static int
+pic_detach_isrc(struct mips_pic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
+{
+
+ mtx_lock_spin(&sc->mutex);
+ if (sc->pic_irqs[irq] != isrc) {
+ mtx_unlock_spin(&sc->mutex);
+ return (sc->pic_irqs[irq] == NULL ? 0 : EINVAL);
+ }
+ sc->pic_irqs[irq] = NULL;
+ isrc->isrc_data = 0;
+ mtx_unlock_spin(&sc->mutex);
+
+ intr_irq_set_name(isrc, "%s", "");
+ return (0);
+}
+
+static int
+pic_irq_from_nspc(struct mips_pic_softc *sc, u_int type, u_int num, u_int *irqp)
+{
+
+ switch (type) {
+ case INTR_IRQ_NSPC_PLAIN:
+ *irqp = num;
+ return (*irqp < sc->nirqs ? 0 : EINVAL);
+
+ case INTR_IRQ_NSPC_SWI:
+ *irqp = num;
+ return (num < NSOFT_IRQS ? 0 : EINVAL);
+
+ case INTR_IRQ_NSPC_IRQ:
+ *irqp = num + NSOFT_IRQS;
+ return (num < NHARD_IRQS ? 0 : EINVAL);
+
+ default:
+ return (EINVAL);
+ }
+}
+
+static int
+pic_map_nspc(struct mips_pic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
+{
+ int error;
+
+ error = pic_irq_from_nspc(sc, isrc->isrc_nspc_type, isrc->isrc_nspc_num,
+ irqp);
+ if (error != 0)
+ return (error);
+ return (pic_attach_isrc(sc, isrc, *irqp));
+}
+
+#ifdef FDT
+static int
+pic_map_fdt(struct mips_pic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
+{
+ u_int irq;
+ int error;
+
+ irq = isrc->isrc_cells[0];
+
+ if (irq >= sc->nirqs)
+ return (EINVAL);
+
+ error = pic_attach_isrc(sc, isrc, irq);
+ if (error != 0)
+ return (error);
+
+ isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN;
+ isrc->isrc_nspc_num = irq;
+ isrc->isrc_trig = INTR_TRIGGER_CONFORM;
+ isrc->isrc_pol = INTR_POLARITY_CONFORM;
+
+ *irqp = irq;
+ return (0);
+}
+#endif
+
+static int
+mips_pic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu)
+{
+ struct mips_pic_softc *sc = device_get_softc(dev);
+ u_int irq;
+ int error;
+
+ if (isrc->isrc_type == INTR_ISRCT_NAMESPACE)
+ error = pic_map_nspc(sc, isrc, &irq);
+#ifdef FDT
+ else if (isrc->isrc_type == INTR_ISRCT_FDT)
+ error = pic_map_fdt(sc, isrc, &irq);
+#endif
+ else
+ return (EINVAL);
+
+ if (error == 0)
+ *is_percpu = TRUE;
+ return (error);
+}
+
+static void
+mips_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+
+ if (isrc->isrc_trig == INTR_TRIGGER_CONFORM)
+ isrc->isrc_trig = INTR_TRIGGER_LEVEL;
+}
+
+static void
+mips_pic_enable_source(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct mips_pic_softc *sc = device_get_softc(dev);
+ u_int irq = isrc->isrc_data;
+
+ pic_irq_unmask(sc, irq);
+}
+
+static void
+mips_pic_disable_source(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct mips_pic_softc *sc = device_get_softc(dev);
+ u_int irq = isrc->isrc_data;
+
+ pic_irq_mask(sc, irq);
+}
+
+static int
+mips_pic_unregister(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct mips_pic_softc *sc = device_get_softc(dev);
+ u_int irq = isrc->isrc_data;
+
+ return (pic_detach_isrc(sc, isrc, irq));
+}
+
+static void
+mips_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+
+ mips_pic_disable_source(dev, isrc);
+}
+
+static void
+mips_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+
+ mips_pic_enable_source(dev, isrc);
+}
+
+static void
+mips_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
+{
+}
+
+#ifdef SMP
+static int
+mips_pic_bind(device_t dev, struct intr_irqsrc *isrc)
+{
+ return (EOPNOTSUPP);
+}
+
+static void
+mips_pic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus)
+{
+}
+#endif
+
+static device_method_t mips_pic_methods[] = {
+ /* Device interface */
+#ifndef FDT
+ DEVMETHOD(device_identify, mips_pic_identify),
+#endif
+ DEVMETHOD(device_probe, mips_pic_probe),
+ DEVMETHOD(device_attach, mips_pic_attach),
+ /* Interrupt controller interface */
+ DEVMETHOD(pic_disable_source, mips_pic_disable_source),
+ DEVMETHOD(pic_enable_intr, mips_pic_enable_intr),
+ DEVMETHOD(pic_enable_source, mips_pic_enable_source),
+ DEVMETHOD(pic_post_filter, mips_pic_post_filter),
+ DEVMETHOD(pic_post_ithread, mips_pic_post_ithread),
+ DEVMETHOD(pic_pre_ithread, mips_pic_pre_ithread),
+ DEVMETHOD(pic_register, mips_pic_register),
+ DEVMETHOD(pic_unregister, mips_pic_unregister),
+#ifdef SMP
+ DEVMETHOD(pic_bind, mips_pic_bind),
+ DEVMETHOD(pic_init_secondary, mips_pic_init_secondary),
+ DEVMETHOD(pic_ipi_send, mips_pic_ipi_send),
+#endif
+ { 0, 0 }
+};
+
+static driver_t mips_pic_driver = {
+ "cpupic",
+ mips_pic_methods,
+ sizeof(struct mips_pic_softc),
+};
+
+static devclass_t mips_pic_devclass;
+
+#ifdef FDT
+EARLY_DRIVER_MODULE(cpupic, ofwbus, mips_pic_driver, mips_pic_devclass, 0, 0,
+ BUS_PASS_INTERRUPT);
+#else
+EARLY_DRIVER_MODULE(cpupic, nexus, mips_pic_driver, mips_pic_devclass, 0, 0,
+ BUS_PASS_INTERRUPT);
+#endif
+
+void
+cpu_init_interrupts(void)
+{
+}
+
+void
+cpu_establish_hardintr(const char *name, driver_filter_t *filt,
+ void (*handler)(void*), void *arg, int irq, int flags, void **cookiep)
+{
+ u_int vec;
+ int res;
+
+ /*
+ * We have 6 levels, but thats 0 - 5 (not including 6)
+ */
+ if (irq < 0 || irq >= NHARD_IRQS)
+ panic("%s called for unknown hard intr %d", __func__, irq);
+
+ KASSERT(pic_sc != NULL, ("%s: no pic", __func__));
+ vec = intr_namespace_map_irq(pic_sc->pic_dev, INTR_IRQ_NSPC_IRQ, irq);
+ KASSERT(vec != NIRQ, ("Unable to map hard IRQ %d\n", irq));
+
+ res = intr_irq_add_handler(pic_sc->pic_dev, filt, handler, arg, vec,
+ flags, cookiep);
+ if (res != 0) panic("Unable to add hard IRQ %d handler", irq);
+
+ (void)pic_irq_from_nspc(pic_sc, INTR_IRQ_NSPC_IRQ, irq, &vec);
+ KASSERT(pic_sc->pic_irqs[vec] != NULL,
+ ("Hard IRQ %d not registered\n", irq));
+ intr_irq_set_name(pic_sc->pic_irqs[vec], "%s", name);
+}
+
+void
+cpu_establish_softintr(const char *name, driver_filter_t *filt,
+ void (*handler)(void*), void *arg, int irq, int flags,
+ void **cookiep)
+{
+ u_int vec;
+ int res;
+
+ if (irq < 0 || irq > NSOFT_IRQS)
+ panic("%s called for unknown soft intr %d", __func__, irq);
+
+ KASSERT(pic_sc != NULL, ("%s: no pic", __func__));
+ vec = intr_namespace_map_irq(pic_sc->pic_dev, INTR_IRQ_NSPC_SWI, irq);
+ KASSERT(vec <= NIRQ, ("Unable to map soft IRQ %d\n", irq));
+
+ intr_irq_add_handler(pic_sc->pic_dev, filt, handler, arg, vec,
+ flags, cookiep);
+ if (res != 0) panic("Unable to add soft IRQ %d handler", irq);
+
+ (void)pic_irq_from_nspc(pic_sc, INTR_IRQ_NSPC_SWI, irq, &vec);
+ KASSERT(pic_sc->pic_irqs[vec] != NULL,
+ ("Soft IRQ %d not registered\n", irq));
+ intr_irq_set_name(pic_sc->pic_irqs[vec], "%s", name);
+}
+
diff --git a/sys/mips/mips/nexus.c b/sys/mips/mips/nexus.c
index d2ee6af..1e3d409 100644
--- a/sys/mips/mips/nexus.c
+++ b/sys/mips/mips/nexus.c
@@ -36,6 +36,7 @@
* this code implements the core resource managers for interrupt
* requests and memory address space.
*/
+#include "opt_platform.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -53,12 +54,20 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <machine/bus.h>
-#include <machine/intr_machdep.h>
#include <machine/pmap.h>
#include <machine/resource.h>
#include <machine/vmparam.h>
-#include "opt_platform.h"
+#ifdef MIPS_INTRNG
+#include <machine/intr.h>
+#else
+#include <machine/intr_machdep.h>
+#endif
+
+#ifdef FDT
+#include <dev/ofw/openfirm.h>
+#include "ofw_bus_if.h"
+#endif
#undef NEXUS_DEBUG
#ifdef NEXUS_DEBUG
@@ -107,6 +116,19 @@ static int nexus_setup_intr(device_t dev, device_t child,
driver_intr_t *intr, void *arg, void **cookiep);
static int nexus_teardown_intr(device_t, device_t, struct resource *,
void *);
+#ifdef MIPS_INTRNG
+#ifdef SMP
+static int nexus_bind_intr(device_t, device_t, struct resource *, int);
+#endif
+#ifdef FDT
+static int nexus_ofw_map_intr(device_t dev, device_t child,
+ phandle_t iparent, int icells, pcell_t *intr);
+#endif
+static int nexus_describe_intr(device_t dev, device_t child,
+ struct resource *irq, void *cookie, const char *descr);
+static int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
+ enum intr_polarity pol);
+#endif
static device_method_t nexus_methods[] = {
/* Device interface */
@@ -127,6 +149,16 @@ static device_method_t nexus_methods[] = {
DEVMETHOD(bus_activate_resource,nexus_activate_resource),
DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
DEVMETHOD(bus_hinted_child, nexus_hinted_child),
+#ifdef MIPS_INTRNG
+ DEVMETHOD(bus_config_intr, nexus_config_intr),
+ DEVMETHOD(bus_describe_intr, nexus_describe_intr),
+#ifdef SMP
+ DEVMETHOD(bus_bind_intr, nexus_bind_intr),
+#endif
+#ifdef FDT
+ DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr),
+#endif
+#endif
{ 0, 0 }
};
@@ -381,6 +413,7 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid,
void *vaddr;
vm_paddr_t paddr;
vm_size_t psize;
+ int err;
/*
* If this is a memory resource, use pmap_mapdev to map it.
@@ -388,10 +421,14 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid,
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
paddr = rman_get_start(r);
psize = rman_get_size(r);
- vaddr = pmap_mapdev(paddr, psize);
-
- rman_set_virtual(r, vaddr);
rman_set_bustag(r, mips_bus_space_generic);
+ err = bus_space_map(rman_get_bustag(r), paddr, psize, 0,
+ (bus_space_handle_t *)&vaddr);
+ if (err != 0) {
+ rman_deactivate_resource(r);
+ return (err);
+ }
+ rman_set_virtual(r, vaddr);
rman_set_bushandle(r, (bus_space_handle_t)(uintptr_t)vaddr);
}
@@ -402,11 +439,16 @@ static int
nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
- vm_offset_t va;
-
- if (type == SYS_RES_MEMORY) {
- va = (vm_offset_t)rman_get_virtual(r);
- pmap_unmapdev(va, rman_get_size(r));
+ bus_space_handle_t vaddr;
+ bus_size_t psize;
+
+ vaddr = rman_get_bushandle(r);
+
+ if (type == SYS_RES_MEMORY && vaddr != 0) {
+ psize = (bus_size_t)rman_get_size(r);
+ bus_space_unmap(rman_get_bustag(r), vaddr, psize);
+ rman_set_virtual(r, NULL);
+ rman_set_bushandle(r, 0);
}
return (rman_deactivate_resource(r));
@@ -416,9 +458,16 @@ static int
nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
{
- register_t s;
int irq;
+#ifdef MIPS_INTRNG
+ for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) {
+ intr_irq_add_handler(child, filt, intr, arg, irq, flags,
+ cookiep);
+ }
+#else
+ register_t s;
+
s = intr_disable();
irq = rman_get_start(res);
if (irq >= NUM_MIPS_IRQS) {
@@ -429,6 +478,7 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
cpu_establish_hardintr(device_get_nameunit(child), filt, intr, arg,
irq, flags, cookiep);
intr_restore(s);
+#endif
return (0);
}
@@ -436,9 +486,50 @@ static int
nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
{
+#ifdef MIPS_INTRNG
+ return (intr_irq_remove_handler(child, rman_get_start(r), ih));
+#else
printf("Unimplemented %s at %s:%d\n", __func__, __FILE__, __LINE__);
return (0);
+#endif
+}
+
+#ifdef MIPS_INTRNG
+static int
+nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
+ enum intr_polarity pol)
+{
+
+ return (intr_irq_config(irq, trig, pol));
+}
+
+static int
+nexus_describe_intr(device_t dev, device_t child, struct resource *irq,
+ void *cookie, const char *descr)
+{
+
+ return (intr_irq_describe(rman_get_start(irq), cookie, descr));
+}
+
+#ifdef SMP
+static int
+nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu)
+{
+
+ return (intr_irq_bind(rman_get_start(irq), cpu));
+}
+#endif
+
+#ifdef FDT
+static int
+nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
+ pcell_t *intr)
+{
+
+ return (intr_fdt_map_irq(iparent, intr, icells));
}
+#endif
+#endif /* MIPS_INTRNG */
static void
nexus_hinted_child(device_t bus, const char *dname, int dunit)
@@ -493,4 +584,5 @@ nexus_hinted_child(device_t bus, const char *dname, int dunit)
}
}
-DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
+EARLY_DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0,
+ BUS_PASS_BUS + BUS_PASS_ORDER_EARLY);
diff --git a/sys/mips/mips/tick.c b/sys/mips/mips/tick.c
index 501e5bb..b146ad7 100644
--- a/sys/mips/mips/tick.c
+++ b/sys/mips/mips/tick.c
@@ -51,6 +51,10 @@ __FBSDID("$FreeBSD$");
#include <machine/locore.h>
#include <machine/md_var.h>
+#ifdef MIPS_INTRNG
+#include <machine/intr.h>
+#endif
+
uint64_t counter_freq;
struct timecounter *platform_timecounter;
@@ -324,12 +328,18 @@ static int
clock_attach(device_t dev)
{
struct clock_softc *sc;
+#ifndef MIPS_INTRNG
int error;
+#endif
if (device_get_unit(dev) != 0)
panic("can't attach more clocks");
softc = sc = device_get_softc(dev);
+#ifdef MIPS_INTRNG
+ cpu_establish_hardintr("clock", clock_intr, NULL, sc, 5, INTR_TYPE_CLK,
+ NULL);
+#else
sc->intr_rid = 0;
sc->intr_res = bus_alloc_resource(dev,
SYS_RES_IRQ, &sc->intr_rid, 5, 5, 1, RF_ACTIVE);
@@ -343,6 +353,7 @@ clock_attach(device_t dev)
device_printf(dev, "bus_setup_intr returned %d\n", error);
return (error);
}
+#endif
sc->tc.tc_get_timecount = counter_get_timecount;
sc->tc.tc_counter_mask = 0xffffffff;
diff --git a/sys/modules/dtb/allwinner/Makefile b/sys/modules/dtb/allwinner/Makefile
index 660ca97..80ac333 100644
--- a/sys/modules/dtb/allwinner/Makefile
+++ b/sys/modules/dtb/allwinner/Makefile
@@ -3,6 +3,8 @@
DTS= \
bananapi.dts \
cubieboard.dts \
- cubieboard2.dts
+ cubieboard2.dts \
+ olimex-a20-som-evb.dts \
+ olinuxino-lime.dts
.include <bsd.dtb.mk>
diff --git a/sys/net/route.c b/sys/net/route.c
index 8ad0e24..45f479c 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -353,10 +353,24 @@ rt_table_init(int offset)
return (rh);
}
+static int
+rt_freeentry(struct radix_node *rn, void *arg)
+{
+ struct radix_head * const rnh = arg;
+ struct radix_node *x;
+
+ x = (struct radix_node *)rn_delete(rn + 2, NULL, rnh);
+ if (x != NULL)
+ R_Free(x);
+ return (0);
+}
+
void
rt_table_destroy(struct rib_head *rh)
{
+ rn_walktree(&rh->rmhead.head, rt_freeentry, &rh->rmhead.head);
+
/* Assume table is already empty */
rw_destroy(&rh->rib_lock);
free(rh, M_RTABLE);
diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c
index c2a09e4..2cface4 100644
--- a/sys/netinet/in_rmx.c
+++ b/sys/netinet/in_rmx.c
@@ -133,7 +133,8 @@ int
in_detachhead(void **head, int off)
{
- return (rn_detachhead(head));
+ rt_table_destroy((struct rib_head *)(*head));
+ return (1);
}
#endif
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index a26bc5b..5837f6f 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -978,10 +978,7 @@ __FBSDID("$FreeBSD$");
(((uint8_t *)&(a)->s_addr)[1] == 168)))
#define IN4_ISLOOPBACK_ADDRESS(a) \
- ((((uint8_t *)&(a)->s_addr)[0] == 127) && \
- (((uint8_t *)&(a)->s_addr)[1] == 0) && \
- (((uint8_t *)&(a)->s_addr)[2] == 0) && \
- (((uint8_t *)&(a)->s_addr)[3] == 1))
+ (((uint8_t *)&(a)->s_addr)[0] == 127)
#define IN4_ISLINKLOCAL_ADDRESS(a) \
((((uint8_t *)&(a)->s_addr)[0] == 169) && \
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index e197936..7e38b78 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -426,11 +426,11 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS)
xinpcb.maxqlen = 0;
} else {
xinpcb.qlen = so->so_qlen;
- xinpcb.qlen_old = so->so_qlen > USHRT_MAX ?
- USHRT_MAX : (uint16_t) so->so_qlen;
+ xinpcb.qlen_old = so->so_qlen > USHRT_MAX ?
+ USHRT_MAX : (uint16_t) so->so_qlen;
xinpcb.maxqlen = so->so_qlimit;
- xinpcb.maxqlen_old = so->so_qlimit > USHRT_MAX ?
- USHRT_MAX : (uint16_t) so->so_qlimit;
+ xinpcb.maxqlen_old = so->so_qlimit > USHRT_MAX ?
+ USHRT_MAX : (uint16_t) so->so_qlimit;
}
SCTP_INP_INCR_REF(inp);
SCTP_INP_RUNLOCK(inp);
diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c
index d49071c..62d8595 100644
--- a/sys/netinet/tcp_lro.c
+++ b/sys/netinet/tcp_lro.c
@@ -347,9 +347,10 @@ tcp_lro_mbuf_compare_header(const void *ppa, const void *ppb)
if (ret != 0)
goto done;
- ret = ma->m_pkthdr.flowid - mb->m_pkthdr.flowid;
- if (ret != 0)
- goto done;
+ if (ma->m_pkthdr.flowid > mb->m_pkthdr.flowid)
+ return (1);
+ else if (ma->m_pkthdr.flowid < mb->m_pkthdr.flowid)
+ return (-1);
ret = TCP_LRO_SEQUENCE(ma) - TCP_LRO_SEQUENCE(mb);
done:
diff --git a/sys/netinet/tcp_pcap.c b/sys/netinet/tcp_pcap.c
index f0c651d..41a7fbf 100644
--- a/sys/netinet/tcp_pcap.c
+++ b/sys/netinet/tcp_pcap.c
@@ -341,7 +341,7 @@ tcp_pcap_add(struct tcphdr *th, struct mbuf *m, struct mbufq *queue)
n = mhead;
tcp_pcap_m_freem(n->m_next);
- m_init(n, NULL, 0, M_NOWAIT, MT_DATA, 0);
+ m_init(n, M_NOWAIT, MT_DATA, 0);
}
}
diff --git a/sys/netinet6/in6_rmx.c b/sys/netinet6/in6_rmx.c
index 38b4bf2..102ad50 100644
--- a/sys/netinet6/in6_rmx.c
+++ b/sys/netinet6/in6_rmx.c
@@ -237,7 +237,9 @@ in6_detachhead(void **head, int off)
{
callout_drain(&V_rtq_mtutimer);
- return (rn_detachhead(head));
+ rt_table_destroy((struct rib_head *)(*head));
+
+ return (1);
}
#endif
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 4371a02..010b7cc 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -113,11 +113,6 @@ VNET_DEFINE(int, nd6_debug) = 0;
static eventhandler_tag lle_event_eh, iflladdr_event_eh;
-/* for debugging? */
-#if 0
-static int nd6_inuse, nd6_allocated;
-#endif
-
VNET_DEFINE(struct nd_drhead, nd_defrouter);
VNET_DEFINE(struct nd_prhead, nd_prefix);
@@ -248,7 +243,7 @@ nd6_ifattach(struct ifnet *ifp)
{
struct nd_ifinfo *nd;
- nd = (struct nd_ifinfo *)malloc(sizeof(*nd), M_IP6NDP, M_WAITOK|M_ZERO);
+ nd = malloc(sizeof(*nd), M_IP6NDP, M_WAITOK | M_ZERO);
nd->initialized = 1;
nd->chlim = IPV6_DEFHLIM;
@@ -2517,7 +2512,6 @@ clear_llinfo_pqueue(struct llentry *ln)
}
ln->la_hold = NULL;
- return;
}
static int nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS);
@@ -2556,7 +2550,7 @@ nd6_sysctl_drlist(SYSCTL_HANDLER_ARGS)
error = sa6_recoverscope(&d.rtaddr);
if (error != 0)
return (error);
- d.flags = dr->flags;
+ d.flags = dr->raflags;
d.rtlifetime = dr->rtlifetime;
d.expire = dr->expire + (time_second - time_uptime);
d.if_index = dr->ifp->if_index;
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 6ff4cac..a11ec51 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -232,13 +232,13 @@ struct in6_ndifreq {
((MAX_RANDOM_FACTOR - MIN_RANDOM_FACTOR) * (x >> 10)))) /1000)
TAILQ_HEAD(nd_drhead, nd_defrouter);
-struct nd_defrouter {
+struct nd_defrouter {
TAILQ_ENTRY(nd_defrouter) dr_entry;
- struct in6_addr rtaddr;
- u_char flags; /* flags on RA message */
+ struct in6_addr rtaddr;
+ u_char raflags; /* flags on RA message */
u_short rtlifetime;
u_long expire;
- struct ifnet *ifp;
+ struct ifnet *ifp;
int installed; /* is installed into kernel routing table */
};
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index 3a4e8a0..5369df9 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -584,7 +584,6 @@ nd6_ns_output_fib(struct ifnet *ifp, const struct in6_addr *saddr6,
bad:
m_freem(m);
- return;
}
#ifndef BURN_BRIDGES
@@ -864,12 +863,6 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
in6 = &ln->r_l3addr.addr6;
- /*
- * Lock to protect the default router list.
- * XXX: this might be unnecessary, since this function
- * is only called under the network software interrupt
- * context. However, we keep it just for safety.
- */
nd6_ifp = lltable_get_ifp(ln->lle_tbl);
dr = defrouter_lookup(in6, nd6_ifp);
if (dr)
@@ -1078,7 +1071,6 @@ nd6_na_output_fib(struct ifnet *ifp, const struct in6_addr *daddr6_0,
bad:
m_freem(m);
- return;
}
#ifndef BURN_BRIDGES
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index ca64908..5f29b66 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -272,7 +272,7 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len)
bzero(&dr0, sizeof(dr0));
dr0.rtaddr = saddr6;
- dr0.flags = nd_ra->nd_ra_flags_reserved;
+ dr0.raflags = nd_ra->nd_ra_flags_reserved;
/*
* Effectively-disable routes from RA messages when
* ND6_IFF_NO_RADR enabled on the receiving interface or
@@ -503,7 +503,6 @@ defrouter_addreq(struct nd_defrouter *new)
}
if (error == 0)
new->installed = 1;
- return;
}
struct nd_defrouter *
@@ -702,8 +701,6 @@ defrouter_select(void)
defrouter_delreq(installed_dr);
defrouter_addreq(selected_dr);
}
-
- return;
}
/*
@@ -713,7 +710,7 @@ defrouter_select(void)
static int
rtpref(struct nd_defrouter *dr)
{
- switch (dr->flags & ND_RA_FLAG_RTPREF_MASK) {
+ switch (dr->raflags & ND_RA_FLAG_RTPREF_MASK) {
case ND_RA_FLAG_RTPREF_HIGH:
return (RTPREF_HIGH);
case ND_RA_FLAG_RTPREF_MEDIUM:
@@ -727,7 +724,7 @@ rtpref(struct nd_defrouter *dr)
* serious bug of kernel internal. We thus always bark here.
* Or, can we even panic?
*/
- log(LOG_ERR, "rtpref: impossible RA flag %x\n", dr->flags);
+ log(LOG_ERR, "rtpref: impossible RA flag %x\n", dr->raflags);
return (RTPREF_INVALID);
}
/* NOTREACHED */
@@ -737,53 +734,47 @@ static struct nd_defrouter *
defrtrlist_update(struct nd_defrouter *new)
{
struct nd_defrouter *dr, *n;
+ int oldpref;
if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) {
/* entry exists */
if (new->rtlifetime == 0) {
defrtrlist_del(dr);
- dr = NULL;
- } else {
- int oldpref = rtpref(dr);
+ return (NULL);
+ }
- /* override */
- dr->flags = new->flags; /* xxx flag check */
- dr->rtlifetime = new->rtlifetime;
- dr->expire = new->expire;
+ oldpref = rtpref(dr);
- /*
- * If the preference does not change, there's no need
- * to sort the entries. Also make sure the selected
- * router is still installed in the kernel.
- */
- if (dr->installed && rtpref(new) == oldpref)
- return (dr);
+ /* override */
+ dr->raflags = new->raflags; /* XXX flag check */
+ dr->rtlifetime = new->rtlifetime;
+ dr->expire = new->expire;
- /*
- * preferred router may be changed, so relocate
- * this router.
- * XXX: calling TAILQ_REMOVE directly is a bad manner.
- * However, since defrtrlist_del() has many side
- * effects, we intentionally do so here.
- * defrouter_select() below will handle routing
- * changes later.
- */
- TAILQ_REMOVE(&V_nd_defrouter, dr, dr_entry);
- n = dr;
- goto insert;
- }
- return (dr);
+ /*
+ * If the preference does not change, there's no need
+ * to sort the entries. Also make sure the selected
+ * router is still installed in the kernel.
+ */
+ if (dr->installed && rtpref(new) == oldpref)
+ return (dr);
+
+ /*
+ * The preferred router may have changed, so relocate this
+ * router.
+ */
+ TAILQ_REMOVE(&V_nd_defrouter, dr, dr_entry);
+ n = dr;
+ goto insert;
}
/* entry does not exist */
if (new->rtlifetime == 0)
return (NULL);
- n = (struct nd_defrouter *)malloc(sizeof(*n), M_IP6NDP, M_NOWAIT);
+ n = malloc(sizeof(*n), M_IP6NDP, M_NOWAIT | M_ZERO);
if (n == NULL)
return (NULL);
- bzero(n, sizeof(*n));
- *n = *new;
+ memcpy(n, new, sizeof(*n));
insert:
/*
@@ -826,10 +817,9 @@ pfxrtr_add(struct nd_prefix *pr, struct nd_defrouter *dr)
{
struct nd_pfxrouter *new;
- new = (struct nd_pfxrouter *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
+ new = malloc(sizeof(*new), M_IP6NDP, M_NOWAIT | M_ZERO);
if (new == NULL)
return;
- bzero(new, sizeof(*new));
new->router = dr;
LIST_INSERT_HEAD(&pr->ndpr_advrtrs, new, pfr_entry);
@@ -869,10 +859,9 @@ nd6_prelist_add(struct nd_prefixctl *pr, struct nd_defrouter *dr,
int error = 0;
char ip6buf[INET6_ADDRSTRLEN];
- new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
+ new = malloc(sizeof(*new), M_IP6NDP, M_NOWAIT | M_ZERO);
if (new == NULL)
- return(ENOMEM);
- bzero(new, sizeof(*new));
+ return (ENOMEM);
new->ndpr_ifp = pr->ndpr_ifp;
new->ndpr_prefix = pr->ndpr_prefix;
new->ndpr_plen = pr->ndpr_plen;
diff --git a/sys/netinet6/scope6.c b/sys/netinet6/scope6.c
index 1a9d038..a00842e 100644
--- a/sys/netinet6/scope6.c
+++ b/sys/netinet6/scope6.c
@@ -371,7 +371,7 @@ sa6_recoverscope(struct sockaddr_in6 *sin6)
zoneid != sin6->sin6_scope_id) {
log(LOG_NOTICE,
"%s: embedded scope mismatch: %s%%%d. "
- "sin6_scope_id was overridden.", __func__,
+ "sin6_scope_id was overridden\n", __func__,
ip6_sprintf(ip6buf, &sin6->sin6_addr),
sin6->sin6_scope_id);
}
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index d0712b4..86da60a 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -412,13 +412,13 @@ tlb_calc_wimg(vm_paddr_t pa, vm_memattr_t ma)
if (ma != VM_MEMATTR_DEFAULT) {
switch (ma) {
case VM_MEMATTR_UNCACHEABLE:
- return (PTE_I | PTE_G);
+ return (MAS2_I | MAS2_G);
case VM_MEMATTR_WRITE_COMBINING:
case VM_MEMATTR_WRITE_BACK:
case VM_MEMATTR_PREFETCHABLE:
- return (PTE_I);
+ return (MAS2_I);
case VM_MEMATTR_WRITE_THROUGH:
- return (PTE_W | PTE_M);
+ return (MAS2_W | MAS2_M);
}
}
@@ -900,8 +900,7 @@ pte_remove(mmu_t mmu, pmap_t pmap, vm_offset_t va, uint8_t flags)
tlb_miss_lock();
tlb0_flush_entry(va);
- pte->flags = 0;
- pte->rpn = 0;
+ *pte = 0;
tlb_miss_unlock();
mtx_unlock_spin(&tlbivax_mutex);
@@ -984,8 +983,8 @@ pte_enter(mmu_t mmu, pmap_t pmap, vm_page_t m, vm_offset_t va, uint32_t flags,
pmap->pm_pdir[pdir_idx] = ptbl;
}
pte = &(pmap->pm_pdir[pdir_idx][ptbl_idx]);
- pte->rpn = PTE_RPN_FROM_PA(VM_PAGE_TO_PHYS(m));
- pte->flags |= (PTE_VALID | flags);
+ *pte = PTE_RPN_FROM_PA(VM_PAGE_TO_PHYS(m));
+ *pte |= (PTE_VALID | flags | PTE_PS_4KB); /* 4KB pages only */
tlb_miss_unlock();
mtx_unlock_spin(&tlbivax_mutex);
@@ -1041,9 +1040,9 @@ kernel_pte_alloc(vm_offset_t data_end, vm_offset_t addr, vm_offset_t pdir)
*/
for (va = addr; va < data_end; va += PAGE_SIZE) {
pte = &(kernel_pmap->pm_pdir[PDIR_IDX(va)][PTBL_IDX(va)]);
- pte->rpn = kernload + (va - kernstart);
- pte->flags = PTE_M | PTE_SR | PTE_SW | PTE_SX | PTE_WIRED |
- PTE_VALID;
+ *pte = PTE_RPN_FROM_PA(kernload + (va - kernstart));
+ *pte |= PTE_M | PTE_SR | PTE_SW | PTE_SX | PTE_WIRED |
+ PTE_VALID | PTE_PS_4KB;
}
}
@@ -1525,7 +1524,8 @@ mmu_booke_kenter_attr(mmu_t mmu, vm_offset_t va, vm_paddr_t pa, vm_memattr_t ma)
(va <= VM_MAX_KERNEL_ADDRESS)), ("mmu_booke_kenter: invalid va"));
flags = PTE_SR | PTE_SW | PTE_SX | PTE_WIRED | PTE_VALID;
- flags |= tlb_calc_wimg(pa, ma);
+ flags |= tlb_calc_wimg(pa, ma) << PTE_MAS2_SHIFT;
+ flags |= PTE_PS_4KB;
pte = pte_find(mmu, kernel_pmap, va);
@@ -1540,17 +1540,15 @@ mmu_booke_kenter_attr(mmu_t mmu, vm_offset_t va, vm_paddr_t pa, vm_memattr_t ma)
tlb0_flush_entry(va);
}
- pte->rpn = PTE_RPN_FROM_PA(pa);
- pte->flags = flags;
+ *pte = PTE_RPN_FROM_PA(pa) | flags;
//debugf("mmu_booke_kenter: pdir_idx = %d ptbl_idx = %d va=0x%08x "
// "pa=0x%08x rpn=0x%08x flags=0x%08x\n",
// pdir_idx, ptbl_idx, va, pa, pte->rpn, pte->flags);
/* Flush the real memory from the instruction cache. */
- if ((flags & (PTE_I | PTE_G)) == 0) {
+ if ((flags & (PTE_I | PTE_G)) == 0)
__syncicache((void *)va, PAGE_SIZE);
- }
tlb_miss_unlock();
mtx_unlock_spin(&tlbivax_mutex);
@@ -1584,8 +1582,7 @@ mmu_booke_kremove(mmu_t mmu, vm_offset_t va)
/* Invalidate entry in TLB0, update PTE. */
tlb0_flush_entry(va);
- pte->flags = 0;
- pte->rpn = 0;
+ *pte = 0;
tlb_miss_unlock();
mtx_unlock_spin(&tlbivax_mutex);
@@ -1700,7 +1697,7 @@ mmu_booke_enter_locked(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
* Before actually updating pte->flags we calculate and
* prepare its new value in a helper var.
*/
- flags = pte->flags;
+ flags = *pte;
flags &= ~(PTE_UW | PTE_UX | PTE_SW | PTE_SX | PTE_MODIFIED);
/* Wiring change, just update stats. */
@@ -1748,7 +1745,7 @@ mmu_booke_enter_locked(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
* are turning execute permissions on, icache should
* be flushed.
*/
- if ((pte->flags & (PTE_UX | PTE_SX)) == 0)
+ if ((*pte & (PTE_UX | PTE_SX)) == 0)
sync++;
}
@@ -1762,7 +1759,7 @@ mmu_booke_enter_locked(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
tlb_miss_lock();
tlb0_flush_entry(va);
- pte->flags = flags;
+ *pte = flags;
tlb_miss_unlock();
mtx_unlock_spin(&tlbivax_mutex);
@@ -2069,7 +2066,7 @@ mmu_booke_protect(mmu_t mmu, pmap_t pmap, vm_offset_t sva, vm_offset_t eva,
vm_page_dirty(m);
tlb0_flush_entry(va);
- pte->flags &= ~(PTE_UW | PTE_SW | PTE_MODIFIED);
+ *pte &= ~(PTE_UW | PTE_SW | PTE_MODIFIED);
tlb_miss_unlock();
mtx_unlock_spin(&tlbivax_mutex);
@@ -2114,7 +2111,7 @@ mmu_booke_remove_write(mmu_t mmu, vm_page_t m)
vm_page_dirty(m);
/* Flush mapping from TLB0. */
- pte->flags &= ~(PTE_UW | PTE_SW | PTE_MODIFIED);
+ *pte &= ~(PTE_UW | PTE_SW | PTE_MODIFIED);
tlb_miss_unlock();
mtx_unlock_spin(&tlbivax_mutex);
@@ -2194,7 +2191,7 @@ retry:
else
pte_wbit = PTE_UW;
- if ((pte->flags & pte_wbit) || ((prot & VM_PROT_WRITE) == 0)) {
+ if ((*pte & pte_wbit) || ((prot & VM_PROT_WRITE) == 0)) {
if (vm_page_pa_tryrelock(pmap, PTE_PA(pte), &pa))
goto retry;
m = PHYS_TO_VM_PAGE(PTE_PA(pte));
@@ -2340,14 +2337,15 @@ mmu_booke_quick_enter_page(mmu_t mmu, vm_page_t m)
paddr = VM_PAGE_TO_PHYS(m);
flags = PTE_SR | PTE_SW | PTE_SX | PTE_WIRED | PTE_VALID;
- flags |= tlb_calc_wimg(paddr, pmap_page_get_memattr(m));
+ flags |= tlb_calc_wimg(paddr, pmap_page_get_memattr(m)) << PTE_MAS2_SHIFT;
+ flags |= PTE_PS_4KB;
critical_enter();
qaddr = PCPU_GET(qmap_addr);
pte = pte_find(mmu, kernel_pmap, qaddr);
- KASSERT(pte->flags == 0, ("mmu_booke_quick_enter_page: PTE busy"));
+ KASSERT(*pte == 0, ("mmu_booke_quick_enter_page: PTE busy"));
/*
* XXX: tlbivax is broadcast to other cores, but qaddr should
@@ -2357,8 +2355,7 @@ mmu_booke_quick_enter_page(mmu_t mmu, vm_page_t m)
__asm __volatile("tlbivax 0, %0" :: "r"(qaddr & MAS2_EPN_MASK));
__asm __volatile("isync; msync");
- pte->rpn = paddr & ~PTE_PA_MASK;
- pte->flags = flags;
+ *pte = PTE_RPN_FROM_PA(paddr) | flags;
/* Flush the real memory from the instruction cache. */
if ((flags & (PTE_I | PTE_G)) == 0)
@@ -2376,11 +2373,10 @@ mmu_booke_quick_remove_page(mmu_t mmu, vm_offset_t addr)
KASSERT(PCPU_GET(qmap_addr) == addr,
("mmu_booke_quick_remove_page: invalid address"));
- KASSERT(pte->flags != 0,
+ KASSERT(*pte != 0,
("mmu_booke_quick_remove_page: PTE not in use"));
- pte->flags = 0;
- pte->rpn = 0;
+ *pte = 0;
critical_exit();
}
@@ -2494,9 +2490,9 @@ mmu_booke_clear_modify(mmu_t mmu, vm_page_t m)
mtx_lock_spin(&tlbivax_mutex);
tlb_miss_lock();
- if (pte->flags & (PTE_SW | PTE_UW | PTE_MODIFIED)) {
+ if (*pte & (PTE_SW | PTE_UW | PTE_MODIFIED)) {
tlb0_flush_entry(pv->pv_va);
- pte->flags &= ~(PTE_SW | PTE_UW | PTE_MODIFIED |
+ *pte &= ~(PTE_SW | PTE_UW | PTE_MODIFIED |
PTE_REFERENCED);
}
@@ -2538,7 +2534,7 @@ mmu_booke_ts_referenced(mmu_t mmu, vm_page_t m)
tlb_miss_lock();
tlb0_flush_entry(pv->pv_va);
- pte->flags &= ~PTE_REFERENCED;
+ *pte &= ~PTE_REFERENCED;
tlb_miss_unlock();
mtx_unlock_spin(&tlbivax_mutex);
@@ -2577,7 +2573,7 @@ mmu_booke_unwire(mmu_t mmu, pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
if (!PTE_ISWIRED(pte))
panic("mmu_booke_unwire: pte %p isn't wired",
pte);
- pte->flags &= ~PTE_WIRED;
+ *pte &= ~PTE_WIRED;
pmap->pm_stats.wired_count--;
}
}
diff --git a/sys/powerpc/booke/trap_subr.S b/sys/powerpc/booke/trap_subr.S
index 5f5f1aa..8737dba 100644
--- a/sys/powerpc/booke/trap_subr.S
+++ b/sys/powerpc/booke/trap_subr.S
@@ -686,7 +686,7 @@ pte_lookup:
* This load may cause a Data TLB miss for non-kernel pmap!
*/
lwz %r21, PTE_FLAGS(%r25)
- andis. %r21, %r21, PTE_VALID@h
+ andi. %r21, %r21, PTE_VALID@l
bne 2f
1:
li %r25, 0
@@ -721,20 +721,21 @@ tlb_fill_entry:
andi. %r22, %r21, (PTE_SW | PTE_UW)@l /* check if writable */
beq 2f
- oris %r21, %r21, PTE_MODIFIED@h /* set modified bit */
+ ori %r21, %r21, PTE_MODIFIED@l /* set modified bit */
2:
stwcx. %r21, %r23, %r25 /* write it back */
bne- 1b
/* Update MAS2. */
- rlwimi %r27, %r21, 0, 27, 30 /* insert WIMG bits from pte */
+ rlwimi %r27, %r21, 13, 27, 30 /* insert WIMG bits from pte */
/* Setup MAS3 value in r23. */
lwz %r23, PTE_RPN(%r25) /* get pte->rpn */
- rlwinm %r22, %r23, 12, 0, 20 /* extract MAS3 portion of RPN */
+ rlwinm %r22, %r23, 20, 0, 11 /* extract MAS3 portion of RPN */
- rlwimi %r22, %r21, 24, 26, 31 /* insert protection bits from pte */
- rlwinm %r23, %r23, 12, 28, 31 /* MAS7 portion of RPN */
+ rlwimi %r22, %r21, 30, 26, 31 /* insert protection bits from pte */
+ rlwimi %r22, %r21, 20, 12, 19 /* insert lower 8 RPN bits to MAS3 */
+ rlwinm %r23, %r23, 20, 24, 31 /* MAS7 portion of RPN */
/* Load MAS registers. */
mtspr SPR_MAS0, %r29
diff --git a/sys/powerpc/include/pte.h b/sys/powerpc/include/pte.h
index 3a27929..7108072 100644
--- a/sys/powerpc/include/pte.h
+++ b/sys/powerpc/include/pte.h
@@ -212,11 +212,7 @@ typedef struct lpte lpte_t;
* page size is 4k (12-bit mask), so RPN can really fit into 24 bits.
*/
#ifndef LOCORE
-struct pte {
- vm_offset_t rpn;
- uint32_t flags;
-};
-typedef struct pte pte_t;
+typedef uint64_t pte_t;
#endif
/* RPN mask, TLB0 4K pages */
@@ -225,13 +221,14 @@ typedef struct pte pte_t;
#if defined(BOOKE_E500)
/* PTE bits assigned to MAS2, MAS3 flags */
-#define PTE_W MAS2_W
-#define PTE_I MAS2_I
-#define PTE_M MAS2_M
-#define PTE_G MAS2_G
+#define PTE_MAS2_SHIFT 19
+#define PTE_W (MAS2_W << PTE_MAS2_SHIFT)
+#define PTE_I (MAS2_I << PTE_MAS2_SHIFT)
+#define PTE_M (MAS2_M << PTE_MAS2_SHIFT)
+#define PTE_G (MAS2_G << PTE_MAS2_SHIFT)
#define PTE_MAS2_MASK (MAS2_G | MAS2_M | MAS2_I | MAS2_W)
-#define PTE_MAS3_SHIFT 8
+#define PTE_MAS3_SHIFT 2
#define PTE_UX (MAS3_UX << PTE_MAS3_SHIFT)
#define PTE_SX (MAS3_SX << PTE_MAS3_SHIFT)
#define PTE_UW (MAS3_UW << PTE_MAS3_SHIFT)
@@ -241,6 +238,9 @@ typedef struct pte pte_t;
#define PTE_MAS3_MASK ((MAS3_UX | MAS3_SX | MAS3_UW \
| MAS3_SW | MAS3_UR | MAS3_SR) << PTE_MAS3_SHIFT)
+#define PTE_PS_SHIFT 8
+#define PTE_PS_4KB (2 << PTE_PS_SHIFT)
+
#elif defined(BOOKE_PPC4XX)
#define PTE_WL1 TLB_WL1
@@ -262,21 +262,21 @@ typedef struct pte pte_t;
#endif
/* Other PTE flags */
-#define PTE_VALID 0x80000000 /* Valid */
-#define PTE_MODIFIED 0x40000000 /* Modified */
-#define PTE_WIRED 0x20000000 /* Wired */
-#define PTE_MANAGED 0x10000000 /* Managed */
-#define PTE_REFERENCED 0x04000000 /* Referenced */
+#define PTE_VALID 0x00000001 /* Valid */
+#define PTE_MODIFIED 0x00001000 /* Modified */
+#define PTE_WIRED 0x00002000 /* Wired */
+#define PTE_MANAGED 0x00000002 /* Managed */
+#define PTE_REFERENCED 0x00040000 /* Referenced */
/* Macro argument must of pte_t type. */
-#define PTE_PA_SHIFT 12
-#define PTE_RPN_FROM_PA(pa) ((pa) >> PTE_PA_SHIFT)
-#define PTE_PA(pte) ((vm_paddr_t)((pte)->rpn) << PTE_PA_SHIFT)
-#define PTE_ISVALID(pte) ((pte)->flags & PTE_VALID)
-#define PTE_ISWIRED(pte) ((pte)->flags & PTE_WIRED)
-#define PTE_ISMANAGED(pte) ((pte)->flags & PTE_MANAGED)
-#define PTE_ISMODIFIED(pte) ((pte)->flags & PTE_MODIFIED)
-#define PTE_ISREFERENCED(pte) ((pte)->flags & PTE_REFERENCED)
+#define PTE_ARPN_SHIFT 12
+#define PTE_RPN_FROM_PA(pa) (((pa) & ~PAGE_MASK) << PTE_ARPN_SHIFT)
+#define PTE_PA(pte) ((vm_paddr_t)(*pte >> PTE_ARPN_SHIFT) & ~PAGE_MASK)
+#define PTE_ISVALID(pte) ((*pte) & PTE_VALID)
+#define PTE_ISWIRED(pte) ((*pte) & PTE_WIRED)
+#define PTE_ISMANAGED(pte) ((*pte) & PTE_MANAGED)
+#define PTE_ISMODIFIED(pte) ((*pte) & PTE_MODIFIED)
+#define PTE_ISREFERENCED(pte) ((*pte) & PTE_REFERENCED)
#endif /* BOOKE */
#endif /* _MACHINE_PTE_H_ */
diff --git a/sys/powerpc/include/ucontext.h b/sys/powerpc/include/ucontext.h
index 34e391a..42c39e1 100644
--- a/sys/powerpc/include/ucontext.h
+++ b/sys/powerpc/include/ucontext.h
@@ -42,11 +42,11 @@ typedef struct __mcontext {
#define _MC_AV_VALID 0x02
int mc_onstack; /* saved onstack flag */
int mc_len; /* sizeof(__mcontext) */
- uint64_t mc_avec[32*2]; /* vector register file */
- uint32_t mc_av[2];
- register_t mc_frame[42];
- uint64_t mc_fpreg[33];
- uint64_t mc_vsxfpreg[32]; /* low-order half of VSR0-31 */
+ __uint64_t mc_avec[32*2]; /* vector register file */
+ __uint32_t mc_av[2];
+ __register_t mc_frame[42];
+ __uint64_t mc_fpreg[33];
+ __uint64_t mc_vsxfpreg[32]; /* low-order half of VSR0-31 */
} mcontext_t __aligned(16);
#if defined(_KERNEL) && defined(__powerpc64__)
diff --git a/sys/powerpc/powerpc/genassym.c b/sys/powerpc/powerpc/genassym.c
index 1faa0d6..44c0280 100644
--- a/sys/powerpc/powerpc/genassym.c
+++ b/sys/powerpc/powerpc/genassym.c
@@ -119,8 +119,12 @@ ASSYM(USER_SR, USER_SR);
#endif
#elif defined(BOOKE)
ASSYM(PM_PDIR, offsetof(struct pmap, pm_pdir));
-ASSYM(PTE_RPN, offsetof(struct pte, rpn));
-ASSYM(PTE_FLAGS, offsetof(struct pte, flags));
+/*
+ * With pte_t being a bitfield struct, these fields cannot be addressed via
+ * offsetof().
+ */
+ASSYM(PTE_RPN, 0);
+ASSYM(PTE_FLAGS, sizeof(uint32_t));
#if defined(BOOKE_E500)
ASSYM(TLB0_ENTRY_SIZE, sizeof(struct tlb_entry));
#endif
diff --git a/sys/riscv/conf/GENERIC b/sys/riscv/conf/GENERIC
index a32a1f2..2565921 100644
--- a/sys/riscv/conf/GENERIC
+++ b/sys/riscv/conf/GENERIC
@@ -98,7 +98,4 @@ device md # Memory "disks"
device gif # IPv6 and IPv4 tunneling
device firmware # firmware assist module
-# RISCVTODO: This needs to be done via loader (when it's available).
options FDT
-options FDT_DTB_STATIC
-makeoptions FDT_DTS_FILE=spike.dts
diff --git a/sys/riscv/conf/QEMU b/sys/riscv/conf/QEMU
new file mode 100644
index 0000000..f04075a
--- /dev/null
+++ b/sys/riscv/conf/QEMU
@@ -0,0 +1,26 @@
+#
+# Kernel configuration file for QEMU emulator.
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
+
+include GENERIC
+ident QEMU
+
+# RISCVTODO: This needs to be done via loader (when it's available).
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=qemu.dts
diff --git a/sys/riscv/conf/SPIKE b/sys/riscv/conf/SPIKE
new file mode 100644
index 0000000..583d5a9
--- /dev/null
+++ b/sys/riscv/conf/SPIKE
@@ -0,0 +1,26 @@
+#
+# Kernel configuration file for UCB Spike simulator.
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
+
+include GENERIC
+ident SPIKE
+
+# RISCVTODO: This needs to be done via loader (when it's available).
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=spike.dts
diff --git a/sys/riscv/htif/htif.c b/sys/riscv/htif/htif.c
index 08e6a43..f8143dc 100644
--- a/sys/riscv/htif/htif.c
+++ b/sys/riscv/htif/htif.c
@@ -183,9 +183,8 @@ htif_enumerate(struct htif_softc *sc)
}
len = strnlen(id, sizeof(id));
- if (len <= 0) {
- continue;
- }
+ if (len <= 0)
+ break;
if (bootverbose)
printf(" %d %s\n", i, id);
diff --git a/sys/riscv/include/ucontext.h b/sys/riscv/include/ucontext.h
index 4fbf346..20b593c 100644
--- a/sys/riscv/include/ucontext.h
+++ b/sys/riscv/include/ucontext.h
@@ -50,7 +50,7 @@ struct gpregs {
};
struct fpregs {
- __uint128_t fp_x[32];
+ __uint64_t fp_x[64] __aligned(16);
__uint64_t fp_fcsr;
int fp_flags;
int pad;
diff --git a/sys/sparc64/include/ucontext.h b/sys/sparc64/include/ucontext.h
index 1c907fe..42deca8 100644
--- a/sys/sparc64/include/ucontext.h
+++ b/sys/sparc64/include/ucontext.h
@@ -33,11 +33,11 @@
#define _MACHINE_UCONTEXT_H_
struct __mcontext {
- uint64_t mc_global[8];
- uint64_t mc_out[8];
- uint64_t mc_local[8];
- uint64_t mc_in[8];
- uint32_t mc_fp[64];
+ __uint64_t mc_global[8];
+ __uint64_t mc_out[8];
+ __uint64_t mc_local[8];
+ __uint64_t mc_in[8];
+ __uint32_t mc_fp[64];
} __aligned(64);
typedef struct __mcontext mcontext_t;
diff --git a/sys/sys/_ucontext.h b/sys/sys/_ucontext.h
new file mode 100644
index 0000000..17b3179
--- /dev/null
+++ b/sys/sys/_ucontext.h
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 1999 Marcel Moolenaar
+ * 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
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS__UCONTEXT_H_
+#define _SYS__UCONTEXT_H_
+
+typedef struct __ucontext {
+ /*
+ * Keep the order of the first two fields. Also,
+ * keep them the first two fields in the structure.
+ * This way we can have a union with struct
+ * sigcontext and ucontext_t. This allows us to
+ * support them both at the same time.
+ * note: the union is not defined, though.
+ */
+ __sigset_t uc_sigmask;
+ mcontext_t uc_mcontext;
+
+ struct __ucontext *uc_link;
+ struct __stack_t uc_stack;
+ int uc_flags;
+ int __spare__[4];
+} ucontext_t;
+
+#endif /* _SYS__UCONTEXT_H */
diff --git a/sys/sys/intr.h b/sys/sys/intr.h
new file mode 100644
index 0000000..27310a4
--- /dev/null
+++ b/sys/sys/intr.h
@@ -0,0 +1,130 @@
+/* $NetBSD: intr.h,v 1.7 2003/06/16 20:01:00 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1997 Mark Brinicombe.
+ * 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. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the company nor the name of the author may 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 OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ *
+ */
+
+#ifndef _SYS_INTR_H_
+#define _SYS_INTR_H_
+
+#ifdef notyet
+#define INTR_SOLO INTR_MD1
+typedef int intr_irq_filter_t(void *arg, struct trapframe *tf);
+#else
+typedef int intr_irq_filter_t(void *arg);
+#endif
+
+#define INTR_ISRC_NAMELEN (MAXCOMLEN + 1)
+
+typedef void intr_ipi_filter_t(void *arg);
+
+enum intr_isrc_type {
+ INTR_ISRCT_NAMESPACE,
+ INTR_ISRCT_FDT
+};
+
+#define INTR_ISRCF_REGISTERED 0x01 /* registered in a controller */
+#define INTR_ISRCF_PERCPU 0x02 /* per CPU interrupt */
+#define INTR_ISRCF_BOUND 0x04 /* bound to a CPU */
+
+/* Interrupt source definition. */
+struct intr_irqsrc {
+ device_t isrc_dev; /* where isrc is mapped */
+ intptr_t isrc_xref; /* device reference key */
+ uintptr_t isrc_data; /* device data for isrc */
+ u_int isrc_irq; /* unique identificator */
+ enum intr_isrc_type isrc_type; /* how is isrc decribed */
+ u_int isrc_flags;
+ char isrc_name[INTR_ISRC_NAMELEN];
+ uint16_t isrc_nspc_type;
+ uint16_t isrc_nspc_num;
+ enum intr_trigger isrc_trig;
+ enum intr_polarity isrc_pol;
+ cpuset_t isrc_cpu; /* on which CPUs is enabled */
+ u_int isrc_index;
+ u_long * isrc_count;
+ u_int isrc_handlers;
+ struct intr_event * isrc_event;
+ intr_irq_filter_t * isrc_filter;
+ intr_ipi_filter_t * isrc_ipifilter;
+ void * isrc_arg;
+#ifdef FDT
+ u_int isrc_ncells;
+ pcell_t isrc_cells[]; /* leave it last */
+#endif
+};
+
+void intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...)
+ __printflike(2, 3);
+
+void intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf);
+
+#define INTR_IRQ_NSPC_NONE 0
+#define INTR_IRQ_NSPC_PLAIN 1
+#define INTR_IRQ_NSPC_IRQ 2
+#define INTR_IRQ_NSPC_IPI 3
+
+u_int intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num);
+#ifdef FDT
+u_int intr_fdt_map_irq(phandle_t, pcell_t *, u_int);
+#endif
+
+int intr_pic_register(device_t dev, intptr_t xref);
+int intr_pic_unregister(device_t dev, intptr_t xref);
+int intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
+ void *arg, u_int ipicount);
+
+int intr_irq_add_handler(device_t dev, driver_filter_t, driver_intr_t, void *,
+ u_int, int, void **);
+int intr_irq_remove_handler(device_t dev, u_int, void *);
+int intr_irq_config(u_int, enum intr_trigger, enum intr_polarity);
+int intr_irq_describe(u_int, void *, const char *);
+
+u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask);
+
+#ifdef SMP
+int intr_irq_bind(u_int, int);
+
+void intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf);
+
+#define AISHF_NOALLOC 0x0001
+
+int intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter,
+ void *arg, u_int flags);
+
+void intr_pic_init_secondary(void);
+
+#endif
+#endif /* _SYS_INTR_H */
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index 91dd895..133dfaa 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -528,7 +528,50 @@ extern uma_zone_t zone_ext_refcnt;
void mb_dupcl(struct mbuf *, const struct mbuf *);
void mb_free_ext(struct mbuf *);
+void m_adj(struct mbuf *, int);
+int m_apply(struct mbuf *, int, int,
+ int (*)(void *, void *, u_int), void *);
+int m_append(struct mbuf *, int, c_caddr_t);
+void m_cat(struct mbuf *, struct mbuf *);
+void m_catpkt(struct mbuf *, struct mbuf *);
+int m_clget(struct mbuf *m, int how);
+void *m_cljget(struct mbuf *m, int how, int size);
+struct mbuf *m_collapse(struct mbuf *, int, int);
+void m_copyback(struct mbuf *, int, int, c_caddr_t);
+void m_copydata(const struct mbuf *, int, int, caddr_t);
+struct mbuf *m_copym(const struct mbuf *, int, int, int);
+struct mbuf *m_copypacket(struct mbuf *, int);
+void m_copy_pkthdr(struct mbuf *, struct mbuf *);
+struct mbuf *m_copyup(struct mbuf *, int, int);
+struct mbuf *m_defrag(struct mbuf *, int);
+void m_demote_pkthdr(struct mbuf *);
+void m_demote(struct mbuf *, int, int);
+struct mbuf *m_devget(char *, int, int, struct ifnet *,
+ void (*)(char *, caddr_t, u_int));
+struct mbuf *m_dup(const struct mbuf *, int);
+int m_dup_pkthdr(struct mbuf *, const struct mbuf *, int);
+int m_extadd(struct mbuf *, caddr_t, u_int,
+ void (*)(struct mbuf *, void *, void *), void *, void *,
+ int, int, int);
+u_int m_fixhdr(struct mbuf *);
+struct mbuf *m_fragment(struct mbuf *, int, int);
+void m_freem(struct mbuf *);
+struct mbuf *m_get2(int, int, short, int);
+struct mbuf *m_getjcl(int, short, int, int);
+struct mbuf *m_getm2(struct mbuf *, int, int, short, int);
+struct mbuf *m_getptr(struct mbuf *, int, int *);
+u_int m_length(struct mbuf *, struct mbuf **);
+int m_mbuftouio(struct uio *, struct mbuf *, int);
+void m_move_pkthdr(struct mbuf *, struct mbuf *);
int m_pkthdr_init(struct mbuf *, int);
+struct mbuf *m_prepend(struct mbuf *, int, int);
+void m_print(const struct mbuf *, int);
+struct mbuf *m_pulldown(struct mbuf *, int, int, int *);
+struct mbuf *m_pullup(struct mbuf *, int);
+int m_sanity(struct mbuf *, int);
+struct mbuf *m_split(struct mbuf *, int, int);
+struct mbuf *m_uiotombuf(struct uio *, int, int, int, int);
+struct mbuf *m_unshare(struct mbuf *, int);
static __inline int
m_gettype(int size)
@@ -618,8 +661,7 @@ m_getzone(int size)
* should go away with constant propagation for !MGETHDR.
*/
static __inline int
-m_init(struct mbuf *m, uma_zone_t zone __unused, int size __unused, int how,
- short type, int flags)
+m_init(struct mbuf *m, int how, short type, int flags)
{
int error;
@@ -647,23 +689,6 @@ m_get(int how, short type)
return (uma_zalloc_arg(zone_mbuf, &args, how));
}
-/*
- * XXX This should be deprecated, very little use.
- */
-static __inline struct mbuf *
-m_getclr(int how, short type)
-{
- struct mbuf *m;
- struct mb_args args;
-
- args.flags = 0;
- args.type = type;
- m = uma_zalloc_arg(zone_mbuf, &args, how);
- if (m != NULL)
- bzero(m->m_data, MLEN);
- return (m);
-}
-
static __inline struct mbuf *
m_gethdr(int how, short type)
{
@@ -684,47 +709,6 @@ m_getcl(int how, short type, int flags)
return (uma_zalloc_arg(zone_pack, &args, how));
}
-static __inline int
-m_clget(struct mbuf *m, int how)
-{
-
- KASSERT((m->m_flags & M_EXT) == 0, ("%s: mbuf %p has M_EXT",
- __func__, m));
- m->m_ext.ext_buf = (char *)NULL;
- uma_zalloc_arg(zone_clust, m, how);
- /*
- * On a cluster allocation failure, drain the packet zone and retry,
- * we might be able to loosen a few clusters up on the drain.
- */
- if ((how & M_NOWAIT) && (m->m_ext.ext_buf == NULL)) {
- zone_drain(zone_pack);
- uma_zalloc_arg(zone_clust, m, how);
- }
- return (m->m_flags & M_EXT);
-}
-
-/*
- * m_cljget() is different from m_clget() as it can allocate clusters without
- * attaching them to an mbuf. In that case the return value is the pointer
- * to the cluster of the requested size. If an mbuf was specified, it gets
- * the cluster attached to it and the return value can be safely ignored.
- * For size it takes MCLBYTES, MJUMPAGESIZE, MJUM9BYTES, MJUM16BYTES.
- */
-static __inline void *
-m_cljget(struct mbuf *m, int how, int size)
-{
- uma_zone_t zone;
-
- if (m != NULL) {
- KASSERT((m->m_flags & M_EXT) == 0, ("%s: mbuf %p has M_EXT",
- __func__, m));
- m->m_ext.ext_buf = NULL;
- }
-
- zone = m_getzone(size);
- return (uma_zalloc_arg(zone, m, how));
-}
-
static __inline void
m_cljset(struct mbuf *m, void *cl, int type)
{
@@ -942,50 +926,6 @@ extern int max_linkhdr; /* Largest link-level header */
extern int max_protohdr; /* Largest protocol header */
extern int nmbclusters; /* Maximum number of clusters */
-struct uio;
-
-void m_adj(struct mbuf *, int);
-int m_apply(struct mbuf *, int, int,
- int (*)(void *, void *, u_int), void *);
-int m_append(struct mbuf *, int, c_caddr_t);
-void m_cat(struct mbuf *, struct mbuf *);
-void m_catpkt(struct mbuf *, struct mbuf *);
-int m_extadd(struct mbuf *, caddr_t, u_int,
- void (*)(struct mbuf *, void *, void *), void *, void *,
- int, int, int);
-struct mbuf *m_collapse(struct mbuf *, int, int);
-void m_copyback(struct mbuf *, int, int, c_caddr_t);
-void m_copydata(const struct mbuf *, int, int, caddr_t);
-struct mbuf *m_copym(const struct mbuf *, int, int, int);
-struct mbuf *m_copypacket(struct mbuf *, int);
-void m_copy_pkthdr(struct mbuf *, struct mbuf *);
-struct mbuf *m_copyup(struct mbuf *, int, int);
-struct mbuf *m_defrag(struct mbuf *, int);
-void m_demote_pkthdr(struct mbuf *);
-void m_demote(struct mbuf *, int, int);
-struct mbuf *m_devget(char *, int, int, struct ifnet *,
- void (*)(char *, caddr_t, u_int));
-struct mbuf *m_dup(const struct mbuf *, int);
-int m_dup_pkthdr(struct mbuf *, const struct mbuf *, int);
-u_int m_fixhdr(struct mbuf *);
-struct mbuf *m_fragment(struct mbuf *, int, int);
-void m_freem(struct mbuf *);
-struct mbuf *m_get2(int, int, short, int);
-struct mbuf *m_getjcl(int, short, int, int);
-struct mbuf *m_getm2(struct mbuf *, int, int, short, int);
-struct mbuf *m_getptr(struct mbuf *, int, int *);
-u_int m_length(struct mbuf *, struct mbuf **);
-int m_mbuftouio(struct uio *, struct mbuf *, int);
-void m_move_pkthdr(struct mbuf *, struct mbuf *);
-struct mbuf *m_prepend(struct mbuf *, int, int);
-void m_print(const struct mbuf *, int);
-struct mbuf *m_pulldown(struct mbuf *, int, int, int *);
-struct mbuf *m_pullup(struct mbuf *, int);
-int m_sanity(struct mbuf *, int);
-struct mbuf *m_split(struct mbuf *, int, int);
-struct mbuf *m_uiotombuf(struct uio *, int, int, int, int);
-struct mbuf *m_unshare(struct mbuf *, int);
-
/*-
* Network packets may have annotations attached by affixing a list of
* "packet tags" to the pkthdr structure. Packet tags are dynamically
diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h
index 4561ec6..e559b76 100644
--- a/sys/sys/pmc.h
+++ b/sys/sys/pmc.h
@@ -1033,7 +1033,7 @@ extern struct pmc_debugflags pmc_debugflags;
#define KTR_PMC KTR_SUBSYS
#define PMC_DEBUG_STRSIZE 128
-#define PMC_DEBUG_DEFAULT_FLAGS { 0, 0, 0, 0, 0, 0, 0, 0 }
+#define PMC_DEBUG_DEFAULT_FLAGS { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
#define PMCDBG0(M, N, L, F) do { \
if (pmc_debugflags.pdb_ ## M & (1 << PMC_DEBUG_MIN_ ## N)) \
diff --git a/sys/sys/signal.h b/sys/sys/signal.h
index 259c39a..ab8fcf4 100644
--- a/sys/sys/signal.h
+++ b/sys/sys/signal.h
@@ -354,18 +354,10 @@ typedef void __siginfohandler_t(int, struct __siginfo *, void *);
#endif
#if __XSI_VISIBLE
-/*
- * Structure used in sigaltstack call.
- */
#if __BSD_VISIBLE
-typedef struct sigaltstack {
-#else
-typedef struct {
+#define __stack_t sigaltstack
#endif
- void *ss_sp; /* signal stack base */
- __size_t ss_size; /* signal stack length */
- int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */
-} stack_t;
+typedef struct __stack_t stack_t;
#define SS_ONSTACK 0x0001 /* take signal on alternate stack */
#define SS_DISABLE 0x0004 /* disable taking signals on alternate stack */
@@ -373,6 +365,17 @@ typedef struct {
#define SIGSTKSZ (MINSIGSTKSZ + 32768) /* recommended stack size */
#endif
+/*
+ * Structure used in sigaltstack call. Its definition is always
+ * needed for __ucontext. If __BSD_VISIBLE is defined, the structure
+ * tag is actually sigaltstack.
+ */
+struct __stack_t {
+ void *ss_sp; /* signal stack base */
+ __size_t ss_size; /* signal stack length */
+ int ss_flags; /* SS_DISABLE and/or SS_ONSTACK */
+};
+
#if __BSD_VISIBLE
/*
* 4.3 compatibility:
diff --git a/sys/sys/ucontext.h b/sys/sys/ucontext.h
index e80ed50..260c157 100644
--- a/sys/sys/ucontext.h
+++ b/sys/sys/ucontext.h
@@ -33,25 +33,9 @@
#include <sys/signal.h>
#include <machine/ucontext.h>
+#include <sys/_ucontext.h>
-typedef struct __ucontext {
- /*
- * Keep the order of the first two fields. Also,
- * keep them the first two fields in the structure.
- * This way we can have a union with struct
- * sigcontext and ucontext_t. This allows us to
- * support them both at the same time.
- * note: the union is not defined, though.
- */
- sigset_t uc_sigmask;
- mcontext_t uc_mcontext;
-
- struct __ucontext *uc_link;
- stack_t uc_stack;
- int uc_flags;
#define UCF_SWAPPED 0x00000001 /* Used by swapcontext(3). */
- int __spare__[4];
-} ucontext_t;
#if defined(_KERNEL) && defined(COMPAT_FREEBSD4)
#if defined(__i386__)
diff --git a/sys/x86/include/ucontext.h b/sys/x86/include/ucontext.h
index 2173efd..c429fd5 100644
--- a/sys/x86/include/ucontext.h
+++ b/sys/x86/include/ucontext.h
@@ -162,4 +162,9 @@ typedef struct __mcontext {
} mcontext_t;
#endif /* __amd64__ */
+#ifdef __LINT__
+typedef struct __mcontext {
+} mcontext_t;
+#endif /* __LINT__ */
+
#endif /* !_X86_UCONTEXT_H_ */
diff --git a/tests/sys/geom/class/gate/3_test.sh b/tests/sys/geom/class/gate/3_test.sh
index 8901aca..3511df7 100644
--- a/tests/sys/geom/class/gate/3_test.sh
+++ b/tests/sys/geom/class/gate/3_test.sh
@@ -27,6 +27,7 @@ if ! ggatel create -u $us /dev/$work; then
exit 1
fi
+sleep 1
dd if=/dev/${src} of=/dev/ggate${us} bs=1m count=1 conv=sync
sleep 1
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index 37f624e..87a40ba 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -7970,7 +7970,6 @@ OLD_FILES+=usr/sbin/unbound
OLD_FILES+=usr/sbin/unbound-anchor
OLD_FILES+=usr/sbin/unbound-checkconf
OLD_FILES+=usr/sbin/unbound-control
-OLD_FILES+=usr/sbin/unbound-control-setup
OLD_FILES+=usr/share/man/man5/unbound.conf.5.gz
OLD_FILES+=usr/share/man/man8/unbound-anchor.8.gz
OLD_FILES+=usr/share/man/man8/unbound-checkconf.8.gz
diff --git a/tools/build/options/WITHOUT_BINUTILS_BOOTSTRAP b/tools/build/options/WITHOUT_BINUTILS_BOOTSTRAP
index 84ae1a17..c64c469 100644
--- a/tools/build/options/WITHOUT_BINUTILS_BOOTSTRAP
+++ b/tools/build/options/WITHOUT_BINUTILS_BOOTSTRAP
@@ -1,6 +1,5 @@
.\" $FreeBSD$
-Set to not build binutils (as, c++-filt, gconv,
-ld, nm, objcopy, objdump, readelf, size and strip)
+Set to not build binutils (as, ld, objcopy and objdump)
as part of the bootstrap process.
.Bf -symbolic
The option does not work for build targets unless some alternative
diff --git a/tools/build/options/WITHOUT_ELFTOOLCHAIN_BOOTSTRAP b/tools/build/options/WITHOUT_ELFTOOLCHAIN_BOOTSTRAP
new file mode 100644
index 0000000..85fa01e
--- /dev/null
+++ b/tools/build/options/WITHOUT_ELFTOOLCHAIN_BOOTSTRAP
@@ -0,0 +1,7 @@
+.\" $FreeBSD$
+Set to not build ELF Tool Chain tools
+(addr2line, nm, size, strings and strip)
+as part of the bootstrap process.
+.Bf -symbolic
+An alternate bootstrap tool chain must be provided.
+.Ef
diff --git a/tools/build/options/WITH_BINUTILS b/tools/build/options/WITH_BINUTILS
new file mode 100644
index 0000000..619dc21
--- /dev/null
+++ b/tools/build/options/WITH_BINUTILS
@@ -0,0 +1,3 @@
+.\" $FreeBSD$
+Set to build and install binutils (as, ld, objcopy, and objdump) as part
+of the normal system build.
diff --git a/tools/build/options/WITH_BINUTILS_BOOTSTRAP b/tools/build/options/WITH_BINUTILS_BOOTSTRAP
new file mode 100644
index 0000000..f32cb06
--- /dev/null
+++ b/tools/build/options/WITH_BINUTILS_BOOTSTRAP
@@ -0,0 +1,3 @@
+.\" $FreeBSD$
+Set build binutils (as, ld, objcopy and objdump)
+as part of the bootstrap process.
diff --git a/tools/build/options/WITH_GDB b/tools/build/options/WITH_GDB
new file mode 100644
index 0000000..994942e
--- /dev/null
+++ b/tools/build/options/WITH_GDB
@@ -0,0 +1,3 @@
+.\" $FreeBSD$
+Set to build
+.Xr gdb 1 .
diff --git a/usr.bin/elfcopy/Makefile b/usr.bin/elfcopy/Makefile
index dc6dd47..0800a0c 100644
--- a/usr.bin/elfcopy/Makefile
+++ b/usr.bin/elfcopy/Makefile
@@ -17,13 +17,14 @@ CLEANFILES+= objcopy.1
PROG= elfcopy
.endif
-SRCS= archive.c ascii.c binary.c main.c sections.c segments.c symbols.c
+SRCS= archive.c ascii.c binary.c main.c pe.c sections.c segments.c symbols.c
WARNS?= 5
-LIBADD= archive elftc elf
+LIBADD= archive elftc elf pe
-CFLAGS+=-I${ELFTCDIR}/libelftc -I${ELFTCDIR}/common
+CFLAGS+=-I${ELFTCDIR}/libelftc -I${ELFTCDIR}/libpe -I${ELFTCDIR}/common
+CFLAGS+=-DWITH_PE=1
MAN= ${PROG}.1 strip.1
diff --git a/usr.bin/hexdump/display.c b/usr.bin/hexdump/display.c
index 4ff3308..36230aa 100644
--- a/usr.bin/hexdump/display.c
+++ b/usr.bin/hexdump/display.c
@@ -374,7 +374,7 @@ doskip(const char *fname, int statok)
if (statok) {
if (fstat(fileno(stdin), &sb))
err(1, "%s", fname);
- if (S_ISREG(sb.st_mode) && skip >= sb.st_size) {
+ if (S_ISREG(sb.st_mode) && skip > sb.st_size) {
address += sb.st_size;
skip -= sb.st_size;
return;
diff --git a/usr.bin/truss/amd64-linux32.c b/usr.bin/truss/amd64-linux32.c
index 2ede617..873ef01 100644
--- a/usr.bin/truss/amd64-linux32.c
+++ b/usr.bin/truss/amd64-linux32.c
@@ -115,6 +115,8 @@ amd64_linux32_fetch_retval(struct trussinfo *trussinfo, long *retval,
retval[0] = regs.r_rax & 0xffffffff;
retval[1] = regs.r_rdx & 0xffffffff;
*errorp = !!(regs.r_rflags & PSL_C);
+ if (*errorp)
+ retval[0] = (int)retval[0];
if (*errorp) {
for (i = 0; i < nitems(bsd_to_linux_errno); i++) {
diff --git a/usr.bin/truss/i386-linux.c b/usr.bin/truss/i386-linux.c
index fbc54a0..c5f625d 100644
--- a/usr.bin/truss/i386-linux.c
+++ b/usr.bin/truss/i386-linux.c
@@ -129,7 +129,7 @@ i386_linux_fetch_retval(struct trussinfo *trussinfo, long *retval, int *errorp)
}
static struct procabi i386_linux = {
- "Linux ELF32",
+ "Linux ELF",
SYSDECODE_ABI_LINUX,
i386_linux_fetch_args,
i386_linux_fetch_retval
diff --git a/usr.sbin/ctld/login.c b/usr.sbin/ctld/login.c
index 72c23ce..3710dbc 100644
--- a/usr.sbin/ctld/login.c
+++ b/usr.sbin/ctld/login.c
@@ -126,15 +126,16 @@ login_receive(struct connection *conn, bool initial)
log_errx(1, "received Login PDU with unsupported "
"Version-min 0x%x", bhslr->bhslr_version_min);
}
- if (ISCSI_SNLT(ntohl(bhslr->bhslr_cmdsn), conn->conn_cmdsn)) {
- login_send_error(request, 0x02, 0x05);
+ if (initial == false &&
+ ISCSI_SNLT(ntohl(bhslr->bhslr_cmdsn), conn->conn_cmdsn)) {
+ login_send_error(request, 0x02, 0x00);
log_errx(1, "received Login PDU with decreasing CmdSN: "
"was %u, is %u", conn->conn_cmdsn,
ntohl(bhslr->bhslr_cmdsn));
}
if (initial == false &&
ntohl(bhslr->bhslr_expstatsn) != conn->conn_statsn) {
- login_send_error(request, 0x02, 0x05);
+ login_send_error(request, 0x02, 0x00);
log_errx(1, "received Login PDU with wrong ExpStatSN: "
"is %u, should be %u", ntohl(bhslr->bhslr_expstatsn),
conn->conn_statsn);
diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8
index c9b79c4..362e5b2 100644
--- a/usr.sbin/jail/jail.8
+++ b/usr.sbin/jail/jail.8
@@ -1260,7 +1260,6 @@ The configuration file was introduced in
The jail feature was written by
.An Poul-Henning Kamp
for R&D Associates
-.Pa http://www.rndassociates.com/
who contributed it to
.Fx .
.Pp
diff --git a/usr.sbin/jail/jail.conf.5 b/usr.sbin/jail/jail.conf.5
index d83bf61..0241a06 100644
--- a/usr.sbin/jail/jail.conf.5
+++ b/usr.sbin/jail/jail.conf.5
@@ -224,7 +224,6 @@ file was added in
The jail feature was written by
.An Poul-Henning Kamp
for R&D Associates
-.Pa http://www.rndassociates.com/
who contributed it to
.Fx .
.Pp
diff --git a/usr.sbin/services_mkdb/services_mkdb.c b/usr.sbin/services_mkdb/services_mkdb.c
index 9ea66de..c928ea9 100644
--- a/usr.sbin/services_mkdb/services_mkdb.c
+++ b/usr.sbin/services_mkdb/services_mkdb.c
@@ -141,7 +141,7 @@ main(int argc, char *argv[])
err(1, "Cannot install exit handler");
(void)snprintf(tname, sizeof(tname), "%s.tmp", dbname);
- db = dbopen(tname, O_RDWR | O_CREAT | O_EXCL | O_SYNC,
+ db = dbopen(tname, O_RDWR | O_CREAT | O_EXCL,
(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), DB_HASH, &hinfo);
if (!db)
err(1, "Error opening temporary database `%s'", tname);
diff --git a/usr.sbin/unbound/control/Makefile b/usr.sbin/unbound/control/Makefile
index 1614127..824e441 100644
--- a/usr.sbin/unbound/control/Makefile
+++ b/usr.sbin/unbound/control/Makefile
@@ -7,7 +7,6 @@ UNBOUNDDIR= ${.CURDIR}/../../../contrib/unbound
.PATH: ${UNBOUNDDIR} ${UNBOUNDDIR}/smallapp ${UNBOUNDDIR}/doc
PROG= unbound-control
-SCRIPTS= unbound-control-setup.sh
SRCS= unbound-control.c worker_cb.c
CFLAGS= -I${UNBOUNDDIR} -I${LDNSDIR}
LIBADD= unbound crypto ssl pthread
diff --git a/usr.sbin/unbound/local-setup/local-unbound-setup.sh b/usr.sbin/unbound/local-setup/local-unbound-setup.sh
index 5df4760..cd21f6f 100755
--- a/usr.sbin/unbound/local-setup/local-unbound-setup.sh
+++ b/usr.sbin/unbound/local-setup/local-unbound-setup.sh
@@ -210,31 +210,7 @@ gen_lanzones_conf() {
echo "server:"
echo " # Unblock reverse lookups for LAN addresses"
echo " unblock-lan-zones: yes"
- echo " domain-insecure: 10.in-addr.arpa."
- echo " domain-insecure: 127.in-addr.arpa."
- echo " domain-insecure: 16.172.in-addr.arpa."
- echo " domain-insecure: 17.172.in-addr.arpa."
- echo " domain-insecure: 18.172.in-addr.arpa."
- echo " domain-insecure: 19.172.in-addr.arpa."
- echo " domain-insecure: 20.172.in-addr.arpa."
- echo " domain-insecure: 21.172.in-addr.arpa."
- echo " domain-insecure: 22.172.in-addr.arpa."
- echo " domain-insecure: 23.172.in-addr.arpa."
- echo " domain-insecure: 24.172.in-addr.arpa."
- echo " domain-insecure: 25.172.in-addr.arpa."
- echo " domain-insecure: 26.172.in-addr.arpa."
- echo " domain-insecure: 27.172.in-addr.arpa."
- echo " domain-insecure: 28.172.in-addr.arpa."
- echo " domain-insecure: 29.172.in-addr.arpa."
- echo " domain-insecure: 30.172.in-addr.arpa."
- echo " domain-insecure: 31.172.in-addr.arpa."
- echo " domain-insecure: 168.192.in-addr.arpa."
- echo " domain-insecure: 254.169.in-addr.arpa."
- echo " domain-insecure: d.f.ip6.arpa."
- echo " domain-insecure: 8.e.ip6.arpa."
- echo " domain-insecure: 9.e.ip6.arpa."
- echo " domain-insecure: a.e.ip6.arpa."
- echo " domain-insecure: b.e.ip6.arpa."
+ echo " insecure-lan-zones: yes"
}
#
OpenPOWER on IntegriCloud