summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ObsoleteFiles.inc2
-rw-r--r--UPDATING33
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.motoofew.d2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.motoomany.d2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.mtatoofew.d2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.mtatoomany.d2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.mutex_owner.d2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.mutex_type_adaptive.d2
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl2
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv6remote.pl2
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localtcp.ksh17
-rwxr-xr-xcddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotetcp.ksh2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localtcpstate.ksh2
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotetcpstate.ksh2
-rw-r--r--cddl/contrib/opensolaris/cmd/zfs/zfs.86
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c22
-rw-r--r--cddl/lib/libdtrace/io.d3
-rw-r--r--cddl/lib/libdtrace/ip.d1
-rw-r--r--cddl/lib/libdtrace/nfs.d1
-rw-r--r--cddl/lib/libdtrace/nfssrv.d3
-rw-r--r--cddl/lib/libdtrace/psinfo.d2
-rw-r--r--cddl/lib/libdtrace/regs_x86.d2
-rw-r--r--cddl/lib/libdtrace/sched.d4
-rw-r--r--cddl/lib/libdtrace/siftr.d1
-rw-r--r--cddl/lib/libdtrace/tcp.d1
-rw-r--r--cddl/lib/libdtrace/udp.d1
-rw-r--r--cddl/usr.sbin/dtrace/Makefile6
-rw-r--r--contrib/bsnmp/snmp_mibII/mibII_ip.c2
-rw-r--r--contrib/elftoolchain/ar/Makefile35
-rw-r--r--contrib/elftoolchain/ar/acplex.l83
-rw-r--r--contrib/elftoolchain/ar/acpyacc.y658
-rw-r--r--contrib/elftoolchain/ar/ar.1603
-rw-r--r--contrib/elftoolchain/ar/ar.5327
-rw-r--r--contrib/elftoolchain/ar/ar.c433
-rw-r--r--contrib/elftoolchain/ar/ar.h143
-rwxr-xr-xcontrib/elftoolchain/ar/benchmark/acp.sh65
-rw-r--r--contrib/elftoolchain/ar/os.Linux.mk9
-rw-r--r--contrib/elftoolchain/ar/ranlib.186
-rw-r--r--contrib/elftoolchain/ar/read.c199
-rw-r--r--contrib/elftoolchain/ar/util.c184
-rw-r--r--contrib/elftoolchain/ar/write.c975
-rw-r--r--contrib/elftoolchain/brandelf/Makefile9
-rw-r--r--contrib/elftoolchain/brandelf/brandelf.1151
-rw-r--r--contrib/elftoolchain/brandelf/brandelf.c311
-rw-r--r--contrib/elftoolchain/elfdump/Makefile11
-rw-r--r--contrib/elftoolchain/elfdump/elfdump.1158
-rw-r--r--contrib/elftoolchain/elfdump/elfdump.c2819
-rw-r--r--contrib/gcc/c-cppbuiltin.c4
-rw-r--r--contrib/gcc/cfgexpand.c82
-rw-r--r--contrib/gcc/common.opt4
-rw-r--r--contrib/gcc/doc/cpp.texi4
-rw-r--r--contrib/gcc/doc/gcc.17
-rw-r--r--contrib/gcc/doc/invoke.texi7
-rw-r--r--contrib/gcc/gcc.c2
-rw-r--r--contrib/libarchive/libarchive/archive_read_support_format_tar.c16
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_gtar_sparse_skip_entry.c135
-rw-r--r--contrib/libarchive/libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu15
-rw-r--r--contrib/llvm/tools/lldb/docs/lldb.12
-rw-r--r--contrib/sendmail/FREEBSD-upgrade1
-rw-r--r--crypto/openssh/auth2-chall.c9
-rw-r--r--crypto/openssh/sshconnect.c42
-rw-r--r--etc/defaults/rc.conf2
-rw-r--r--etc/network.subr67
-rw-r--r--etc/portsnap.conf2
-rwxr-xr-xetc/rc.d/netif12
-rwxr-xr-xetc/rc.d/rctl1
-rw-r--r--etc/rc.subr10
-rw-r--r--gnu/usr.bin/binutils/Makefile17
-rw-r--r--gnu/usr.bin/binutils/addr2line/Makefile17
-rw-r--r--gnu/usr.bin/binutils/addr2line/Makefile.depend21
-rw-r--r--gnu/usr.bin/binutils/addr2line/addr2line.1266
-rw-r--r--gnu/usr.bin/binutils/ar/Makefile.depend21
-rw-r--r--gnu/usr.bin/binutils/nm/Makefile18
-rw-r--r--gnu/usr.bin/binutils/nm/Makefile.depend21
-rw-r--r--gnu/usr.bin/binutils/nm/nm.1450
-rw-r--r--gnu/usr.bin/binutils/ranlib/Makefile.depend21
-rw-r--r--gnu/usr.bin/binutils/readelf/Makefile20
-rw-r--r--gnu/usr.bin/binutils/readelf/Makefile.depend21
-rw-r--r--gnu/usr.bin/binutils/readelf/readelf.1377
-rw-r--r--gnu/usr.bin/binutils/size/Makefile17
-rw-r--r--gnu/usr.bin/binutils/size/Makefile.depend21
-rw-r--r--gnu/usr.bin/binutils/size/size.1263
-rw-r--r--gnu/usr.bin/binutils/strings/Makefile17
-rw-r--r--gnu/usr.bin/binutils/strings/Makefile.depend21
-rw-r--r--gnu/usr.bin/binutils/strings/strings.1254
-rw-r--r--gnu/usr.bin/binutils/strip/Makefile18
-rw-r--r--gnu/usr.bin/binutils/strip/Makefile.depend21
-rw-r--r--gnu/usr.bin/binutils/strip/strip.1392
-rw-r--r--gnu/usr.bin/cc/Makefile3
-rw-r--r--gnu/usr.bin/cc/c++filt/Makefile19
-rw-r--r--gnu/usr.bin/cc/c++filt/Makefile.depend23
-rw-r--r--lib/libarchive/test/Makefile1
-rw-r--r--lib/libc/amd64/sys/__vdso_gettc.c16
-rw-r--r--lib/libc/i386/sys/__vdso_gettc.c58
-rw-r--r--lib/libc/stdio/open_memstream.36
-rw-r--r--lib/libc/sys/__vdso_gettimeofday.c25
-rw-r--r--lib/libc/sys/kqueue.210
-rw-r--r--lib/libc/sys/unlink.25
-rw-r--r--lib/libthr/arch/amd64/Makefile.inc6
-rw-r--r--lib/libthr/arch/i386/Makefile.inc6
-rw-r--r--libexec/rtld-elf/amd64/Makefile.inc2
-rw-r--r--libexec/rtld-elf/i386/Makefile.inc2
-rw-r--r--libexec/ypxfr/ypxfr_getmap.c4
-rw-r--r--libexec/ypxfr/ypxfr_main.c12
-rw-r--r--libexec/ypxfr/ypxfrd_getmap.c2
-rw-r--r--release/doc/en_US.ISO8859-1/relnotes/article.xml4
-rw-r--r--release/tools/ec2.conf5
-rw-r--r--sbin/ipfw/ipfw2.c11
-rw-r--r--sbin/mdconfig/mdconfig.893
-rw-r--r--sbin/routed/input.c6
-rw-r--r--sbin/setkey/parse.y23
-rw-r--r--sbin/setkey/setkey.81
-rw-r--r--sbin/setkey/token.l4
-rw-r--r--sbin/sysctl/sysctl.c50
-rw-r--r--share/man/man4/Makefile3
-rw-r--r--share/man/man4/bwi.43
-rw-r--r--share/man/man4/cloudabi.4103
-rw-r--r--share/man/man4/pms.48
-rw-r--r--share/man/man4/ral.43
-rw-r--r--share/man/man4/uftdi.466
-rw-r--r--share/man/man5/src.conf.584
-rw-r--r--share/man/man9/CTASSERT.919
-rw-r--r--share/man/man9/Makefile2
-rw-r--r--share/man/man9/pmap.92
-rw-r--r--share/man/man9/pmap_quick_enter_page.9103
-rw-r--r--share/man/man9/sysctl.952
-rw-r--r--share/misc/committers-ports.dot5
-rw-r--r--share/misc/committers-src.dot3
-rw-r--r--share/mk/bsd.cpu.mk21
-rw-r--r--share/mk/src.opts.mk18
-rw-r--r--sys/amd64/amd64/mp_machdep.c1
-rw-r--r--sys/amd64/amd64/pmap.c12
-rw-r--r--sys/amd64/cloudabi64/cloudabi64_sysvec.c14
-rw-r--r--sys/amd64/include/atomic.h24
-rw-r--r--sys/amd64/include/in_cksum.h2
-rw-r--r--sys/amd64/include/md_var.h1
-rw-r--r--sys/amd64/include/xen/xenvar.h59
-rw-r--r--sys/arm/arm/pmap-v6-new.c109
-rw-r--r--sys/arm/arm/pmap-v6.c69
-rw-r--r--sys/arm/arm/pmap.c36
-rw-r--r--sys/arm/conf/BEAGLEBONE1
-rw-r--r--sys/arm/include/float.h6
-rw-r--r--sys/arm/include/pcpu.h8
-rw-r--r--sys/arm/ti/ti_gpio.c18
-rw-r--r--sys/arm64/arm64/elf_machdep.c4
-rw-r--r--sys/arm64/arm64/gic_v3.c18
-rw-r--r--sys/arm64/arm64/gic_v3_its.c76
-rw-r--r--sys/arm64/arm64/gic_v3_var.h2
-rw-r--r--sys/arm64/arm64/machdep.c27
-rw-r--r--sys/arm64/arm64/mem.c71
-rw-r--r--sys/arm64/arm64/pmap.c36
-rw-r--r--sys/arm64/arm64/stack_machdep.c32
-rw-r--r--sys/arm64/arm64/swtch.S8
-rw-r--r--sys/arm64/arm64/trap.c11
-rw-r--r--sys/arm64/arm64/uio_machdep.c2
-rw-r--r--sys/arm64/arm64/uma_machdep.c (renamed from sys/amd64/include/xen/xenfunc.h)94
-rw-r--r--sys/arm64/arm64/vfp.c14
-rw-r--r--sys/arm64/arm64/vm_machdep.c17
-rw-r--r--sys/arm64/conf/GENERIC3
-rw-r--r--sys/arm64/include/atomic.h19
-rw-r--r--sys/arm64/include/cpu.h26
-rw-r--r--sys/arm64/include/float.h4
-rw-r--r--sys/arm64/include/in_cksum.h6
-rw-r--r--sys/arm64/include/vfp.h2
-rw-r--r--sys/arm64/include/vmparam.h7
-rw-r--r--sys/boot/common/module.c8
-rw-r--r--sys/boot/forth/loader.conf2
-rw-r--r--sys/boot/forth/loader.rc3
-rw-r--r--sys/boot/forth/menu.rc3
-rw-r--r--sys/boot/i386/loader/Makefile7
-rw-r--r--sys/boot/mips/beri/loader/Makefile8
-rw-r--r--sys/boot/pc98/loader/Makefile7
-rw-r--r--sys/boot/powerpc/kboot/Makefile8
-rw-r--r--sys/boot/powerpc/ofw/Makefile8
-rw-r--r--sys/boot/powerpc/ps3/Makefile8
-rw-r--r--sys/boot/sparc64/loader/Makefile8
-rw-r--r--sys/cam/ctl/ctl.c22
-rw-r--r--sys/cam/ctl/ctl.h2
-rw-r--r--sys/cam/ctl/ctl_backend_block.c88
-rw-r--r--sys/cam/ctl/ctl_cmd_table.c12
-rw-r--r--sys/cam/ctl/ctl_private.h1
-rw-r--r--sys/cam/ctl/ctl_ser_table.c29
-rw-r--r--sys/cam/ctl/ctl_tpc.c9
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c8
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c15
-rw-r--r--sys/cddl/dev/fbt/aarch64/fbt_isa.c1
-rw-r--r--sys/cddl/dev/fbt/arm/fbt_isa.c1
-rw-r--r--sys/cddl/dev/fbt/fbt.h2
-rw-r--r--sys/cddl/dev/fbt/powerpc/fbt_isa.c1
-rw-r--r--sys/cddl/dev/fbt/x86/fbt_isa.c1
-rw-r--r--sys/compat/cloudabi/cloudabi_fd.c374
-rw-r--r--sys/compat/cloudabi/cloudabi_file.c490
-rw-r--r--sys/compat/cloudabi/cloudabi_futex.c83
-rw-r--r--sys/compat/cloudabi/cloudabi_proc.c9
-rw-r--r--sys/compat/cloudabi/cloudabi_sock.c118
-rw-r--r--sys/compat/cloudabi/cloudabi_util.h17
-rw-r--r--sys/compat/cloudabi64/cloudabi64_poll.c9
-rw-r--r--sys/compat/cloudabi64/cloudabi64_proto.h16
-rw-r--r--sys/compat/cloudabi64/cloudabi64_syscall.h5
-rw-r--r--sys/compat/cloudabi64/cloudabi64_syscalls.c3
-rw-r--r--sys/compat/cloudabi64/cloudabi64_sysent.c3
-rw-r--r--sys/compat/cloudabi64/cloudabi64_systrace_args.c62
-rw-r--r--sys/compat/cloudabi64/syscalls.master12
-rw-r--r--sys/compat/linux/linux_event.c2
-rw-r--r--sys/compat/linux/linux_file.c4
-rw-r--r--sys/compat/linux/linux_fork.c8
-rw-r--r--sys/conf/files5
-rw-r--r--sys/conf/files.arm645
-rw-r--r--sys/conf/options.arm649
-rw-r--r--sys/contrib/alpine-hal/al_hal_common.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_common.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_iofic.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_iofic.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_iofic_regs.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_iofic_regs.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_nb_regs.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_nb_regs.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_pbs_regs.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_pbs_regs.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_pcie.c (renamed from sys/arm/annapurna/alpine/hal/al_hal_pcie.c)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_pcie.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_pcie.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_pcie_axi_reg.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_pcie_axi_reg.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_pcie_interrupts.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_pcie_interrupts.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_pcie_regs.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_pcie_regs.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_pcie_w_reg.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_pcie_w_reg.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_plat_services.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_plat_services.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_plat_types.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_plat_types.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_reg_utils.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_reg_utils.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_types.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_types.h)0
-rw-r--r--sys/contrib/alpine-hal/al_hal_unit_adapter_regs.h (renamed from sys/arm/annapurna/alpine/hal/al_hal_unit_adapter_regs.h)0
-rw-r--r--sys/contrib/cloudabi/syscalldefs_md.h6
-rw-r--r--sys/contrib/cloudabi/syscalldefs_mi.h9
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c13
-rw-r--r--sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c19
-rw-r--r--sys/crypto/aesni/aesni.h2
-rw-r--r--sys/crypto/aesni/aesni_ghash.c4
-rw-r--r--sys/dev/ata/ata-all.c2
-rw-r--r--sys/dev/ata/ata-lowlevel.c237
-rw-r--r--sys/dev/ath/ath_rate/sample/sample.c9
-rw-r--r--sys/dev/ath/ath_rate/sample/sample.h3
-rw-r--r--sys/dev/ath/if_ath.c501
-rw-r--r--sys/dev/ath/if_ath_beacon.c6
-rw-r--r--sys/dev/ath/if_ath_debug.h7
-rw-r--r--sys/dev/ath/if_ath_keycache.c6
-rw-r--r--sys/dev/ath/if_ath_misc.h2
-rw-r--r--sys/dev/ath/if_ath_rx.c46
-rw-r--r--sys/dev/ath/if_ath_rx_edma.c10
-rw-r--r--sys/dev/ath/if_ath_sysctl.c12
-rw-r--r--sys/dev/ath/if_ath_tdma.c2
-rw-r--r--sys/dev/ath/if_ath_tx.c31
-rw-r--r--sys/dev/ath/if_ath_tx_edma.c10
-rw-r--r--sys/dev/ath/if_athvar.h7
-rw-r--r--sys/dev/bwi/bwimac.c73
-rw-r--r--sys/dev/bwi/bwiphy.c2
-rw-r--r--sys/dev/bwi/bwirf.c9
-rw-r--r--sys/dev/bwi/if_bwi.c398
-rw-r--r--sys/dev/bwi/if_bwivar.h4
-rw-r--r--sys/dev/bwn/if_bwn.c444
-rw-r--r--sys/dev/bwn/if_bwnvar.h6
-rw-r--r--sys/dev/bxe/bxe.c36
-rw-r--r--sys/dev/bxe/bxe.h1
-rw-r--r--sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c30
-rw-r--r--sys/dev/cxgb/ulp/tom/cxgb_listen.c28
-rw-r--r--sys/dev/cxgbe/firmware/t4fw-1.14.4.0.bin.uu (renamed from sys/dev/cxgbe/firmware/t4fw-1.14.2.0.bin.uu)4467
-rw-r--r--sys/dev/cxgbe/firmware/t4fw_interface.h4
-rw-r--r--sys/dev/cxgbe/firmware/t5fw-1.14.4.0.bin.uu (renamed from sys/dev/cxgbe/firmware/t5fw-1.14.2.0.bin.uu)9752
-rw-r--r--sys/dev/cxgbe/t4_main.c4
-rw-r--r--sys/dev/cxgbe/tom/t4_connect.c4
-rw-r--r--sys/dev/cxgbe/tom/t4_cpl_io.c20
-rw-r--r--sys/dev/cxgbe/tom/t4_listen.c28
-rw-r--r--sys/dev/cxgbe/tom/t4_tom.c7
-rw-r--r--sys/dev/drm2/i915/i915_drv.h3
-rw-r--r--sys/dev/drm2/i915/i915_gem.c4214
-rw-r--r--sys/dev/drm2/i915/i915_gem_gtt.c55
-rw-r--r--sys/dev/e1000/if_em.c3
-rw-r--r--sys/dev/e1000/if_igb.c3
-rw-r--r--sys/dev/gpio/gpiobacklight.c211
-rw-r--r--sys/dev/if_ndis/if_ndis.c998
-rw-r--r--sys/dev/if_ndis/if_ndisvar.h27
-rw-r--r--sys/dev/ipw/if_ipw.c254
-rw-r--r--sys/dev/ipw/if_ipwvar.h4
-rw-r--r--sys/dev/iscsi/iscsi.c27
-rw-r--r--sys/dev/iwi/if_iwi.c306
-rw-r--r--sys/dev/iwi/if_iwivar.h11
-rw-r--r--sys/dev/iwn/if_iwn.c363
-rw-r--r--sys/dev/iwn/if_iwnvar.h8
-rw-r--r--sys/dev/ixgbe/if_ix.c6
-rw-r--r--sys/dev/malo/if_malo.c439
-rw-r--r--sys/dev/malo/if_malo.h10
-rw-r--r--sys/dev/mii/brgphy.c1
-rw-r--r--sys/dev/mii/miidevs1
-rw-r--r--sys/dev/mmc/host/dwmmc.c2
-rw-r--r--sys/dev/mwl/if_mwl.c509
-rw-r--r--sys/dev/mwl/if_mwl_pci.c1
-rw-r--r--sys/dev/mwl/if_mwlvar.h6
-rw-r--r--sys/dev/nand/nfc_rb.c5
-rw-r--r--sys/dev/nvme/nvme.c9
-rw-r--r--sys/dev/ofw/ofw_cpu.c20
-rw-r--r--sys/dev/pms/freebsd/driver/common/lxutil.c48
-rw-r--r--sys/dev/pms/freebsd/driver/ini/src/agtiapi.c42
-rw-r--r--sys/dev/proto/proto_busdma.c7
-rw-r--r--sys/dev/ral/if_ral_pci.c1
-rw-r--r--sys/dev/ral/rt2560.c307
-rw-r--r--sys/dev/ral/rt2560var.h9
-rw-r--r--sys/dev/ral/rt2661.c289
-rw-r--r--sys/dev/ral/rt2661var.h7
-rw-r--r--sys/dev/ral/rt2860.c274
-rw-r--r--sys/dev/ral/rt2860var.h7
-rw-r--r--sys/dev/usb/controller/dwc_otg.c85
-rw-r--r--sys/dev/usb/controller/dwc_otg.h3
-rw-r--r--sys/dev/usb/serial/uftdi.c101
-rw-r--r--sys/dev/usb/serial/uftdi_reg.h5
-rw-r--r--sys/dev/usb/uftdiio.h30
-rw-r--r--sys/dev/usb/wlan/if_rsu.c299
-rw-r--r--sys/dev/usb/wlan/if_rsureg.h9
-rw-r--r--sys/dev/usb/wlan/if_rum.c302
-rw-r--r--sys/dev/usb/wlan/if_rumvar.h7
-rw-r--r--sys/dev/usb/wlan/if_run.c363
-rw-r--r--sys/dev/usb/wlan/if_runvar.h9
-rw-r--r--sys/dev/usb/wlan/if_uath.c308
-rw-r--r--sys/dev/usb/wlan/if_uathvar.h3
-rw-r--r--sys/dev/usb/wlan/if_upgt.c323
-rw-r--r--sys/dev/usb/wlan/if_upgtvar.h6
-rw-r--r--sys/dev/usb/wlan/if_ural.c284
-rw-r--r--sys/dev/usb/wlan/if_uralvar.h7
-rw-r--r--sys/dev/usb/wlan/if_urtw.c338
-rw-r--r--sys/dev/usb/wlan/if_urtwn.c282
-rw-r--r--sys/dev/usb/wlan/if_urtwnreg.h5
-rw-r--r--sys/dev/usb/wlan/if_urtwvar.h6
-rw-r--r--sys/dev/usb/wlan/if_zyd.c299
-rw-r--r--sys/dev/usb/wlan/if_zydreg.h5
-rw-r--r--sys/dev/wi/if_wi.c382
-rw-r--r--sys/dev/wi/if_wi_pccard.c1
-rw-r--r--sys/dev/wi/if_wi_pci.c17
-rw-r--r--sys/dev/wi/if_wivar.h8
-rw-r--r--sys/dev/wpi/if_wpi.c481
-rw-r--r--sys/dev/wpi/if_wpivar.h7
-rw-r--r--sys/dev/wtap/if_wtap.c235
-rw-r--r--sys/dev/wtap/if_wtapvar.h8
-rw-r--r--sys/dev/xen/balloon/balloon.c2
-rw-r--r--sys/dev/xen/blkfront/blkfront.c112
-rw-r--r--sys/dev/xen/blkfront/block.h25
-rw-r--r--sys/dev/xen/control/control.c3
-rw-r--r--sys/dev/xen/netback/netback.c4
-rw-r--r--sys/dev/xen/netfront/netfront.c6
-rw-r--r--sys/dev/xen/pcifront/pcifront.c2
-rw-r--r--sys/fs/devfs/devfs_vnops.c23
-rw-r--r--sys/fs/ext2fs/ext2_subr.c32
-rw-r--r--sys/fs/nfsclient/nfs_clport.c85
-rw-r--r--sys/fs/nfsserver/nfs_nfsdstate.c3
-rw-r--r--sys/geom/eli/g_eli_integrity.c11
-rw-r--r--sys/geom/eli/g_eli_privacy.c11
-rw-r--r--sys/geom/geom_dev.c21
-rw-r--r--sys/geom/geom_io.c10
-rw-r--r--sys/geom/uzip/g_uzip.c8
-rw-r--r--sys/i386/i386/genassym.c1
-rw-r--r--sys/i386/i386/locore.s4
-rw-r--r--sys/i386/i386/machdep.c2
-rw-r--r--sys/i386/i386/mp_machdep.c2
-rw-r--r--sys/i386/i386/pmap.c101
-rw-r--r--sys/i386/i386/vm_machdep.c4
-rw-r--r--sys/i386/include/atomic.h95
-rw-r--r--sys/i386/include/in_cksum.h2
-rw-r--r--sys/i386/include/md_var.h1
-rw-r--r--sys/i386/include/param.h5
-rw-r--r--sys/i386/include/pcpu.h3
-rw-r--r--sys/i386/include/privatespace.h49
-rw-r--r--sys/i386/include/xen/xenfunc.h81
-rw-r--r--sys/i386/include/xen/xenvar.h36
-rw-r--r--sys/kern/init_main.c2
-rw-r--r--sys/kern/kern_descrip.c5
-rw-r--r--sys/kern/kern_event.c6
-rw-r--r--sys/kern/kern_exec.c4
-rw-r--r--sys/kern/kern_fork.c12
-rw-r--r--sys/kern/kern_kthread.c2
-rw-r--r--sys/kern/kern_linker.c8
-rw-r--r--sys/kern/kern_lock.c6
-rw-r--r--sys/kern/kern_mutex.c8
-rw-r--r--sys/kern/kern_rmlock.c13
-rw-r--r--sys/kern/kern_rwlock.c13
-rw-r--r--sys/kern/kern_sharedpage.c42
-rw-r--r--sys/kern/kern_shutdown.c126
-rw-r--r--sys/kern/kern_sx.c12
-rw-r--r--sys/kern/kern_sysctl.c204
-rw-r--r--sys/kern/kern_umtx.c6
-rw-r--r--sys/kern/sched_4bsd.c4
-rw-r--r--sys/kern/sched_ule.c4
-rw-r--r--sys/kern/subr_param.c7
-rw-r--r--sys/kern/sys_pipe.c22
-rw-r--r--sys/kern/sys_process.c11
-rw-r--r--sys/kern/uipc_shm.c43
-rw-r--r--sys/kern/vfs_bio.c240
-rw-r--r--sys/kern/vfs_init.c4
-rw-r--r--sys/kern/vfs_subr.c4
-rw-r--r--sys/kern/vfs_vnops.c62
-rw-r--r--sys/mips/conf/XLR2
-rw-r--r--sys/mips/conf/XLR642
-rw-r--r--sys/mips/conf/XLRN322
-rw-r--r--sys/mips/include/float.h2
-rw-r--r--sys/mips/include/in_cksum.h2
-rw-r--r--sys/mips/mips/pmap.c106
-rw-r--r--sys/mips/rmi/dev/iic/ds1374u.c147
-rw-r--r--sys/mips/rmi/files.xlr1
-rw-r--r--sys/mips/rmi/xlr_i2c.c2
-rw-r--r--sys/modules/Makefile7
-rw-r--r--sys/modules/cxgbe/t4_firmware/Makefile2
-rw-r--r--sys/modules/cxgbe/t5_firmware/Makefile2
-rw-r--r--sys/modules/if_stf/Makefile2
-rw-r--r--sys/modules/zfs/Makefile2
-rw-r--r--sys/net/bpf.c62
-rw-r--r--sys/net/bpf.h6
-rw-r--r--sys/net/bpf_buffer.c5
-rw-r--r--sys/net/if_gif.c7
-rw-r--r--sys/net/if_spppsubr.c2
-rw-r--r--sys/net/if_stf.c43
-rw-r--r--sys/net/pfkeyv2.h38
-rw-r--r--sys/net/radix.c10
-rw-r--r--sys/net/radix.h2
-rw-r--r--sys/net/route.c8
-rw-r--r--sys/net80211/ieee80211.c282
-rw-r--r--sys/net80211/ieee80211_ddb.c3
-rw-r--r--sys/net80211/ieee80211_freebsd.c90
-rw-r--r--sys/net80211/ieee80211_ioctl.c71
-rw-r--r--sys/net80211/ieee80211_output.c30
-rw-r--r--sys/net80211/ieee80211_power.c55
-rw-r--r--sys/net80211/ieee80211_proto.c36
-rw-r--r--sys/net80211/ieee80211_proto.h3
-rw-r--r--sys/net80211/ieee80211_regdomain.c3
-rw-r--r--sys/net80211/ieee80211_scan_sta.c26
-rw-r--r--sys/net80211/ieee80211_var.h27
-rw-r--r--sys/netinet/if_ether.c19
-rw-r--r--sys/netinet/igmp.c11
-rw-r--r--sys/netinet/in.c41
-rw-r--r--sys/netinet/in_gif.c50
-rw-r--r--sys/netinet/in_mcast.c10
-rw-r--r--sys/netinet/in_pcb.c58
-rw-r--r--sys/netinet/in_pcb.h97
-rw-r--r--sys/netinet/in_var.h23
-rw-r--r--sys/netinet/ip_ecn.h4
-rw-r--r--sys/netinet/ip_icmp.c9
-rw-r--r--sys/netinet/ip_input.c5
-rw-r--r--sys/netinet/ip_output.c219
-rw-r--r--sys/netinet/raw_ip.c14
-rw-r--r--sys/netinet/sctp_asconf.c8
-rw-r--r--sys/netinet/sctp_indata.c29
-rw-r--r--sys/netinet/sctp_indata.h6
-rw-r--r--sys/netinet/sctp_input.c15
-rw-r--r--sys/netinet/sctp_output.c34
-rw-r--r--sys/netinet/sctp_pcb.c26
-rw-r--r--sys/netinet/sctp_timer.c4
-rw-r--r--sys/netinet/sctputil.c5
-rw-r--r--sys/netinet/tcp_input.c120
-rw-r--r--sys/netinet/tcp_reass.c232
-rw-r--r--sys/netinet/tcp_subr.c52
-rw-r--r--sys/netinet/tcp_syncache.c20
-rw-r--r--sys/netinet/tcp_timer.c44
-rw-r--r--sys/netinet/tcp_timewait.c37
-rw-r--r--sys/netinet/tcp_usrreq.c46
-rw-r--r--sys/netinet/tcp_var.h14
-rw-r--r--sys/netinet/toecore.c6
-rw-r--r--sys/netinet6/in6.c28
-rw-r--r--sys/netinet6/in6_gif.c45
-rw-r--r--sys/netinet6/in6_ifattach.c2
-rw-r--r--sys/netinet6/in6_pcb.c4
-rw-r--r--sys/netinet6/in6_src.c100
-rw-r--r--sys/netinet6/in6_var.h16
-rw-r--r--sys/netinet6/ip6_input.c6
-rw-r--r--sys/netipsec/ipsec_output.c3
-rw-r--r--sys/netipsec/key.c2
-rw-r--r--sys/netipsec/key_debug.c5
-rw-r--r--sys/netipsec/keydb.h8
-rw-r--r--sys/netipsec/xform.h1
-rw-r--r--sys/netipsec/xform_ah.c35
-rw-r--r--sys/netipsec/xform_esp.c204
-rw-r--r--sys/netpfil/ipfw/ip_fw2.c50
-rw-r--r--sys/netpfil/pf/pf.c6
-rw-r--r--sys/netpfil/pf/pf_norm.c4
-rw-r--r--sys/ofed/drivers/infiniband/core/mad.c7
-rw-r--r--sys/ofed/drivers/net/mlx4/en_tx.c6
-rw-r--r--sys/ofed/include/linux/in.h4
-rw-r--r--sys/opencrypto/cryptodev.h10
-rw-r--r--sys/opencrypto/cryptosoft.c8
-rw-r--r--sys/opencrypto/xform.c13
-rw-r--r--sys/pc98/include/privatespace.h6
-rw-r--r--sys/powerpc/aim/mmu_oea.c16
-rw-r--r--sys/powerpc/aim/mmu_oea64.c71
-rw-r--r--sys/powerpc/booke/pmap.c77
-rw-r--r--sys/powerpc/include/float.h2
-rw-r--r--sys/powerpc/include/in_cksum.h2
-rw-r--r--sys/powerpc/include/pcpu.h12
-rw-r--r--sys/powerpc/powerpc/mmu_if.m23
-rw-r--r--sys/powerpc/powerpc/pmap_dispatch.c14
-rw-r--r--sys/rpc/svc_vc.c2
-rw-r--r--sys/sparc64/include/float.h2
-rw-r--r--sys/sparc64/include/in_cksum.h2
-rw-r--r--sys/sparc64/include/pcpu.h3
-rw-r--r--sys/sparc64/sparc64/pmap.c68
-rw-r--r--sys/sys/buf.h3
-rw-r--r--sys/sys/event.h1
-rw-r--r--sys/sys/filedesc.h8
-rw-r--r--sys/sys/mbuf.h1
-rw-r--r--sys/sys/msg.h5
-rw-r--r--sys/sys/proc.h12
-rw-r--r--sys/sys/sem.h5
-rw-r--r--sys/sys/shm.h5
-rw-r--r--sys/sys/syscallsubr.h9
-rw-r--r--sys/sys/sysctl.h4
-rw-r--r--sys/sys/sysent.h11
-rw-r--r--sys/sys/umtx.h2
-rw-r--r--sys/ufs/ffs/ffs_subr.c35
-rw-r--r--sys/vm/pmap.h2
-rw-r--r--sys/vm/vm_fault.c53
-rw-r--r--sys/vm/vm_map.c2
-rw-r--r--sys/vm/vm_map.h6
-rw-r--r--sys/vm/vm_pager.c2
-rw-r--r--sys/vm/vm_reserv.c32
-rw-r--r--sys/x86/include/_types.h12
-rw-r--r--sys/x86/include/float.h2
-rw-r--r--sys/x86/include/specialreg.h11
-rw-r--r--sys/x86/x86/identcpu.c46
-rw-r--r--sys/x86/x86/mp_x86.c2
-rw-r--r--sys/x86/xen/xen_intr.c1
-rw-r--r--sys/xen/interface/io/blkif.h171
-rw-r--r--tests/sys/kern/ptrace_test.c581
-rw-r--r--tests/sys/kern/unix_seqpacket_test.c60
-rw-r--r--tests/sys/vm/Makefile2
-rw-r--r--tests/sys/vm/mmap_test.c129
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc32
-rw-r--r--tools/build/options/WITHOUT_BINUTILS3
-rw-r--r--tools/build/options/WITHOUT_ELFCOPY_AS_OBJCOPY4
-rw-r--r--tools/build/options/WITHOUT_ELFTOOLCHAIN_TOOLS7
-rw-r--r--tools/build/options/WITH_DTRACE_TESTS5
-rw-r--r--tools/build/options/WITH_ELFCOPY_AS_OBJCOPY4
-rw-r--r--tools/bus_space/C/lang.c11
-rw-r--r--tools/bus_space/C/libbus.h3
-rw-r--r--tools/bus_space/Python/lang.c25
-rw-r--r--tools/bus_space/busdma.c6
-rw-r--r--tools/bus_space/busdma.h2
-rw-r--r--tools/bus_space/examples/am79c900_diag.py344
-rw-r--r--tools/tools/iwn/iwnstats/main.c15
-rw-r--r--usr.bin/ar/ar.11
-rw-r--r--usr.bin/ar/ar.c24
-rw-r--r--usr.bin/brandelf/brandelf.12
-rw-r--r--usr.bin/calendar/calendars/calendar.freebsd1
-rw-r--r--usr.bin/elfcopy/Makefile12
-rw-r--r--usr.bin/find/extern.h2
-rw-r--r--usr.bin/find/misc.c38
-rw-r--r--usr.bin/getopt/getopt.112
-rw-r--r--usr.bin/ipcrm/ipcrm.c28
-rw-r--r--usr.bin/mkimg/image.c12
-rw-r--r--usr.bin/mkimg/image.h1
-rw-r--r--usr.bin/mkimg/mkimg.184
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu29
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.gz.uu26
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu36
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu26
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu29
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu26
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.gz.uu36
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu26
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu26
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu36
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu29
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu26
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.gz.uu37
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu29
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu28
-rw-r--r--usr.bin/mkimg/vhd.c92
-rw-r--r--usr.bin/patch/common.h6
-rw-r--r--usr.bin/patch/inp.c100
-rw-r--r--usr.bin/patch/pathnames.h2
-rw-r--r--usr.bin/patch/pch.c18
-rw-r--r--usr.bin/truss/syscall.h2
-rw-r--r--usr.bin/truss/syscalls.c276
-rw-r--r--usr.bin/vgrind/vgrindefs.c322
-rw-r--r--usr.bin/wall/ttymsg.c4
-rw-r--r--usr.bin/xargs/xargs.17
-rw-r--r--usr.bin/xargs/xargs.c15
-rw-r--r--usr.bin/ypcat/ypcat.c63
-rw-r--r--usr.bin/ypmatch/ypmatch.c70
-rw-r--r--usr.bin/ypwhich/ypwhich.c2
-rw-r--r--usr.sbin/bhyve/bhyve.835
-rwxr-xr-xusr.sbin/bsdinstall/scripts/auto2
-rw-r--r--usr.sbin/chkgrp/chkgrp.c4
-rw-r--r--usr.sbin/crunch/crunchgen/crunchgen.c4
-rw-r--r--usr.sbin/pw/Makefile3
-rw-r--r--usr.sbin/pw/cpdir.c7
-rw-r--r--usr.sbin/pw/grupd.c4
-rw-r--r--usr.sbin/pw/psdate.c5
-rw-r--r--usr.sbin/pw/pw.8208
-rw-r--r--usr.sbin/pw/pw.c310
-rw-r--r--usr.sbin/pw/pw.h57
-rw-r--r--usr.sbin/pw/pw_conf.c123
-rw-r--r--usr.sbin/pw/pw_group.c766
-rw-r--r--usr.sbin/pw/pw_log.c2
-rw-r--r--usr.sbin/pw/pw_nis.c2
-rw-r--r--usr.sbin/pw/pw_user.c2192
-rw-r--r--usr.sbin/pw/pw_utils.c99
-rw-r--r--usr.sbin/pw/pwupd.c14
-rw-r--r--usr.sbin/pw/pwupd.h17
-rw-r--r--usr.sbin/pw/rm_r.c9
-rw-r--r--usr.sbin/pw/strtounum.c71
-rw-r--r--usr.sbin/pw/tests/Makefile12
-rwxr-xr-xusr.sbin/pw/tests/pw_groupadd.sh26
-rwxr-xr-xusr.sbin/pw/tests/pw_groupdel.sh2
-rwxr-xr-xusr.sbin/pw/tests/pw_useradd.sh56
-rwxr-xr-xusr.sbin/pw/tests/pw_userdel.sh12
-rwxr-xr-xusr.sbin/pw/tests/pw_usermod.sh58
-rw-r--r--usr.sbin/syslogd/syslogd.c28
-rw-r--r--usr.sbin/yp_mkdb/yp_mkdb.c4
-rw-r--r--usr.sbin/yppush/yppush_main.c24
-rw-r--r--usr.sbin/ypserv/yp_access.c8
-rw-r--r--usr.sbin/ypserv/yp_dblookup.c2
-rw-r--r--usr.sbin/ypserv/yp_error.c6
-rw-r--r--usr.sbin/ypserv/yp_main.c6
623 files changed, 31396 insertions, 23591 deletions
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index 16f8d2f..e1c4d83 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -99,6 +99,8 @@ OLD_FILES+=usr/lib/clang/3.6.1/lib/freebsd/libclang_rt.ubsan_cxx-x86_64.a
OLD_DIRS+=usr/lib/clang/3.6.1/lib/freebsd
OLD_DIRS+=usr/lib/clang/3.6.1/lib
OLD_DIRS+=usr/lib/clang/3.6.1
+# 20150802: Remove netbsd's test on pw(8)
+OLD_FILES+=usr/tests/usr.sbin/pw/pw_test
# 20150719: Remove libarchive.pc
OLD_FILES+=usr/libdata/pkgconfig/libarchive.pc
# 20150705: Rename DTrace provider man pages.
diff --git a/UPDATING b/UPDATING
index 86c5808..3d1058b 100644
--- a/UPDATING
+++ b/UPDATING
@@ -36,6 +36,24 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
20141231 entry below for information about prerequisites and upgrading,
if you are not already using 3.5.0 or higher.
+20150806:
+ The menu.rc and loader.rc files will now be replaced during
+ upgrades. Please migrate local changes to menu.rc.local and
+ loader.rc.local instead.
+
+20150805:
+ GNU Binutils versions of addr2line, c++filt, nm, readelf, size,
+ strings and strip have been removed. The src.conf(5) knob
+ WITHOUT_ELFTOOLCHAIN_TOOLS no longer provides the binutils tools.
+
+20150728:
+ As ZFS requires more kernel stack pages than is the default on some
+ architectures e.g. i386, it now warns if KSTACK_PAGES is less than
+ ZFS_MIN_KSTACK_PAGES (which is 4 at the time of writing).
+
+ Please consider using 'options KSTACK_PAGES=X' where X is greater
+ than or equal to ZFS_MIN_KSTACK_PAGES i.e. 4 in such configurations.
+
20150706:
sendmail has been updated to 8.15.2. Starting with FreeBSD 11.0
and sendmail 8.15, sendmail uses uncompressed IPv6 addresses by
@@ -221,7 +239,7 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
taken from the ELF Tool Chain project rather than GNU binutils. They
should be drop-in replacements, with the addition of arm64 support.
The WITHOUT_ELFTOOLCHAIN_TOOLS= knob may be used to obtain the
- binutils tools, if necessary.
+ binutils tools, if necessary. See 20150805 for updated information.
20150105:
The default Unbound configuration now enables remote control
@@ -575,6 +593,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
# pkg install pkg; ldd /usr/local/sbin/pkg | grep bsdyml
20131010:
+ The stable/10 branch has been created in subversion from head
+ revision r256279.
+
+20131010:
The rc.d/jail script has been updated to support jail(8)
configuration file. The "jail_<jname>_*" rc.conf(5) variables
for per-jail configuration are automatically converted to
@@ -1117,6 +1139,13 @@ COMMON ITEMS:
around can lead to problems if pam has changed too much from your
starting point to allow continued authentication after the upgrade.
+ This file should be read as a log of events. When a later event changes
+ information of a prior event, the prior event should not be deleted.
+ Instead, a pointer to the entry with the new information should be
+ placed in the old entry. Readers of this file should also sanity check
+ older entries before relying on them blindly. Authors of new entries
+ should write them with this in mind.
+
ZFS notes
---------
When upgrading the boot ZFS pool to a new version, always follow
@@ -1287,7 +1316,7 @@ FORMAT:
This file contains a list, in reverse chronological order, of major
breakages in tracking -current. It is not guaranteed to be a complete
-list of such breakages, and only contains entries since October 10, 2007.
+list of such breakages, and only contains entries since September 23, 2011.
If you need to see UPDATING entries from before that date, you will need
to fetch an UPDATING file from an older FreeBSD release.
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.motoofew.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.motoofew.d
index cf4dd5e..823a98d 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.motoofew.d
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.motoofew.d
@@ -34,7 +34,7 @@
*
*/
-lockstat:kernel:mtx_lock:adaptive-acquire
+lockstat:::adaptive-acquire
{
mutex_owned();
exit(1);
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.motoomany.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.motoomany.d
index 6cc4be0..37637c0 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.motoomany.d
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.motoomany.d
@@ -34,7 +34,7 @@
*
*/
-lockstat:kernel:mtx_lock:adaptive-acquire
+lockstat:::adaptive-acquire
{
mutex_owned((kmutex_t *)arg0, 99);
exit(1);
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.mtatoofew.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.mtatoofew.d
index 61d967a..2d299d4 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.mtatoofew.d
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.mtatoofew.d
@@ -36,7 +36,7 @@
*/
-lockstat:kernel:mtx_lock:adaptive-acquire
+lockstat:::adaptive-acquire
{
mutex_type_adaptive();
exit(1);
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.mtatoomany.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.mtatoomany.d
index f2c3178..42ae016 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.mtatoomany.d
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/err.D_PROTO_LEN.mtatoomany.d
@@ -35,7 +35,7 @@
*/
-lockstat:kernel:mtx_lock:adaptive-acquire
+lockstat:::adaptive-acquire
{
mutex_type_adaptive((kmutex_t *)arg0, 99);
exit(1);
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.mutex_owner.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.mutex_owner.d
index dbb10c3..0784eda 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.mutex_owner.d
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.mutex_owner.d
@@ -48,7 +48,7 @@ BEGIN
i = 0;
}
-lockstat::mtx_lock:adaptive-acquire
+lockstat:::adaptive-acquire
{
ptr = mutex_owner((struct mtx *)arg0);
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.mutex_type_adaptive.d b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.mutex_type_adaptive.d
index ac43e79..f953d24 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.mutex_type_adaptive.d
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/funcs/tst.mutex_type_adaptive.d
@@ -44,7 +44,7 @@ BEGIN
ret = -99;
}
-mtx_lock:adaptive-acquire
+lockstat:::adaptive-acquire
{
ret = mutex_type_adaptive((struct mtx *)arg0);
i++;
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
index ccc247d..5f58eb8 100755
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv4remote.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/env perl
#
# CDDL HEADER START
#
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv6remote.pl b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv6remote.pl
index 35bea8e..fbfcdfd 100755
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv6remote.pl
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/get.ipv6remote.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/env perl
#
# CDDL HEADER START
#
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localtcp.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localtcp.ksh
index 2e3ffec..1d2a992 100755
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localtcp.ksh
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4localtcp.ksh
@@ -58,12 +58,25 @@ fi
dtrace=$1
local=127.0.0.1
-tcpport=22
DIR=/var/tmp/dtest.$$
+tcpport=1024
+bound=5000
+while [ $tcpport -lt $bound ]; do
+ nc -z $local $tcpport >/dev/null || break
+ tcpport=$(($tcpport + 1))
+done
+if [ $tcpport -eq $bound ]; then
+ echo "couldn't find an available TCP port"
+ exit 1
+fi
+
mkdir $DIR
cd $DIR
+# nc will exit when the connection is closed.
+nc -l $local $tcpport &
+
cat > test.pl <<-EOPERL
use IO::Socket;
my \$s = IO::Socket::INET->new(
@@ -76,7 +89,7 @@ cat > test.pl <<-EOPERL
sleep(2);
EOPERL
-$dtrace -c '/usr/bin/perl test.pl' -qs /dev/stdin <<EODTRACE
+$dtrace -c 'perl test.pl' -qs /dev/stdin <<EODTRACE
BEGIN
{
ipsend = tcpsend = ipreceive = tcpreceive = 0;
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotetcp.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotetcp.ksh
index 65ede66..4c91f00 100755
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotetcp.ksh
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.ipv4remotetcp.ksh
@@ -79,7 +79,7 @@ cat > test.pl <<-EOPERL
sleep(2);
EOPERL
-$dtrace -c '/usr/bin/perl test.pl' -qs /dev/stdin <<EODTRACE
+$dtrace -c 'perl test.pl' -qs /dev/stdin <<EODTRACE
BEGIN
{
ipsend = tcpsend = ipreceive = tcpreceive = 0;
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localtcpstate.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localtcpstate.ksh
index 9668ad5..d7a3780 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localtcpstate.ksh
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.localtcpstate.ksh
@@ -82,7 +82,7 @@ cat > test.pl <<-EOPERL
sleep(2);
EOPERL
-$dtrace -c '/usr/bin/perl test.pl' -qs /dev/stdin <<EODTRACE
+$dtrace -c 'perl test.pl' -qs /dev/stdin <<EODTRACE
BEGIN
{
ipsend = tcpsend = ipreceive = tcpreceive = 0;
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotetcpstate.ksh b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotetcpstate.ksh
index 6771280..271cc78 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotetcpstate.ksh
+++ b/cddl/contrib/opensolaris/cmd/dtrace/test/tst/common/ip/tst.remotetcpstate.ksh
@@ -87,7 +87,7 @@ cat > test.pl <<-EOPERL
sleep(2);
EOPERL
-$dtrace -c '/usr/bin/perl test.pl' -qs /dev/stdin <<EODTRACE
+$dtrace -c 'perl test.pl' -qs /dev/stdin <<EODTRACE
BEGIN
{
ipsend = tcpsend = ipreceive = tcpreceive = 0;
diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs.8 b/cddl/contrib/opensolaris/cmd/zfs/zfs.8
index f2852cf..b7d9ac0 100644
--- a/cddl/contrib/opensolaris/cmd/zfs/zfs.8
+++ b/cddl/contrib/opensolaris/cmd/zfs/zfs.8
@@ -27,11 +27,11 @@
.\" Copyright (c) 2013, Steven Hartland <smh@FreeBSD.org>
.\" Copyright (c) 2014 Nexenta Systems, Inc. All Rights Reserved.
.\" Copyright (c) 2014, Xin LI <delphij@FreeBSD.org>
-.\" Copyright (c) 2014, The FreeBSD Foundation, All Rights Reserved.
+.\" Copyright (c) 2014-2015, The FreeBSD Foundation, All Rights Reserved.
.\"
.\" $FreeBSD$
.\"
-.Dd December 12, 2014
+.Dd July 30, 2015
.Dt ZFS 8
.Os
.Sh NAME
@@ -938,7 +938,7 @@ not be used by any other dataset.
Disabling checksums is
.Em NOT
a recommended practice.
-.It Sy compression Ns = Ns Cm on | off | lzjb | gzip | gzip- Ns Ar N | zle | Cm lz4
+.It Sy compression Ns = Ns Cm on | off | lzjb | gzip | gzip- Ns Ar N | Cm zle | Cm lz4
Controls the compression algorithm used for this dataset. The
.Cm lzjb
compression algorithm is optimized for performance while providing decent data
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c
index ae26d55..d408aed 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_printf.c
@@ -1348,6 +1348,7 @@ dt_printf_format(dtrace_hdl_t *dtp, FILE *fp, const dt_pfargv_t *pfv,
dtrace_aggdesc_t *agg;
caddr_t lim = (caddr_t)buf + len, limit;
char format[64] = "%";
+ size_t ret;
int i, aggrec, curagg = -1;
uint64_t normal;
@@ -1379,7 +1380,9 @@ dt_printf_format(dtrace_hdl_t *dtp, FILE *fp, const dt_pfargv_t *pfv,
int prec = pfd->pfd_prec;
int rval;
+ const char *start;
char *f = format + 1; /* skip initial '%' */
+ size_t fmtsz = sizeof(format) - 1;
const dtrace_recdesc_t *rec;
dt_pfprint_f *func;
caddr_t addr;
@@ -1536,6 +1539,7 @@ dt_printf_format(dtrace_hdl_t *dtp, FILE *fp, const dt_pfargv_t *pfv,
break;
}
+ start = f;
if (pfd->pfd_flags & DT_PFCONV_ALT)
*f++ = '#';
if (pfd->pfd_flags & DT_PFCONV_ZPAD)
@@ -1548,6 +1552,7 @@ dt_printf_format(dtrace_hdl_t *dtp, FILE *fp, const dt_pfargv_t *pfv,
*f++ = '\'';
if (pfd->pfd_flags & DT_PFCONV_SPACE)
*f++ = ' ';
+ fmtsz -= f - start;
/*
* If we're printing a stack and DT_PFCONV_LEFT is set, we
@@ -1558,13 +1563,20 @@ dt_printf_format(dtrace_hdl_t *dtp, FILE *fp, const dt_pfargv_t *pfv,
if (func == pfprint_stack && (pfd->pfd_flags & DT_PFCONV_LEFT))
width = 0;
- if (width != 0)
- f += snprintf(f, sizeof (format), "%d", ABS(width));
+ if (width != 0) {
+ ret = snprintf(f, fmtsz, "%d", ABS(width));
+ f += ret;
+ fmtsz = MAX(0, fmtsz - ret);
+ }
- if (prec > 0)
- f += snprintf(f, sizeof (format), ".%d", prec);
+ if (prec > 0) {
+ ret = snprintf(f, fmtsz, ".%d", prec);
+ f += ret;
+ fmtsz = MAX(0, fmtsz - ret);
+ }
- (void) strcpy(f, pfd->pfd_fmt);
+ if (strlcpy(f, pfd->pfd_fmt, fmtsz) >= fmtsz)
+ return (dt_set_errno(dtp, EDT_COMPILER));
pfd->pfd_rec = rec;
if (func(dtp, fp, format, pfd, addr, size, normal) < 0)
diff --git a/cddl/lib/libdtrace/io.d b/cddl/lib/libdtrace/io.d
index 18a54af..41f7aa1 100644
--- a/cddl/lib/libdtrace/io.d
+++ b/cddl/lib/libdtrace/io.d
@@ -25,8 +25,7 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
+#pragma D depends_on module kernel
#pragma D depends_on provider io
typedef struct devinfo {
diff --git a/cddl/lib/libdtrace/ip.d b/cddl/lib/libdtrace/ip.d
index a1a2996..33fb007 100644
--- a/cddl/lib/libdtrace/ip.d
+++ b/cddl/lib/libdtrace/ip.d
@@ -25,6 +25,7 @@
* Copyright (c) 2013 Mark Johnston <markj@freebsd.org>
*/
+#pragma D depends_on module kernel
#pragma D depends_on provider ip
/*
diff --git a/cddl/lib/libdtrace/nfs.d b/cddl/lib/libdtrace/nfs.d
index be34228..ae864ed 100644
--- a/cddl/lib/libdtrace/nfs.d
+++ b/cddl/lib/libdtrace/nfs.d
@@ -30,6 +30,7 @@
#pragma D depends_on library ip.d
#pragma D depends_on library net.d
+#pragma D depends_on module kernel
#pragma D depends_on module nfs
typedef struct nfsv4opinfo {
diff --git a/cddl/lib/libdtrace/nfssrv.d b/cddl/lib/libdtrace/nfssrv.d
index 68ac08b..37842f7 100644
--- a/cddl/lib/libdtrace/nfssrv.d
+++ b/cddl/lib/libdtrace/nfssrv.d
@@ -30,7 +30,8 @@
#pragma D depends_on library ip.d
#pragma D depends_on library net.d
-#pragma D depends_on module nfs.d
+#pragma D depends_on library nfs.d
+#pragma D depends_on module kernel
#pragma D depends_on module nfssrv
#pragma D binding "1.5" translator
diff --git a/cddl/lib/libdtrace/psinfo.d b/cddl/lib/libdtrace/psinfo.d
index c2219f7..1b13863 100644
--- a/cddl/lib/libdtrace/psinfo.d
+++ b/cddl/lib/libdtrace/psinfo.d
@@ -28,6 +28,8 @@
* Use is subject to license terms.
*/
+#pragma D depends_on module kernel
+
typedef struct psinfo {
int pr_nlwp; /* number of threads */
pid_t pr_pid; /* unique process id */
diff --git a/cddl/lib/libdtrace/regs_x86.d b/cddl/lib/libdtrace/regs_x86.d
index 7dce197..03528a6 100644
--- a/cddl/lib/libdtrace/regs_x86.d
+++ b/cddl/lib/libdtrace/regs_x86.d
@@ -28,8 +28,6 @@
* Use is subject to license terms.
*/
-#pragma ident "@(#)regs.d.in 1.1 04/09/28 SMI"
-
inline int R_GS = 0;
#pragma D binding "1.0" R_GS
inline int R_FS = 1;
diff --git a/cddl/lib/libdtrace/sched.d b/cddl/lib/libdtrace/sched.d
index d91d3c5..104fd57 100644
--- a/cddl/lib/libdtrace/sched.d
+++ b/cddl/lib/libdtrace/sched.d
@@ -27,9 +27,7 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#pragma D depends_on module unix
+#pragma D depends_on module kernel
#pragma D depends_on provider sched
struct cpuinfo {
diff --git a/cddl/lib/libdtrace/siftr.d b/cddl/lib/libdtrace/siftr.d
index a6ff844..37bc30f 100644
--- a/cddl/lib/libdtrace/siftr.d
+++ b/cddl/lib/libdtrace/siftr.d
@@ -21,6 +21,7 @@
* $FreeBSD$
*/
+#pragma D depends_on module kernel
#pragma D depends_on module siftr
#pragma D depends_on provider tcp
diff --git a/cddl/lib/libdtrace/tcp.d b/cddl/lib/libdtrace/tcp.d
index 4b826f1..8398cd3 100644
--- a/cddl/lib/libdtrace/tcp.d
+++ b/cddl/lib/libdtrace/tcp.d
@@ -26,6 +26,7 @@
*/
#pragma D depends_on library ip.d
+#pragma D depends_on module kernel
#pragma D depends_on provider tcp
/*
diff --git a/cddl/lib/libdtrace/udp.d b/cddl/lib/libdtrace/udp.d
index 21538eb..eeba58c 100644
--- a/cddl/lib/libdtrace/udp.d
+++ b/cddl/lib/libdtrace/udp.d
@@ -26,6 +26,7 @@
*/
#pragma D depends_on library ip.d
+#pragma D depends_on module kernel
#pragma D depends_on provider udp
/*
diff --git a/cddl/usr.sbin/dtrace/Makefile b/cddl/usr.sbin/dtrace/Makefile
index 8c5e3ab..551f6cf 100644
--- a/cddl/usr.sbin/dtrace/Makefile
+++ b/cddl/usr.sbin/dtrace/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <src.opts.mk>
+
.PATH: ${.CURDIR}/../../../cddl/contrib/opensolaris/cmd/dtrace
PROG= dtrace
@@ -22,4 +24,8 @@ CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris \
LIBADD= dtrace
+.if ${MK_DTRACE_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/contrib/bsnmp/snmp_mibII/mibII_ip.c b/contrib/bsnmp/snmp_mibII/mibII_ip.c
index 11efe82..1e33dc9 100644
--- a/contrib/bsnmp/snmp_mibII/mibII_ip.c
+++ b/contrib/bsnmp/snmp_mibII/mibII_ip.c
@@ -151,7 +151,7 @@ int
op_ip(struct snmp_context *ctx, struct snmp_value *value,
u_int sub, u_int idx __unused, enum snmp_op op)
{
- int old;
+ int old = 0;
switch (op) {
diff --git a/contrib/elftoolchain/ar/Makefile b/contrib/elftoolchain/ar/Makefile
new file mode 100644
index 0000000..ddd8113
--- /dev/null
+++ b/contrib/elftoolchain/ar/Makefile
@@ -0,0 +1,35 @@
+# $Id: Makefile 3107 2014-12-20 08:31:58Z kaiwang27 $
+
+TOP= ..
+
+PROG= ar
+SRCS= ar.c read.c util.c write.c
+LSRC= acplex.l
+YSRC= acpyacc.y
+
+WARNS?= 5
+
+DPADD= ${LIBARCHIVE} ${LIBELFTC} ${LIBELF} ${LIBZ}
+LDADD= -larchive -lelftc -lelf -lz
+
+CFLAGS+=-I. -I${.CURDIR}
+
+LINKS= ${BINDIR}/ar ${BINDIR}/ranlib
+
+EXTRA_TARGETS= ranlib
+
+CLEANFILES+= ${EXTRA_TARGETS}
+
+MAN= ar.1 ranlib.1 ar.5
+
+all: ${EXTRA_TARGETS}
+
+${EXTRA_TARGETS}: ${PROG}
+ ln -s ${PROG} ${.TARGET}
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
+
+.if ${OS_HOST} == "OpenBSD"
+CFLAGS+= -I/usr/local/include
+LDFLAGS+= -L/usr/local/lib
+.endif
diff --git a/contrib/elftoolchain/ar/acplex.l b/contrib/elftoolchain/ar/acplex.l
new file mode 100644
index 0000000..6b50fb3
--- /dev/null
+++ b/contrib/elftoolchain/ar/acplex.l
@@ -0,0 +1,83 @@
+%{
+/*-
+ * Copyright (c) 2008 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
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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 <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: acplex.l 3174 2015-03-27 17:13:41Z emaste $");
+
+#include "acpyacc.h"
+
+#define YY_NO_UNPUT
+#if !defined(ELFTC_BROKEN_YY_NO_INPUT)
+#define YY_NO_INPUT
+#endif
+
+int lineno = 1;
+
+int yylex(void);
+
+%}
+
+%option nounput
+%option noyywrap
+
+%%
+
+ADDLIB|addlib { return (ADDLIB); }
+ADDMOD|addmod { return (ADDMOD); }
+CLEAR|clear { return (CLEAR); }
+CREATE|create { return (CREATE); }
+DELETE|delete { return (DELETE); }
+DIRECTORY|directory { return (DIRECTORY); }
+END|end { return (END); }
+EXTRACT|extract { return (EXTRACT); }
+LIST|list { return (LIST); }
+OPEN|open { return (OPEN); }
+REPLACE|replace { return (REPLACE); }
+VERBOSE|verbose { return (VERBOSE); }
+SAVE|save { return (SAVE); }
+"(" { return (LP); }
+")" { return (RP); }
+"," { return (COMMA); }
+
+[-_A-Za-z0-9/:$.\\]+ {
+ yylval.str = strdup(yytext);
+ if (yylval.str == NULL)
+ err(EXIT_FAILURE, "strdup failed");
+ return (FNAME);
+}
+
+[ \t] /* whitespace */
+"*".* /* comment */
+";".* /* comment */
+"+\n" { lineno++; /* '+' is line continuation char */ }
+"\n" { lineno++; return (EOL); }
diff --git a/contrib/elftoolchain/ar/acpyacc.y b/contrib/elftoolchain/ar/acpyacc.y
new file mode 100644
index 0000000..84f08e2
--- /dev/null
+++ b/contrib/elftoolchain/ar/acpyacc.y
@@ -0,0 +1,658 @@
+%{
+/*-
+ * Copyright (c) 2008 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
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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/mman.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <archive.h>
+#include <archive_entry.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libelftc.h"
+
+#include "ar.h"
+
+ELFTC_VCSID("$Id");
+
+
+#define TEMPLATE "arscp.XXXXXXXX"
+
+struct list {
+ char *str;
+ struct list *next;
+};
+
+
+extern int yylex(void);
+extern int yyparse(void);
+
+static void yyerror(const char *);
+static void arscp_addlib(char *archive, struct list *list);
+static void arscp_addmod(struct list *list);
+static void arscp_clear(void);
+static void arscp_create(char *in, char *out);
+static void arscp_delete(struct list *list);
+static void arscp_dir(char *archive, struct list *list, char *rlt);
+static void arscp_end(int eval);
+static void arscp_extract(struct list *list);
+static void arscp_free_argv(void);
+static void arscp_free_mlist(struct list *list);
+static void arscp_list(void);
+static struct list *arscp_mlist(struct list *list, char *str);
+static void arscp_mlist2argv(struct list *list);
+static int arscp_mlist_len(struct list *list);
+static void arscp_open(char *fname);
+static void arscp_prompt(void);
+static void arscp_replace(struct list *list);
+static void arscp_save(void);
+static int arscp_target_exist(void);
+
+extern int lineno;
+
+static struct bsdar *bsdar;
+static char *target;
+static char *tmpac;
+static int interactive;
+static int verbose;
+
+%}
+
+%token ADDLIB
+%token ADDMOD
+%token CLEAR
+%token CREATE
+%token DELETE
+%token DIRECTORY
+%token END
+%token EXTRACT
+%token LIST
+%token OPEN
+%token REPLACE
+%token VERBOSE
+%token SAVE
+%token LP
+%token RP
+%token COMMA
+%token EOL
+%token <str> FNAME
+%type <list> mod_list
+
+%union {
+ char *str;
+ struct list *list;
+}
+
+%%
+
+begin
+ : { arscp_prompt(); } ar_script
+ ;
+
+ar_script
+ : cmd_list
+ |
+ ;
+
+mod_list
+ : FNAME { $$ = arscp_mlist(NULL, $1); }
+ | mod_list separator FNAME { $$ = arscp_mlist($1, $3); }
+ ;
+
+separator
+ : COMMA
+ |
+ ;
+
+cmd_list
+ : rawcmd
+ | cmd_list rawcmd
+ ;
+
+rawcmd
+ : cmd EOL { arscp_prompt(); }
+ ;
+
+cmd
+ : addlib_cmd
+ | addmod_cmd
+ | clear_cmd
+ | create_cmd
+ | delete_cmd
+ | directory_cmd
+ | end_cmd
+ | extract_cmd
+ | list_cmd
+ | open_cmd
+ | replace_cmd
+ | verbose_cmd
+ | save_cmd
+ | invalid_cmd
+ | empty_cmd
+ | error
+ ;
+
+addlib_cmd
+ : ADDLIB FNAME LP mod_list RP { arscp_addlib($2, $4); }
+ | ADDLIB FNAME { arscp_addlib($2, NULL); }
+ ;
+
+addmod_cmd
+ : ADDMOD mod_list { arscp_addmod($2); }
+ ;
+
+clear_cmd
+ : CLEAR { arscp_clear(); }
+ ;
+
+create_cmd
+ : CREATE FNAME { arscp_create(NULL, $2); }
+ ;
+
+delete_cmd
+ : DELETE mod_list { arscp_delete($2); }
+ ;
+
+directory_cmd
+ : DIRECTORY FNAME { arscp_dir($2, NULL, NULL); }
+ | DIRECTORY FNAME LP mod_list RP { arscp_dir($2, $4, NULL); }
+ | DIRECTORY FNAME LP mod_list RP FNAME { arscp_dir($2, $4, $6); }
+ ;
+
+end_cmd
+ : END { arscp_end(EXIT_SUCCESS); }
+ ;
+
+extract_cmd
+ : EXTRACT mod_list { arscp_extract($2); }
+ ;
+
+list_cmd
+ : LIST { arscp_list(); }
+ ;
+
+open_cmd
+ : OPEN FNAME { arscp_open($2); }
+ ;
+
+replace_cmd
+ : REPLACE mod_list { arscp_replace($2); }
+ ;
+
+save_cmd
+ : SAVE { arscp_save(); }
+ ;
+
+verbose_cmd
+ : VERBOSE { verbose = !verbose; }
+ ;
+
+empty_cmd
+ :
+ ;
+
+invalid_cmd
+ : FNAME { yyerror(NULL); }
+ ;
+
+%%
+
+/* ARGSUSED */
+static void
+yyerror(const char *s)
+{
+
+ (void) s;
+ printf("Syntax error in archive script, line %d\n", lineno);
+}
+
+/*
+ * The arscp_open() function will first open an archive and check its
+ * validity. If the archive format is valid, it will call
+ * arscp_create() to create a temporary copy of the archive.
+ */
+static void
+arscp_open(char *fname)
+{
+ struct archive *a;
+ struct archive_entry *entry;
+ int r;
+
+ if ((a = archive_read_new()) == NULL)
+ bsdar_errc(bsdar, 0, "archive_read_new failed");
+ archive_read_support_format_ar(a);
+ AC(archive_read_open_filename(a, fname, DEF_BLKSZ));
+ if ((r = archive_read_next_header(a, &entry)))
+ bsdar_warnc(bsdar, 0, "%s", archive_error_string(a));
+ AC(archive_read_close(a));
+ ACV(archive_read_free(a));
+ if (r != ARCHIVE_OK)
+ return;
+ arscp_create(fname, fname);
+}
+
+/*
+ * Create an archive.
+ *
+ * If the parameter 'in' is NULL (the 'CREATE' command), a new empty
+ * archive will be created. If the parameter 'in' is not NULL (the
+ * 'OPEN' command), the resulting archive will be a modified version
+ * of the existing archive.
+ */
+static void
+arscp_create(char *in, char *out)
+{
+ struct archive *a;
+ int ifd, ofd;
+
+ /* Delete the previously created temporary archive, if any. */
+ if (tmpac) {
+ if (unlink(tmpac) < 0)
+ bsdar_errc(bsdar, errno, "unlink failed");
+ free(tmpac);
+ }
+
+ tmpac = strdup(TEMPLATE);
+ if (tmpac == NULL)
+ bsdar_errc(bsdar, errno, "strdup failed");
+ if ((ofd = mkstemp(tmpac)) < 0)
+ bsdar_errc(bsdar, errno, "mkstemp failed");
+
+ if (in) {
+ /*
+ * The 'OPEN' command creates a temporary copy of the
+ * input archive.
+ */
+ if ((ifd = open(in, O_RDONLY)) < 0 ||
+ elftc_copyfile(ifd, ofd) < 0) {
+ bsdar_warnc(bsdar, errno, "'OPEN' failed");
+ (void) close(ofd);
+ if (ifd != -1)
+ (void) close(ifd);
+ return;
+ }
+ (void) close(ifd);
+ (void) close(ofd);
+ } else {
+ /*
+ * The 'CREATE' command creates an "empty" archive (an
+ * archive consisting only of the archive header).
+ */
+ if ((a = archive_write_new()) == NULL)
+ bsdar_errc(bsdar, 0, "archive_write_new failed");
+ archive_write_set_format_ar_svr4(a);
+ AC(archive_write_open_fd(a, ofd));
+ AC(archive_write_close(a));
+ ACV(archive_write_free(a));
+ }
+
+ /* Override the previous target, if any. */
+ if (target)
+ free(target);
+
+ target = out;
+ bsdar->filename = tmpac;
+}
+
+/*
+ * Add all modules of an archive to the current archive. If the
+ * parameter 'list' is not NULL, only those modules specified by
+ * 'list' will be added.
+ */
+static void
+arscp_addlib(char *archive, struct list *list)
+{
+
+ if (!arscp_target_exist())
+ return;
+ arscp_mlist2argv(list);
+ bsdar->addlib = archive;
+ ar_write_archive(bsdar, 'A');
+ arscp_free_argv();
+ arscp_free_mlist(list);
+}
+
+/*
+ * Add modules to the current archive.
+ */
+static void
+arscp_addmod(struct list *list)
+{
+
+ if (!arscp_target_exist())
+ return;
+ arscp_mlist2argv(list);
+ ar_write_archive(bsdar, 'q');
+ arscp_free_argv();
+ arscp_free_mlist(list);
+}
+
+/*
+ * Delete modules from the current archive.
+ */
+static void
+arscp_delete(struct list *list)
+{
+
+ if (!arscp_target_exist())
+ return;
+ arscp_mlist2argv(list);
+ ar_write_archive(bsdar, 'd');
+ arscp_free_argv();
+ arscp_free_mlist(list);
+}
+
+/*
+ * Extract modules from the current archive.
+ */
+static void
+arscp_extract(struct list *list)
+{
+
+ if (!arscp_target_exist())
+ return;
+ arscp_mlist2argv(list);
+ ar_read_archive(bsdar, 'x');
+ arscp_free_argv();
+ arscp_free_mlist(list);
+}
+
+/*
+ * List the contents of an archive (simple mode).
+ */
+static void
+arscp_list(void)
+{
+
+ if (!arscp_target_exist())
+ return;
+ bsdar->argc = 0;
+ bsdar->argv = NULL;
+ /* Always verbose. */
+ bsdar->options |= AR_V;
+ ar_read_archive(bsdar, 't');
+ bsdar->options &= ~AR_V;
+}
+
+/*
+ * List the contents of an archive (advanced mode).
+ */
+static void
+arscp_dir(char *archive, struct list *list, char *rlt)
+{
+ FILE *out;
+
+ /* If rlt != NULL, redirect the output to it. */
+ out = NULL;
+ if (rlt) {
+ out = bsdar->output;
+ if ((bsdar->output = fopen(rlt, "w")) == NULL)
+ bsdar_errc(bsdar, errno, "fopen %s failed", rlt);
+ }
+
+ bsdar->filename = archive;
+ if (list)
+ arscp_mlist2argv(list);
+ else {
+ bsdar->argc = 0;
+ bsdar->argv = NULL;
+ }
+ if (verbose)
+ bsdar->options |= AR_V;
+ ar_read_archive(bsdar, 't');
+ bsdar->options &= ~AR_V;
+
+ if (rlt) {
+ if (fclose(bsdar->output) == EOF)
+ bsdar_errc(bsdar, errno, "fclose %s failed", rlt);
+ bsdar->output = out;
+ free(rlt);
+ }
+ free(archive);
+ bsdar->filename = tmpac;
+ arscp_free_argv();
+ arscp_free_mlist(list);
+}
+
+
+/*
+ * Replace modules in the current archive.
+ */
+static void
+arscp_replace(struct list *list)
+{
+
+ if (!arscp_target_exist())
+ return;
+ arscp_mlist2argv(list);
+ ar_write_archive(bsdar, 'r');
+ arscp_free_argv();
+ arscp_free_mlist(list);
+}
+
+/*
+ * Rename the temporary archive to the target archive.
+ */
+static void
+arscp_save(void)
+{
+ mode_t mask;
+
+ if (target) {
+ if (rename(tmpac, target) < 0)
+ bsdar_errc(bsdar, errno, "rename failed");
+ /*
+ * Because mkstemp() creates temporary files with mode
+ * 0600, we set target archive's mode as per the
+ * process umask.
+ */
+ mask = umask(0);
+ umask(mask);
+ if (chmod(target, 0666 & ~mask) < 0)
+ bsdar_errc(bsdar, errno, "chmod failed");
+ free(tmpac);
+ free(target);
+ tmpac = NULL;
+ target= NULL;
+ bsdar->filename = NULL;
+ } else
+ bsdar_warnc(bsdar, 0, "no open output archive");
+}
+
+/*
+ * Discard the contents of the current archive. This is achieved by
+ * invoking the 'CREATE' cmd on the current archive.
+ */
+static void
+arscp_clear(void)
+{
+ char *new_target;
+
+ if (target) {
+ new_target = strdup(target);
+ if (new_target == NULL)
+ bsdar_errc(bsdar, errno, "strdup failed");
+ arscp_create(NULL, new_target);
+ }
+}
+
+/*
+ * Quit ar(1). Note that the 'END' cmd will not 'SAVE' the current
+ * archive before exiting.
+ */
+static void
+arscp_end(int eval)
+{
+
+ if (target)
+ free(target);
+ if (tmpac) {
+ if (unlink(tmpac) == -1)
+ bsdar_errc(bsdar, errno, "unlink %s failed", tmpac);
+ free(tmpac);
+ }
+
+ exit(eval);
+}
+
+/*
+ * Check if a target was specified, i.e, whether an 'OPEN' or 'CREATE'
+ * had been issued by the user.
+ */
+static int
+arscp_target_exist(void)
+{
+
+ if (target)
+ return (1);
+
+ bsdar_warnc(bsdar, 0, "no open output archive");
+ return (0);
+}
+
+/*
+ * Construct the list of modules.
+ */
+static struct list *
+arscp_mlist(struct list *list, char *str)
+{
+ struct list *l;
+
+ l = malloc(sizeof(*l));
+ if (l == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ l->str = str;
+ l->next = list;
+
+ return (l);
+}
+
+/*
+ * Calculate the length of an mlist.
+ */
+static int
+arscp_mlist_len(struct list *list)
+{
+ int len;
+
+ for(len = 0; list; list = list->next)
+ len++;
+
+ return (len);
+}
+
+/*
+ * Free the space allocated for a module list.
+ */
+static void
+arscp_free_mlist(struct list *list)
+{
+ struct list *l;
+
+ /* Note: list->str was freed in arscp_free_argv(). */
+ for(; list; list = l) {
+ l = list->next;
+ free(list);
+ }
+}
+
+/*
+ * Convert a module list to an 'argv' array.
+ */
+static void
+arscp_mlist2argv(struct list *list)
+{
+ char **argv;
+ int i, n;
+
+ n = arscp_mlist_len(list);
+ argv = malloc(n * sizeof(*argv));
+ if (argv == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+
+ /* Note that module names are stored in reverse order. */
+ for(i = n - 1; i >= 0; i--, list = list->next) {
+ if (list == NULL)
+ bsdar_errc(bsdar, errno, "invalid mlist");
+ argv[i] = list->str;
+ }
+
+ bsdar->argc = n;
+ bsdar->argv = argv;
+}
+
+/*
+ * Free the space allocated for an argv array and its elements.
+ */
+static void
+arscp_free_argv(void)
+{
+ int i;
+
+ for(i = 0; i < bsdar->argc; i++)
+ free(bsdar->argv[i]);
+
+ free(bsdar->argv);
+}
+
+/*
+ * Show a prompt if we are in interactive mode.
+ */
+static void
+arscp_prompt(void)
+{
+
+ if (interactive) {
+ printf("AR >");
+ fflush(stdout);
+ }
+}
+
+/*
+ * The main function implementing script mode.
+ */
+void
+ar_mode_script(struct bsdar *ar)
+{
+
+ bsdar = ar;
+ interactive = isatty(fileno(stdin));
+ while(yyparse()) {
+ if (!interactive)
+ arscp_end(EXIT_FAILURE);
+ }
+
+ /* Script ends without END */
+ arscp_end(EXIT_SUCCESS);
+}
diff --git a/contrib/elftoolchain/ar/ar.1 b/contrib/elftoolchain/ar/ar.1
new file mode 100644
index 0000000..2bfa908
--- /dev/null
+++ b/contrib/elftoolchain/ar/ar.1
@@ -0,0 +1,603 @@
+.\" Copyright (c) 2007,2009-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: ar.1 3195 2015-05-12 17:22:19Z emaste $
+.\"
+.Dd December 10, 2012
+.Os
+.Dt AR 1
+.Sh NAME
+.Nm ar
+.Nd manage archives
+.Sh SYNOPSIS
+.Nm
+.Fl d
+.Op Fl T
+.Op Fl f
+.Op Fl j
+.Op Fl v
+.Op Fl z
+.Ar archive
+.Ar
+.Nm
+.Fl m
+.Op Fl T
+.Op Fl a Ar position-after
+.Op Fl b Ar position-before
+.Op Fl f
+.Op Fl i Ar position-before
+.Op Fl j
+.Op Fl s | Fl S
+.Op Fl z
+.Ar archive
+.Ar
+.Nm
+.Fl p
+.Op Fl T
+.Op Fl f
+.Op Fl v
+.Ar archive
+.Op Ar
+.Nm
+.Fl q
+.Op Fl T
+.Op Fl c
+.Op Fl D
+.Op Fl f
+.Op Fl F Ar flavor | Fl -flavor Ar flavor
+.Op Fl s | Fl S
+.Op Fl v
+.Op Fl z
+.Ar archive
+.Ar
+.Nm
+.Fl r
+.Op Fl T
+.Op Fl a Ar position-after
+.Op Fl b Ar position-before
+.Op Fl c
+.Op Fl D
+.Op Fl f
+.Op Fl F Ar flavor | Fl -flavor Ar flavor
+.Op Fl i Ar position-before
+.Op Fl j
+.Op Fl s | Fl S
+.Op Fl u
+.Op Fl v
+.Op Fl z
+.Ar archive
+.Ar
+.Nm
+.Fl s
+.Op Fl D
+.Op Fl j
+.Op Fl z
+.Ar archive
+.Nm
+.Fl t
+.Op Fl f
+.Op Fl T
+.Op Fl v
+.Ar archive
+.Op Ar
+.Nm
+.Fl x
+.Op Fl C
+.Op Fl T
+.Op Fl f
+.Op Fl o
+.Op Fl u
+.Op Fl v
+.Ar archive
+.Op Ar
+.Nm
+.Fl M
+.Nm
+.Fl V
+.Sh DESCRIPTION
+The
+.Nm
+utility creates and maintains groups of files combined into an
+archive.
+Once an archive has been created, new files can be added to it, and
+existing files can be extracted, deleted or replaced.
+.Pp
+Files are named in the archive by their last file name component,
+so if a file referenced by a path containing a
+.Dq /
+is archived, it will be named by the last component of the path.
+Similarly when matching paths listed on the command line against
+file names stored in the archive, only the last component of the
+path will be compared.
+.Pp
+The normal use of
+.Nm
+is for the creation and maintenance of libraries suitable for use
+with the link editor
+.Xr ld 1 ,
+although it is not restricted to this purpose.
+The
+.Nm
+utility can create and manage an archive symbol table (see
+.Xr ar 5 )
+used to speed up link editing operations.
+If a symbol table is present in an archive, it will be
+kept up-to-date by subsequent operations on the archive.
+.Sh OPTIONS
+The
+.Nm
+utility supports the following options:
+.Bl -tag -width indent
+.It Fl a Ar member-after
+When used with option
+.Fl m
+this option specifies that the archive members specified by
+arguments
+.Ar
+are moved to after the archive member named by argument
+.Ar member-after .
+When used with option
+.Fl r
+this option specifies that the files specified by arguments
+.Ar
+are added after the archive member named by argument
+.Ar member-after .
+.It Fl b Ar member-before
+When used with option
+.Fl m
+this option specifies that the archive members specified by
+arguments
+.Ar
+are moved to before the archive member named by argument
+.Ar member-before .
+When used with option
+.Fl r
+this option specifies that the files specified by arguments
+.Ar
+are added before the archive member named by argument
+.Ar member-before .
+.It Fl c
+Suppress the informational message printed when a new archive is
+created using the
+.Fl r
+and
+.Fl q
+options.
+.It Fl C
+Prevent extracted files from replacing like-named files
+in the file system.
+.It Fl d
+Delete the members named by arguments
+.Ar
+from the archive specified by argument
+.Ar archive .
+The archive's symbol table, if present, is updated to reflect
+the new contents of the archive.
+.It Fl D
+When used in combination with the
+.Fl r
+or
+.Fl q
+option, insert 0's instead of the real mtime, uid and gid values
+and 0644 instead of file mode from the members named by arguments
+.Ar .
+This ensures that checksums on the resulting archives are reproducible
+when member contents are identical.
+.It Fl f
+Synonymous with option
+.Fl T .
+.It Fl F Ar flavor | Fl -flavor Ar flavor
+Create archives with the specified archive format.
+Legal values for argument
+.Ar flavor
+are:
+.Bl -tag -width indent -compact
+.It Ar bsd
+Create BSD format archives.
+.It Ar gnu
+An alias for
+.Ar svr4 .
+.It Ar svr4
+Create SVR4 format archives.
+.El
+If this option is not specified,
+.Nm
+will create archives using the SVR4 format.
+.It Fl i Ar member-before
+Synonymous with option
+.Fl b .
+.It Fl j
+This option is accepted for compatibility with the
+.Tn FreeBSD
+version of the
+.Nm
+utility, but is ignored.
+.It Fl l
+This option is accepted for compatibility with GNU
+.Xr ar 1 ,
+but is ignored.
+.It Fl m
+Move archive members specified by arguments
+.Ar
+within the archive.
+If a position has been specified by one of the
+.Fl a ,
+.Fl b
+or
+.Fl i
+options, the members are moved to before or after the specified
+position.
+If no position has been specified, the specified members are moved
+to the end of the archive.
+If the archive has a symbol table, it is updated to reflect the
+new contents of the archive.
+.It Fl M
+Read and execute MRI librarian commands from standard input.
+The commands understood by the
+.Nm
+utility are described in the section
+.Sx "MRI Librarian Commands" .
+.It Fl o
+Preserve the original modification times of members when extracting
+them.
+.It Fl p
+Write the contents of the specified archive members named by
+arguments
+.Ar
+to standard output.
+If no members were specified, the contents of all the files in the
+archive are written in the order they appear in the archive.
+.It Fl q
+Append the files specified by arguments
+.Ar
+to the archive specified by argument
+.Ar archive
+without checking if the files already exist in the archive.
+The archive symbol table will be updated as needed.
+If the file specified by the argument
+.Ar archive
+does not already exist, a new archive will be created.
+.It Fl r
+Replace (add) the files specified by arguments
+.Ar
+in the archive specified by argument
+.Ar archive ,
+creating the archive if necessary.
+Replacing existing members will not change the order of members within
+the archive.
+If a file named in arguments
+.Ar
+does not exist, existing members in the archive that match that
+name are not changed.
+New files are added to the end of the archive unless one of the
+positioning options
+.Fl a ,
+.Fl b
+or
+.Fl i
+is specified.
+The archive symbol table, if it exists, is updated to reflect the
+new state of the archive.
+.It Fl s
+Add an archive symbol table (see
+.Xr ar 5 )
+to the archive specified by argument
+.Ar archive .
+Invoking
+.Nm
+with the
+.Fl s
+option alone is equivalent to invoking
+.Xr ranlib 1 .
+.It Fl S
+Do not generate an archive symbol table.
+.It Fl t
+For
+.Nm ,
+list the files specified by arguments
+.Ar
+in the order in which they appear in the archive, one per line.
+If no files are specified, all files in the archive are listed.
+.It Fl T
+Use only the first fifteen characters of the archive member name or
+command line file name argument when naming archive members.
+.It Fl u
+Conditionally update the archive or extract members.
+When used with the
+.Fl r
+option, files named by arguments
+.Ar
+will be replaced in the archive if they are newer than their
+archived versions.
+When used with the
+.Fl x
+option, the members specified by arguments
+.Ar
+will be extracted only if they are newer than the corresponding
+files in the file system.
+.It Fl v
+Provide verbose output.
+When used with the
+.Fl d ,
+.Fl m ,
+.Fl q
+or
+.Fl x
+options,
+.Nm
+gives a file-by-file description of the archive modification being
+performed, which consists of three white-space separated fields:
+the option letter, a dash
+.Dq "-" ,
+and the file name.
+When used with the
+.Fl r
+option,
+.Nm
+displays the description as above, but the initial letter is an
+.Dq a
+if the file is added to the archive, or an
+.Dq r
+if the file replaces a file already in the archive.
+When used with the
+.Fl p
+option, the name of the file enclosed in
+.Dq <
+and
+.Dq >
+characters is written to standard output preceded by a single newline
+character and followed by two newline characters.
+The contents of the named file follow the file name.
+When used with the
+.Fl t
+option,
+.Nm
+displays eight whitespace separated fields:
+the file permissions as displayed by
+.Xr strmode 3 ,
+decimal user and group IDs separated by a slash (
+.Dq / Ns ) ,
+the file size in bytes, the file modification time in
+.Xr strftime 3
+format
+.Dq "%b %e %H:%M %Y" ,
+and the name of the file.
+.It Fl V
+Print a version identifier and exit.
+.It Fl x
+Extract archive members specified by arguments
+.Ar
+into the current directory.
+If no members have been specified, extract all members of the archive.
+If the file corresponding to an extracted member does not exist it
+will be created.
+If the file corresponding to an extracted member does exist, its owner
+and group will not be changed while its contents will be overwritten
+and its permissions will set to that entered in the archive.
+The file's access and modification time would be that of the time
+of extraction unless the
+.Fl o
+option was specified.
+.It Fl z
+This option is accepted for compatibility with the
+.Tn FreeBSD
+version of the
+.Nm
+utility, but is ignored.
+.El
+.Ss "MRI Librarian Commands"
+If the
+.Fl M
+option is specified, the
+.Nm
+utility will read and execute commands from its standard input.
+If standard input is a terminal, the
+.Nm
+utility will display the prompt
+.Dq Li "AR >"
+before reading a line, and will continue operation even if errors are
+encountered.
+If standard input is not a terminal, the
+.Nm
+utility will not display a prompt and will terminate execution on
+encountering an error.
+.Pp
+Each input line contains a single command.
+Words in an input line are separated by whitespace characters.
+The first word of the line is the command, the remaining words are
+the arguments to the command.
+The command word may be specified in either case.
+Arguments may be separated by commas or blanks.
+.Pp
+Empty lines are allowed and are ignored.
+Long lines are continued by ending them with the
+.Dq Li +
+character.
+.Pp
+The
+.Dq Li *
+and
+.Dq Li "\;"
+characters start a comment.
+Comments extend till the end of the line.
+.Pp
+When executing an MRI librarian script the
+.Nm
+utility works on a temporary copy of an archive.
+Changes to the copy are made permanent using the
+.Ic save
+command.
+.Pp
+Commands understood by the
+.Nm
+utility are:
+.Bl -tag -width indent
+.It Ic addlib Ar archive | Ic addlib Ar archive Pq Ar member Oo Li , Ar member Oc Ns ...
+Add the contents of the archive named by argument
+.Ar archive
+to the current archive.
+If specific members are named using the arguments
+.Ar member ,
+then those members are added to the current archive.
+If no members are specified, the entire contents of the archive
+are added to the current archive.
+.It Ic addmod Ar member Oo Li , Ar member Oc Ns ...
+Add the files named by arguments
+.Ar member
+to the current archive.
+.It Ic clear
+Discard all the contents of the current archive.
+.It Ic create Ar archive
+Create a new archive named by the argument
+.Ar archive ,
+and makes it the current archive.
+If the named archive already exists, it will be overwritten
+when the
+.Ic save
+command is issued.
+.It Ic delete Ar module Oo Li , Ar member Oc Ns ...
+Delete the modules named by the arguments
+.Ar member
+from the current archive.
+.It Ic directory Ar archive Po Ar member Oo Li , Ar member Oc Ns ... Pc Op Ar outputfile
+List each named module in the archive.
+The format of the output depends on the verbosity setting set using
+the
+.Ic verbose
+command.
+Output is sent to standard output, or to the file specified by
+argument
+.Ar outputfile .
+.It Ic end
+Exit successfully from the
+.Nm
+utility.
+Any unsaved changes to the current archive will be discarded.
+.It Ic extract Ar member Oo Li , Ar member Oc Ns ...
+Extract the members named by the arguments
+.Ar member
+from the current archive.
+.It Ic list
+Display the contents of the current archive in verbose style.
+.It Ic open Ar archive
+Open the archive named by argument
+.Ar archive
+and make it the current archive.
+.It Ic replace Ar member Oo Li , Ar member Oc Ns ...
+Replace named members in the current archive with the files specified
+by arguments
+.Ar member .
+The files must be present in the current directory and the named
+modules must already exist in the current archive.
+.It Ic save
+Commit all changes to the current archive.
+.It Ic verbose
+Toggle the verbosity of the
+.Ic directory
+command.
+.El
+.Sh EXAMPLES
+To create a new archive
+.Pa ex.a
+containing three files
+.Pa ex1.o ,
+.Pa ex2.o
+and
+.Pa ex3.o ,
+use:
+.Dl "ar -rc ex.a ex1.o ex2.o ex3.o"
+.Pp
+To add an archive symbol table to an existing archive
+.Pa ex.a ,
+use:
+.Dl "ar -s ex.a"
+.Pp
+To delete file
+.Pa ex1.o
+from archive
+.Pa ex.a ,
+use:
+.D1 "ar -d ex.a ex1.o"
+.Pp
+To verbosely list the contents of archive
+.Pa ex.a ,
+use:
+.D1 "ar -tv ex.a"
+.Pp
+To create a new archive
+.Pa ex.a
+containing the files
+.Pa ex1.o ,
+and
+.Pa ex2.o ,
+using MRI librarian commands, use the following script:
+.Bd -literal -offset indent
+create ex.a * specify the output archive
+addmod ex1.o ex2.o * add modules
+save * save pending changes
+end * exit the utility
+.Ed
+.Sh DIAGNOSTICS
+.Ex -std
+.Sh SEE ALSO
+.Xr ld 1 ,
+.Xr ranlib 1 ,
+.Xr archive 3 ,
+.Xr elf 3 ,
+.Xr strftime 3 ,
+.Xr strmode 3 ,
+.Xr ar 5
+.Sh STANDARDS COMPLIANCE
+The
+.Nm
+utility's support for the
+.Fl a ,
+.Fl b ,
+.Fl c ,
+.Fl i ,
+.Fl m ,
+.Fl p ,
+.Fl q ,
+.Fl r ,
+.Fl s ,
+.Fl t ,
+.Fl u ,
+.Fl v ,
+.Fl C
+and
+.Fl T
+options is believed to be compliant with
+.St -p1003.2 .
+.Sh HISTORY
+An
+.Nm
+command first appeared in AT&T UNIX Version 1.
+In
+.Fx 8.0 ,
+.An Kai Wang Aq Mt kaiw@FreeBSD.org
+reimplemented
+.Nm
+using the
+.Lb libarchive
+and the
+.Lb libelf .
diff --git a/contrib/elftoolchain/ar/ar.5 b/contrib/elftoolchain/ar/ar.5
new file mode 100644
index 0000000..45961e0
--- /dev/null
+++ b/contrib/elftoolchain/ar/ar.5
@@ -0,0 +1,327 @@
+.\" Copyright (c) 2010 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 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: ar.5 3182 2015-04-10 16:08:10Z emaste $
+.\"
+.Dd November 28, 2010
+.Os
+.Dt AR 5
+.Sh NAME
+.Nm ar
+.Nd archive file format for
+.Xr ar 1
+and
+.Xr ranlib 1
+.Sh SYNOPSIS
+.In ar.h
+.Sh DESCRIPTION
+.Xr ar 1
+archives are created and managed by the
+.Xr ar 1
+and
+.Xr ranlib 1
+utilities.
+These archives are typically used during program development to
+hold libraries of program objects.
+An
+.Xr ar 1
+archive is contained in a single operating system file.
+.Pp
+This manual page documents two variants of the
+.Xr ar 1
+archive format: the BSD archive format, and the SVR4/GNU archive
+format.
+.Pp
+In both variants the archive file starts with an identifying byte
+sequence of the seven ASCII characters
+.Sq Li "!<arch>"
+followed by a ASCII linefeed character
+.Po
+see the constant
+.Dq ARMAG
+in the header file
+.In ar.h
+.Pc .
+.Pp
+Archive members follow the initial identifying byte sequence.
+Each archive member is prefixed by a fixed size header describing the
+file attributes associated with the member.
+.Ss "Archive Headers"
+An archive header describes the file attributes for the archive member that
+follows it.
+The
+.Xr ar 5
+format only supports a limited number of attributes: the file name,
+the file creation time stamp, the uid and gid of the creator, the file
+mode and the file size.
+.Pp
+Archive headers are placed at an even byte offset in the archive file.
+If the data for an archive member ends at an odd byte offset, then a
+padding byte with value 0x0A is used to position the next archive
+header on an even byte offset.
+.Pp
+An archive header comprises the following fixed sized fields:
+.Bl -tag -width "Li ar_name"
+.It Ar ar_name
+(16 bytes) The file name of the archive member.
+The format of this field varies between the BSD and SVR4/GNU formats and
+is described in more detail in the section
+.Sx "Representing File Names"
+below.
+.It Ar ar_date
+(12 bytes) The file modification time for the member in seconds since the
+epoch, encoded as a decimal number.
+.It Ar ar_uid
+(6 bytes) The uid associated with the archive member, encoded as a
+decimal number.
+.It Ar ar_gid
+(6 bytes) The gid associated with the archive member, encoded as a
+decimal number.
+.It Ar ar_mode
+(8 bytes) The file mode for the archive member, encoded as an octal
+number.
+.It Ar ar_size
+(10 bytes) In the SVR4/GNU archive format this field holds the size in
+bytes of the archive member, encoded as a decimal number.
+In the BSD archive format, for short file names, this field
+holds the size in bytes of the archive member, encoded as a decimal
+number.
+For long file names
+.Po
+see
+.Sx "Representing File Names"
+below
+.Pc ,
+the field contains the combined size of the
+archive member and its file name, encoded as a decimal number.
+.It Ar ar_fmag
+(2 bytes) This field holds 2 bytes with values 0x96 and 0x0A
+respectively, marking the end of the header.
+.El
+.Pp
+Unused bytes in the fields of an archive header are set to the value
+0x20.
+.Ss "Representing File Names"
+The BSD and SVR4/GNU variants use different schemes for encoding file
+names for members.
+.Bl -tag -width "SVR4/GNU"
+.It "BSD"
+File names that are up to 16 bytes long and which do not contain
+embedded spaces are stored directly in the
+.Ar ar_name
+field of the archive header.
+File names that are either longer than 16 bytes or which contain
+embedded spaces are stored immediately after the archive header
+and the
+.Ar ar_name
+field of the archive header is set to the string
+.Dq "#1/"
+followed by a decimal representation of the number of bytes needed for
+the file name.
+In addition, the
+.Ar ar_size
+field of the archive header is set to the decimal representation of
+the combined sizes of the archive member and the file name.
+The file contents of the member follows the file name without further
+padding.
+.Pp
+As an example, if the file name for a member was
+.Dq "A B"
+and its contents was the string
+.Dq "C D" ,
+then the
+.Ar ar_name
+field of the header would contain
+.Dq Li "#1/3" ,
+the
+.Ar ar_size
+field of the header would contain
+.Dq Li 6 ,
+and the bytes immediately following the header would be 0x41, 0x20,
+0x42, 0x43, 0x20 and 0x44
+.Po
+ASCII
+.Dq "A BC D"
+.Pc .
+.It "SVR4/GNU"
+File names that are up to 15 characters long are stored directly in the
+.Ar ar_name
+field of the header, terminated by a
+.Dq Li /
+character.
+.Pp
+If the file name is larger than would fit in space for the
+.Ar ar_name
+field, then the actual file name is kept in the archive
+string table
+.Po
+see
+.Sx "Archive String Tables"
+below
+.Pc ,
+and the decimal offset of the file name in the string table is stored
+in the
+.Ar ar_name
+field, prefixed by a
+.Dq Li /
+character.
+.Pp
+As an example, if the real file name has been stored at offset 768 in
+the archive string table, the
+.Ar ar_name
+field of the header will contain the string
+.Dq /768 .
+.El
+.Ss "Special Archive Members"
+The following archive members are special.
+.Bl -tag -width indent
+.It Dq Li /
+In the SVR4/GNU variant of the archive format, the archive member with
+name
+.Dq Li /
+denotes an archive symbol table.
+If present, this member will be the very first member in the
+archive.
+.It Dq Li //
+In the SVR4/GNU variant of the archive format, the archive member with
+name
+.Dq Li //
+denotes the archive string table.
+This special member is used to hold filenames that do not fit in the
+file name field of the header
+.Po
+see
+.Sx "Representing File Names"
+above
+.Pc .
+If present, this member immediately follows the archive symbol table
+if an archive symbol table is present, or is the first member otherwise.
+.It Dq Li "__.SYMDEF"
+This special member contains the archive symbol table in the BSD
+variant of the archive format.
+If present, this member will be the very first member in the
+archive.
+.El
+.Ss "Archive String Tables"
+An archive string table is used in the SVR4/GNU archive format to hold
+file names that are too large to fit into the constraints of the
+.Ar ar_name
+field of the archive header.
+An archive string table contains a sequence of file names.
+Each file name in the archive string table is terminated by the
+byte sequence 0x2F, 0x0A
+.Po
+the ASCII string
+.Dq "/\en"
+.Pc .
+No padding is used to separate adjacent file names.
+.Ss "Archive Symbol Tables"
+Archive symbol tables are used to speed up link editing by providing a
+mapping between the program symbols defined in the archive
+and the corresponding archive members.
+Archive symbol tables are managed by the
+.Xr ranlib 1
+utility.
+.Pp
+The format of archive symbol tables is as follows:
+.Bl -tag -width "SVR4/GNU"
+.It BSD
+In the BSD archive format, the archive symbol table comprises
+of two parts: a part containing an array of
+.Vt "struct ranlib"
+descriptors, followed by a part containing a symbol string table.
+The sizes and layout of the structures that make up a BSD format
+archive symbol table are machine dependent.
+.Pp
+The part containing
+.Vt "struct ranlib"
+descriptors begins with a field containing the size in bytes of the
+array of
+.Vt "struct ranlib"
+descriptors encoded as a C
+.Vt long
+value.
+.Pp
+The array of
+.Vt "struct ranlib"
+descriptors follows the size field.
+Each
+.Vt "struct ranlib"
+descriptor describes one symbol.
+.Pp
+A
+.Vt "struct ranlib"
+descriptor comprises two fields:
+.Bl -tag -width "Ar ran_strx" -compact
+.It Ar ran_strx
+.Pq C Vt long
+This field contains the zero-based offset of the symbol name in the
+symbol string table.
+.It Ar ran_off
+.Pq C Vt long
+This field is the file offset to the archive header for the archive
+member defining the symbol.
+.El
+.Pp
+The part containing the symbol string table begins with a field
+containing the size in bytes of the string table, encoded as a C
+.Vt long
+value.
+This string table follows the size field, and contains
+NUL-terminated strings for the symbols in the symbol table.
+.It SVR4/GNU
+In the SVR4/GNU archive format, the archive symbol table starts with a
+4-byte binary value containing the number of entries contained in the
+archive symbol table.
+This count of entries is stored most significant byte first.
+.Pp
+Next, there are
+.Ar count
+4-byte numbers, each stored most significant byte first.
+Each number is a binary offset to the archive header for the member in
+the archive file for the corresponding symbol table entry.
+.Pp
+After the binary offset values, there are
+.Ar count
+NUL-terminated strings in sequence, holding the symbol names for
+the corresponding symbol table entries.
+.El
+.Sh STANDARDS COMPLIANCE
+The
+.Xr ar 1
+archive format is not currently specified by a standard.
+.Pp
+This manual page documents the
+.Xr ar 1
+archive formats used by the
+.Bx 4.4
+and
+.Ux SVR4
+operating system releases.
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr ld 1 ,
+.Xr ranlib 1 ,
+.Xr elf 3 ,
+.Xr elf_getarsym 3 ,
+.Xr elf_rand 3
diff --git a/contrib/elftoolchain/ar/ar.c b/contrib/elftoolchain/ar/ar.c
new file mode 100644
index 0000000..ceecbd9
--- /dev/null
+++ b/contrib/elftoolchain/ar/ar.c
@@ -0,0 +1,433 @@
+/*-
+ * Copyright (c) 2007 Kai Wang
+ * Copyright (c) 2007 Tim Kientzle
+ * Copyright (c) 2007 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
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Hugh Smith at The University of Guelph.
+ *
+ * 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 the University 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 REGENTS 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 REGENTS 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 <sys/types.h>
+#include <archive.h>
+#include <errno.h>
+#include <getopt.h>
+#include <libelftc.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "ar.h"
+
+ELFTC_VCSID("$Id: ar.c 3183 2015-04-10 16:18:42Z emaste $");
+
+enum options
+{
+ OPTION_HELP
+};
+
+static struct option longopts[] =
+{
+ {"flavor", required_argument, NULL, 'F'},
+ {"help", no_argument, NULL, OPTION_HELP},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+};
+
+static void bsdar_usage(void);
+static void ranlib_usage(void);
+static void set_mode(struct bsdar *bsdar, char opt);
+static void only_mode(struct bsdar *bsdar, const char *opt,
+ const char *valid_modes);
+static void bsdar_version(void);
+
+int
+main(int argc, char **argv)
+{
+ struct bsdar *bsdar, bsdar_storage;
+ char *arcmd, *argv1_saved;
+ size_t len;
+ int i, opt;
+
+ bsdar = &bsdar_storage;
+ memset(bsdar, 0, sizeof(*bsdar));
+
+ arcmd = argv1_saved = NULL;
+ bsdar->output = stdout;
+
+ if ((bsdar->progname = ELFTC_GETPROGNAME()) == NULL)
+ bsdar->progname = "ar";
+
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ bsdar_errc(bsdar, 0, "ELF library initialization failed: %s",
+ elf_errmsg(-1));
+
+ /*
+ * Act like ranlib if our name ends in "ranlib"; this
+ * accommodates names like "arm-freebsd7.1-ranlib",
+ * "bsdranlib", etc.
+ */
+ len = strlen(bsdar->progname);
+ if (len >= strlen("ranlib") &&
+ strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) {
+ while ((opt = getopt_long(argc, argv, "tDV", longopts,
+ NULL)) != -1) {
+ switch(opt) {
+ case 't':
+ /* Ignored. */
+ break;
+ case 'D':
+ bsdar->options |= AR_D;
+ break;
+ case 'V':
+ bsdar_version();
+ break;
+ case OPTION_HELP:
+ ranlib_usage();
+ default:
+ ranlib_usage();
+ }
+ }
+ argv += optind;
+ argc -= optind;
+
+ if (*argv == NULL)
+ ranlib_usage();
+
+ bsdar->options |= AR_S;
+ for (;(bsdar->filename = *argv++) != NULL;)
+ ar_write_archive(bsdar, 's');
+
+ exit(EXIT_SUCCESS);
+ } else {
+ if (argc < 2)
+ bsdar_usage();
+
+ /*
+ * Tack on a leading '-', for old-style usage.
+ */
+ if (*argv[1] != '-') {
+ argv1_saved = argv[1];
+ len = strlen(argv[1]) + 2;
+ if ((arcmd = malloc(len)) == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ (void) snprintf(arcmd, len, "-%s", argv[1]);
+ argv[1] = arcmd;
+ }
+ }
+
+ while ((opt = getopt_long(argc, argv, "abCcdDfF:ijlMmopqrSsTtuVvxz",
+ longopts, NULL)) != -1) {
+ switch(opt) {
+ case 'a':
+ bsdar->options |= AR_A;
+ break;
+ case 'b':
+ case 'i':
+ bsdar->options |= AR_B;
+ break;
+ case 'C':
+ bsdar->options |= AR_CC;
+ break;
+ case 'c':
+ bsdar->options |= AR_C;
+ break;
+ case 'd':
+ set_mode(bsdar, opt);
+ break;
+ case 'D':
+ bsdar->options |= AR_D;
+ break;
+ case 'F':
+ if (!strcasecmp(optarg, "svr4") ||
+ !strcasecmp(optarg, "gnu"))
+ bsdar->options &= ~AR_BSD;
+ else if (!strcasecmp(optarg, "bsd"))
+ bsdar->options |= AR_BSD;
+ else
+ bsdar_usage();
+ break;
+ case 'f':
+ case 'T':
+ bsdar->options |= AR_TR;
+ break;
+ case 'j':
+ /* ignored */
+ break;
+ case 'l':
+ /* ignored, for GNU ar comptibility */
+ break;
+ case 'M':
+ set_mode(bsdar, opt);
+ break;
+ case 'm':
+ set_mode(bsdar, opt);
+ break;
+ case 'o':
+ bsdar->options |= AR_O;
+ break;
+ case 'p':
+ set_mode(bsdar, opt);
+ break;
+ case 'q':
+ set_mode(bsdar, opt);
+ break;
+ case 'r':
+ set_mode(bsdar, opt);
+ break;
+ case 'S':
+ bsdar->options |= AR_SS;
+ break;
+ case 's':
+ bsdar->options |= AR_S;
+ break;
+ case 't':
+ set_mode(bsdar, opt);
+ break;
+ case 'u':
+ bsdar->options |= AR_U;
+ break;
+ case 'V':
+ bsdar_version();
+ break;
+ case 'v':
+ bsdar->options |= AR_V;
+ break;
+ case 'x':
+ set_mode(bsdar, opt);
+ break;
+ case 'z':
+ /* ignored */
+ break;
+ case OPTION_HELP:
+ bsdar_usage();
+ default:
+ bsdar_usage();
+ }
+ }
+
+ /* Restore argv[1] if we had modified it. */
+ if (arcmd != NULL) {
+ argv[1] = argv1_saved;
+ free(arcmd);
+ arcmd = argv1_saved = NULL;
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (*argv == NULL && bsdar->mode != 'M')
+ bsdar_usage();
+
+ if (bsdar->options & AR_A && bsdar->options & AR_B)
+ bsdar_errc(bsdar, 0,
+ "only one of -a and -[bi] options allowed");
+
+ if (bsdar->options & AR_J && bsdar->options & AR_Z)
+ bsdar_errc(bsdar, 0,
+ "only one of -j and -z options allowed");
+
+ if (bsdar->options & AR_S && bsdar->options & AR_SS)
+ bsdar_errc(bsdar, 0,
+ "only one of -s and -S options allowed");
+
+ if (bsdar->options & (AR_A | AR_B)) {
+ if (*argv == NULL)
+ bsdar_errc(bsdar, 0,
+ "no position operand specified");
+ if ((bsdar->posarg = basename(*argv)) == NULL)
+ bsdar_errc(bsdar, errno,
+ "basename failed");
+ argc--;
+ argv++;
+ }
+
+ if (bsdar->options & AR_A)
+ only_mode(bsdar, "-a", "mqr");
+ if (bsdar->options & AR_B)
+ only_mode(bsdar, "-b", "mqr");
+ if (bsdar->options & AR_C)
+ only_mode(bsdar, "-c", "qr");
+ if (bsdar->options & AR_CC)
+ only_mode(bsdar, "-C", "x");
+ if (bsdar->options & AR_D)
+ only_mode(bsdar, "-D", "qr");
+ if (bsdar->options & AR_O)
+ only_mode(bsdar, "-o", "x");
+ if (bsdar->options & AR_SS)
+ only_mode(bsdar, "-S", "mqr");
+ if (bsdar->options & AR_U)
+ only_mode(bsdar, "-u", "qrx");
+
+ if (bsdar->mode == 'M') {
+ ar_mode_script(bsdar);
+ exit(EXIT_SUCCESS);
+ }
+
+ if ((bsdar->filename = *argv) == NULL)
+ bsdar_usage();
+
+ bsdar->argc = --argc;
+ bsdar->argv = ++argv;
+
+ if ((!bsdar->mode || strchr("ptx", bsdar->mode)) &&
+ bsdar->options & AR_S) {
+ ar_write_archive(bsdar, 's');
+ if (!bsdar->mode)
+ exit(EXIT_SUCCESS);
+ }
+
+ switch(bsdar->mode) {
+ case 'd': case 'm': case 'q': case 'r':
+ ar_write_archive(bsdar, bsdar->mode);
+ break;
+
+ case 'p': case 't': case 'x':
+ ar_read_archive(bsdar, bsdar->mode);
+ break;
+ default:
+ bsdar_usage();
+ /* NOTREACHED */
+ }
+
+ for (i = 0; i < bsdar->argc; i++)
+ if (bsdar->argv[i] != NULL)
+ bsdar_warnc(bsdar, 0, "%s: not found in archive",
+ bsdar->argv[i]);
+
+ exit(EXIT_SUCCESS);
+}
+
+static void
+set_mode(struct bsdar *bsdar, char opt)
+{
+
+ if (bsdar->mode != '\0' && bsdar->mode != opt)
+ bsdar_errc(bsdar, 0, "Can't specify both -%c and -%c",
+ opt, bsdar->mode);
+ bsdar->mode = opt;
+}
+
+static void
+only_mode(struct bsdar *bsdar, const char *opt, const char *valid_modes)
+{
+
+ if (strchr(valid_modes, bsdar->mode) == NULL)
+ bsdar_errc(bsdar, 0, "Option %s is not permitted in mode -%c",
+ opt, bsdar->mode);
+}
+
+#define AR_USAGE_MESSAGE "\
+Usage: %s <command> [options] archive file...\n\
+ Manage archives.\n\n\
+ Where <command> is one of:\n\
+ -d Delete members from the archive.\n\
+ -m Move archive members within the archive.\n\
+ -p Write the contents of members to standard output.\n\
+ -q Append files to an archive.\n\
+ -r Replace (add) files to an archive.\n\
+ -s Add an archive symbol to an archive.\n\
+ -t List files in an archive.\n\
+ -x Extract members from an archive.\n\
+ -M Execute MRI librarian commands.\n\
+ -V Print a version identifier and exit.\n\n\
+ Options:\n\
+ -a MEMBER Add members after the specified member.\n\
+ -b MEMBER | -i MEMBER\n\
+ Add members before the specified member.\n\
+ -c Do not print a message when creating a new archive.\n\
+ -f | -T Only use the first fifteen characters of the member name.\n\
+ -j (This option is accepted, but is ignored).\n\
+ -l (This option is accepted, but is ignored).\n\
+ -o Preserve modification times when extracting members.\n\
+ -u Conditionally update or extract members.\n\
+ -v Be verbose.\n\
+ -z (This option is accepted, but is ignored).\n\
+ -C Do not overwrite existing files in the file system.\n\
+ -D Use fixed metadata, for consistent archive checksums.\n\
+ -F FORMAT | --flavor=FORMAT\n\
+ Create archives with the specified format.\n\
+ -S Do not generate an archive symbol table.\n"
+
+static void
+bsdar_usage(void)
+{
+ (void) fprintf(stderr, AR_USAGE_MESSAGE, ELFTC_GETPROGNAME());
+ exit(EXIT_FAILURE);
+}
+
+#define RANLIB_USAGE_MESSAGE "\
+Usage: %s [options] archive...\n\
+ Update or create archive symbol tables.\n\n\
+ Options:\n\
+ -t (This option is accepted, but ignored).\n\
+ -D Use fixed metadata, for consistent archive checksums.\n\
+ -V Print a version identifier and exit.\n"
+
+static void
+ranlib_usage(void)
+{
+ (void)fprintf(stderr, RANLIB_USAGE_MESSAGE, ELFTC_GETPROGNAME());
+ exit(EXIT_FAILURE);
+}
+
+static void
+bsdar_version(void)
+{
+ (void)printf("%s (%s, %s)\n", ELFTC_GETPROGNAME(), archive_version_string(),
+ elftc_version());
+ exit(EXIT_SUCCESS);
+}
diff --git a/contrib/elftoolchain/ar/ar.h b/contrib/elftoolchain/ar/ar.h
new file mode 100644
index 0000000..a75b9a9
--- /dev/null
+++ b/contrib/elftoolchain/ar/ar.h
@@ -0,0 +1,143 @@
+/*-
+ * Copyright (c) 2007 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
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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: ar.h 2496 2012-04-24 02:33:40Z jkoshy $
+ */
+
+#include <libelf.h>
+
+#include "_elftc.h"
+
+/*
+ * ar(1) options.
+ */
+#define AR_A 0x0001 /* position-after */
+#define AR_B 0x0002 /* position-before */
+#define AR_C 0x0004 /* creating new archive */
+#define AR_CC 0x0008 /* do not overwrite when extracting */
+#define AR_J 0x0010 /* bzip2 compression */
+#define AR_O 0x0020 /* preserve original mtime when extracting */
+#define AR_S 0x0040 /* write archive symbol table */
+#define AR_SS 0x0080 /* do not write archive symbol table */
+#define AR_TR 0x0100 /* only keep first 15 chars for member name */
+#define AR_U 0x0200 /* only extract or update newer members.*/
+#define AR_V 0x0400 /* verbose mode */
+#define AR_Z 0x0800 /* gzip compression */
+#define AR_D 0x1000 /* insert dummy mode, mtime, uid and gid */
+#define AR_BSD 0x2000 /* use the BSD archive format */
+
+#define DEF_BLKSZ 10240 /* default block size */
+
+/* Special names. */
+
+#define AR_STRINGTAB_NAME_SVR4 "//"
+#define AR_SYMTAB_NAME_BSD "__.SYMDEF"
+#define AR_SYMTAB_NAME_SVR4 "/"
+
+/*
+ * Convenient wrapper for general libarchive error handling.
+ */
+#define AC(CALL) do { \
+ if ((CALL)) \
+ bsdar_errc(bsdar, 0, "%s", \
+ archive_error_string(a)); \
+} while (0)
+
+/*
+ * The 'ACV' wrapper is used for libarchive APIs that changed from
+ * returning 'void' to returning an 'int' in later versions of libarchive.
+ */
+#if ARCHIVE_VERSION_NUMBER >= 2000000
+#define ACV(CALL) AC(CALL)
+#else
+#define ACV(CALL) do { \
+ (CALL); \
+ } while (0)
+#endif
+
+/*
+ * In-memory representation of archive member(object).
+ */
+struct ar_obj {
+ Elf *elf; /* object file descriptor */
+ char *name; /* member name */
+ uid_t uid; /* user id */
+ gid_t gid; /* group id */
+ mode_t md; /* octal file permissions */
+ size_t size; /* member size */
+ time_t mtime; /* modification time */
+ dev_t dev; /* inode's device */
+ ino_t ino; /* inode's number */
+
+ TAILQ_ENTRY(ar_obj) objs;
+};
+
+/*
+ * Structure encapsulates the "global" data for "ar" program.
+ */
+struct bsdar {
+ const char *filename; /* archive name. */
+ const char *addlib; /* target of ADDLIB. */
+ const char *posarg; /* position arg for modifiers -a, -b. */
+ char mode; /* program mode */
+ int options; /* command line options */
+ FILE *output; /* default output stream */
+
+ const char *progname; /* program name */
+ int argc;
+ char **argv;
+
+ dev_t ar_dev; /* archive device. */
+ ino_t ar_ino; /* archive inode. */
+
+ /*
+ * Fields for the archive string table.
+ */
+ char *as; /* buffer for archive string table. */
+ size_t as_sz; /* current size of as table. */
+ size_t as_cap; /* capacity of as table buffer. */
+
+ /*
+ * Fields for the archive symbol table.
+ */
+ uint32_t s_cnt; /* current number of symbols. */
+ uint32_t *s_so; /* symbol offset table. */
+ size_t s_so_cap; /* capacity of so table buffer. */
+ char *s_sn; /* symbol name table */
+ size_t s_sn_cap; /* capacity of sn table buffer. */
+ size_t s_sn_sz; /* current size of sn table. */
+ /* Current member's offset (relative to the end of pseudo members.) */
+ off_t rela_off;
+
+ TAILQ_HEAD(, ar_obj) v_obj; /* object(member) list */
+};
+
+void ar_mode_script(struct bsdar *ar);
+void ar_read_archive(struct bsdar *_ar, int _mode);
+void ar_write_archive(struct bsdar *_ar, int _mode);
+void bsdar_errc(struct bsdar *, int _code, const char *fmt, ...);
+int bsdar_is_pseudomember(struct bsdar *_ar, const char *_name);
+const char *bsdar_strmode(mode_t m);
+void bsdar_warnc(struct bsdar *, int _code, const char *fmt, ...);
diff --git a/contrib/elftoolchain/ar/benchmark/acp.sh b/contrib/elftoolchain/ar/benchmark/acp.sh
new file mode 100755
index 0000000..11be68b
--- /dev/null
+++ b/contrib/elftoolchain/ar/benchmark/acp.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+# $Id: acp.sh 2086 2011-10-27 05:18:01Z jkoshy $
+
+# This script is adapted from Jan Psota's Tar Comparison Program(TCP).
+
+n=3 # number of repetitions
+AR="bsdar gnuar" # ar archivers to compare
+
+test $# -ge 2 || {
+ echo "usage: $0 source_dir where_to_place_archive [where_to_extract_it]"
+ exit 0
+}
+
+THISDIR=`/bin/pwd`
+src=$1
+dst=$2/acp.a
+ext=${3:-$2}/acptmp
+test -e $dst -o -e /tmp/acp \
+ && { echo "$dst or /tmp/acp exists, exiting"; exit 1; }
+mkdir -p $ext || exit 1
+
+show_result ()
+{
+ awk -vL="`du -k $dst`" '{printf "%s\t%s\t%s\%10.1d KB/s\n",
+$1, $3, $5, ($1>0?L/$1:0)}' /tmp/acp | sort | head -n 1
+}
+
+test -d $src || { echo "'$src' is not a directory"; exit 1; }
+
+# ar versions
+for ar in $AR; do echo -n "$ar: "; $ar -V | head -n 1;
+done
+
+echo
+echo "best time of $n repetitions"
+echo -n " src=$src, "
+echo -n "`du -sh $src | awk '{print $1}'`"
+echo -n " in "
+echo "`find $src | wc -l` files"
+echo " archive=$dst, extract to $ext"
+
+echo "program operation real user system speed"
+for op in "cru $dst $src/*" "t $dst" "x `basename $dst`"; do
+ for ar in $AR; do
+ echo -n "$ar "
+ echo $op | grep -q ^cr && echo -n "create "
+ echo $op | grep -q ^t && echo -n "list "
+ echo $op | grep -q ^x && echo -n "extract "
+ num=0
+ while [ $num -lt $n ]; do
+ echo $op | grep -q ^cr && rm -f $dst
+ echo $op | grep -q ^x && { rm -rf $ext; mkdir -p $ext
+ cp $dst $ext; cd $ext; }
+ sync
+ time $ar $op > /dev/null 2>> /tmp/acp
+ echo $op | grep -q ^x && cd $THISDIR
+ num=`expr $num + 1`
+ done
+ show_result
+ rm -rf /tmp/acp
+ done
+ echo
+done
+rm -rf $ext $dst
+rm -f /tmp/acp
diff --git a/contrib/elftoolchain/ar/os.Linux.mk b/contrib/elftoolchain/ar/os.Linux.mk
new file mode 100644
index 0000000..daed864
--- /dev/null
+++ b/contrib/elftoolchain/ar/os.Linux.mk
@@ -0,0 +1,9 @@
+.if ${OS_DISTRIBUTION} == "Ubuntu"
+.if ${OS_DISTRIBUTION_VERSION} >= 14
+# Ubuntu Trusty Tahr and later.
+
+# Use the --nounput option to flex(1), to prevent unused functions from
+# being generated.
+LFLAGS += --nounput
+.endif
+.endif
diff --git a/contrib/elftoolchain/ar/ranlib.1 b/contrib/elftoolchain/ar/ranlib.1
new file mode 100644
index 0000000..89ab4ab
--- /dev/null
+++ b/contrib/elftoolchain/ar/ranlib.1
@@ -0,0 +1,86 @@
+.\" Copyright (c) 2007,2009-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: ranlib.1 3195 2015-05-12 17:22:19Z emaste $
+.\"
+.Dd December 9, 2012
+.Os
+.Dt RANLIB 1
+.Sh NAME
+.Nm ranlib
+.Nd update archive symbol tables
+.Sh SYNOPSIS
+.Nm
+.Op Fl D
+.Op Fl t
+.Ar archive Ns ...
+.Nm
+.Fl V
+.Sh DESCRIPTION
+The
+.Nm ranlib
+utility is used to update an existing archive symbol table in an
+.Xr ar 1
+archive, or to add an archive symbol table to an archive lacking one.
+.Sh OPTIONS
+The
+.Nm
+utility supports the following options:
+.Bl -tag -width indent
+.It Fl D
+Use zeros for the mtime, uid and gid fields, and use mode 0644 for the
+file mode field for all archive member headers.
+This ensures that checksums on the resulting archives are reproducible
+when member contents are identical.
+.It Fl t
+This option is accepted, but is ignored.
+.It Fl V
+Print a version identifier and exit.
+.El
+.Sh EXAMPLES
+To update the archive symbol table for an archive
+.Pa lib.a ,
+use:
+.Dl "ranlib lib.a"
+.Sh DIAGNOSTICS
+.Ex -std
+.Sh SEE ALSO
+.Xr ar 1 ,
+.Xr ld 1 ,
+.Xr archive 3 ,
+.Xr elf 3 ,
+.Xr ar 5
+.Sh HISTORY
+The
+.Nm
+command first appeared in AT&T UNIX Version 7.
+.Pp
+In
+.Fx 8.0 ,
+.An Kai Wang Aq Mt kaiw@FreeBSD.org
+reimplemented
+.Nm
+using the
+.Lb libarchive
+and the
+.Lb libelf .
diff --git a/contrib/elftoolchain/ar/read.c b/contrib/elftoolchain/ar/read.c
new file mode 100644
index 0000000..08b3224
--- /dev/null
+++ b/contrib/elftoolchain/ar/read.c
@@ -0,0 +1,199 @@
+/*-
+ * Copyright (c) 2007 Kai Wang
+ * Copyright (c) 2007 Tim Kientzle
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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 <sys/stat.h>
+
+#include <archive.h>
+#include <archive_entry.h>
+#include <assert.h>
+#include <errno.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ar.h"
+
+ELFTC_VCSID("$Id: read.c 3180 2015-04-09 15:13:57Z emaste $");
+
+/*
+ * Handle read modes: 'x', 't' and 'p'.
+ */
+void
+ar_read_archive(struct bsdar *bsdar, int mode)
+{
+ FILE *out;
+ struct archive *a;
+ struct archive_entry *entry;
+ struct stat sb;
+ struct tm *tp;
+ const char *bname;
+ const char *name;
+ mode_t md;
+ size_t size;
+ time_t mtime;
+ uid_t uid;
+ gid_t gid;
+ char **av;
+ char buf[25];
+ char find;
+ int i, flags, r;
+
+ assert(mode == 'p' || mode == 't' || mode == 'x');
+
+ if ((a = archive_read_new()) == NULL)
+ bsdar_errc(bsdar, 0, "archive_read_new failed");
+ archive_read_support_format_ar(a);
+ AC(archive_read_open_filename(a, bsdar->filename, DEF_BLKSZ));
+
+ out = bsdar->output;
+
+ for (;;) {
+ r = archive_read_next_header(a, &entry);
+ if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
+ r == ARCHIVE_FATAL)
+ bsdar_warnc(bsdar, 0, "%s", archive_error_string(a));
+ if (r == ARCHIVE_EOF || r == ARCHIVE_FATAL)
+ break;
+ if (r == ARCHIVE_RETRY) {
+ bsdar_warnc(bsdar, 0, "Retrying...");
+ continue;
+ }
+
+ if (archive_format(a) == ARCHIVE_FORMAT_AR_BSD)
+ bsdar->options |= AR_BSD;
+ else
+ bsdar->options &= ~AR_BSD;
+
+ if ((name = archive_entry_pathname(entry)) == NULL)
+ break;
+
+ /* Skip pseudo members. */
+ if (bsdar_is_pseudomember(bsdar, name))
+ continue;
+
+ if (bsdar->argc > 0) {
+ find = 0;
+ for(i = 0; i < bsdar->argc; i++) {
+ av = &bsdar->argv[i];
+ if (*av == NULL)
+ continue;
+ if ((bname = basename(*av)) == NULL)
+ bsdar_errc(bsdar, errno,
+ "basename failed");
+ if (strcmp(bname, name) != 0)
+ continue;
+
+ *av = NULL;
+ find = 1;
+ break;
+ }
+ if (!find)
+ continue;
+ }
+
+ if (mode == 't') {
+ if (bsdar->options & AR_V) {
+ md = archive_entry_mode(entry);
+ uid = archive_entry_uid(entry);
+ gid = archive_entry_gid(entry);
+ size = archive_entry_size(entry);
+ mtime = archive_entry_mtime(entry);
+ (void)fprintf(out, "%s %6d/%-6d %8ju ",
+ bsdar_strmode(md) + 1, uid, gid,
+ (uintmax_t)size);
+ tp = localtime(&mtime);
+ (void)strftime(buf, sizeof(buf),
+ "%b %e %H:%M %Y", tp);
+ (void)fprintf(out, "%s %s", buf, name);
+ } else
+ (void)fprintf(out, "%s", name);
+ r = archive_read_data_skip(a);
+ if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY ||
+ r == ARCHIVE_FATAL) {
+ (void)fprintf(out, "\n");
+ bsdar_warnc(bsdar, 0, "%s",
+ archive_error_string(a));
+ }
+
+ if (r == ARCHIVE_FATAL)
+ break;
+
+ (void)fprintf(out, "\n");
+ } else {
+ /* mode == 'x' || mode = 'p' */
+ if (mode == 'p') {
+ if (bsdar->options & AR_V) {
+ (void)fprintf(out, "\n<%s>\n\n",
+ name);
+ fflush(out);
+ }
+ r = archive_read_data_into_fd(a, fileno(out));
+ } else {
+ /* mode == 'x' */
+ if (stat(name, &sb) != 0) {
+ if (errno != ENOENT) {
+ bsdar_warnc(bsdar, 0,
+ "stat %s failed",
+ bsdar->filename);
+ continue;
+ }
+ } else {
+ /* stat success, file exist */
+ if (bsdar->options & AR_CC)
+ continue;
+ if (bsdar->options & AR_U &&
+ archive_entry_mtime(entry) <=
+ sb.st_mtime)
+ continue;
+ }
+
+ if (bsdar->options & AR_V)
+ (void)fprintf(out, "x - %s\n", name);
+ /* Disallow absolute paths. */
+ if (name[0] == '/') {
+ bsdar_warnc(bsdar, 0,
+ "Absolute path '%s'", name);
+ continue;
+ }
+ /* Basic path security flags. */
+ flags = ARCHIVE_EXTRACT_SECURE_SYMLINKS |
+ ARCHIVE_EXTRACT_SECURE_NODOTDOT;
+ if (bsdar->options & AR_O)
+ flags |= ARCHIVE_EXTRACT_TIME;
+
+ r = archive_read_extract(a, entry, flags);
+ }
+
+ if (r)
+ bsdar_warnc(bsdar, 0, "%s",
+ archive_error_string(a));
+ }
+ }
+ AC(archive_read_close(a));
+ ACV(archive_read_free(a));
+}
diff --git a/contrib/elftoolchain/ar/util.c b/contrib/elftoolchain/ar/util.c
new file mode 100644
index 0000000..f22542e
--- /dev/null
+++ b/contrib/elftoolchain/ar/util.c
@@ -0,0 +1,184 @@
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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 <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ar.h"
+
+ELFTC_VCSID("$Id: util.c 3174 2015-03-27 17:13:41Z emaste $");
+
+static void bsdar_vwarnc(struct bsdar *, int code,
+ const char *fmt, va_list ap);
+static void bsdar_verrc(struct bsdar *bsdar, int code,
+ const char *fmt, va_list ap);
+
+static void
+bsdar_vwarnc(struct bsdar *bsdar, int code, const char *fmt, va_list ap)
+{
+
+ fprintf(stderr, "%s: warning: ", bsdar->progname);
+ vfprintf(stderr, fmt, ap);
+ if (code != 0)
+ fprintf(stderr, ": %s", strerror(code));
+ fprintf(stderr, "\n");
+}
+
+void
+bsdar_warnc(struct bsdar *bsdar, int code, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ bsdar_vwarnc(bsdar, code, fmt, ap);
+ va_end(ap);
+}
+
+static void
+bsdar_verrc(struct bsdar *bsdar, int code, const char *fmt, va_list ap)
+{
+
+ fprintf(stderr, "%s: fatal: ", bsdar->progname);
+ vfprintf(stderr, fmt, ap);
+ if (code != 0)
+ fprintf(stderr, ": %s", strerror(code));
+ fprintf(stderr, "\n");
+}
+
+void
+bsdar_errc(struct bsdar *bsdar, int code, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ bsdar_verrc(bsdar, code, fmt, ap);
+ va_end(ap);
+ exit(EXIT_FAILURE);
+}
+
+#define AR_STRMODE_SIZE 12
+const char *
+bsdar_strmode(mode_t m)
+{
+ static char buf[AR_STRMODE_SIZE];
+
+#if ELFTC_HAVE_STRMODE
+ /* Use the system's strmode(3). */
+ strmode(m, buf);
+ return buf;
+
+#else
+ char c;
+
+ /*
+ * The first character of the string denotes the type of the
+ * entry.
+ */
+ if (S_ISBLK(m))
+ c = 'b';
+ else if (S_ISCHR(m))
+ c = 'c';
+ else if (S_ISDIR(m))
+ c = 'd';
+#if defined(S_ISFIFO)
+ else if (S_ISFIFO(m))
+ c = 'p';
+#endif
+#if defined(S_ISLNK)
+ else if (S_ISLNK(m))
+ c = 'l';
+#endif
+ else if (S_ISREG(m))
+ c = '-';
+#if defined(S_ISSOCK)
+ else if (S_ISSOCK(m))
+ c = 's';
+#endif
+ else
+ c = '?';
+ buf[0] = c;
+
+ /* The next 3 characters show permissions for the owner. */
+ buf[1] = (m & S_IRUSR) ? 'r' : '-';
+ buf[2] = m & S_IWUSR ? 'w' : '-';
+ if (m & S_ISUID)
+ c = (m & S_IXUSR) ? 's' : 'S';
+ else
+ c = (m & S_IXUSR) ? 'x' : '-';
+ buf[3] = c;
+
+ /* The next 3 characters describe permissions for the group. */
+ buf[4] = (m & S_IRGRP) ? 'r' : '-';
+ buf[5] = m & S_IWGRP ? 'w' : '-';
+ if (m & S_ISGID)
+ c = (m & S_IXGRP) ? 's' : 'S';
+ else
+ c = (m & S_IXGRP) ? 'x' : '-';
+ buf[6] = c;
+
+
+ /* The next 3 characters describe permissions for others. */
+ buf[7] = (m & S_IROTH) ? 'r' : '-';
+ buf[8] = m & S_IWOTH ? 'w' : '-';
+ if (m & S_ISVTX) /* sticky bit */
+ c = (m & S_IXOTH) ? 't' : 'T';
+ else
+ c = (m & S_IXOTH) ? 'x' : '-';
+ buf[9] = c;
+
+ /* End the string with a blank and NUL-termination. */
+ buf[10] = ' ';
+ buf[11] = '\0';
+
+ return buf;
+#endif /* !ELTC_HAVE_STRMODE */
+}
+
+int
+bsdar_is_pseudomember(struct bsdar *bsdar, const char *name)
+{
+ /*
+ * The "__.SYMDEF" member is special in the BSD format
+ * variant.
+ */
+ if (bsdar->options & AR_BSD)
+ return (strcmp(name, AR_SYMTAB_NAME_BSD) == 0);
+ else
+ /*
+ * The names "/ " and "// " are special in the SVR4
+ * variant.
+ */
+ return (strcmp(name, AR_STRINGTAB_NAME_SVR4) == 0 ||
+ strcmp(name, AR_SYMTAB_NAME_SVR4) == 0);
+}
diff --git a/contrib/elftoolchain/ar/write.c b/contrib/elftoolchain/ar/write.c
new file mode 100644
index 0000000..90be5da
--- /dev/null
+++ b/contrib/elftoolchain/ar/write.c
@@ -0,0 +1,975 @@
+/*-
+ * Copyright (c) 2007 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
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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 <sys/stat.h>
+
+#include <archive.h>
+#include <archive_entry.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ar.h"
+
+ELFTC_VCSID("$Id: write.c 3183 2015-04-10 16:18:42Z emaste $");
+
+#define _ARMAG_LEN 8 /* length of the magic string */
+#define _ARHDR_LEN 60 /* length of the archive header */
+#define _INIT_AS_CAP 128 /* initial archive string table size */
+#define _INIT_SYMOFF_CAP (256*(sizeof(uint32_t))) /* initial so table size */
+#define _INIT_SYMNAME_CAP 1024 /* initial sn table size */
+#define _MAXNAMELEN_SVR4 15 /* max member name length in svr4 variant */
+#define _MAXNAMELEN_BSD 16 /* max member name length in bsd variant */
+#define _TRUNCATE_LEN 15 /* number of bytes to keep for member name */
+
+static void add_to_ar_str_table(struct bsdar *bsdar, const char *name);
+static void add_to_ar_sym_table(struct bsdar *bsdar, const char *name);
+static struct ar_obj *create_obj_from_file(struct bsdar *bsdar,
+ const char *name, time_t mtime);
+static void create_symtab_entry(struct bsdar *bsdar, Elf *e);
+static void free_obj(struct ar_obj *obj);
+static void insert_obj(struct bsdar *bsdar, struct ar_obj *obj,
+ struct ar_obj *pos);
+static void read_objs(struct bsdar *bsdar, const char *archive,
+ int checkargv);
+static void write_cleanup(struct bsdar *bsdar);
+static void write_data(struct bsdar *bsdar, struct archive *a,
+ const void *buf, size_t s);
+static void write_objs(struct bsdar *bsdar);
+
+/*
+ * Create an object from a file, and return the created object
+ * descriptor. Return NULL if either an error occurs, or if the '-u'
+ * option was specified and the member is not newer than the existing
+ * one in the archive.
+ */
+static struct ar_obj *
+create_obj_from_file(struct bsdar *bsdar, const char *name, time_t mtime)
+{
+ struct ar_obj *obj;
+ struct stat sb;
+ const char *bname;
+ char *tmpname;
+ int fd;
+
+ if (name == NULL)
+ return (NULL);
+
+ obj = malloc(sizeof(struct ar_obj));
+ if (obj == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+
+ obj->elf = NULL;
+
+ if ((fd = open(name, O_RDONLY, 0)) < 0) {
+ bsdar_warnc(bsdar, errno, "can't open file: %s", name);
+ free(obj);
+ return (NULL);
+ }
+
+ tmpname = strdup(name);
+ if ((bname = basename(tmpname)) == NULL)
+ bsdar_errc(bsdar, errno, "basename failed");
+ if (bsdar->options & AR_TR && strlen(bname) > _TRUNCATE_LEN) {
+ if ((obj->name = malloc(_TRUNCATE_LEN + 1)) == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ (void)strncpy(obj->name, bname, _TRUNCATE_LEN);
+ obj->name[_TRUNCATE_LEN] = '\0';
+ } else
+ if ((obj->name = strdup(bname)) == NULL)
+ bsdar_errc(bsdar, errno, "strdup failed");
+ free(tmpname);
+
+ if (fstat(fd, &sb) < 0) {
+ bsdar_warnc(bsdar, errno, "can't fstat file: %s", obj->name);
+ goto giveup;
+ }
+ if (!S_ISREG(sb.st_mode)) {
+ bsdar_warnc(bsdar, 0, "%s is not an ordinary file", obj->name);
+ goto giveup;
+ }
+
+ if (sb.st_dev == bsdar->ar_dev && sb.st_ino == bsdar->ar_ino) {
+ bsdar_warnc(bsdar, 0, "cannot add archive \"%s\" to itself",
+ obj->name);
+ goto giveup;
+ }
+
+ /*
+ * If the '-u' option is specified and member is not newer
+ * than the existing one, we should not replace the member.
+ * However, if mtime == 0, i.e., if nonexistent members are to
+ * be forcibly replaced, then the '-u' option is to be ignored.
+ */
+ if (mtime != 0 && bsdar->options & AR_U && sb.st_mtime <= mtime)
+ goto giveup;
+
+ /*
+ * When the '-D' option is specified, the mtime and UID/GID of
+ * the member will be set to 0, and the file mode will be set
+ * to 644. This ensures that checksums will match for two
+ * archives containing identical content.
+ */
+ if (bsdar->options & AR_D) {
+ obj->uid = 0;
+ obj->gid = 0;
+ obj->mtime = 0;
+ obj->md = S_IFREG | 0644;
+ } else {
+ obj->uid = sb.st_uid;
+ obj->gid = sb.st_gid;
+ obj->mtime = sb.st_mtime;
+ obj->md = sb.st_mode;
+ }
+ obj->size = sb.st_size;
+ obj->dev = sb.st_dev;
+ obj->ino = sb.st_ino;
+
+ if (obj->size == 0) {
+ return (obj);
+ }
+
+ if ((obj->elf = elf_open(fd)) == NULL) {
+ bsdar_warnc(bsdar, 0, "file initialization failed for %s: %s",
+ obj->name, elf_errmsg(-1));
+ goto giveup;
+ }
+
+ /*
+ * Read the object fully into memory and close its file
+ * descriptor.
+ */
+ if (elf_cntl(obj->elf, ELF_C_FDREAD) < 0) {
+ bsdar_warnc(bsdar, 0, "%s could not be read in: %s",
+ obj->name, elf_errmsg(-1));
+ goto giveup;
+ }
+
+ if (close(fd) < 0)
+ bsdar_errc(bsdar, errno, "close failed: %s",
+ obj->name);
+
+ return (obj);
+
+giveup:
+ if (obj->elf)
+ elf_end(obj->elf);
+
+ if (close(fd) < 0)
+ bsdar_errc(bsdar, errno, "close failed: %s",
+ obj->name);
+ free(obj->name);
+ free(obj);
+ return (NULL);
+}
+
+/*
+ * Free an object and its associated allocations.
+ */
+static void
+free_obj(struct ar_obj *obj)
+{
+ if (obj->elf)
+ elf_end(obj->elf);
+
+ free(obj->name);
+ free(obj);
+}
+
+/*
+ * Insert an object into a list, either before/after the 'pos' obj or
+ * at the end of the list.
+ */
+static void
+insert_obj(struct bsdar *bsdar, struct ar_obj *obj, struct ar_obj *pos)
+{
+ if (obj == NULL)
+ bsdar_errc(bsdar, 0, "try to insert a null obj");
+
+ if (pos == NULL || obj == pos)
+ /*
+ * If the object to move happens to be the position
+ * obj, or if there is no position obj, move the
+ * object to the end.
+ */
+ goto tail;
+
+ if (bsdar->options & AR_B) {
+ TAILQ_INSERT_BEFORE(pos, obj, objs);
+ return;
+ }
+ if (bsdar->options & AR_A) {
+ TAILQ_INSERT_AFTER(&bsdar->v_obj, pos, obj, objs);
+ return;
+ }
+
+tail:
+ TAILQ_INSERT_TAIL(&bsdar->v_obj, obj, objs);
+
+}
+
+/*
+ * Read objects from archive into the 'v_obj' list. Note that
+ * 'checkargv' is set when read_objs() is used to read objects from
+ * the target of 'ADDLIB' command in ar script mode; in this case the
+ * 'argv' array specifies the members that 'ADDLIB' is to operate on.
+ */
+static void
+read_objs(struct bsdar *bsdar, const char *archive, int checkargv)
+{
+ struct archive *a;
+ struct archive_entry *entry;
+ struct ar_obj *obj;
+ const char *name;
+ const char *bname;
+ char *buff;
+ char **av;
+ size_t size;
+ int i, r, find;
+
+ if ((a = archive_read_new()) == NULL)
+ bsdar_errc(bsdar, 0, "archive_read_new failed");
+ archive_read_support_format_ar(a);
+ AC(archive_read_open_filename(a, archive, DEF_BLKSZ));
+ for (;;) {
+ r = archive_read_next_header(a, &entry);
+ if (r == ARCHIVE_FATAL)
+ bsdar_errc(bsdar, 0, "%s", archive_error_string(a));
+ if (r == ARCHIVE_EOF)
+ break;
+ if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY)
+ bsdar_warnc(bsdar, 0, "%s", archive_error_string(a));
+ if (r == ARCHIVE_RETRY) {
+ bsdar_warnc(bsdar, 0, "Retrying...");
+ continue;
+ }
+
+ name = archive_entry_pathname(entry);
+
+ /*
+ * Skip pseudo members.
+ */
+ if (bsdar_is_pseudomember(bsdar, name))
+ continue;
+
+ /*
+ * If 'checkargv' is set, only read those members
+ * specified in argv.
+ */
+ if (checkargv && bsdar->argc > 0) {
+ find = 0;
+ for(i = 0; i < bsdar->argc; i++) {
+ av = &bsdar->argv[i];
+ if (*av == NULL)
+ continue;
+ if ((bname = basename(*av)) == NULL)
+ bsdar_errc(bsdar, errno,
+ "basename failed");
+ if (strcmp(bname, name) != 0)
+ continue;
+
+ *av = NULL;
+ find = 1;
+ break;
+ }
+ if (!find)
+ continue;
+ }
+
+ size = archive_entry_size(entry);
+
+ if (size > 0) {
+ if ((buff = malloc(size)) == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ if (archive_read_data(a, buff, size) != (ssize_t)size) {
+ bsdar_warnc(bsdar, 0, "%s",
+ archive_error_string(a));
+ free(buff);
+ continue;
+ }
+ } else
+ buff = NULL;
+
+ obj = malloc(sizeof(struct ar_obj));
+ if (obj == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ obj->elf = NULL;
+ if (buff) {
+ obj->elf = elf_openmemory(buff, size);
+ if (obj->elf == NULL) {
+ bsdar_warnc(bsdar, 0, "elf_openmemory() "
+ "failed for %s: %s", name,
+ elf_errmsg(-1));
+ free(buff);
+ free(obj);
+ continue;
+ }
+ }
+ if ((obj->name = strdup(name)) == NULL)
+ bsdar_errc(bsdar, errno, "strdup failed");
+ obj->size = size;
+ obj->uid = archive_entry_uid(entry);
+ obj->gid = archive_entry_gid(entry);
+ obj->md = archive_entry_mode(entry);
+ obj->mtime = archive_entry_mtime(entry);
+ obj->dev = 0;
+ obj->ino = 0;
+
+ TAILQ_INSERT_TAIL(&bsdar->v_obj, obj, objs);
+ }
+ AC(archive_read_close(a));
+ ACV(archive_read_free(a));
+}
+
+/*
+ * Write an archive.
+ */
+void
+ar_write_archive(struct bsdar *bsdar, int mode)
+{
+ struct ar_obj *nobj, *obj, *obj_temp, *pos;
+ struct stat sb;
+ const char *bname;
+ char **av;
+ int i;
+
+ TAILQ_INIT(&bsdar->v_obj);
+ nobj = NULL;
+ pos = NULL;
+ memset(&sb, 0, sizeof(sb));
+
+ assert(mode == 'A' || mode == 'd' || mode == 'm' || mode == 'q' ||
+ mode == 'r' || mode == 's');
+
+ /*
+ * Test if the specified archive exists, to determine
+ * whether we are creating a new archive.
+ */
+ if (stat(bsdar->filename, &sb) != 0) {
+ if (errno != ENOENT) {
+ bsdar_warnc(bsdar, 0, "stat %s failed",
+ bsdar->filename);
+ return;
+ }
+
+ /* We do not create archive in mode 'd', 'm' and 's'. */
+ if (mode != 'r' && mode != 'q') {
+ bsdar_warnc(bsdar, 0, "%s: no such file",
+ bsdar->filename);
+ return;
+ }
+
+ /* Issue a message if the '-c' option was not specified. */
+ if (!(bsdar->options & AR_C))
+ bsdar_warnc(bsdar, 0, "creating %s", bsdar->filename);
+ goto new_archive;
+ }
+
+ bsdar->ar_dev = sb.st_dev;
+ bsdar->ar_ino = sb.st_ino;
+
+ /*
+ * First read members from the existing archive.
+ */
+ read_objs(bsdar, bsdar->filename, 0);
+
+ /*
+ * For mode 's', no member will be moved, deleted or replaced.
+ */
+ if (mode == 's')
+ goto write_objs;
+
+ /*
+ * For mode 'q', we don't need to adjust existing members either.
+ * Also, -a, -b and -i are ignored in this mode. New members are
+ * always inserted at tail.
+ */
+ if (mode == 'q')
+ goto new_archive;
+
+ /*
+ * Mode 'A' adds the contents of another archive to the tail
+ * of current archive. Note that mode 'A' is a special mode
+ * for the 'ADDLIB' command in ar's script mode. Currently
+ * there is no option that invokes this function from ar's
+ * command line.
+ */
+ if (mode == 'A') {
+ /*
+ * Read objects from the target archive of the
+ * 'ADDLIB' command. If there are members specified in
+ * 'argv', read those members only, otherwise the
+ * entire archive will be read.
+ */
+ read_objs(bsdar, bsdar->addlib, 1);
+ goto write_objs;
+ }
+
+ /*
+ * Try to find the position member specified by user.
+ */
+ if (bsdar->options & AR_A || bsdar->options & AR_B) {
+ TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
+ if (strcmp(obj->name, bsdar->posarg) == 0) {
+ pos = obj;
+ break;
+ }
+ }
+
+ /*
+ * If we cannot find the position specified by the
+ * user, silently insert objects at the tail of the
+ * list.
+ */
+ if (pos == NULL)
+ bsdar->options &= ~(AR_A | AR_B);
+ }
+
+ for (i = 0; i < bsdar->argc; i++) {
+ av = &bsdar->argv[i];
+
+ TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) {
+ if ((bname = basename(*av)) == NULL)
+ bsdar_errc(bsdar, errno, "basename failed");
+ if (bsdar->options & AR_TR) {
+ if (strncmp(bname, obj->name, _TRUNCATE_LEN))
+ continue;
+ } else
+ if (strcmp(bname, obj->name) != 0)
+ continue;
+
+ if (mode == 'r') {
+ /*
+ * If the new member should not
+ * replace the old one, skip it.
+ */
+ nobj = create_obj_from_file(bsdar, *av,
+ obj->mtime);
+ if (nobj == NULL)
+ goto skip_obj;
+ }
+
+ if (bsdar->options & AR_V)
+ (void)fprintf(bsdar->output, "%c - %s\n",
+ mode, *av);
+
+ TAILQ_REMOVE(&bsdar->v_obj, obj, objs);
+ if (mode == 'd' || mode == 'r')
+ free_obj(obj);
+
+ if (mode == 'm')
+ insert_obj(bsdar, obj, pos);
+ if (mode == 'r')
+ insert_obj(bsdar, nobj, pos);
+
+ skip_obj:
+ *av = NULL;
+ break;
+ }
+
+ }
+
+new_archive:
+ /*
+ * When operating in mode 'r', directly add the specified
+ * objects which do not exist in current archive. When
+ * operating in mode 'q', all objects specified by the command
+ * line args are appended to the archive, without checking
+ * existing members in the archive.
+ */
+ for (i = 0; i < bsdar->argc; i++) {
+ av = &bsdar->argv[i];
+ if (*av != NULL && (mode == 'r' || mode == 'q')) {
+ nobj = create_obj_from_file(bsdar, *av, 0);
+ if (nobj != NULL)
+ insert_obj(bsdar, nobj, pos);
+ if (bsdar->options & AR_V && nobj != NULL)
+ (void)fprintf(bsdar->output, "a - %s\n", *av);
+ *av = NULL;
+ }
+ }
+
+write_objs:
+ write_objs(bsdar);
+ write_cleanup(bsdar);
+}
+
+/*
+ * Release memory.
+ */
+static void
+write_cleanup(struct bsdar *bsdar)
+{
+ struct ar_obj *obj, *obj_temp;
+
+ TAILQ_FOREACH_SAFE(obj, &bsdar->v_obj, objs, obj_temp) {
+ TAILQ_REMOVE(&bsdar->v_obj, obj, objs);
+ free_obj(obj);
+ }
+
+ free(bsdar->as);
+ free(bsdar->s_so);
+ free(bsdar->s_sn);
+ bsdar->as = NULL;
+ bsdar->s_so = NULL;
+ bsdar->s_sn = NULL;
+}
+
+/*
+ * Wrapper for archive_write_data().
+ */
+static void
+write_data(struct bsdar *bsdar, struct archive *a, const void *buf, size_t s)
+{
+ if (archive_write_data(a, buf, s) != (ssize_t)s)
+ bsdar_errc(bsdar, 0, "%s", archive_error_string(a));
+}
+
+/*
+ * Compute the size of the symbol table for an archive.
+ */
+static size_t
+bsdar_symtab_size(struct bsdar *bsdar)
+{
+ size_t sz;
+
+ if (bsdar->options & AR_BSD) {
+ /*
+ * A BSD style symbol table has two parts.
+ * Each part is preceded by its size in bytes,
+ * encoded as a C 'long'. In the first part,
+ * there are 's_cnt' entries, each entry being
+ * 2 'long's in size. The second part
+ * contains a string table.
+ */
+ sz = 2 * sizeof(long) + (bsdar->s_cnt * 2 * sizeof(long)) +
+ bsdar->s_sn_sz;
+ } else {
+ /*
+ * An SVR4 style symbol table comprises of a 32 bit
+ * number holding the number of entries, followed by
+ * that many 32-bit offsets, followed by a string
+ * table.
+ */
+ sz = sizeof(uint32_t) + bsdar->s_cnt * sizeof(uint32_t) +
+ bsdar->s_sn_sz;
+ }
+
+ return (sz);
+}
+
+static void
+write_svr4_symtab_entry(struct bsdar *bsdar, struct archive *a)
+{
+ int nr;
+ uint32_t i;
+
+ /* Translate offsets to big-endian form. */
+ for (i = 0; i < bsdar->s_cnt; i++)
+ bsdar->s_so[i] = htobe32(bsdar->s_so[i]);
+
+ nr = htobe32(bsdar->s_cnt);
+ write_data(bsdar, a, &nr, sizeof(uint32_t));
+ write_data(bsdar, a, bsdar->s_so, sizeof(uint32_t) *
+ bsdar->s_cnt);
+ write_data(bsdar, a, bsdar->s_sn, bsdar->s_sn_sz);
+}
+
+static void
+write_bsd_symtab_entry(struct bsdar *bsdar, struct archive *a)
+{
+ long br_sz, br_off, br_strx;
+ char *s;
+ uint32_t i;
+
+ /*
+ * Write out the size in the byte of the array of 'ranlib'
+ * descriptors to follow.
+ */
+
+ br_sz = (long) (bsdar->s_cnt * 2 * sizeof(long));
+ write_data(bsdar, a, &br_sz, sizeof(long));
+
+ /*
+ * Write out the array of 'ranlib' descriptors. Each
+ * descriptor comprises of (a) an offset into the following
+ * string table and (b) a file offset to the relevant member.
+ */
+ for (i = 0, s = bsdar->s_sn; i < bsdar->s_cnt; i++) {
+ br_strx = (long) (s - bsdar->s_sn);
+ br_off = (long) bsdar->s_so[i];
+ write_data(bsdar, a, &br_strx, sizeof(long));
+ write_data(bsdar, a, &br_off, sizeof(long));
+
+ /* Find the start of the next symbol in the string table. */
+ while (*s++ != '\0')
+ ;
+ }
+
+ /*
+ * Write out the size of the string table as a 'long',
+ * followed by the string table itself.
+ */
+ br_sz = (long) bsdar->s_sn_sz;
+ write_data(bsdar, a, &br_sz, sizeof(long));
+ write_data(bsdar, a, bsdar->s_sn, bsdar->s_sn_sz);
+}
+
+
+/*
+ * Write the resulting archive members.
+ */
+static void
+write_objs(struct bsdar *bsdar)
+{
+ struct ar_obj *obj;
+ struct archive *a;
+ struct archive_entry *entry;
+ size_t s_sz; /* size of archive symbol table. */
+ size_t pm_sz; /* size of pseudo members */
+ size_t namelen; /* size of member name. */
+ size_t obj_sz; /* size of object + extended header. */
+ int i;
+ char *buf;
+ const char *entry_name;
+
+ bsdar->rela_off = 0;
+
+ /*
+ * Create the archive symbol table and the archive string
+ * table, if needed.
+ */
+ TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
+ if (!(bsdar->options & AR_SS) && obj->elf != NULL)
+ create_symtab_entry(bsdar, obj->elf);
+
+ obj_sz = 0;
+ namelen = strlen(obj->name);
+ if (bsdar->options & AR_BSD) {
+ /* Account for the space used by the file name. */
+ if (namelen > _MAXNAMELEN_BSD ||
+ strchr(obj->name, ' '))
+ obj_sz += namelen;
+ } else if (namelen > _MAXNAMELEN_SVR4)
+ add_to_ar_str_table(bsdar, obj->name);
+
+ obj_sz += obj->size; /* add the actual object size */
+
+ /* Roundup the final size and add the header length. */
+ bsdar->rela_off += _ARHDR_LEN + obj_sz + (obj_sz & 1);
+ }
+
+ /*
+ * Pad the symbol name string table. It is treated specially
+ * because symbol name table should be padded by a '\0', and
+ * not '\n' as for normal members. The size of the 'sn' table
+ * includes the pad byte.
+ */
+ if (bsdar->s_cnt != 0 && bsdar->s_sn_sz % 2 != 0)
+ bsdar->s_sn[bsdar->s_sn_sz++] = '\0';
+
+ /*
+ * The archive string table is padded by a "\n" like a normal
+ * member. The difference is that the size of archive string
+ * table includes the pad byte, while normal members' size
+ * fields do not.
+ */
+ if (bsdar->as != NULL && bsdar->as_sz % 2 != 0)
+ bsdar->as[bsdar->as_sz++] = '\n';
+
+ /*
+ * If there is a symbol table, calculate the size of pseudo
+ * members, and convert previously stored relative offsets to
+ * absolute ones.
+ *
+ * absolute_offset = relative_offset + size_of_pseudo_members)
+ */
+
+ s_sz = bsdar_symtab_size(bsdar);
+ if (bsdar->s_cnt != 0) {
+ pm_sz = _ARMAG_LEN + (_ARHDR_LEN + s_sz);
+ if (bsdar->as != NULL) /* SVR4 archives only */
+ pm_sz += _ARHDR_LEN + bsdar->as_sz;
+ for (i = 0; (size_t) i < bsdar->s_cnt; i++)
+ bsdar->s_so[i] = bsdar->s_so[i] + pm_sz;
+ }
+
+ if ((a = archive_write_new()) == NULL)
+ bsdar_errc(bsdar, 0, "archive_write_new failed");
+
+ if (bsdar->options & AR_BSD)
+ archive_write_set_format_ar_bsd(a);
+ else
+ archive_write_set_format_ar_svr4(a);
+
+ AC(archive_write_open_filename(a, bsdar->filename));
+
+ /*
+ * Write the archive symbol table, if there is one. If
+ * options '-s' was explicitly specified or if we were invoked
+ * as 'ranlib', write the symbol table even if it is empty.
+ */
+ if ((bsdar->s_cnt != 0 && !(bsdar->options & AR_SS)) ||
+ bsdar->options & AR_S) {
+ if (bsdar->options & AR_BSD)
+ entry_name = AR_SYMTAB_NAME_BSD;
+ else
+ entry_name = AR_SYMTAB_NAME_SVR4;
+
+ entry = archive_entry_new();
+ archive_entry_copy_pathname(entry, entry_name);
+ if ((bsdar->options & AR_D) == 0)
+ archive_entry_set_mtime(entry, time(NULL), 0);
+ archive_entry_set_size(entry, s_sz);
+ AC(archive_write_header(a, entry));
+ if (bsdar->options & AR_BSD)
+ write_bsd_symtab_entry(bsdar, a);
+ else
+ write_svr4_symtab_entry(bsdar, a);
+ archive_entry_free(entry);
+ }
+
+ /* Write the archive string table, if any. */
+ if (bsdar->as != NULL) {
+ entry = archive_entry_new();
+ archive_entry_copy_pathname(entry, AR_STRINGTAB_NAME_SVR4);
+ archive_entry_set_size(entry, bsdar->as_sz);
+ AC(archive_write_header(a, entry));
+ write_data(bsdar, a, bsdar->as, bsdar->as_sz);
+ archive_entry_free(entry);
+ }
+
+ /* Write normal members. */
+ TAILQ_FOREACH(obj, &bsdar->v_obj, objs) {
+ if ((buf = elf_rawfile(obj->elf, NULL)) == NULL) {
+ bsdar_warnc(bsdar, 0, "elf_rawfile() failed: %s",
+ elf_errmsg(-1));
+ continue;
+ }
+
+ entry = archive_entry_new();
+ archive_entry_copy_pathname(entry, obj->name);
+ archive_entry_set_uid(entry, obj->uid);
+ archive_entry_set_gid(entry, obj->gid);
+ archive_entry_set_mode(entry, obj->md);
+ archive_entry_set_size(entry, obj->size);
+ archive_entry_set_mtime(entry, obj->mtime, 0);
+ archive_entry_set_dev(entry, obj->dev);
+ archive_entry_set_ino(entry, obj->ino);
+ archive_entry_set_filetype(entry, AE_IFREG);
+ AC(archive_write_header(a, entry));
+ write_data(bsdar, a, buf, obj->size);
+ archive_entry_free(entry);
+ }
+
+ AC(archive_write_close(a));
+ ACV(archive_write_free(a));
+}
+
+/*
+ * Extract global symbols from ELF binary members.
+ */
+static void
+create_symtab_entry(struct bsdar *bsdar, Elf *e)
+{
+ Elf_Scn *scn;
+ GElf_Shdr shdr;
+ GElf_Sym sym;
+ Elf_Data *data;
+ char *name;
+ size_t n, shstrndx;
+ int elferr, tabndx, len, i;
+
+ if (elf_kind(e) != ELF_K_ELF) {
+ /* Silently a ignore non-ELF member. */
+ return;
+ }
+ if (elf_getshstrndx(e, &shstrndx) == 0) {
+ bsdar_warnc(bsdar, 0, "elf_getshstrndx failed: %s",
+ elf_errmsg(-1));
+ return;
+ }
+
+ tabndx = -1;
+ scn = NULL;
+ while ((scn = elf_nextscn(e, scn)) != NULL) {
+ if (gelf_getshdr(scn, &shdr) != &shdr) {
+ bsdar_warnc(bsdar, 0,
+ "elf_getshdr failed: %s", elf_errmsg(-1));
+ continue;
+ }
+ if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL) {
+ bsdar_warnc(bsdar, 0,
+ "elf_strptr failed: %s", elf_errmsg(-1));
+ continue;
+ }
+ if (strcmp(name, ".strtab") == 0) {
+ tabndx = elf_ndxscn(scn);
+ break;
+ }
+ }
+ elferr = elf_errno();
+ if (elferr != 0)
+ bsdar_warnc(bsdar, 0, "elf_nextscn failed: %s",
+ elf_errmsg(elferr));
+ if (tabndx == -1) {
+ bsdar_warnc(bsdar, 0, "can't find .strtab section");
+ return;
+ }
+
+ scn = NULL;
+ while ((scn = elf_nextscn(e, scn)) != NULL) {
+ if (gelf_getshdr(scn, &shdr) != &shdr) {
+ bsdar_warnc(bsdar, 0, "elf_getshdr failed: %s",
+ elf_errmsg(-1));
+ continue;
+ }
+ if (shdr.sh_type != SHT_SYMTAB)
+ continue;
+
+ data = NULL;
+ n = 0;
+ while (n < shdr.sh_size &&
+ (data = elf_getdata(scn, data)) != NULL) {
+ len = data->d_size / shdr.sh_entsize;
+ for (i = 0; i < len; i++) {
+ if (gelf_getsym(data, i, &sym) != &sym) {
+ bsdar_warnc(bsdar, 0,
+ "gelf_getsym failed: %s",
+ elf_errmsg(-1));
+ continue;
+ }
+
+ /* Keep only global and weak symbols. */
+ if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL &&
+ GELF_ST_BIND(sym.st_info) != STB_WEAK)
+ continue;
+
+ /* Keep only defined symbols. */
+ if (sym.st_shndx == SHN_UNDEF)
+ continue;
+
+ if ((name = elf_strptr(e, tabndx,
+ sym.st_name)) == NULL) {
+ bsdar_warnc(bsdar, 0,
+ "elf_strptr failed: %s",
+ elf_errmsg(-1));
+ continue;
+ }
+
+ add_to_ar_sym_table(bsdar, name);
+ }
+ }
+ }
+ elferr = elf_errno();
+ if (elferr != 0)
+ bsdar_warnc(bsdar, 0, "elf_nextscn failed: %s",
+ elf_errmsg(elferr));
+}
+
+/*
+ * Append to the archive string table buffer.
+ */
+static void
+add_to_ar_str_table(struct bsdar *bsdar, const char *name)
+{
+
+ if (bsdar->as == NULL) {
+ bsdar->as_cap = _INIT_AS_CAP;
+ bsdar->as_sz = 0;
+ if ((bsdar->as = malloc(bsdar->as_cap)) == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ }
+
+ /*
+ * The space required for holding one member name in the 'as'
+ * table includes: strlen(name) + (1 for '/') + (1 for '\n') +
+ * (possibly 1 for padding).
+ */
+ while (bsdar->as_sz + strlen(name) + 3 > bsdar->as_cap) {
+ bsdar->as_cap *= 2;
+ bsdar->as = realloc(bsdar->as, bsdar->as_cap);
+ if (bsdar->as == NULL)
+ bsdar_errc(bsdar, errno, "realloc failed");
+ }
+ strncpy(&bsdar->as[bsdar->as_sz], name, strlen(name));
+ bsdar->as_sz += strlen(name);
+ bsdar->as[bsdar->as_sz++] = '/';
+ bsdar->as[bsdar->as_sz++] = '\n';
+}
+
+/*
+ * Append to the archive symbol table buffer.
+ */
+static void
+add_to_ar_sym_table(struct bsdar *bsdar, const char *name)
+{
+
+ if (bsdar->s_so == NULL) {
+ if ((bsdar->s_so = malloc(_INIT_SYMOFF_CAP)) ==
+ NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ bsdar->s_so_cap = _INIT_SYMOFF_CAP;
+ bsdar->s_cnt = 0;
+ }
+
+ if (bsdar->s_sn == NULL) {
+ if ((bsdar->s_sn = malloc(_INIT_SYMNAME_CAP)) == NULL)
+ bsdar_errc(bsdar, errno, "malloc failed");
+ bsdar->s_sn_cap = _INIT_SYMNAME_CAP;
+ bsdar->s_sn_sz = 0;
+ }
+
+ if (bsdar->s_cnt * sizeof(uint32_t) >= bsdar->s_so_cap) {
+ bsdar->s_so_cap *= 2;
+ bsdar->s_so = realloc(bsdar->s_so, bsdar->s_so_cap);
+ if (bsdar->s_so == NULL)
+ bsdar_errc(bsdar, errno, "realloc failed");
+ }
+ bsdar->s_so[bsdar->s_cnt] = bsdar->rela_off;
+ bsdar->s_cnt++;
+
+ /*
+ * The space required for holding one symbol name in the 'sn'
+ * table includes: strlen(name) + (1 for '\n') + (possibly 1
+ * for padding).
+ */
+ while (bsdar->s_sn_sz + strlen(name) + 2 > bsdar->s_sn_cap) {
+ bsdar->s_sn_cap *= 2;
+ bsdar->s_sn = realloc(bsdar->s_sn, bsdar->s_sn_cap);
+ if (bsdar->s_sn == NULL)
+ bsdar_errc(bsdar, errno, "realloc failed");
+ }
+ strncpy(&bsdar->s_sn[bsdar->s_sn_sz], name, strlen(name));
+ bsdar->s_sn_sz += strlen(name);
+ bsdar->s_sn[bsdar->s_sn_sz++] = '\0';
+}
diff --git a/contrib/elftoolchain/brandelf/Makefile b/contrib/elftoolchain/brandelf/Makefile
new file mode 100644
index 0000000..28ba3e0
--- /dev/null
+++ b/contrib/elftoolchain/brandelf/Makefile
@@ -0,0 +1,9 @@
+# $Id: Makefile 2066 2011-10-26 15:40:28Z jkoshy $
+
+TOP= ..
+
+PROG= brandelf
+WARNS?= 6
+LDADD= -lelftc -lelf
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
diff --git a/contrib/elftoolchain/brandelf/brandelf.1 b/contrib/elftoolchain/brandelf/brandelf.1
new file mode 100644
index 0000000..1c2e485
--- /dev/null
+++ b/contrib/elftoolchain/brandelf/brandelf.1
@@ -0,0 +1,151 @@
+.\" Copyright (c) 1997
+.\" John-Mark Gurney. 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. Neither the name of the author nor the names of any co-contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY John-Mark Gurney 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: src/usr.bin/brandelf/brandelf.1,v 1.17 2007/03/09 14:36:18 ru Exp $
+.\" $Id: brandelf.1 3195 2015-05-12 17:22:19Z emaste $
+.\"
+.Dd October 27, 2014
+.Dt BRANDELF 1
+.Os
+.Sh NAME
+.Nm brandelf
+.Nd mark an ELF binary for a specific ABI
+.Sh SYNOPSIS
+.Nm
+.Op Fl V | Fl -version
+.Op Fl f Ar ELF_ABI_number
+.Op Fl h | Fl -help
+.Op Fl l
+.Op Fl t Ar brand
+.Op Fl v
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility marks an ELF binary to be run under a certain ABI.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl f Ar ELF_ABI_number
+Forces branding with the supplied ELF ABI number.
+Incompatible with the
+.Fl t
+option.
+These values are assigned by SCO/USL.
+.It Fl h | Fl -help
+Print a usage message and exit.
+.It Fl l
+Writes the list of all known ELF types to standard output.
+.It Fl t Ar brand
+Brands the given ELF binaries to be of the ABI specified by argument
+.Ar brand .
+Supported ABIs include
+.Dq Li 86Open ,
+.Dq Li AIX ,
+.Dq Li ARM ,
+.Dq Li AROS ,
+.Dq Li FreeBSD ,
+.Dq Li GNU ,
+.Dq Li HP/UX ,
+.Dq Li Hurd ,
+.Dq Li IRIX ,
+.Dq Li Linux
+(an alias for
+.Dq Li GNU ) ,
+.Dq Li Modesto ,
+.Dq Li NSK ,
+.Dq Li NetBSD ,
+.Dq Li None ,
+.Dq Li OpenBSD ,
+.Dq Li OpenVMS ,
+.Dq Li Standalone ,
+.Dq Li SVR4
+(an alias for
+.Dq Li None ) ,
+.Dq Li Solaris
+and
+.Dq Li Tru64 .
+.It Fl v
+This option is accepted for compatibility with other versions of
+.Nm ,
+but is otherwise ignored.
+.It Fl V | Fl -version
+Print a version identifier and exit.
+.El
+.Pp
+If the options
+.Fl f Ar ELF_ABI_number
+or
+.Fl t Ar brand
+were specified,
+.Nm
+will brand the files named by command-line arguments
+.Ar
+to be of type
+.Ar ELF_ABI_number
+or
+.Ar brand
+respectively.
+.Pp
+If neither of the
+.Fl f
+or
+.Fl t
+options were specified,
+.Nm
+will display the current branding for the files named by the arguments
+.Ar .
+.Sh EXIT STATUS
+Exit status is 0 on success, and 1 if the command
+fails if a file does not exist, is too short, fails to brand properly,
+or the brand requested is not one of the known types and the
+.Fl f
+option is not set.
+.Sh EXAMPLES
+The following is an example of a typical usage
+of the
+.Nm
+command:
+.Bd -literal -offset indent
+brandelf file
+brandelf -t GNU file
+.Ed
+.Sh SEE ALSO
+.Rs
+.%A The Santa Cruz Operation, Inc.
+.%T System V Application Binary Interface
+.%D April 29, 1998 (DRAFT)
+.%O http://www.sco.com/developer/devspecs/
+.Re
+.Sh HISTORY
+The
+.Nm
+manual page first appeared in
+.Fx 2.2 .
+.Sh AUTHORS
+This manual page was written by
+.An John-Mark Gurney Aq Mt gurney_j@efn.org .
diff --git a/contrib/elftoolchain/brandelf/brandelf.c b/contrib/elftoolchain/brandelf/brandelf.c
new file mode 100644
index 0000000..5f5e631
--- /dev/null
+++ b/contrib/elftoolchain/brandelf/brandelf.c
@@ -0,0 +1,311 @@
+/*-
+ * Copyright (c) 2008 Hyogeol Lee
+ * Copyright (c) 2000, 2001 David O'Brien
+ * Copyright (c) 1996 Søren Schmidt
+ * 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <getopt.h>
+#include <libelf.h>
+#include <libelftc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: brandelf.c 3174 2015-03-27 17:13:41Z emaste $");
+
+static int elftype(const char *);
+static const char *iselftype(int);
+static void printelftypes(void);
+static void printversion(void);
+static void usage(void);
+
+struct ELFtypes {
+ const char *str;
+ int value;
+};
+/* XXX - any more types? */
+static struct ELFtypes elftypes[] = {
+ { "86Open", ELFOSABI_86OPEN },
+ { "AIX", ELFOSABI_AIX },
+ { "ARM", ELFOSABI_ARM },
+ { "AROS", ELFOSABI_AROS },
+ { "FreeBSD", ELFOSABI_FREEBSD },
+ { "GNU", ELFOSABI_GNU },
+ { "HP/UX", ELFOSABI_HPUX},
+ { "Hurd", ELFOSABI_HURD },
+ { "IRIX", ELFOSABI_IRIX },
+ { "Linux", ELFOSABI_GNU },
+ { "Modesto", ELFOSABI_MODESTO },
+ { "NSK", ELFOSABI_NSK },
+ { "NetBSD", ELFOSABI_NETBSD},
+ { "None", ELFOSABI_NONE},
+ { "OpenBSD", ELFOSABI_OPENBSD },
+ { "OpenVMS", ELFOSABI_OPENVMS },
+ { "Standalone", ELFOSABI_STANDALONE },
+ { "SVR4", ELFOSABI_NONE },
+ { "Solaris", ELFOSABI_SOLARIS },
+ { "Tru64", ELFOSABI_TRU64 }
+};
+
+static struct option brandelf_longopts[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
+};
+
+int
+main(int argc, char **argv)
+{
+ GElf_Ehdr ehdr;
+ Elf *elf;
+ Elf_Kind kind;
+ int type = ELFOSABI_NONE;
+ int retval = 0;
+ int ch, change = 0, force = 0, listed = 0;
+
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ errx(EXIT_FAILURE, "elf_version error");
+
+ while ((ch = getopt_long(argc, argv, "Vf:hlt:v", brandelf_longopts,
+ NULL)) != -1)
+ switch (ch) {
+ case 'f':
+ if (change)
+ errx(EXIT_FAILURE, "ERROR: the -f option is "
+ "incompatible with the -t option.");
+ force = 1;
+ type = atoi(optarg);
+ if (errno == ERANGE || type < 0 || type > 255) {
+ warnx("ERROR: invalid argument to option "
+ "-f: %s", optarg);
+ usage();
+ }
+ break;
+ case 'h':
+ usage();
+ break;
+ case 'l':
+ printelftypes();
+ listed = 1;
+ break;
+ case 'v':
+ /* This flag is ignored. */
+ break;
+ case 't':
+ if (force)
+ errx(EXIT_FAILURE, "the -t option is "
+ "incompatible with the -f option.");
+ if ((type = elftype(optarg)) == -1) {
+ warnx("ERROR: invalid ELF type '%s'", optarg);
+ usage();
+ }
+
+ change = 1;
+ break;
+ case 'V':
+ printversion();
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+ if (!argc) {
+ if (listed)
+ exit(0);
+ else {
+ warnx("no file(s) specified");
+ usage();
+ }
+ }
+
+ while (argc) {
+ int fd;
+
+ elf = NULL;
+
+ if ((fd = open(argv[0], (change || force) ? O_RDWR :
+ O_RDONLY, 0)) < 0) {
+ warn("error opening file %s", argv[0]);
+ retval = 1;
+ goto fail;
+ }
+
+ if ((elf = elf_begin(fd, (change || force) ? ELF_C_RDWR :
+ ELF_C_READ, NULL)) == NULL) {
+ warnx("elf_begin failed: %s", elf_errmsg(-1));
+ retval = 1;
+ goto fail;
+ }
+
+ if ((kind = elf_kind(elf)) != ELF_K_ELF) {
+ if (kind == ELF_K_AR)
+ warnx("file '%s' is an archive.", argv[0]);
+ else
+ warnx("file '%s' is not an ELF file.",
+ argv[0]);
+ retval = 1;
+ goto fail;
+ }
+
+ if (gelf_getehdr(elf, &ehdr) == NULL) {
+ warnx("gelf_getehdr: %s", elf_errmsg(-1));
+ retval = 1;
+ goto fail;
+ }
+
+ if (!change && !force) {
+ fprintf(stdout,
+ "File '%s' is of brand '%s' (%u).\n",
+ argv[0], iselftype(ehdr.e_ident[EI_OSABI]),
+ ehdr.e_ident[EI_OSABI]);
+ if (!iselftype(type)) {
+ warnx("ELF ABI Brand '%u' is unknown",
+ type);
+ printelftypes();
+ }
+ } else {
+
+ /*
+ * Keep the existing layout of the ELF object.
+ */
+ if (elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT) == 0) {
+ warnx("elf_flagelf failed: %s",
+ elf_errmsg(-1));
+ retval = 1;
+ goto fail;
+ }
+
+ /*
+ * Update the ABI type.
+ */
+ ehdr.e_ident[EI_OSABI] = type;
+ if (gelf_update_ehdr(elf, &ehdr) == 0) {
+ warnx("gelf_update_ehdr error: %s",
+ elf_errmsg(-1));
+ retval = 1;
+ goto fail;
+ }
+
+ /*
+ * Write back changes.
+ */
+ if (elf_update(elf, ELF_C_WRITE) == -1) {
+ warnx("elf_update error: %s", elf_errmsg(-1));
+ retval = 1;
+ goto fail;
+ }
+ }
+fail:
+
+ if (elf)
+ elf_end(elf);
+
+ if (fd >= 0 && close(fd) == -1) {
+ warnx("%s: close error", argv[0]);
+ retval = 1;
+ }
+
+ argc--;
+ argv++;
+ }
+
+ return (retval);
+}
+
+#define USAGE_MESSAGE "\
+Usage: %s [options] file...\n\
+ Set or display the ABI field for an ELF object.\n\n\
+ Supported options are:\n\
+ -f NUM Set the ELF ABI to the number 'NUM'.\n\
+ -h | --help Print a usage message and exit.\n\
+ -l List known ELF ABI names.\n\
+ -t ABI Set the ELF ABI to the value named by \"ABI\".\n\
+ -V | --version Print a version identifier and exit.\n"
+
+static void
+usage(void)
+{
+ (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
+ exit(1);
+}
+
+static void
+printversion(void)
+{
+ (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
+ exit(0);
+}
+
+static const char *
+iselftype(int etype)
+{
+ size_t elfwalk;
+
+ for (elfwalk = 0;
+ elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
+ elfwalk++)
+ if (etype == elftypes[elfwalk].value)
+ return (elftypes[elfwalk].str);
+ return (0);
+}
+
+static int
+elftype(const char *elfstrtype)
+{
+ size_t elfwalk;
+
+ for (elfwalk = 0;
+ elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
+ elfwalk++)
+ if (strcasecmp(elfstrtype, elftypes[elfwalk].str) == 0)
+ return (elftypes[elfwalk].value);
+ return (-1);
+}
+
+static void
+printelftypes(void)
+{
+ size_t elfwalk;
+
+ (void) printf("Known ELF types are: ");
+ for (elfwalk = 0;
+ elfwalk < sizeof(elftypes)/sizeof(elftypes[0]);
+ elfwalk++)
+ (void) printf("%s(%u) ", elftypes[elfwalk].str,
+ elftypes[elfwalk].value);
+ (void) printf("\n");
+}
diff --git a/contrib/elftoolchain/elfdump/Makefile b/contrib/elftoolchain/elfdump/Makefile
new file mode 100644
index 0000000..b78d465
--- /dev/null
+++ b/contrib/elftoolchain/elfdump/Makefile
@@ -0,0 +1,11 @@
+# $Id: Makefile 2289 2011-12-04 07:11:47Z jkoshy $
+
+TOP= ..
+
+PROG= elfdump
+WARNS?= 6
+
+DPADD= ${LIBELFTC} ${LIBELF}
+LDADD= -lelftc -lelf
+
+.include "${TOP}/mk/elftoolchain.prog.mk"
diff --git a/contrib/elftoolchain/elfdump/elfdump.1 b/contrib/elftoolchain/elfdump/elfdump.1
new file mode 100644
index 0000000..eae7262
--- /dev/null
+++ b/contrib/elftoolchain/elfdump/elfdump.1
@@ -0,0 +1,158 @@
+.\" Copyright (c) 2003 David O'Brien
+.\" 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: src/usr.bin/elfdump/elfdump.1,v 1.6 2005/01/18 13:43:48 ru Exp $
+.\" $Id: elfdump.1 3195 2015-05-12 17:22:19Z emaste $
+.\"
+.Dd August 25, 2011
+.Dt ELFDUMP 1
+.Os
+.Sh NAME
+.Nm elfdump
+.Nd "display information about"
+.Tn ELF
+files
+.Sh SYNOPSIS
+.Nm
+.Fl a | cdeGhiknprsv
+.Op Fl S
+.Op Fl V
+.Op Fl N Ar name
+.Op Fl w Ar file
+.Ar file ...
+.Sh DESCRIPTION
+The
+.Nm
+utility
+dumps various information about the specified
+.Tn ELF
+.Ar file .
+.Pp
+The options are as follows:
+.Bl -tag -width ".Fl w Ar file"
+.It Fl a
+Dump all information.
+.It Fl c
+Dump shared headers.
+.It Fl d
+Dump dynamic symbols.
+.It Fl e
+Dump ELF header.
+.It Fl G
+Dump the GOT.
+.It Fl h
+Dump the hash values.
+.It Fl i
+Dump the dynamic interpreter.
+.It Fl k
+Dump the ELF checksum.
+.It Fl n
+Dump note sections.
+.It Fl N Ar name
+Only dump the section with the specific
+.Ar name .
+Archive symbol table can be specified with
+the special section name ARSYM.
+More than one
+.Fl N
+option may appear.
+.It Fl p
+Dump the program header.
+.It Fl r
+Dump relocations.
+.It Fl s
+Dump the symbol table.
+.It Fl S
+Output in the Solaris
+.Nm
+format.
+.It Fl v
+Dump the symbol-versioning sections.
+.It Fl V
+Print a version identifier and exit.
+.It Fl w Ar file
+Write output to a
+.Ar file
+instead of the standard output.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+The following is an example of a typical usage
+of the
+.Nm
+command:
+.Pp
+.Dl "elfdump -a -w output /bin/ls"
+.Pp
+To dump the content of '.dynsym' symbol table:
+.Pp
+.Dl "elfdump -s -N .dynsym /bin/ls"
+.Pp
+To dump the archive symbol table,
+but not the symbol tables of archive members:
+.Pp
+.Dl "elfdump -s -N ARSYM /usr/lib/libelf.a"
+.Pp
+To dump the content of .got section and
+the symbol-versioning sections in Solaris
+.Nm
+format:
+.Pp
+.Dl "elfdump -S -Gv /bin/ls"
+.Sh SEE ALSO
+.Xr objdump 1 ,
+.Xr readelf 1 ,
+.Xr elf 3
+.Rs
+.%A "AT&T Unix Systems Labs"
+.%T "System V Application Binary Interface"
+.%O http://www.sco.com/developers/gabi/
+.Re
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 5.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+utility
+was written by
+.An Jake Burkholder Aq Mt jake@FreeBSD.org .
+Later it was rewritten based on the
+libelf library.
+This
+manual page was written by
+.An David O'Brien Aq Mt obrien@FreeBSD.org .
+.Pp
+.An Kai Wang Aq Mt kaiw@FreeBSD.org
+rewrote it using the
+.Lb libelf
+and implemented additional functionality.
+.Sh BUGS
+Does not fully implement the
+.Tn ELF
+gABI.
diff --git a/contrib/elftoolchain/elfdump/elfdump.c b/contrib/elftoolchain/elfdump/elfdump.c
new file mode 100644
index 0000000..e4e565b
--- /dev/null
+++ b/contrib/elftoolchain/elfdump/elfdump.c
@@ -0,0 +1,2819 @@
+/*-
+ * Copyright (c) 2007-2012 Kai Wang
+ * Copyright (c) 2003 David O'Brien. All rights reserved.
+ * Copyright (c) 2001 Jake Burkholder
+ * 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/queue.h>
+#include <sys/stat.h>
+
+#include <ar.h>
+#include <assert.h>
+#include <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <getopt.h>
+#include <libelftc.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef USE_LIBARCHIVE_AR
+#include <archive.h>
+#include <archive_entry.h>
+#endif
+
+#include "_elftc.h"
+
+ELFTC_VCSID("$Id: elfdump.c 3198 2015-05-14 18:36:19Z emaste $");
+
+#if defined(ELFTC_NEED_ELF_NOTE_DEFINITION)
+#include "native-elf-format.h"
+#if ELFTC_CLASS == ELFCLASS32
+typedef Elf32_Nhdr Elf_Note;
+#else
+typedef Elf64_Nhdr Elf_Note;
+#endif
+#endif
+
+/* elfdump(1) options. */
+#define ED_DYN (1<<0)
+#define ED_EHDR (1<<1)
+#define ED_GOT (1<<2)
+#define ED_HASH (1<<3)
+#define ED_INTERP (1<<4)
+#define ED_NOTE (1<<5)
+#define ED_PHDR (1<<6)
+#define ED_REL (1<<7)
+#define ED_SHDR (1<<8)
+#define ED_SYMTAB (1<<9)
+#define ED_SYMVER (1<<10)
+#define ED_CHECKSUM (1<<11)
+#define ED_ALL ((1<<12)-1)
+
+/* elfdump(1) run control flags. */
+#define SOLARIS_FMT (1<<0)
+#define PRINT_FILENAME (1<<1)
+#define PRINT_ARSYM (1<<2)
+#define ONLY_ARSYM (1<<3)
+
+/* Convenient print macro. */
+#define PRT(...) fprintf(ed->out, __VA_ARGS__)
+
+/* Internal data structure for sections. */
+struct section {
+ const char *name; /* section name */
+ Elf_Scn *scn; /* section scn */
+ uint64_t off; /* section offset */
+ uint64_t sz; /* section size */
+ uint64_t entsize; /* section entsize */
+ uint64_t align; /* section alignment */
+ uint64_t type; /* section type */
+ uint64_t flags; /* section flags */
+ uint64_t addr; /* section virtual addr */
+ uint32_t link; /* section link ndx */
+ uint32_t info; /* section info ndx */
+};
+
+struct spec_name {
+ const char *name;
+ STAILQ_ENTRY(spec_name) sn_list;
+};
+
+/* Structure encapsulates the global data for readelf(1). */
+struct elfdump {
+ FILE *out; /* output redirection. */
+ const char *filename; /* current processing file. */
+ const char *archive; /* archive name */
+ int options; /* command line options. */
+ int flags; /* run control flags. */
+ Elf *elf; /* underlying ELF descriptor. */
+#ifndef USE_LIBARCHIVE_AR
+ Elf *ar; /* ar(1) archive descriptor. */
+#endif
+ GElf_Ehdr ehdr; /* ELF header. */
+ int ec; /* ELF class. */
+ size_t shnum; /* #sections. */
+ struct section *sl; /* list of sections. */
+ STAILQ_HEAD(, spec_name) snl; /* list of names specified by -N. */
+};
+
+/* Relocation entry. */
+struct rel_entry {
+ union {
+ GElf_Rel rel;
+ GElf_Rela rela;
+ } u_r;
+ const char *symn;
+ uint32_t type;
+};
+
+#if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS)
+static __inline uint32_t
+be32dec(const void *pp)
+{
+ unsigned char const *p = (unsigned char const *)pp;
+
+ return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+}
+
+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]);
+}
+#endif
+
+/* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#tag_encodings */
+static const char *
+d_tags(uint64_t tag)
+{
+ 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";
+ /* 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_SUNW_CONFIG";
+ case 0x6ffffefb: return "DT_SUNW_DEPAUDIT";
+ case 0x6ffffefc: return "DT_SUNW_AUDIT";
+ case 0x6ffffefd: return "DT_SUNW_PLTPAD";
+ case 0x6ffffefe: return "DT_SUNW_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";
+ /* 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";
+ }
+}
+
+static const char *
+e_machines(unsigned int mach)
+{
+ static char machdesc[64];
+
+ switch (mach) {
+ case EM_NONE: return "EM_NONE";
+ case EM_M32: return "EM_M32";
+ case EM_SPARC: return "EM_SPARC";
+ case EM_386: return "EM_386";
+ case EM_68K: return "EM_68K";
+ case EM_88K: return "EM_88K";
+ case EM_IAMCU: return "EM_IAMCU";
+ case EM_860: return "EM_860";
+ case EM_MIPS: return "EM_MIPS";
+ case EM_PPC: return "EM_PPC";
+ case EM_ARM: return "EM_ARM";
+ case EM_ALPHA: return "EM_ALPHA (legacy)";
+ case EM_SPARCV9:return "EM_SPARCV9";
+ case EM_IA_64: return "EM_IA_64";
+ case EM_X86_64: return "EM_X86_64";
+ }
+ snprintf(machdesc, sizeof(machdesc),
+ "(unknown machine) -- type 0x%x", mach);
+ return (machdesc);
+}
+
+static const char *e_types[] = {
+ "ET_NONE", "ET_REL", "ET_EXEC", "ET_DYN", "ET_CORE"
+};
+
+static const char *ei_versions[] = {
+ "EV_NONE", "EV_CURRENT"
+};
+
+static const char *ei_classes[] = {
+ "ELFCLASSNONE", "ELFCLASS32", "ELFCLASS64"
+};
+
+static const char *ei_data[] = {
+ "ELFDATANONE", "ELFDATA2LSB", "ELFDATA2MSB"
+};
+
+static const char *ei_abis[] = {
+ "ELFOSABI_SYSV", "ELFOSABI_HPUX", "ELFOSABI_NETBSD", "ELFOSABI_LINUX",
+ "ELFOSABI_HURD", "ELFOSABI_86OPEN", "ELFOSABI_SOLARIS",
+ "ELFOSABI_MONTEREY", "ELFOSABI_IRIX", "ELFOSABI_FREEBSD",
+ "ELFOSABI_TRU64", "ELFOSABI_MODESTO", "ELFOSABI_OPENBSD"
+};
+
+static const char *p_types[] = {
+ "PT_NULL", "PT_LOAD", "PT_DYNAMIC", "PT_INTERP", "PT_NOTE",
+ "PT_SHLIB", "PT_PHDR", "PT_TLS"
+};
+
+static const char *p_flags[] = {
+ "", "PF_X", "PF_W", "PF_X|PF_W", "PF_R", "PF_X|PF_R", "PF_W|PF_R",
+ "PF_X|PF_W|PF_R"
+};
+
+static const char *
+sh_name(struct elfdump *ed, int ndx)
+{
+ static char num[10];
+
+ switch (ndx) {
+ case SHN_UNDEF: return "UNDEF";
+ case SHN_ABS: return "ABS";
+ case SHN_COMMON: return "COMMON";
+ default:
+ if ((uint64_t)ndx < ed->shnum)
+ return (ed->sl[ndx].name);
+ else {
+ snprintf(num, sizeof(num), "%d", ndx);
+ return (num);
+ }
+ }
+}
+
+/* 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 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";
+ }
+}
+
+/*
+ * Define known section flags. These flags are defined in the order
+ * they are to be printed out.
+ */
+#define DEFINE_SHFLAGS() \
+ DEFINE_SHF(WRITE) \
+ DEFINE_SHF(ALLOC) \
+ DEFINE_SHF(EXECINSTR) \
+ DEFINE_SHF(MERGE) \
+ DEFINE_SHF(STRINGS) \
+ DEFINE_SHF(INFO_LINK) \
+ DEFINE_SHF(LINK_ORDER) \
+ DEFINE_SHF(OS_NONCONFORMING) \
+ DEFINE_SHF(GROUP) \
+ DEFINE_SHF(TLS)
+
+#undef DEFINE_SHF
+#define DEFINE_SHF(F) "SHF_" #F "|"
+#define ALLSHFLAGS DEFINE_SHFLAGS()
+
+static const char *
+sh_flags(uint64_t shf)
+{
+ static char flg[sizeof(ALLSHFLAGS)+1];
+
+ flg[0] = '\0';
+
+#undef DEFINE_SHF
+#define DEFINE_SHF(N) \
+ if (shf & SHF_##N) \
+ strcat(flg, "SHF_" #N "|"); \
+
+ DEFINE_SHFLAGS()
+
+ flg[strlen(flg) - 1] = '\0'; /* Remove the trailing "|". */
+
+ 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_types_S[] = {
+ "NOTY", "OBJT", "FUNC", "SECT", "FILE"
+};
+
+static const char *st_bindings[] = {
+ "STB_LOCAL", "STB_GLOBAL", "STB_WEAK"
+};
+
+static const char *st_bindings_S[] = {
+ "LOCL", "GLOB", "WEAK"
+};
+
+static unsigned char st_others[] = {
+ 'D', 'I', 'H', 'P'
+};
+
+static const char *
+r_type(unsigned int mach, unsigned int type)
+{
+ switch(mach) {
+ case EM_NONE: return "";
+ case EM_386:
+ case EM_IAMCU:
+ switch(type) {
+ case 0: return "R_386_NONE";
+ case 1: return "R_386_32";
+ case 2: return "R_386_PC32";
+ case 3: return "R_386_GOT32";
+ 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 8: return "R_386_RELATIVE";
+ case 9: return "R_386_GOTOFF";
+ case 10: return "R_386_GOTPC";
+ case 14: return "R_386_TLS_TPOFF";
+ case 15: return "R_386_TLS_IE";
+ case 16: return "R_386_TLS_GOTIE";
+ case 17: return "R_386_TLS_LE";
+ case 18: return "R_386_TLS_GD";
+ case 19: return "R_386_TLS_LDM";
+ case 24: return "R_386_TLS_GD_32";
+ case 25: return "R_386_TLS_GD_PUSH";
+ case 26: return "R_386_TLS_GD_CALL";
+ case 27: return "R_386_TLS_GD_POP";
+ case 28: return "R_386_TLS_LDM_32";
+ case 29: return "R_386_TLS_LDM_PUSH";
+ case 30: return "R_386_TLS_LDM_CALL";
+ case 31: return "R_386_TLS_LDM_POP";
+ case 32: return "R_386_TLS_LDO_32";
+ case 33: return "R_386_TLS_IE_32";
+ case 34: return "R_386_TLS_LE_32";
+ case 35: return "R_386_TLS_DTPMOD32";
+ case 36: return "R_386_TLS_DTPOFF32";
+ case 37: return "R_386_TLS_TPOFF32";
+ default: return "";
+ }
+ case EM_ARM:
+ switch(type) {
+ case 0: return "R_ARM_NONE";
+ case 1: return "R_ARM_PC24";
+ case 2: return "R_ARM_ABS32";
+ case 3: return "R_ARM_REL32";
+ case 4: return "R_ARM_PC13";
+ case 5: return "R_ARM_ABS16";
+ case 6: return "R_ARM_ABS12";
+ case 7: return "R_ARM_THM_ABS5";
+ case 8: return "R_ARM_ABS8";
+ case 9: return "R_ARM_SBREL32";
+ case 10: return "R_ARM_THM_PC22";
+ case 11: return "R_ARM_THM_PC8";
+ case 12: return "R_ARM_AMP_VCALL9";
+ case 13: return "R_ARM_SWI24";
+ case 14: return "R_ARM_THM_SWI8";
+ case 15: return "R_ARM_XPC25";
+ case 16: return "R_ARM_THM_XPC22";
+ case 20: return "R_ARM_COPY";
+ case 21: return "R_ARM_GLOB_DAT";
+ case 22: return "R_ARM_JUMP_SLOT";
+ case 23: return "R_ARM_RELATIVE";
+ case 24: return "R_ARM_GOTOFF";
+ case 25: return "R_ARM_GOTPC";
+ case 26: return "R_ARM_GOT32";
+ case 27: return "R_ARM_PLT32";
+ case 100: return "R_ARM_GNU_VTENTRY";
+ case 101: return "R_ARM_GNU_VTINHERIT";
+ case 250: return "R_ARM_RSBREL32";
+ case 251: return "R_ARM_THM_RPC22";
+ case 252: return "R_ARM_RREL32";
+ case 253: return "R_ARM_RABS32";
+ case 254: return "R_ARM_RPC24";
+ case 255: return "R_ARM_RBASE";
+ default: return "";
+ }
+ case EM_IA_64:
+ switch(type) {
+ case 0: return "R_IA_64_NONE";
+ case 33: return "R_IA_64_IMM14";
+ case 34: return "R_IA_64_IMM22";
+ case 35: return "R_IA_64_IMM64";
+ case 36: return "R_IA_64_DIR32MSB";
+ case 37: return "R_IA_64_DIR32LSB";
+ case 38: return "R_IA_64_DIR64MSB";
+ case 39: return "R_IA_64_DIR64LSB";
+ case 42: return "R_IA_64_GPREL22";
+ case 43: return "R_IA_64_GPREL64I";
+ case 44: return "R_IA_64_GPREL32MSB";
+ case 45: return "R_IA_64_GPREL32LSB";
+ case 46: return "R_IA_64_GPREL64MSB";
+ case 47: return "R_IA_64_GPREL64LSB";
+ case 50: return "R_IA_64_LTOFF22";
+ case 51: return "R_IA_64_LTOFF64I";
+ case 58: return "R_IA_64_PLTOFF22";
+ case 59: return "R_IA_64_PLTOFF64I";
+ case 62: return "R_IA_64_PLTOFF64MSB";
+ case 63: return "R_IA_64_PLTOFF64LSB";
+ case 67: return "R_IA_64_FPTR64I";
+ case 68: return "R_IA_64_FPTR32MSB";
+ case 69: return "R_IA_64_FPTR32LSB";
+ case 70: return "R_IA_64_FPTR64MSB";
+ case 71: return "R_IA_64_FPTR64LSB";
+ case 72: return "R_IA_64_PCREL60B";
+ case 73: return "R_IA_64_PCREL21B";
+ case 74: return "R_IA_64_PCREL21M";
+ case 75: return "R_IA_64_PCREL21F";
+ case 76: return "R_IA_64_PCREL32MSB";
+ case 77: return "R_IA_64_PCREL32LSB";
+ case 78: return "R_IA_64_PCREL64MSB";
+ case 79: return "R_IA_64_PCREL64LSB";
+ case 82: return "R_IA_64_LTOFF_FPTR22";
+ case 83: return "R_IA_64_LTOFF_FPTR64I";
+ case 84: return "R_IA_64_LTOFF_FPTR32MSB";
+ case 85: return "R_IA_64_LTOFF_FPTR32LSB";
+ case 86: return "R_IA_64_LTOFF_FPTR64MSB";
+ case 87: return "R_IA_64_LTOFF_FPTR64LSB";
+ case 92: return "R_IA_64_SEGREL32MSB";
+ case 93: return "R_IA_64_SEGREL32LSB";
+ case 94: return "R_IA_64_SEGREL64MSB";
+ case 95: return "R_IA_64_SEGREL64LSB";
+ case 100: return "R_IA_64_SECREL32MSB";
+ case 101: return "R_IA_64_SECREL32LSB";
+ case 102: return "R_IA_64_SECREL64MSB";
+ case 103: return "R_IA_64_SECREL64LSB";
+ case 108: return "R_IA_64_REL32MSB";
+ case 109: return "R_IA_64_REL32LSB";
+ case 110: return "R_IA_64_REL64MSB";
+ case 111: return "R_IA_64_REL64LSB";
+ case 116: return "R_IA_64_LTV32MSB";
+ case 117: return "R_IA_64_LTV32LSB";
+ case 118: return "R_IA_64_LTV64MSB";
+ case 119: return "R_IA_64_LTV64LSB";
+ case 121: return "R_IA_64_PCREL21BI";
+ case 122: return "R_IA_64_PCREL22";
+ case 123: return "R_IA_64_PCREL64I";
+ case 128: return "R_IA_64_IPLTMSB";
+ case 129: return "R_IA_64_IPLTLSB";
+ case 133: return "R_IA_64_SUB";
+ case 134: return "R_IA_64_LTOFF22X";
+ case 135: return "R_IA_64_LDXMOV";
+ case 145: return "R_IA_64_TPREL14";
+ case 146: return "R_IA_64_TPREL22";
+ case 147: return "R_IA_64_TPREL64I";
+ case 150: return "R_IA_64_TPREL64MSB";
+ case 151: return "R_IA_64_TPREL64LSB";
+ case 154: return "R_IA_64_LTOFF_TPREL22";
+ case 166: return "R_IA_64_DTPMOD64MSB";
+ case 167: return "R_IA_64_DTPMOD64LSB";
+ case 170: return "R_IA_64_LTOFF_DTPMOD22";
+ case 177: return "R_IA_64_DTPREL14";
+ case 178: return "R_IA_64_DTPREL22";
+ case 179: return "R_IA_64_DTPREL64I";
+ case 180: return "R_IA_64_DTPREL32MSB";
+ case 181: return "R_IA_64_DTPREL32LSB";
+ case 182: return "R_IA_64_DTPREL64MSB";
+ case 183: return "R_IA_64_DTPREL64LSB";
+ case 186: return "R_IA_64_LTOFF_DTPREL22";
+ default: return "";
+ }
+ case EM_MIPS:
+ switch(type) {
+ case 0: return "R_MIPS_NONE";
+ case 1: return "R_MIPS_16";
+ case 2: return "R_MIPS_32";
+ case 3: return "R_MIPS_REL32";
+ case 4: return "R_MIPS_26";
+ case 5: return "R_MIPS_HI16";
+ case 6: return "R_MIPS_LO16";
+ case 7: return "R_MIPS_GPREL16";
+ case 8: return "R_MIPS_LITERAL";
+ case 9: return "R_MIPS_GOT16";
+ case 10: return "R_MIPS_PC16";
+ case 11: return "R_MIPS_CALL16";
+ case 12: return "R_MIPS_GPREL32";
+ case 21: return "R_MIPS_GOTHI16";
+ case 22: return "R_MIPS_GOTLO16";
+ case 30: return "R_MIPS_CALLHI16";
+ case 31: return "R_MIPS_CALLLO16";
+ default: return "";
+ }
+ case EM_PPC:
+ switch(type) {
+ case 0: return "R_PPC_NONE";
+ case 1: return "R_PPC_ADDR32";
+ case 2: return "R_PPC_ADDR24";
+ case 3: return "R_PPC_ADDR16";
+ case 4: return "R_PPC_ADDR16_LO";
+ case 5: return "R_PPC_ADDR16_HI";
+ case 6: return "R_PPC_ADDR16_HA";
+ case 7: return "R_PPC_ADDR14";
+ case 8: return "R_PPC_ADDR14_BRTAKEN";
+ case 9: return "R_PPC_ADDR14_BRNTAKEN";
+ case 10: return "R_PPC_REL24";
+ case 11: return "R_PPC_REL14";
+ case 12: return "R_PPC_REL14_BRTAKEN";
+ case 13: return "R_PPC_REL14_BRNTAKEN";
+ case 14: return "R_PPC_GOT16";
+ case 15: return "R_PPC_GOT16_LO";
+ case 16: return "R_PPC_GOT16_HI";
+ case 17: return "R_PPC_GOT16_HA";
+ case 18: return "R_PPC_PLTREL24";
+ case 19: return "R_PPC_COPY";
+ case 20: return "R_PPC_GLOB_DAT";
+ case 21: return "R_PPC_JMP_SLOT";
+ case 22: return "R_PPC_RELATIVE";
+ case 23: return "R_PPC_LOCAL24PC";
+ case 24: return "R_PPC_UADDR32";
+ case 25: return "R_PPC_UADDR16";
+ case 26: return "R_PPC_REL32";
+ case 27: return "R_PPC_PLT32";
+ case 28: return "R_PPC_PLTREL32";
+ case 29: return "R_PPC_PLT16_LO";
+ case 30: return "R_PPC_PLT16_HI";
+ case 31: return "R_PPC_PLT16_HA";
+ case 32: return "R_PPC_SDAREL16";
+ case 33: return "R_PPC_SECTOFF";
+ case 34: return "R_PPC_SECTOFF_LO";
+ case 35: return "R_PPC_SECTOFF_HI";
+ case 36: return "R_PPC_SECTOFF_HA";
+ case 67: return "R_PPC_TLS";
+ case 68: return "R_PPC_DTPMOD32";
+ case 69: return "R_PPC_TPREL16";
+ case 70: return "R_PPC_TPREL16_LO";
+ case 71: return "R_PPC_TPREL16_HI";
+ case 72: return "R_PPC_TPREL16_HA";
+ case 73: return "R_PPC_TPREL32";
+ case 74: return "R_PPC_DTPREL16";
+ case 75: return "R_PPC_DTPREL16_LO";
+ case 76: return "R_PPC_DTPREL16_HI";
+ case 77: return "R_PPC_DTPREL16_HA";
+ case 78: return "R_PPC_DTPREL32";
+ case 79: return "R_PPC_GOT_TLSGD16";
+ case 80: return "R_PPC_GOT_TLSGD16_LO";
+ case 81: return "R_PPC_GOT_TLSGD16_HI";
+ case 82: return "R_PPC_GOT_TLSGD16_HA";
+ case 83: return "R_PPC_GOT_TLSLD16";
+ case 84: return "R_PPC_GOT_TLSLD16_LO";
+ case 85: return "R_PPC_GOT_TLSLD16_HI";
+ case 86: return "R_PPC_GOT_TLSLD16_HA";
+ case 87: return "R_PPC_GOT_TPREL16";
+ case 88: return "R_PPC_GOT_TPREL16_LO";
+ case 89: return "R_PPC_GOT_TPREL16_HI";
+ case 90: return "R_PPC_GOT_TPREL16_HA";
+ case 101: return "R_PPC_EMB_NADDR32";
+ case 102: return "R_PPC_EMB_NADDR16";
+ case 103: return "R_PPC_EMB_NADDR16_LO";
+ case 104: return "R_PPC_EMB_NADDR16_HI";
+ case 105: return "R_PPC_EMB_NADDR16_HA";
+ case 106: return "R_PPC_EMB_SDAI16";
+ case 107: return "R_PPC_EMB_SDA2I16";
+ case 108: return "R_PPC_EMB_SDA2REL";
+ case 109: return "R_PPC_EMB_SDA21";
+ case 110: return "R_PPC_EMB_MRKREF";
+ case 111: return "R_PPC_EMB_RELSEC16";
+ case 112: return "R_PPC_EMB_RELST_LO";
+ case 113: return "R_PPC_EMB_RELST_HI";
+ case 114: return "R_PPC_EMB_RELST_HA";
+ case 115: return "R_PPC_EMB_BIT_FLD";
+ case 116: return "R_PPC_EMB_RELSDA";
+ default: return "";
+ }
+ case EM_SPARC:
+ case EM_SPARCV9:
+ switch(type) {
+ case 0: return "R_SPARC_NONE";
+ case 1: return "R_SPARC_8";
+ case 2: return "R_SPARC_16";
+ case 3: return "R_SPARC_32";
+ case 4: return "R_SPARC_DISP8";
+ case 5: return "R_SPARC_DISP16";
+ case 6: return "R_SPARC_DISP32";
+ case 7: return "R_SPARC_WDISP30";
+ case 8: return "R_SPARC_WDISP22";
+ case 9: return "R_SPARC_HI22";
+ case 10: return "R_SPARC_22";
+ case 11: return "R_SPARC_13";
+ case 12: return "R_SPARC_LO10";
+ case 13: return "R_SPARC_GOT10";
+ case 14: return "R_SPARC_GOT13";
+ case 15: return "R_SPARC_GOT22";
+ case 16: return "R_SPARC_PC10";
+ case 17: return "R_SPARC_PC22";
+ case 18: return "R_SPARC_WPLT30";
+ case 19: return "R_SPARC_COPY";
+ case 20: return "R_SPARC_GLOB_DAT";
+ case 21: return "R_SPARC_JMP_SLOT";
+ case 22: return "R_SPARC_RELATIVE";
+ case 23: return "R_SPARC_UA32";
+ case 24: return "R_SPARC_PLT32";
+ case 25: return "R_SPARC_HIPLT22";
+ case 26: return "R_SPARC_LOPLT10";
+ case 27: return "R_SPARC_PCPLT32";
+ case 28: return "R_SPARC_PCPLT22";
+ case 29: return "R_SPARC_PCPLT10";
+ case 30: return "R_SPARC_10";
+ case 31: return "R_SPARC_11";
+ case 32: return "R_SPARC_64";
+ case 33: return "R_SPARC_OLO10";
+ case 34: return "R_SPARC_HH22";
+ case 35: return "R_SPARC_HM10";
+ case 36: return "R_SPARC_LM22";
+ case 37: return "R_SPARC_PC_HH22";
+ case 38: return "R_SPARC_PC_HM10";
+ case 39: return "R_SPARC_PC_LM22";
+ case 40: return "R_SPARC_WDISP16";
+ case 41: return "R_SPARC_WDISP19";
+ case 42: return "R_SPARC_GLOB_JMP";
+ case 43: return "R_SPARC_7";
+ case 44: return "R_SPARC_5";
+ case 45: return "R_SPARC_6";
+ case 46: return "R_SPARC_DISP64";
+ case 47: return "R_SPARC_PLT64";
+ case 48: return "R_SPARC_HIX22";
+ case 49: return "R_SPARC_LOX10";
+ case 50: return "R_SPARC_H44";
+ case 51: return "R_SPARC_M44";
+ case 52: return "R_SPARC_L44";
+ case 53: return "R_SPARC_REGISTER";
+ case 54: return "R_SPARC_UA64";
+ case 55: return "R_SPARC_UA16";
+ case 56: return "R_SPARC_TLS_GD_HI22";
+ case 57: return "R_SPARC_TLS_GD_LO10";
+ case 58: return "R_SPARC_TLS_GD_ADD";
+ case 59: return "R_SPARC_TLS_GD_CALL";
+ case 60: return "R_SPARC_TLS_LDM_HI22";
+ case 61: return "R_SPARC_TLS_LDM_LO10";
+ case 62: return "R_SPARC_TLS_LDM_ADD";
+ case 63: return "R_SPARC_TLS_LDM_CALL";
+ case 64: return "R_SPARC_TLS_LDO_HIX22";
+ case 65: return "R_SPARC_TLS_LDO_LOX10";
+ case 66: return "R_SPARC_TLS_LDO_ADD";
+ case 67: return "R_SPARC_TLS_IE_HI22";
+ case 68: return "R_SPARC_TLS_IE_LO10";
+ case 69: return "R_SPARC_TLS_IE_LD";
+ case 70: return "R_SPARC_TLS_IE_LDX";
+ case 71: return "R_SPARC_TLS_IE_ADD";
+ case 72: return "R_SPARC_TLS_LE_HIX22";
+ case 73: return "R_SPARC_TLS_LE_LOX10";
+ case 74: return "R_SPARC_TLS_DTPMOD32";
+ case 75: return "R_SPARC_TLS_DTPMOD64";
+ case 76: return "R_SPARC_TLS_DTPOFF32";
+ case 77: return "R_SPARC_TLS_DTPOFF64";
+ case 78: return "R_SPARC_TLS_TPOFF32";
+ case 79: return "R_SPARC_TLS_TPOFF64";
+ default: return "";
+ }
+ case EM_X86_64:
+ switch(type) {
+ case 0: return "R_X86_64_NONE";
+ case 1: return "R_X86_64_64";
+ case 2: return "R_X86_64_PC32";
+ case 3: return "R_X86_64_GOT32";
+ 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 8: return "R_X86_64_RELATIVE";
+ case 9: return "R_X86_64_GOTPCREL";
+ case 10: return "R_X86_64_32";
+ case 11: return "R_X86_64_32S";
+ case 12: return "R_X86_64_16";
+ case 13: return "R_X86_64_PC16";
+ case 14: return "R_X86_64_8";
+ case 15: return "R_X86_64_PC8";
+ case 16: return "R_X86_64_DTPMOD64";
+ case 17: return "R_X86_64_DTPOFF64";
+ case 18: return "R_X86_64_TPOFF64";
+ case 19: return "R_X86_64_TLSGD";
+ case 20: return "R_X86_64_TLSLD";
+ case 21: return "R_X86_64_DTPOFF32";
+ case 22: return "R_X86_64_GOTTPOFF";
+ case 23: return "R_X86_64_TPOFF32";
+ default: return "";
+ }
+ default: return "";
+ }
+}
+
+static void add_name(struct elfdump *ed, const char *name);
+static void elf_print_object(struct elfdump *ed);
+static void elf_print_elf(struct elfdump *ed);
+static void elf_print_ehdr(struct elfdump *ed);
+static void elf_print_phdr(struct elfdump *ed);
+static void elf_print_shdr(struct elfdump *ed);
+static void elf_print_symtab(struct elfdump *ed, int i);
+static void elf_print_symtabs(struct elfdump *ed);
+static void elf_print_symver(struct elfdump *ed);
+static void elf_print_verdef(struct elfdump *ed, struct section *s);
+static void elf_print_verneed(struct elfdump *ed, struct section *s);
+static void elf_print_interp(struct elfdump *ed);
+static void elf_print_dynamic(struct elfdump *ed);
+static void elf_print_rel_entry(struct elfdump *ed, struct section *s,
+ int j, struct rel_entry *r);
+static void elf_print_rela(struct elfdump *ed, struct section *s,
+ Elf_Data *data);
+static void elf_print_rel(struct elfdump *ed, struct section *s,
+ Elf_Data *data);
+static void elf_print_reloc(struct elfdump *ed);
+static void elf_print_got(struct elfdump *ed);
+static void elf_print_got_section(struct elfdump *ed, struct section *s);
+static void elf_print_note(struct elfdump *ed);
+static void elf_print_svr4_hash(struct elfdump *ed, struct section *s);
+static void elf_print_svr4_hash64(struct elfdump *ed, struct section *s);
+static void elf_print_gnu_hash(struct elfdump *ed, struct section *s);
+static void elf_print_hash(struct elfdump *ed);
+static void elf_print_checksum(struct elfdump *ed);
+static void find_gotrel(struct elfdump *ed, struct section *gs,
+ struct rel_entry *got);
+static struct spec_name *find_name(struct elfdump *ed, const char *name);
+static const char *get_symbol_name(struct elfdump *ed, int symtab, int i);
+static const char *get_string(struct elfdump *ed, int strtab, size_t off);
+static void get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs);
+static void load_sections(struct elfdump *ed);
+static void unload_sections(struct elfdump *ed);
+static void usage(void);
+#ifdef USE_LIBARCHIVE_AR
+static int ac_detect_ar(int fd);
+static void ac_print_ar(struct elfdump *ed, int fd);
+#else
+static void elf_print_ar(struct elfdump *ed, int fd);
+#endif /* USE_LIBARCHIVE_AR */
+
+static struct option elfdump_longopts[] =
+{
+ { "help", no_argument, NULL, 'H' },
+ { "version", no_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
+};
+
+int
+main(int ac, char **av)
+{
+ struct elfdump *ed, ed_storage;
+ struct spec_name *sn;
+ int ch, i;
+
+ ed = &ed_storage;
+ memset(ed, 0, sizeof(*ed));
+ STAILQ_INIT(&ed->snl);
+ ed->out = stdout;
+ while ((ch = getopt_long(ac, av, "acdeiGHhknN:prsSvVw:",
+ elfdump_longopts, NULL)) != -1)
+ switch (ch) {
+ case 'a':
+ ed->options = ED_ALL;
+ break;
+ case 'c':
+ ed->options |= ED_SHDR;
+ break;
+ case 'd':
+ ed->options |= ED_DYN;
+ break;
+ case 'e':
+ ed->options |= ED_EHDR;
+ break;
+ case 'i':
+ ed->options |= ED_INTERP;
+ break;
+ case 'G':
+ ed->options |= ED_GOT;
+ break;
+ case 'h':
+ ed->options |= ED_HASH;
+ break;
+ case 'k':
+ ed->options |= ED_CHECKSUM;
+ break;
+ case 'n':
+ ed->options |= ED_NOTE;
+ break;
+ case 'N':
+ add_name(ed, optarg);
+ break;
+ case 'p':
+ ed->options |= ED_PHDR;
+ break;
+ case 'r':
+ ed->options |= ED_REL;
+ break;
+ case 's':
+ ed->options |= ED_SYMTAB;
+ break;
+ case 'S':
+ ed->flags |= SOLARIS_FMT;
+ break;
+ case 'v':
+ ed->options |= ED_SYMVER;
+ break;
+ case 'V':
+ (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(),
+ elftc_version());
+ exit(EXIT_SUCCESS);
+ break;
+ case 'w':
+ if ((ed->out = fopen(optarg, "w")) == NULL)
+ err(EXIT_FAILURE, "%s", optarg);
+ break;
+ case '?':
+ case 'H':
+ default:
+ usage();
+ }
+
+ ac -= optind;
+ av += optind;
+
+ if (ed->options == 0)
+ ed->options = ED_ALL;
+ sn = NULL;
+ if (ed->options & ED_SYMTAB &&
+ (STAILQ_EMPTY(&ed->snl) || (sn = find_name(ed, "ARSYM")) != NULL)) {
+ ed->flags |= PRINT_ARSYM;
+ if (sn != NULL) {
+ STAILQ_REMOVE(&ed->snl, sn, spec_name, sn_list);
+ if (STAILQ_EMPTY(&ed->snl))
+ ed->flags |= ONLY_ARSYM;
+ }
+ }
+ if (ac == 0)
+ usage();
+ if (ac > 1)
+ ed->flags |= PRINT_FILENAME;
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ errx(EXIT_FAILURE, "ELF library initialization failed: %s",
+ elf_errmsg(-1));
+
+ for (i = 0; i < ac; i++) {
+ ed->filename = av[i];
+ ed->archive = NULL;
+ elf_print_object(ed);
+ }
+
+ exit(EXIT_SUCCESS);
+}
+
+#ifdef USE_LIBARCHIVE_AR
+
+/* Archive symbol table entry. */
+struct arsym_entry {
+ char *sym_name;
+ size_t off;
+};
+
+/*
+ * Convenient wrapper for general libarchive error handling.
+ */
+#define AC(CALL) do { \
+ if ((CALL)) { \
+ warnx("%s", archive_error_string(a)); \
+ return; \
+ } \
+} while (0)
+
+/*
+ * Detect an ar(1) archive using libarchive(3).
+ */
+static int
+ac_detect_ar(int fd)
+{
+ struct archive *a;
+ struct archive_entry *entry;
+ int r;
+
+ r = -1;
+ if ((a = archive_read_new()) == NULL)
+ return (0);
+ archive_read_support_format_ar(a);
+ if (archive_read_open_fd(a, fd, 10240) == ARCHIVE_OK)
+ r = archive_read_next_header(a, &entry);
+ archive_read_close(a);
+ archive_read_free(a);
+
+ return (r == ARCHIVE_OK);
+}
+
+/*
+ * Dump an ar(1) archive using libarchive(3).
+ */
+static void
+ac_print_ar(struct elfdump *ed, int fd)
+{
+ struct archive *a;
+ struct archive_entry *entry;
+ struct arsym_entry *arsym;
+ const char *name;
+ char idx[10], *b;
+ void *buff;
+ size_t size;
+ uint32_t cnt;
+ int i, r;
+
+ if (lseek(fd, 0, SEEK_SET) == -1)
+ err(EXIT_FAILURE, "lseek failed");
+ if ((a = archive_read_new()) == NULL)
+ errx(EXIT_FAILURE, "%s", archive_error_string(a));
+ archive_read_support_format_ar(a);
+ AC(archive_read_open_fd(a, fd, 10240));
+ for(;;) {
+ r = archive_read_next_header(a, &entry);
+ if (r == ARCHIVE_FATAL)
+ errx(EXIT_FAILURE, "%s", archive_error_string(a));
+ if (r == ARCHIVE_EOF)
+ break;
+ if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY)
+ warnx("%s", archive_error_string(a));
+ if (r == ARCHIVE_RETRY)
+ continue;
+ name = archive_entry_pathname(entry);
+ size = archive_entry_size(entry);
+ if (size == 0)
+ continue;
+ if ((buff = malloc(size)) == NULL) {
+ warn("malloc failed");
+ continue;
+ }
+ if (archive_read_data(a, buff, size) != (ssize_t)size) {
+ warnx("%s", archive_error_string(a));
+ free(buff);
+ continue;
+ }
+
+ /*
+ * Note that when processing arsym via libarchive, there is
+ * no way to tell which member a certain symbol belongs to,
+ * since we can not just "lseek" to a member offset and read
+ * the member header.
+ */
+ if (!strcmp(name, "/") && ed->flags & PRINT_ARSYM) {
+ b = buff;
+ cnt = be32dec(b);
+ if (cnt == 0) {
+ free(buff);
+ continue;
+ }
+ arsym = calloc(cnt, sizeof(*arsym));
+ if (arsym == NULL)
+ err(EXIT_FAILURE, "calloc failed");
+ b += sizeof(uint32_t);
+ for (i = 0; (size_t)i < cnt; i++) {
+ arsym[i].off = be32dec(b);
+ b += sizeof(uint32_t);
+ }
+ for (i = 0; (size_t)i < cnt; i++) {
+ arsym[i].sym_name = b;
+ b += strlen(b) + 1;
+ }
+ if (ed->flags & SOLARIS_FMT) {
+ PRT("\nSymbol Table: (archive)\n");
+ PRT(" index offset symbol\n");
+ } else
+ PRT("\nsymbol table (archive):\n");
+ for (i = 0; (size_t)i < cnt; i++) {
+ if (ed->flags & SOLARIS_FMT) {
+ snprintf(idx, sizeof(idx), "[%d]", i);
+ PRT("%10s ", idx);
+ PRT("0x%8.8jx ",
+ (uintmax_t)arsym[i].off);
+ PRT("%s\n", arsym[i].sym_name);
+ } else {
+ PRT("\nentry: %d\n", i);
+ PRT("\toffset: %#jx\n",
+ (uintmax_t)arsym[i].off);
+ PRT("\tsymbol: %s\n",
+ arsym[i].sym_name);
+ }
+ }
+ free(arsym);
+ free(buff);
+ /* No need to continue if we only dump ARSYM. */
+ if (ed->flags & ONLY_ARSYM) {
+ AC(archive_read_close(a));
+ AC(archive_read_free(a));
+ return;
+ }
+ continue;
+ }
+ if ((ed->elf = elf_memory(buff, size)) == NULL) {
+ warnx("elf_memroy() failed: %s",
+ elf_errmsg(-1));
+ free(buff);
+ continue;
+ }
+ /* Skip non-ELF member. */
+ if (elf_kind(ed->elf) == ELF_K_ELF) {
+ printf("\n%s(%s):\n", ed->archive, name);
+ elf_print_elf(ed);
+ }
+ elf_end(ed->elf);
+ free(buff);
+ }
+ AC(archive_read_close(a));
+ AC(archive_read_free(a));
+}
+
+#else /* USE_LIBARCHIVE_AR */
+
+/*
+ * Dump an ar(1) archive.
+ */
+static void
+elf_print_ar(struct elfdump *ed, int fd)
+{
+ Elf *e;
+ Elf_Arhdr *arh;
+ Elf_Arsym *arsym;
+ Elf_Cmd cmd;
+ char idx[10];
+ size_t cnt;
+ int i;
+
+ ed->ar = ed->elf;
+
+ if (ed->flags & PRINT_ARSYM) {
+ cnt = 0;
+ if ((arsym = elf_getarsym(ed->ar, &cnt)) == NULL) {
+ warnx("elf_getarsym failed: %s", elf_errmsg(-1));
+ goto print_members;
+ }
+ if (cnt == 0)
+ goto print_members;
+ if (ed->flags & SOLARIS_FMT) {
+ PRT("\nSymbol Table: (archive)\n");
+ PRT(" index offset member name and symbol\n");
+ } else
+ PRT("\nsymbol table (archive):\n");
+ for (i = 0; (size_t)i < cnt - 1; i++) {
+ if (elf_rand(ed->ar, arsym[i].as_off) !=
+ arsym[i].as_off) {
+ warnx("elf_rand failed: %s", elf_errmsg(-1));
+ break;
+ }
+ if ((e = elf_begin(fd, ELF_C_READ, ed->ar)) == NULL) {
+ warnx("elf_begin failed: %s", elf_errmsg(-1));
+ break;
+ }
+ if ((arh = elf_getarhdr(e)) == NULL) {
+ warnx("elf_getarhdr failed: %s",
+ elf_errmsg(-1));
+ break;
+ }
+ if (ed->flags & SOLARIS_FMT) {
+ snprintf(idx, sizeof(idx), "[%d]", i);
+ PRT("%10s ", idx);
+ PRT("0x%8.8jx ",
+ (uintmax_t)arsym[i].as_off);
+ PRT("(%s):%s\n", arh->ar_name,
+ arsym[i].as_name);
+ } else {
+ PRT("\nentry: %d\n", i);
+ PRT("\toffset: %#jx\n",
+ (uintmax_t)arsym[i].as_off);
+ PRT("\tmember: %s\n", arh->ar_name);
+ PRT("\tsymbol: %s\n", arsym[i].as_name);
+ }
+ elf_end(e);
+ }
+
+ /* No need to continue if we only dump ARSYM. */
+ if (ed->flags & ONLY_ARSYM)
+ return;
+ }
+
+print_members:
+
+ /* Rewind the archive. */
+ if (elf_rand(ed->ar, SARMAG) != SARMAG) {
+ warnx("elf_rand failed: %s", elf_errmsg(-1));
+ return;
+ }
+
+ /* Dump each member of the archive. */
+ cmd = ELF_C_READ;
+ while ((ed->elf = elf_begin(fd, cmd, ed->ar)) != NULL) {
+ /* Skip non-ELF member. */
+ if (elf_kind(ed->elf) == ELF_K_ELF) {
+ if ((arh = elf_getarhdr(ed->elf)) == NULL) {
+ warnx("elf_getarhdr failed: %s",
+ elf_errmsg(-1));
+ break;
+ }
+ printf("\n%s(%s):\n", ed->archive, arh->ar_name);
+ elf_print_elf(ed);
+ }
+ cmd = elf_next(ed->elf);
+ elf_end(ed->elf);
+ }
+}
+
+#endif /* USE_LIBARCHIVE_AR */
+
+/*
+ * Dump an object. (ELF object or ar(1) archive)
+ */
+static void
+elf_print_object(struct elfdump *ed)
+{
+ int fd;
+
+ if ((fd = open(ed->filename, O_RDONLY)) == -1) {
+ warn("open %s failed", ed->filename);
+ return;
+ }
+
+#ifdef USE_LIBARCHIVE_AR
+ if (ac_detect_ar(fd)) {
+ ed->archive = ed->filename;
+ ac_print_ar(ed, fd);
+ return;
+ }
+#endif /* USE_LIBARCHIVE_AR */
+
+ if ((ed->elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
+ warnx("elf_begin() failed: %s", elf_errmsg(-1));
+ return;
+ }
+
+ switch (elf_kind(ed->elf)) {
+ case ELF_K_NONE:
+ warnx("Not an ELF file.");
+ return;
+ case ELF_K_ELF:
+ if (ed->flags & PRINT_FILENAME)
+ printf("\n%s:\n", ed->filename);
+ elf_print_elf(ed);
+ break;
+ case ELF_K_AR:
+#ifndef USE_LIBARCHIVE_AR
+ ed->archive = ed->filename;
+ elf_print_ar(ed, fd);
+#endif
+ break;
+ default:
+ warnx("Internal: libelf returned unknown elf kind.");
+ return;
+ }
+
+ elf_end(ed->elf);
+}
+
+/*
+ * Dump an ELF object.
+ */
+static void
+elf_print_elf(struct elfdump *ed)
+{
+
+ if (gelf_getehdr(ed->elf, &ed->ehdr) == NULL) {
+ warnx("gelf_getehdr failed: %s", elf_errmsg(-1));
+ return;
+ }
+ if ((ed->ec = gelf_getclass(ed->elf)) == ELFCLASSNONE) {
+ warnx("gelf_getclass failed: %s", elf_errmsg(-1));
+ return;
+ }
+
+ if (ed->options & (ED_SHDR | ED_DYN | ED_REL | ED_GOT | ED_SYMTAB |
+ ED_SYMVER | ED_NOTE | ED_HASH))
+ load_sections(ed);
+
+ if (ed->options & ED_EHDR)
+ elf_print_ehdr(ed);
+ if (ed->options & ED_PHDR)
+ elf_print_phdr(ed);
+ if (ed->options & ED_INTERP)
+ elf_print_interp(ed);
+ if (ed->options & ED_SHDR)
+ elf_print_shdr(ed);
+ if (ed->options & ED_DYN)
+ elf_print_dynamic(ed);
+ if (ed->options & ED_REL)
+ elf_print_reloc(ed);
+ if (ed->options & ED_GOT)
+ elf_print_got(ed);
+ if (ed->options & ED_SYMTAB)
+ elf_print_symtabs(ed);
+ if (ed->options & ED_SYMVER)
+ elf_print_symver(ed);
+ if (ed->options & ED_NOTE)
+ elf_print_note(ed);
+ if (ed->options & ED_HASH)
+ elf_print_hash(ed);
+ if (ed->options & ED_CHECKSUM)
+ elf_print_checksum(ed);
+
+ unload_sections(ed);
+}
+
+/*
+ * Read the section headers from ELF object and store them in the
+ * internal cache.
+ */
+static void
+load_sections(struct elfdump *ed)
+{
+ struct section *s;
+ const char *name;
+ Elf_Scn *scn;
+ GElf_Shdr sh;
+ size_t shstrndx, ndx;
+ int elferr;
+
+ assert(ed->sl == NULL);
+
+ if (!elf_getshnum(ed->elf, &ed->shnum)) {
+ warnx("elf_getshnum failed: %s", elf_errmsg(-1));
+ return;
+ }
+ if (ed->shnum == 0)
+ return;
+ if ((ed->sl = calloc(ed->shnum, sizeof(*ed->sl))) == NULL)
+ err(EXIT_FAILURE, "calloc failed");
+ if (!elf_getshstrndx(ed->elf, &shstrndx)) {
+ warnx("elf_getshstrndx failed: %s", elf_errmsg(-1));
+ return;
+ }
+ if ((scn = elf_getscn(ed->elf, 0)) == NULL) {
+ warnx("elf_getscn failed: %s", elf_errmsg(-1));
+ return;
+ }
+ (void) elf_errno();
+ do {
+ if (gelf_getshdr(scn, &sh) == NULL) {
+ warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
+ (void) elf_errno();
+ continue;
+ }
+ if ((name = elf_strptr(ed->elf, shstrndx, sh.sh_name)) == NULL) {
+ (void) elf_errno();
+ name = "ERROR";
+ }
+ if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF)
+ if ((elferr = elf_errno()) != 0) {
+ warnx("elf_ndxscn failed: %s",
+ elf_errmsg(elferr));
+ continue;
+ }
+ if (ndx >= ed->shnum) {
+ warnx("section index of '%s' out of range", name);
+ continue;
+ }
+ s = &ed->sl[ndx];
+ s->name = name;
+ s->scn = scn;
+ s->off = sh.sh_offset;
+ s->sz = sh.sh_size;
+ s->entsize = sh.sh_entsize;
+ s->align = sh.sh_addralign;
+ s->type = sh.sh_type;
+ s->flags = sh.sh_flags;
+ s->addr = sh.sh_addr;
+ s->link = sh.sh_link;
+ s->info = sh.sh_info;
+ } while ((scn = elf_nextscn(ed->elf, scn)) != NULL);
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
+}
+
+/*
+ * Release section related resources.
+ */
+static void
+unload_sections(struct elfdump *ed)
+{
+ if (ed->sl != NULL) {
+ free(ed->sl);
+ ed->sl = NULL;
+ }
+}
+
+/*
+ * Add a name to the '-N' name list.
+ */
+static void
+add_name(struct elfdump *ed, const char *name)
+{
+ struct spec_name *sn;
+
+ if (find_name(ed, name))
+ return;
+ if ((sn = malloc(sizeof(*sn))) == NULL) {
+ warn("malloc failed");
+ return;
+ }
+ sn->name = name;
+ STAILQ_INSERT_TAIL(&ed->snl, sn, sn_list);
+}
+
+/*
+ * Lookup a name in the '-N' name list.
+ */
+static struct spec_name *
+find_name(struct elfdump *ed, const char *name)
+{
+ struct spec_name *sn;
+
+ STAILQ_FOREACH(sn, &ed->snl, sn_list) {
+ if (!strcmp(sn->name, name))
+ return (sn);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Retrieve the name of a symbol using the section index of the symbol
+ * table and the index of the symbol within that table.
+ */
+static const char *
+get_symbol_name(struct elfdump *ed, int symtab, int i)
+{
+ static char sname[64];
+ struct section *s;
+ const char *name;
+ GElf_Sym sym;
+ Elf_Data *data;
+ int elferr;
+
+ s = &ed->sl[symtab];
+ if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM)
+ return ("");
+ (void) elf_errno();
+ if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+ return ("");
+ }
+ if (gelf_getsym(data, i, &sym) != &sym)
+ return ("");
+ if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) {
+ if (sym.st_shndx < ed->shnum) {
+ snprintf(sname, sizeof(sname), "%s (section)",
+ ed->sl[sym.st_shndx].name);
+ return (sname);
+ } else
+ return ("");
+ }
+ if ((name = elf_strptr(ed->elf, s->link, sym.st_name)) == NULL)
+ return ("");
+
+ return (name);
+}
+
+/*
+ * Retrieve a string using string table section index and the string offset.
+ */
+static const char*
+get_string(struct elfdump *ed, int strtab, size_t off)
+{
+ const char *name;
+
+ if ((name = elf_strptr(ed->elf, strtab, off)) == NULL)
+ return ("");
+
+ return (name);
+}
+
+/*
+ * Dump the ELF Executable Header.
+ */
+static void
+elf_print_ehdr(struct elfdump *ed)
+{
+
+ if (!STAILQ_EMPTY(&ed->snl))
+ return;
+
+ if (ed->flags & SOLARIS_FMT) {
+ PRT("\nELF Header\n");
+ PRT(" ei_magic: { %#x, %c, %c, %c }\n",
+ ed->ehdr.e_ident[0], ed->ehdr.e_ident[1],
+ ed->ehdr.e_ident[2], ed->ehdr.e_ident[3]);
+ PRT(" ei_class: %-18s",
+ ei_classes[ed->ehdr.e_ident[EI_CLASS]]);
+ PRT(" ei_data: %s\n", ei_data[ed->ehdr.e_ident[EI_DATA]]);
+ PRT(" e_machine: %-18s", e_machines(ed->ehdr.e_machine));
+ PRT(" e_version: %s\n", ei_versions[ed->ehdr.e_version]);
+ PRT(" e_type: %s\n", e_types[ed->ehdr.e_type]);
+ PRT(" e_flags: %18d\n", ed->ehdr.e_flags);
+ PRT(" e_entry: %#18jx", (uintmax_t)ed->ehdr.e_entry);
+ PRT(" e_ehsize: %6d", ed->ehdr.e_ehsize);
+ PRT(" e_shstrndx:%5d\n", ed->ehdr.e_shstrndx);
+ PRT(" e_shoff: %#18jx", (uintmax_t)ed->ehdr.e_shoff);
+ PRT(" e_shentsize: %3d", ed->ehdr.e_shentsize);
+ PRT(" e_shnum: %5d\n", ed->ehdr.e_shnum);
+ PRT(" e_phoff: %#18jx", (uintmax_t)ed->ehdr.e_phoff);
+ PRT(" e_phentsize: %3d", ed->ehdr.e_phentsize);
+ PRT(" e_phnum: %5d\n", ed->ehdr.e_phnum);
+ } else {
+ PRT("\nelf header:\n");
+ PRT("\n");
+ PRT("\te_ident: %s %s %s\n",
+ ei_classes[ed->ehdr.e_ident[EI_CLASS]],
+ ei_data[ed->ehdr.e_ident[EI_DATA]],
+ ei_abis[ed->ehdr.e_ident[EI_OSABI]]);
+ PRT("\te_type: %s\n", e_types[ed->ehdr.e_type]);
+ PRT("\te_machine: %s\n", e_machines(ed->ehdr.e_machine));
+ PRT("\te_version: %s\n", ei_versions[ed->ehdr.e_version]);
+ PRT("\te_entry: %#jx\n", (uintmax_t)ed->ehdr.e_entry);
+ PRT("\te_phoff: %ju\n", (uintmax_t)ed->ehdr.e_phoff);
+ PRT("\te_shoff: %ju\n", (uintmax_t) ed->ehdr.e_shoff);
+ PRT("\te_flags: %u\n", ed->ehdr.e_flags);
+ PRT("\te_ehsize: %u\n", ed->ehdr.e_ehsize);
+ PRT("\te_phentsize: %u\n", ed->ehdr.e_phentsize);
+ PRT("\te_phnum: %u\n", ed->ehdr.e_phnum);
+ PRT("\te_shentsize: %u\n", ed->ehdr.e_shentsize);
+ PRT("\te_shnum: %u\n", ed->ehdr.e_shnum);
+ PRT("\te_shstrndx: %u\n", ed->ehdr.e_shstrndx);
+ }
+}
+
+/*
+ * Dump the ELF Program Header Table.
+ */
+static void
+elf_print_phdr(struct elfdump *ed)
+{
+ GElf_Phdr ph;
+ size_t phnum;
+ int header, i;
+
+ if (elf_getphnum(ed->elf, &phnum) == 0) {
+ warnx("elf_getphnum failed: %s", elf_errmsg(-1));
+ return;
+ }
+ header = 0;
+ for (i = 0; (u_int64_t) i < phnum; i++) {
+ if (gelf_getphdr(ed->elf, i, &ph) != &ph) {
+ warnx("elf_getphdr failed: %s", elf_errmsg(-1));
+ continue;
+ }
+ if (!STAILQ_EMPTY(&ed->snl) &&
+ find_name(ed, p_types[ph.p_type & 0x7]) == NULL)
+ continue;
+ if (ed->flags & SOLARIS_FMT) {
+ PRT("\nProgram Header[%d]:\n", i);
+ PRT(" p_vaddr: %#-14jx", (uintmax_t)ph.p_vaddr);
+ PRT(" p_flags: [ %s ]\n", p_flags[ph.p_flags]);
+ PRT(" p_paddr: %#-14jx", (uintmax_t)ph.p_paddr);
+ PRT(" p_type: [ %s ]\n", p_types[ph.p_type & 0x7]);
+ PRT(" p_filesz: %#-14jx",
+ (uintmax_t)ph.p_filesz);
+ PRT(" p_memsz: %#jx\n", (uintmax_t)ph.p_memsz);
+ PRT(" p_offset: %#-14jx",
+ (uintmax_t)ph.p_offset);
+ PRT(" p_align: %#jx\n", (uintmax_t)ph.p_align);
+ } else {
+ if (!header) {
+ PRT("\nprogram header:\n");
+ header = 1;
+ }
+ PRT("\n");
+ PRT("entry: %d\n", i);
+ PRT("\tp_type: %s\n", p_types[ph.p_type & 0x7]);
+ PRT("\tp_offset: %ju\n", (uintmax_t)ph.p_offset);
+ PRT("\tp_vaddr: %#jx\n", (uintmax_t)ph.p_vaddr);
+ PRT("\tp_paddr: %#jx\n", (uintmax_t)ph.p_paddr);
+ PRT("\tp_filesz: %ju\n", (uintmax_t)ph.p_filesz);
+ PRT("\tp_memsz: %ju\n", (uintmax_t)ph.p_memsz);
+ PRT("\tp_flags: %s\n", p_flags[ph.p_flags]);
+ PRT("\tp_align: %ju\n", (uintmax_t)ph.p_align);
+ }
+ }
+}
+
+/*
+ * Dump the ELF Section Header Table.
+ */
+static void
+elf_print_shdr(struct elfdump *ed)
+{
+ struct section *s;
+ int i;
+
+ if (!STAILQ_EMPTY(&ed->snl))
+ return;
+
+ if ((ed->flags & SOLARIS_FMT) == 0)
+ PRT("\nsection header:\n");
+ for (i = 0; (size_t)i < ed->shnum; i++) {
+ s = &ed->sl[i];
+ if (ed->flags & SOLARIS_FMT) {
+ if (i == 0)
+ continue;
+ PRT("\nSection Header[%d]:", i);
+ PRT(" sh_name: %s\n", s->name);
+ PRT(" sh_addr: %#-14jx", (uintmax_t)s->addr);
+ if (s->flags != 0)
+ PRT(" sh_flags: [ %s ]\n", sh_flags(s->flags));
+ 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_offset: %#-14jx", (uintmax_t)s->off);
+ PRT(" sh_entsize: %#jx\n", (uintmax_t)s->entsize);
+ PRT(" sh_link: %-14u", s->link);
+ PRT(" sh_info: %u\n", s->info);
+ PRT(" sh_addralign: %#jx\n", (uintmax_t)s->align);
+ } else {
+ 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_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);
+ PRT("\tsh_size: %ju\n", (uintmax_t)s->sz);
+ PRT("\tsh_link: %u\n", s->link);
+ PRT("\tsh_info: %u\n", s->info);
+ PRT("\tsh_addralign: %ju\n", (uintmax_t)s->align);
+ PRT("\tsh_entsize: %ju\n", (uintmax_t)s->entsize);
+ }
+ }
+}
+
+/*
+ * Retrieve the content of the corresponding SHT_SUNW_versym section for
+ * a symbol table section.
+ */
+static void
+get_versym(struct elfdump *ed, int i, uint16_t **vs, int *nvs)
+{
+ struct section *s;
+ Elf_Data *data;
+ int j, elferr;
+
+ s = NULL;
+ for (j = 0; (size_t)j < ed->shnum; j++) {
+ s = &ed->sl[j];
+ if (s->type == SHT_SUNW_versym && s->link == (uint32_t)i)
+ break;
+ }
+ if ((size_t)j >= ed->shnum) {
+ *vs = NULL;
+ return;
+ }
+ (void) elf_errno();
+ if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+ *vs = NULL;
+ return;
+ }
+
+ *vs = data->d_buf;
+ *nvs = data->d_size / s->entsize;
+}
+
+/*
+ * Dump the symbol table section.
+ */
+static void
+elf_print_symtab(struct elfdump *ed, int i)
+{
+ struct section *s;
+ const char *name;
+ uint16_t *vs;
+ char idx[10];
+ Elf_Data *data;
+ GElf_Sym sym;
+ int len, j, elferr, nvs;
+
+ s = &ed->sl[i];
+ if (ed->flags & SOLARIS_FMT)
+ PRT("\nSymbol Table Section: %s\n", s->name);
+ else
+ PRT("\nsymbol table (%s):\n", s->name);
+ (void) elf_errno();
+ if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+ return;
+ }
+ vs = NULL;
+ nvs = 0;
+ len = data->d_size / s->entsize;
+ if (ed->flags & SOLARIS_FMT) {
+ if (ed->ec == ELFCLASS32)
+ PRT(" index value ");
+ else
+ PRT(" index value ");
+ PRT("size type bind oth ver shndx name\n");
+ get_versym(ed, i, &vs, &nvs);
+ if (vs != NULL && nvs != len) {
+ warnx("#symbol not equal to #versym");
+ vs = NULL;
+ }
+ }
+ for (j = 0; j < len; j++) {
+ if (gelf_getsym(data, j, &sym) != &sym) {
+ warnx("gelf_getsym failed: %s", elf_errmsg(-1));
+ continue;
+ }
+ name = get_string(ed, s->link, sym.st_name);
+ if (ed->flags & SOLARIS_FMT) {
+ snprintf(idx, sizeof(idx), "[%d]", j);
+ if (ed->ec == ELFCLASS32)
+ PRT("%10s ", idx);
+ else
+ PRT("%10s ", idx);
+ PRT("0x%8.8jx ", (uintmax_t)sym.st_value);
+ if (ed->ec == ELFCLASS32)
+ 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("%c ", st_others[sym.st_other]);
+ PRT("%3u ", (vs == NULL ? 0 : vs[j]));
+ PRT("%-11.11s ", sh_name(ed, sym.st_shndx));
+ PRT("%s\n", name);
+ } else {
+ PRT("\nentry: %d\n", j);
+ PRT("\tst_name: %s\n", name);
+ 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)]);
+ PRT("\tst_shndx: %ju\n", (uintmax_t)sym.st_shndx);
+ }
+ }
+}
+
+/*
+ * Dump the symbol tables. (.dynsym and .symtab)
+ */
+static void
+elf_print_symtabs(struct elfdump *ed)
+{
+ int i;
+
+ for (i = 0; (size_t)i < ed->shnum; i++)
+ if ((ed->sl[i].type == SHT_SYMTAB ||
+ ed->sl[i].type == SHT_DYNSYM) &&
+ (STAILQ_EMPTY(&ed->snl) || find_name(ed, ed->sl[i].name)))
+ elf_print_symtab(ed, i);
+}
+
+/*
+ * Dump the content of .dynamic section.
+ */
+static void
+elf_print_dynamic(struct elfdump *ed)
+{
+ struct section *s;
+ const char *name;
+ char idx[10];
+ Elf_Data *data;
+ GElf_Dyn dyn;
+ int elferr, i, len;
+
+ s = NULL;
+ for (i = 0; (size_t)i < ed->shnum; i++) {
+ s = &ed->sl[i];
+ if (s->type == SHT_DYNAMIC &&
+ (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name)))
+ break;
+ }
+ if ((size_t)i >= ed->shnum)
+ return;
+
+ if (ed->flags & SOLARIS_FMT) {
+ PRT("Dynamic Section: %s\n", s->name);
+ PRT(" index tag value\n");
+ } else
+ PRT("\ndynamic:\n");
+ (void) elf_errno();
+ if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+ return;
+ }
+ len = data->d_size / s->entsize;
+ for (i = 0; i < len; i++) {
+ if (gelf_getdyn(data, i, &dyn) != &dyn) {
+ warnx("gelf_getdyn failed: %s", elf_errmsg(-1));
+ continue;
+ }
+
+ if (ed->flags & SOLARIS_FMT) {
+ snprintf(idx, sizeof(idx), "[%d]", i);
+ PRT("%10s %-16s ", idx, d_tags(dyn.d_tag));
+ } else {
+ PRT("\n");
+ PRT("entry: %d\n", i);
+ PRT("\td_tag: %s\n", d_tags(dyn.d_tag));
+ }
+ switch(dyn.d_tag) {
+ case DT_NEEDED:
+ case DT_SONAME:
+ case DT_RPATH:
+ if ((name = elf_strptr(ed->elf, s->link,
+ dyn.d_un.d_val)) == NULL)
+ name = "";
+ if (ed->flags & SOLARIS_FMT)
+ PRT("%#-16jx %s\n", (uintmax_t)dyn.d_un.d_val,
+ name);
+ else
+ PRT("\td_val: %s\n", name);
+ break;
+ case DT_PLTRELSZ:
+ case DT_RELA:
+ case DT_RELASZ:
+ case DT_RELAENT:
+ case DT_RELACOUNT:
+ case DT_STRSZ:
+ case DT_SYMENT:
+ case DT_RELSZ:
+ case DT_RELENT:
+ case DT_PLTREL:
+ case DT_VERDEF:
+ case DT_VERDEFNUM:
+ case DT_VERNEED:
+ case DT_VERNEEDNUM:
+ case DT_VERSYM:
+ if (ed->flags & SOLARIS_FMT)
+ PRT("%#jx\n", (uintmax_t)dyn.d_un.d_val);
+ else
+ PRT("\td_val: %ju\n",
+ (uintmax_t)dyn.d_un.d_val);
+ break;
+ case DT_PLTGOT:
+ case DT_HASH:
+ case DT_GNU_HASH:
+ case DT_STRTAB:
+ case DT_SYMTAB:
+ case DT_INIT:
+ case DT_FINI:
+ case DT_REL:
+ case DT_JMPREL:
+ case DT_DEBUG:
+ if (ed->flags & SOLARIS_FMT)
+ PRT("%#jx\n", (uintmax_t)dyn.d_un.d_ptr);
+ else
+ PRT("\td_ptr: %#jx\n",
+ (uintmax_t)dyn.d_un.d_ptr);
+ break;
+ case DT_NULL:
+ case DT_SYMBOLIC:
+ case DT_TEXTREL:
+ default:
+ if (ed->flags & SOLARIS_FMT)
+ PRT("\n");
+ break;
+ }
+ }
+}
+
+/*
+ * Dump a .rel/.rela section entry.
+ */
+static void
+elf_print_rel_entry(struct elfdump *ed, struct section *s, int j,
+ struct rel_entry *r)
+{
+
+ if (ed->flags & SOLARIS_FMT) {
+ PRT(" %-23s ", r_type(ed->ehdr.e_machine,
+ GELF_R_TYPE(r->u_r.rel.r_info)));
+ PRT("%#12jx ", (uintmax_t)r->u_r.rel.r_offset);
+ if (r->type == SHT_RELA)
+ PRT("%10jd ", (intmax_t)r->u_r.rela.r_addend);
+ else
+ PRT(" ");
+ PRT("%-14s ", s->name);
+ PRT("%s\n", r->symn);
+ } else {
+ PRT("\n");
+ PRT("entry: %d\n", j);
+ PRT("\tr_offset: %#jx\n", (uintmax_t)r->u_r.rel.r_offset);
+ if (ed->ec == ELFCLASS32)
+ PRT("\tr_info: %#jx\n", (uintmax_t)
+ ELF32_R_INFO(ELF64_R_SYM(r->u_r.rel.r_info),
+ ELF64_R_TYPE(r->u_r.rel.r_info)));
+ else
+ PRT("\tr_info: %#jx\n", (uintmax_t)r->u_r.rel.r_info);
+ if (r->type == SHT_RELA)
+ PRT("\tr_addend: %jd\n",
+ (intmax_t)r->u_r.rela.r_addend);
+ }
+}
+
+/*
+ * Dump a relocation section of type SHT_RELA.
+ */
+static void
+elf_print_rela(struct elfdump *ed, struct section *s, Elf_Data *data)
+{
+ struct rel_entry r;
+ int j, len;
+
+ if (ed->flags & SOLARIS_FMT) {
+ PRT("\nRelocation Section: %s\n", s->name);
+ PRT(" type offset "
+ "addend section with respect to\n");
+ } else
+ PRT("\nrelocation with addend (%s):\n", s->name);
+ r.type = SHT_RELA;
+ len = data->d_size / s->entsize;
+ for (j = 0; j < len; j++) {
+ if (gelf_getrela(data, j, &r.u_r.rela) != &r.u_r.rela) {
+ warnx("gelf_getrela failed: %s",
+ elf_errmsg(-1));
+ continue;
+ }
+ r.symn = get_symbol_name(ed, s->link,
+ GELF_R_SYM(r.u_r.rela.r_info));
+ elf_print_rel_entry(ed, s, j, &r);
+ }
+}
+
+/*
+ * Dump a relocation section of type SHT_REL.
+ */
+static void
+elf_print_rel(struct elfdump *ed, struct section *s, Elf_Data *data)
+{
+ struct rel_entry r;
+ int j, len;
+
+ if (ed->flags & SOLARIS_FMT) {
+ PRT("\nRelocation Section: %s\n", s->name);
+ PRT(" type offset "
+ "section with respect to\n");
+ } else
+ PRT("\nrelocation (%s):\n", s->name);
+ r.type = SHT_REL;
+ len = data->d_size / s->entsize;
+ for (j = 0; j < len; j++) {
+ if (gelf_getrel(data, j, &r.u_r.rel) != &r.u_r.rel) {
+ warnx("gelf_getrel failed: %s", elf_errmsg(-1));
+ continue;
+ }
+ r.symn = get_symbol_name(ed, s->link,
+ GELF_R_SYM(r.u_r.rel.r_info));
+ elf_print_rel_entry(ed, s, j, &r);
+ }
+}
+
+/*
+ * Dump relocation sections.
+ */
+static void
+elf_print_reloc(struct elfdump *ed)
+{
+ struct section *s;
+ Elf_Data *data;
+ int i, elferr;
+
+ for (i = 0; (size_t)i < ed->shnum; i++) {
+ s = &ed->sl[i];
+ if ((s->type == SHT_REL || s->type == SHT_RELA) &&
+ (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) {
+ (void) elf_errno();
+ if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_getdata failed: %s",
+ elf_errmsg(elferr));
+ continue;
+ }
+ if (s->type == SHT_REL)
+ elf_print_rel(ed, s, data);
+ else
+ elf_print_rela(ed, s, data);
+ }
+ }
+}
+
+/*
+ * Dump the content of PT_INTERP segment.
+ */
+static void
+elf_print_interp(struct elfdump *ed)
+{
+ const char *s;
+ GElf_Phdr phdr;
+ size_t phnum;
+ int i;
+
+ if (!STAILQ_EMPTY(&ed->snl) && find_name(ed, "PT_INTERP") == NULL)
+ return;
+
+ if ((s = elf_rawfile(ed->elf, NULL)) == NULL) {
+ warnx("elf_rawfile failed: %s", elf_errmsg(-1));
+ return;
+ }
+ if (!elf_getphnum(ed->elf, &phnum)) {
+ warnx("elf_getphnum failed: %s", elf_errmsg(-1));
+ return;
+ }
+ for (i = 0; (size_t)i < phnum; i++) {
+ if (gelf_getphdr(ed->elf, i, &phdr) != &phdr) {
+ warnx("elf_getphdr failed: %s", elf_errmsg(-1));
+ continue;
+ }
+ if (phdr.p_type == PT_INTERP) {
+ PRT("\ninterp:\n");
+ PRT("\t%s\n", s + phdr.p_offset);
+ }
+ }
+}
+
+/*
+ * Search the relocation sections for entries refering to the .got section.
+ */
+static void
+find_gotrel(struct elfdump *ed, struct section *gs, struct rel_entry *got)
+{
+ struct section *s;
+ struct rel_entry r;
+ Elf_Data *data;
+ int elferr, i, j, k, len;
+
+ for(i = 0; (size_t)i < ed->shnum; i++) {
+ s = &ed->sl[i];
+ if (s->type != SHT_REL && s->type != SHT_RELA)
+ continue;
+ (void) elf_errno();
+ if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_getdata failed: %s",
+ elf_errmsg(elferr));
+ return;
+ }
+ memset(&r, 0, sizeof(struct rel_entry));
+ r.type = s->type;
+ len = data->d_size / s->entsize;
+ for (j = 0; j < len; j++) {
+ if (s->type == SHT_REL) {
+ if (gelf_getrel(data, j, &r.u_r.rel) !=
+ &r.u_r.rel) {
+ warnx("gelf_getrel failed: %s",
+ elf_errmsg(-1));
+ continue;
+ }
+ } else {
+ if (gelf_getrela(data, j, &r.u_r.rela) !=
+ &r.u_r.rela) {
+ warnx("gelf_getrel failed: %s",
+ elf_errmsg(-1));
+ continue;
+ }
+ }
+ if (r.u_r.rel.r_offset >= gs->addr &&
+ r.u_r.rel.r_offset < gs->addr + gs->sz) {
+ r.symn = get_symbol_name(ed, s->link,
+ GELF_R_SYM(r.u_r.rel.r_info));
+ k = (r.u_r.rel.r_offset - gs->addr) /
+ gs->entsize;
+ memcpy(&got[k], &r, sizeof(struct rel_entry));
+ }
+ }
+ }
+}
+
+static void
+elf_print_got_section(struct elfdump *ed, struct section *s)
+{
+ struct rel_entry *got;
+ Elf_Data *data, dst;
+ int elferr, i, len;
+
+ if (s->entsize == 0) {
+ /* XXX IA64 GOT section generated by gcc has entry size 0. */
+ if (s->align != 0)
+ s->entsize = s->align;
+ else
+ return;
+ }
+
+ if (ed->flags & SOLARIS_FMT)
+ PRT("\nGlobal Offset Table Section: %s (%jd entries)\n",
+ s->name, s->sz / s->entsize);
+ else
+ PRT("\nglobal offset table: %s\n", s->name);
+ (void) elf_errno();
+ if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+ return;
+ }
+
+ /*
+ * GOT section has section type SHT_PROGBITS, thus libelf treats it as
+ * byte stream and will not perfrom any translation on it. As a result,
+ * an exlicit call to gelf_xlatetom is needed here. Depends on arch,
+ * GOT section should be translated to either WORD or XWORD.
+ */
+ if (ed->ec == ELFCLASS32)
+ data->d_type = ELF_T_WORD;
+ else
+ data->d_type = ELF_T_XWORD;
+ memcpy(&dst, data, sizeof(Elf_Data));
+ if (gelf_xlatetom(ed->elf, &dst, data, ed->ehdr.e_ident[EI_DATA]) !=
+ &dst) {
+ warnx("gelf_xlatetom failed: %s", elf_errmsg(-1));
+ return;
+ }
+ len = dst.d_size / s->entsize;
+ if (ed->flags & SOLARIS_FMT) {
+ /*
+ * In verbose/Solaris mode, we search the relocation sections
+ * and try to find the corresponding reloc entry for each GOT
+ * section entry.
+ */
+ if ((got = calloc(len, sizeof(struct rel_entry))) == NULL)
+ err(EXIT_FAILURE, "calloc failed");
+ find_gotrel(ed, s, got);
+ if (ed->ec == ELFCLASS32) {
+ PRT(" ndx addr value reloc ");
+ PRT("addend symbol\n");
+ } else {
+ PRT(" ndx addr value ");
+ PRT("reloc addend symbol\n");
+ }
+ for(i = 0; i < len; i++) {
+ PRT("[%5.5d] ", i);
+ if (ed->ec == ELFCLASS32) {
+ PRT("%-8.8jx ", 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("%-18s ", r_type(ed->ehdr.e_machine,
+ GELF_R_TYPE(got[i].u_r.rel.r_info)));
+ if (ed->ec == ELFCLASS32)
+ PRT("%-8.8jd ",
+ (intmax_t)got[i].u_r.rela.r_addend);
+ else
+ PRT("%-12.12jd ",
+ (intmax_t)got[i].u_r.rela.r_addend);
+ if (got[i].symn == NULL)
+ got[i].symn = "";
+ PRT("%s\n", got[i].symn);
+ }
+ free(got);
+ } else {
+ for(i = 0; i < len; i++) {
+ PRT("\nentry: %d\n", i);
+ 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));
+ }
+ }
+}
+
+/*
+ * Dump the content of Global Offset Table section.
+ */
+static void
+elf_print_got(struct elfdump *ed)
+{
+ struct section *s;
+ int i;
+
+ if (!STAILQ_EMPTY(&ed->snl))
+ return;
+
+ s = NULL;
+ for (i = 0; (size_t)i < ed->shnum; i++) {
+ s = &ed->sl[i];
+ if (s->name && !strncmp(s->name, ".got", 4) &&
+ (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name)))
+ elf_print_got_section(ed, s);
+ }
+}
+
+/*
+ * Dump the content of .note.ABI-tag section.
+ */
+static void
+elf_print_note(struct elfdump *ed)
+{
+ struct section *s;
+ Elf_Data *data;
+ Elf_Note *en;
+ uint32_t namesz;
+ uint32_t descsz;
+ uint32_t desc;
+ size_t count;
+ int elferr, i;
+ char *src, idx[10];
+
+ s = NULL;
+ for (i = 0; (size_t)i < ed->shnum; i++) {
+ s = &ed->sl[i];
+ if (s->type == SHT_NOTE && s->name &&
+ !strcmp(s->name, ".note.ABI-tag") &&
+ (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name)))
+ break;
+ }
+ if ((size_t)i >= ed->shnum)
+ return;
+ if (ed->flags & SOLARIS_FMT)
+ PRT("\nNote Section: %s\n", s->name);
+ else
+ PRT("\nnote (%s):\n", s->name);
+ (void) elf_errno();
+ if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_getdata failed: %s", elf_errmsg(elferr));
+ return;
+ }
+ src = data->d_buf;
+ count = data->d_size;
+ while (count > sizeof(Elf_Note)) {
+ en = (Elf_Note *) (uintptr_t) src;
+ namesz = en->n_namesz;
+ descsz = en->n_descsz;
+ src += sizeof(Elf_Note);
+ count -= sizeof(Elf_Note);
+ if (ed->flags & SOLARIS_FMT) {
+ PRT("\n type %#x\n", en->n_type);
+ PRT(" namesz %#x:\n", en->n_namesz);
+ PRT("%s\n", src);
+ } else
+ PRT("\t%s ", src);
+ src += roundup2(namesz, 4);
+ count -= roundup2(namesz, 4);
+
+ /*
+ * Note that we dump the whole desc part if we're in
+ * "Solaris mode", while in the normal mode, we only look
+ * at the first 4 bytes (a 32bit word) of the desc, i.e,
+ * we assume that it's always a FreeBSD version number.
+ */
+ if (ed->flags & SOLARIS_FMT) {
+ PRT(" descsz %#x:", en->n_descsz);
+ for (i = 0; (uint32_t)i < descsz; i++) {
+ if ((i & 0xF) == 0) {
+ snprintf(idx, sizeof(idx), "desc[%d]",
+ i);
+ PRT("\n %-9s", idx);
+ } else if ((i & 0x3) == 0)
+ PRT(" ");
+ PRT(" %2.2x", src[i]);
+ }
+ PRT("\n");
+ } else {
+ if (ed->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
+ desc = be32dec(src);
+ else
+ desc = le32dec(src);
+ PRT("%d\n", desc);
+ }
+ src += roundup2(descsz, 4);
+ count -= roundup2(descsz, 4);
+ }
+}
+
+/*
+ * Dump a hash table.
+ */
+static void
+elf_print_svr4_hash(struct elfdump *ed, struct section *s)
+{
+ Elf_Data *data;
+ uint32_t *buf;
+ uint32_t *bucket, *chain;
+ uint32_t nbucket, nchain;
+ uint32_t *bl, *c, maxl, total;
+ int i, j, first, elferr;
+ char idx[10];
+
+ if (ed->flags & SOLARIS_FMT)
+ PRT("\nHash Section: %s\n", s->name);
+ else
+ PRT("\nhash table (%s):\n", s->name);
+ (void) elf_errno();
+ if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_getdata failed: %s",
+ elf_errmsg(elferr));
+ return;
+ }
+ if (data->d_size < 2 * sizeof(uint32_t)) {
+ warnx(".hash section too small");
+ return;
+ }
+ buf = data->d_buf;
+ nbucket = buf[0];
+ nchain = buf[1];
+ if (nbucket <= 0 || nchain <= 0) {
+ warnx("Malformed .hash section");
+ return;
+ }
+ if (data->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) {
+ warnx("Malformed .hash section");
+ return;
+ }
+ bucket = &buf[2];
+ chain = &buf[2 + nbucket];
+
+ if (ed->flags & SOLARIS_FMT) {
+ maxl = 0;
+ if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
+ err(EXIT_FAILURE, "calloc failed");
+ for (i = 0; (uint32_t)i < nbucket; i++)
+ for (j = bucket[i]; j > 0 && (uint32_t)j < nchain;
+ j = chain[j])
+ if (++bl[i] > maxl)
+ maxl = bl[i];
+ if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
+ err(EXIT_FAILURE, "calloc failed");
+ for (i = 0; (uint32_t)i < nbucket; i++)
+ c[bl[i]]++;
+ PRT(" bucket symndx name\n");
+ for (i = 0; (uint32_t)i < nbucket; i++) {
+ first = 1;
+ for (j = bucket[i]; j > 0 && (uint32_t)j < nchain;
+ j = chain[j]) {
+ if (first) {
+ PRT("%10d ", i);
+ first = 0;
+ } else
+ PRT(" ");
+ snprintf(idx, sizeof(idx), "[%d]", j);
+ PRT("%-10s ", idx);
+ PRT("%s\n", get_symbol_name(ed, s->link, j));
+ }
+ }
+ PRT("\n");
+ total = 0;
+ for (i = 0; (uint32_t)i <= maxl; i++) {
+ total += c[i] * i;
+ PRT("%10u buckets contain %8d symbols\n", c[i], i);
+ }
+ PRT("%10u buckets %8u symbols (globals)\n", nbucket,
+ total);
+ } else {
+ PRT("\nnbucket: %u\n", nbucket);
+ PRT("nchain: %u\n\n", nchain);
+ for (i = 0; (uint32_t)i < nbucket; i++)
+ PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]);
+ for (i = 0; (uint32_t)i < nchain; i++)
+ PRT("chain[%d]:\n\t%u\n\n", i, chain[i]);
+ }
+}
+
+/*
+ * Dump a 64bit hash table.
+ */
+static void
+elf_print_svr4_hash64(struct elfdump *ed, struct section *s)
+{
+ Elf_Data *data, dst;
+ uint64_t *buf;
+ uint64_t *bucket, *chain;
+ uint64_t nbucket, nchain;
+ uint64_t *bl, *c, maxl, total;
+ int i, j, elferr, first;
+ char idx[10];
+
+ if (ed->flags & SOLARIS_FMT)
+ PRT("\nHash Section: %s\n", s->name);
+ else
+ PRT("\nhash table (%s):\n", s->name);
+
+ /*
+ * ALPHA uses 64-bit hash entries. Since libelf assumes that
+ * .hash section contains only 32-bit entry, an explicit
+ * gelf_xlatetom is needed here.
+ */
+ (void) elf_errno();
+ if ((data = elf_rawdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_rawdata failed: %s",
+ elf_errmsg(elferr));
+ return;
+ }
+ data->d_type = ELF_T_XWORD;
+ memcpy(&dst, data, sizeof(Elf_Data));
+ if (gelf_xlatetom(ed->elf, &dst, data,
+ ed->ehdr.e_ident[EI_DATA]) != &dst) {
+ warnx("gelf_xlatetom failed: %s", elf_errmsg(-1));
+ return;
+ }
+ if (dst.d_size < 2 * sizeof(uint64_t)) {
+ warnx(".hash section too small");
+ return;
+ }
+ buf = dst.d_buf;
+ nbucket = buf[0];
+ nchain = buf[1];
+ if (nbucket <= 0 || nchain <= 0) {
+ warnx("Malformed .hash section");
+ return;
+ }
+ if (dst.d_size != (nbucket + nchain + 2) * sizeof(uint64_t)) {
+ warnx("Malformed .hash section");
+ return;
+ }
+ bucket = &buf[2];
+ chain = &buf[2 + nbucket];
+
+ if (ed->flags & SOLARIS_FMT) {
+ maxl = 0;
+ if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
+ err(EXIT_FAILURE, "calloc failed");
+ for (i = 0; (uint64_t)i < nbucket; i++)
+ for (j = bucket[i]; j > 0 && (uint64_t)j < nchain;
+ j = chain[j])
+ if (++bl[i] > maxl)
+ maxl = bl[i];
+ if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
+ err(EXIT_FAILURE, "calloc failed");
+ for (i = 0; (uint64_t)i < nbucket; i++)
+ c[bl[i]]++;
+ PRT(" bucket symndx name\n");
+ for (i = 0; (uint64_t)i < nbucket; i++) {
+ first = 1;
+ for (j = bucket[i]; j > 0 && (uint64_t)j < nchain;
+ j = chain[j]) {
+ if (first) {
+ PRT("%10d ", i);
+ first = 0;
+ } else
+ PRT(" ");
+ snprintf(idx, sizeof(idx), "[%d]", j);
+ PRT("%-10s ", idx);
+ PRT("%s\n", get_symbol_name(ed, s->link, j));
+ }
+ }
+ PRT("\n");
+ total = 0;
+ for (i = 0; (uint64_t)i <= maxl; i++) {
+ total += c[i] * i;
+ PRT("%10ju buckets contain %8d symbols\n",
+ (uintmax_t)c[i], i);
+ }
+ PRT("%10ju buckets %8ju symbols (globals)\n",
+ (uintmax_t)nbucket, (uintmax_t)total);
+ } else {
+ PRT("\nnbucket: %ju\n", (uintmax_t)nbucket);
+ PRT("nchain: %ju\n\n", (uintmax_t)nchain);
+ for (i = 0; (uint64_t)i < nbucket; i++)
+ PRT("bucket[%d]:\n\t%ju\n\n", i, (uintmax_t)bucket[i]);
+ for (i = 0; (uint64_t)i < nchain; i++)
+ PRT("chain[%d]:\n\t%ju\n\n", i, (uintmax_t)chain[i]);
+ }
+
+}
+
+/*
+ * Dump a GNU hash table.
+ */
+static void
+elf_print_gnu_hash(struct elfdump *ed, struct section *s)
+{
+ struct section *ds;
+ Elf_Data *data;
+ uint32_t *buf;
+ uint32_t *bucket, *chain;
+ uint32_t nbucket, nchain, symndx, maskwords, shift2;
+ uint32_t *bl, *c, maxl, total;
+ int i, j, first, elferr, dynsymcount;
+ char idx[10];
+
+ if (ed->flags & SOLARIS_FMT)
+ PRT("\nGNU Hash Section: %s\n", s->name);
+ else
+ PRT("\ngnu hash table (%s):\n", s->name);
+ (void) elf_errno();
+ if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_getdata failed: %s",
+ elf_errmsg(elferr));
+ return;
+ }
+ if (data->d_size < 4 * sizeof(uint32_t)) {
+ warnx(".gnu.hash section too small");
+ return;
+ }
+ buf = data->d_buf;
+ nbucket = buf[0];
+ symndx = buf[1];
+ maskwords = buf[2];
+ shift2 = buf[3];
+ buf += 4;
+ ds = &ed->sl[s->link];
+ dynsymcount = ds->sz / ds->entsize;
+ nchain = dynsymcount - symndx;
+ if (data->d_size != 4 * sizeof(uint32_t) + maskwords *
+ (ed->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) +
+ (nbucket + nchain) * sizeof(uint32_t)) {
+ warnx("Malformed .gnu.hash section");
+ return;
+ }
+ bucket = buf + (ed->ec == ELFCLASS32 ? maskwords : maskwords * 2);
+ chain = bucket + nbucket;
+
+ if (ed->flags & SOLARIS_FMT) {
+ maxl = 0;
+ if ((bl = calloc(nbucket, sizeof(*bl))) == NULL)
+ err(EXIT_FAILURE, "calloc failed");
+ for (i = 0; (uint32_t)i < nbucket; i++)
+ for (j = bucket[i];
+ j > 0 && (uint32_t)j - symndx < nchain;
+ j++) {
+ if (++bl[i] > maxl)
+ maxl = bl[i];
+ if (chain[j - symndx] & 1)
+ break;
+ }
+ if ((c = calloc(maxl + 1, sizeof(*c))) == NULL)
+ err(EXIT_FAILURE, "calloc failed");
+ for (i = 0; (uint32_t)i < nbucket; i++)
+ c[bl[i]]++;
+ PRT(" bucket symndx name\n");
+ for (i = 0; (uint32_t)i < nbucket; i++) {
+ first = 1;
+ for (j = bucket[i];
+ j > 0 && (uint32_t)j - symndx < nchain;
+ j++) {
+ if (first) {
+ PRT("%10d ", i);
+ first = 0;
+ } else
+ PRT(" ");
+ snprintf(idx, sizeof(idx), "[%d]", j );
+ PRT("%-10s ", idx);
+ PRT("%s\n", get_symbol_name(ed, s->link, j));
+ if (chain[j - symndx] & 1)
+ break;
+ }
+ }
+ PRT("\n");
+ total = 0;
+ for (i = 0; (uint32_t)i <= maxl; i++) {
+ total += c[i] * i;
+ PRT("%10u buckets contain %8d symbols\n", c[i], i);
+ }
+ PRT("%10u buckets %8u symbols (globals)\n", nbucket,
+ total);
+ } else {
+ PRT("\nnbucket: %u\n", nbucket);
+ PRT("symndx: %u\n", symndx);
+ PRT("maskwords: %u\n", maskwords);
+ PRT("shift2: %u\n", shift2);
+ PRT("nchain: %u\n\n", nchain);
+ for (i = 0; (uint32_t)i < nbucket; i++)
+ PRT("bucket[%d]:\n\t%u\n\n", i, bucket[i]);
+ for (i = 0; (uint32_t)i < nchain; i++)
+ PRT("chain[%d]:\n\t%u\n\n", i, chain[i]);
+ }
+}
+
+/*
+ * Dump hash tables.
+ */
+static void
+elf_print_hash(struct elfdump *ed)
+{
+ struct section *s;
+ int i;
+
+ for (i = 0; (size_t)i < ed->shnum; i++) {
+ s = &ed->sl[i];
+ if ((s->type == SHT_HASH || s->type == SHT_GNU_HASH) &&
+ (STAILQ_EMPTY(&ed->snl) || find_name(ed, s->name))) {
+ if (s->type == SHT_GNU_HASH)
+ elf_print_gnu_hash(ed, s);
+ else if (ed->ehdr.e_machine == EM_ALPHA &&
+ s->entsize == 8)
+ elf_print_svr4_hash64(ed, s);
+ else
+ elf_print_svr4_hash(ed, s);
+ }
+ }
+}
+
+/*
+ * Dump the content of a Version Definition(SHT_SUNW_Verdef) Section.
+ */
+static void
+elf_print_verdef(struct elfdump *ed, struct section *s)
+{
+ Elf_Data *data;
+ Elf32_Verdef *vd;
+ Elf32_Verdaux *vda;
+ const char *str;
+ char idx[10];
+ uint8_t *buf, *end, *buf2;
+ int i, j, elferr, count;
+
+ if (ed->flags & SOLARIS_FMT)
+ PRT("Version Definition Section: %s\n", s->name);
+ else
+ PRT("\nversion definition section (%s):\n", s->name);
+ (void) elf_errno();
+ if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_getdata failed: %s",
+ elf_errmsg(elferr));
+ return;
+ }
+ buf = data->d_buf;
+ end = buf + data->d_size;
+ i = 0;
+ if (ed->flags & SOLARIS_FMT)
+ PRT(" index version dependency\n");
+ while (buf + sizeof(Elf32_Verdef) <= end) {
+ vd = (Elf32_Verdef *) (uintptr_t) buf;
+ if (ed->flags & SOLARIS_FMT) {
+ snprintf(idx, sizeof(idx), "[%d]", vd->vd_ndx);
+ PRT("%10s ", idx);
+ } else {
+ PRT("\nentry: %d\n", i++);
+ PRT("\tvd_version: %u\n", vd->vd_version);
+ PRT("\tvd_flags: %u\n", vd->vd_flags);
+ PRT("\tvd_ndx: %u\n", vd->vd_ndx);
+ PRT("\tvd_cnt: %u\n", vd->vd_cnt);
+ PRT("\tvd_hash: %u\n", vd->vd_hash);
+ PRT("\tvd_aux: %u\n", vd->vd_aux);
+ PRT("\tvd_next: %u\n\n", vd->vd_next);
+ }
+ buf2 = buf + vd->vd_aux;
+ j = 0;
+ count = 0;
+ while (buf2 + sizeof(Elf32_Verdaux) <= end && j < vd->vd_cnt) {
+ vda = (Elf32_Verdaux *) (uintptr_t) buf2;
+ str = get_string(ed, s->link, vda->vda_name);
+ if (ed->flags & SOLARIS_FMT) {
+ if (count == 0)
+ PRT("%-26.26s", str);
+ else if (count == 1)
+ PRT(" %-20.20s", str);
+ else {
+ PRT("\n%40.40s", "");
+ PRT("%s", str);
+ }
+ } else {
+ PRT("\t\tvda: %d\n", j++);
+ PRT("\t\t\tvda_name: %s\n", str);
+ PRT("\t\t\tvda_next: %u\n", vda->vda_next);
+ }
+ if (vda->vda_next == 0) {
+ if (ed->flags & SOLARIS_FMT) {
+ if (vd->vd_flags & VER_FLG_BASE) {
+ if (count == 0)
+ PRT("%-20.20s", "");
+ PRT("%s", "[ BASE ]");
+ }
+ PRT("\n");
+ }
+ break;
+ }
+ if (ed->flags & SOLARIS_FMT)
+ count++;
+ buf2 += vda->vda_next;
+ }
+ if (vd->vd_next == 0)
+ break;
+ buf += vd->vd_next;
+ }
+}
+
+/*
+ * Dump the content of a Version Needed(SHT_SUNW_Verneed) Section.
+ */
+static void
+elf_print_verneed(struct elfdump *ed, struct section *s)
+{
+ Elf_Data *data;
+ Elf32_Verneed *vn;
+ Elf32_Vernaux *vna;
+ uint8_t *buf, *end, *buf2;
+ int i, j, elferr, first;
+
+ if (ed->flags & SOLARIS_FMT)
+ PRT("\nVersion Needed Section: %s\n", s->name);
+ else
+ PRT("\nversion need section (%s):\n", s->name);
+ (void) elf_errno();
+ if ((data = elf_getdata(s->scn, NULL)) == NULL) {
+ elferr = elf_errno();
+ if (elferr != 0)
+ warnx("elf_getdata failed: %s",
+ elf_errmsg(elferr));
+ return;
+ }
+ buf = data->d_buf;
+ end = buf + data->d_size;
+ if (ed->flags & SOLARIS_FMT)
+ PRT(" file version\n");
+ i = 0;
+ while (buf + sizeof(Elf32_Verneed) <= end) {
+ vn = (Elf32_Verneed *) (uintptr_t) buf;
+ if (ed->flags & SOLARIS_FMT)
+ PRT(" %-26.26s ",
+ get_string(ed, s->link, vn->vn_file));
+ else {
+ PRT("\nentry: %d\n", i++);
+ PRT("\tvn_version: %u\n", vn->vn_version);
+ PRT("\tvn_cnt: %u\n", vn->vn_cnt);
+ PRT("\tvn_file: %s\n",
+ get_string(ed, s->link, vn->vn_file));
+ PRT("\tvn_aux: %u\n", vn->vn_aux);
+ PRT("\tvn_next: %u\n\n", vn->vn_next);
+ }
+ buf2 = buf + vn->vn_aux;
+ j = 0;
+ first = 1;
+ while (buf2 + sizeof(Elf32_Vernaux) <= end && j < vn->vn_cnt) {
+ vna = (Elf32_Vernaux *) (uintptr_t) buf2;
+ if (ed->flags & SOLARIS_FMT) {
+ if (!first)
+ PRT("%40.40s", "");
+ else
+ first = 0;
+ PRT("%s\n", get_string(ed, s->link,
+ vna->vna_name));
+ } else {
+ PRT("\t\tvna: %d\n", j++);
+ PRT("\t\t\tvna_hash: %u\n", vna->vna_hash);
+ PRT("\t\t\tvna_flags: %u\n", vna->vna_flags);
+ PRT("\t\t\tvna_other: %u\n", vna->vna_other);
+ PRT("\t\t\tvna_name: %s\n",
+ get_string(ed, s->link, vna->vna_name));
+ PRT("\t\t\tvna_next: %u\n", vna->vna_next);
+ }
+ if (vna->vna_next == 0)
+ break;
+ buf2 += vna->vna_next;
+ }
+ if (vn->vn_next == 0)
+ break;
+ buf += vn->vn_next;
+ }
+}
+
+/*
+ * Dump the symbol-versioning sections.
+ */
+static void
+elf_print_symver(struct elfdump *ed)
+{
+ struct section *s;
+ int i;
+
+ for (i = 0; (size_t)i < ed->shnum; i++) {
+ s = &ed->sl[i];
+ if (!STAILQ_EMPTY(&ed->snl) && !find_name(ed, s->name))
+ continue;
+ if (s->type == SHT_SUNW_verdef)
+ elf_print_verdef(ed, s);
+ if (s->type == SHT_SUNW_verneed)
+ elf_print_verneed(ed, s);
+ }
+}
+
+/*
+ * Dump the ELF checksum. See gelf_checksum(3) for details.
+ */
+static void
+elf_print_checksum(struct elfdump *ed)
+{
+
+ if (!STAILQ_EMPTY(&ed->snl))
+ return;
+
+ PRT("\nelf checksum: %#lx\n", gelf_checksum(ed->elf));
+}
+
+#define USAGE_MESSAGE "\
+Usage: %s [options] file...\n\
+ Display information about ELF objects and ar(1) archives.\n\n\
+ Options:\n\
+ -a Show all information.\n\
+ -c Show shared headers.\n\
+ -d Show dynamic symbols.\n\
+ -e Show the ELF header.\n\
+ -G Show the GOT.\n\
+ -H | --help Show a usage message and exit.\n\
+ -h Show hash values.\n\
+ -i Show the dynamic interpreter.\n\
+ -k Show the ELF checksum.\n\
+ -n Show the contents of note sections.\n\
+ -N NAME Show the section named \"NAME\".\n\
+ -p Show the program header.\n\
+ -r Show relocations.\n\
+ -s Show the symbol table.\n\
+ -S Use the Solaris elfdump format.\n\
+ -v Show symbol-versioning information.\n\
+ -V | --version Print a version identifier and exit.\n\
+ -w FILE Write output to \"FILE\".\n"
+
+static void
+usage(void)
+{
+ fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
+ exit(EXIT_FAILURE);
+}
diff --git a/contrib/gcc/c-cppbuiltin.c b/contrib/gcc/c-cppbuiltin.c
index 6b65cdf..511104f 100644
--- a/contrib/gcc/c-cppbuiltin.c
+++ b/contrib/gcc/c-cppbuiltin.c
@@ -553,7 +553,9 @@ c_cpp_builtins (cpp_reader *pfile)
/* Make the choice of the stack protector runtime visible to source code.
The macro names and values here were chosen for compatibility with an
earlier implementation, i.e. ProPolice. */
- if (flag_stack_protect == 2)
+ if (flag_stack_protect == 3)
+ cpp_define (pfile, "__SSP_STRONG__=3");
+ else if (flag_stack_protect == 2)
cpp_define (pfile, "__SSP_ALL__=2");
else if (flag_stack_protect == 1)
cpp_define (pfile, "__SSP__=1");
diff --git a/contrib/gcc/cfgexpand.c b/contrib/gcc/cfgexpand.c
index b688917..ccb534f 100644
--- a/contrib/gcc/cfgexpand.c
+++ b/contrib/gcc/cfgexpand.c
@@ -810,6 +810,12 @@ clear_tree_used (tree block)
clear_tree_used (t);
}
+enum {
+ SPCT_FLAG_DEFAULT = 1,
+ SPCT_FLAG_ALL = 2,
+ SPCT_FLAG_STRONG = 3
+};
+
/* Examine TYPE and determine a bit mask of the following features. */
#define SPCT_HAS_LARGE_CHAR_ARRAY 1
@@ -879,7 +885,8 @@ stack_protect_decl_phase (tree decl)
if (bits & SPCT_HAS_SMALL_CHAR_ARRAY)
has_short_buffer = true;
- if (flag_stack_protect == 2)
+ if (flag_stack_protect == SPCT_FLAG_ALL
+ || flag_stack_protect == SPCT_FLAG_STRONG)
{
if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY))
&& !(bits & SPCT_HAS_AGGREGATE))
@@ -947,12 +954,36 @@ create_stack_guard (void)
cfun->stack_protect_guard = guard;
}
+/* Helper routine to check if a record or union contains an array field. */
+
+static int
+record_or_union_type_has_array_p (tree tree_type)
+{
+ tree fields = TYPE_FIELDS (tree_type);
+ tree f;
+
+ for (f = fields; f; f = TREE_CHAIN (f))
+ if (TREE_CODE (f) == FIELD_DECL)
+ {
+ tree field_type = TREE_TYPE (f);
+ if ((TREE_CODE (field_type) == RECORD_TYPE
+ || TREE_CODE (field_type) == UNION_TYPE
+ || TREE_CODE (field_type) == QUAL_UNION_TYPE)
+ && record_or_union_type_has_array_p (field_type))
+ return 1;
+ if (TREE_CODE (field_type) == ARRAY_TYPE)
+ return 1;
+ }
+ return 0;
+}
+
/* Expand all variables used in the function. */
static void
expand_used_vars (void)
{
tree t, outer_block = DECL_INITIAL (current_function_decl);
+ bool gen_stack_protect_signal = false;
/* Compute the phase of the stack frame for this function. */
{
@@ -972,6 +1003,29 @@ expand_used_vars (void)
has_protected_decls = false;
has_short_buffer = false;
+ if (flag_stack_protect == SPCT_FLAG_STRONG)
+ for (t = cfun->unexpanded_var_list; t; t = TREE_CHAIN (t))
+ {
+ tree var = TREE_VALUE (t);
+ if (!is_global_var (var))
+ {
+ tree var_type = TREE_TYPE (var);
+ /* Examine local referenced variables that have their addresses
+ * taken, contain an array, or are arrays. */
+ if (TREE_CODE (var) == VAR_DECL
+ && (TREE_CODE (var_type) == ARRAY_TYPE
+ || TREE_ADDRESSABLE (var)
+ || ((TREE_CODE (var_type) == RECORD_TYPE
+ || TREE_CODE (var_type) == UNION_TYPE
+ || TREE_CODE (var_type) == QUAL_UNION_TYPE)
+ && record_or_union_type_has_array_p (var_type))))
+ {
+ gen_stack_protect_signal = true;
+ break;
+ }
+ }
+ }
+
/* At this point all variables on the unexpanded_var_list with TREE_USED
set are not associated with any block scope. Lay them out. */
for (t = cfun->unexpanded_var_list; t; t = TREE_CHAIN (t))
@@ -1032,12 +1086,26 @@ expand_used_vars (void)
dump_stack_var_partition ();
}
- /* There are several conditions under which we should create a
- stack guard: protect-all, alloca used, protected decls present. */
- if (flag_stack_protect == 2
- || (flag_stack_protect
- && (current_function_calls_alloca || has_protected_decls)))
- create_stack_guard ();
+ switch (flag_stack_protect)
+ {
+ case SPCT_FLAG_ALL:
+ create_stack_guard ();
+ break;
+
+ case SPCT_FLAG_STRONG:
+ if (gen_stack_protect_signal
+ || current_function_calls_alloca || has_protected_decls)
+ create_stack_guard ();
+ break;
+
+ case SPCT_FLAG_DEFAULT:
+ if (current_function_calls_alloca || has_protected_decls)
+ create_stack_guard();
+ break;
+
+ default:
+ ;
+ }
/* Assign rtl to each variable based on these partitions. */
if (stack_vars_num > 0)
diff --git a/contrib/gcc/common.opt b/contrib/gcc/common.opt
index 7dd3909..c185d1f 100644
--- a/contrib/gcc/common.opt
+++ b/contrib/gcc/common.opt
@@ -878,6 +878,10 @@ fstack-protector-all
Common Report RejectNegative Var(flag_stack_protect, 2) VarExists
Use a stack protection method for every function
+fstack-protector-strong
+Common Report RejectNegative Var(flag_stack_protect, 3)
+Use a smart stack protection method for certain functions
+
fstrength-reduce
Common
Does nothing. Preserved for backward compatibility.
diff --git a/contrib/gcc/doc/cpp.texi b/contrib/gcc/doc/cpp.texi
index 7c21c56..26bc6b7 100644
--- a/contrib/gcc/doc/cpp.texi
+++ b/contrib/gcc/doc/cpp.texi
@@ -2134,6 +2134,10 @@ use.
This macro is defined, with value 2, when @option{-fstack-protector-all} is
in use.
+@item __SSP_STRONG__
+This macro is defined, with value 3, when @option{-fstack-protector-strong} is
+in use.
+
@item __TIMESTAMP__
This macro expands to a string constant that describes the date and time
of the last modification of the current source file. The string constant
diff --git a/contrib/gcc/doc/gcc.1 b/contrib/gcc/doc/gcc.1
index 1879d76..8afd6aa 100644
--- a/contrib/gcc/doc/gcc.1
+++ b/contrib/gcc/doc/gcc.1
@@ -339,7 +339,7 @@ in the following sections.
\&\fB\-fsched2\-use\-superblocks
\&\-fsched2\-use\-traces \-fsee \-freschedule\-modulo\-scheduled\-loops
\&\-fsection\-anchors \-fsignaling\-nans \-fsingle\-precision\-constant
-\&\-fstack\-protector \-fstack\-protector\-all
+\&\-fstack\-protector \-fstack\-protector\-all \-fstack\-protector\-strong
\&\-fstrict\-aliasing \-fstrict\-overflow \-ftracer \-fthread\-jumps
\&\-funroll\-all\-loops \-funroll\-loops \-fpeel\-loops
\&\-fsplit\-ivs\-in\-unroller \-funswitch\-loops
@@ -5193,6 +5193,11 @@ If a guard check fails, an error message is printed and the program exits.
.IP "\fB\-fstack\-protector\-all\fR" 4
.IX Item "-fstack-protector-all"
Like \fB\-fstack\-protector\fR except that all functions are protected.
+.IP "\fB\-fstack\-protector\-strong\fR" 4
+.IX Item "-fstack-protector-strong"
+Like \fB\-fstack\-protector\fR but includes additional functions to
+be protected \-\-\- those that have local array definitions, or have
+references to local frame addresses.
.IP "\fB\-fsection\-anchors\fR" 4
.IX Item "-fsection-anchors"
Try to reduce the number of symbolic address calculations by using
diff --git a/contrib/gcc/doc/invoke.texi b/contrib/gcc/doc/invoke.texi
index 4779bbd..2bf48c3 100644
--- a/contrib/gcc/doc/invoke.texi
+++ b/contrib/gcc/doc/invoke.texi
@@ -331,7 +331,7 @@ in the following sections.
-fsched2-use-superblocks @gol
-fsched2-use-traces -fsee -freschedule-modulo-scheduled-loops @gol
-fsection-anchors -fsignaling-nans -fsingle-precision-constant @gol
--fstack-protector -fstack-protector-all @gol
+-fstack-protector -fstack-protector-all -fstack-protector-strong @gol
-fstrict-aliasing -fstrict-overflow -ftracer -fthread-jumps @gol
-funroll-all-loops -funroll-loops -fpeel-loops @gol
-fsplit-ivs-in-unroller -funswitch-loops @gol
@@ -5810,6 +5810,11 @@ If a guard check fails, an error message is printed and the program exits.
@item -fstack-protector-all
Like @option{-fstack-protector} except that all functions are protected.
+@item -fstack-protector-strong
+Like @option{-fstack-protector} but includes additional functions to
+be protected --- those that have local array definitions, or have
+references to local frame addresses.
+
@item -fsection-anchors
@opindex fsection-anchors
Try to reduce the number of symbolic address calculations by using
diff --git a/contrib/gcc/gcc.c b/contrib/gcc/gcc.c
index 5ed3a82..91e750a 100644
--- a/contrib/gcc/gcc.c
+++ b/contrib/gcc/gcc.c
@@ -680,7 +680,7 @@ proper position among the other output files. */
#ifdef TARGET_LIBC_PROVIDES_SSP
#define LINK_SSP_SPEC "%{fstack-protector:}"
#else
-#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all:-lssp_nonshared -lssp}"
+#define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-strong|fstack-protector-all:-lssp_nonshared -lssp}"
#endif
#endif
diff --git a/contrib/libarchive/libarchive/archive_read_support_format_tar.c b/contrib/libarchive/libarchive/archive_read_support_format_tar.c
index fde339a..c2003e7 100644
--- a/contrib/libarchive/libarchive/archive_read_support_format_tar.c
+++ b/contrib/libarchive/libarchive/archive_read_support_format_tar.c
@@ -585,13 +585,23 @@ static int
archive_read_format_tar_skip(struct archive_read *a)
{
int64_t bytes_skipped;
+ int64_t request;
+ struct sparse_block *p;
struct tar* tar;
tar = (struct tar *)(a->format->data);
- bytes_skipped = __archive_read_consume(a,
- tar->entry_bytes_remaining + tar->entry_padding +
- tar->entry_bytes_unconsumed);
+ /* Do not consume the hole of a sparse file. */
+ request = 0;
+ for (p = tar->sparse_list; p != NULL; p = p->next) {
+ if (!p->hole)
+ request += p->remaining;
+ }
+ if (request > tar->entry_bytes_remaining)
+ request = tar->entry_bytes_remaining;
+ request += tar->entry_padding + tar->entry_bytes_unconsumed;
+
+ bytes_skipped = __archive_read_consume(a, request);
if (bytes_skipped < 0)
return (ARCHIVE_FATAL);
diff --git a/contrib/libarchive/libarchive/test/test_read_format_gtar_sparse_skip_entry.c b/contrib/libarchive/libarchive/test/test_read_format_gtar_sparse_skip_entry.c
new file mode 100644
index 0000000..20567c7
--- /dev/null
+++ b/contrib/libarchive/libarchive/test/test_read_format_gtar_sparse_skip_entry.c
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 2014 Michihiro NAKAJIMA
+ * 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(S) ``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(S) 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 "test.h"
+__FBSDID("$FreeBSD");
+
+/*
+ * To test skip a sparse file entry, this test does not read file data.
+ */
+DEFINE_TEST(test_read_format_gtar_sparse_skip_entry)
+{
+#ifndef __FreeBSD__ /* Backport test. */
+ const char *refname = "test_read_format_gtar_sparse_skip_entry.tar.Z.uu";
+#else
+ const char *refname = "test_read_format_gtar_sparse_skip_entry.tar.Z";
+#endif
+ struct archive *a;
+ struct archive_entry *ae;
+ const void *p;
+ size_t s;
+ int64_t o;
+
+#ifndef __FreeBSD__ /* Backport test. */
+ copy_reference_file(refname);
+#else
+ extract_reference_file(refname);
+#endif
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_filename(a, refname, 10240));
+
+ /* Verify regular first file. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("a", archive_entry_pathname(ae));
+ assertEqualInt(10737418244, archive_entry_size(ae));
+#ifndef __FreeBSD__ /* Backport test. */
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a),
+ ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
+#endif
+
+ /* Verify regular second file. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("b", archive_entry_pathname(ae));
+ assertEqualInt(4, archive_entry_size(ae));
+#ifndef __FreeBSD__ /* Backport test. */
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a),
+ ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
+#endif
+
+
+ /* End of archive. */
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+ /* Verify archive format. */
+ assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0));
+ assertEqualIntA(a, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE,
+ archive_format(a));
+
+ /* Close the archive. */
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+
+
+ /*
+ * Read just one block of a sparse file and skip it.
+ */
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_filename(a, refname, 10240));
+
+ /* Verify regular first file. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("a", archive_entry_pathname(ae));
+ assertEqualInt(10737418244, archive_entry_size(ae));
+#ifndef __FreeBSD__ /* Backport test. */
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a),
+ ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
+#endif
+ assertEqualInt(0, archive_read_data_block(a, &p, &s, &o));
+ assertEqualInt(4096, s);
+ assertEqualInt(0, o);
+
+
+ /* Verify regular second file. */
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+ assertEqualString("b", archive_entry_pathname(ae));
+ assertEqualInt(4, archive_entry_size(ae));
+#ifndef __FreeBSD__ /* Backport test. */
+ assertEqualInt(archive_entry_is_encrypted(ae), 0);
+ assertEqualIntA(a, archive_read_has_encrypted_entries(a),
+ ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
+#endif
+
+
+ /* End of archive. */
+ assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+ /* Verify archive format. */
+ assertEqualIntA(a, ARCHIVE_FILTER_COMPRESS, archive_filter_code(a, 0));
+ assertEqualIntA(a, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE,
+ archive_format(a));
+
+ /* Close the archive. */
+ assertEqualInt(ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_free(a));
+}
+
diff --git a/contrib/libarchive/libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu b/contrib/libarchive/libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu
new file mode 100644
index 0000000..dc0daae
--- /dev/null
+++ b/contrib/libarchive/libarchive/test/test_read_format_gtar_sparse_skip_entry.tar.Z.uu
@@ -0,0 +1,15 @@
+begin 644 -
+M'YV04,+@05(F#)DR<EZ$`<"PH<.'$"-*G$BQHL6*,#+:L$$#!(",,6[4@.$1
+MI$B2'S.JS#A#A@P0,63,L`$C!HP9-VB\K"FCAHT8`$#@N4BTJ-&C2"/6F4,G
+MC)R48^J424HQZE2J$E=F+*G5(]:O8,.*'3M6!LDY:?24Z6'S!DX:,7#(H$%#
+MP0R2;>BD:;,V!@T8-6)NE&'#10T<-#;>R(%CAEV28_3R9?LW\(P8-F[`<#%C
+M)@T<->#6>`PBC.2^E07;J#'#Q>J-F5DJ<`GBB),J+N;`<3JGC(LV8=2\D<-V
+M]DO;N'7S]MTFC9OA/6#,CE'[=N[=<GJ[<!-F<AB[-:HGQZY=3D$V:-6RA>$V
+M9]RY=<G*GT^_OOW[^/.#13Z%?!DC:;!1AD+Z%6B12AMUE%)((W'%($I:U603
+M#!W%-%---^6T4PPM8184#`:&"-9233V5D57SH2A?A%RMY)6(,,8HHPP*2/=7
+M#C8HT-9;[_VE0'PR!BGDD$06:>212"9YD1EOO*&`DE!&*>645%9IY9589JGE
+MEEQVZ>678(8IYIADEFGFF6BFJ>::;+;IYIMPQBGGG'36:>>=>.:IYYY\]NGG
+MGX`&*NB@A!9JJ)YB](D@1PZ>U&B#*468484RT11###7<8!8(&-)4PX=^DN@4
+B5%*E6.J*746JTHN'2LFDDZW&*NNLM-9JZZVXYJKKKKR&!0``
+`
+end
diff --git a/contrib/llvm/tools/lldb/docs/lldb.1 b/contrib/llvm/tools/lldb/docs/lldb.1
index 0d94dcb..57b0931 100644
--- a/contrib/llvm/tools/lldb/docs/lldb.1
+++ b/contrib/llvm/tools/lldb/docs/lldb.1
@@ -1,6 +1,6 @@
.Dd June 7, 2012 \" DATE
.Dt LLDB 1 \" Program name and manual section number
-.Os Darwin \" Operating System
+.Os
.Sh NAME \" Section Header - required - don't modify
.Nm lldb
.Nd The debugger
diff --git a/contrib/sendmail/FREEBSD-upgrade b/contrib/sendmail/FREEBSD-upgrade
index 64adce4..451a2a0 100644
--- a/contrib/sendmail/FREEBSD-upgrade
+++ b/contrib/sendmail/FREEBSD-upgrade
@@ -86,6 +86,7 @@ infrastructure in FreeBSD:
share/man/man8/rc.sendmail.8
share/mk/bsd.libnames.mk
share/sendmail/Makefile
+ tools/build/mk/OptionalObsoleteFiles.inc
usr.bin/Makefile
usr.bin/vacation/Makefile
usr.sbin/Makefile
diff --git a/crypto/openssh/auth2-chall.c b/crypto/openssh/auth2-chall.c
index 980250a..791be5c 100644
--- a/crypto/openssh/auth2-chall.c
+++ b/crypto/openssh/auth2-chall.c
@@ -82,6 +82,7 @@ struct KbdintAuthctxt
void *ctxt;
KbdintDevice *device;
u_int nreq;
+ u_int devices_done;
};
#ifdef USE_PAM
@@ -168,11 +169,15 @@ kbdint_next_device(Authctxt *authctxt, KbdintAuthctxt *kbdintctxt)
if (len == 0)
break;
for (i = 0; devices[i]; i++) {
- if (!auth2_method_allowed(authctxt,
+ if ((kbdintctxt->devices_done & (1 << i)) != 0 ||
+ !auth2_method_allowed(authctxt,
"keyboard-interactive", devices[i]->name))
continue;
- if (strncmp(kbdintctxt->devices, devices[i]->name, len) == 0)
+ if (strncmp(kbdintctxt->devices, devices[i]->name,
+ len) == 0) {
kbdintctxt->device = devices[i];
+ kbdintctxt->devices_done |= 1 << i;
+ }
}
t = kbdintctxt->devices;
kbdintctxt->devices = t[len] ? xstrdup(t+len+1) : NULL;
diff --git a/crypto/openssh/sshconnect.c b/crypto/openssh/sshconnect.c
index fd8ad1d..25ced57 100644
--- a/crypto/openssh/sshconnect.c
+++ b/crypto/openssh/sshconnect.c
@@ -1247,29 +1247,39 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
{
int flags = 0;
char *fp;
+ Key *plain = NULL;
fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
debug("Server host key: %s %s", key_type(host_key), fp);
free(fp);
- /* XXX certs are not yet supported for DNS */
- if (!key_is_cert(host_key) && options.verify_host_key_dns &&
- verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
- if (flags & DNS_VERIFY_FOUND) {
-
- if (options.verify_host_key_dns == 1 &&
- flags & DNS_VERIFY_MATCH &&
- flags & DNS_VERIFY_SECURE)
- return 0;
-
- if (flags & DNS_VERIFY_MATCH) {
- matching_host_key_dns = 1;
- } else {
- warn_changed_key(host_key);
- error("Update the SSHFP RR in DNS with the new "
- "host key to get rid of this message.");
+ if (options.verify_host_key_dns) {
+ /*
+ * XXX certs are not yet supported for DNS, so downgrade
+ * them and try the plain key.
+ */
+ plain = key_from_private(host_key);
+ if (key_is_cert(plain))
+ key_drop_cert(plain);
+ if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) {
+ if (flags & DNS_VERIFY_FOUND) {
+ if (options.verify_host_key_dns == 1 &&
+ flags & DNS_VERIFY_MATCH &&
+ flags & DNS_VERIFY_SECURE) {
+ key_free(plain);
+ return 0;
+ }
+ if (flags & DNS_VERIFY_MATCH) {
+ matching_host_key_dns = 1;
+ } else {
+ warn_changed_key(plain);
+ error("Update the SSHFP RR in DNS "
+ "with the new host key to get rid "
+ "of this message.");
+ }
}
}
+ key_free(plain);
}
return check_host_key(host, hostaddr, options.port, host_key, RDRW,
diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf
index 125d59e..fbe18db 100644
--- a/etc/defaults/rc.conf
+++ b/etc/defaults/rc.conf
@@ -664,7 +664,7 @@ opensm_enable="NO" # Opensm(8) for infiniband devices defaults to off
casperd_enable="YES" # casperd(8) daemon
# rctl(8) requires kernel options RACCT and RCTL
-rctl_enable="NO" # Load rctl(8) rules on boot
+rctl_enable="YES" # Load rctl(8) rules on boot
rctl_rules="/etc/rctl.conf" # rctl(8) ruleset. See rctl.conf(5).
iovctl_files="" # Config files for iovctl(8)
diff --git a/etc/network.subr b/etc/network.subr
index 73ed575..5087a93 100644
--- a/etc/network.subr
+++ b/etc/network.subr
@@ -1249,6 +1249,70 @@ ifscript_down()
fi
}
+# wlan_up
+# Create IEEE802.3 interfaces.
+#
+wlan_up()
+{
+ local _list _iflist wlan parent ifn
+ _list=
+ _iflist=$*
+
+ for wlan in `set | egrep ^wlans_[a-z]+[0-9]+=[a-z]+[0-9]+`; do
+ # Parse wlans_$parent=$ifn
+ wlan=`echo $wlan | sed -E 's/wlans_([a-z]+[0-9]+)=([a-z]+[0-9]+)/\1:\2/'`
+ OIFS=$IFS; IFS=:; set -- $wlan; parent=$1; ifn=$2; IFS=$OIFS
+ case $_iflist in
+ ""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn) ;;
+ *) continue ;;
+ esac
+ # Skip if ${ifn} already exists.
+ if ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
+ continue
+ fi
+ ${IFCONFIG_CMD} ${ifn} create wlandev ${parent}
+ if [ $? -eq 0 ]; then
+ _list="$_list $ifn"
+ fi
+ done
+ if [ -n "${_list# }" ]; then
+ echo "Created wlan(4) interfaces: ${_list# }."
+ fi
+ debug "Created wlan(4)s: ${_list# }"
+}
+
+# wlan_down
+# Destroy IEEE802.3 interfaces.
+#
+wlan_down()
+{
+ local _list _iflist wlan parent ifn
+ _list=
+ _iflist=$*
+
+ for wlan in `set | egrep ^wlans_[a-z]+[0-9]+=[a-z]+[0-9]+`; do
+ # Parse wlans_$parent=$ifn
+ wlan=`echo $wlan | sed -E 's/wlans_([a-z]+[0-9]+)=([a-z]+[0-9]+)/\1:\2/'`
+ OIFS=$IFS; IFS=:; set -- $wlan; parent=$1; ifn=$2; IFS=$OIFS
+ case $_iflist in
+ ""|$ifn|$ifn\ *|*\ $ifn\ *|*\ $ifn) ;;
+ *) continue ;;
+ esac
+ # Skip if ${ifn} doesn't exists.
+ if ! ${IFCONFIG_CMD} $ifn > /dev/null 2>&1; then
+ continue
+ fi
+ ${IFCONFIG_CMD} -n ${ifn} destroy
+ if [ $? -eq 0 ]; then
+ _list="$_list $ifn"
+ fi
+ done
+ if [ -n "${_list# }" ]; then
+ echo "Destroyed wlan(4) interfaces: ${_list# }."
+ fi
+ debug "Destroyed wlan(4)s: ${_list# }"
+}
+
# clone_up
# Create cloneable interfaces.
#
@@ -1398,6 +1462,9 @@ clone_down()
# Create and configure child interfaces. Return 0 if child
# interfaces are created.
#
+# XXXGL: the wlan code in this functions is superseded by wlan_up(),
+# and will go away soon.
+#
childif_create()
{
local cfg child child_vlans child_wlans create_args debug_flags ifn i
diff --git a/etc/portsnap.conf b/etc/portsnap.conf
index d308260..f6c18de 100644
--- a/etc/portsnap.conf
+++ b/etc/portsnap.conf
@@ -30,6 +30,6 @@ KEYPRINT=9b5feee6d69f170e3dd0a2c8e469ddbd64f13f978f2f3aede40c98633216c330
# REFUSE korean polish portuguese russian ukrainian vietnamese
# List of INDEX files to build and the DESCRIBE file to use for each
-INDEX INDEX-8 DESCRIBE.8
INDEX INDEX-9 DESCRIBE.9
INDEX INDEX-10 DESCRIBE.10
+INDEX INDEX-11 DESCRIBE.11
diff --git a/etc/rc.d/netif b/etc/rc.d/netif
index 0915b28..c7b84b9 100755
--- a/etc/rc.d/netif
+++ b/etc/rc.d/netif
@@ -37,6 +37,8 @@ name="netif"
rcvar="${name}_enable"
start_cmd="netif_start"
stop_cmd="netif_stop"
+wlanup_cmd="wlan_up"
+wlandown_cmd="wlan_down"
cloneup_cmd="clone_up"
clonedown_cmd="clone_down"
clear_cmd="doclear"
@@ -65,6 +67,9 @@ netif_start()
trap : 2
fi
+ # Create IEEE802.3 interface
+ wlan_up $cmdifn
+
# Create cloned interfaces
clone_up $cmdifn
@@ -91,12 +96,14 @@ netif_start()
netif_stop()
{
_clone_down=1
+ _wlan_down=1
netif_stop0 $*
}
doclear()
{
_clone_down=
+ _wlan_down=
netif_stop0 $*
}
@@ -111,6 +118,11 @@ netif_stop0()
# Deconfigure the interface(s)
netif_common ifn_stop $cmdifn
+ # Destroy wlan interfaces
+ if [ -n "$_wlan_down" ]; then
+ wlan_down $cmdifn
+ fi
+
# Destroy cloned interfaces
if [ -n "$_clone_down" ]; then
clone_down $cmdifn
diff --git a/etc/rc.d/rctl b/etc/rc.d/rctl
index 567436b..93b200d 100755
--- a/etc/rc.d/rctl
+++ b/etc/rc.d/rctl
@@ -10,6 +10,7 @@
. /etc/rc.subr
name="rctl"
+rcvar="rctl_enable"
start_cmd="rctl_start"
stop_cmd="rctl_stop"
diff --git a/etc/rc.subr b/etc/rc.subr
index 7b1e387..c23c8fd 100644
--- a/etc/rc.subr
+++ b/etc/rc.subr
@@ -1266,8 +1266,11 @@ _run_rc_killcmd()
# run_rc_script file arg
# Start the script `file' with `arg', and correctly handle the
# return value from the script.
-# If `file' ends with `.sh', it's sourced into the current environment
-# when $rc_fast_and_loose is set, otherwise it is run as a child process.
+# If `file' ends with `.sh' and lives in /etc/rc.d, ignore it as it's
+# an old-style startup file.
+# If `file' ends with `.sh' and does not live in /etc/rc.d, it's sourced
+# into the current environment if $rc_fast_and_loose is set; otherwise
+# it is run as a child process.
# If `file' appears to be a backup or scratch file, ignore it.
# Otherwise if it is executable run as a child process.
#
@@ -1333,7 +1336,8 @@ load_rc_config()
# If a service name was specified, attempt to load
# service-specific configuration
if [ -n "$_name" ] ; then
- for _d in /etc ${local_startup%*/rc.d}; do
+ for _d in /etc ${local_startup}; do
+ _d=${_d%/rc.d}
if [ -f ${_d}/rc.conf.d/"$_name" ]; then
debug "Sourcing ${_d}/rc.conf.d/$_name"
. ${_d}/rc.conf.d/"$_name"
diff --git a/gnu/usr.bin/binutils/Makefile b/gnu/usr.bin/binutils/Makefile
index 1c863df..d8ebdb1 100644
--- a/gnu/usr.bin/binutils/Makefile
+++ b/gnu/usr.bin/binutils/Makefile
@@ -7,24 +7,13 @@ SUBDIR= doc\
libbfd \
libopcodes \
libbinutils \
- ${_addr2line} \
as \
ld \
- ${_nm} \
- objcopy \
+ ${_objcopy} \
objdump \
- ${_readelf} \
- ${_size} \
- ${_strings} \
- ${_strip}
-.if ${MK_ELFTOOLCHAIN_TOOLS} == "no"
-_addr2line= addr2line
-_nm= nm
-_readelf= readelf
-_size= size
-_strings= strings
-_strip= strip
+.if ${MK_ELFTOOLCHAIN_TOOLS} == "no" || ${MK_ELFCOPY_AS_OBJCOPY} == "no"
+_objcopy= objcopy
.endif
.include <bsd.subdir.mk>
diff --git a/gnu/usr.bin/binutils/addr2line/Makefile b/gnu/usr.bin/binutils/addr2line/Makefile
deleted file mode 100644
index 2380738..0000000
--- a/gnu/usr.bin/binutils/addr2line/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# $FreeBSD$
-
-.include "../Makefile.inc0"
-
-.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
-
-PROG= addr2line
-SRCS= addr2line.c
-CFLAGS+= -D_GNU_SOURCE
-CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
-CFLAGS+= -I${SRCDIR}/binutils
-DPADD= ${RELTOP}/libbinutils/libbinutils.a
-DPADD+= ${RELTOP}/libbfd/libbfd.a
-DPADD+= ${RELTOP}/libiberty/libiberty.a
-LDADD= ${DPADD}
-
-.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/addr2line/Makefile.depend b/gnu/usr.bin/binutils/addr2line/Makefile.depend
deleted file mode 100644
index b58c9bd..0000000
--- a/gnu/usr.bin/binutils/addr2line/Makefile.depend
+++ /dev/null
@@ -1,21 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- gnu/lib/libgcc \
- gnu/usr.bin/binutils/libbfd \
- gnu/usr.bin/binutils/libbinutils \
- gnu/usr.bin/binutils/libiberty \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/gnu/usr.bin/binutils/addr2line/addr2line.1 b/gnu/usr.bin/binutils/addr2line/addr2line.1
deleted file mode 100644
index 4f76544..0000000
--- a/gnu/usr.bin/binutils/addr2line/addr2line.1
+++ /dev/null
@@ -1,266 +0,0 @@
-.\" $FreeBSD$
-.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
-.\"
-.\" Standard preamble:
-.\" ========================================================================
-.de Sp \" Vertical space (when we can't use .PP)
-.if t .sp .5v
-.if n .sp
-..
-.de Vb \" Begin verbatim text
-.ft CW
-.nf
-.ne \\$1
-..
-.de Ve \" End verbatim text
-.ft R
-.fi
-..
-.\" Set up some character translations and predefined strings. \*(-- will
-.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
-.\" double quote, and \*(R" will give a right double quote. \*(C+ will
-.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
-.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
-.\" nothing in troff, for use with C<>.
-.tr \(*W-
-.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
-.ie n \{\
-. ds -- \(*W-
-. ds PI pi
-. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
-. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
-. ds L" ""
-. ds R" ""
-. ds C` ""
-. ds C' ""
-'br\}
-.el\{\
-. ds -- \|\(em\|
-. ds PI \(*p
-. ds L" ``
-. ds R" ''
-'br\}
-.\"
-.\" Escape single quotes in literal strings from groff's Unicode transform.
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\"
-.\" If the F register is turned on, we'll generate index entries on stderr for
-.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
-.\" entries marked with X<> in POD. Of course, you'll have to process the
-.\" output yourself in some meaningful fashion.
-.ie \nF \{\
-. de IX
-. tm Index:\\$1\t\\n%\t"\\$2"
-..
-. nr % 0
-. rr F
-.\}
-.el \{\
-. de IX
-..
-.\}
-.\"
-.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
-.\" Fear. Run. Save yourself. No user-serviceable parts.
-. \" fudge factors for nroff and troff
-.if n \{\
-. ds #H 0
-. ds #V .8m
-. ds #F .3m
-. ds #[ \f1
-. ds #] \fP
-.\}
-.if t \{\
-. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
-. ds #V .6m
-. ds #F 0
-. ds #[ \&
-. ds #] \&
-.\}
-. \" simple accents for nroff and troff
-.if n \{\
-. ds ' \&
-. ds ` \&
-. ds ^ \&
-. ds , \&
-. ds ~ ~
-. ds /
-.\}
-.if t \{\
-. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
-. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
-. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
-. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
-. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
-. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
-.\}
-. \" troff and (daisy-wheel) nroff accents
-.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
-.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
-.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
-.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
-.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
-.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
-.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
-.ds ae a\h'-(\w'a'u*4/10)'e
-.ds Ae A\h'-(\w'A'u*4/10)'E
-. \" corrections for vroff
-.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
-.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
-. \" for low resolution devices (crt and lpr)
-.if \n(.H>23 .if \n(.V>19 \
-\{\
-. ds : e
-. ds 8 ss
-. ds o a
-. ds d- d\h'-1'\(ga
-. ds D- D\h'-1'\(hy
-. ds th \o'bp'
-. ds Th \o'LP'
-. ds ae ae
-. ds Ae AE
-.\}
-.rm #[ #] #H #V #F C
-.\" ========================================================================
-.\"
-.IX Title "ADDR2LINE 1"
-.TH ADDR2LINE 1 "2010-10-30" "binutils-2.17.50" "GNU Development Tools"
-.\" For nroff, turn off justification. Always turn off hyphenation; it makes
-.\" way too many mistakes in technical documents.
-.if n .ad l
-.nh
-.SH "NAME"
-addr2line \- convert addresses into file names and line numbers
-.SH "SYNOPSIS"
-.IX Header "SYNOPSIS"
-addr2line [\fB\-b\fR \fIbfdname\fR|\fB\-\-target=\fR\fIbfdname\fR]
- [\fB\-C\fR|\fB\-\-demangle\fR[=\fIstyle\fR]]
- [\fB\-e\fR \fIfilename\fR|\fB\-\-exe=\fR\fIfilename\fR]
- [\fB\-f\fR|\fB\-\-functions\fR] [\fB\-s\fR|\fB\-\-basename\fR]
- [\fB\-i\fR|\fB\-\-inlines\fR]
- [\fB\-j\fR|\fB\-\-section=\fR\fIname\fR]
- [\fB\-H\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR]
- [addr addr ...]
-.SH "DESCRIPTION"
-.IX Header "DESCRIPTION"
-\&\fBaddr2line\fR translates addresses into file names and line numbers.
-Given an address in an executable or an offset in a section of a relocatable
-object, it uses the debugging information to figure out which file name and
-line number are associated with it.
-.PP
-The executable or relocatable object to use is specified with the \fB\-e\fR
-option. The default is the file \fIa.out\fR. The section in the relocatable
-object to use is specified with the \fB\-j\fR option.
-.PP
-\&\fBaddr2line\fR has two modes of operation.
-.PP
-In the first, hexadecimal addresses are specified on the command line,
-and \fBaddr2line\fR displays the file name and line number for each
-address.
-.PP
-In the second, \fBaddr2line\fR reads hexadecimal addresses from
-standard input, and prints the file name and line number for each
-address on standard output. In this mode, \fBaddr2line\fR may be used
-in a pipe to convert dynamically chosen addresses.
-.PP
-The format of the output is \fB\s-1FILENAME:LINENO\s0\fR. The file name and
-line number for each address is printed on a separate line. If the
-\&\fB\-f\fR option is used, then each \fB\s-1FILENAME:LINENO\s0\fR line is
-preceded by a \fB\s-1FUNCTIONNAME\s0\fR line which is the name of the function
-containing the address.
-.PP
-If the file name or function name can not be determined,
-\&\fBaddr2line\fR will print two question marks in their place. If the
-line number can not be determined, \fBaddr2line\fR will print 0.
-.SH "OPTIONS"
-.IX Header "OPTIONS"
-The long and short forms of options, shown here as alternatives, are
-equivalent.
-.IP "\fB\-b\fR \fIbfdname\fR" 4
-.IX Item "-b bfdname"
-.PD 0
-.IP "\fB\-\-target=\fR\fIbfdname\fR" 4
-.IX Item "--target=bfdname"
-.PD
-Specify that the object-code format for the object files is
-\&\fIbfdname\fR.
-.IP "\fB\-C\fR" 4
-.IX Item "-C"
-.PD 0
-.IP "\fB\-\-demangle[=\fR\fIstyle\fR\fB]\fR" 4
-.IX Item "--demangle[=style]"
-.PD
-Decode (\fIdemangle\fR) low-level symbol names into user-level names.
-Besides removing any initial underscore prepended by the system, this
-makes \*(C+ function names readable. Different compilers have different
-mangling styles. The optional demangling style argument can be used to
-choose an appropriate demangling style for your compiler.
-.IP "\fB\-e\fR \fIfilename\fR" 4
-.IX Item "-e filename"
-.PD 0
-.IP "\fB\-\-exe=\fR\fIfilename\fR" 4
-.IX Item "--exe=filename"
-.PD
-Specify the name of the executable for which addresses should be
-translated. The default file is \fIa.out\fR.
-.IP "\fB\-f\fR" 4
-.IX Item "-f"
-.PD 0
-.IP "\fB\-\-functions\fR" 4
-.IX Item "--functions"
-.PD
-Display function names as well as file and line number information.
-.IP "\fB\-s\fR" 4
-.IX Item "-s"
-.PD 0
-.IP "\fB\-\-basenames\fR" 4
-.IX Item "--basenames"
-.PD
-Display only the base of each file name.
-.IP "\fB\-i\fR" 4
-.IX Item "-i"
-.PD 0
-.IP "\fB\-\-inlines\fR" 4
-.IX Item "--inlines"
-.PD
-If the address belongs to a function that was inlined, the source
-information for all enclosing scopes back to the first non-inlined
-function will also be printed. For example, if \f(CW\*(C`main\*(C'\fR inlines
-\&\f(CW\*(C`callee1\*(C'\fR which inlines \f(CW\*(C`callee2\*(C'\fR, and address is from
-\&\f(CW\*(C`callee2\*(C'\fR, the source information for \f(CW\*(C`callee1\*(C'\fR and \f(CW\*(C`main\*(C'\fR
-will also be printed.
-.IP "\fB\-j\fR" 4
-.IX Item "-j"
-.PD 0
-.IP "\fB\-\-section\fR" 4
-.IX Item "--section"
-.PD
-Read offsets relative to the specified section instead of absolute addresses.
-.IP "\fB@\fR\fIfile\fR" 4
-.IX Item "@file"
-Read command-line options from \fIfile\fR. The options read are
-inserted in place of the original @\fIfile\fR option. If \fIfile\fR
-does not exist, or cannot be read, then the option will be treated
-literally, and not removed.
-.Sp
-Options in \fIfile\fR are separated by whitespace. A whitespace
-character may be included in an option by surrounding the entire
-option in either single or double quotes. Any character (including a
-backslash) may be included by prefixing the character to be included
-with a backslash. The \fIfile\fR may itself contain additional
-@\fIfile\fR options; any such options will be processed recursively.
-.SH "SEE ALSO"
-.IX Header "SEE ALSO"
-Info entries for \fIbinutils\fR.
-.SH "COPYRIGHT"
-.IX Header "COPYRIGHT"
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
-.PP
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the \s-1GNU\s0 Free Documentation License, Version 1.1
-or any later version published by the Free Software Foundation;
-with no Invariant Sections, with no Front-Cover Texts, and with no
-Back-Cover Texts. A copy of the license is included in the
-section entitled \*(L"\s-1GNU\s0 Free Documentation License\*(R".
diff --git a/gnu/usr.bin/binutils/ar/Makefile.depend b/gnu/usr.bin/binutils/ar/Makefile.depend
deleted file mode 100644
index 9a5a4f9..0000000
--- a/gnu/usr.bin/binutils/ar/Makefile.depend
+++ /dev/null
@@ -1,21 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DIRDEPS = \
- gnu/usr.bin/binutils/libbfd \
- gnu/usr.bin/binutils/libbinutils \
- gnu/usr.bin/binutils/libiberty \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/gnu/usr.bin/binutils/nm/Makefile b/gnu/usr.bin/binutils/nm/Makefile
deleted file mode 100644
index 4ef2b8f..0000000
--- a/gnu/usr.bin/binutils/nm/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# $FreeBSD$
-
-.include "../Makefile.inc0"
-
-.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
-
-PROG= nm
-SRCS= nm.c
-CFLAGS+= -D_GNU_SOURCE
-CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
-CFLAGS+= -I${SRCDIR}/bfd
-CFLAGS+= -I${SRCDIR}/binutils
-DPADD= ${RELTOP}/libbinutils/libbinutils.a
-DPADD+= ${RELTOP}/libbfd/libbfd.a
-DPADD+= ${RELTOP}/libiberty/libiberty.a
-LDADD= ${DPADD}
-
-.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/nm/Makefile.depend b/gnu/usr.bin/binutils/nm/Makefile.depend
deleted file mode 100644
index b58c9bd..0000000
--- a/gnu/usr.bin/binutils/nm/Makefile.depend
+++ /dev/null
@@ -1,21 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- gnu/lib/libgcc \
- gnu/usr.bin/binutils/libbfd \
- gnu/usr.bin/binutils/libbinutils \
- gnu/usr.bin/binutils/libiberty \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/gnu/usr.bin/binutils/nm/nm.1 b/gnu/usr.bin/binutils/nm/nm.1
deleted file mode 100644
index e94e472..0000000
--- a/gnu/usr.bin/binutils/nm/nm.1
+++ /dev/null
@@ -1,450 +0,0 @@
-.\" $FreeBSD$
-.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
-.\"
-.\" Standard preamble:
-.\" ========================================================================
-.de Sp \" Vertical space (when we can't use .PP)
-.if t .sp .5v
-.if n .sp
-..
-.de Vb \" Begin verbatim text
-.ft CW
-.nf
-.ne \\$1
-..
-.de Ve \" End verbatim text
-.ft R
-.fi
-..
-.\" Set up some character translations and predefined strings. \*(-- will
-.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
-.\" double quote, and \*(R" will give a right double quote. \*(C+ will
-.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
-.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
-.\" nothing in troff, for use with C<>.
-.tr \(*W-
-.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
-.ie n \{\
-. ds -- \(*W-
-. ds PI pi
-. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
-. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
-. ds L" ""
-. ds R" ""
-. ds C` ""
-. ds C' ""
-'br\}
-.el\{\
-. ds -- \|\(em\|
-. ds PI \(*p
-. ds L" ``
-. ds R" ''
-'br\}
-.\"
-.\" Escape single quotes in literal strings from groff's Unicode transform.
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\"
-.\" If the F register is turned on, we'll generate index entries on stderr for
-.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
-.\" entries marked with X<> in POD. Of course, you'll have to process the
-.\" output yourself in some meaningful fashion.
-.ie \nF \{\
-. de IX
-. tm Index:\\$1\t\\n%\t"\\$2"
-..
-. nr % 0
-. rr F
-.\}
-.el \{\
-. de IX
-..
-.\}
-.\"
-.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
-.\" Fear. Run. Save yourself. No user-serviceable parts.
-. \" fudge factors for nroff and troff
-.if n \{\
-. ds #H 0
-. ds #V .8m
-. ds #F .3m
-. ds #[ \f1
-. ds #] \fP
-.\}
-.if t \{\
-. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
-. ds #V .6m
-. ds #F 0
-. ds #[ \&
-. ds #] \&
-.\}
-. \" simple accents for nroff and troff
-.if n \{\
-. ds ' \&
-. ds ` \&
-. ds ^ \&
-. ds , \&
-. ds ~ ~
-. ds /
-.\}
-.if t \{\
-. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
-. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
-. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
-. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
-. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
-. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
-.\}
-. \" troff and (daisy-wheel) nroff accents
-.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
-.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
-.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
-.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
-.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
-.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
-.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
-.ds ae a\h'-(\w'a'u*4/10)'e
-.ds Ae A\h'-(\w'A'u*4/10)'E
-. \" corrections for vroff
-.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
-.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
-. \" for low resolution devices (crt and lpr)
-.if \n(.H>23 .if \n(.V>19 \
-\{\
-. ds : e
-. ds 8 ss
-. ds o a
-. ds d- d\h'-1'\(ga
-. ds D- D\h'-1'\(hy
-. ds th \o'bp'
-. ds Th \o'LP'
-. ds ae ae
-. ds Ae AE
-.\}
-.rm #[ #] #H #V #F C
-.\" ========================================================================
-.\"
-.IX Title "NM 1"
-.TH NM 1 "2010-10-30" "binutils-2.17.50" "GNU Development Tools"
-.\" For nroff, turn off justification. Always turn off hyphenation; it makes
-.\" way too many mistakes in technical documents.
-.if n .ad l
-.nh
-.SH "NAME"
-nm \- list symbols from object files
-.SH "SYNOPSIS"
-.IX Header "SYNOPSIS"
-nm [\fB\-a\fR|\fB\-\-debug\-syms\fR] [\fB\-g\fR|\fB\-\-extern\-only\fR]
- [\fB\-B\fR] [\fB\-C\fR|\fB\-\-demangle\fR[=\fIstyle\fR]] [\fB\-D\fR|\fB\-\-dynamic\fR]
- [\fB\-S\fR|\fB\-\-print\-size\fR] [\fB\-s\fR|\fB\-\-print\-armap\fR]
- [\fB\-A\fR|\fB\-o\fR|\fB\-\-print\-file\-name\fR][\fB\-\-special\-syms\fR]
- [\fB\-n\fR|\fB\-v\fR|\fB\-\-numeric\-sort\fR] [\fB\-p\fR|\fB\-\-no\-sort\fR]
- [\fB\-r\fR|\fB\-\-reverse\-sort\fR] [\fB\-\-size\-sort\fR] [\fB\-u\fR|\fB\-\-undefined\-only\fR]
- [\fB\-t\fR \fIradix\fR|\fB\-\-radix=\fR\fIradix\fR] [\fB\-P\fR|\fB\-\-portability\fR]
- [\fB\-\-target=\fR\fIbfdname\fR] [\fB\-f\fR\fIformat\fR|\fB\-\-format=\fR\fIformat\fR]
- [\fB\-\-defined\-only\fR] [\fB\-l\fR|\fB\-\-line\-numbers\fR] [\fB\-\-no\-demangle\fR]
- [\fB\-V\fR|\fB\-\-version\fR] [\fB\-X 32_64\fR] [\fB\-\-help\fR] [\fIobjfile\fR...]
-.SH "DESCRIPTION"
-.IX Header "DESCRIPTION"
-\&\s-1GNU\s0 \fBnm\fR lists the symbols from object files \fIobjfile\fR....
-If no object files are listed as arguments, \fBnm\fR assumes the file
-\&\fIa.out\fR.
-.PP
-For each symbol, \fBnm\fR shows:
-.IP "\(bu" 4
-The symbol value, in the radix selected by options (see below), or
-hexadecimal by default.
-.IP "\(bu" 4
-The symbol type. At least the following types are used; others are, as
-well, depending on the object file format. If lowercase, the symbol is
-local; if uppercase, the symbol is global (external).
-.RS 4
-.ie n .IP """A""" 4
-.el .IP "\f(CWA\fR" 4
-.IX Item "A"
-The symbol's value is absolute, and will not be changed by further
-linking.
-.ie n .IP """B""" 4
-.el .IP "\f(CWB\fR" 4
-.IX Item "B"
-The symbol is in the uninitialized data section (known as \s-1BSS\s0).
-.ie n .IP """C""" 4
-.el .IP "\f(CWC\fR" 4
-.IX Item "C"
-The symbol is common. Common symbols are uninitialized data. When
-linking, multiple common symbols may appear with the same name. If the
-symbol is defined anywhere, the common symbols are treated as undefined
-references.
-.ie n .IP """D""" 4
-.el .IP "\f(CWD\fR" 4
-.IX Item "D"
-The symbol is in the initialized data section.
-.ie n .IP """G""" 4
-.el .IP "\f(CWG\fR" 4
-.IX Item "G"
-The symbol is in an initialized data section for small objects. Some
-object file formats permit more efficient access to small data objects,
-such as a global int variable as opposed to a large global array.
-.ie n .IP """I""" 4
-.el .IP "\f(CWI\fR" 4
-.IX Item "I"
-The symbol is an indirect reference to another symbol. This is a \s-1GNU\s0
-extension to the a.out object file format which is rarely used.
-.ie n .IP """N""" 4
-.el .IP "\f(CWN\fR" 4
-.IX Item "N"
-The symbol is a debugging symbol.
-.ie n .IP """R""" 4
-.el .IP "\f(CWR\fR" 4
-.IX Item "R"
-The symbol is in a read only data section.
-.ie n .IP """S""" 4
-.el .IP "\f(CWS\fR" 4
-.IX Item "S"
-The symbol is in an uninitialized data section for small objects.
-.ie n .IP """T""" 4
-.el .IP "\f(CWT\fR" 4
-.IX Item "T"
-The symbol is in the text (code) section.
-.ie n .IP """U""" 4
-.el .IP "\f(CWU\fR" 4
-.IX Item "U"
-The symbol is undefined.
-.ie n .IP """V""" 4
-.el .IP "\f(CWV\fR" 4
-.IX Item "V"
-The symbol is a weak object. When a weak defined symbol is linked with
-a normal defined symbol, the normal defined symbol is used with no error.
-When a weak undefined symbol is linked and the symbol is not defined,
-the value of the weak symbol becomes zero with no error.
-.ie n .IP """W""" 4
-.el .IP "\f(CWW\fR" 4
-.IX Item "W"
-The symbol is a weak symbol that has not been specifically tagged as a
-weak object symbol. When a weak defined symbol is linked with a normal
-defined symbol, the normal defined symbol is used with no error.
-When a weak undefined symbol is linked and the symbol is not defined,
-the value of the symbol is determined in a system-specific manner without
-error. On some systems, uppercase indicates that a default value has been
-specified.
-.ie n .IP """\-""" 4
-.el .IP "\f(CW\-\fR" 4
-.IX Item "-"
-The symbol is a stabs symbol in an a.out object file. In this case, the
-next values printed are the stabs other field, the stabs desc field, and
-the stab type. Stabs symbols are used to hold debugging information.
-.ie n .IP """?""" 4
-.el .IP "\f(CW?\fR" 4
-.IX Item "?"
-The symbol type is unknown, or object file format specific.
-.RE
-.RS 4
-.RE
-.IP "\(bu" 4
-The symbol name.
-.SH "OPTIONS"
-.IX Header "OPTIONS"
-The long and short forms of options, shown here as alternatives, are
-equivalent.
-.IP "\fB\-A\fR" 4
-.IX Item "-A"
-.PD 0
-.IP "\fB\-o\fR" 4
-.IX Item "-o"
-.IP "\fB\-\-print\-file\-name\fR" 4
-.IX Item "--print-file-name"
-.PD
-Precede each symbol by the name of the input file (or archive member)
-in which it was found, rather than identifying the input file once only,
-before all of its symbols.
-.IP "\fB\-a\fR" 4
-.IX Item "-a"
-.PD 0
-.IP "\fB\-\-debug\-syms\fR" 4
-.IX Item "--debug-syms"
-.PD
-Display all symbols, even debugger-only symbols; normally these are not
-listed.
-.IP "\fB\-B\fR" 4
-.IX Item "-B"
-The same as \fB\-\-format=bsd\fR (for compatibility with the \s-1MIPS\s0 \fBnm\fR).
-.IP "\fB\-C\fR" 4
-.IX Item "-C"
-.PD 0
-.IP "\fB\-\-demangle[=\fR\fIstyle\fR\fB]\fR" 4
-.IX Item "--demangle[=style]"
-.PD
-Decode (\fIdemangle\fR) low-level symbol names into user-level names.
-Besides removing any initial underscore prepended by the system, this
-makes \*(C+ function names readable. Different compilers have different
-mangling styles. The optional demangling style argument can be used to
-choose an appropriate demangling style for your compiler.
-.IP "\fB\-\-no\-demangle\fR" 4
-.IX Item "--no-demangle"
-Do not demangle low-level symbol names. This is the default.
-.IP "\fB\-D\fR" 4
-.IX Item "-D"
-.PD 0
-.IP "\fB\-\-dynamic\fR" 4
-.IX Item "--dynamic"
-.PD
-Display the dynamic symbols rather than the normal symbols. This is
-only meaningful for dynamic objects, such as certain types of shared
-libraries.
-.IP "\fB\-f\fR \fIformat\fR" 4
-.IX Item "-f format"
-.PD 0
-.IP "\fB\-\-format=\fR\fIformat\fR" 4
-.IX Item "--format=format"
-.PD
-Use the output format \fIformat\fR, which can be \f(CW\*(C`bsd\*(C'\fR,
-\&\f(CW\*(C`sysv\*(C'\fR, or \f(CW\*(C`posix\*(C'\fR. The default is \f(CW\*(C`bsd\*(C'\fR.
-Only the first character of \fIformat\fR is significant; it can be
-either upper or lower case.
-.IP "\fB\-g\fR" 4
-.IX Item "-g"
-.PD 0
-.IP "\fB\-\-extern\-only\fR" 4
-.IX Item "--extern-only"
-.PD
-Display only external symbols.
-.IP "\fB\-l\fR" 4
-.IX Item "-l"
-.PD 0
-.IP "\fB\-\-line\-numbers\fR" 4
-.IX Item "--line-numbers"
-.PD
-For each symbol, use debugging information to try to find a filename and
-line number. For a defined symbol, look for the line number of the
-address of the symbol. For an undefined symbol, look for the line
-number of a relocation entry which refers to the symbol. If line number
-information can be found, print it after the other symbol information.
-.IP "\fB\-n\fR" 4
-.IX Item "-n"
-.PD 0
-.IP "\fB\-v\fR" 4
-.IX Item "-v"
-.IP "\fB\-\-numeric\-sort\fR" 4
-.IX Item "--numeric-sort"
-.PD
-Sort symbols numerically by their addresses, rather than alphabetically
-by their names.
-.IP "\fB\-p\fR" 4
-.IX Item "-p"
-.PD 0
-.IP "\fB\-\-no\-sort\fR" 4
-.IX Item "--no-sort"
-.PD
-Do not bother to sort the symbols in any order; print them in the order
-encountered.
-.IP "\fB\-P\fR" 4
-.IX Item "-P"
-.PD 0
-.IP "\fB\-\-portability\fR" 4
-.IX Item "--portability"
-.PD
-Use the \s-1POSIX\s0.2 standard output format instead of the default format.
-Equivalent to \fB\-f posix\fR.
-.IP "\fB\-S\fR" 4
-.IX Item "-S"
-.PD 0
-.IP "\fB\-\-print\-size\fR" 4
-.IX Item "--print-size"
-.PD
-Print size, not the value, of defined symbols for the \f(CW\*(C`bsd\*(C'\fR output format.
-.IP "\fB\-s\fR" 4
-.IX Item "-s"
-.PD 0
-.IP "\fB\-\-print\-armap\fR" 4
-.IX Item "--print-armap"
-.PD
-When listing symbols from archive members, include the index: a mapping
-(stored in the archive by \fBar\fR or \fBranlib\fR) of which modules
-contain definitions for which names.
-.IP "\fB\-r\fR" 4
-.IX Item "-r"
-.PD 0
-.IP "\fB\-\-reverse\-sort\fR" 4
-.IX Item "--reverse-sort"
-.PD
-Reverse the order of the sort (whether numeric or alphabetic); let the
-last come first.
-.IP "\fB\-\-size\-sort\fR" 4
-.IX Item "--size-sort"
-Sort symbols by size. The size is computed as the difference between
-the value of the symbol and the value of the symbol with the next higher
-value. If the \f(CW\*(C`bsd\*(C'\fR output format is used the size of the symbol
-is printed, rather than the value, and \fB\-S\fR must be used in order
-both size and value to be printed.
-.IP "\fB\-\-special\-syms\fR" 4
-.IX Item "--special-syms"
-Display symbols which have a target-specific special meaning. These
-symbols are usually used by the target for some special processing and
-are not normally helpful when included included in the normal symbol
-lists. For example for \s-1ARM\s0 targets this option would skip the mapping
-symbols used to mark transitions between \s-1ARM\s0 code, \s-1THUMB\s0 code and
-data.
-.IP "\fB\-t\fR \fIradix\fR" 4
-.IX Item "-t radix"
-.PD 0
-.IP "\fB\-\-radix=\fR\fIradix\fR" 4
-.IX Item "--radix=radix"
-.PD
-Use \fIradix\fR as the radix for printing the symbol values. It must be
-\&\fBd\fR for decimal, \fBo\fR for octal, or \fBx\fR for hexadecimal.
-.IP "\fB\-\-target=\fR\fIbfdname\fR" 4
-.IX Item "--target=bfdname"
-Specify an object code format other than your system's default format.
-.IP "\fB\-u\fR" 4
-.IX Item "-u"
-.PD 0
-.IP "\fB\-\-undefined\-only\fR" 4
-.IX Item "--undefined-only"
-.PD
-Display only undefined symbols (those external to each object file).
-.IP "\fB\-\-defined\-only\fR" 4
-.IX Item "--defined-only"
-Display only defined symbols for each object file.
-.IP "\fB\-V\fR" 4
-.IX Item "-V"
-.PD 0
-.IP "\fB\-\-version\fR" 4
-.IX Item "--version"
-.PD
-Show the version number of \fBnm\fR and exit.
-.IP "\fB\-X\fR" 4
-.IX Item "-X"
-This option is ignored for compatibility with the \s-1AIX\s0 version of
-\&\fBnm\fR. It takes one parameter which must be the string
-\&\fB32_64\fR. The default mode of \s-1AIX\s0 \fBnm\fR corresponds
-to \fB\-X 32\fR, which is not supported by \s-1GNU\s0 \fBnm\fR.
-.IP "\fB\-\-help\fR" 4
-.IX Item "--help"
-Show a summary of the options to \fBnm\fR and exit.
-.IP "\fB@\fR\fIfile\fR" 4
-.IX Item "@file"
-Read command-line options from \fIfile\fR. The options read are
-inserted in place of the original @\fIfile\fR option. If \fIfile\fR
-does not exist, or cannot be read, then the option will be treated
-literally, and not removed.
-.Sp
-Options in \fIfile\fR are separated by whitespace. A whitespace
-character may be included in an option by surrounding the entire
-option in either single or double quotes. Any character (including a
-backslash) may be included by prefixing the character to be included
-with a backslash. The \fIfile\fR may itself contain additional
-@\fIfile\fR options; any such options will be processed recursively.
-.SH "SEE ALSO"
-.IX Header "SEE ALSO"
-\&\fIar\fR\|(1), \fIobjdump\fR\|(1), \fIranlib\fR\|(1), and the Info entries for \fIbinutils\fR.
-.SH "COPYRIGHT"
-.IX Header "COPYRIGHT"
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
-.PP
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the \s-1GNU\s0 Free Documentation License, Version 1.1
-or any later version published by the Free Software Foundation;
-with no Invariant Sections, with no Front-Cover Texts, and with no
-Back-Cover Texts. A copy of the license is included in the
-section entitled \*(L"\s-1GNU\s0 Free Documentation License\*(R".
diff --git a/gnu/usr.bin/binutils/ranlib/Makefile.depend b/gnu/usr.bin/binutils/ranlib/Makefile.depend
deleted file mode 100644
index 9a5a4f9..0000000
--- a/gnu/usr.bin/binutils/ranlib/Makefile.depend
+++ /dev/null
@@ -1,21 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DIRDEPS = \
- gnu/usr.bin/binutils/libbfd \
- gnu/usr.bin/binutils/libbinutils \
- gnu/usr.bin/binutils/libiberty \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/gnu/usr.bin/binutils/readelf/Makefile b/gnu/usr.bin/binutils/readelf/Makefile
deleted file mode 100644
index d90c3bc..0000000
--- a/gnu/usr.bin/binutils/readelf/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# $FreeBSD$
-
-.include "../Makefile.inc0"
-
-.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
-
-# No a.out vs. ELF version so don't install in /usr/libexec/elf
-BINDIR=/usr/bin
-
-PROG= readelf
-SRCS= ${PROG}.c
-CFLAGS+= -D_GNU_SOURCE
-CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils -I${SRCDIR}/binutils
-
-DPADD= ${RELTOP}/libbinutils/libbinutils.a
-DPADD+= ${RELTOP}/libbfd/libbfd.a
-DPADD+= ${RELTOP}/libiberty/libiberty.a
-LDADD= ${DPADD}
-
-.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/readelf/Makefile.depend b/gnu/usr.bin/binutils/readelf/Makefile.depend
deleted file mode 100644
index b58c9bd..0000000
--- a/gnu/usr.bin/binutils/readelf/Makefile.depend
+++ /dev/null
@@ -1,21 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- gnu/lib/libgcc \
- gnu/usr.bin/binutils/libbfd \
- gnu/usr.bin/binutils/libbinutils \
- gnu/usr.bin/binutils/libiberty \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/gnu/usr.bin/binutils/readelf/readelf.1 b/gnu/usr.bin/binutils/readelf/readelf.1
deleted file mode 100644
index e246d2c..0000000
--- a/gnu/usr.bin/binutils/readelf/readelf.1
+++ /dev/null
@@ -1,377 +0,0 @@
-.\" $FreeBSD$
-.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
-.\"
-.\" Standard preamble:
-.\" ========================================================================
-.de Sp \" Vertical space (when we can't use .PP)
-.if t .sp .5v
-.if n .sp
-..
-.de Vb \" Begin verbatim text
-.ft CW
-.nf
-.ne \\$1
-..
-.de Ve \" End verbatim text
-.ft R
-.fi
-..
-.\" Set up some character translations and predefined strings. \*(-- will
-.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
-.\" double quote, and \*(R" will give a right double quote. \*(C+ will
-.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
-.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
-.\" nothing in troff, for use with C<>.
-.tr \(*W-
-.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
-.ie n \{\
-. ds -- \(*W-
-. ds PI pi
-. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
-. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
-. ds L" ""
-. ds R" ""
-. ds C` ""
-. ds C' ""
-'br\}
-.el\{\
-. ds -- \|\(em\|
-. ds PI \(*p
-. ds L" ``
-. ds R" ''
-'br\}
-.\"
-.\" Escape single quotes in literal strings from groff's Unicode transform.
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\"
-.\" If the F register is turned on, we'll generate index entries on stderr for
-.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
-.\" entries marked with X<> in POD. Of course, you'll have to process the
-.\" output yourself in some meaningful fashion.
-.ie \nF \{\
-. de IX
-. tm Index:\\$1\t\\n%\t"\\$2"
-..
-. nr % 0
-. rr F
-.\}
-.el \{\
-. de IX
-..
-.\}
-.\"
-.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
-.\" Fear. Run. Save yourself. No user-serviceable parts.
-. \" fudge factors for nroff and troff
-.if n \{\
-. ds #H 0
-. ds #V .8m
-. ds #F .3m
-. ds #[ \f1
-. ds #] \fP
-.\}
-.if t \{\
-. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
-. ds #V .6m
-. ds #F 0
-. ds #[ \&
-. ds #] \&
-.\}
-. \" simple accents for nroff and troff
-.if n \{\
-. ds ' \&
-. ds ` \&
-. ds ^ \&
-. ds , \&
-. ds ~ ~
-. ds /
-.\}
-.if t \{\
-. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
-. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
-. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
-. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
-. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
-. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
-.\}
-. \" troff and (daisy-wheel) nroff accents
-.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
-.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
-.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
-.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
-.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
-.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
-.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
-.ds ae a\h'-(\w'a'u*4/10)'e
-.ds Ae A\h'-(\w'A'u*4/10)'E
-. \" corrections for vroff
-.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
-.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
-. \" for low resolution devices (crt and lpr)
-.if \n(.H>23 .if \n(.V>19 \
-\{\
-. ds : e
-. ds 8 ss
-. ds o a
-. ds d- d\h'-1'\(ga
-. ds D- D\h'-1'\(hy
-. ds th \o'bp'
-. ds Th \o'LP'
-. ds ae ae
-. ds Ae AE
-.\}
-.rm #[ #] #H #V #F C
-.\" ========================================================================
-.\"
-.IX Title "READELF 1"
-.TH READELF 1 "2010-10-30" "binutils-2.17.50" "GNU Development Tools"
-.\" For nroff, turn off justification. Always turn off hyphenation; it makes
-.\" way too many mistakes in technical documents.
-.if n .ad l
-.nh
-.SH "NAME"
-readelf \- Displays information about ELF files.
-.SH "SYNOPSIS"
-.IX Header "SYNOPSIS"
-readelf [\fB\-a\fR|\fB\-\-all\fR]
- [\fB\-h\fR|\fB\-\-file\-header\fR]
- [\fB\-l\fR|\fB\-\-program\-headers\fR|\fB\-\-segments\fR]
- [\fB\-S\fR|\fB\-\-section\-headers\fR|\fB\-\-sections\fR]
- [\fB\-g\fR|\fB\-\-section\-groups\fR]
- [\fB\-t\fR|\fB\-\-section\-details\fR]
- [\fB\-e\fR|\fB\-\-headers\fR]
- [\fB\-s\fR|\fB\-\-syms\fR|\fB\-\-symbols\fR]
- [\fB\-n\fR|\fB\-\-notes\fR]
- [\fB\-r\fR|\fB\-\-relocs\fR]
- [\fB\-u\fR|\fB\-\-unwind\fR]
- [\fB\-d\fR|\fB\-\-dynamic\fR]
- [\fB\-V\fR|\fB\-\-version\-info\fR]
- [\fB\-A\fR|\fB\-\-arch\-specific\fR]
- [\fB\-D\fR|\fB\-\-use\-dynamic\fR]
- [\fB\-x\fR <number or name>|\fB\-\-hex\-dump=\fR<number or name>]
- [\fB\-w[liaprmfFsoR]\fR|
- \fB\-\-debug\-dump\fR[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames\-interp,=str,=loc,=Ranges]]
- [\fB\-I\fR|\fB\-histogram\fR]
- [\fB\-v\fR|\fB\-\-version\fR]
- [\fB\-W\fR|\fB\-\-wide\fR]
- [\fB\-H\fR|\fB\-\-help\fR]
- \fIelffile\fR...
-.SH "DESCRIPTION"
-.IX Header "DESCRIPTION"
-\&\fBreadelf\fR displays information about one or more \s-1ELF\s0 format object
-files. The options control what particular information to display.
-.PP
-\&\fIelffile\fR... are the object files to be examined. 32\-bit and
-64\-bit \s-1ELF\s0 files are supported, as are archives containing \s-1ELF\s0 files.
-.PP
-This program performs a similar function to \fBobjdump\fR but it
-goes into more detail and it exists independently of the \s-1BFD\s0
-library, so if there is a bug in \s-1BFD\s0 then readelf will not be
-affected.
-.SH "OPTIONS"
-.IX Header "OPTIONS"
-The long and short forms of options, shown here as alternatives, are
-equivalent. At least one option besides \fB\-v\fR or \fB\-H\fR must be
-given.
-.IP "\fB\-a\fR" 4
-.IX Item "-a"
-.PD 0
-.IP "\fB\-\-all\fR" 4
-.IX Item "--all"
-.PD
-Equivalent to specifying \fB\-\-file\-header\fR,
-\&\fB\-\-program\-headers\fR, \fB\-\-sections\fR, \fB\-\-symbols\fR,
-\&\fB\-\-relocs\fR, \fB\-\-dynamic\fR, \fB\-\-notes\fR and
-\&\fB\-\-version\-info\fR.
-.IP "\fB\-h\fR" 4
-.IX Item "-h"
-.PD 0
-.IP "\fB\-\-file\-header\fR" 4
-.IX Item "--file-header"
-.PD
-Displays the information contained in the \s-1ELF\s0 header at the start of the
-file.
-.IP "\fB\-l\fR" 4
-.IX Item "-l"
-.PD 0
-.IP "\fB\-\-program\-headers\fR" 4
-.IX Item "--program-headers"
-.IP "\fB\-\-segments\fR" 4
-.IX Item "--segments"
-.PD
-Displays the information contained in the file's segment headers, if it
-has any.
-.IP "\fB\-S\fR" 4
-.IX Item "-S"
-.PD 0
-.IP "\fB\-\-sections\fR" 4
-.IX Item "--sections"
-.IP "\fB\-\-section\-headers\fR" 4
-.IX Item "--section-headers"
-.PD
-Displays the information contained in the file's section headers, if it
-has any.
-.IP "\fB\-g\fR" 4
-.IX Item "-g"
-.PD 0
-.IP "\fB\-\-section\-groups\fR" 4
-.IX Item "--section-groups"
-.PD
-Displays the information contained in the file's section groups, if it
-has any.
-.IP "\fB\-t\fR" 4
-.IX Item "-t"
-.PD 0
-.IP "\fB\-\-section\-details\fR" 4
-.IX Item "--section-details"
-.PD
-Displays the detailed section information. Implies \fB\-S\fR.
-.IP "\fB\-s\fR" 4
-.IX Item "-s"
-.PD 0
-.IP "\fB\-\-symbols\fR" 4
-.IX Item "--symbols"
-.IP "\fB\-\-syms\fR" 4
-.IX Item "--syms"
-.PD
-Displays the entries in symbol table section of the file, if it has one.
-.IP "\fB\-e\fR" 4
-.IX Item "-e"
-.PD 0
-.IP "\fB\-\-headers\fR" 4
-.IX Item "--headers"
-.PD
-Display all the headers in the file. Equivalent to \fB\-h \-l \-S\fR.
-.IP "\fB\-n\fR" 4
-.IX Item "-n"
-.PD 0
-.IP "\fB\-\-notes\fR" 4
-.IX Item "--notes"
-.PD
-Displays the contents of the \s-1NOTE\s0 segments and/or sections, if any.
-.IP "\fB\-r\fR" 4
-.IX Item "-r"
-.PD 0
-.IP "\fB\-\-relocs\fR" 4
-.IX Item "--relocs"
-.PD
-Displays the contents of the file's relocation section, if it has one.
-.IP "\fB\-u\fR" 4
-.IX Item "-u"
-.PD 0
-.IP "\fB\-\-unwind\fR" 4
-.IX Item "--unwind"
-.PD
-Displays the contents of the file's unwind section, if it has one. Only
-the unwind sections for \s-1IA64\s0 \s-1ELF\s0 files are currently supported.
-.IP "\fB\-d\fR" 4
-.IX Item "-d"
-.PD 0
-.IP "\fB\-\-dynamic\fR" 4
-.IX Item "--dynamic"
-.PD
-Displays the contents of the file's dynamic section, if it has one.
-.IP "\fB\-V\fR" 4
-.IX Item "-V"
-.PD 0
-.IP "\fB\-\-version\-info\fR" 4
-.IX Item "--version-info"
-.PD
-Displays the contents of the version sections in the file, it they
-exist.
-.IP "\fB\-A\fR" 4
-.IX Item "-A"
-.PD 0
-.IP "\fB\-\-arch\-specific\fR" 4
-.IX Item "--arch-specific"
-.PD
-Displays architecture-specific information in the file, if there
-is any.
-.IP "\fB\-D\fR" 4
-.IX Item "-D"
-.PD 0
-.IP "\fB\-\-use\-dynamic\fR" 4
-.IX Item "--use-dynamic"
-.PD
-When displaying symbols, this option makes \fBreadelf\fR use the
-symbol table in the file's dynamic section, rather than the one in the
-symbols section.
-.IP "\fB\-x <number or name>\fR" 4
-.IX Item "-x <number or name>"
-.PD 0
-.IP "\fB\-\-hex\-dump=<number or name>\fR" 4
-.IX Item "--hex-dump=<number or name>"
-.PD
-Displays the contents of the indicated section as a hexadecimal dump.
-A number identifies a particular section by index in the section table;
-any other string identifies all sections with that name in the object file.
-.IP "\fB\-w[liaprmfFsoR]\fR" 4
-.IX Item "-w[liaprmfFsoR]"
-.PD 0
-.IP "\fB\-\-debug\-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames\-interp,=str,=loc,=Ranges]\fR" 4
-.IX Item "--debug-dump[=line,=info,=abbrev,=pubnames,=aranges,=macro,=frames,=frames-interp,=str,=loc,=Ranges]"
-.PD
-Displays the contents of the debug sections in the file, if any are
-present. If one of the optional letters or words follows the switch
-then only data found in those specific sections will be dumped.
-.IP "\fB\-I\fR" 4
-.IX Item "-I"
-.PD 0
-.IP "\fB\-\-histogram\fR" 4
-.IX Item "--histogram"
-.PD
-Display a histogram of bucket list lengths when displaying the contents
-of the symbol tables.
-.IP "\fB\-v\fR" 4
-.IX Item "-v"
-.PD 0
-.IP "\fB\-\-version\fR" 4
-.IX Item "--version"
-.PD
-Display the version number of readelf.
-.IP "\fB\-W\fR" 4
-.IX Item "-W"
-.PD 0
-.IP "\fB\-\-wide\fR" 4
-.IX Item "--wide"
-.PD
-Don't break output lines to fit into 80 columns. By default
-\&\fBreadelf\fR breaks section header and segment listing lines for
-64\-bit \s-1ELF\s0 files, so that they fit into 80 columns. This option causes
-\&\fBreadelf\fR to print each section header resp. each segment one a
-single line, which is far more readable on terminals wider than 80 columns.
-.IP "\fB\-H\fR" 4
-.IX Item "-H"
-.PD 0
-.IP "\fB\-\-help\fR" 4
-.IX Item "--help"
-.PD
-Display the command line options understood by \fBreadelf\fR.
-.IP "\fB@\fR\fIfile\fR" 4
-.IX Item "@file"
-Read command-line options from \fIfile\fR. The options read are
-inserted in place of the original @\fIfile\fR option. If \fIfile\fR
-does not exist, or cannot be read, then the option will be treated
-literally, and not removed.
-.Sp
-Options in \fIfile\fR are separated by whitespace. A whitespace
-character may be included in an option by surrounding the entire
-option in either single or double quotes. Any character (including a
-backslash) may be included by prefixing the character to be included
-with a backslash. The \fIfile\fR may itself contain additional
-@\fIfile\fR options; any such options will be processed recursively.
-.SH "SEE ALSO"
-.IX Header "SEE ALSO"
-\&\fIobjdump\fR\|(1), and the Info entries for \fIbinutils\fR.
-.SH "COPYRIGHT"
-.IX Header "COPYRIGHT"
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
-.PP
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the \s-1GNU\s0 Free Documentation License, Version 1.1
-or any later version published by the Free Software Foundation;
-with no Invariant Sections, with no Front-Cover Texts, and with no
-Back-Cover Texts. A copy of the license is included in the
-section entitled \*(L"\s-1GNU\s0 Free Documentation License\*(R".
diff --git a/gnu/usr.bin/binutils/size/Makefile b/gnu/usr.bin/binutils/size/Makefile
deleted file mode 100644
index c5c19c1..0000000
--- a/gnu/usr.bin/binutils/size/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# $FreeBSD$
-
-.include "../Makefile.inc0"
-
-.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
-
-PROG= size
-SRCS= size.c
-CFLAGS+= -D_GNU_SOURCE
-CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
-CFLAGS+= -I${SRCDIR}/binutils
-DPADD= ${RELTOP}/libbinutils/libbinutils.a
-DPADD+= ${RELTOP}/libbfd/libbfd.a
-DPADD+= ${RELTOP}/libiberty/libiberty.a
-LDADD= ${DPADD}
-
-.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/size/Makefile.depend b/gnu/usr.bin/binutils/size/Makefile.depend
deleted file mode 100644
index b58c9bd..0000000
--- a/gnu/usr.bin/binutils/size/Makefile.depend
+++ /dev/null
@@ -1,21 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- gnu/lib/libgcc \
- gnu/usr.bin/binutils/libbfd \
- gnu/usr.bin/binutils/libbinutils \
- gnu/usr.bin/binutils/libiberty \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/gnu/usr.bin/binutils/size/size.1 b/gnu/usr.bin/binutils/size/size.1
deleted file mode 100644
index 7064762..0000000
--- a/gnu/usr.bin/binutils/size/size.1
+++ /dev/null
@@ -1,263 +0,0 @@
-.\" $FreeBSD$
-.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
-.\"
-.\" Standard preamble:
-.\" ========================================================================
-.de Sp \" Vertical space (when we can't use .PP)
-.if t .sp .5v
-.if n .sp
-..
-.de Vb \" Begin verbatim text
-.ft CW
-.nf
-.ne \\$1
-..
-.de Ve \" End verbatim text
-.ft R
-.fi
-..
-.\" Set up some character translations and predefined strings. \*(-- will
-.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
-.\" double quote, and \*(R" will give a right double quote. \*(C+ will
-.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
-.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
-.\" nothing in troff, for use with C<>.
-.tr \(*W-
-.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
-.ie n \{\
-. ds -- \(*W-
-. ds PI pi
-. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
-. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
-. ds L" ""
-. ds R" ""
-. ds C` ""
-. ds C' ""
-'br\}
-.el\{\
-. ds -- \|\(em\|
-. ds PI \(*p
-. ds L" ``
-. ds R" ''
-'br\}
-.\"
-.\" Escape single quotes in literal strings from groff's Unicode transform.
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\"
-.\" If the F register is turned on, we'll generate index entries on stderr for
-.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
-.\" entries marked with X<> in POD. Of course, you'll have to process the
-.\" output yourself in some meaningful fashion.
-.ie \nF \{\
-. de IX
-. tm Index:\\$1\t\\n%\t"\\$2"
-..
-. nr % 0
-. rr F
-.\}
-.el \{\
-. de IX
-..
-.\}
-.\"
-.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
-.\" Fear. Run. Save yourself. No user-serviceable parts.
-. \" fudge factors for nroff and troff
-.if n \{\
-. ds #H 0
-. ds #V .8m
-. ds #F .3m
-. ds #[ \f1
-. ds #] \fP
-.\}
-.if t \{\
-. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
-. ds #V .6m
-. ds #F 0
-. ds #[ \&
-. ds #] \&
-.\}
-. \" simple accents for nroff and troff
-.if n \{\
-. ds ' \&
-. ds ` \&
-. ds ^ \&
-. ds , \&
-. ds ~ ~
-. ds /
-.\}
-.if t \{\
-. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
-. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
-. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
-. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
-. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
-. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
-.\}
-. \" troff and (daisy-wheel) nroff accents
-.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
-.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
-.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
-.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
-.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
-.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
-.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
-.ds ae a\h'-(\w'a'u*4/10)'e
-.ds Ae A\h'-(\w'A'u*4/10)'E
-. \" corrections for vroff
-.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
-.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
-. \" for low resolution devices (crt and lpr)
-.if \n(.H>23 .if \n(.V>19 \
-\{\
-. ds : e
-. ds 8 ss
-. ds o a
-. ds d- d\h'-1'\(ga
-. ds D- D\h'-1'\(hy
-. ds th \o'bp'
-. ds Th \o'LP'
-. ds ae ae
-. ds Ae AE
-.\}
-.rm #[ #] #H #V #F C
-.\" ========================================================================
-.\"
-.IX Title "SIZE 1"
-.TH SIZE 1 "2010-10-30" "binutils-2.17.50" "GNU Development Tools"
-.\" For nroff, turn off justification. Always turn off hyphenation; it makes
-.\" way too many mistakes in technical documents.
-.if n .ad l
-.nh
-.SH "NAME"
-size \- list section sizes and total size
-.SH "SYNOPSIS"
-.IX Header "SYNOPSIS"
-size [\fB\-A\fR|\fB\-B\fR|\fB\-\-format=\fR\fIcompatibility\fR]
- [\fB\-\-help\fR]
- [\fB\-d\fR|\fB\-o\fR|\fB\-x\fR|\fB\-\-radix=\fR\fInumber\fR]
- [\fB\-t\fR|\fB\-\-totals\fR]
- [\fB\-\-target=\fR\fIbfdname\fR] [\fB\-V\fR|\fB\-\-version\fR]
- [\fIobjfile\fR...]
-.SH "DESCRIPTION"
-.IX Header "DESCRIPTION"
-The \s-1GNU\s0 \fBsize\fR utility lists the section sizes\-\-\-and the total
-size\-\-\-for each of the object or archive files \fIobjfile\fR in its
-argument list. By default, one line of output is generated for each
-object file or each module in an archive.
-.PP
-\&\fIobjfile\fR... are the object files to be examined.
-If none are specified, the file \f(CW\*(C`a.out\*(C'\fR will be used.
-.SH "OPTIONS"
-.IX Header "OPTIONS"
-The command line options have the following meanings:
-.IP "\fB\-A\fR" 4
-.IX Item "-A"
-.PD 0
-.IP "\fB\-B\fR" 4
-.IX Item "-B"
-.IP "\fB\-\-format=\fR\fIcompatibility\fR" 4
-.IX Item "--format=compatibility"
-.PD
-Using one of these options, you can choose whether the output from \s-1GNU\s0
-\&\fBsize\fR resembles output from System V \fBsize\fR (using \fB\-A\fR,
-or \fB\-\-format=sysv\fR), or Berkeley \fBsize\fR (using \fB\-B\fR, or
-\&\fB\-\-format=berkeley\fR). The default is the one-line format similar to
-Berkeley's.
-.Sp
-Here is an example of the Berkeley (default) format of output from
-\&\fBsize\fR:
-.Sp
-.Vb 4
-\& $ size \-\-format=Berkeley ranlib size
-\& text data bss dec hex filename
-\& 294880 81920 11592 388392 5ed28 ranlib
-\& 294880 81920 11888 388688 5ee50 size
-.Ve
-.Sp
-This is the same data, but displayed closer to System V conventions:
-.Sp
-.Vb 7
-\& $ size \-\-format=SysV ranlib size
-\& ranlib :
-\& section size addr
-\& .text 294880 8192
-\& .data 81920 303104
-\& .bss 11592 385024
-\& Total 388392
-\&
-\&
-\& size :
-\& section size addr
-\& .text 294880 8192
-\& .data 81920 303104
-\& .bss 11888 385024
-\& Total 388688
-.Ve
-.IP "\fB\-\-help\fR" 4
-.IX Item "--help"
-Show a summary of acceptable arguments and options.
-.IP "\fB\-d\fR" 4
-.IX Item "-d"
-.PD 0
-.IP "\fB\-o\fR" 4
-.IX Item "-o"
-.IP "\fB\-x\fR" 4
-.IX Item "-x"
-.IP "\fB\-\-radix=\fR\fInumber\fR" 4
-.IX Item "--radix=number"
-.PD
-Using one of these options, you can control whether the size of each
-section is given in decimal (\fB\-d\fR, or \fB\-\-radix=10\fR); octal
-(\fB\-o\fR, or \fB\-\-radix=8\fR); or hexadecimal (\fB\-x\fR, or
-\&\fB\-\-radix=16\fR). In \fB\-\-radix=\fR\fInumber\fR, only the three
-values (8, 10, 16) are supported. The total size is always given in two
-radices; decimal and hexadecimal for \fB\-d\fR or \fB\-x\fR output, or
-octal and hexadecimal if you're using \fB\-o\fR.
-.IP "\fB\-t\fR" 4
-.IX Item "-t"
-.PD 0
-.IP "\fB\-\-totals\fR" 4
-.IX Item "--totals"
-.PD
-Show totals of all objects listed (Berkeley format listing mode only).
-.IP "\fB\-\-target=\fR\fIbfdname\fR" 4
-.IX Item "--target=bfdname"
-Specify that the object-code format for \fIobjfile\fR is
-\&\fIbfdname\fR. This option may not be necessary; \fBsize\fR can
-automatically recognize many formats.
-.IP "\fB\-V\fR" 4
-.IX Item "-V"
-.PD 0
-.IP "\fB\-\-version\fR" 4
-.IX Item "--version"
-.PD
-Display the version number of \fBsize\fR.
-.IP "\fB@\fR\fIfile\fR" 4
-.IX Item "@file"
-Read command-line options from \fIfile\fR. The options read are
-inserted in place of the original @\fIfile\fR option. If \fIfile\fR
-does not exist, or cannot be read, then the option will be treated
-literally, and not removed.
-.Sp
-Options in \fIfile\fR are separated by whitespace. A whitespace
-character may be included in an option by surrounding the entire
-option in either single or double quotes. Any character (including a
-backslash) may be included by prefixing the character to be included
-with a backslash. The \fIfile\fR may itself contain additional
-@\fIfile\fR options; any such options will be processed recursively.
-.SH "SEE ALSO"
-.IX Header "SEE ALSO"
-\&\fIar\fR\|(1), \fIobjdump\fR\|(1), \fIreadelf\fR\|(1), and the Info entries for \fIbinutils\fR.
-.SH "COPYRIGHT"
-.IX Header "COPYRIGHT"
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
-.PP
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the \s-1GNU\s0 Free Documentation License, Version 1.1
-or any later version published by the Free Software Foundation;
-with no Invariant Sections, with no Front-Cover Texts, and with no
-Back-Cover Texts. A copy of the license is included in the
-section entitled \*(L"\s-1GNU\s0 Free Documentation License\*(R".
diff --git a/gnu/usr.bin/binutils/strings/Makefile b/gnu/usr.bin/binutils/strings/Makefile
deleted file mode 100644
index a432d51..0000000
--- a/gnu/usr.bin/binutils/strings/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-# $FreeBSD$
-
-.include "../Makefile.inc0"
-
-.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
-
-PROG= strings
-SRCS= strings.c
-CFLAGS+= -D_GNU_SOURCE
-CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
-CFLAGS+= -I${SRCDIR}/binutils
-DPADD= ${RELTOP}/libbinutils/libbinutils.a
-DPADD+= ${RELTOP}/libbfd/libbfd.a
-DPADD+= ${RELTOP}/libiberty/libiberty.a
-LDADD= ${DPADD}
-
-.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/strings/Makefile.depend b/gnu/usr.bin/binutils/strings/Makefile.depend
deleted file mode 100644
index b58c9bd..0000000
--- a/gnu/usr.bin/binutils/strings/Makefile.depend
+++ /dev/null
@@ -1,21 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- gnu/lib/libgcc \
- gnu/usr.bin/binutils/libbfd \
- gnu/usr.bin/binutils/libbinutils \
- gnu/usr.bin/binutils/libiberty \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/gnu/usr.bin/binutils/strings/strings.1 b/gnu/usr.bin/binutils/strings/strings.1
deleted file mode 100644
index 075e3a5..0000000
--- a/gnu/usr.bin/binutils/strings/strings.1
+++ /dev/null
@@ -1,254 +0,0 @@
-.\" $FreeBSD$
-.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
-.\"
-.\" Standard preamble:
-.\" ========================================================================
-.de Sp \" Vertical space (when we can't use .PP)
-.if t .sp .5v
-.if n .sp
-..
-.de Vb \" Begin verbatim text
-.ft CW
-.nf
-.ne \\$1
-..
-.de Ve \" End verbatim text
-.ft R
-.fi
-..
-.\" Set up some character translations and predefined strings. \*(-- will
-.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
-.\" double quote, and \*(R" will give a right double quote. \*(C+ will
-.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
-.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
-.\" nothing in troff, for use with C<>.
-.tr \(*W-
-.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
-.ie n \{\
-. ds -- \(*W-
-. ds PI pi
-. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
-. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
-. ds L" ""
-. ds R" ""
-. ds C` ""
-. ds C' ""
-'br\}
-.el\{\
-. ds -- \|\(em\|
-. ds PI \(*p
-. ds L" ``
-. ds R" ''
-'br\}
-.\"
-.\" Escape single quotes in literal strings from groff's Unicode transform.
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\"
-.\" If the F register is turned on, we'll generate index entries on stderr for
-.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
-.\" entries marked with X<> in POD. Of course, you'll have to process the
-.\" output yourself in some meaningful fashion.
-.ie \nF \{\
-. de IX
-. tm Index:\\$1\t\\n%\t"\\$2"
-..
-. nr % 0
-. rr F
-.\}
-.el \{\
-. de IX
-..
-.\}
-.\"
-.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
-.\" Fear. Run. Save yourself. No user-serviceable parts.
-. \" fudge factors for nroff and troff
-.if n \{\
-. ds #H 0
-. ds #V .8m
-. ds #F .3m
-. ds #[ \f1
-. ds #] \fP
-.\}
-.if t \{\
-. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
-. ds #V .6m
-. ds #F 0
-. ds #[ \&
-. ds #] \&
-.\}
-. \" simple accents for nroff and troff
-.if n \{\
-. ds ' \&
-. ds ` \&
-. ds ^ \&
-. ds , \&
-. ds ~ ~
-. ds /
-.\}
-.if t \{\
-. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
-. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
-. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
-. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
-. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
-. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
-.\}
-. \" troff and (daisy-wheel) nroff accents
-.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
-.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
-.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
-.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
-.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
-.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
-.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
-.ds ae a\h'-(\w'a'u*4/10)'e
-.ds Ae A\h'-(\w'A'u*4/10)'E
-. \" corrections for vroff
-.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
-.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
-. \" for low resolution devices (crt and lpr)
-.if \n(.H>23 .if \n(.V>19 \
-\{\
-. ds : e
-. ds 8 ss
-. ds o a
-. ds d- d\h'-1'\(ga
-. ds D- D\h'-1'\(hy
-. ds th \o'bp'
-. ds Th \o'LP'
-. ds ae ae
-. ds Ae AE
-.\}
-.rm #[ #] #H #V #F C
-.\" ========================================================================
-.\"
-.IX Title "STRINGS 1"
-.TH STRINGS 1 "2010-10-30" "binutils-2.17.50" "GNU Development Tools"
-.\" For nroff, turn off justification. Always turn off hyphenation; it makes
-.\" way too many mistakes in technical documents.
-.if n .ad l
-.nh
-.SH "NAME"
-strings \- print the strings of printable characters in files.
-.SH "SYNOPSIS"
-.IX Header "SYNOPSIS"
-strings [\fB\-afov\fR] [\fB\-\fR\fImin-len\fR]
- [\fB\-n\fR \fImin-len\fR] [\fB\-\-bytes=\fR\fImin-len\fR]
- [\fB\-t\fR \fIradix\fR] [\fB\-\-radix=\fR\fIradix\fR]
- [\fB\-e\fR \fIencoding\fR] [\fB\-\-encoding=\fR\fIencoding\fR]
- [\fB\-\fR] [\fB\-\-all\fR] [\fB\-\-print\-file\-name\fR]
- [\fB\-T\fR \fIbfdname\fR] [\fB\-\-target=\fR\fIbfdname\fR]
- [\fB\-\-help\fR] [\fB\-\-version\fR] \fIfile\fR...
-.SH "DESCRIPTION"
-.IX Header "DESCRIPTION"
-For each \fIfile\fR given, \s-1GNU\s0 \fBstrings\fR prints the printable
-character sequences that are at least 4 characters long (or the number
-given with the options below) and are followed by an unprintable
-character. By default, it only prints the strings from the initialized
-and loaded sections of object files; for other types of files, it prints
-the strings from the whole file.
-.PP
-\&\fBstrings\fR is mainly useful for determining the contents of non-text
-files.
-.SH "OPTIONS"
-.IX Header "OPTIONS"
-.IP "\fB\-a\fR" 4
-.IX Item "-a"
-.PD 0
-.IP "\fB\-\-all\fR" 4
-.IX Item "--all"
-.IP "\fB\-\fR" 4
-.IX Item "-"
-.PD
-Do not scan only the initialized and loaded sections of object files;
-scan the whole files.
-.IP "\fB\-f\fR" 4
-.IX Item "-f"
-.PD 0
-.IP "\fB\-\-print\-file\-name\fR" 4
-.IX Item "--print-file-name"
-.PD
-Print the name of the file before each string.
-.IP "\fB\-\-help\fR" 4
-.IX Item "--help"
-Print a summary of the program usage on the standard output and exit.
-.IP "\fB\-\fR\fImin-len\fR" 4
-.IX Item "-min-len"
-.PD 0
-.IP "\fB\-n\fR \fImin-len\fR" 4
-.IX Item "-n min-len"
-.IP "\fB\-\-bytes=\fR\fImin-len\fR" 4
-.IX Item "--bytes=min-len"
-.PD
-Print sequences of characters that are at least \fImin-len\fR characters
-long, instead of the default 4.
-.IP "\fB\-o\fR" 4
-.IX Item "-o"
-Like \fB\-t o\fR. Some other versions of \fBstrings\fR have \fB\-o\fR
-act like \fB\-t d\fR instead. Since we can not be compatible with both
-ways, we simply chose one.
-.IP "\fB\-t\fR \fIradix\fR" 4
-.IX Item "-t radix"
-.PD 0
-.IP "\fB\-\-radix=\fR\fIradix\fR" 4
-.IX Item "--radix=radix"
-.PD
-Print the offset within the file before each string. The single
-character argument specifies the radix of the offset\-\-\-\fBo\fR for
-octal, \fBx\fR for hexadecimal, or \fBd\fR for decimal.
-.IP "\fB\-e\fR \fIencoding\fR" 4
-.IX Item "-e encoding"
-.PD 0
-.IP "\fB\-\-encoding=\fR\fIencoding\fR" 4
-.IX Item "--encoding=encoding"
-.PD
-Select the character encoding of the strings that are to be found.
-Possible values for \fIencoding\fR are: \fBs\fR = single\-7\-bit\-byte
-characters (\s-1ASCII\s0, \s-1ISO\s0 8859, etc., default), \fBS\fR =
-single\-8\-bit\-byte characters, \fBb\fR = 16\-bit bigendian, \fBl\fR =
-16\-bit littleendian, \fBB\fR = 32\-bit bigendian, \fBL\fR = 32\-bit
-littleendian. Useful for finding wide character strings.
-.IP "\fB\-T\fR \fIbfdname\fR" 4
-.IX Item "-T bfdname"
-.PD 0
-.IP "\fB\-\-target=\fR\fIbfdname\fR" 4
-.IX Item "--target=bfdname"
-.PD
-Specify an object code format other than your system's default format.
-.IP "\fB\-v\fR" 4
-.IX Item "-v"
-.PD 0
-.IP "\fB\-\-version\fR" 4
-.IX Item "--version"
-.PD
-Print the program version number on the standard output and exit.
-.IP "\fB@\fR\fIfile\fR" 4
-.IX Item "@file"
-Read command-line options from \fIfile\fR. The options read are
-inserted in place of the original @\fIfile\fR option. If \fIfile\fR
-does not exist, or cannot be read, then the option will be treated
-literally, and not removed.
-.Sp
-Options in \fIfile\fR are separated by whitespace. A whitespace
-character may be included in an option by surrounding the entire
-option in either single or double quotes. Any character (including a
-backslash) may be included by prefixing the character to be included
-with a backslash. The \fIfile\fR may itself contain additional
-@\fIfile\fR options; any such options will be processed recursively.
-.SH "SEE ALSO"
-.IX Header "SEE ALSO"
-\&\fIar\fR\|(1), \fInm\fR\|(1), \fIobjdump\fR\|(1), \fIranlib\fR\|(1), \fIreadelf\fR\|(1)
-and the Info entries for \fIbinutils\fR.
-.SH "COPYRIGHT"
-.IX Header "COPYRIGHT"
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
-.PP
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the \s-1GNU\s0 Free Documentation License, Version 1.1
-or any later version published by the Free Software Foundation;
-with no Invariant Sections, with no Front-Cover Texts, and with no
-Back-Cover Texts. A copy of the license is included in the
-section entitled \*(L"\s-1GNU\s0 Free Documentation License\*(R".
diff --git a/gnu/usr.bin/binutils/strip/Makefile b/gnu/usr.bin/binutils/strip/Makefile
deleted file mode 100644
index d3cf8c4..0000000
--- a/gnu/usr.bin/binutils/strip/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# $FreeBSD$
-
-.include "../Makefile.inc0"
-
-.PATH: ${SRCDIR}/binutils ${SRCDIR}/binutils/doc
-
-PROG= strip
-SRCS= objcopy.c is-strip.c
-CFLAGS+= -D_GNU_SOURCE
-CFLAGS+= -I${.CURDIR}/${RELTOP}/libbinutils
-CFLAGS+= -I${SRCDIR}/binutils -I${SRCDIR}/bfd
-DPADD= ${RELTOP}/libbinutils/libbinutils.a
-DPADD+= ${RELTOP}/libbfd/libbfd.a
-DPADD+= ${RELTOP}/libiberty/libiberty.a
-LDADD= ${DPADD}
-INSTALLFLAGS= -S
-
-.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/binutils/strip/Makefile.depend b/gnu/usr.bin/binutils/strip/Makefile.depend
deleted file mode 100644
index b58c9bd..0000000
--- a/gnu/usr.bin/binutils/strip/Makefile.depend
+++ /dev/null
@@ -1,21 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DIRDEPS = \
- gnu/lib/csu \
- gnu/lib/libgcc \
- gnu/usr.bin/binutils/libbfd \
- gnu/usr.bin/binutils/libbinutils \
- gnu/usr.bin/binutils/libiberty \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/gnu/usr.bin/binutils/strip/strip.1 b/gnu/usr.bin/binutils/strip/strip.1
deleted file mode 100644
index 3f0d7a3..0000000
--- a/gnu/usr.bin/binutils/strip/strip.1
+++ /dev/null
@@ -1,392 +0,0 @@
-.\" $FreeBSD$
-.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
-.\"
-.\" Standard preamble:
-.\" ========================================================================
-.de Sp \" Vertical space (when we can't use .PP)
-.if t .sp .5v
-.if n .sp
-..
-.de Vb \" Begin verbatim text
-.ft CW
-.nf
-.ne \\$1
-..
-.de Ve \" End verbatim text
-.ft R
-.fi
-..
-.\" Set up some character translations and predefined strings. \*(-- will
-.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
-.\" double quote, and \*(R" will give a right double quote. \*(C+ will
-.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
-.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
-.\" nothing in troff, for use with C<>.
-.tr \(*W-
-.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
-.ie n \{\
-. ds -- \(*W-
-. ds PI pi
-. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
-. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
-. ds L" ""
-. ds R" ""
-. ds C` ""
-. ds C' ""
-'br\}
-.el\{\
-. ds -- \|\(em\|
-. ds PI \(*p
-. ds L" ``
-. ds R" ''
-'br\}
-.\"
-.\" Escape single quotes in literal strings from groff's Unicode transform.
-.ie \n(.g .ds Aq \(aq
-.el .ds Aq '
-.\"
-.\" If the F register is turned on, we'll generate index entries on stderr for
-.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
-.\" entries marked with X<> in POD. Of course, you'll have to process the
-.\" output yourself in some meaningful fashion.
-.ie \nF \{\
-. de IX
-. tm Index:\\$1\t\\n%\t"\\$2"
-..
-. nr % 0
-. rr F
-.\}
-.el \{\
-. de IX
-..
-.\}
-.\"
-.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
-.\" Fear. Run. Save yourself. No user-serviceable parts.
-. \" fudge factors for nroff and troff
-.if n \{\
-. ds #H 0
-. ds #V .8m
-. ds #F .3m
-. ds #[ \f1
-. ds #] \fP
-.\}
-.if t \{\
-. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
-. ds #V .6m
-. ds #F 0
-. ds #[ \&
-. ds #] \&
-.\}
-. \" simple accents for nroff and troff
-.if n \{\
-. ds ' \&
-. ds ` \&
-. ds ^ \&
-. ds , \&
-. ds ~ ~
-. ds /
-.\}
-.if t \{\
-. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
-. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
-. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
-. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
-. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
-. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
-.\}
-. \" troff and (daisy-wheel) nroff accents
-.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
-.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
-.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
-.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
-.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
-.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
-.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
-.ds ae a\h'-(\w'a'u*4/10)'e
-.ds Ae A\h'-(\w'A'u*4/10)'E
-. \" corrections for vroff
-.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
-.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
-. \" for low resolution devices (crt and lpr)
-.if \n(.H>23 .if \n(.V>19 \
-\{\
-. ds : e
-. ds 8 ss
-. ds o a
-. ds d- d\h'-1'\(ga
-. ds D- D\h'-1'\(hy
-. ds th \o'bp'
-. ds Th \o'LP'
-. ds ae ae
-. ds Ae AE
-.\}
-.rm #[ #] #H #V #F C
-.\" ========================================================================
-.\"
-.IX Title "STRIP 1"
-.TH STRIP 1 "2010-10-30" "binutils-2.17.50" "GNU Development Tools"
-.\" For nroff, turn off justification. Always turn off hyphenation; it makes
-.\" way too many mistakes in technical documents.
-.if n .ad l
-.nh
-.SH "NAME"
-strip \- Discard symbols from object files
-.SH "SYNOPSIS"
-.IX Header "SYNOPSIS"
-strip [\fB\-F\fR \fIbfdname\fR |\fB\-\-target=\fR\fIbfdname\fR]
- [\fB\-I\fR \fIbfdname\fR |\fB\-\-input\-target=\fR\fIbfdname\fR]
- [\fB\-O\fR \fIbfdname\fR |\fB\-\-output\-target=\fR\fIbfdname\fR]
- [\fB\-s\fR|\fB\-\-strip\-all\fR]
- [\fB\-S\fR|\fB\-g\fR|\fB\-d\fR|\fB\-\-strip\-debug\fR]
- [\fB\-K\fR \fIsymbolname\fR |\fB\-\-keep\-symbol=\fR\fIsymbolname\fR]
- [\fB\-N\fR \fIsymbolname\fR |\fB\-\-strip\-symbol=\fR\fIsymbolname\fR]
- [\fB\-w\fR|\fB\-\-wildcard\fR]
- [\fB\-x\fR|\fB\-\-discard\-all\fR] [\fB\-X\fR |\fB\-\-discard\-locals\fR]
- [\fB\-R\fR \fIsectionname\fR |\fB\-\-remove\-section=\fR\fIsectionname\fR]
- [\fB\-o\fR \fIfile\fR] [\fB\-p\fR|\fB\-\-preserve\-dates\fR]
- [\fB\-\-keep\-file\-symbols\fR]
- [\fB\-\-only\-keep\-debug\fR]
- [\fB\-v\fR |\fB\-\-verbose\fR] [\fB\-V\fR|\fB\-\-version\fR]
- [\fB\-\-help\fR] [\fB\-\-info\fR]
- \fIobjfile\fR...
-.SH "DESCRIPTION"
-.IX Header "DESCRIPTION"
-\&\s-1GNU\s0 \fBstrip\fR discards all symbols from object files
-\&\fIobjfile\fR. The list of object files may include archives.
-At least one object file must be given.
-.PP
-\&\fBstrip\fR modifies the files named in its argument,
-rather than writing modified copies under different names.
-.SH "OPTIONS"
-.IX Header "OPTIONS"
-.IP "\fB\-F\fR \fIbfdname\fR" 4
-.IX Item "-F bfdname"
-.PD 0
-.IP "\fB\-\-target=\fR\fIbfdname\fR" 4
-.IX Item "--target=bfdname"
-.PD
-Treat the original \fIobjfile\fR as a file with the object
-code format \fIbfdname\fR, and rewrite it in the same format.
-.IP "\fB\-\-help\fR" 4
-.IX Item "--help"
-Show a summary of the options to \fBstrip\fR and exit.
-.IP "\fB\-\-info\fR" 4
-.IX Item "--info"
-Display a list showing all architectures and object formats available.
-.IP "\fB\-I\fR \fIbfdname\fR" 4
-.IX Item "-I bfdname"
-.PD 0
-.IP "\fB\-\-input\-target=\fR\fIbfdname\fR" 4
-.IX Item "--input-target=bfdname"
-.PD
-Treat the original \fIobjfile\fR as a file with the object
-code format \fIbfdname\fR.
-.IP "\fB\-O\fR \fIbfdname\fR" 4
-.IX Item "-O bfdname"
-.PD 0
-.IP "\fB\-\-output\-target=\fR\fIbfdname\fR" 4
-.IX Item "--output-target=bfdname"
-.PD
-Replace \fIobjfile\fR with a file in the output format \fIbfdname\fR.
-.IP "\fB\-R\fR \fIsectionname\fR" 4
-.IX Item "-R sectionname"
-.PD 0
-.IP "\fB\-\-remove\-section=\fR\fIsectionname\fR" 4
-.IX Item "--remove-section=sectionname"
-.PD
-Remove any section named \fIsectionname\fR from the output file. This
-option may be given more than once. Note that using this option
-inappropriately may make the output file unusable.
-.IP "\fB\-s\fR" 4
-.IX Item "-s"
-.PD 0
-.IP "\fB\-\-strip\-all\fR" 4
-.IX Item "--strip-all"
-.PD
-Remove all symbols.
-.IP "\fB\-g\fR" 4
-.IX Item "-g"
-.PD 0
-.IP "\fB\-S\fR" 4
-.IX Item "-S"
-.IP "\fB\-d\fR" 4
-.IX Item "-d"
-.IP "\fB\-\-strip\-debug\fR" 4
-.IX Item "--strip-debug"
-.PD
-Remove debugging symbols only.
-.IP "\fB\-\-strip\-unneeded\fR" 4
-.IX Item "--strip-unneeded"
-Remove all symbols that are not needed for relocation processing.
-.IP "\fB\-K\fR \fIsymbolname\fR" 4
-.IX Item "-K symbolname"
-.PD 0
-.IP "\fB\-\-keep\-symbol=\fR\fIsymbolname\fR" 4
-.IX Item "--keep-symbol=symbolname"
-.PD
-When stripping symbols, keep symbol \fIsymbolname\fR even if it would
-normally be stripped. This option may be given more than once.
-.IP "\fB\-N\fR \fIsymbolname\fR" 4
-.IX Item "-N symbolname"
-.PD 0
-.IP "\fB\-\-strip\-symbol=\fR\fIsymbolname\fR" 4
-.IX Item "--strip-symbol=symbolname"
-.PD
-Remove symbol \fIsymbolname\fR from the source file. This option may be
-given more than once, and may be combined with strip options other than
-\&\fB\-K\fR.
-.IP "\fB\-o\fR \fIfile\fR" 4
-.IX Item "-o file"
-Put the stripped output in \fIfile\fR, rather than replacing the
-existing file. When this argument is used, only one \fIobjfile\fR
-argument may be specified.
-.IP "\fB\-p\fR" 4
-.IX Item "-p"
-.PD 0
-.IP "\fB\-\-preserve\-dates\fR" 4
-.IX Item "--preserve-dates"
-.PD
-Preserve the access and modification dates of the file.
-.IP "\fB\-w\fR" 4
-.IX Item "-w"
-.PD 0
-.IP "\fB\-\-wildcard\fR" 4
-.IX Item "--wildcard"
-.PD
-Permit regular expressions in \fIsymbolname\fRs used in other command
-line options. The question mark (?), asterisk (*), backslash (\e) and
-square brackets ([]) operators can be used anywhere in the symbol
-name. If the first character of the symbol name is the exclamation
-point (!) then the sense of the switch is reversed for that symbol.
-For example:
-.Sp
-.Vb 1
-\& \-w \-K !foo \-K fo*
-.Ve
-.Sp
-would cause strip to only keep symbols that start with the letters
-\&\*(L"fo\*(R", but to discard the symbol \*(L"foo\*(R".
-.IP "\fB\-x\fR" 4
-.IX Item "-x"
-.PD 0
-.IP "\fB\-\-discard\-all\fR" 4
-.IX Item "--discard-all"
-.PD
-Remove non-global symbols.
-.IP "\fB\-X\fR" 4
-.IX Item "-X"
-.PD 0
-.IP "\fB\-\-discard\-locals\fR" 4
-.IX Item "--discard-locals"
-.PD
-Remove compiler-generated local symbols.
-(These usually start with \fBL\fR or \fB.\fR.)
-.IP "\fB\-\-keep\-file\-symbols\fR" 4
-.IX Item "--keep-file-symbols"
-When stripping a file, perhaps with \fB\-\-strip\-debug\fR or
-\&\fB\-\-strip\-unneeded\fR, retain any symbols specifying source file names,
-which would otherwise get stripped.
-.IP "\fB\-\-only\-keep\-debug\fR" 4
-.IX Item "--only-keep-debug"
-Strip a file, removing contents of any sections that would not be
-stripped by \fB\-\-strip\-debug\fR and leaving the debugging sections
-intact. In \s-1ELF\s0 files, this preserves all note sections in the output.
-.Sp
-The intention is that this option will be used in conjunction with
-\&\fB\-\-add\-gnu\-debuglink\fR to create a two part executable. One a
-stripped binary which will occupy less space in \s-1RAM\s0 and in a
-distribution and the second a debugging information file which is only
-needed if debugging abilities are required. The suggested procedure
-to create these files is as follows:
-.RS 4
-.IP "1.<Link the executable as normal. Assuming that it is called>" 4
-.IX Item "1.<Link the executable as normal. Assuming that it is called>"
-\&\f(CW\*(C`foo\*(C'\fR then...
-.ie n .IP "1.<Run ""objcopy \-\-only\-keep\-debug foo foo.dbg"" to>" 4
-.el .IP "1.<Run \f(CWobjcopy \-\-only\-keep\-debug foo foo.dbg\fR to>" 4
-.IX Item "1.<Run objcopy --only-keep-debug foo foo.dbg to>"
-create a file containing the debugging info.
-.ie n .IP "1.<Run ""objcopy \-\-strip\-debug foo"" to create a>" 4
-.el .IP "1.<Run \f(CWobjcopy \-\-strip\-debug foo\fR to create a>" 4
-.IX Item "1.<Run objcopy --strip-debug foo to create a>"
-stripped executable.
-.ie n .IP "1.<Run ""objcopy \-\-add\-gnu\-debuglink=foo.dbg foo"">" 4
-.el .IP "1.<Run \f(CWobjcopy \-\-add\-gnu\-debuglink=foo.dbg foo\fR>" 4
-.IX Item "1.<Run objcopy --add-gnu-debuglink=foo.dbg foo>"
-to add a link to the debugging info into the stripped executable.
-.RE
-.RS 4
-.Sp
-Note \- the choice of \f(CW\*(C`.dbg\*(C'\fR as an extension for the debug info
-file is arbitrary. Also the \f(CW\*(C`\-\-only\-keep\-debug\*(C'\fR step is
-optional. You could instead do this:
-.IP "1.<Link the executable as normal.>" 4
-.IX Item "1.<Link the executable as normal.>"
-.PD 0
-.ie n .IP "1.<Copy ""foo"" to ""foo.full"">" 4
-.el .IP "1.<Copy \f(CWfoo\fR to \f(CWfoo.full\fR>" 4
-.IX Item "1.<Copy foo to foo.full>"
-.ie n .IP "1.<Run ""strip \-\-strip\-debug foo"">" 4
-.el .IP "1.<Run \f(CWstrip \-\-strip\-debug foo\fR>" 4
-.IX Item "1.<Run strip --strip-debug foo>"
-.ie n .IP "1.<Run ""objcopy \-\-add\-gnu\-debuglink=foo.full foo"">" 4
-.el .IP "1.<Run \f(CWobjcopy \-\-add\-gnu\-debuglink=foo.full foo\fR>" 4
-.IX Item "1.<Run objcopy --add-gnu-debuglink=foo.full foo>"
-.RE
-.RS 4
-.PD
-.Sp
-ie the file pointed to by the \fB\-\-add\-gnu\-debuglink\fR can be the
-full executable. It does not have to be a file created by the
-\&\fB\-\-only\-keep\-debug\fR switch.
-.Sp
-Note \- this switch is only intended for use on fully linked files. It
-does not make sense to use it on object files where the debugging
-information may be incomplete. Besides the gnu_debuglink feature
-currently only supports the presence of one filename containing
-debugging information, not multiple filenames on a one-per-object-file
-basis.
-.RE
-.IP "\fB\-V\fR" 4
-.IX Item "-V"
-.PD 0
-.IP "\fB\-\-version\fR" 4
-.IX Item "--version"
-.PD
-Show the version number for \fBstrip\fR.
-.IP "\fB\-v\fR" 4
-.IX Item "-v"
-.PD 0
-.IP "\fB\-\-verbose\fR" 4
-.IX Item "--verbose"
-.PD
-Verbose output: list all object files modified. In the case of
-archives, \fBstrip \-v\fR lists all members of the archive.
-.IP "\fB@\fR\fIfile\fR" 4
-.IX Item "@file"
-Read command-line options from \fIfile\fR. The options read are
-inserted in place of the original @\fIfile\fR option. If \fIfile\fR
-does not exist, or cannot be read, then the option will be treated
-literally, and not removed.
-.Sp
-Options in \fIfile\fR are separated by whitespace. A whitespace
-character may be included in an option by surrounding the entire
-option in either single or double quotes. Any character (including a
-backslash) may be included by prefixing the character to be included
-with a backslash. The \fIfile\fR may itself contain additional
-@\fIfile\fR options; any such options will be processed recursively.
-.SH "SEE ALSO"
-.IX Header "SEE ALSO"
-the Info entries for \fIbinutils\fR.
-.SH "COPYRIGHT"
-.IX Header "COPYRIGHT"
-Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
-.PP
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the \s-1GNU\s0 Free Documentation License, Version 1.1
-or any later version published by the Free Software Foundation;
-with no Invariant Sections, with no Front-Cover Texts, and with no
-Back-Cover Texts. A copy of the license is included in the
-section entitled \*(L"\s-1GNU\s0 Free Documentation License\*(R".
diff --git a/gnu/usr.bin/cc/Makefile b/gnu/usr.bin/cc/Makefile
index 65dc087..41349cf 100644
--- a/gnu/usr.bin/cc/Makefile
+++ b/gnu/usr.bin/cc/Makefile
@@ -13,9 +13,6 @@ SUBDIR+= cpp
.if ${MK_CXX} != "no"
SUBDIR+= cc1plus c++
-.if ${MK_ELFTOOLCHAIN_TOOLS} == "no"
-SUBDIR+= c++filt
-.endif
.endif
.if ${MK_GCOV} != "no"
diff --git a/gnu/usr.bin/cc/c++filt/Makefile b/gnu/usr.bin/cc/c++filt/Makefile
deleted file mode 100644
index b9daaf0..0000000
--- a/gnu/usr.bin/cc/c++filt/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-# $FreeBSD$
-
-MAN=
-.include <bsd.own.mk>
-
-.include "../Makefile.inc"
-.include "../Makefile.fe"
-
-.PATH: ${GCCLIB}/libiberty
-
-PROG= c++filt
-SRCS= cp-demangle.c
-
-CFLAGS+= -DSTANDALONE_DEMANGLER -DVERSION=\"$(GCC_VERSION)\"
-
-DPADD= ${LIBIBERTY}
-LDADD= ${LIBIBERTY}
-
-.include <bsd.prog.mk>
diff --git a/gnu/usr.bin/cc/c++filt/Makefile.depend b/gnu/usr.bin/cc/c++filt/Makefile.depend
deleted file mode 100644
index 0f7485d..0000000
--- a/gnu/usr.bin/cc/c++filt/Makefile.depend
+++ /dev/null
@@ -1,23 +0,0 @@
-# $FreeBSD$
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DIRDEPS = \
- gnu/lib/csu \
- gnu/lib/libgcc \
- gnu/usr.bin/cc/cc_tools \
- gnu/usr.bin/cc/libiberty \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libc_nonshared \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/lib/libarchive/test/Makefile b/lib/libarchive/test/Makefile
index 80d6dd4..e57c5ff 100644
--- a/lib/libarchive/test/Makefile
+++ b/lib/libarchive/test/Makefile
@@ -120,6 +120,7 @@ TESTS= \
test_read_format_gtar_gz.c \
test_read_format_gtar_lzma.c \
test_read_format_gtar_sparse.c \
+ test_read_format_gtar_sparse_skip_entry.c \
test_read_format_iso_Z.c \
test_read_format_iso_multi_extent.c \
test_read_format_iso_xorriso.c \
diff --git a/lib/libc/amd64/sys/__vdso_gettc.c b/lib/libc/amd64/sys/__vdso_gettc.c
index c6f2dfb..1899b21 100644
--- a/lib/libc/amd64/sys/__vdso_gettc.c
+++ b/lib/libc/amd64/sys/__vdso_gettc.c
@@ -36,19 +36,29 @@ __FBSDID("$FreeBSD$");
static u_int
__vdso_gettc_low(const struct vdso_timehands *th)
{
- uint32_t rv;
+ u_int rv;
- __asm __volatile("rdtsc; shrd %%cl, %%edx, %0"
+ __asm __volatile("lfence; rdtsc; shrd %%cl, %%edx, %0"
: "=a" (rv) : "c" (th->th_x86_shift) : "edx");
return (rv);
}
+static u_int
+__vdso_rdtsc32(void)
+{
+ u_int rv;
+
+ __asm __volatile("lfence;rdtsc" : "=a" (rv) : : "edx");
+ return (rv);
+}
+
#pragma weak __vdso_gettc
u_int
__vdso_gettc(const struct vdso_timehands *th)
{
- return (th->th_x86_shift > 0 ? __vdso_gettc_low(th) : rdtsc32());
+ return (th->th_x86_shift > 0 ? __vdso_gettc_low(th) :
+ __vdso_rdtsc32());
}
#pragma weak __vdso_gettimekeep
diff --git a/lib/libc/i386/sys/__vdso_gettc.c b/lib/libc/i386/sys/__vdso_gettc.c
index c6f2dfb..1454f16 100644
--- a/lib/libc/i386/sys/__vdso_gettc.c
+++ b/lib/libc/i386/sys/__vdso_gettc.c
@@ -31,24 +31,78 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/vdso.h>
#include <machine/cpufunc.h>
+#include <machine/specialreg.h>
#include "libc_private.h"
+static int lfence_works = -1;
+
+static int
+get_lfence_usage(void)
+{
+ u_int cpuid_supported, p[4];
+
+ if (lfence_works == -1) {
+ __asm __volatile(
+ " pushfl\n"
+ " popl %%eax\n"
+ " movl %%eax,%%ecx\n"
+ " xorl $0x200000,%%eax\n"
+ " pushl %%eax\n"
+ " popfl\n"
+ " pushfl\n"
+ " popl %%eax\n"
+ " xorl %%eax,%%ecx\n"
+ " je 1f\n"
+ " movl $1,%0\n"
+ " jmp 2f\n"
+ "1: movl $0,%0\n"
+ "2:\n"
+ : "=r" (cpuid_supported) : : "eax", "ecx");
+ if (cpuid_supported) {
+ __asm __volatile(
+ " pushl %%ebx\n"
+ " cpuid\n"
+ " movl %%ebx,%1\n"
+ " popl %%ebx\n"
+ : "=a" (p[0]), "=r" (p[1]), "=c" (p[2]), "=d" (p[3])
+ : "0" (0x1));
+ lfence_works = (p[3] & CPUID_SSE2) != 0;
+ } else
+ lfence_works = 0;
+ }
+ return (lfence_works);
+}
+
static u_int
__vdso_gettc_low(const struct vdso_timehands *th)
{
- uint32_t rv;
+ u_int rv;
+ if (get_lfence_usage() == 1)
+ lfence();
__asm __volatile("rdtsc; shrd %%cl, %%edx, %0"
: "=a" (rv) : "c" (th->th_x86_shift) : "edx");
return (rv);
}
+static u_int
+__vdso_rdtsc32(void)
+{
+ u_int rv;
+
+ if (get_lfence_usage() == 1)
+ lfence();
+ rv = rdtsc32();
+ return (rv);
+}
+
#pragma weak __vdso_gettc
u_int
__vdso_gettc(const struct vdso_timehands *th)
{
- return (th->th_x86_shift > 0 ? __vdso_gettc_low(th) : rdtsc32());
+ return (th->th_x86_shift > 0 ? __vdso_gettc_low(th) :
+ __vdso_rdtsc32());
}
#pragma weak __vdso_gettimekeep
diff --git a/lib/libc/stdio/open_memstream.3 b/lib/libc/stdio/open_memstream.3
index e01952b..1a0cb07 100644
--- a/lib/libc/stdio/open_memstream.3
+++ b/lib/libc/stdio/open_memstream.3
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 28, 2014
+.Dd August 1, 2015
.Dt OPEN_MEMSTREAM 3
.Os
.Sh NAME
@@ -86,13 +86,13 @@ will contain the start of the memory buffer and the variable referenced by
will contain the smaller of the current position and the current buffer length.
.Pp
After a successful call to
-.Xr fflush 3,
+.Xr fflush 3 ,
the pointer referenced by
.Fa bufp
and the variable referenced by
.Fa sizep
are only valid until the next write operation or a call to
-.Xr fclose 3.
+.Xr fclose 3 .
.Pp
Once a stream is closed,
the allocated buffer referenced by
diff --git a/lib/libc/sys/__vdso_gettimeofday.c b/lib/libc/sys/__vdso_gettimeofday.c
index a305173..b3527fa 100644
--- a/lib/libc/sys/__vdso_gettimeofday.c
+++ b/lib/libc/sys/__vdso_gettimeofday.c
@@ -42,6 +42,15 @@ tc_delta(const struct vdso_timehands *th)
th->th_counter_mask);
}
+/*
+ * Calculate the absolute or boot-relative time from the
+ * machine-specific fast timecounter and the published timehands
+ * structure read from the shared page.
+ *
+ * The lockless reading scheme is similar to the one used to read the
+ * in-kernel timehands, see sys/kern/kern_tc.c:binuptime(). This code
+ * is based on the kernel implementation.
+ */
static int
binuptime(struct bintime *bt, struct vdso_timekeep *tk, int abs)
{
@@ -52,27 +61,21 @@ binuptime(struct bintime *bt, struct vdso_timekeep *tk, int abs)
if (!tk->tk_enabled)
return (ENOSYS);
- /*
- * XXXKIB. The load of tk->tk_current should use
- * atomic_load_acq_32 to provide load barrier. But
- * since tk points to r/o mapped page, x86
- * implementation of atomic_load_acq faults.
- */
- curr = tk->tk_current;
- rmb();
+ curr = atomic_load_acq_32(&tk->tk_current);
th = &tk->tk_th[curr];
if (th->th_algo != VDSO_TH_ALGO_1)
return (ENOSYS);
- gen = th->th_gen;
+ gen = atomic_load_acq_32(&th->th_gen);
*bt = th->th_offset;
bintime_addx(bt, th->th_scale * tc_delta(th));
if (abs)
bintime_add(bt, &th->th_boottime);
/*
- * Barrier for load of both tk->tk_current and th->th_gen.
+ * Ensure that the load of th_offset is completed
+ * before the load of th_gen.
*/
- rmb();
+ atomic_thread_fence_acq();
} while (curr != tk->tk_current || gen == 0 || gen != th->th_gen);
return (0);
}
diff --git a/lib/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2
index c5e8caf..ca94852 100644
--- a/lib/libc/sys/kqueue.2
+++ b/lib/libc/sys/kqueue.2
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 29, 2015
+.Dd August 4, 2015
.Dt KQUEUE 2
.Os
.Sh NAME
@@ -288,6 +288,14 @@ Returns when the file pointer is not at the end of file.
.Va data
contains the offset from current position to end of file,
and may be negative.
+.Pp
+This behavior is different from
+.Xr poll 2 ,
+where read events are triggered for regular files unconditionally.
+This event can be triggered unconditionally by setting the
+.Dv NOTE_FILE_POLL
+flag in
+.Va fflags .
.It "Fifos, Pipes"
Returns when the there is data to read;
.Va data
diff --git a/lib/libc/sys/unlink.2 b/lib/libc/sys/unlink.2
index 406c77c..e59ecf8 100644
--- a/lib/libc/sys/unlink.2
+++ b/lib/libc/sys/unlink.2
@@ -28,7 +28,7 @@
.\" @(#)unlink.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd April 25, 2010
+.Dd July 28, 2015
.Dt UNLINK 2
.Os
.Sh NAME
@@ -151,6 +151,9 @@ The
.Fa path
argument
points outside the process's allocated address space.
+.It Bq Er ENOSPC
+On file systems supporting copy-on-write or snapshots, there was not enough
+free space to record metadata for the delete operation of the file.
.El
.Pp
In addition to the errors returned by the
diff --git a/lib/libthr/arch/amd64/Makefile.inc b/lib/libthr/arch/amd64/Makefile.inc
index 797618d..43f6e83 100644
--- a/lib/libthr/arch/amd64/Makefile.inc
+++ b/lib/libthr/arch/amd64/Makefile.inc
@@ -1,3 +1,9 @@
#$FreeBSD$
SRCS+= _umtx_op_err.S
+
+# With the current compiler and libthr code, using SSE in libthr
+# does not provide enough performance improvement to outweigh
+# the extra context switch cost. This can measurably impact
+# performance when the application also does not use enough SSE.
+CFLAGS+=${CFLAGS_NO_SIMD}
diff --git a/lib/libthr/arch/i386/Makefile.inc b/lib/libthr/arch/i386/Makefile.inc
index bdab0bc..23a9549 100644
--- a/lib/libthr/arch/i386/Makefile.inc
+++ b/lib/libthr/arch/i386/Makefile.inc
@@ -1,3 +1,9 @@
# $FreeBSD$
SRCS+= _umtx_op_err.S
+
+# With the current compiler and libthr code, using SSE in libthr
+# does not provide enough performance improvement to outweigh
+# the extra context switch cost. This can measurably impact
+# performance when the application also does not use enough SSE.
+CFLAGS+=${CFLAGS_NO_SIMD}
diff --git a/libexec/rtld-elf/amd64/Makefile.inc b/libexec/rtld-elf/amd64/Makefile.inc
index 7528dbe..a09db6f 100644
--- a/libexec/rtld-elf/amd64/Makefile.inc
+++ b/libexec/rtld-elf/amd64/Makefile.inc
@@ -1,6 +1,6 @@
# $FreeBSD$
-CFLAGS+= -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float
+CFLAGS+= ${CFLAGS_NO_SIMD} -msoft-float
# Uncomment this to build the dynamic linker as an executable instead
# of a shared library:
#LDSCRIPT= ${.CURDIR}/${MACHINE_CPUARCH}/elf_rtld.x
diff --git a/libexec/rtld-elf/i386/Makefile.inc b/libexec/rtld-elf/i386/Makefile.inc
index 7528dbe..a09db6f 100644
--- a/libexec/rtld-elf/i386/Makefile.inc
+++ b/libexec/rtld-elf/i386/Makefile.inc
@@ -1,6 +1,6 @@
# $FreeBSD$
-CFLAGS+= -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -mno-sse3 -msoft-float
+CFLAGS+= ${CFLAGS_NO_SIMD} -msoft-float
# Uncomment this to build the dynamic linker as an executable instead
# of a shared library:
#LDSCRIPT= ${.CURDIR}/${MACHINE_CPUARCH}/elf_rtld.x
diff --git a/libexec/ypxfr/ypxfr_getmap.c b/libexec/ypxfr/ypxfr_getmap.c
index 4b8794f..458971f 100644
--- a/libexec/ypxfr/ypxfr_getmap.c
+++ b/libexec/ypxfr/ypxfr_getmap.c
@@ -43,8 +43,8 @@ __FBSDID("$FreeBSD$");
extern bool_t xdr_ypresp_all_seq(XDR *, unsigned long *);
-int (*ypresp_allfn)();
-void *ypresp_data;
+static int (*ypresp_allfn)();
+static void *ypresp_data;
extern DB *specdbp;
extern enum ypstat yp_errno;
diff --git a/libexec/ypxfr/ypxfr_main.c b/libexec/ypxfr/ypxfr_main.c
index 03a30f6..03ebbe1 100644
--- a/libexec/ypxfr/ypxfr_main.c
+++ b/libexec/ypxfr/ypxfr_main.c
@@ -54,12 +54,12 @@ __FBSDID("$FreeBSD$");
char *progname = "ypxfr";
char *yp_dir = _PATH_YP;
int _rpcpmstart = 0;
-int ypxfr_use_yplib = 0; /* Assume the worst. */
-int ypxfr_clear = 1;
-int ypxfr_prognum = 0;
-struct sockaddr_in ypxfr_callback_addr;
-struct yppushresp_xfr ypxfr_resp;
-DB *dbp;
+static int ypxfr_use_yplib = 0; /* Assume the worst. */
+static int ypxfr_clear = 1;
+static int ypxfr_prognum = 0;
+static struct sockaddr_in ypxfr_callback_addr;
+static struct yppushresp_xfr ypxfr_resp;
+static DB *dbp;
static void
ypxfr_exit(ypxfrstat retval, char *temp)
diff --git a/libexec/ypxfr/ypxfrd_getmap.c b/libexec/ypxfr/ypxfrd_getmap.c
index b1424ac..a5ac92d 100644
--- a/libexec/ypxfr/ypxfrd_getmap.c
+++ b/libexec/ypxfr/ypxfrd_getmap.c
@@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include "ypxfr_extern.h"
-int fp = 0;
+static int fp = 0;
static bool_t
xdr_my_xfr(register XDR *xdrs, xfr *objp)
diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml
index f00a268..fbf35b5 100644
--- a/release/doc/en_US.ISO8859-1/relnotes/article.xml
+++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml
@@ -1049,7 +1049,7 @@
<para revision="272730">The &man.alc.4; driver has been updated
to support AR816x and AR817x ethernet controllers.</para>
- <para revision="272906">The &man.pfil.9; interface default hash
+ <para revision="272906">The &man.pf.4; packet filter default hash
has been changed from <literal>Jenkins</literal> to
<literal>Murmur3</literal>, providing a 3-percent performance
increase in packets-per-second.</para>
@@ -1405,7 +1405,7 @@
&os;.</para>
<sect2 xml:id="network-protocols">
- <title>Network Procols</title>
+ <title>Network Protocols</title>
<para revision="263140">Support for the IPX network transport
protocol has been removed, and will not be supported in
diff --git a/release/tools/ec2.conf b/release/tools/ec2.conf
index 9472ec5..557e602 100644
--- a/release/tools/ec2.conf
+++ b/release/tools/ec2.conf
@@ -70,6 +70,11 @@ vm_extra_pre_umount() {
# nodes, but apply the workaround just in case.
echo 'hw.broken_txfifo="1"' >> ${DESTDIR}/boot/loader.conf
+ # Some EC2 instances suffer a significant (~40%) reduction in
+ # throughput when using blkif indirect segment I/Os. Disable this
+ # by default for now.
+ echo 'hw.xbd.xbd_enable_indirect="0"' >> ${DESTDIR}/boot/loader.conf
+
# The first time the AMI boots, the installed "first boot" scripts
# should be allowed to run:
# * ec2_configinit (download and process EC2 user-data)
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index 687d707..5dea974 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -3033,9 +3033,10 @@ fill_flags_cmd(ipfw_insn *cmd, enum ipfw_opcodes opcode,
void
ipfw_delete(char *av[])
{
- int i;
+ int i, j;
int exitval = EX_OK;
int do_set = 0;
+ char *sep;
ipfw_range_tlv rt;
av++;
@@ -3053,7 +3054,11 @@ ipfw_delete(char *av[])
/* Rule number */
while (*av && isdigit(**av)) {
- i = atoi(*av); av++;
+ i = strtol(*av, &sep, 10);
+ j = i;
+ if (*sep== '-')
+ j = strtol(sep + 1, NULL, 10);
+ av++;
if (co.do_nat) {
exitval = do_cmd(IP_FW_NAT_DEL, &i, sizeof i);
if (exitval) {
@@ -3068,7 +3073,7 @@ ipfw_delete(char *av[])
rt.flags = IPFW_RCFLAG_SET;
} else {
rt.start_rule = i & 0xffff;
- rt.end_rule = i & 0xffff;
+ rt.end_rule = j & 0xffff;
if (rt.start_rule == 0 && rt.end_rule == 0)
rt.flags |= IPFW_RCFLAG_ALL;
else
diff --git a/sbin/mdconfig/mdconfig.8 b/sbin/mdconfig/mdconfig.8
index 04d3391..2645327 100644
--- a/sbin/mdconfig/mdconfig.8
+++ b/sbin/mdconfig/mdconfig.8
@@ -37,12 +37,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 30, 2013
+.Dd August 6, 2015
.Dt MDCONFIG 8
.Os
.Sh NAME
.Nm mdconfig
-.Nd configure and enable memory disks
+.Nd create and control memory disks
.Sh SYNOPSIS
.Nm
.Fl a
@@ -75,7 +75,7 @@
.Sh DESCRIPTION
The
.Nm
-utility configures and enables
+utility creates and controls
.Xr md 4
devices.
.Pp
@@ -103,7 +103,7 @@ If the
.Fl o Cm reserve
option is not set, creating and filling a large
malloc-backed memory disk is a very easy way to
-panic a system.
+panic the system.
.It Cm vnode
A file specified with
.Fl f Ar file
@@ -164,7 +164,9 @@ or
.Cm t
which
denotes byte, kilobyte, megabyte, gigabyte and terabyte respectively.
-The
+When used without the
+.Fl r
+option, the
.Fl a
and
.Fl t Ar swap
@@ -206,6 +208,11 @@ Enable/disable compression features to reduce memory usage.
.It Oo Cm no Oc Ns Cm force
Disable/enable extra sanity checks to prevent the user from doing something
that might adversely affect the system.
+This can be used with the
+.Fl d
+flag to forcibly destroy an
+.Xr md 4
+disk that is still in use.
.It Oo Cm no Oc Ns Cm readonly
Enable/disable readonly mode.
.El
@@ -227,66 +234,58 @@ is provided for convenience as an abbreviation of
.Fl t Ar vnode
.Fl f Ar file .
.Sh EXAMPLES
-Create a 4 megabyte
-.Xr malloc 9
-backed memory disk.
-The name of the allocated unit will be printed on stdout, such as
-.Dq Li md3 :
-.Pp
-.Dl mdconfig -a -t malloc -s 4m
-.Pp
-Create a disk named
-.Pa /dev/md4
-with
+Create a disk with
.Pa /tmp/boot.flp
-as backing storage:
+as backing storage.
+The name of the allocated unit will be printed on stdout, such as
+.Dq Li md0 :
+.Bd -literal -offset indent
+mdconfig /tmp/boot.flp
+.Ed
.Pp
-.Dl mdconfig -a -t vnode -f /tmp/boot.flp -u md4
+Create a 1 gigabyte swap backed memory disk named
+.Dq Li md3 :
+.Bd -literal -offset indent
+mdconfig -s 1g -u md3
+.Ed
.Pp
Detach and free all resources used by
-.Pa /dev/md4 :
+.Pa /dev/md3 :
+.Bd -literal -offset indent
+mdconfig -du md3
+.Ed
+.Pp
+Show detailed information on current memory disks:
+.Bd -literal -offset indent
+mdconfig -lv
+.Ed
.Pp
-.Dl mdconfig -d -u md4
+Resize the
+.Dq Li md3
+memory disk to 2 gigabytes:
+.Bd -literal -offset indent
+mdconfig -rs 2g -u md3
+.Ed
.Pp
-Create a 128MByte swap backed disk, initialize an
+Create a 1 gigabyte swap backed disk, initialize an
.Xr ffs 7
file system on it, and mount it on
.Pa /tmp :
.Bd -literal -offset indent
-mdconfig -a -t swap -s 128M -u md10
+mdconfig -s 1g -u md10
newfs -U /dev/md10
mount /dev/md10 /tmp
chmod 1777 /tmp
.Ed
.Pp
-Create a 5MB file-backed disk
-.Po Fl a
-and
-.Fl t Ar vnode
-are implied
-.Pc :
-.Bd -literal -offset indent
-dd if=/dev/zero of=somebackingfile bs=1k count=5k
-mdconfig -f somebackingfile -u md0
-bsdlabel -w md0 auto
-newfs md0c
-mount /dev/md0c /mnt
-.Ed
-.Pp
-Create an
-.Xr md 4
-device out of an ISO 9660 CD image file
-.Po Fl a
-and
-.Fl t Ar vnode
-are implied
-.Pc , using the first available
+Create a memory disk out of an ISO 9660 CD image file,
+using the first available
.Xr md 4
-device, and then mount the new memory disk:
+device, and then mount it:
.Bd -literal -offset indent
mount -t cd9660 /dev/`mdconfig -f cdimage.iso` /mnt
-.Pp
.Ed
+.Pp
Create a file-backed device from a hard disk image that begins
with 512K of raw header information.
.Xr gnop 8
@@ -294,7 +293,7 @@ is used to skip over the header information, positioning
.Pa md1.nop
to the start of the filesystem in the image.
.Bd -literal -offset indent
-mdconfig -f diskimage.img -u md1
+mdconfig -u md1 -f diskimage.img
gnop create -o 512K md1
mount /dev/md1.nop /mnt
.Ed
diff --git a/sbin/routed/input.c b/sbin/routed/input.c
index 895ef50..bc03028 100644
--- a/sbin/routed/input.c
+++ b/sbin/routed/input.c
@@ -160,6 +160,12 @@ input(struct sockaddr_in *from, /* received from this IP address */
trace_rip("Recv", "from", from, sifp, rip, cc);
+ if (sifp == 0) {
+ trace_pkt(" discard a request from an indirect router"
+ " (possibly an attack)");
+ return;
+ }
+
if (rip->rip_vers == 0) {
msglim(&bad_router, FROM_NADDR,
"RIP version 0, cmd %d, packet received from %s",
diff --git a/sbin/setkey/parse.y b/sbin/setkey/parse.y
index c551c35..60e779d 100644
--- a/sbin/setkey/parse.y
+++ b/sbin/setkey/parse.y
@@ -100,6 +100,7 @@ extern void yyerror(const char *);
%token F_EXT EXTENSION NOCYCLICSEQ
%token ALG_AUTH ALG_AUTH_NOKEY
%token ALG_ENC ALG_ENC_NOKEY ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD
+%token ALG_ENC_SALT
%token ALG_COMP
%token F_LIFETIME_HARD F_LIFETIME_SOFT
%token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
@@ -111,6 +112,7 @@ extern void yyerror(const char *);
%type <num> prefix protocol_spec upper_spec
%type <num> ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD ALG_ENC_NOKEY
+%type <num> ALG_ENC_SALT
%type <num> ALG_AUTH ALG_AUTH_NOKEY
%type <num> ALG_COMP
%type <num> PR_ESP PR_AH PR_IPCOMP PR_TCP
@@ -402,6 +404,27 @@ enc_alg
return -1;
}
}
+ | ALG_ENC_SALT key_string
+ {
+ if ($1 < 0) {
+ yyerror("unsupported algorithm");
+ return -1;
+ }
+ p_alg_enc = $1;
+
+ p_key_enc_len = $2.len;
+
+ p_key_enc = $2.buf;
+ /*
+ * Salted keys include a 4 byte value that is
+ * not part of the key.
+ */
+ if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
+ p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len - 4)) < 0) {
+ yyerror(ipsec_strerror());
+ return -1;
+ }
+ }
;
auth_alg
diff --git a/sbin/setkey/setkey.8 b/sbin/setkey/setkey.8
index b9c6160..62fb2e1 100644
--- a/sbin/setkey/setkey.8
+++ b/sbin/setkey/setkey.8
@@ -624,7 +624,6 @@ null 0 to 2048 rfc2410
blowfish-cbc 40 to 448 rfc2451
cast128-cbc 40 to 128 rfc2451
des-deriv 64 ipsec-ciph-des-derived-01
-3des-deriv 192 no document
rijndael-cbc 128/192/256 rfc3602
aes-ctr 160/224/288 draft-ietf-ipsec-ciph-aes-ctr-03
aes-gcm-16 160/224/288 rfc4106
diff --git a/sbin/setkey/token.l b/sbin/setkey/token.l
index 1b66719..7f30859 100644
--- a/sbin/setkey/token.l
+++ b/sbin/setkey/token.l
@@ -166,9 +166,9 @@ tcp { yylval.num = 0; return(PR_TCP); }
<S_ENCALG>des-deriv { yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC_DESDERIV); }
<S_ENCALG>des-32iv { yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC_DES32IV); }
<S_ENCALG>rijndael-cbc { yylval.num = SADB_X_EALG_RIJNDAELCBC; BEGIN INITIAL; return(ALG_ENC); }
-<S_ENCALG>aes-ctr { yylval.num = SADB_X_EALG_AESCTR; BEGIN INITIAL; return(ALG_ENC); }
+<S_ENCALG>aes-ctr { yylval.num = SADB_X_EALG_AESCTR; BEGIN INITIAL; return(ALG_ENC_SALT); }
<S_ENCALG>camellia-cbc { yylval.num = SADB_X_EALG_CAMELLIACBC; BEGIN INITIAL; return(ALG_ENC); }
-<S_ENCALG>aes-gcm-16 { yylval.num = SADB_X_EALG_AESGCM16; BEGIN INITIAL; return(ALG_ENC); }
+<S_ENCALG>aes-gcm-16 { yylval.num = SADB_X_EALG_AESGCM16; BEGIN INITIAL; return(ALG_ENC_SALT); }
/* compression algorithms */
{hyphen}C { return(F_COMP); }
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c
index f321120..d740778c 100644
--- a/sbin/sysctl/sysctl.c
+++ b/sbin/sysctl/sysctl.c
@@ -81,7 +81,7 @@ static int show_var(int *, int);
static int sysctl_all(int *oid, int len);
static int name2oid(const char *, int *);
-static int strIKtoi(const char *, char **);
+static int strIKtoi(const char *, char **, const char *);
static int ctl_sign[CTLTYPE+1] = {
[CTLTYPE_INT] = 1,
@@ -336,8 +336,8 @@ parse(const char *string, int lineno)
switch (kind & CTLTYPE) {
case CTLTYPE_INT:
- if (strcmp(fmt, "IK") == 0)
- intval = strIKtoi(newvalstr, &endptr);
+ if (strncmp(fmt, "IK", 2) == 0)
+ intval = strIKtoi(newvalstr, &endptr, fmt);
else
intval = (int)strtol(newvalstr, &endptr,
0);
@@ -666,12 +666,13 @@ S_bios_smap_xattr(size_t l2, void *p)
#endif
static int
-strIKtoi(const char *str, char **endptrp)
+strIKtoi(const char *str, char **endptrp, const char *fmt)
{
int kelv;
float temp;
size_t len;
const char *p;
+ int prec, i;
assert(errno == 0);
@@ -679,16 +680,36 @@ strIKtoi(const char *str, char **endptrp)
/* caller already checked this */
assert(len > 0);
+ /*
+ * A format of "IK" is in deciKelvin. A format of "IK3" is in
+ * milliKelvin. The single digit following IK is log10 of the
+ * multiplying factor to convert Kelvin into the untis of this sysctl,
+ * or the dividing factor to convert the sysctl value to Kelvin. Numbers
+ * larger than 6 will run into precision issues with 32-bit integers.
+ * Characters that aren't ASCII digits after the 'K' are ignored. No
+ * localization is present because this is an interface from the kernel
+ * to this program (eg not an end-user interface), so isdigit() isn't
+ * used here.
+ */
+ if (fmt[2] != '\0' && fmt[2] >= '0' && fmt[2] <= '9')
+ prec = fmt[2] - '0';
+ else
+ prec = 1;
p = &str[len - 1];
- if (*p == 'C' || *p == 'F') {
+ if (*p == 'C' || *p == 'F' || *p == 'K') {
temp = strtof(str, endptrp);
if (*endptrp != str && *endptrp == p && errno == 0) {
if (*p == 'F')
temp = (temp - 32) * 5 / 9;
*endptrp = NULL;
- return (temp * 10 + 2732);
+ if (*p != 'K')
+ temp += 273.15;
+ for (i = 0; i < prec; i++)
+ temp *= 10.0;
+ return ((int)(temp + 0.5));
}
} else {
+ /* No unit specified -> treat it as a raw number */
kelv = (int)strtol(str, endptrp, 10);
if (*endptrp != str && *endptrp == p && errno == 0) {
*endptrp = NULL;
@@ -772,7 +793,9 @@ show_var(int *oid, int nlen)
size_t intlen;
size_t j, len;
u_int kind;
+ float base;
int (*func)(size_t, void *);
+ int prec;
/* Silence GCC. */
umv = mv = intlen = 0;
@@ -893,8 +916,19 @@ show_var(int *oid, int nlen)
else if (fmt[1] == 'K') {
if (mv < 0)
printf("%jd", mv);
- else
- printf("%.1fC", (mv - 2732.0) / 10);
+ else {
+ /*
+ * See strIKtoi for details on fmt.
+ */
+ prec = 1;
+ if (fmt[2] != '\0')
+ prec = fmt[2] - '0';
+ base = 1.0;
+ for (int i = 0; i < prec; i++)
+ base *= 10.0;
+ printf("%.*fC", prec,
+ (float)mv / base - 273.15);
+ }
} else
printf(hflag ? "%'jd" : "%jd", mv);
sep1 = " ";
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index fc73704..5cb8c23 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -96,6 +96,7 @@ MAN= aac.4 \
cdce.4 \
ch.4 \
ciss.4 \
+ cloudabi.4 \
cm.4 \
cmx.4 \
${_coretemp.4} \
@@ -583,6 +584,7 @@ MLINKS+=bwn.4 if_bwn.4
MLINKS+=${_bxe.4} ${_if_bxe.4}
MLINKS+=cas.4 if_cas.4
MLINKS+=cdce.4 if_cdce.4
+MLINKS+=cloudabi.4 cloudabi64.4
MLINKS+=crypto.4 cryptodev.4
MLINKS+=cue.4 if_cue.4
MLINKS+=cxgb.4 if_cxgb.4
@@ -666,6 +668,7 @@ MLINKS+=pccbb.4 cbb.4
MLINKS+=pcm.4 snd.4 \
pcm.4 sound.4
MLINKS+=pcn.4 if_pcn.4
+MLINKS+=pms.4 pmspcv.4
MLINKS+=ral.4 if_ral.4
MLINKS+=re.4 if_re.4
MLINKS+=rl.4 if_rl.4
diff --git a/share/man/man4/bwi.4 b/share/man/man4/bwi.4
index fe1ea65..7ee9e85 100644
--- a/share/man/man4/bwi.4
+++ b/share/man/man4/bwi.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 6, 2011
+.Dd August 7, 2015
.Dt BWI 4
.Os
.Sh NAME
@@ -76,6 +76,7 @@ driver supports Broadcom BCM43xx based wireless devices, including:
.It Em "Card" Ta Em "Chip" Ta Em "Bus" Ta Em "Standard"
.It "Apple Airport Extreme BCM4306 PCI b/g"
.It "Apple Airport Extreme BCM4318 PCI b/g"
+.It "ASUS WL-100g BCM4306 CardBus b/g"
.It "ASUS WL-138g BCM4318 PCI b/g"
.It "Buffalo WLI-CB-G54S BCM4318 CardBus b/g"
.It "Buffalo WLI-PCI-G54S BCM4306 PCI b/g"
diff --git a/share/man/man4/cloudabi.4 b/share/man/man4/cloudabi.4
new file mode 100644
index 0000000..050e8c0
--- /dev/null
+++ b/share/man/man4/cloudabi.4
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2015 Nuxi, https://nuxi.nl/
+.\"
+.\" 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$
+.Dd July 31, 2015
+.Dt CLOUDABI 4
+.Os
+.Sh NAME
+.Nm cloudabi ,
+.Nm cloudabi64
+.Nd CloudABI support
+.Sh SYNOPSIS
+Support for 64-bit CloudABI executables can be compiled into the kernel
+by adding this line to the kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "options COMPAT_CLOUDABI64"
+.Ed
+.Pp
+CloudABI support can also be loaded at boot time from
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+cloudabi_load="YES"
+cloudabi64_load="YES"
+.Ed
+.Sh DESCRIPTION
+CloudABI is a POSIX-like pure capability-based runtime environment,
+similar to
+.Xr capsicum 4 .
+It can be used to develop applications that are cross-platform,
+easier to test,
+and hardened against security exploits.
+.Pp
+Support for CloudABI on
+.Fx
+consists of two separate kernel modules.
+The
+.Nm cloudabi
+kernel module implements all of the system calls that do not depend on
+data structures that differ between architectures.
+.Pp
+The
+.Nm cloudabi64
+kernel module provides implementations of all of the machine-dependent
+system calls.
+It assumes that pointers stored in data structures provided as system
+call arguments are 64 bits in size.
+It also provides the image activator that loads and starts 64-bit ELF
+executables.
+.Pp
+Though the
+.Nm cloudabi
+module can be loaded on any architecture supported by
+.Fx ,
+the
+.Nm cloudabi64
+module is only available for amd64.
+.Pp
+A full cross compilation toolchain for CloudABI is available in the
+.Pa devel/cloudabi-toolchain
+port.
+.Pp
+The
+.Pa sysutils/cloudabi-utils
+port provides the
+.Xr cloudabi-run 1
+utility.
+.Xr cloudabi-run 1
+can be used to safely execute CloudABI processes with access to a
+restricted set of resources.
+.Sh SEE ALSO
+.Xr cloudabi-run 1 ,
+.Xr capsicum 4 ,
+.Xr linux 4 ,
+.Xr elf 5
+.Pp
+cloudlibc on GitHub:
+.Pa https://github.com/NuxiNL/cloudlibc .
+.Sh HISTORY
+CloudABI support first appeared in
+.Fx 11.0 .
+.Sh AUTHORS
+Nuxi:
+.Pa https://nuxi.nl/ .
diff --git a/share/man/man4/pms.4 b/share/man/man4/pms.4
index 7684051..05dd7bc 100644
--- a/share/man/man4/pms.4
+++ b/share/man/man4/pms.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 23, 2015
+.Dd July 30, 2015
.Dt PMS 4
.Os
.Sh NAME
@@ -35,14 +35,14 @@ To compile the driver into the kernel,
place the following line in the
kernel configuration file:
.Bd -ragged -offset indent
-.Cd "device pms"
+.Cd "device pmspcv"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
-pms_load="YES"
+pmspcv_load="YES"
.Ed
.Sh DESCRIPTION
The
@@ -124,5 +124,3 @@ The
.Nm
device driver first appeared in
.Fx 10.2 .
-.Sh AUTHORS
-.An Achim Leubner Aq Mt Achim.Leubner@pmcs.com
diff --git a/share/man/man4/ral.4 b/share/man/man4/ral.4
index 29aaa8c..7ca2699 100644
--- a/share/man/man4/ral.4
+++ b/share/man/man4/ral.4
@@ -14,7 +14,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 10, 2012
+.Dd August 4, 2015
.Dt RAL 4
.Os
.Sh NAME
@@ -184,6 +184,7 @@ chipsets, including:
.It "MSI PC54G2" Ta RT2560 Ta PCI
.It "OvisLink EVO-W54PCI" Ta RT2560 Ta PCI
.It "PheeNet HWL-PCIG/RA" Ta RT2560 Ta PCI
+.It "Planex GW-NS300N" Ta RT2860 Ta CardBus
.It "Pro-Nets CB80211G" Ta RT2560 Ta CardBus
.It "Pro-Nets PC80211G" Ta RT2560 Ta PCI
.It "Repotec RP-WB7108" Ta RT2560 Ta CardBus
diff --git a/share/man/man4/uftdi.4 b/share/man/man4/uftdi.4
index 1045169..687d443 100644
--- a/share/man/man4/uftdi.4
+++ b/share/man/man4/uftdi.4
@@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 31, 2014
+.Dd August 6, 2015
.Dt UFTDI 4
.Os
.Sh NAME
@@ -110,6 +110,11 @@ The
must be one of the
.Va uftdi_bitmodes
values.
+Setting
+.Va mode
+to
+.Dv UFTDI_BITMODE_NONE
+returns the channel to standard UART mode.
.Bd -literal
enum uftdi_bitmodes
{
@@ -139,12 +144,15 @@ and
data which either reflects pin state or is interpreted
as MPSSE commands and parameters, depending on the mode.
.It Dv UFTDIIOC_GET_BITMODE Pq Vt "struct uftdi_bitmode"
-Return the state of the bitbang pins at the time of the call in the
+Return the current bitbang mode in the
+.Va mode
+member, and the state of the DBUS0..DBUS7 pins at the time
+of the call in the
.Va iomask
member.
-The
-.Va mode
-member is unused.
+The pin state can be read while the chip is in any mode, including
+.Dv UFTDI_BITMODE_NONE
+(UART) mode.
.It Dv UFTDIIOC_SET_ERROR_CHAR Pq Vt int
Set the character which is inserted into the buffer to mark
the point of an error such as FIFO overflow.
@@ -164,6 +172,54 @@ This is the
.Va bcdDevice
value from the
.Va usb_device_descriptor .
+.It Dv UFTDIIOC_READ_EEPROM Pq Vt "struct uftdi_eeio"
+Read one or more words from the configuration eeprom.
+The FTDI chip performs eeprom I/O in 16-bit words.
+Set
+.Va offset
+and
+.Va length
+to values evenly divisible by two before the call, and the
+.Va data
+array will contain the requested values from eeprom after the call.
+.Bd -literal
+struct uftdi_eeio
+{
+ uint16_t offset;
+ uint16_t length;
+ uint16_t data[64];
+};
+.Ed
+.Pp
+The FT232R chip has an internal eeprom.
+An external serial eeprom is optional on other FTDI chips.
+The eeprom may contain 64, 128, or 256 words,
+depending on the part used.
+Multiple calls may be needed to read or write the larger parts.
+When no eeprom is present, all words in the returned data are 0xffff.
+An erased eeprom also reads as all 0xffff.
+.It Dv UFTDIIOC_WRITE_EEPROM Pq Vt "struct uftdi_eeio"
+Write one or more words to the configuration eeprom.
+The
+.Va uftdi_eeio
+values are as described for
+.Dv UFTDIIOC_READ_EEPROM .
+.Pp
+The FTDI chip does a blind write to the eeprom, and it will appear
+to succeed even when no eeprom is present.
+To ensure a good write you must read back and verify the data.
+It is
+.Em not
+necessary to erase before writing.
+Any position within the eeprom can be overwritten at any time.
+.It Dv UFTDIIOC_ERASE_EEPROM Pq Vt int
+Erase the entire eeprom.
+This is useful primarily for test and debugging, as there is no
+need to erase before writing.
+To help prevent accidental erasure caused by calling the wrong
+ioctl, you must pass the special value
+.Dv UFTDI_CONFIRM_ERASE
+as the argument to this ioctl.
.El
.Sh HARDWARE
The
diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5
index 90885e7..b1ac394 100644
--- a/share/man/man5/src.conf.5
+++ b/share/man/man5/src.conf.5
@@ -1,7 +1,7 @@
.\" DO NOT EDIT-- this file is automatically generated.
-.\" from FreeBSD: head/tools/build/options/makeman 255964 2013-10-01 07:22:04Z des
+.\" from FreeBSD: head/tools/build/options/makeman 284708 2015-06-22 20:21:57Z sjg
.\" $FreeBSD$
-.Dd June 22, 2015
+.Dd August 1, 2015
.Dt SRC.CONF 5
.Os
.Sh NAME
@@ -127,7 +127,7 @@ Set to not build
.Xr autofs 4
related programs, libraries, and kernel modules.
.It Va WITH_AUTO_OBJ
-.\" $FreeBSD$
+.\" from FreeBSD: head/tools/build/options/WITH_AUTO_OBJ 284708 2015-06-22 20:21:57Z sjg
Enable automatic creation of objdirs.
.It Va WITHOUT_BHYVE
.\" from FreeBSD: head/tools/build/options/WITHOUT_BHYVE 277727 2015-01-26 06:44:48Z ngie
@@ -137,11 +137,14 @@ associated utilities, and examples.
.Pp
This option only affects amd64/amd64.
.It Va WITHOUT_BINUTILS
-.\" from FreeBSD: head/tools/build/options/WITHOUT_BINUTILS 266158 2014-05-15 16:51:45Z brooks
-Set to not build or install binutils (as, c++-filt, gconv,
+.\" from FreeBSD: head/tools/build/options/WITHOUT_BINUTILS 286036 2015-07-29 20:02:20Z emaste
+Set to not build or install binutils (as, c++-filt,
ld, nm, objcopy, objdump, readelf, size and strip) as part
of the normal system build.
The resulting system cannot build programs from source.
+.Pp
+It is a default setting on
+arm64/aarch64.
.It Va WITHOUT_BINUTILS_BOOTSTRAP
.\" from FreeBSD: head/tools/build/options/WITHOUT_BINUTILS_BOOTSTRAP 264660 2014-04-18 17:03:58Z imp
Set to not build binutils (as, c++-filt, gconv,
@@ -151,6 +154,9 @@ as part of the bootstrap process.
The option does not work for build targets unless some alternative
toolchain is provided.
.Ef
+.Pp
+It is a default setting on
+arm64/aarch64.
.It Va WITHOUT_BLUETOOTH
.\" from FreeBSD: head/tools/build/options/WITHOUT_BLUETOOTH 156932 2006-03-21 07:50:50Z ru
Set to not build Bluetooth related kernel modules, programs and libraries.
@@ -243,7 +249,7 @@ When set, it also enforces the following options:
Set to build the Clang C/C++ compiler during the normal phase of the build.
.Pp
It is a default setting on
-amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, i386/i386, pc98/i386, powerpc/powerpc and powerpc/powerpc64.
+amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, arm64/aarch64, i386/i386, pc98/i386, powerpc/powerpc and powerpc/powerpc64.
.It Va WITHOUT_CLANG_BOOTSTRAP
.\" from FreeBSD: head/tools/build/options/WITHOUT_CLANG_BOOTSTRAP 273177 2014-10-16 18:28:11Z skreuzer
Set to not build the Clang C/C++ compiler during the bootstrap phase of the build.
@@ -258,7 +264,7 @@ mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, powerpc/powerp
Set to build the Clang C/C++ compiler during the bootstrap phase of the build.
.Pp
It is a default setting on
-amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, i386/i386 and pc98/i386.
+amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, arm64/aarch64, i386/i386 and pc98/i386.
.It Va WITH_CLANG_EXTRAS
.\" from FreeBSD: head/tools/build/options/WITH_CLANG_EXTRAS 231057 2012-02-05 23:56:22Z dim
Set to build additional clang and llvm tools, such as bugpoint.
@@ -268,14 +274,14 @@ Set to avoid building the ARCMigrate, Rewriter and StaticAnalyzer components of
the Clang C/C++ compiler.
.Pp
It is a default setting on
-arm/arm, arm/armeb, arm/armv6, arm/armv6hf, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32 and sparc64/sparc64.
+mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32 and sparc64/sparc64.
.It Va WITH_CLANG_FULL
.\" from FreeBSD: head/tools/build/options/WITH_CLANG_FULL 246259 2013-02-02 22:28:29Z dim
Set to build the ARCMigrate, Rewriter and StaticAnalyzer components of the
Clang C/C++ compiler.
.Pp
It is a default setting on
-amd64/amd64, i386/i386, pc98/i386, powerpc/powerpc and powerpc/powerpc64.
+amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, arm64/aarch64, i386/i386, pc98/i386, powerpc/powerpc and powerpc/powerpc64.
.It Va WITHOUT_CLANG_IS_CC
.\" from FreeBSD: head/tools/build/options/WITHOUT_CLANG_IS_CC 242629 2012-11-05 21:53:23Z brooks
Set to install the GCC compiler as
@@ -295,7 +301,7 @@ and
.Pa /usr/bin/cpp .
.Pp
It is a default setting on
-amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, i386/i386 and pc98/i386.
+amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, arm64/aarch64, i386/i386 and pc98/i386.
.It Va WITHOUT_CPP
.\" from FreeBSD: head/tools/build/options/WITHOUT_CPP 156932 2006-03-21 07:50:50Z ru
Set to not build
@@ -396,7 +402,7 @@ and are located automatically by
.\" from FreeBSD: head/tools/build/options/WITHOUT_DICT 156932 2006-03-21 07:50:50Z ru
Set to not build the Webster dictionary files.
.It Va WITH_DIRDEPS_CACHE
-.\" $FreeBSD$
+.\" from FreeBSD: head/tools/build/options/WITH_DIRDEPS_CACHE 284708 2015-06-22 20:21:57Z sjg
Cache result of dirdeps.mk which can save significant time
for subsequent builds.
Depends on
@@ -408,6 +414,12 @@ Set to not build dma Mail Transport Agent
.\" from FreeBSD: head/tools/build/options/WITHOUT_DOCCOMPRESS 266752 2014-05-27 15:52:27Z gjb
Set to not to install compressed system documentation.
Only the uncompressed version will be installed.
+.It Va WITH_DTRACE_TESTS
+.\" from FreeBSD: head/tools/build/options/WITH_DTRACE_TESTS 286174 2015-08-02 00:37:33Z markj
+Set to build and install the DTrace test suite in
+.Pa /usr/tests/cddl/usr.sbin/dtrace .
+This test suite is considered experimental on architectures other than
+amd64/amd64 and running it may cause system instability.
.It Va WITHOUT_DYNAMICROOT
.\" from FreeBSD: head/tools/build/options/WITHOUT_DYNAMICROOT 156932 2006-03-21 07:50:50Z ru
Set this if you do not want to link
@@ -429,11 +441,29 @@ and related programs.
.It Va WITH_EISA
.\" from FreeBSD: head/tools/build/options/WITH_EISA 264654 2014-04-18 16:53:06Z imp
Set to build EISA kernel modules.
+.It Va WITHOUT_ELFCOPY_AS_OBJCOPY
+.\" from FreeBSD: head/tools/build/options/WITHOUT_ELFCOPY_AS_OBJCOPY 286030 2015-07-29 18:45:38Z emaste
+Set to build and install
+.Xr objcopy 1
+from GNU Binutils, instead of the one from ELF Tool Chain.
+.Pp
+It is a default setting on
+amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, i386/i386, mips/mipsel, mips/mips, mips/mips64el, mips/mips64, mips/mipsn32, pc98/i386, powerpc/powerpc, powerpc/powerpc64 and sparc64/sparc64.
+.It Va WITH_ELFCOPY_AS_OBJCOPY
+.\" from FreeBSD: head/tools/build/options/WITH_ELFCOPY_AS_OBJCOPY 286030 2015-07-29 18:45:38Z emaste
+Set to build and install ELF Tool Chain's elfcopy as
+.Xr objcopy 1 ,
+instead of the one from GNU Binutils.
+.Pp
+It is a default setting on
+arm64/aarch64.
.It Va WITHOUT_ELFTOOLCHAIN_TOOLS
-.\" from FreeBSD: head/tools/build/options/WITHOUT_ELFTOOLCHAIN_TOOLS 276796 2015-01-07 22:02:37Z emaste
+.\" from FreeBSD: head/tools/build/options/WITHOUT_ELFTOOLCHAIN_TOOLS 286016 2015-07-29 15:42:22Z emaste
Set to use
.Xr addr2line 1 ,
+.Xr c++filt 1 ,
.Xr nm 1 ,
+.Xr readelf 1 ,
.Xr size 1 ,
.Xr strings 1 ,
and
@@ -462,11 +492,6 @@ and
.\" from FreeBSD: head/tools/build/options/WITHOUT_FLOPPY 221540 2011-05-06 19:13:03Z ru
Set to not build or install programs
for operating floppy disk driver.
-.It Va WITH_FMAKE
-.\" from FreeBSD: head/tools/build/options/WITH_FMAKE 275138 2014-11-26 20:43:09Z gjb
-Causes the old FreeBSD
-.Xr make 1
-program to be built and installed as fmake.
.It Va WITHOUT_FMTREE
.\" from FreeBSD: head/tools/build/options/WITHOUT_FMTREE 261299 2014-01-30 21:37:43Z brooks
Set to not build and install
@@ -503,7 +528,7 @@ Set to not build games.
Set to not build and install gcc and g++ as part of the normal build process.
.Pp
It is a default setting on
-amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, i386/i386 and pc98/i386.
+amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, arm64/aarch64, i386/i386 and pc98/i386.
.It Va WITH_GCC
.\" from FreeBSD: head/tools/build/options/WITH_GCC 255326 2013-09-06 20:49:48Z zeising
Set to build and install gcc and g++.
@@ -518,7 +543,7 @@ unless an alternative compiler is provided via
XCC.
.Pp
It is a default setting on
-amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, i386/i386 and pc98/i386.
+amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, arm64/aarch64, i386/i386 and pc98/i386.
.It Va WITH_GCC_BOOTSTRAP
.\" from FreeBSD: head/tools/build/options/WITH_GCC_BOOTSTRAP 264660 2014-04-18 17:03:58Z imp
Set to build gcc and g++ as part of the bootstrap process.
@@ -534,6 +559,9 @@ tool.
.\" from FreeBSD: head/tools/build/options/WITHOUT_GDB 156932 2006-03-21 07:50:50Z ru
Set to not build
.Xr gdb 1 .
+.Pp
+It is a default setting on
+arm64/aarch64.
.It Va WITHOUT_GNU
.\" from FreeBSD: head/tools/build/options/WITHOUT_GNU 174550 2007-12-12 16:43:17Z ru
Set to not build contributed GNU software as a part of the base system.
@@ -554,7 +582,7 @@ Do not build the GNU C++ stack (g++, libstdc++).
This is the default on platforms where clang is the system compiler.
.Pp
It is a default setting on
-amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, i386/i386 and pc98/i386.
+amd64/amd64, arm/arm, arm/armeb, arm/armv6, arm/armv6hf, arm64/aarch64, i386/i386 and pc98/i386.
.It Va WITH_GNUCXX
.\" from FreeBSD: head/tools/build/options/WITH_GNUCXX 255321 2013-09-06 20:08:03Z theraven
Build the GNU C++ stack (g++, libstdc++).
@@ -861,11 +889,11 @@ Set to not build utilities for manual pages,
.Xr manctl 8 ,
and related support files.
.It Va WITH_META_FILES
-.\" $FreeBSD$
+.\" from FreeBSD: head/tools/build/options/WITH_META_FILES 284708 2015-06-22 20:21:57Z sjg
Create meta files during non META_MODE build.
The meta files can be useful for debugging.
.It Va WITH_META_MODE
-.\" $FreeBSD$
+.\" from FreeBSD: head/tools/build/options/WITH_META_MODE 284708 2015-06-22 20:21:57Z sjg
Enable building in meta mode.
.Pp
The build is driven by dirdeps.mk using DIRDEPS stored in
@@ -1153,7 +1181,7 @@ Set to not build kernel modules that include sourceless microcode.
.\" from FreeBSD: head/tools/build/options/WITHOUT_SSP 180012 2008-06-25 21:33:28Z ru
Set to not build world with propolice stack smashing protection.
.It Va WITH_STAGING
-.\" $FreeBSD$
+.\" from FreeBSD: head/tools/build/options/WITH_STAGING 284708 2015-06-22 20:21:57Z sjg
Enable staging of files to a stage tree.
This can be best thought of as auto-install to
.Va DESTDIR
@@ -1173,13 +1201,13 @@ is set explicitly)
is set explicitly)
.El
.It Va WITH_STAGING_MAN
-.\" $FreeBSD$
+.\" from FreeBSD: head/tools/build/options/WITH_STAGING_MAN 284708 2015-06-22 20:21:57Z sjg
Enable staging of MAN pages to stage tree.
.It Va WITH_STAGING_PROG
-.\" $FreeBSD$
+.\" from FreeBSD: head/tools/build/options/WITH_STAGING_PROG 284708 2015-06-22 20:21:57Z sjg
Enable staging of PROGs to stage tree.
.It Va WITH_STALE_STAGED
-.\" $FreeBSD$
+.\" from FreeBSD: head/tools/build/options/WITH_STALE_STAGED 284708 2015-06-22 20:21:57Z sjg
Check staged files are not stale.
.It Va WITH_SVN
.\" from FreeBSD: head/tools/build/options/WITH_SVN 252561 2013-07-03 12:36:47Z zeising
@@ -1206,7 +1234,7 @@ Set to not build
.Xr sysinstall 8
and related programs.
.It Va WITH_SYSROOT
-.\" $FreeBSD$
+.\" from FreeBSD: head/tools/build/options/WITH_SYSROOT 284708 2015-06-22 20:21:57Z sjg
Enable use of sysroot during build.
Depends on
.Va WITH_META_MODE .
@@ -1246,6 +1274,8 @@ When set, it also enforces the following options:
.Pp
.Bl -item -compact
.It
+.Va WITHOUT_DTRACE_TESTS
+.It
.Va WITHOUT_TESTS_SUPPORT
.El
.It Va WITHOUT_TESTS_SUPPORT
diff --git a/share/man/man9/CTASSERT.9 b/share/man/man9/CTASSERT.9
index 6211c2e..39f25d6 100644
--- a/share/man/man9/CTASSERT.9
+++ b/share/man/man9/CTASSERT.9
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 5, 2008
+.Dd August 1, 2015
.Dt CTASSERT 9
.Os
.Sh NAME
@@ -39,6 +39,15 @@
.Sh DESCRIPTION
The
.Fn CTASSERT
+macro is deprecated and the C11 standard
+.Fn _Static_assert
+should be used instead.
+The header
+.Fa sys/cdefs.h
+should be included to provide compatibility for pre-C11 compilers.
+.Pp
+The
+.Fn CTASSERT
macro evaluates
.Fa expression
at compile time and causes a compiler error if it is false.
@@ -48,14 +57,6 @@ The
macro is useful for asserting the size or alignment of important
data structures and variables during compilation, which would
otherwise cause the code to fail at run time.
-.Sh IMPLEMENTATION NOTES
-The
-.Fn CTASSERT
-macro should not be used in a header file.
-It is implemented using a dummy typedef, with a name (based on line number)
-that may conflict with a
-.Fn CTASSERT
-in a source file including that header.
.Sh EXAMPLES
Assert that the size of the
.Vt uuid
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index 695fa23..521a710 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -223,6 +223,7 @@ MAN= accept_filter.9 \
pmap_pinit.9 \
pmap_protect.9 \
pmap_qenter.9 \
+ pmap_quick_enter_page.9 \
pmap_release.9 \
pmap_remove.9 \
pmap_resident_count.9 \
@@ -1265,6 +1266,7 @@ MLINKS+=pmap_is_modified.9 pmap_ts_referenced.9
MLINKS+=pmap_pinit.9 pmap_pinit0.9 \
pmap_pinit.9 pmap_pinit2.9
MLINKS+=pmap_qenter.9 pmap_qremove.9
+MLINKS+=pmap_quick_enter_page.9 pmap_quick_remove_page.9
MLINKS+=pmap_remove.9 pmap_remove_all.9 \
pmap_remove.9 pmap_remove_pages.9
MLINKS+=pmap_resident_count.9 pmap_wired_count.9
diff --git a/share/man/man9/pmap.9 b/share/man/man9/pmap.9
index 5d31780..f7edc33 100644
--- a/share/man/man9/pmap.9
+++ b/share/man/man9/pmap.9
@@ -111,6 +111,8 @@ operation.
.Xr pmap_protect 9 ,
.Xr pmap_qenter 9 ,
.Xr pmap_qremove 9 ,
+.Xr pmap_quick_enter_page 9 ,
+.Xr pmap_quick_remove_page 9 ,
.Xr pmap_release 9 ,
.Xr pmap_remove 9 ,
.Xr pmap_remove_all 9 ,
diff --git a/share/man/man9/pmap_quick_enter_page.9 b/share/man/man9/pmap_quick_enter_page.9
new file mode 100644
index 0000000..2089dd9
--- /dev/null
+++ b/share/man/man9/pmap_quick_enter_page.9
@@ -0,0 +1,103 @@
+.\"
+.\" Copyright (c) 2015 Jason A. Harmening <jah@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.
+.\" 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$
+.\"
+.Dd August 6, 2015
+.Dt PMAP_QUICK_ENTER_PAGE 9
+.Os
+.Sh NAME
+.Nm pmap_quick_enter_page ,
+.Nm pmap_quick_remove_page
+.Nd manage fast, single-page kernel address space mappings
+.Sh SYNOPSIS
+.In sys/param.h
+.In vm/vm.h
+.In vm/pmap.h
+.Ft vm_offset_t
+.Fn pmap_quick_enter_page "vm_page_t m"
+.Ft void
+.Fn pmap_quick_remove_page "vm_offset_t kva"
+.Sh DESCRIPTION
+The
+.Fn pmap_quick_enter_page
+function accepts a single page
+.Fa m ,
+and enters this page into a preallocated address in kernel virtual
+address (KVA) space.
+This function is intended for temporary mappings that will only
+be used for a very short period, for example a copy operation on
+the page contents.
+.Pp
+The
+.Fn pmap_quick_remove_page
+function removes a mapping previously created by
+.Fn pmap_quick_enter_page
+at
+.Fa kva ,
+making the KVA frame used by
+.Fn pmap_quick_enter_page
+available for reuse.
+.Pp
+On many architectures,
+.Fn pmap_quick_enter_page
+uses a per-CPU pageframe.
+In those cases, it must disable preemption on the local CPU.
+The corresponding call to
+.Fn pmap_quick_remove_page
+then re-enables preemption.
+It is therefore not safe for machine-independent code to sleep
+or perform locking operations while holding these mappings.
+Current implementations only guarantee the availability of a single
+page for the calling thread, so calls to
+.Fn pmap_quick_enter_page
+must not be nested.
+.Pp
+.Fn pmap_quick_enter_page
+and
+.Fn pmap_quick_remove_page
+do not sleep, and
+.Fn pmap_quick_enter_page
+always returns a valid address.
+It is safe to use these functions under all types of locks except spin mutexes.
+It is also safe to use them in all thread contexts except primary interrupt
+context.
+.Pp
+The page
+.Em must
+not be swapped or otherwise reused while the mapping is active.
+It must be either wired or held, or it must belong to an unmanaged
+region such as I/O device memory.
+.Sh RETURN VALUES
+The
+.Fn pmap_quick_enter_page
+function returns the kernel virtual address
+that is mapped to the page
+.Fa m .
+.Sh SEE ALSO
+.Xr pmap 9
+.Sh AUTHORS
+This manual page was written by
+.An Jason A Harmening Aq Mt jah@FreeBSD.org .
diff --git a/share/man/man9/sysctl.9 b/share/man/man9/sysctl.9
index cdf0592..51ab5d7 100644
--- a/share/man/man9/sysctl.9
+++ b/share/man/man9/sysctl.9
@@ -318,35 +318,33 @@ which specifies the format of the OID in a symbolic way.
This format is used as a hint by
.Xr sysctl 8
to apply proper data formatting for display purposes.
-Currently used format names are:
-.Dq N
-for node,
-.Dq A
-for
-.Li "char *" ,
-.Dq I
-for
-.Li "int" ,
-.Dq IU
-for
-.Li "unsigned int" ,
-.Dq L
-for
-.Li "long" ,
-.Dq LU
-for
-.Li "unsigned long" ,
-.Dq Q
-for
-.Li "quad_t" ,
-.Dq QU
-for
+.Pp
+Current formats:
+.Bl -tag -width "S,TYPE" -compact -offset indent
+.It Cm N
+node
+.It Cm A
+.Li "char *"
+.It Cm I
+.Li "int"
+.It Cm IK Ns Op Ar n
+temperature in Kelvin, multiplied by an optional single digit
+power of ten scaling factor: 1 (default) gives deciKelvin, 0 gives Kelvin, 3
+gives milliKelvin
+.It Cm IU
+.Li "unsigned int"
+.It Cm L
+.Li "long"
+.It Cm LU
+.Li "unsigned long"
+.It Cm Q
+.Li "quad_t"
+.It Cm QU
.Li "u_quad_t"
-and
-.Dq S,TYPE
-for
+.It Cm "S,TYPE"
.Li "struct TYPE"
-structures.
+structures
+.El
.It Fa descr
A pointer to a textual description of the OID.
.El
diff --git a/share/misc/committers-ports.dot b/share/misc/committers-ports.dot
index b007609..aac0ade 100644
--- a/share/misc/committers-ports.dot
+++ b/share/misc/committers-ports.dot
@@ -128,6 +128,7 @@ johans [label="Johan Selst\njohans@FreeBSD.org\n2006/04/01"]
josef [label="Josef El-Rayes\njosef@FreeBSD.org\n2004/12/20"]
jpaetzel [label="Josh Paetzel\njpaetzel@FreeBSD.org\n2008/09/05"]
jsa [label="Joseph S. Atkinson\njsa@FreeBSD.org\n2010/07/15"]
+junovitch [label="Jason Unovitch\njunovitch@FreeBSD.org\n2015/07/27"]
jylefort [label="Jean-Yves Lefort\njylefort@FreeBSD.org\n2005/04/12"]
kami [label="Dominic Fandrey\nkami@FreeBSD.org\n2014/09/09"]
kevlo [label="Kevin Lo\nkevlo@FreeBSD.org\n2003/02/21"]
@@ -315,6 +316,7 @@ db -> tj
decke -> sperber
+delphij -> junovitch
delphij -> nemoliu
delphij -> rafan
@@ -347,6 +349,8 @@ erwin -> lbr
erwin -> lth
erwin -> simon
+feld -> junovitch
+
fjoe -> danfe
fjoe -> flo
fjoe -> krion
@@ -508,6 +512,7 @@ pawel -> nemysis
pgj -> ashish
pgj -> jacula
+pgollucci -> junovitch
pgollucci -> sunpoet
pgollucci -> swills
diff --git a/share/misc/committers-src.dot b/share/misc/committers-src.dot
index cdf8bab..53628b3 100644
--- a/share/misc/committers-src.dot
+++ b/share/misc/committers-src.dot
@@ -106,6 +106,7 @@ adrian [label="Adrian Chadd\nadrian@FreeBSD.org\n2000/07/03"]
ae [label="Andrey V. Elsukov\nae@FreeBSD.org\n2010/06/03"]
akiyama [label="Shunsuke Akiyama\nakiyama@FreeBSD.org\n2000/06/19"]
alc [label="Alan Cox\nalc@FreeBSD.org\n1999/02/23"]
+allanjude [label="Allan Jude\nallanjude@FreeBSD.org\n2015/07/30"]
ambrisko [label="Doug Ambrisko\nambrisko@FreeBSD.org\n2001/12/19"]
anchie [label="Ana Kukec\nanchie@FreeBSD.org\n2010/04/14"]
andre [label="Andre Oppermann\nandre@FreeBSD.org\n2003/11/12"]
@@ -346,6 +347,7 @@ avg -> art
avg -> pluknet
avg -> smh
+bapt -> allanjude
bapt -> bdrewery
benno -> grehan
@@ -572,6 +574,7 @@ kib -> zont
kmacy -> lstewart
+marcel -> allanjude
marcel -> art
marcel -> arun
marcel -> marius
diff --git a/share/mk/bsd.cpu.mk b/share/mk/bsd.cpu.mk
index 6ba87cc..7d776bc 100644
--- a/share/mk/bsd.cpu.mk
+++ b/share/mk/bsd.cpu.mk
@@ -282,6 +282,27 @@ _CPUCFLAGS += -mfloat-abi=softfp
CFLAGS += ${_CPUCFLAGS}
.endif
+#
+# Prohibit the compiler from emitting SIMD instructions.
+# These flags are added to CFLAGS in areas where the extra context-switch
+# cost outweighs the advantages of SIMD instructions.
+#
+# gcc:
+# Setting -mno-mmx implies -mno-3dnow
+# Setting -mno-sse implies -mno-sse2, -mno-sse3, -mno-ssse3 and -mfpmath=387
+#
+# clang:
+# Setting -mno-mmx implies -mno-3dnow and -mno-3dnowa
+# Setting -mno-sse implies -mno-sse2, -mno-sse3, -mno-ssse3, -mno-sse41 and
+# -mno-sse42
+# (-mfpmath= is not supported)
+#
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
+CFLAGS_NO_SIMD.clang= -mno-avx
+CFLAGS_NO_SIMD= -mno-mmx -mno-sse
+.endif
+CFLAGS_NO_SIMD += ${CFLAGS_NO_SIMD.${COMPILER_TYPE}}
+
# Add in any architecture-specific CFLAGS.
# These come from make.conf or the command line or the environment.
CFLAGS += ${CFLAGS.${MACHINE_ARCH}}
diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk
index 3331f6f..ba8f48f 100644
--- a/share/mk/src.opts.mk
+++ b/share/mk/src.opts.mk
@@ -178,6 +178,7 @@ __DEFAULT_YES_OPTIONS = \
__DEFAULT_NO_OPTIONS = \
BSD_GREP \
CLANG_EXTRAS \
+ DTRACE_TESTS \
EISA \
HESIOD \
LLDB \
@@ -214,15 +215,11 @@ __TT=${MACHINE}
# If the compiler is not C++11 capable, disable clang and use gcc instead.
__DEFAULT_YES_OPTIONS+=GCC GCC_BOOTSTRAP GNUCXX
__DEFAULT_NO_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_FULL CLANG_IS_CC
-.elif ${__T} == "aarch64" || ${__T} == "amd64" || ${__T} == "i386"
-# On x86 and arm64, clang is enabled, and will be installed as the default cc.
+.elif ${__T} == "aarch64" || ${__T} == "amd64" || ${__TT} == "arm" || \
+ ${__T} == "i386"
+# On x86 and arm, clang is enabled, and will be installed as the default cc.
__DEFAULT_YES_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_FULL CLANG_IS_CC
__DEFAULT_NO_OPTIONS+=GCC GCC_BOOTSTRAP GNUCXX
-.elif ${__TT} == "arm"
-# On arm, clang is enabled, and it is installed as the default cc, but
-# since gcc is unable to build the full clang, disable it by default.
-__DEFAULT_YES_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_IS_CC
-__DEFAULT_NO_OPTIONS+=CLANG_FULL GCC GCC_BOOTSTRAP GNUCXX
.elif ${__T:Mpowerpc*}
# On powerpc, clang is enabled, but gcc is installed as the default cc.
__DEFAULT_YES_OPTIONS+=CLANG CLANG_FULL GCC GCC_BOOTSTRAP GNUCXX
@@ -234,6 +231,9 @@ __DEFAULT_NO_OPTIONS+=CLANG CLANG_BOOTSTRAP CLANG_FULL CLANG_IS_CC
.endif
.if ${__T} == "aarch64"
BROKEN_OPTIONS+=BINUTILS BINUTILS_BOOTSTRAP GCC GCC_BOOTSTRAP GDB
+__DEFAULT_YES_OPTIONS+=ELFCOPY_AS_OBJCOPY
+.else
+__DEFAULT_NO_OPTIONS+=ELFCOPY_AS_OBJCOPY
.endif
# LLVM lacks support for FreeBSD 64-bit atomic operations for ARMv4/ARMv5
.if ${__T} == "arm" || ${__T} == "armeb"
@@ -319,6 +319,10 @@ MK_KERBEROS:= no
MK_AUTHPF:= no
.endif
+.if ${MK_TESTS} == "no"
+MK_DTRACE_TESTS:= no
+.endif
+
.if ${MK_TEXTPROC} == "no"
MK_GROFF:= no
.endif
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index e91e6d5..a2ca9e2 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -252,6 +252,7 @@ init_secondary(void)
wrmsr(MSR_FSBASE, 0); /* User value */
wrmsr(MSR_GSBASE, (u_int64_t)pc);
wrmsr(MSR_KGSBASE, (u_int64_t)pc); /* XXX User value while we're in the kernel */
+ intel_fix_cpuid();
lidt(&r_idt);
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 6a3de60..780d0e3 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -6940,6 +6940,18 @@ pmap_unmap_io_transient(vm_page_t page[], vm_offset_t vaddr[], int count,
}
}
+vm_offset_t
+pmap_quick_enter_page(vm_page_t m)
+{
+
+ return (PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)));
+}
+
+void
+pmap_quick_remove_page(vm_offset_t addr)
+{
+}
+
#include "opt_ddb.h"
#ifdef DDB
#include <ddb/ddb.h>
diff --git a/sys/amd64/cloudabi64/cloudabi64_sysvec.c b/sys/amd64/cloudabi64/cloudabi64_sysvec.c
index 428d9f7..36edfc5 100644
--- a/sys/amd64/cloudabi64/cloudabi64_sysvec.c
+++ b/sys/amd64/cloudabi64/cloudabi64_sysvec.c
@@ -73,10 +73,20 @@ cloudabi64_fixup(register_t **stack_base, struct image_params *imgp)
{
char canarybuf[64];
Elf64_Auxargs *args;
+ struct thread *td;
void *argdata, *canary;
size_t argdatalen;
int error;
+ /*
+ * CloudABI executables do not store the FreeBSD OS release
+ * number in their header. Set the OS release number to the
+ * latest version of FreeBSD, so that system calls behave as if
+ * called natively.
+ */
+ td = curthread;
+ td->td_proc->p_osrel = __FreeBSD_version;
+
/* Store canary for stack smashing protection. */
argdata = *stack_base;
arc4rand(canarybuf, sizeof(canarybuf), 0);
@@ -108,7 +118,7 @@ cloudabi64_fixup(register_t **stack_base, struct image_params *imgp)
VAL(CLOUDABI_AT_PAGESZ, args->pagesz),
PTR(CLOUDABI_AT_PHDR, args->phdr),
VAL(CLOUDABI_AT_PHNUM, args->phnum),
- VAL(CLOUDABI_AT_TID, curthread->td_tid),
+ VAL(CLOUDABI_AT_TID, td->td_tid),
#undef VAL
#undef PTR
{ .a_type = CLOUDABI_AT_NULL },
@@ -214,7 +224,7 @@ static struct sysentvec cloudabi64_elf_sysvec = {
.sv_usrstack = USRSTACK,
.sv_stackprot = VM_PROT_READ | VM_PROT_WRITE,
.sv_copyout_strings = cloudabi64_copyout_strings,
- .sv_flags = SV_ABI_CLOUDABI,
+ .sv_flags = SV_ABI_CLOUDABI | SV_CAPSICUM,
.sv_set_syscall_retval = cloudabi64_set_syscall_retval,
.sv_fetch_syscall_args = cloudabi64_fetch_syscall_args,
.sv_syscallnames = cloudabi64_syscallnames,
diff --git a/sys/amd64/include/atomic.h b/sys/amd64/include/atomic.h
index 016aa70..33d79b2 100644
--- a/sys/amd64/include/atomic.h
+++ b/sys/amd64/include/atomic.h
@@ -269,13 +269,13 @@ atomic_testandset_long(volatile u_long *p, u_int v)
* IA32 memory model, a simple store guarantees release semantics.
*
* However, a load may pass a store if they are performed on distinct
- * addresses, so for atomic_load_acq we introduce a Store/Load barrier
- * before the load in SMP kernels. We use "lock addl $0,mem", as
- * recommended by the AMD Software Optimization Guide, and not mfence.
- * In the kernel, we use a private per-cpu cache line as the target
- * for the locked addition, to avoid introducing false data
- * dependencies. In userspace, a word in the red zone on the stack
- * (-8(%rsp)) is utilized.
+ * addresses, so we need a Store/Load barrier for sequentially
+ * consistent fences in SMP kernels. We use "lock addl $0,mem" for a
+ * Store/Load barrier, as recommended by the AMD Software Optimization
+ * Guide, and not mfence. To avoid false data dependencies, we use a
+ * special address for "mem". In the kernel, we use a private per-cpu
+ * cache line. In user space, we use a word in the stack's red zone
+ * (-8(%rsp)).
*
* For UP kernels, however, the memory of the single processor is
* always consistent, so we only need to stop the compiler from
@@ -319,22 +319,12 @@ __storeload_barrier(void)
}
#endif /* _KERNEL*/
-/*
- * C11-standard acq/rel semantics only apply when the variable in the
- * call is the same for acq as it is for rel. However, our previous
- * (x86) implementations provided much stronger ordering than required
- * (essentially what is called seq_cst order in C11). This
- * implementation provides the historical strong ordering since some
- * callers depend on it.
- */
-
#define ATOMIC_LOAD(TYPE) \
static __inline u_##TYPE \
atomic_load_acq_##TYPE(volatile u_##TYPE *p) \
{ \
u_##TYPE res; \
\
- __storeload_barrier(); \
res = *p; \
__compiler_membar(); \
return (res); \
diff --git a/sys/amd64/include/in_cksum.h b/sys/amd64/include/in_cksum.h
index 156035e..d76b48a 100644
--- a/sys/amd64/include/in_cksum.h
+++ b/sys/amd64/include/in_cksum.h
@@ -10,7 +10,7 @@
* 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index 954df3e..0657dee 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -114,6 +114,7 @@ void dump_drop_page(vm_paddr_t);
void identify_cpu(void);
void initializecpu(void);
void initializecpucache(void);
+bool intel_fix_cpuid(void);
void fillw(int /*u_short*/ pat, void *base, size_t cnt);
void fpstate_drop(struct thread *td);
int is_physical_memory(vm_paddr_t addr);
diff --git a/sys/amd64/include/xen/xenvar.h b/sys/amd64/include/xen/xenvar.h
deleted file mode 100644
index 110a351..0000000
--- a/sys/amd64/include/xen/xenvar.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*-
- * Copyright (c) 2008 Kip Macy
- * 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$
- */
-#ifndef XENVAR_H_
-#define XENVAR_H_
-#define XBOOTUP 0x1
-#define XPMAP 0x2
-extern int xendebug_flags;
-#ifndef NOXENDEBUG
-#define XENPRINTF printk
-#else
-#define XENPRINTF printf
-#endif
-#include <xen/features.h>
-
-#if 0
-#define TRACE_ENTER XENPRINTF("(file=%s, line=%d) entered %s\n", __FILE__, __LINE__, __FUNCTION__)
-#define TRACE_EXIT XENPRINTF("(file=%s, line=%d) exiting %s\n", __FILE__, __LINE__, __FUNCTION__)
-#define TRACE_DEBUG(argflags, _f, _a...) \
-if (xendebug_flags & argflags) XENPRINTF("(file=%s, line=%d) " _f "\n", __FILE__, __LINE__, ## _a);
-#else
-#define TRACE_ENTER
-#define TRACE_EXIT
-#define TRACE_DEBUG(argflags, _f, _a...)
-#endif
-
-#define vtomach(va) pmap_kextract((vm_offset_t) (va))
-
-void xpq_init(void);
-
-int xen_create_contiguous_region(vm_page_t pages, int npages);
-
-void xen_destroy_contiguous_region(void * addr, int npages);
-
-#endif
diff --git a/sys/arm/arm/pmap-v6-new.c b/sys/arm/arm/pmap-v6-new.c
index 13a97de..b18648f 100644
--- a/sys/arm/arm/pmap-v6-new.c
+++ b/sys/arm/arm/pmap-v6-new.c
@@ -162,7 +162,6 @@ __FBSDID("$FreeBSD$");
static void pmap_zero_page_check(vm_page_t m);
void pmap_debug(int level);
int pmap_pid_dump(int pid);
-void pmap_pvdump(vm_paddr_t pa);
#define PDEBUG(_lev_,_stat_) \
if (pmap_debug_level >= (_lev_)) \
@@ -1157,6 +1156,22 @@ pmap_bootstrap(vm_offset_t firstaddr)
virtual_end = vm_max_kernel_address;
}
+static void
+pmap_init_qpages(void)
+{
+ struct pcpu *pc;
+ int i;
+
+ CPU_FOREACH(i) {
+ pc = pcpu_find(i);
+ pc->pc_qmap_addr = kva_alloc(PAGE_SIZE);
+ if (pc->pc_qmap_addr == 0)
+ panic("pmap_init_qpages: unable to allocate KVA");
+ }
+}
+
+SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL);
+
/*
* The function can already be use in second initialization stage.
* As such, the function DOES NOT call pmap_growkernel() where PT2
@@ -5710,6 +5725,42 @@ pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
mtx_unlock(&sysmaps->lock);
}
+vm_offset_t
+pmap_quick_enter_page(vm_page_t m)
+{
+ pt2_entry_t *pte;
+ vm_offset_t qmap_addr;
+
+ critical_enter();
+
+ qmap_addr = PCPU_GET(qmap_addr);
+ pte = pt2map_entry(qmap_addr);
+
+ KASSERT(*pte == 0, ("pmap_quick_enter_page: PTE busy"));
+
+ pte2_store(pte, PTE2_KERN_NG(VM_PAGE_TO_PHYS(m),
+ PTE2_AP_KRW, pmap_page_get_memattr(m)));
+ tlb_flush_local(qmap_addr);
+
+ return (qmap_addr);
+}
+
+void
+pmap_quick_remove_page(vm_offset_t addr)
+{
+ pt2_entry_t *pte;
+ vm_offset_t qmap_addr;
+
+ qmap_addr = PCPU_GET(qmap_addr);
+ pte = pt2map_entry(qmap_addr);
+
+ KASSERT(addr == qmap_addr, ("pmap_quick_remove_page: invalid address"));
+ KASSERT(*pte != 0, ("pmap_quick_remove_page: PTE not in use"));
+
+ pte2_clear(pte);
+ critical_exit();
+}
+
/*
* Copy the range specified by src_addr/len
* from the source map to the range dst_addr/len
@@ -6345,62 +6396,6 @@ pmap_pid_dump(int pid)
return (npte2);
}
-/*
- * Print address space of pmap.
- */
-static void
-pads(pmap_t pmap)
-{
- int i, j;
- vm_paddr_t va;
- pt1_entry_t pte1;
- pt2_entry_t *pte2p, pte2;
-
- if (pmap == kernel_pmap)
- return;
- for (i = 0; i < NPTE1_IN_PT1; i++) {
- pte1 = pte1_load(&pmap->pm_pt1[i]);
- if (pte1_is_section(pte1)) {
- /*
- * QQQ: Do something here!
- */
- } else if (pte1_is_link(pte1)) {
- for (j = 0; j < NPTE2_IN_PT2; j++) {
- va = (i << PTE1_SHIFT) + (j << PAGE_SHIFT);
- if (pmap == kernel_pmap && va < KERNBASE)
- continue;
- if (pmap != kernel_pmap && va >= KERNBASE &&
- (va < UPT2V_MIN_ADDRESS ||
- va >= UPT2V_MAX_ADDRESS))
- continue;
-
- pte2p = pmap_pte2(pmap, va);
- pte2 = pte2_load(pte2p);
- pmap_pte2_release(pte2p);
- if (!pte2_is_valid(pte2))
- continue;
- printf("%x:%x ", va, pte2);
- }
- }
- }
-}
-
-void
-pmap_pvdump(vm_paddr_t pa)
-{
- pv_entry_t pv;
- pmap_t pmap;
- vm_page_t m;
-
- printf("pa %x", pa);
- m = PHYS_TO_VM_PAGE(pa);
- TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
- pmap = PV_PMAP(pv);
- printf(" -> pmap %p, va %x", (void *)pmap, pv->pv_va);
- pads(pmap);
- }
- printf(" ");
-}
#endif
#ifdef DDB
diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c
index a9421aa..50172f2 100644
--- a/sys/arm/arm/pmap-v6.c
+++ b/sys/arm/arm/pmap-v6.c
@@ -1979,6 +1979,7 @@ pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt)
pmap_set_pcb_pagedir(kernel_pmap, thread0.td_pcb);
}
+
/***************************************************
* Pmap allocation/deallocation routines.
***************************************************/
@@ -2306,6 +2307,31 @@ pmap_remove_pages(pmap_t pmap)
PMAP_UNLOCK(pmap);
}
+static void
+pmap_init_qpages(void)
+{
+ struct pcpu *pc;
+ struct l2_bucket *l2b;
+ int i;
+
+ CPU_FOREACH(i) {
+ pc = pcpu_find(i);
+ pc->pc_qmap_addr = kva_alloc(PAGE_SIZE);
+ if (pc->pc_qmap_addr == 0)
+ panic("pmap_init_qpages: unable to allocate KVA");
+
+ l2b = pmap_get_l2_bucket(pmap_kernel(), pc->pc_qmap_addr);
+ if (l2b == NULL)
+ l2b = pmap_grow_l2_bucket(pmap_kernel(),
+ pc->pc_qmap_addr);
+ if (l2b == NULL)
+ panic("pmap_alloc_specials: no l2b for 0x%x",
+ pc->pc_qmap_addr);
+ pc->pc_qmap_pte = &l2b->l2b_kva[l2pte_index(pc->pc_qmap_addr)];
+ }
+}
+
+SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL);
/***************************************************
* Low level mapping routines.....
@@ -4678,6 +4704,49 @@ pmap_copy_page(vm_page_t src, vm_page_t dst)
pmap_copy_page_generic(VM_PAGE_TO_PHYS(src), VM_PAGE_TO_PHYS(dst));
}
+vm_offset_t
+pmap_quick_enter_page(vm_page_t m)
+{
+ pt_entry_t *qmap_pte;
+ vm_offset_t qmap_addr;
+
+ critical_enter();
+
+ qmap_addr = PCPU_GET(qmap_addr);
+ qmap_pte = PCPU_GET(qmap_pte);
+
+ KASSERT(*qmap_pte == 0, ("pmap_quick_enter_page: PTE busy"));
+
+ *qmap_pte = L2_S_PROTO | VM_PAGE_TO_PHYS(m) | L2_S_REF;
+ if (m->md.pv_memattr != VM_MEMATTR_UNCACHEABLE)
+ *qmap_pte |= pte_l2_s_cache_mode;
+ pmap_set_prot(qmap_pte, VM_PROT_READ | VM_PROT_WRITE, 0);
+ PTE_SYNC(qmap_pte);
+ cpu_tlb_flushD_SE(qmap_addr);
+ cpu_cpwait();
+
+ return (qmap_addr);
+}
+
+void
+pmap_quick_remove_page(vm_offset_t addr)
+{
+ pt_entry_t *qmap_pte;
+
+ qmap_pte = PCPU_GET(qmap_pte);
+
+ KASSERT(addr == PCPU_GET(qmap_addr),
+ ("pmap_quick_remove_page: invalid address"));
+ KASSERT(*qmap_pte != 0,
+ ("pmap_quick_remove_page: PTE not in use"));
+
+ cpu_idcache_wbinv_range(addr, PAGE_SIZE);
+ pmap_l2cache_wbinv_range(addr, *qmap_pte & L2_S_FRAME, PAGE_SIZE);
+ *qmap_pte = 0;
+ PTE_SYNC(qmap_pte);
+ critical_exit();
+}
+
/*
* this routine returns true if a physical page resides
* in the given pmap.
diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c
index dfd5bcb..daaa0ee 100644
--- a/sys/arm/arm/pmap.c
+++ b/sys/arm/arm/pmap.c
@@ -227,8 +227,8 @@ vm_offset_t vm_max_kernel_address;
struct pmap kernel_pmap_store;
static pt_entry_t *csrc_pte, *cdst_pte;
-static vm_offset_t csrcp, cdstp;
-static struct mtx cmtx;
+static vm_offset_t csrcp, cdstp, qmap_addr;
+static struct mtx cmtx, qmap_mtx;
static void pmap_init_l1(struct l1_ttable *, pd_entry_t *);
/*
@@ -2155,6 +2155,7 @@ pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt)
pd_entry_t pde;
pd_entry_t *kernel_l1pt = (pd_entry_t *)l1pt->pv_va;
pt_entry_t *ptep;
+ pt_entry_t *qmap_pte;
vm_paddr_t pa;
vm_offset_t va;
vm_size_t size;
@@ -2276,6 +2277,8 @@ pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt)
pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)csrc_pte);
pmap_alloc_specials(&virtual_avail, 1, &cdstp, &cdst_pte);
pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)cdst_pte);
+ pmap_alloc_specials(&virtual_avail, 1, &qmap_addr, &qmap_pte);
+ pmap_set_pt_cache_mode(kernel_l1pt, (vm_offset_t)qmap_pte);
size = ((vm_max_kernel_address - pmap_curmaxkvaddr) + L1_S_OFFSET) /
L1_S_SIZE;
pmap_alloc_specials(&virtual_avail,
@@ -2302,6 +2305,7 @@ pmap_bootstrap(vm_offset_t firstaddr, struct pv_addr *l1pt)
virtual_end = vm_max_kernel_address;
kernel_vm_end = pmap_curmaxkvaddr;
mtx_init(&cmtx, "TMP mappings mtx", NULL, MTX_DEF);
+ mtx_init(&qmap_mtx, "quick mapping mtx", NULL, MTX_DEF);
pmap_set_pcb_pagedir(kernel_pmap, thread0.td_pcb);
}
@@ -4343,6 +4347,34 @@ pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
}
}
+vm_offset_t
+pmap_quick_enter_page(vm_page_t m)
+{
+ /*
+ * Don't bother with a PCPU pageframe, since we don't support
+ * SMP for anything pre-armv7. Use pmap_kenter() to ensure
+ * caching is handled correctly for multiple mappings of the
+ * same physical page.
+ */
+
+ mtx_assert(&qmap_mtx, MA_NOTOWNED);
+ mtx_lock(&qmap_mtx);
+
+ pmap_kenter(qmap_addr, VM_PAGE_TO_PHYS(m));
+
+ return (qmap_addr);
+}
+
+void
+pmap_quick_remove_page(vm_offset_t addr)
+{
+ KASSERT(addr == qmap_addr,
+ ("pmap_quick_remove_page: invalid address"));
+ mtx_assert(&qmap_mtx, MA_OWNED);
+ pmap_kremove(addr);
+ mtx_unlock(&qmap_mtx);
+}
+
/*
* this routine returns true if a physical page resides
* in the given pmap.
diff --git a/sys/arm/conf/BEAGLEBONE b/sys/arm/conf/BEAGLEBONE
index bee9427..a0ca1b6 100644
--- a/sys/arm/conf/BEAGLEBONE
+++ b/sys/arm/conf/BEAGLEBONE
@@ -32,7 +32,6 @@ makeoptions MODULES_EXTRA="dtb/am335x"
options KDTRACE_HOOKS # Kernel DTrace hooks
options DDB_CTF # all architectures - kernel ELF linker loads CTF data
makeoptions WITH_CTF=1
-makeoptions MODULES_EXTRA+="opensolaris dtrace dtrace/profile dtrace/fbt"
options HZ=100
options SCHED_4BSD # 4BSD scheduler
diff --git a/sys/arm/include/float.h b/sys/arm/include/float.h
index 644b5ff..358a611 100644
--- a/sys/arm/include/float.h
+++ b/sys/arm/include/float.h
@@ -10,11 +10,7 @@
* 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 the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
diff --git a/sys/arm/include/pcpu.h b/sys/arm/include/pcpu.h
index 73400c5..d98d639 100644
--- a/sys/arm/include/pcpu.h
+++ b/sys/arm/include/pcpu.h
@@ -47,10 +47,14 @@ struct vmspace;
unsigned int pc_vfpmvfr0; \
unsigned int pc_vfpmvfr1; \
struct pmap *pc_curpmap; \
- char __pad[141]
+ vm_offset_t pc_qmap_addr; \
+ void *pc_qmap_pte; \
+ char __pad[133]
#else
#define PCPU_MD_FIELDS \
- char __pad[157]
+ vm_offset_t qmap_addr; \
+ void *pc_qmap_pte; \
+ char __pad[149]
#endif
#ifdef _KERNEL
diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c
index 8e28adc..2818bab 100644
--- a/sys/arm/ti/ti_gpio.c
+++ b/sys/arm/ti/ti_gpio.c
@@ -573,7 +573,7 @@ ti_gpio_bank_init(device_t dev)
{
int pin;
struct ti_gpio_softc *sc;
- uint32_t flags, reg_oe, rev;
+ uint32_t flags, reg_oe, reg_set, rev;
clk_ident_t clk;
sc = device_get_softc(dev);
@@ -607,12 +607,18 @@ ti_gpio_bank_init(device_t dev)
/* Init OE register based on pads configuration. */
reg_oe = 0xffffffff;
+ reg_set = 0;
for (pin = 0; pin < PINS_PER_BANK; pin++) {
TI_GPIO_GET_FLAGS(dev, pin, &flags);
- if (flags & GPIO_PIN_OUTPUT)
+ if (flags & GPIO_PIN_OUTPUT) {
reg_oe &= ~(1UL << pin);
+ if (flags & GPIO_PIN_PULLUP)
+ reg_set |= (1UL << pin);
+ }
}
ti_gpio_write_4(sc, TI_GPIO_OE, reg_oe);
+ if (reg_set)
+ ti_gpio_write_4(sc, TI_GPIO_SETDATAOUT, reg_set);
return (0);
}
@@ -843,14 +849,16 @@ static int
ti_gpio_activate_resource(device_t dev, device_t child, int type, int rid,
struct resource *res)
{
- int pin;
+ struct ti_gpio_mask_arg mask_arg;
if (type != SYS_RES_IRQ)
return (ENXIO);
/* Unmask the interrupt. */
- pin = rman_get_start(res);
- ti_gpio_unmask_irq((void *)(uintptr_t)pin);
+ mask_arg.pin = rman_get_start(res);
+ mask_arg.softc = device_get_softc(dev);
+
+ ti_gpio_unmask_irq((void *)&mask_arg);
return (0);
}
diff --git a/sys/arm64/arm64/elf_machdep.c b/sys/arm64/arm64/elf_machdep.c
index 5702e7f..08a297b 100644
--- a/sys/arm64/arm64/elf_machdep.c
+++ b/sys/arm64/arm64/elf_machdep.c
@@ -137,7 +137,7 @@ elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
int type, elf_lookup_fn lookup __unused)
{
- panic("elf_reloc_local");
+ panic("ARM64TODO: elf_reloc_local");
}
/* Process one elf relocation with addend. */
@@ -146,7 +146,7 @@ elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
elf_lookup_fn lookup)
{
- panic("elf_reloc");
+ panic("ARM64TODO: elf_reloc");
}
int
diff --git a/sys/arm64/arm64/gic_v3.c b/sys/arm64/arm64/gic_v3.c
index 5dc2c0b..022a6c2 100644
--- a/sys/arm64/arm64/gic_v3.c
+++ b/sys/arm64/arm64/gic_v3.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <machine/bus.h>
+#include <machine/cpu.h>
#include <machine/intr.h>
#include "pic_if.h"
@@ -230,7 +231,22 @@ gic_v3_dispatch(device_t dev, struct trapframe *frame)
uint64_t active_irq;
while (1) {
- active_irq = gic_icc_read(IAR1);
+ if (CPU_MATCH_ERRATA_CAVIUM_THUNDER_1_1) {
+ /*
+ * Hardware: Cavium ThunderX
+ * Chip revision: Pass 1.0 (early version)
+ * Pass 1.1 (production)
+ * ERRATUM: 22978, 23154
+ */
+ __asm __volatile(
+ "nop;nop;nop;nop;nop;nop;nop;nop; \n"
+ "mrs %0, ICC_IAR1_EL1 \n"
+ "nop;nop;nop;nop; \n"
+ "dsb sy \n"
+ : "=&r" (active_irq));
+ } else {
+ active_irq = gic_icc_read(IAR1);
+ }
if (__predict_false(active_irq == ICC_IAR1_EL1_SPUR))
break;
diff --git a/sys/arm64/arm64/gic_v3_its.c b/sys/arm64/arm64/gic_v3_its.c
index 274a6aa..fb4b868 100644
--- a/sys/arm64/arm64/gic_v3_its.c
+++ b/sys/arm64/arm64/gic_v3_its.c
@@ -101,6 +101,8 @@ static void its_cmd_mapi(struct gic_v3_its_softc *, struct its_dev *, uint32_t);
static void its_cmd_inv(struct gic_v3_its_softc *, struct its_dev *, uint32_t);
static void its_cmd_invall(struct gic_v3_its_softc *, struct its_col *);
+static uint32_t its_get_devbits(device_t);
+
static void lpi_init_conftable(struct gic_v3_its_softc *);
static void lpi_bitmap_init(struct gic_v3_its_softc *);
static void lpi_init_cpu(struct gic_v3_its_softc *);
@@ -142,13 +144,19 @@ const char *its_ptab_type[] = {
*/
/* Cavium ThunderX PCI devid acquire function */
+static uint32_t its_get_devbits_thunder(device_t);
static uint32_t its_get_devid_thunder(device_t);
static const struct its_quirks its_quirks[] = {
{
+ /*
+ * Hardware: Cavium ThunderX
+ * Chip revision: Pass 1.0, Pass 1.1
+ */
.cpuid = CPU_ID_RAW(CPU_IMPL_CAVIUM, CPU_PART_THUNDER, 0, 0),
.cpuid_mask = CPU_IMPL_MASK | CPU_PART_MASK,
.devid_func = its_get_devid_thunder,
+ .devbits_func = its_get_devbits_thunder,
},
};
@@ -299,7 +307,6 @@ its_alloc_tables(struct gic_v3_its_softc *sc)
{
uint64_t gits_baser, gits_tmp;
uint64_t type, esize, cache, share, psz;
- uint64_t gits_typer;
size_t page_size, npages, nitspages, nidents, tn;
size_t its_tbl_size;
vm_offset_t ptab_vaddr;
@@ -308,9 +315,6 @@ its_alloc_tables(struct gic_v3_its_softc *sc)
page_size = PAGE_SIZE_64K;
- /* Read features first */
- gits_typer = gic_its_read(sc, 8, GITS_TYPER);
-
for (tn = 0; tn < GITS_BASER_NUM; tn++) {
gits_baser = gic_its_read(sc, 8, GITS_BASER(tn));
type = GITS_BASER_TYPE(gits_baser);
@@ -324,7 +328,7 @@ its_alloc_tables(struct gic_v3_its_softc *sc)
case GITS_BASER_TYPE_RES7:
continue;
case GITS_BASER_TYPE_DEV:
- nidents = (1 << GITS_TYPER_DEVB(gits_typer));
+ nidents = (1 << its_get_devbits(sc->dev));
its_tbl_size = esize * nidents;
its_tbl_size = roundup2(its_tbl_size, page_size);
npages = howmany(its_tbl_size, PAGE_SIZE);
@@ -1447,6 +1451,68 @@ its_get_devid_thunder(device_t pci_dev)
return (0);
}
+static uint32_t
+its_get_devbits_thunder(device_t dev)
+{
+ uint32_t devid_bits;
+
+ /*
+ * GITS_TYPER[17:13] of ThunderX reports that device IDs
+ * are to be 21 bits in length.
+ * The entry size of the ITS table can be read from GITS_BASERn[52:48]
+ * and on ThunderX is supposed to be 8 bytes in length (for device
+ * table). Finally the page size that is to be used by ITS to access
+ * this table will be set to 64KB.
+ *
+ * This gives 0x200000 entries of size 0x8 bytes covered by 256 pages
+ * each of which 64KB in size. The number of pages (minus 1) should
+ * then be written to GITS_BASERn[7:0]. In that case this value would
+ * be 0xFF but on ThunderX the maximum value that HW accepts is 0xFD.
+ *
+ * Set arbitrary number of device ID bits to 20 in order to limit
+ * the number of entries in ITS device table to 0x100000 and hence
+ * the table size to 8MB.
+ */
+ devid_bits = 20;
+ if (bootverbose) {
+ device_printf(dev,
+ "Limiting number of Device ID bits implemented to %d\n",
+ devid_bits);
+ }
+
+ return (devid_bits);
+}
+
+static __inline uint32_t
+its_get_devbits_default(device_t dev)
+{
+ uint64_t gits_typer;
+ struct gic_v3_its_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ gits_typer = gic_its_read(sc, 8, GITS_TYPER);
+
+ return (GITS_TYPER_DEVB(gits_typer));
+}
+
+static uint32_t
+its_get_devbits(device_t dev)
+{
+ const struct its_quirks *quirk;
+ size_t i;
+
+ for (i = 0; i < nitems(its_quirks); i++) {
+ quirk = &its_quirks[i];
+ if (CPU_MATCH_RAW(quirk->cpuid_mask, quirk->cpuid)) {
+ if (quirk->devbits_func != NULL)
+ return ((*quirk->devbits_func)(dev));
+ }
+ }
+
+ return (its_get_devbits_default(dev));
+}
+
static __inline uint32_t
its_get_devid_default(device_t pci_dev)
{
diff --git a/sys/arm64/arm64/gic_v3_var.h b/sys/arm64/arm64/gic_v3_var.h
index 1621c0c..8bfce9b 100644
--- a/sys/arm64/arm64/gic_v3_var.h
+++ b/sys/arm64/arm64/gic_v3_var.h
@@ -235,12 +235,14 @@ struct gic_v3_its_softc {
};
/* Stuff that is specific to the vendor's implementation */
+typedef uint32_t (*its_devbits_func_t)(device_t);
typedef uint32_t (*its_devid_func_t)(device_t);
struct its_quirks {
uint64_t cpuid;
uint64_t cpuid_mask;
its_devid_func_t devid_func;
+ its_devbits_func_t devbits_func;
};
extern devclass_t gic_v3_its_devclass;
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
index f67211f..d63ee7a 100644
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -180,7 +180,7 @@ fill_fpregs(struct thread *td, struct fpreg *regs)
* If we have just been running VFP instructions we will
* need to save the state to memcpy it below.
*/
- vfp_save_state(td);
+ vfp_save_state(td, pcb);
memcpy(regs->fp_q, pcb->pcb_vfp, sizeof(regs->fp_q));
regs->fp_cr = pcb->pcb_fpcr;
@@ -209,21 +209,21 @@ int
fill_dbregs(struct thread *td, struct dbreg *regs)
{
- panic("fill_dbregs");
+ panic("ARM64TODO: fill_dbregs");
}
int
set_dbregs(struct thread *td, struct dbreg *regs)
{
- panic("set_dbregs");
+ panic("ARM64TODO: set_dbregs");
}
int
ptrace_set_pc(struct thread *td, u_long addr)
{
- panic("ptrace_set_pc");
+ panic("ARM64TODO: ptrace_set_pc");
return (0);
}
@@ -314,7 +314,7 @@ get_fpcontext(struct thread *td, mcontext_t *mcp)
* If we have just been running VFP instructions we will
* need to save the state to memcpy it below.
*/
- vfp_save_state(td);
+ vfp_save_state(td, curpcb);
memcpy(mcp->mc_fpregs.fp_q, curpcb->pcb_vfp,
sizeof(mcp->mc_fpregs));
@@ -376,7 +376,11 @@ void
cpu_halt(void)
{
- panic("cpu_halt");
+ /* We should have shutdown by now, if not enter a low power sleep */
+ intr_disable();
+ while (1) {
+ __asm __volatile("wfi");
+ }
}
/*
@@ -387,7 +391,7 @@ void
cpu_flush_dcache(void *ptr, size_t len)
{
- /* TBD */
+ /* ARM64TODO TBD */
}
/* Get current clock frequency for the given CPU ID. */
@@ -395,7 +399,7 @@ int
cpu_est_clockrate(int cpu_id, uint64_t *rate)
{
- panic("cpu_est_clockrate");
+ panic("ARM64TODO: cpu_est_clockrate");
}
void
@@ -818,8 +822,13 @@ initarm(struct arm64_bootparams *abp)
/* Print the memory map */
mem_len = 0;
- for (i = 0; i < physmap_idx; i += 2)
+ for (i = 0; i < physmap_idx; i += 2) {
+ dump_avail[i] = physmap[i];
+ dump_avail[i + 1] = physmap[i + 1];
mem_len += physmap[i + 1] - physmap[i];
+ }
+ dump_avail[i] = 0;
+ dump_avail[i + 1] = 0;
/* Set the pcpu data, this is needed by pmap_bootstrap */
pcpup = &__pcpu[0];
diff --git a/sys/arm64/arm64/mem.c b/sys/arm64/arm64/mem.c
index 70c0f57..481ef884 100644
--- a/sys/arm64/arm64/mem.c
+++ b/sys/arm64/arm64/mem.c
@@ -33,15 +33,84 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/malloc.h>
#include <sys/memrange.h>
+#include <sys/uio.h>
#include <machine/memdev.h>
+#include <machine/vmparam.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_page.h>
struct mem_range_softc mem_range_softc;
int
memrw(struct cdev *dev, struct uio *uio, int flags)
{
+ struct iovec *iov;
+ struct vm_page m;
+ vm_page_t marr;
+ vm_offset_t off, v;
+ u_int cnt;
+ int error;
+
+ error = 0;
+
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("memrw");
+ continue;
+ }
+
+ v = uio->uio_offset;
+ off = v & PAGE_MASK;
+ cnt = ulmin(iov->iov_len, PAGE_SIZE - (u_int)off);
+ if (cnt == 0)
+ continue;
+
+ switch(dev2unit(dev)) {
+ case CDEV_MINOR_KMEM:
+ /* If the address is in the DMAP just copy it */
+ if (VIRT_IN_DMAP(v)) {
+ error = uiomove((void *)v, cnt, uio);
+ break;
+ }
+
+ if (!kernacc((void *)v, cnt, uio->uio_rw == UIO_READ ?
+ VM_PROT_READ : VM_PROT_WRITE)) {
+ error = EFAULT;
+ break;
+ }
+
+ /* Get the physical address to read */
+ v = pmap_extract(kernel_pmap, v);
+ if (v == 0) {
+ error = EFAULT;
+ break;
+ }
+
+ /* FALLTHROUGH */
+ case CDEV_MINOR_MEM:
+ /* If within the DMAP use this to copy from */
+ if (PHYS_IN_DMAP(v)) {
+ v = PHYS_TO_DMAP(v);
+ error = uiomove((void *)v, cnt, uio);
+ break;
+ }
+
+ /* Have uiomove_fromphys handle the data */
+ m.phys_addr = trunc_page(v);
+ marr = &m;
+ uiomove_fromphys(&marr, off, cnt, uio);
+ break;
+ }
+ }
- panic("memrw");
+ return (error);
}
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index 7e41820..c2bccb8 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -1434,7 +1434,7 @@ static vm_page_t
reclaim_pv_chunk(pmap_t locked_pmap, struct rwlock **lockp)
{
- panic("reclaim_pv_chunk");
+ panic("ARM64TODO: reclaim_pv_chunk");
}
/*
@@ -2441,6 +2441,18 @@ pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
}
}
+vm_offset_t
+pmap_quick_enter_page(vm_page_t m)
+{
+
+ return (PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)));
+}
+
+void
+pmap_quick_remove_page(vm_offset_t addr)
+{
+}
+
/*
* Returns true if the pmap's pv is one of the first
* 16 pvs linked to from this page. This count may
@@ -2881,7 +2893,7 @@ retry:
* at all. We need to be able to set it in
* the exception handler.
*/
- panic("TODO: safe_to_clear_referenced\n");
+ panic("ARM64TODO: safe_to_clear_referenced\n");
} else if ((pmap_load(l3) & ATTR_SW_WIRED) == 0) {
/*
* Wired pages cannot be paged out so
@@ -2949,7 +2961,7 @@ pmap_clear_modify(vm_page_t m)
if ((m->aflags & PGA_WRITEABLE) == 0)
return;
- /* TODO: We lack support for tracking if a page is modified */
+ /* ARM64TODO: We lack support for tracking if a page is modified */
}
void *
@@ -2971,7 +2983,17 @@ void
pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma)
{
- panic("pmap_page_set_memattr");
+ m->md.pv_memattr = ma;
+
+ /*
+ * ARM64TODO: Implement the below (from the amd64 pmap)
+ * If "m" is a normal page, update its direct mapping. This update
+ * can be relied upon to perform any cache operations that are
+ * required for data coherence.
+ */
+ if ((m->flags & PG_FICTITIOUS) == 0 &&
+ PHYS_IN_DMAP(VM_PAGE_TO_PHYS(m)))
+ panic("ARM64TODO: pmap_page_set_memattr");
}
/*
@@ -2981,7 +3003,7 @@ int
pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa)
{
- panic("pmap_mincore");
+ panic("ARM64TODO: pmap_mincore");
}
void
@@ -3001,7 +3023,7 @@ void
pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz)
{
- panic("pmap_sync_icache");
+ panic("ARM64TODO: pmap_sync_icache");
}
/*
@@ -3085,7 +3107,7 @@ pmap_unmap_io_transient(vm_page_t page[], vm_offset_t vaddr[], int count,
for (i = 0; i < count; i++) {
paddr = VM_PAGE_TO_PHYS(page[i]);
if (paddr >= DMAP_MAX_PHYSADDR) {
- panic("pmap_unmap_io_transient: TODO: Unmap data");
+ panic("ARM64TODO: pmap_unmap_io_transient: Unmap data");
}
}
}
diff --git a/sys/arm64/arm64/stack_machdep.c b/sys/arm64/arm64/stack_machdep.c
index a640077..72a9ab9 100644
--- a/sys/arm64/arm64/stack_machdep.c
+++ b/sys/arm64/arm64/stack_machdep.c
@@ -40,21 +40,49 @@ __FBSDID("$FreeBSD$");
#include <machine/pcb.h>
#include <machine/stack.h>
+static void
+stack_capture(struct stack *st, struct unwind_state *frame)
+{
+
+ stack_zero(st);
+ while (1) {
+ unwind_frame(frame);
+ if (!INKERNEL((vm_offset_t)frame->fp) ||
+ !INKERNEL((vm_offset_t)frame->pc))
+ break;
+ if (stack_put(st, frame->pc) == -1)
+ break;
+ }
+}
+
void
stack_save_td(struct stack *st, struct thread *td)
{
+ struct unwind_state frame;
if (TD_IS_SWAPPED(td))
panic("stack_save_td: swapped");
if (TD_IS_RUNNING(td))
panic("stack_save_td: running");
- stack_zero(st);
+ frame.sp = td->td_pcb->pcb_sp;
+ frame.fp = td->td_pcb->pcb_x[29];
+ frame.pc = td->td_pcb->pcb_x[30];
+
+ stack_capture(st, &frame);
}
void
stack_save(struct stack *st)
{
+ struct unwind_state frame;
+ uint64_t sp;
- stack_zero(st);
+ __asm __volatile("mov %0, sp" : "=&r" (sp));
+
+ frame.sp = sp;
+ frame.fp = (uint64_t)__builtin_frame_address(0);
+ frame.pc = (uint64_t)stack_save;
+
+ stack_capture(st, &frame);
}
diff --git a/sys/arm64/arm64/swtch.S b/sys/arm64/arm64/swtch.S
index a987134..fbffaed 100644
--- a/sys/arm64/arm64/swtch.S
+++ b/sys/arm64/arm64/swtch.S
@@ -131,6 +131,8 @@ ENTRY(cpu_switch)
mov x19, x0
mov x20, x1
mov x21, x2
+ /* Load the pcb address */
+ mov x1, x4
bl vfp_save_state
mov x2, x21
mov x1, x20
@@ -268,9 +270,11 @@ ENTRY(savectx)
/* Store the VFP registers */
#ifdef VFP
- mov x29, lr
+ mov x28, lr
+ mov x1, x0 /* move pcb to the correct register */
+ mov x0, xzr /* td = NULL */
bl vfp_save_state
- mov lr, x29
+ mov lr, x28
#endif
ret
diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c
index 89c104f..22d49b1 100644
--- a/sys/arm64/arm64/trap.c
+++ b/sys/arm64/arm64/trap.c
@@ -119,7 +119,7 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
sa->narg = sa->callp->sy_narg;
memcpy(sa->args, ap, nap * sizeof(register_t));
if (sa->narg > nap)
- panic("TODO: Could we have more then 8 args?");
+ panic("ARM64TODO: Could we have more then 8 args?");
td->td_retval[0] = 0;
td->td_retval[1] = 0;
@@ -319,10 +319,17 @@ do_el0_sync(struct trapframe *frame)
#endif
break;
case EXCP_SVC:
+ /*
+ * Ensure the svc_handler is being run with interrupts enabled.
+ * They will be automatically restored when returning from
+ * exception handler.
+ */
+ intr_enable();
svc_handler(frame);
break;
case EXCP_INSN_ABORT_L:
case EXCP_DATA_ABORT_L:
+ case EXCP_DATA_ABORT:
data_abort(frame, esr, 1);
break;
default:
@@ -335,6 +342,6 @@ void
do_el0_error(struct trapframe *frame)
{
- panic("do_el0_error");
+ panic("ARM64TODO: do_el0_error");
}
diff --git a/sys/arm64/arm64/uio_machdep.c b/sys/arm64/arm64/uio_machdep.c
index e6f6d39..11ed239 100644
--- a/sys/arm64/arm64/uio_machdep.c
+++ b/sys/arm64/arm64/uio_machdep.c
@@ -124,7 +124,7 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
}
out:
if (__predict_false(mapped)) {
- panic("TODO 3");
+ panic("ARM64TODO: uiomove_fromphys");
pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT], &vaddr, 1,
TRUE);
}
diff --git a/sys/amd64/include/xen/xenfunc.h b/sys/arm64/arm64/uma_machdep.c
index d8a6b5c..b17a253 100644
--- a/sys/amd64/include/xen/xenfunc.h
+++ b/sys/arm64/arm64/uma_machdep.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004, 2005 Kip Macy
+ * Copyright (c) 2003 Alan L. Cox <alc@cs.rice.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,52 +22,60 @@
* 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 _XEN_XENFUNC_H_
-#define _XEN_XENFUNC_H_
-
-#include <machine/xen/xenvar.h>
-
-#define BKPT __asm__("int3");
-#define XPQ_CALL_DEPTH 5
-#define XPQ_CALL_COUNT 2
-#define PG_PRIV PG_AVAIL3
-typedef struct {
- unsigned long pt_ref;
- unsigned long pt_eip[XPQ_CALL_COUNT][XPQ_CALL_DEPTH];
-} pteinfo_t;
-
-extern pteinfo_t *pteinfo_list;
-#ifdef XENDEBUG_LOW
-#define __PRINTK(x) printk x
-#else
-#define __PRINTK(x)
-#endif
-
-char *xen_setbootenv(char *cmd_line);
-
-int xen_boothowto(char *envp);
-
-void _xen_machphys_update(vm_paddr_t, vm_paddr_t, char *file, int line);
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
-#ifdef INVARIANTS
-#define xen_machphys_update(a, b) _xen_machphys_update((a), (b), __FILE__, __LINE__)
-#else
-#define xen_machphys_update(a, b) _xen_machphys_update((a), (b), NULL, 0)
-#endif
+#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+#include <vm/uma.h>
+#include <vm/uma_int.h>
+#include <machine/md_var.h>
+#include <machine/vmparam.h>
-extern struct mtx balloon_lock;
-#if 0
-#define balloon_lock(__flags) mtx_lock_irqsave(&balloon_lock, __flags)
-#define balloon_unlock(__flags) mtx_unlock_irqrestore(&balloon_lock, __flags)
-#else
-#define balloon_lock(__flags) __flags = 1
-#define balloon_unlock(__flags) __flags = 0
-#endif
+void *
+uma_small_alloc(uma_zone_t zone, vm_size_t bytes, u_int8_t *flags, int wait)
+{
+ vm_page_t m;
+ vm_paddr_t pa;
+ void *va;
+ int pflags;
+ *flags = UMA_SLAB_PRIV;
+ pflags = malloc2vm_flags(wait) | VM_ALLOC_NOOBJ | VM_ALLOC_WIRED;
+ for (;;) {
+ m = vm_page_alloc(NULL, 0, pflags);
+ if (m == NULL) {
+ if (wait & M_NOWAIT)
+ return (NULL);
+ else
+ VM_WAIT;
+ } else
+ break;
+ }
+ pa = m->phys_addr;
+ va = (void *)PHYS_TO_DMAP(pa);
+ if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0)
+ bzero(va, PAGE_SIZE);
+ return (va);
+}
+void
+uma_small_free(void *mem, vm_size_t size, u_int8_t flags)
+{
+ vm_page_t m;
+ vm_paddr_t pa;
-#endif /* _XEN_XENFUNC_H_ */
+ pa = DMAP_TO_PHYS((vm_offset_t)mem);
+ m = PHYS_TO_VM_PAGE(pa);
+ m->wire_count--;
+ vm_page_free(m);
+ atomic_subtract_int(&vm_cnt.v_wire_count, 1);
+}
diff --git a/sys/arm64/arm64/vfp.c b/sys/arm64/arm64/vfp.c
index a987242..8278f87 100644
--- a/sys/arm64/arm64/vfp.c
+++ b/sys/arm64/arm64/vfp.c
@@ -82,12 +82,18 @@ vfp_discard(struct thread *td)
}
void
-vfp_save_state(struct thread *td)
+vfp_save_state(struct thread *td, struct pcb *pcb)
{
__int128_t *vfp_state;
uint64_t fpcr, fpsr;
uint32_t cpacr;
+ KASSERT(pcb != NULL, ("NULL vfp pcb"));
+ KASSERT(td == NULL || td->td_pcb == pcb, ("Invalid vfp pcb"));
+
+ if (td == NULL)
+ td = curthread;
+
critical_enter();
/*
* Only store the registers if the VFP is enabled,
@@ -98,7 +104,7 @@ vfp_save_state(struct thread *td)
KASSERT(PCPU_GET(fpcurthread) == td,
("Storing an invalid VFP state"));
- vfp_state = td->td_pcb->pcb_vfp;
+ vfp_state = pcb->pcb_vfp;
__asm __volatile(
"mrs %0, fpcr \n"
"mrs %1, fpsr \n"
@@ -120,8 +126,8 @@ vfp_save_state(struct thread *td)
"stp q30, q31, [%2, #16 * 30]\n"
: "=&r"(fpcr), "=&r"(fpsr) : "r"(vfp_state));
- td->td_pcb->pcb_fpcr = fpcr;
- td->td_pcb->pcb_fpsr = fpsr;
+ pcb->pcb_fpcr = fpcr;
+ pcb->pcb_fpsr = fpsr;
dsb(ish);
vfp_disable();
diff --git a/sys/arm64/arm64/vm_machdep.c b/sys/arm64/arm64/vm_machdep.c
index bd6d980..edcdeca 100644
--- a/sys/arm64/arm64/vm_machdep.c
+++ b/sys/arm64/arm64/vm_machdep.c
@@ -74,7 +74,7 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
td1->td_pcb->pcb_tpidr_el0 = READ_SPECIALREG(tpidr_el0);
#ifdef VFP
if ((td1->td_pcb->pcb_fpflags & PCB_FP_STARTED) != 0)
- vfp_save_state(td1);
+ vfp_save_state(td1, td1->td_pcb);
#endif
}
@@ -258,18 +258,3 @@ swi_vm(void *v)
/* Nothing to do here - busdma bounce buffers are not implemented. */
}
-
-void *
-uma_small_alloc(uma_zone_t zone, vm_size_t bytes, u_int8_t *flags, int wait)
-{
-
- panic("uma_small_alloc");
-}
-
-void
-uma_small_free(void *mem, vm_size_t size, u_int8_t flags)
-{
-
- panic("uma_small_free");
-}
-
diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC
index c4ef49d..e3b0c77 100644
--- a/sys/arm64/conf/GENERIC
+++ b/sys/arm64/conf/GENERIC
@@ -109,6 +109,9 @@ device psci # Support for ARM PSCI
# Note that 'bpf' is required for DHCP.
device bpf # Berkeley packet filter
+# Chip-specific errata
+options THUNDERX_PASS_1_1_ERRATA
+
options FDT
device acpi
diff --git a/sys/arm64/include/atomic.h b/sys/arm64/include/atomic.h
index 4c9d718..12ce4a1 100644
--- a/sys/arm64/include/atomic.h
+++ b/sys/arm64/include/atomic.h
@@ -153,6 +153,22 @@ atomic_set_32(volatile uint32_t *p, uint32_t val)
);
}
+static __inline uint32_t
+atomic_swap_32(volatile uint32_t *p, uint32_t val)
+{
+ uint32_t tmp;
+ int res;
+
+ __asm __volatile(
+ "1: ldxr %w0, [%2] \n"
+ " stxr %w1, %w3, [%2] \n"
+ " cbnz %w1, 1b \n"
+ : "=&r"(tmp), "=&r"(res), "+r" (p), "+r" (val) : : "cc", "memory"
+ );
+
+ return (tmp);
+}
+
static __inline void
atomic_subtract_32(volatile uint32_t *p, uint32_t val)
{
@@ -174,6 +190,7 @@ atomic_subtract_32(volatile uint32_t *p, uint32_t val)
#define atomic_fetchadd_int atomic_fetchadd_32
#define atomic_readandclear_int atomic_readandclear_32
#define atomic_set_int atomic_set_32
+#define atomic_swap_int atomic_swap_32
#define atomic_subtract_int atomic_subtract_32
static __inline void
@@ -515,6 +532,7 @@ atomic_swap_64(volatile uint64_t *p, uint64_t val)
#define atomic_fetchadd_long atomic_fetchadd_64
#define atomic_readandclear_long atomic_readandclear_64
#define atomic_set_long atomic_set_64
+#define atomic_swap_long atomic_swap_64
#define atomic_subtract_long atomic_subtract_64
#define atomic_add_ptr atomic_add_64
@@ -523,6 +541,7 @@ atomic_swap_64(volatile uint64_t *p, uint64_t val)
#define atomic_fetchadd_ptr atomic_fetchadd_64
#define atomic_readandclear_ptr atomic_readandclear_64
#define atomic_set_ptr atomic_set_64
+#define atomic_swap_ptr atomic_swap_64
#define atomic_subtract_ptr atomic_subtract_64
static __inline void
diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h
index 15cdd80..ec351ad 100644
--- a/sys/arm64/include/cpu.h
+++ b/sys/arm64/include/cpu.h
@@ -78,6 +78,9 @@
#define CPU_PART_CORTEX_A53 0xD03
#define CPU_PART_CORTEX_A57 0xD07
+#define CPU_REV_THUNDER_1_0 0x00
+#define CPU_REV_THUNDER_1_1 0x01
+
#define CPU_IMPL(midr) (((midr) >> 24) & 0xff)
#define CPU_PART(midr) (((midr) >> 4) & 0xfff)
#define CPU_VAR(midr) (((midr) >> 20) & 0xf)
@@ -105,6 +108,29 @@
#define CPU_MATCH_RAW(mask, devid) \
(((mask) & PCPU_GET(midr)) == ((mask) & (devid)))
+/*
+ * Chip-specific errata. This defines are intended to be
+ * booleans used within if statements. When an appropriate
+ * kernel option is disabled, these defines must be defined
+ * as 0 to allow the compiler to remove a dead code thus
+ * produce better optimized kernel image.
+ */
+/*
+ * Vendor: Cavium
+ * Chip: ThunderX
+ * Revision(s): Pass 1.0, Pass 1.1
+ */
+#ifdef THUNDERX_PASS_1_1_ERRATA
+#define CPU_MATCH_ERRATA_CAVIUM_THUNDER_1_1 \
+ (CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK | CPU_REV_MASK, \
+ CPU_IMPL_CAVIUM, CPU_PART_THUNDER, 0, CPU_REV_THUNDER_1_0) || \
+ CPU_MATCH(CPU_IMPL_MASK | CPU_PART_MASK | CPU_REV_MASK, \
+ CPU_IMPL_CAVIUM, CPU_PART_THUNDER, 0, CPU_REV_THUNDER_1_1))
+#else
+#define CPU_MATCH_ERRATA_CAVIUM_THUNDER_1_1 0
+#endif
+
+
extern char btext[];
extern char etext[];
diff --git a/sys/arm64/include/float.h b/sys/arm64/include/float.h
index 2bb86bd..0829f6f 100644
--- a/sys/arm64/include/float.h
+++ b/sys/arm64/include/float.h
@@ -10,10 +10,6 @@
* 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 the University of
- * California, Berkeley and its contributors.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
diff --git a/sys/arm64/include/in_cksum.h b/sys/arm64/include/in_cksum.h
index 40524e4..522ba00 100644
--- a/sys/arm64/include/in_cksum.h
+++ b/sys/arm64/include/in_cksum.h
@@ -10,11 +10,7 @@
* 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 the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
diff --git a/sys/arm64/include/vfp.h b/sys/arm64/include/vfp.h
index ccb853c..39adf4f 100644
--- a/sys/arm64/include/vfp.h
+++ b/sys/arm64/include/vfp.h
@@ -38,7 +38,7 @@
void vfp_init(void);
void vfp_discard(struct thread *);
void vfp_restore_state(void);
-void vfp_save_state(struct thread *);
+void vfp_save_state(struct thread *, struct pcb *);
#endif
#endif
diff --git a/sys/arm64/include/vmparam.h b/sys/arm64/include/vmparam.h
index 8ad6029..3c14af8 100644
--- a/sys/arm64/include/vmparam.h
+++ b/sys/arm64/include/vmparam.h
@@ -165,6 +165,9 @@
/* True if pa is in the dmap range */
#define PHYS_IN_DMAP(pa) ((pa) <= DMAP_MAX_PHYSADDR)
+/* True if va is in the dmap range */
+#define VIRT_IN_DMAP(va) ((va) >= DMAP_MIN_ADDRESS && \
+ (va) <= DMAP_MAX_ADDRESS)
#define PHYS_TO_DMAP(pa) \
({ \
@@ -176,7 +179,7 @@
#define DMAP_TO_PHYS(va) \
({ \
- KASSERT(((va) <= DMAP_MAX_ADDRESS || (va) >= DMAP_MIN_ADDRESS), \
+ KASSERT(VIRT_IN_DMAP(va), \
("%s: VA out of range, VA: 0x%lx", __func__, \
(vm_offset_t)(va))); \
(va) & ~DMAP_MIN_ADDRESS; \
@@ -221,6 +224,8 @@
#define VM_INITIAL_PAGEIN 16
#endif
+#define UMA_MD_SMALL_ALLOC
+
extern u_int tsb_kernel_ldd_phys;
extern vm_offset_t vm_max_kernel_address;
extern vm_offset_t init_pt_va;
diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c
index b48b493..163814b 100644
--- a/sys/boot/common/module.c
+++ b/sys/boot/common/module.c
@@ -102,6 +102,7 @@ COMMAND_SET(load, "load", "load a kernel or module", command_load);
static int
command_load(int argc, char *argv[])
{
+ struct preloaded_file *fp;
char *typestr;
int dofile, dokld, ch, error;
@@ -139,6 +140,13 @@ command_load(int argc, char *argv[])
command_errmsg = "invalid load type";
return(CMD_ERROR);
}
+
+ fp = file_findfile(argv[1], typestr);
+ if (fp) {
+ sprintf(command_errbuf, "warning: file '%s' already loaded", argv[1]);
+ return (CMD_ERROR);
+ }
+
return (file_loadraw(argv[1], typestr, 1) ? CMD_OK : CMD_ERROR);
}
/*
diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf
index caafcc6..e2338ab 100644
--- a/sys/boot/forth/loader.conf
+++ b/sys/boot/forth/loader.conf
@@ -268,6 +268,8 @@ screensave_name="green_saver" # Set to the name of the screensaver module
### Emulation modules ######################################
##############################################################
+cloudabi_load="NO" # Platform independent CloudABI support
+cloudabi64_load="NO" # 64-bit CloudABI executables support
ibcs2_load="NO" # IBCS2 (SCO) emulation
ibcs2_coff_load="NO"
linux_load="NO" # Linux emulation
diff --git a/sys/boot/forth/loader.rc b/sys/boot/forth/loader.rc
index b4a6d51..0bc6657 100644
--- a/sys/boot/forth/loader.rc
+++ b/sys/boot/forth/loader.rc
@@ -1,6 +1,9 @@
\ Loader.rc
\ $FreeBSD$
\
+\ You should not edit this file! Put any overrides in loader.rc.local
+\ instead as this file can be replaced during system updates.
+\
\ Includes additional commands
include /boot/loader.4th
try-include /boot/loader.rc.local
diff --git a/sys/boot/forth/menu.rc b/sys/boot/forth/menu.rc
index e650848..7ffeef4 100644
--- a/sys/boot/forth/menu.rc
+++ b/sys/boot/forth/menu.rc
@@ -1,6 +1,9 @@
\ Menu.rc
\ $FreeBSD$
\
+\ You should not edit this file! Put any overrides in menu.rc.local
+\ instead as this file can be replaced during system updates.
+\
\ Load required Forth modules
include /boot/version.4th
include /boot/brand.4th
diff --git a/sys/boot/i386/loader/Makefile b/sys/boot/i386/loader/Makefile
index ade6054..bcbe0b8 100644
--- a/sys/boot/i386/loader/Makefile
+++ b/sys/boot/i386/loader/Makefile
@@ -110,12 +110,7 @@ FILESMODE_${LOADER}= ${BINMODE} -b
.include "${.CURDIR}/../../forth/Makefile.inc"
FILES+= pcibios.4th
-.if !exists(${DESTDIR}/boot/loader.rc)
-FILES+= loader.rc
-.endif
-.if !exists(${DESTDIR}/boot/menu.rc)
-FILES+= menu.rc
-.endif
+FILES+= loader.rc menu.rc
.endif
# XXX crt0.o needs to be first for pxeboot(8) to work
diff --git a/sys/boot/mips/beri/loader/Makefile b/sys/boot/mips/beri/loader/Makefile
index a134f3d..7223492 100644
--- a/sys/boot/mips/beri/loader/Makefile
+++ b/sys/boot/mips/beri/loader/Makefile
@@ -125,13 +125,7 @@ loader.help: help.common help.mips
.PATH: ${.CURDIR}/../../../forth
.include "${.CURDIR}/../../../forth/Makefile.inc"
-.if !exists(${DESTDIR}/boot/loader.rc)
-FILES+= loader.rc
-.endif
-
-.if !exists(${DESTDIR}/boot/menu.rc)
-FILES+= menu.rc
-.endif
+FILES+= loader.rc menu.rc
.if defined(LOADER_USB_SUPPORT)
# Do garbage collection
diff --git a/sys/boot/pc98/loader/Makefile b/sys/boot/pc98/loader/Makefile
index 9333f3c..319600f 100644
--- a/sys/boot/pc98/loader/Makefile
+++ b/sys/boot/pc98/loader/Makefile
@@ -90,12 +90,7 @@ FILESMODE_${LOADER}= ${BINMODE} -b
.PATH: ${.CURDIR}/../../forth
.include "${.CURDIR}/../../forth/Makefile.inc"
-.if !exists(${DESTDIR}/boot/loader.rc)
-FILES+= ${.CURDIR}/../../i386/loader/loader.rc
-.endif
-.if !exists(${DESTDIR}/boot/menu.rc)
-FILES+= menu.rc
-.endif
+FILES+= ${.CURDIR}/../../i386/loader/loader.rc menu.rc
# XXX crt0.o needs to be first for pxeboot(8) to work
OBJS= ${BTXCRT}
diff --git a/sys/boot/powerpc/kboot/Makefile b/sys/boot/powerpc/kboot/Makefile
index 4601f29..a47275c 100644
--- a/sys/boot/powerpc/kboot/Makefile
+++ b/sys/boot/powerpc/kboot/Makefile
@@ -117,12 +117,6 @@ loader.help: help.common help.kboot ${.CURDIR}/../../fdt/help.fdt
.PATH: ${.CURDIR}/../../forth
.include "${.CURDIR}/../../forth/Makefile.inc"
-.if !exists(${DESTDIR}/boot/loader.rc)
-FILES+= loader.rc
-.endif
-
-.if !exists(${DESTDIR}/boot/menu.rc)
-FILES+= menu.rc
-.endif
+FILES+= loader.rc menu.rc
.include <bsd.prog.mk>
diff --git a/sys/boot/powerpc/ofw/Makefile b/sys/boot/powerpc/ofw/Makefile
index 6a2fc70..ab5720f 100644
--- a/sys/boot/powerpc/ofw/Makefile
+++ b/sys/boot/powerpc/ofw/Makefile
@@ -112,12 +112,6 @@ loader.help: help.common help.ofw ${.CURDIR}/../../fdt/help.fdt
.PATH: ${.CURDIR}/../../forth
.include "${.CURDIR}/../../forth/Makefile.inc"
-.if !exists(${DESTDIR}/boot/loader.rc)
-FILES+= loader.rc
-.endif
-
-.if !exists(${DESTDIR}/boot/menu.rc)
-FILES+= menu.rc
-.endif
+FILES+= loader.rc menu.rc
.include <bsd.prog.mk>
diff --git a/sys/boot/powerpc/ps3/Makefile b/sys/boot/powerpc/ps3/Makefile
index 861872f..baf2507 100644
--- a/sys/boot/powerpc/ps3/Makefile
+++ b/sys/boot/powerpc/ps3/Makefile
@@ -114,12 +114,6 @@ loader.help: help.common help.ps3 ${.CURDIR}/../../fdt/help.fdt
.PATH: ${.CURDIR}/../../forth
.include "${.CURDIR}/../../forth/Makefile.inc"
-.if !exists(${DESTDIR}/boot/loader.rc)
-FILES+= loader.rc
-.endif
-
-.if !exists(${DESTDIR}/boot/menu.rc)
-FILES+= menu.rc
-.endif
+FILES+= loader.rc menu.rc
.include <bsd.prog.mk>
diff --git a/sys/boot/sparc64/loader/Makefile b/sys/boot/sparc64/loader/Makefile
index 5c9bfbb..05d23ff 100644
--- a/sys/boot/sparc64/loader/Makefile
+++ b/sys/boot/sparc64/loader/Makefile
@@ -99,12 +99,6 @@ loader.help: help.common help.sparc64
.PATH: ${.CURDIR}/../../forth
.include "${.CURDIR}/../../forth/Makefile.inc"
-.if !exists(${DESTDIR}/boot/loader.rc)
-FILES+= loader.rc
-.endif
-
-.if !exists(${DESTDIR}/boot/menu.rc)
-FILES+= menu.rc
-.endif
+FILES+= loader.rc menu.rc
.include <bsd.prog.mk>
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 3d562d0..1b6c149 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -374,9 +374,11 @@ SYSCTL_INT(_kern_cam_ctl, OID_AUTO, debug, CTLFLAG_RWTUN,
*/
#define SCSI_EVPD_NUM_SUPPORTED_PAGES 10
+#ifdef notyet
static void ctl_isc_event_handler(ctl_ha_channel chanel, ctl_ha_event event,
int param);
static void ctl_copy_sense_data(union ctl_ha_msg *src, union ctl_io *dest);
+#endif
static int ctl_init(void);
void ctl_shutdown(void);
static int ctl_open(struct cdev *dev, int flags, int fmt, struct thread *td);
@@ -444,7 +446,9 @@ static int ctl_scsiio_lun_check(struct ctl_lun *lun,
const struct ctl_cmd_entry *entry,
struct ctl_scsiio *ctsio);
//static int ctl_check_rtr(union ctl_io *pending_io, struct ctl_softc *softc);
+#ifdef notyet
static void ctl_failover(void);
+#endif
static void ctl_clear_ua(struct ctl_softc *ctl_softc, uint32_t initidx,
ctl_ua_type ua_type);
static int ctl_scsiio_precheck(struct ctl_softc *ctl_softc,
@@ -483,7 +487,9 @@ static void ctl_work_thread(void *arg);
static void ctl_enqueue_incoming(union ctl_io *io);
static void ctl_enqueue_rtr(union ctl_io *io);
static void ctl_enqueue_done(union ctl_io *io);
+#ifdef notyet
static void ctl_enqueue_isc(union ctl_io *io);
+#endif
static const struct ctl_cmd_entry *
ctl_get_cmd_entry(struct ctl_scsiio *ctsio, int *sa);
static const struct ctl_cmd_entry *
@@ -511,7 +517,6 @@ static struct cdevsw ctl_cdevsw = {
MALLOC_DEFINE(M_CTL, "ctlmem", "Memory used for CTL");
-MALLOC_DEFINE(M_CTLIO, "ctlio", "Memory used for CTL requests");
static int ctl_module_event_handler(module_t, int /*modeventtype_t*/, void *);
@@ -529,6 +534,7 @@ static struct ctl_frontend ioctl_frontend =
.name = "ioctl",
};
+#ifdef notyet
static void
ctl_isc_handler_finish_xfer(struct ctl_softc *ctl_softc,
union ctl_ha_msg *msg_info)
@@ -963,6 +969,7 @@ ctl_copy_sense_data(union ctl_ha_msg *src, union ctl_io *dest)
dest->scsiio.sense_len = src->scsi.sense_len;
dest->io_hdr.status = src->hdr.status;
}
+#endif
static void
ctl_est_ua(struct ctl_lun *lun, uint32_t initidx, ctl_ua_type ua)
@@ -5507,9 +5514,11 @@ ctl_sync_cache(struct ctl_scsiio *ctsio)
{
struct ctl_lun *lun;
struct ctl_softc *softc;
+ struct ctl_lba_len_flags *lbalen;
uint64_t starting_lba;
uint32_t block_count;
int retval;
+ uint8_t byte2;
CTL_DEBUG_PRINT(("ctl_sync_cache\n"));
@@ -5524,6 +5533,7 @@ ctl_sync_cache(struct ctl_scsiio *ctsio)
starting_lba = scsi_4btoul(cdb->begin_lba);
block_count = scsi_2btoul(cdb->lb_count);
+ byte2 = cdb->byte2;
break;
}
case SYNCHRONIZE_CACHE_16: {
@@ -5532,6 +5542,7 @@ ctl_sync_cache(struct ctl_scsiio *ctsio)
starting_lba = scsi_8btou64(cdb->begin_lba);
block_count = scsi_4btoul(cdb->lb_count);
+ byte2 = cdb->byte2;
break;
}
default:
@@ -5562,6 +5573,11 @@ ctl_sync_cache(struct ctl_scsiio *ctsio)
goto bailout;
}
+ lbalen = (struct ctl_lba_len_flags *)&ctsio->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
+ lbalen->lba = starting_lba;
+ lbalen->len = block_count;
+ lbalen->flags = byte2;
+
/*
* Check to see whether we're configured to send the SYNCHRONIZE
* CACHE command directly to the back end.
@@ -11361,6 +11377,7 @@ ctl_failover_io(union ctl_io *io, int have_lock)
ctl_done(io);
}
+#ifdef notyet
static void
ctl_failover(void)
{
@@ -11601,6 +11618,7 @@ ctl_failover(void)
ctl_pause_rtr = 0;
mtx_unlock(&softc->ctl_lock);
}
+#endif
static void
ctl_clear_ua(struct ctl_softc *ctl_softc, uint32_t initidx,
@@ -14244,6 +14262,7 @@ ctl_enqueue_done(union ctl_io *io)
wakeup(thr);
}
+#ifdef notyet
static void
ctl_enqueue_isc(union ctl_io *io)
{
@@ -14356,6 +14375,7 @@ struct ctl_ha_component ctl_ha_component_ctlisc =
.start = ctl_isc_start,
.quiesce = ctl_isc_quiesce
};
+#endif
/*
* vim: ts=8
diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h
index 2693419..b1d9118 100644
--- a/sys/cam/ctl/ctl.h
+++ b/sys/cam/ctl/ctl.h
@@ -191,7 +191,9 @@ void ctl_data_submit_done(union ctl_io *io);
void ctl_config_read_done(union ctl_io *io);
void ctl_config_write_done(union ctl_io *io);
void ctl_portDB_changed(int portnum);
+#ifdef notyet
void ctl_init_isc_msg(void);
+#endif
/*
* KPI to manipulate LUN/port options
diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c
index 8ea52aa..5bb3121 100644
--- a/sys/cam/ctl/ctl_backend_block.c
+++ b/sys/cam/ctl/ctl_backend_block.c
@@ -224,6 +224,7 @@ struct ctl_be_block_io {
devstat_trans_flags ds_trans_type;
uint64_t io_len;
uint64_t io_offset;
+ int io_arg;
struct ctl_be_block_softc *softc;
struct ctl_be_block_lun *lun;
void (*beio_cont)(struct ctl_be_block_io *beio); /* to continue processing */
@@ -581,7 +582,8 @@ ctl_be_block_flush_file(struct ctl_be_block_lun *be_lun,
vn_lock(be_lun->vn, lock_flags | LK_RETRY);
- error = VOP_FSYNC(be_lun->vn, MNT_WAIT, curthread);
+ error = VOP_FSYNC(be_lun->vn, beio->io_arg ? MNT_NOWAIT : MNT_WAIT,
+ curthread);
VOP_UNLOCK(be_lun->vn, 0);
vn_finished_write(mountpoint);
@@ -674,9 +676,6 @@ ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
* ZFS pays attention to IO_SYNC (which translates into the
* Solaris define FRSYNC for zfs_read()) for reads. It
* attempts to sync the file before reading.
- *
- * So, to attempt to provide some barrier semantics in the
- * BIO_ORDERED case, set both IO_DIRECT and IO_SYNC.
*/
error = VOP_READ(be_lun->vn, &xuio, flags, file_data->cred);
@@ -711,9 +710,6 @@ ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun,
* ZFS pays attention to IO_SYNC (a.k.a. FSYNC or FRSYNC)
* for writes. It will flush the transaction from the
* cache before returning.
- *
- * So if we've got the BIO_ORDERED flag set, we want
- * IO_SYNC in either the UFS or ZFS case.
*/
error = VOP_WRITE(be_lun->vn, &xuio, flags, file_data->cred);
VOP_UNLOCK(be_lun->vn, 0);
@@ -981,7 +977,6 @@ ctl_be_block_flush_dev(struct ctl_be_block_lun *be_lun,
bio = g_alloc_bio();
bio->bio_cmd = BIO_FLUSH;
- bio->bio_flags |= BIO_ORDERED;
bio->bio_dev = dev_data->cdev;
bio->bio_offset = 0;
bio->bio_data = 0;
@@ -1167,6 +1162,26 @@ ctl_be_block_getattr_dev(struct ctl_be_block_lun *be_lun, const char *attrname)
}
static void
+ctl_be_block_cw_dispatch_sync(struct ctl_be_block_lun *be_lun,
+ union ctl_io *io)
+{
+ struct ctl_be_block_io *beio;
+ struct ctl_lba_len_flags *lbalen;
+
+ DPRINTF("entered\n");
+ beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
+ lbalen = (struct ctl_lba_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
+
+ beio->io_len = lbalen->len * be_lun->blocksize;
+ beio->io_offset = lbalen->lba * be_lun->blocksize;
+ beio->io_arg = (lbalen->flags & SSC_IMMED) != 0;
+ beio->bio_cmd = BIO_FLUSH;
+ beio->ds_trans_type = DEVSTAT_NO_DATA;
+ DPRINTF("SYNC\n");
+ be_lun->lun_flush(be_lun, beio);
+}
+
+static void
ctl_be_block_cw_done_ws(struct ctl_be_block_io *beio)
{
union ctl_io *io;
@@ -1188,7 +1203,6 @@ ctl_be_block_cw_dispatch_ws(struct ctl_be_block_lun *be_lun,
union ctl_io *io)
{
struct ctl_be_block_io *beio;
- struct ctl_be_block_softc *softc;
struct ctl_lba_len_flags *lbalen;
uint64_t len_left, lba;
uint32_t pb, pbo, adj;
@@ -1198,7 +1212,6 @@ ctl_be_block_cw_dispatch_ws(struct ctl_be_block_lun *be_lun,
DPRINTF("entered\n");
beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
- softc = be_lun->softc;
lbalen = ARGS(beio->io);
if (lbalen->flags & ~(SWS_LBDATA | SWS_UNMAP | SWS_ANCHOR | SWS_NDOB) ||
@@ -1214,21 +1227,6 @@ ctl_be_block_cw_dispatch_ws(struct ctl_be_block_lun *be_lun,
return;
}
- switch (io->scsiio.tag_type) {
- case CTL_TAG_ORDERED:
- beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
- break;
- case CTL_TAG_HEAD_OF_QUEUE:
- beio->ds_tag_type = DEVSTAT_TAG_HEAD;
- break;
- case CTL_TAG_UNTAGGED:
- case CTL_TAG_SIMPLE:
- case CTL_TAG_ACA:
- default:
- beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
- break;
- }
-
if (lbalen->flags & (SWS_UNMAP | SWS_ANCHOR)) {
beio->io_offset = lbalen->lba * be_lun->blocksize;
beio->io_len = (uint64_t)lbalen->len * be_lun->blocksize;
@@ -1303,13 +1301,11 @@ ctl_be_block_cw_dispatch_unmap(struct ctl_be_block_lun *be_lun,
union ctl_io *io)
{
struct ctl_be_block_io *beio;
- struct ctl_be_block_softc *softc;
struct ctl_ptr_len_flags *ptrlen;
DPRINTF("entered\n");
beio = (struct ctl_be_block_io *)PRIV(io)->ptr;
- softc = be_lun->softc;
ptrlen = (struct ctl_ptr_len_flags *)&io->io_hdr.ctl_private[CTL_PRIV_LBA_LEN];
if ((ptrlen->flags & ~SU_ANCHOR) != 0 || be_lun->unmap == NULL) {
@@ -1324,29 +1320,11 @@ ctl_be_block_cw_dispatch_unmap(struct ctl_be_block_lun *be_lun,
return;
}
- switch (io->scsiio.tag_type) {
- case CTL_TAG_ORDERED:
- beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
- break;
- case CTL_TAG_HEAD_OF_QUEUE:
- beio->ds_tag_type = DEVSTAT_TAG_HEAD;
- break;
- case CTL_TAG_UNTAGGED:
- case CTL_TAG_SIMPLE:
- case CTL_TAG_ACA:
- default:
- beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
- break;
- }
-
beio->io_len = 0;
beio->io_offset = -1;
-
beio->bio_cmd = BIO_DELETE;
beio->ds_trans_type = DEVSTAT_FREE;
-
DPRINTF("UNMAP\n");
-
be_lun->unmap(be_lun, beio);
}
@@ -1417,16 +1395,26 @@ ctl_be_block_cw_dispatch(struct ctl_be_block_lun *be_lun,
beio->io = io;
beio->lun = be_lun;
beio->beio_cont = ctl_be_block_cw_done;
+ switch (io->scsiio.tag_type) {
+ case CTL_TAG_ORDERED:
+ beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
+ break;
+ case CTL_TAG_HEAD_OF_QUEUE:
+ beio->ds_tag_type = DEVSTAT_TAG_HEAD;
+ break;
+ case CTL_TAG_UNTAGGED:
+ case CTL_TAG_SIMPLE:
+ case CTL_TAG_ACA:
+ default:
+ beio->ds_tag_type = DEVSTAT_TAG_SIMPLE;
+ break;
+ }
PRIV(io)->ptr = (void *)beio;
switch (io->scsiio.cdb[0]) {
case SYNCHRONIZE_CACHE:
case SYNCHRONIZE_CACHE_16:
- beio->bio_cmd = BIO_FLUSH;
- beio->ds_trans_type = DEVSTAT_NO_DATA;
- beio->ds_tag_type = DEVSTAT_TAG_ORDERED;
- beio->io_len = 0;
- be_lun->lun_flush(be_lun, beio);
+ ctl_be_block_cw_dispatch_sync(be_lun, io);
break;
case WRITE_SAME_10:
case WRITE_SAME_16:
diff --git a/sys/cam/ctl/ctl_cmd_table.c b/sys/cam/ctl/ctl_cmd_table.c
index b07ea93..08ff88a 100644
--- a/sys/cam/ctl/ctl_cmd_table.c
+++ b/sys/cam/ctl/ctl_cmd_table.c
@@ -785,10 +785,10 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
/* 35 SYNCHRONIZE CACHE(10) */
-{ctl_sync_cache, CTL_SERIDX_START, CTL_CMD_FLAG_OK_ON_SLUN |
- CTL_FLAG_DATA_NONE,
+{ctl_sync_cache, CTL_SERIDX_SYNC, CTL_CMD_FLAG_OK_ON_SLUN |
+ CTL_FLAG_DATA_NONE,
CTL_LUN_PAT_NONE,
- 10, {0, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}},
+ 10, {0x02, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}},
/* 36 LOCK UNLOCK CACHE(10) */
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
@@ -1138,10 +1138,10 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
/* 91 SYNCHRONIZE CACHE(16) */
-{ctl_sync_cache, CTL_SERIDX_START, CTL_CMD_FLAG_OK_ON_SLUN |
- CTL_FLAG_DATA_NONE,
+{ctl_sync_cache, CTL_SERIDX_SYNC, CTL_CMD_FLAG_OK_ON_SLUN |
+ CTL_FLAG_DATA_NONE,
CTL_LUN_PAT_NONE,
- 16, {0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 16, {0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
/* 92 LOCK UNLOCK CACHE(16) */
diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h
index 8a00b5c..a038552 100644
--- a/sys/cam/ctl/ctl_private.h
+++ b/sys/cam/ctl/ctl_private.h
@@ -141,6 +141,7 @@ typedef enum {
CTL_SERIDX_READ,
CTL_SERIDX_WRITE,
CTL_SERIDX_UNMAP,
+ CTL_SERIDX_SYNC,
CTL_SERIDX_MD_SNS,
CTL_SERIDX_MD_SEL,
CTL_SERIDX_RQ_SNS,
diff --git a/sys/cam/ctl/ctl_ser_table.c b/sys/cam/ctl/ctl_ser_table.c
index ee2d019..8d5d6bc 100644
--- a/sys/cam/ctl/ctl_ser_table.c
+++ b/sys/cam/ctl/ctl_ser_table.c
@@ -63,19 +63,20 @@
static ctl_serialize_action
ctl_serialize_table[CTL_SERIDX_COUNT][CTL_SERIDX_COUNT] = {
-/**>IDX_ :: 2nd:TUR RD WRT UNM MDSN MDSL RQSN INQ RDCP RES LSNS FMT STR*/
-/*TUR */{ pS, pS, pS, pS, bK, bK, bK, pS, pS, bK, pS, bK, bK},
-/*READ */{ pS, xS, xT, bO, bK, bK, bK, pS, pS, bK, pS, bK, bK},
-/*WRITE */{ pS, xT, xT, bO, bK, bK, bK, pS, pS, bK, pS, bK, bK},
-/*UNMAP */{ pS, xO, xO, pS, bK, bK, bK, pS, pS, bK, pS, bK, bK},
-/*MD_SNS */{ bK, bK, bK, bK, pS, bK, bK, pS, pS, bK, pS, bK, bK},
-/*MD_SEL */{ bK, bK, bK, bK, bK, bK, bK, pS, pS, bK, pS, bK, bK},
-/*RQ_SNS */{ pS, pS, pS, pS, pS, pS, bK, pS, pS, bK, pS, bK, bK},
-/*INQ */{ pS, pS, pS, pS, pS, pS, bK, pS, pS, pS, pS, bK, bK},
-/*RD_CAP */{ pS, pS, pS, pS, pS, pS, bK, pS, pS, pS, pS, bK, pS},
-/*RES */{ bK, bK, bK, bK, bK, bK, bK, pS, bK, bK, bK, bK, bK},
-/*LOG_SNS */{ pS, pS, pS, pS, pS, bK, bK, pS, pS, bK, pS, bK, bK},
-/*FORMAT */{ pS, bK, bK, bK, bK, bK, pS, pS, bK, bK, bK, bK, bK},
-/*START */{ bK, bK, bK, bK, bK, bK, bK, pS, bK, bK, bK, bK, bK},
+/**>IDX_ :: 2nd:TUR RD WRT UNM SYN MDSN MDSL RQSN INQ RDCP RES LSNS FMT STR*/
+/*TUR */{ pS, pS, pS, pS, pS, bK, bK, bK, pS, pS, bK, pS, bK, bK},
+/*READ */{ pS, xS, xT, bO, pS, bK, bK, bK, pS, pS, bK, pS, bK, bK},
+/*WRITE */{ pS, xT, xT, bO, bO, bK, bK, bK, pS, pS, bK, pS, bK, bK},
+/*UNMAP */{ pS, xO, xO, pS, pS, bK, bK, bK, pS, pS, bK, pS, bK, bK},
+/*SYNC */{ pS, pS, pS, pS, pS, bK, bK, bK, pS, pS, bK, pS, bK, bK},
+/*MD_SNS */{ bK, bK, bK, bK, bK, pS, bK, bK, pS, pS, bK, pS, bK, bK},
+/*MD_SEL */{ bK, bK, bK, bK, bK, bK, bK, bK, pS, pS, bK, pS, bK, bK},
+/*RQ_SNS */{ pS, pS, pS, pS, pS, pS, pS, bK, pS, pS, bK, pS, bK, bK},
+/*INQ */{ pS, pS, pS, pS, pS, pS, pS, bK, pS, pS, pS, pS, bK, bK},
+/*RD_CAP */{ pS, pS, pS, pS, pS, pS, pS, bK, pS, pS, pS, pS, bK, pS},
+/*RES */{ bK, bK, bK, bK, bK, bK, bK, bK, pS, bK, bK, bK, bK, bK},
+/*LOG_SNS */{ pS, pS, pS, pS, pS, pS, bK, bK, pS, pS, bK, pS, bK, bK},
+/*FORMAT */{ pS, bK, bK, bK, bK, bK, bK, pS, pS, bK, bK, bK, bK, bK},
+/*START */{ bK, bK, bK, bK, bK, bK, bK, bK, pS, bK, bK, bK, bK, bK},
};
diff --git a/sys/cam/ctl/ctl_tpc.c b/sys/cam/ctl/ctl_tpc.c
index 490cddd..662ee3d 100644
--- a/sys/cam/ctl/ctl_tpc.c
+++ b/sys/cam/ctl/ctl_tpc.c
@@ -817,7 +817,7 @@ tpc_process_b2b(struct tpc_list *list)
struct scsi_ec_segment_b2b *seg;
struct scsi_ec_cscd_dtsp *sdstp, *ddstp;
struct tpc_io *tior, *tiow;
- struct runl run, *prun;
+ struct runl run;
uint64_t sl, dl;
off_t srclba, dstlba, numbytes, donebytes, roundbytes;
int numlba;
@@ -889,8 +889,7 @@ tpc_process_b2b(struct tpc_list *list)
list->segsectors = numbytes / dstblock;
donebytes = 0;
TAILQ_INIT(&run);
- prun = &run;
- list->tbdio = 1;
+ list->tbdio = 0;
while (donebytes < numbytes) {
roundbytes = numbytes - donebytes;
if (roundbytes > TPC_MAX_IO_SIZE) {
@@ -942,8 +941,8 @@ tpc_process_b2b(struct tpc_list *list)
tiow->io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = tiow;
TAILQ_INSERT_TAIL(&tior->run, tiow, rlinks);
- TAILQ_INSERT_TAIL(prun, tior, rlinks);
- prun = &tior->run;
+ TAILQ_INSERT_TAIL(&run, tior, rlinks);
+ list->tbdio++;
donebytes += roundbytes;
srclba += roundbytes / srcblock;
dstlba += roundbytes / dstblock;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
index 4da9444..a3a0bba 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
@@ -3510,7 +3510,6 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
*/
if (DTRACE_ANCHORED(mstate->dtms_probe) && CPU_ON_INTR(CPU))
return ((uint64_t)p0.p_cred->cr_uid);
-#endif
/*
* It is always safe to dereference one's own t_procp pointer:
@@ -3522,6 +3521,9 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
* credential, since this is never NULL after process birth.
*/
return ((uint64_t)curthread->t_procp->p_cred->cr_uid);
+#else
+ return ((uint64_t)curthread->td_ucred->cr_uid);
+#endif
case DIF_VAR_GID:
if (!dtrace_priv_proc(state))
@@ -3533,7 +3535,6 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
*/
if (DTRACE_ANCHORED(mstate->dtms_probe) && CPU_ON_INTR(CPU))
return ((uint64_t)p0.p_cred->cr_gid);
-#endif
/*
* It is always safe to dereference one's own t_procp pointer:
@@ -3545,6 +3546,9 @@ dtrace_dif_variable(dtrace_mstate_t *mstate, dtrace_state_t *state, uint64_t v,
* credential, since this is never NULL after process birth.
*/
return ((uint64_t)curthread->t_procp->p_cred->cr_gid);
+#else
+ return ((uint64_t)curthread->td_ucred->cr_gid);
+#endif
case DIF_VAR_ERRNO: {
#ifdef illumos
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
index e3b6581..7bf9de2 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -132,6 +132,9 @@
* distinguish between the operation failing, and
* deserialization failing.
*/
+#ifdef __FreeBSD__
+#include "opt_kstack_pages.h"
+#endif
#include <sys/types.h>
#include <sys/param.h>
@@ -6491,10 +6494,22 @@ static void zfs_shutdown(void *, int);
static eventhandler_tag zfs_shutdown_event_tag;
+#ifdef __FreeBSD__
+#define ZFS_MIN_KSTACK_PAGES 4
+#endif
+
int
zfs__init(void)
{
+#ifdef __FreeBSD__
+#if KSTACK_PAGES < ZFS_MIN_KSTACK_PAGES
+ printf("ZFS NOTICE: KSTACK_PAGES is %d which could result in stack "
+ "overflow panic!\nPlease consider adding "
+ "'options KSTACK_PAGES=%d' to your kernel config\n", KSTACK_PAGES,
+ ZFS_MIN_KSTACK_PAGES);
+#endif
+#endif
zfs_root_token = root_mount_hold("ZFS");
mutex_init(&zfs_share_lock, NULL, MUTEX_DEFAULT, NULL);
diff --git a/sys/cddl/dev/fbt/aarch64/fbt_isa.c b/sys/cddl/dev/fbt/aarch64/fbt_isa.c
index 94de1e8..627fdf9 100644
--- a/sys/cddl/dev/fbt/aarch64/fbt_isa.c
+++ b/sys/cddl/dev/fbt/aarch64/fbt_isa.c
@@ -58,7 +58,6 @@ fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
- fbt->fbtp_invop_cnt++;
cpu->cpu_dtrace_caller = addr;
dtrace_probe(fbt->fbtp_id, frame->tf_x[0],
diff --git a/sys/cddl/dev/fbt/arm/fbt_isa.c b/sys/cddl/dev/fbt/arm/fbt_isa.c
index 83c28b8..c02c1ec 100644
--- a/sys/cddl/dev/fbt/arm/fbt_isa.c
+++ b/sys/cddl/dev/fbt/arm/fbt_isa.c
@@ -56,7 +56,6 @@ fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
- fbt->fbtp_invop_cnt++;
cpu->cpu_dtrace_caller = addr;
/* TODO: Need 5th parameter from stack */
diff --git a/sys/cddl/dev/fbt/fbt.h b/sys/cddl/dev/fbt/fbt.h
index 6438583..ea245cb 100644
--- a/sys/cddl/dev/fbt/fbt.h
+++ b/sys/cddl/dev/fbt/fbt.h
@@ -45,8 +45,6 @@ typedef struct fbt_probe {
const char *fbtp_name;
modctl_t *fbtp_ctl;
int fbtp_loadcnt;
- int fbtp_primary;
- int fbtp_invop_cnt;
int fbtp_symindx;
struct fbt_probe *fbtp_next;
} fbt_probe_t;
diff --git a/sys/cddl/dev/fbt/powerpc/fbt_isa.c b/sys/cddl/dev/fbt/powerpc/fbt_isa.c
index 0e131bf..d55d553 100644
--- a/sys/cddl/dev/fbt/powerpc/fbt_isa.c
+++ b/sys/cddl/dev/fbt/powerpc/fbt_isa.c
@@ -60,7 +60,6 @@ fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
- fbt->fbtp_invop_cnt++;
if (fbt->fbtp_roffset == 0) {
cpu->cpu_dtrace_caller = addr;
diff --git a/sys/cddl/dev/fbt/x86/fbt_isa.c b/sys/cddl/dev/fbt/x86/fbt_isa.c
index 160c9b3..4514b34 100644
--- a/sys/cddl/dev/fbt/x86/fbt_isa.c
+++ b/sys/cddl/dev/fbt/x86/fbt_isa.c
@@ -66,7 +66,6 @@ fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
- fbt->fbtp_invop_cnt++;
if (fbt->fbtp_roffset == 0) {
int i = 0;
/*
diff --git a/sys/compat/cloudabi/cloudabi_fd.c b/sys/compat/cloudabi/cloudabi_fd.c
index 8b72c19..f16d668 100644
--- a/sys/compat/cloudabi/cloudabi_fd.c
+++ b/sys/compat/cloudabi/cloudabi_fd.c
@@ -27,13 +27,65 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/capsicum.h>
#include <sys/filedesc.h>
#include <sys/proc.h>
+#include <sys/mman.h>
+#include <sys/socketvar.h>
#include <sys/syscallsubr.h>
#include <sys/sysproto.h>
+#include <sys/systm.h>
#include <sys/unistd.h>
+#include <sys/vnode.h>
#include <compat/cloudabi/cloudabi_proto.h>
+#include <compat/cloudabi/cloudabi_syscalldefs.h>
+#include <compat/cloudabi/cloudabi_util.h>
+
+/* Translation between CloudABI and Capsicum rights. */
+#define RIGHTS_MAPPINGS \
+ MAPPING(CLOUDABI_RIGHT_FD_DATASYNC, CAP_FSYNC) \
+ MAPPING(CLOUDABI_RIGHT_FD_READ, CAP_READ) \
+ MAPPING(CLOUDABI_RIGHT_FD_SEEK, CAP_SEEK) \
+ MAPPING(CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS, CAP_FCNTL) \
+ MAPPING(CLOUDABI_RIGHT_FD_SYNC, CAP_FSYNC) \
+ MAPPING(CLOUDABI_RIGHT_FD_TELL, CAP_SEEK_TELL) \
+ MAPPING(CLOUDABI_RIGHT_FD_WRITE, CAP_WRITE) \
+ MAPPING(CLOUDABI_RIGHT_FILE_ADVISE) \
+ MAPPING(CLOUDABI_RIGHT_FILE_ALLOCATE, CAP_WRITE) \
+ MAPPING(CLOUDABI_RIGHT_FILE_CREATE_DIRECTORY, CAP_MKDIRAT) \
+ MAPPING(CLOUDABI_RIGHT_FILE_CREATE_FILE, CAP_CREATE) \
+ MAPPING(CLOUDABI_RIGHT_FILE_CREATE_FIFO, CAP_MKFIFOAT) \
+ MAPPING(CLOUDABI_RIGHT_FILE_LINK_SOURCE, CAP_LOOKUP) \
+ MAPPING(CLOUDABI_RIGHT_FILE_LINK_TARGET, CAP_LINKAT) \
+ MAPPING(CLOUDABI_RIGHT_FILE_OPEN, CAP_LOOKUP) \
+ MAPPING(CLOUDABI_RIGHT_FILE_READDIR, CAP_READ) \
+ MAPPING(CLOUDABI_RIGHT_FILE_READLINK, CAP_LOOKUP) \
+ MAPPING(CLOUDABI_RIGHT_FILE_RENAME_SOURCE, CAP_RENAMEAT) \
+ MAPPING(CLOUDABI_RIGHT_FILE_RENAME_TARGET, CAP_LINKAT) \
+ MAPPING(CLOUDABI_RIGHT_FILE_STAT_FGET, CAP_FSTAT) \
+ MAPPING(CLOUDABI_RIGHT_FILE_STAT_FPUT_SIZE, CAP_FTRUNCATE) \
+ MAPPING(CLOUDABI_RIGHT_FILE_STAT_FPUT_TIMES, CAP_FUTIMES) \
+ MAPPING(CLOUDABI_RIGHT_FILE_STAT_GET, CAP_FSTATAT) \
+ MAPPING(CLOUDABI_RIGHT_FILE_STAT_PUT_TIMES, CAP_FUTIMESAT) \
+ MAPPING(CLOUDABI_RIGHT_FILE_SYMLINK, CAP_SYMLINKAT) \
+ MAPPING(CLOUDABI_RIGHT_FILE_UNLINK, CAP_UNLINKAT) \
+ MAPPING(CLOUDABI_RIGHT_MEM_MAP, CAP_MMAP) \
+ MAPPING(CLOUDABI_RIGHT_MEM_MAP_EXEC, CAP_MMAP_X) \
+ MAPPING(CLOUDABI_RIGHT_POLL_FD_READWRITE, CAP_EVENT) \
+ MAPPING(CLOUDABI_RIGHT_POLL_MODIFY, CAP_KQUEUE_CHANGE) \
+ MAPPING(CLOUDABI_RIGHT_POLL_PROC_TERMINATE, CAP_PDWAIT) \
+ MAPPING(CLOUDABI_RIGHT_POLL_WAIT, CAP_KQUEUE_EVENT) \
+ MAPPING(CLOUDABI_RIGHT_PROC_EXEC, CAP_FEXECVE) \
+ MAPPING(CLOUDABI_RIGHT_SOCK_ACCEPT, CAP_ACCEPT) \
+ MAPPING(CLOUDABI_RIGHT_SOCK_BIND_DIRECTORY, CAP_BINDAT) \
+ MAPPING(CLOUDABI_RIGHT_SOCK_BIND_SOCKET, CAP_BIND) \
+ MAPPING(CLOUDABI_RIGHT_SOCK_CONNECT_DIRECTORY, CAP_CONNECTAT) \
+ MAPPING(CLOUDABI_RIGHT_SOCK_CONNECT_SOCKET, CAP_CONNECT) \
+ MAPPING(CLOUDABI_RIGHT_SOCK_LISTEN, CAP_LISTEN) \
+ MAPPING(CLOUDABI_RIGHT_SOCK_SHUTDOWN, CAP_SHUTDOWN) \
+ MAPPING(CLOUDABI_RIGHT_SOCK_STAT_GET, CAP_GETPEERNAME, \
+ CAP_GETSOCKNAME, CAP_GETSOCKOPT)
int
cloudabi_sys_fd_close(struct thread *td, struct cloudabi_sys_fd_close_args *uap)
@@ -46,11 +98,19 @@ int
cloudabi_sys_fd_create1(struct thread *td,
struct cloudabi_sys_fd_create1_args *uap)
{
+ struct filecaps fcaps = {};
struct socket_args socket_args = {
.domain = AF_UNIX,
};
switch (uap->type) {
+ case CLOUDABI_FILETYPE_POLL:
+ cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_KQUEUE);
+ return (kern_kqueue(td, 0, &fcaps));
+ case CLOUDABI_FILETYPE_SHARED_MEMORY:
+ cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_FTRUNCATE,
+ CAP_MMAP_RWX);
+ return (kern_shm_open(td, SHM_ANON, O_RDWR, 0, &fcaps));
case CLOUDABI_FILETYPE_SOCKET_DGRAM:
socket_args.type = SOCK_DGRAM;
return (sys_socket(td, &socket_args));
@@ -69,10 +129,24 @@ int
cloudabi_sys_fd_create2(struct thread *td,
struct cloudabi_sys_fd_create2_args *uap)
{
+ struct filecaps fcaps1 = {}, fcaps2 = {};
int fds[2];
int error;
switch (uap->type) {
+ case CLOUDABI_FILETYPE_FIFO:
+ /*
+ * CloudABI pipes are unidirectional. Restrict rights on
+ * the pipe to simulate this.
+ */
+ cap_rights_init(&fcaps1.fc_rights, CAP_EVENT, CAP_FCNTL,
+ CAP_FSTAT, CAP_READ);
+ fcaps1.fc_fcntls = CAP_FCNTL_SETFL;
+ cap_rights_init(&fcaps2.fc_rights, CAP_EVENT, CAP_FCNTL,
+ CAP_FSTAT, CAP_WRITE);
+ fcaps2.fc_fcntls = CAP_FCNTL_SETFL;
+ error = kern_pipe(td, fds, 0, &fcaps1, &fcaps2);
+ break;
case CLOUDABI_FILETYPE_SOCKET_DGRAM:
error = kern_socketpair(td, AF_UNIX, SOCK_DGRAM, 0, fds);
break;
@@ -160,22 +234,314 @@ cloudabi_sys_fd_seek(struct thread *td, struct cloudabi_sys_fd_seek_args *uap)
return (sys_lseek(td, &lseek_args));
}
+/* Converts a file descriptor to a CloudABI file descriptor type. */
+cloudabi_filetype_t
+cloudabi_convert_filetype(const struct file *fp)
+{
+ struct socket *so;
+ struct vnode *vp;
+
+ switch (fp->f_type) {
+ case DTYPE_FIFO:
+ return (CLOUDABI_FILETYPE_FIFO);
+ case DTYPE_KQUEUE:
+ return (CLOUDABI_FILETYPE_POLL);
+ case DTYPE_PIPE:
+ return (CLOUDABI_FILETYPE_FIFO);
+ case DTYPE_PROCDESC:
+ return (CLOUDABI_FILETYPE_PROCESS);
+ case DTYPE_SHM:
+ return (CLOUDABI_FILETYPE_SHARED_MEMORY);
+ case DTYPE_SOCKET:
+ so = fp->f_data;
+ switch (so->so_type) {
+ case SOCK_DGRAM:
+ return (CLOUDABI_FILETYPE_SOCKET_DGRAM);
+ case SOCK_SEQPACKET:
+ return (CLOUDABI_FILETYPE_SOCKET_SEQPACKET);
+ case SOCK_STREAM:
+ return (CLOUDABI_FILETYPE_SOCKET_STREAM);
+ default:
+ return (CLOUDABI_FILETYPE_UNKNOWN);
+ }
+ case DTYPE_VNODE:
+ vp = fp->f_vnode;
+ switch (vp->v_type) {
+ case VBLK:
+ return (CLOUDABI_FILETYPE_BLOCK_DEVICE);
+ case VCHR:
+ return (CLOUDABI_FILETYPE_CHARACTER_DEVICE);
+ case VDIR:
+ return (CLOUDABI_FILETYPE_DIRECTORY);
+ case VFIFO:
+ return (CLOUDABI_FILETYPE_FIFO);
+ case VLNK:
+ return (CLOUDABI_FILETYPE_SYMBOLIC_LINK);
+ case VREG:
+ return (CLOUDABI_FILETYPE_REGULAR_FILE);
+ case VSOCK:
+ return (CLOUDABI_FILETYPE_SOCKET_STREAM);
+ default:
+ return (CLOUDABI_FILETYPE_UNKNOWN);
+ }
+ default:
+ return (CLOUDABI_FILETYPE_UNKNOWN);
+ }
+}
+
+/* Removes rights that conflict with the file descriptor type. */
+void
+cloudabi_remove_conflicting_rights(cloudabi_filetype_t filetype,
+ cloudabi_rights_t *base, cloudabi_rights_t *inheriting)
+{
+
+ /*
+ * CloudABI has a small number of additional rights bits to
+ * disambiguate between multiple purposes. Remove the bits that
+ * don't apply to the type of the file descriptor.
+ *
+ * As file descriptor access modes (O_ACCMODE) has been fully
+ * replaced by rights bits, CloudABI distinguishes between
+ * rights that apply to the file descriptor itself (base) versus
+ * rights of new file descriptors derived from them
+ * (inheriting). The code below approximates the pair by
+ * decomposing depending on the file descriptor type.
+ *
+ * We need to be somewhat accurate about which actions can
+ * actually be performed on the file descriptor, as functions
+ * like fcntl(fd, F_GETFL) are emulated on top of this.
+ */
+ switch (filetype) {
+ case CLOUDABI_FILETYPE_DIRECTORY:
+ *base &= CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS |
+ CLOUDABI_RIGHT_FD_SYNC | CLOUDABI_RIGHT_FILE_ADVISE |
+ CLOUDABI_RIGHT_FILE_CREATE_DIRECTORY |
+ CLOUDABI_RIGHT_FILE_CREATE_FILE |
+ CLOUDABI_RIGHT_FILE_CREATE_FIFO |
+ CLOUDABI_RIGHT_FILE_LINK_SOURCE |
+ CLOUDABI_RIGHT_FILE_LINK_TARGET |
+ CLOUDABI_RIGHT_FILE_OPEN |
+ CLOUDABI_RIGHT_FILE_READDIR |
+ CLOUDABI_RIGHT_FILE_READLINK |
+ CLOUDABI_RIGHT_FILE_RENAME_SOURCE |
+ CLOUDABI_RIGHT_FILE_RENAME_TARGET |
+ CLOUDABI_RIGHT_FILE_STAT_FGET |
+ CLOUDABI_RIGHT_FILE_STAT_FPUT_TIMES |
+ CLOUDABI_RIGHT_FILE_STAT_GET |
+ CLOUDABI_RIGHT_FILE_STAT_PUT_TIMES |
+ CLOUDABI_RIGHT_FILE_SYMLINK |
+ CLOUDABI_RIGHT_FILE_UNLINK |
+ CLOUDABI_RIGHT_POLL_FD_READWRITE |
+ CLOUDABI_RIGHT_SOCK_BIND_DIRECTORY |
+ CLOUDABI_RIGHT_SOCK_CONNECT_DIRECTORY;
+ *inheriting &= CLOUDABI_RIGHT_FD_DATASYNC |
+ CLOUDABI_RIGHT_FD_READ |
+ CLOUDABI_RIGHT_FD_SEEK |
+ CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS |
+ CLOUDABI_RIGHT_FD_SYNC |
+ CLOUDABI_RIGHT_FD_TELL |
+ CLOUDABI_RIGHT_FD_WRITE |
+ CLOUDABI_RIGHT_FILE_ADVISE |
+ CLOUDABI_RIGHT_FILE_ALLOCATE |
+ CLOUDABI_RIGHT_FILE_CREATE_DIRECTORY |
+ CLOUDABI_RIGHT_FILE_CREATE_FILE |
+ CLOUDABI_RIGHT_FILE_CREATE_FIFO |
+ CLOUDABI_RIGHT_FILE_LINK_SOURCE |
+ CLOUDABI_RIGHT_FILE_LINK_TARGET |
+ CLOUDABI_RIGHT_FILE_OPEN |
+ CLOUDABI_RIGHT_FILE_READDIR |
+ CLOUDABI_RIGHT_FILE_READLINK |
+ CLOUDABI_RIGHT_FILE_RENAME_SOURCE |
+ CLOUDABI_RIGHT_FILE_RENAME_TARGET |
+ CLOUDABI_RIGHT_FILE_STAT_FGET |
+ CLOUDABI_RIGHT_FILE_STAT_FPUT_SIZE |
+ CLOUDABI_RIGHT_FILE_STAT_FPUT_TIMES |
+ CLOUDABI_RIGHT_FILE_STAT_GET |
+ CLOUDABI_RIGHT_FILE_STAT_PUT_TIMES |
+ CLOUDABI_RIGHT_FILE_SYMLINK |
+ CLOUDABI_RIGHT_FILE_UNLINK |
+ CLOUDABI_RIGHT_MEM_MAP |
+ CLOUDABI_RIGHT_MEM_MAP_EXEC |
+ CLOUDABI_RIGHT_POLL_FD_READWRITE |
+ CLOUDABI_RIGHT_PROC_EXEC |
+ CLOUDABI_RIGHT_SOCK_BIND_DIRECTORY |
+ CLOUDABI_RIGHT_SOCK_CONNECT_DIRECTORY;
+ break;
+ case CLOUDABI_FILETYPE_FIFO:
+ *base &= CLOUDABI_RIGHT_FD_READ |
+ CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS |
+ CLOUDABI_RIGHT_FD_WRITE |
+ CLOUDABI_RIGHT_FILE_STAT_FGET |
+ CLOUDABI_RIGHT_POLL_FD_READWRITE;
+ *inheriting = 0;
+ break;
+ case CLOUDABI_FILETYPE_POLL:
+ *base &= ~CLOUDABI_RIGHT_FILE_ADVISE;
+ *inheriting = 0;
+ break;
+ case CLOUDABI_FILETYPE_PROCESS:
+ *base &= ~CLOUDABI_RIGHT_FILE_ADVISE;
+ *inheriting = 0;
+ break;
+ case CLOUDABI_FILETYPE_REGULAR_FILE:
+ *base &= CLOUDABI_RIGHT_FD_DATASYNC |
+ CLOUDABI_RIGHT_FD_READ |
+ CLOUDABI_RIGHT_FD_SEEK |
+ CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS |
+ CLOUDABI_RIGHT_FD_SYNC |
+ CLOUDABI_RIGHT_FD_TELL |
+ CLOUDABI_RIGHT_FD_WRITE |
+ CLOUDABI_RIGHT_FILE_ADVISE |
+ CLOUDABI_RIGHT_FILE_ALLOCATE |
+ CLOUDABI_RIGHT_FILE_STAT_FGET |
+ CLOUDABI_RIGHT_FILE_STAT_FPUT_SIZE |
+ CLOUDABI_RIGHT_FILE_STAT_FPUT_TIMES |
+ CLOUDABI_RIGHT_MEM_MAP |
+ CLOUDABI_RIGHT_MEM_MAP_EXEC |
+ CLOUDABI_RIGHT_POLL_FD_READWRITE |
+ CLOUDABI_RIGHT_PROC_EXEC;
+ *inheriting = 0;
+ break;
+ case CLOUDABI_FILETYPE_SHARED_MEMORY:
+ *base &= ~(CLOUDABI_RIGHT_FD_SEEK |
+ CLOUDABI_RIGHT_FD_TELL |
+ CLOUDABI_RIGHT_FILE_ADVISE |
+ CLOUDABI_RIGHT_FILE_ALLOCATE |
+ CLOUDABI_RIGHT_FILE_READDIR);
+ *inheriting = 0;
+ break;
+ case CLOUDABI_FILETYPE_SOCKET_DGRAM:
+ case CLOUDABI_FILETYPE_SOCKET_SEQPACKET:
+ case CLOUDABI_FILETYPE_SOCKET_STREAM:
+ *base &= CLOUDABI_RIGHT_FD_READ |
+ CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS |
+ CLOUDABI_RIGHT_FD_WRITE |
+ CLOUDABI_RIGHT_FILE_STAT_FGET |
+ CLOUDABI_RIGHT_POLL_FD_READWRITE |
+ CLOUDABI_RIGHT_SOCK_ACCEPT |
+ CLOUDABI_RIGHT_SOCK_BIND_SOCKET |
+ CLOUDABI_RIGHT_SOCK_CONNECT_SOCKET |
+ CLOUDABI_RIGHT_SOCK_LISTEN |
+ CLOUDABI_RIGHT_SOCK_SHUTDOWN |
+ CLOUDABI_RIGHT_SOCK_STAT_GET;
+ break;
+ default:
+ *inheriting = 0;
+ break;
+ }
+}
+
+/* Converts FreeBSD's Capsicum rights to CloudABI's set of rights. */
+static void
+convert_capabilities(const cap_rights_t *capabilities,
+ cloudabi_filetype_t filetype, cloudabi_rights_t *base,
+ cloudabi_rights_t *inheriting)
+{
+ cloudabi_rights_t rights;
+
+ /* Convert FreeBSD bits to CloudABI bits. */
+ rights = 0;
+#define MAPPING(cloudabi, ...) do { \
+ if (cap_rights_is_set(capabilities, ##__VA_ARGS__)) \
+ rights |= (cloudabi); \
+} while (0);
+ RIGHTS_MAPPINGS
+#undef MAPPING
+
+ *base = rights;
+ *inheriting = rights;
+ cloudabi_remove_conflicting_rights(filetype, base, inheriting);
+}
+
int
cloudabi_sys_fd_stat_get(struct thread *td,
struct cloudabi_sys_fd_stat_get_args *uap)
{
+ cloudabi_fdstat_t fsb = {};
+ struct filedesc *fdp;
+ struct file *fp;
+ seq_t seq;
+ cap_rights_t rights;
+ int error, oflags;
+ bool modified;
+
+ /* Obtain file descriptor properties. */
+ fdp = td->td_proc->p_fd;
+ do {
+ error = fget_unlocked(fdp, uap->fd, cap_rights_init(&rights),
+ &fp, &seq);
+ if (error != 0)
+ return (error);
+ if (fp->f_ops == &badfileops) {
+ fdrop(fp, td);
+ return (EBADF);
+ }
- /* Not implemented. */
- return (ENOSYS);
+ rights = *cap_rights(fdp, uap->fd);
+ oflags = OFLAGS(fp->f_flag);
+ fsb.fs_filetype = cloudabi_convert_filetype(fp);
+
+ modified = fd_modified(fdp, uap->fd, seq);
+ fdrop(fp, td);
+ } while (modified);
+
+ /* Convert file descriptor flags. */
+ if (oflags & O_APPEND)
+ fsb.fs_flags |= CLOUDABI_FDFLAG_APPEND;
+ if (oflags & O_NONBLOCK)
+ fsb.fs_flags |= CLOUDABI_FDFLAG_NONBLOCK;
+ if (oflags & O_SYNC)
+ fsb.fs_flags |= CLOUDABI_FDFLAG_SYNC;
+
+ /* Convert capabilities to CloudABI rights. */
+ convert_capabilities(&rights, fsb.fs_filetype,
+ &fsb.fs_rights_base, &fsb.fs_rights_inheriting);
+ return (copyout(&fsb, (void *)uap->buf, sizeof(fsb)));
+}
+
+/* Converts CloudABI rights to a set of Capsicum capabilities. */
+int
+cloudabi_convert_rights(cloudabi_rights_t in, cap_rights_t *out)
+{
+
+ cap_rights_init(out);
+#define MAPPING(cloudabi, ...) do { \
+ if (in & (cloudabi)) { \
+ cap_rights_set(out, ##__VA_ARGS__); \
+ in &= ~(cloudabi); \
+ } \
+} while (0);
+ RIGHTS_MAPPINGS
+#undef MAPPING
+ if (in != 0)
+ return (ENOTCAPABLE);
+ return (0);
}
int
cloudabi_sys_fd_stat_put(struct thread *td,
struct cloudabi_sys_fd_stat_put_args *uap)
{
+ cloudabi_fdstat_t fsb;
+ int error, oflags;
- /* Not implemented. */
- return (ENOSYS);
+ error = copyin(uap->buf, &fsb, sizeof(fsb));
+ if (error != 0)
+ return (error);
+
+ if (uap->flags == CLOUDABI_FDSTAT_FLAGS) {
+ /* Convert flags. */
+ oflags = 0;
+ if (fsb.fs_flags & CLOUDABI_FDFLAG_APPEND)
+ oflags |= O_APPEND;
+ if (fsb.fs_flags & CLOUDABI_FDFLAG_NONBLOCK)
+ oflags |= O_NONBLOCK;
+ if (fsb.fs_flags & (CLOUDABI_FDFLAG_SYNC |
+ CLOUDABI_FDFLAG_DSYNC | CLOUDABI_FDFLAG_RSYNC))
+ oflags |= O_SYNC;
+ return (kern_fcntl(td, uap->fd, F_SETFL, oflags));
+ }
+ return (EINVAL);
}
int
diff --git a/sys/compat/cloudabi/cloudabi_file.c b/sys/compat/cloudabi/cloudabi_file.c
index b508517..8938252 100644
--- a/sys/compat/cloudabi/cloudabi_file.c
+++ b/sys/compat/cloudabi/cloudabi_file.c
@@ -27,14 +27,23 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/capsicum.h>
+#include <sys/dirent.h>
#include <sys/fcntl.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/namei.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
#include <sys/syscallsubr.h>
+#include <sys/uio.h>
+#include <sys/vnode.h>
#include <compat/cloudabi/cloudabi_proto.h>
#include <compat/cloudabi/cloudabi_syscalldefs.h>
+#include <compat/cloudabi/cloudabi_util.h>
+
+#include <security/mac/mac_framework.h>
static MALLOC_DEFINE(M_CLOUDABI_PATH, "cloudabipath", "CloudABI pathnames");
@@ -133,9 +142,31 @@ int
cloudabi_sys_file_create(struct thread *td,
struct cloudabi_sys_file_create_args *uap)
{
+ char *path;
+ int error;
+
+ error = copyin_path(uap->path, uap->pathlen, &path);
+ if (error != 0)
+ return (error);
- /* Not implemented. */
- return (ENOSYS);
+ /*
+ * CloudABI processes cannot interact with UNIX credentials and
+ * permissions. Depend on the umask that is set prior to
+ * execution to restrict the file permissions.
+ */
+ switch (uap->type) {
+ case CLOUDABI_FILETYPE_DIRECTORY:
+ error = kern_mkdirat(td, uap->fd, path, UIO_SYSSPACE, 0777);
+ break;
+ case CLOUDABI_FILETYPE_FIFO:
+ error = kern_mkfifoat(td, uap->fd, path, UIO_SYSSPACE, 0666);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ cloudabi_freestr(path);
+ return (error);
}
int
@@ -166,18 +197,304 @@ int
cloudabi_sys_file_open(struct thread *td,
struct cloudabi_sys_file_open_args *uap)
{
+ cloudabi_fdstat_t fds;
+ cap_rights_t rights;
+ struct filecaps fcaps = {};
+ struct nameidata nd;
+ struct file *fp;
+ struct vnode *vp;
+ char *path;
+ int error, fd, fflags;
+ bool read, write;
+
+ error = copyin(uap->fds, &fds, sizeof(fds));
+ if (error != 0)
+ return (error);
+
+ /* All the requested rights should be set on the descriptor. */
+ error = cloudabi_convert_rights(
+ fds.fs_rights_base | fds.fs_rights_inheriting, &rights);
+ if (error != 0)
+ return (error);
+ cap_rights_set(&rights, CAP_LOOKUP);
+
+ /* Convert rights to corresponding access mode. */
+ read = (fds.fs_rights_base & (CLOUDABI_RIGHT_FD_READ |
+ CLOUDABI_RIGHT_FILE_READDIR | CLOUDABI_RIGHT_MEM_MAP_EXEC)) != 0;
+ write = (fds.fs_rights_base & (CLOUDABI_RIGHT_FD_DATASYNC |
+ CLOUDABI_RIGHT_FD_WRITE | CLOUDABI_RIGHT_FILE_ALLOCATE |
+ CLOUDABI_RIGHT_FILE_STAT_FPUT_SIZE)) != 0;
+ fflags = read ? write ? FREAD | FWRITE : FREAD : FWRITE;
+
+ /* Convert open flags. */
+ if ((uap->oflags & CLOUDABI_O_CREAT) != 0) {
+ fflags |= O_CREAT;
+ cap_rights_set(&rights, CAP_CREATE);
+ }
+ if ((uap->oflags & CLOUDABI_O_DIRECTORY) != 0)
+ fflags |= O_DIRECTORY;
+ if ((uap->oflags & CLOUDABI_O_EXCL) != 0)
+ fflags |= O_EXCL;
+ if ((uap->oflags & CLOUDABI_O_TRUNC) != 0) {
+ fflags |= O_TRUNC;
+ cap_rights_set(&rights, CAP_FTRUNCATE);
+ }
+ if ((fds.fs_flags & CLOUDABI_FDFLAG_APPEND) != 0)
+ fflags |= O_APPEND;
+ if ((fds.fs_flags & CLOUDABI_FDFLAG_NONBLOCK) != 0)
+ fflags |= O_NONBLOCK;
+ if ((fds.fs_flags & (CLOUDABI_FDFLAG_SYNC | CLOUDABI_FDFLAG_DSYNC |
+ CLOUDABI_FDFLAG_RSYNC)) != 0) {
+ fflags |= O_SYNC;
+ cap_rights_set(&rights, CAP_FSYNC);
+ }
+ if ((uap->fd & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) == 0)
+ fflags |= O_NOFOLLOW;
+ if (write && (fflags & (O_APPEND | O_TRUNC)) == 0)
+ cap_rights_set(&rights, CAP_SEEK);
+
+ /* Allocate new file descriptor. */
+ error = falloc_noinstall(td, &fp);
+ if (error != 0)
+ return (error);
+ fp->f_flag = fflags & FMASK;
+
+ /* Open path. */
+ error = copyin_path(uap->path, uap->pathlen, &path);
+ if (error != 0) {
+ fdrop(fp, td);
+ return (error);
+ }
+ NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, uap->fd,
+ &rights, td);
+ error = vn_open(&nd, &fflags, 0777 & ~td->td_proc->p_fd->fd_cmask, fp);
+ cloudabi_freestr(path);
+ if (error != 0) {
+ /* Custom operations provided. */
+ if (error == ENXIO && fp->f_ops != &badfileops)
+ goto success;
+
+ /*
+ * POSIX compliance: return ELOOP in case openat() is
+ * called on a symbolic link and O_NOFOLLOW is set.
+ */
+ if (error == EMLINK)
+ error = ELOOP;
+ fdrop(fp, td);
+ return (error);
+ }
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ filecaps_free(&nd.ni_filecaps);
+ fp->f_vnode = vp = nd.ni_vp;
+
+ /* Install vnode operations if no custom operations are provided. */
+ if (fp->f_ops == &badfileops) {
+ fp->f_seqcount = 1;
+ finit(fp, (fflags & FMASK) | (fp->f_flag & FHASLOCK),
+ DTYPE_VNODE, vp, &vnops);
+ }
+ VOP_UNLOCK(vp, 0);
+
+ /* Truncate file. */
+ if (fflags & O_TRUNC) {
+ error = fo_truncate(fp, 0, td->td_ucred, td);
+ if (error != 0) {
+ fdrop(fp, td);
+ return (error);
+ }
+ }
+
+success:
+ /* Determine which Capsicum rights to set on the file descriptor. */
+ cloudabi_remove_conflicting_rights(cloudabi_convert_filetype(fp),
+ &fds.fs_rights_base, &fds.fs_rights_inheriting);
+ cloudabi_convert_rights(fds.fs_rights_base | fds.fs_rights_inheriting,
+ &fcaps.fc_rights);
+ if (cap_rights_is_set(&fcaps.fc_rights))
+ fcaps.fc_fcntls = CAP_FCNTL_SETFL;
+
+ error = finstall(td, fp, &fd, fflags, &fcaps);
+ fdrop(fp, td);
+ if (error != 0)
+ return (error);
+ td->td_retval[0] = fd;
+ return (0);
+}
+
+/* Converts a FreeBSD directory entry structure and writes it to userspace. */
+static int
+write_dirent(struct dirent *bde, cloudabi_dircookie_t cookie, struct uio *uio)
+{
+ cloudabi_dirent_t cde = {
+ .d_next = cookie,
+ .d_ino = bde->d_fileno,
+ .d_namlen = bde->d_namlen,
+ };
+ size_t len;
+ int error;
+
+ /* Convert file type. */
+ switch (bde->d_type) {
+ case DT_BLK:
+ cde.d_type = CLOUDABI_FILETYPE_BLOCK_DEVICE;
+ break;
+ case DT_CHR:
+ cde.d_type = CLOUDABI_FILETYPE_CHARACTER_DEVICE;
+ break;
+ case DT_DIR:
+ cde.d_type = CLOUDABI_FILETYPE_DIRECTORY;
+ break;
+ case DT_FIFO:
+ cde.d_type = CLOUDABI_FILETYPE_FIFO;
+ break;
+ case DT_LNK:
+ cde.d_type = CLOUDABI_FILETYPE_SYMBOLIC_LINK;
+ break;
+ case DT_REG:
+ cde.d_type = CLOUDABI_FILETYPE_REGULAR_FILE;
+ break;
+ case DT_SOCK:
+ /* The exact socket type cannot be derived. */
+ cde.d_type = CLOUDABI_FILETYPE_SOCKET_STREAM;
+ break;
+ default:
+ cde.d_type = CLOUDABI_FILETYPE_UNKNOWN;
+ break;
+ }
+
+ /* Write directory entry structure. */
+ len = sizeof(cde) < uio->uio_resid ? sizeof(cde) : uio->uio_resid;
+ error = uiomove(&cde, len, uio);
+ if (error != 0)
+ return (error);
- /* Not implemented. */
- return (ENOSYS);
+ /* Write filename. */
+ len = bde->d_namlen < uio->uio_resid ? bde->d_namlen : uio->uio_resid;
+ return (uiomove(bde->d_name, len, uio));
}
int
cloudabi_sys_file_readdir(struct thread *td,
struct cloudabi_sys_file_readdir_args *uap)
{
+ struct iovec iov = {
+ .iov_base = uap->buf,
+ .iov_len = uap->nbyte
+ };
+ struct uio uio = {
+ .uio_iov = &iov,
+ .uio_iovcnt = 1,
+ .uio_resid = iov.iov_len,
+ .uio_segflg = UIO_USERSPACE,
+ .uio_rw = UIO_READ,
+ .uio_td = td
+ };
+ struct file *fp;
+ struct vnode *vp;
+ void *readbuf;
+ cap_rights_t rights;
+ cloudabi_dircookie_t offset;
+ int error;
+
+ /* Obtain directory vnode. */
+ error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp);
+ if (error != 0) {
+ if (error == EINVAL)
+ return (ENOTDIR);
+ return (error);
+ }
+ if ((fp->f_flag & FREAD) == 0) {
+ fdrop(fp, td);
+ return (EBADF);
+ }
- /* Not implemented. */
- return (ENOSYS);
+ /*
+ * Call VOP_READDIR() and convert resulting data until the user
+ * provided buffer is filled.
+ */
+ readbuf = malloc(MAXBSIZE, M_TEMP, M_WAITOK);
+ offset = uap->cookie;
+ vp = fp->f_vnode;
+ while (uio.uio_resid > 0) {
+ struct iovec readiov = {
+ .iov_base = readbuf,
+ .iov_len = MAXBSIZE
+ };
+ struct uio readuio = {
+ .uio_iov = &readiov,
+ .uio_iovcnt = 1,
+ .uio_rw = UIO_READ,
+ .uio_segflg = UIO_SYSSPACE,
+ .uio_td = td,
+ .uio_resid = MAXBSIZE,
+ .uio_offset = offset
+ };
+ struct dirent *bde;
+ unsigned long *cookies, *cookie;
+ size_t readbuflen;
+ int eof, ncookies;
+
+ /* Validate file type. */
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ if (vp->v_type != VDIR) {
+ VOP_UNLOCK(vp, 0);
+ error = ENOTDIR;
+ goto done;
+ }
+#ifdef MAC
+ error = mac_vnode_check_readdir(td->td_ucred, vp);
+ if (error != 0) {
+ VOP_UNLOCK(vp, 0);
+ goto done;
+ }
+#endif /* MAC */
+
+ /* Read new directory entries. */
+ cookies = NULL;
+ ncookies = 0;
+ error = VOP_READDIR(vp, &readuio, fp->f_cred, &eof,
+ &ncookies, &cookies);
+ VOP_UNLOCK(vp, 0);
+ if (error != 0)
+ goto done;
+
+ /* Convert entries to CloudABI's format. */
+ readbuflen = MAXBSIZE - readuio.uio_resid;
+ bde = readbuf;
+ cookie = cookies;
+ while (readbuflen >= offsetof(struct dirent, d_name) &&
+ uio.uio_resid > 0 && ncookies > 0) {
+ /* Ensure that the returned offset always increases. */
+ if (readbuflen >= bde->d_reclen && bde->d_fileno != 0 &&
+ *cookie > offset) {
+ error = write_dirent(bde, *cookie, &uio);
+ if (error != 0) {
+ free(cookies, M_TEMP);
+ goto done;
+ }
+ }
+
+ if (offset < *cookie)
+ offset = *cookie;
+ ++cookie;
+ --ncookies;
+ readbuflen -= bde->d_reclen;
+ bde = (struct dirent *)((char *)bde + bde->d_reclen);
+ }
+ free(cookies, M_TEMP);
+ if (eof)
+ break;
+ }
+
+done:
+ fdrop(fp, td);
+ free(readbuf, M_TEMP);
+ if (error != 0)
+ return (error);
+
+ /* Return number of bytes copied to userspace. */
+ td->td_retval[0] = uap->nbyte - uio.uio_resid;
+ return (0);
}
int
@@ -220,40 +537,185 @@ cloudabi_sys_file_rename(struct thread *td,
return (error);
}
+/* Converts a FreeBSD stat structure to a CloudABI stat structure. */
+static void
+convert_stat(const struct stat *sb, cloudabi_filestat_t *csb)
+{
+ cloudabi_filestat_t res = {
+ .st_dev = sb->st_dev,
+ .st_ino = sb->st_ino,
+ .st_nlink = sb->st_nlink,
+ .st_size = sb->st_size,
+ };
+
+ cloudabi_convert_timespec(&sb->st_atim, &res.st_atim);
+ cloudabi_convert_timespec(&sb->st_mtim, &res.st_mtim);
+ cloudabi_convert_timespec(&sb->st_ctim, &res.st_ctim);
+ *csb = res;
+}
+
int
cloudabi_sys_file_stat_fget(struct thread *td,
struct cloudabi_sys_file_stat_fget_args *uap)
{
+ struct stat sb;
+ cloudabi_filestat_t csb;
+ struct file *fp;
+ cap_rights_t rights;
+ cloudabi_filetype_t filetype;
+ int error;
+
+ /* Fetch file descriptor attributes. */
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FSTAT), &fp);
+ if (error != 0)
+ return (error);
+ error = fo_stat(fp, &sb, td->td_ucred, td);
+ if (error != 0) {
+ fdrop(fp, td);
+ return (error);
+ }
+ filetype = cloudabi_convert_filetype(fp);
+ fdrop(fp, td);
+
+ /* Convert attributes to CloudABI's format. */
+ convert_stat(&sb, &csb);
+ csb.st_filetype = filetype;
+ return (copyout(&csb, uap->buf, sizeof(csb)));
+}
+
+/* Converts timestamps to arguments to futimens() and utimensat(). */
+static void
+convert_utimens_arguments(const cloudabi_filestat_t *fs,
+ cloudabi_fsflags_t flags, struct timespec *ts)
+{
+
+ if ((flags & CLOUDABI_FILESTAT_ATIM_NOW) != 0) {
+ ts[0].tv_nsec = UTIME_NOW;
+ } else if ((flags & CLOUDABI_FILESTAT_ATIM) != 0) {
+ ts[0].tv_sec = fs->st_atim / 1000000000;
+ ts[0].tv_nsec = fs->st_atim % 1000000000;
+ } else {
+ ts[0].tv_nsec = UTIME_OMIT;
+ }
- /* Not implemented. */
- return (ENOSYS);
+ if ((flags & CLOUDABI_FILESTAT_MTIM_NOW) != 0) {
+ ts[1].tv_nsec = UTIME_NOW;
+ } else if ((flags & CLOUDABI_FILESTAT_MTIM) != 0) {
+ ts[1].tv_sec = fs->st_mtim / 1000000000;
+ ts[1].tv_nsec = fs->st_mtim % 1000000000;
+ } else {
+ ts[1].tv_nsec = UTIME_OMIT;
+ }
}
int
cloudabi_sys_file_stat_fput(struct thread *td,
struct cloudabi_sys_file_stat_fput_args *uap)
{
+ cloudabi_filestat_t fs;
+ struct timespec ts[2];
+ int error;
+
+ error = copyin(uap->buf, &fs, sizeof(fs));
+ if (error != 0)
+ return (error);
- /* Not implemented. */
- return (ENOSYS);
+ /*
+ * Only support truncation and timestamp modification separately
+ * for now, to prevent unnecessary code duplication.
+ */
+ if ((uap->flags & CLOUDABI_FILESTAT_SIZE) != 0) {
+ /* Call into kern_ftruncate() for file truncation. */
+ if ((uap->flags & ~CLOUDABI_FILESTAT_SIZE) != 0)
+ return (EINVAL);
+ return (kern_ftruncate(td, uap->fd, fs.st_size));
+ } else if ((uap->flags & (CLOUDABI_FILESTAT_ATIM |
+ CLOUDABI_FILESTAT_ATIM_NOW | CLOUDABI_FILESTAT_MTIM |
+ CLOUDABI_FILESTAT_MTIM_NOW)) != 0) {
+ /* Call into kern_futimens() for timestamp modification. */
+ if ((uap->flags & ~(CLOUDABI_FILESTAT_ATIM |
+ CLOUDABI_FILESTAT_ATIM_NOW | CLOUDABI_FILESTAT_MTIM |
+ CLOUDABI_FILESTAT_MTIM_NOW)) != 0)
+ return (EINVAL);
+ convert_utimens_arguments(&fs, uap->flags, ts);
+ return (kern_futimens(td, uap->fd, ts, UIO_SYSSPACE));
+ }
+ return (EINVAL);
}
int
cloudabi_sys_file_stat_get(struct thread *td,
struct cloudabi_sys_file_stat_get_args *uap)
{
+ struct stat sb;
+ cloudabi_filestat_t csb;
+ char *path;
+ int error;
+
+ error = copyin_path(uap->path, uap->pathlen, &path);
+ if (error != 0)
+ return (error);
+
+ error = kern_statat(td,
+ (uap->fd & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0 ? 0 :
+ AT_SYMLINK_NOFOLLOW, uap->fd, path, UIO_SYSSPACE, &sb, NULL);
+ cloudabi_freestr(path);
+ if (error != 0)
+ return (error);
- /* Not implemented. */
- return (ENOSYS);
+ /* Convert results and return them. */
+ convert_stat(&sb, &csb);
+ if (S_ISBLK(sb.st_mode))
+ csb.st_filetype = CLOUDABI_FILETYPE_BLOCK_DEVICE;
+ else if (S_ISCHR(sb.st_mode))
+ csb.st_filetype = CLOUDABI_FILETYPE_CHARACTER_DEVICE;
+ else if (S_ISDIR(sb.st_mode))
+ csb.st_filetype = CLOUDABI_FILETYPE_DIRECTORY;
+ else if (S_ISFIFO(sb.st_mode))
+ csb.st_filetype = CLOUDABI_FILETYPE_FIFO;
+ else if (S_ISREG(sb.st_mode))
+ csb.st_filetype = CLOUDABI_FILETYPE_REGULAR_FILE;
+ else if (S_ISSOCK(sb.st_mode)) {
+ /* Inaccurate, but the best that we can do. */
+ csb.st_filetype = CLOUDABI_FILETYPE_SOCKET_STREAM;
+ } else if (S_ISLNK(sb.st_mode))
+ csb.st_filetype = CLOUDABI_FILETYPE_SYMBOLIC_LINK;
+ else
+ csb.st_filetype = CLOUDABI_FILETYPE_UNKNOWN;
+ return (copyout(&csb, uap->buf, sizeof(csb)));
}
int
cloudabi_sys_file_stat_put(struct thread *td,
struct cloudabi_sys_file_stat_put_args *uap)
{
+ cloudabi_filestat_t fs;
+ struct timespec ts[2];
+ char *path;
+ int error;
+
+ /*
+ * Only support timestamp modification for now, as there is no
+ * truncateat().
+ */
+ if ((uap->flags & ~(CLOUDABI_FILESTAT_ATIM |
+ CLOUDABI_FILESTAT_ATIM_NOW | CLOUDABI_FILESTAT_MTIM |
+ CLOUDABI_FILESTAT_MTIM_NOW)) != 0)
+ return (EINVAL);
- /* Not implemented. */
- return (ENOSYS);
+ error = copyin(uap->buf, &fs, sizeof(fs));
+ if (error != 0)
+ return (error);
+ error = copyin_path(uap->path, uap->pathlen, &path);
+ if (error != 0)
+ return (error);
+
+ convert_utimens_arguments(&fs, uap->flags, ts);
+ error = kern_utimensat(td, uap->fd, path, UIO_SYSSPACE, ts,
+ UIO_SYSSPACE, (uap->fd & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0 ?
+ 0 : AT_SYMLINK_NOFOLLOW);
+ cloudabi_freestr(path);
+ return (error);
}
int
diff --git a/sys/compat/cloudabi/cloudabi_futex.c b/sys/compat/cloudabi/cloudabi_futex.c
index 8025090..aec2f33 100644
--- a/sys/compat/cloudabi/cloudabi_futex.c
+++ b/sys/compat/cloudabi/cloudabi_futex.c
@@ -35,13 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/sx.h>
#include <sys/systm.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-#include <vm/vm_extern.h>
-#include <vm/vm_map.h>
-#include <vm/vm_object.h>
+#include <sys/umtx.h>
#include <compat/cloudabi/cloudabi_proto.h>
#include <compat/cloudabi/cloudabi_syscalldefs.h>
@@ -105,13 +99,7 @@ struct futex_waiter;
/* Identifier of a location in memory. */
struct futex_address {
- /* For process-private objects: address space of the process. */
- struct vmspace * fa_vmspace;
- /* For process-shared objects: VM object containing the object. */
- struct vm_object * fa_vmobject;
-
- /* Memory address within address space or offset within VM object. */
- uintptr_t fa_offset;
+ struct umtx_key fa_key;
};
/* A set of waiting threads. */
@@ -225,61 +213,16 @@ static int
futex_address_create(struct futex_address *fa, struct thread *td,
const void *object, cloudabi_mflags_t scope)
{
- struct vmspace *vs;
- struct vm_object *vo;
- vm_map_t map;
- vm_map_entry_t entry;
- vm_pindex_t pindex;
- vm_prot_t prot;
- boolean_t wired;
- /*
- * Most of the time objects are stored in privately mapped
- * anonymous memory. For these objects we wouldn't need to look
- * up the corresponding VM object. The scope hint provided by
- * userspace allows us to skip the VM map lookup for the common
- * case.
- *
- * POSIX does permit enabling PTHREAD_PROCESS_SHARED on a lock
- * stored in a private mapping, at the cost of additional
- * performance overhead. Fall back to identifying the object by
- * virtual memory address if the mapping isn't shared.
- */
- vs = td->td_proc->p_vmspace;
+ KASSERT(td == curthread,
+ ("Can only create umtx keys for the current thread"));
switch (scope) {
- case CLOUDABI_MAP_SHARED:
- map = &vs->vm_map;
- if (vm_map_lookup(&map, (vm_offset_t)object,
- VM_PROT_COPY | VM_PROT_WRITE, &entry, &vo, &pindex, &prot,
- &wired) != KERN_SUCCESS)
- return (EFAULT);
-
- if (entry->inheritance == VM_INHERIT_SHARE) {
- /*
- * Address corresponds to a shared mapping.
- * Identify the address by its VM object.
- */
- fa->fa_vmspace = NULL;
- fa->fa_vmobject = vo;
- vm_object_reference(vo);
- fa->fa_offset = entry->offset - entry->start +
- (vm_offset_t)object;
- vm_map_lookup_done(map, entry);
- return (0);
- }
- vm_map_lookup_done(map, entry);
- /* FALLTHROUGH */
case CLOUDABI_MAP_PRIVATE:
- /*
- * Address corresponds to a private mapping. Never
- * identify the address by its VM object, as shadow
- * objects may get inserted if another thread forks.
- * Simply use the VM space instead.
- */
- fa->fa_vmspace = vs;
- fa->fa_vmobject = NULL;
- fa->fa_offset = (uintptr_t)object;
- return (0);
+ return (umtx_key_get(object, TYPE_FUTEX, THREAD_SHARE,
+ &fa->fa_key));
+ case CLOUDABI_MAP_SHARED:
+ return (umtx_key_get(object, TYPE_FUTEX, AUTO_SHARE,
+ &fa->fa_key));
default:
return (EINVAL);
}
@@ -289,8 +232,7 @@ static void
futex_address_free(struct futex_address *fa)
{
- if (fa->fa_vmobject != NULL)
- vm_object_deallocate(fa->fa_vmobject);
+ umtx_key_release(&fa->fa_key);
}
static bool
@@ -298,10 +240,7 @@ futex_address_match(const struct futex_address *fa1,
const struct futex_address *fa2)
{
- /* Either fa_vmspace or fa_vmobject is NULL. */
- return (fa1->fa_vmspace == fa2->fa_vmspace &&
- fa1->fa_vmobject == fa2->fa_vmobject &&
- fa1->fa_offset == fa2->fa_offset);
+ return (umtx_key_match(&fa1->fa_key, &fa2->fa_key));
}
/*
diff --git a/sys/compat/cloudabi/cloudabi_proc.c b/sys/compat/cloudabi/cloudabi_proc.c
index 1f4418f..22f199d 100644
--- a/sys/compat/cloudabi/cloudabi_proc.c
+++ b/sys/compat/cloudabi/cloudabi_proc.c
@@ -27,8 +27,11 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/capsicum.h>
+#include <sys/filedesc.h>
#include <sys/imgact.h>
#include <sys/lock.h>
+#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
@@ -67,10 +70,12 @@ int
cloudabi_sys_proc_fork(struct thread *td,
struct cloudabi_sys_proc_fork_args *uap)
{
+ struct filecaps fcaps = {};
struct proc *p2;
int error, fd;
- error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2, &fd, 0);
+ cap_rights_init(&fcaps.fc_rights, CAP_FSTAT, CAP_PDWAIT);
+ error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2, &fd, 0, &fcaps);
if (error != 0)
return (error);
/* Return the file descriptor to the parent process. */
@@ -129,3 +134,5 @@ cloudabi_sys_proc_raise(struct thread *td,
PROC_UNLOCK(p);
return (0);
}
+
+MODULE_VERSION(cloudabi, 1);
diff --git a/sys/compat/cloudabi/cloudabi_sock.c b/sys/compat/cloudabi/cloudabi_sock.c
index 877571c..1cfff92 100644
--- a/sys/compat/cloudabi/cloudabi_sock.c
+++ b/sys/compat/cloudabi/cloudabi_sock.c
@@ -27,14 +27,62 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/capsicum.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/protosw.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <sys/syscallsubr.h>
#include <sys/sysproto.h>
#include <sys/systm.h>
#include <sys/un.h>
+#include <net/vnet.h>
+
+#include <netinet/in.h>
+
#include <compat/cloudabi/cloudabi_proto.h>
#include <compat/cloudabi/cloudabi_syscalldefs.h>
+#include <compat/cloudabi/cloudabi_util.h>
+
+/* Converts FreeBSD's struct sockaddr to CloudABI's cloudabi_sockaddr_t. */
+void
+cloudabi_convert_sockaddr(const struct sockaddr *sa, socklen_t sal,
+ cloudabi_sockaddr_t *rsa)
+{
+ const struct sockaddr_in *sin;
+ const struct sockaddr_in6 *sin6;
+
+ /* Zero-sized socket address. */
+ if (sal < offsetof(struct sockaddr, sa_family) + sizeof(sa->sa_family))
+ return;
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (sal < sizeof(struct sockaddr_in))
+ return;
+ sin = (const struct sockaddr_in *)sa;
+ rsa->sa_family = CLOUDABI_AF_INET;
+ memcpy(&rsa->sa_inet.addr, &sin->sin_addr,
+ sizeof(rsa->sa_inet.addr));
+ rsa->sa_inet.port = ntohs(sin->sin_port);
+ return;
+ case AF_INET6:
+ if (sal < sizeof(struct sockaddr_in6))
+ return;
+ sin6 = (const struct sockaddr_in6 *)sa;
+ rsa->sa_family = CLOUDABI_AF_INET6;
+ memcpy(&rsa->sa_inet6.addr, &sin6->sin6_addr,
+ sizeof(rsa->sa_inet6.addr));
+ rsa->sa_inet6.port = ntohs(sin6->sin6_port);
+ return;
+ case AF_UNIX:
+ rsa->sa_family = CLOUDABI_AF_UNIX;
+ return;
+ }
+}
/* Copies a pathname into a UNIX socket address structure. */
static int
@@ -62,9 +110,27 @@ int
cloudabi_sys_sock_accept(struct thread *td,
struct cloudabi_sys_sock_accept_args *uap)
{
+ struct sockaddr *sa;
+ cloudabi_sockstat_t ss = {};
+ socklen_t sal;
+ int error;
- /* Not implemented. */
- return (ENOSYS);
+ if (uap->buf == NULL) {
+ /* Only return the new file descriptor number. */
+ return (kern_accept(td, uap->s, NULL, NULL, NULL));
+ } else {
+ /* Also return properties of the new socket descriptor. */
+ sal = MAX(sizeof(struct sockaddr_in),
+ sizeof(struct sockaddr_in6));
+ error = kern_accept(td, uap->s, (void *)&sa, &sal, NULL);
+ if (error != 0)
+ return (error);
+
+ /* TODO(ed): Fill the other members of cloudabi_sockstat_t. */
+ cloudabi_convert_sockaddr(sa, sal, &ss.ss_peername);
+ free(sa, M_SONAME);
+ return (copyout(&ss, uap->buf, sizeof(ss)));
+ }
}
int
@@ -134,7 +200,51 @@ int
cloudabi_sys_sock_stat_get(struct thread *td,
struct cloudabi_sys_sock_stat_get_args *uap)
{
+ cloudabi_sockstat_t ss = {};
+ cap_rights_t rights;
+ struct file *fp;
+ struct sockaddr *sa;
+ struct socket *so;
+ int error;
+
+ error = getsock_cap(td, uap->fd, cap_rights_init(&rights,
+ CAP_GETSOCKOPT | CAP_GETPEERNAME | CAP_GETSOCKNAME), &fp, NULL);
+ if (error != 0)
+ return (error);
+ so = fp->f_data;
+
+ CURVNET_SET(so->so_vnet);
+
+ /* Set ss_sockname. */
+ error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
+ if (error == 0) {
+ cloudabi_convert_sockaddr(sa, sa->sa_len, &ss.ss_sockname);
+ free(sa, M_SONAME);
+ }
+
+ /* Set ss_peername. */
+ if ((so->so_state & (SS_ISCONNECTED | SS_ISCONFIRMING)) != 0) {
+ error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa);
+ if (error == 0) {
+ cloudabi_convert_sockaddr(sa, sa->sa_len,
+ &ss.ss_peername);
+ free(sa, M_SONAME);
+ }
+ }
+
+ CURVNET_RESTORE();
+
+ /* Set ss_error. */
+ SOCK_LOCK(so);
+ ss.ss_error = so->so_error;
+ if ((uap->flags & CLOUDABI_SOCKSTAT_CLEAR_ERROR) != 0)
+ so->so_error = 0;
+ SOCK_UNLOCK(so);
+
+ /* Set ss_state. */
+ if ((so->so_options & SO_ACCEPTCONN) != 0)
+ ss.ss_state |= CLOUDABI_SOCKSTAT_ACCEPTCONN;
- /* Not implemented. */
- return (ENOSYS);
+ fdrop(fp, td);
+ return (copyout(&ss, uap->buf, sizeof(ss)));
}
diff --git a/sys/compat/cloudabi/cloudabi_util.h b/sys/compat/cloudabi/cloudabi_util.h
index 5350d24..10da229 100644
--- a/sys/compat/cloudabi/cloudabi_util.h
+++ b/sys/compat/cloudabi/cloudabi_util.h
@@ -28,8 +28,11 @@
#ifndef _CLOUDABI_UTIL_H_
#define _CLOUDABI_UTIL_H_
+#include <sys/socket.h>
+
#include <compat/cloudabi/cloudabi_syscalldefs.h>
+struct file;
struct thread;
struct timespec;
@@ -40,6 +43,20 @@ int cloudabi_clock_time_get(struct thread *, cloudabi_clockid_t,
/* Converts a FreeBSD errno to a CloudABI errno. */
cloudabi_errno_t cloudabi_convert_errno(int);
+/* Converts FreeBSD's struct sockaddr to CloudABI's cloudabi_sockaddr_t. */
+void cloudabi_convert_sockaddr(const struct sockaddr *, socklen_t,
+ cloudabi_sockaddr_t *);
+
+/* Converts a file descriptor to a CloudABI file descriptor type. */
+cloudabi_filetype_t cloudabi_convert_filetype(const struct file *);
+
+/* Converts CloudABI rights to a set of Capsicum capabilities. */
+int cloudabi_convert_rights(cloudabi_rights_t, cap_rights_t *);
+
+/* Removes rights that conflict with the file descriptor type. */
+void cloudabi_remove_conflicting_rights(cloudabi_filetype_t,
+ cloudabi_rights_t *, cloudabi_rights_t *);
+
/* Converts a struct timespec to a CloudABI timestamp. */
int cloudabi_convert_timespec(const struct timespec *, cloudabi_timestamp_t *);
diff --git a/sys/compat/cloudabi64/cloudabi64_poll.c b/sys/compat/cloudabi64/cloudabi64_poll.c
index 544886d..0a18838 100644
--- a/sys/compat/cloudabi64/cloudabi64_poll.c
+++ b/sys/compat/cloudabi64/cloudabi64_poll.c
@@ -36,3 +36,12 @@ cloudabi64_sys_poll(struct thread *td, struct cloudabi64_sys_poll_args *uap)
/* Not implemented. */
return (ENOSYS);
}
+
+int
+cloudabi64_sys_poll_fd(struct thread *td,
+ struct cloudabi64_sys_poll_fd_args *uap)
+{
+
+ /* Not implemented. */
+ return (ENOSYS);
+}
diff --git a/sys/compat/cloudabi64/cloudabi64_proto.h b/sys/compat/cloudabi64/cloudabi64_proto.h
index dd86bc9..8c65fe3 100644
--- a/sys/compat/cloudabi64/cloudabi64_proto.h
+++ b/sys/compat/cloudabi64/cloudabi64_proto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 285906 2015-07-27 10:04:06Z ed
+ * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 286318 2015-08-05 13:09:46Z ed
*/
#ifndef _CLOUDABI64_SYSPROTO_H_
@@ -232,11 +232,9 @@ struct cloudabi_sys_mem_unmap_args {
char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
};
struct cloudabi64_sys_poll_args {
- char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
char in_l_[PADL_(const cloudabi64_subscription_t *)]; const cloudabi64_subscription_t * in; char in_r_[PADR_(const cloudabi64_subscription_t *)];
- char nin_l_[PADL_(cloudabi64_size_t)]; cloudabi64_size_t nin; char nin_r_[PADR_(cloudabi64_size_t)];
char out_l_[PADL_(cloudabi64_event_t *)]; cloudabi64_event_t * out; char out_r_[PADR_(cloudabi64_event_t *)];
- char nout_l_[PADL_(cloudabi64_size_t)]; cloudabi64_size_t nout; char nout_r_[PADR_(cloudabi64_size_t)];
+ char nevents_l_[PADL_(cloudabi64_size_t)]; cloudabi64_size_t nevents; char nevents_r_[PADR_(cloudabi64_size_t)];
};
struct cloudabi_sys_proc_exec_args {
char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
@@ -310,6 +308,14 @@ struct cloudabi_sys_thread_tcb_set_args {
struct cloudabi_sys_thread_yield_args {
register_t dummy;
};
+struct cloudabi64_sys_poll_fd_args {
+ char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
+ char in_l_[PADL_(const cloudabi64_subscription_t *)]; const cloudabi64_subscription_t * in; char in_r_[PADR_(const cloudabi64_subscription_t *)];
+ char nin_l_[PADL_(cloudabi64_size_t)]; cloudabi64_size_t nin; char nin_r_[PADR_(cloudabi64_size_t)];
+ char out_l_[PADL_(cloudabi64_event_t *)]; cloudabi64_event_t * out; char out_r_[PADR_(cloudabi64_event_t *)];
+ char nout_l_[PADL_(cloudabi64_size_t)]; cloudabi64_size_t nout; char nout_r_[PADR_(cloudabi64_size_t)];
+ char timeout_l_[PADL_(const cloudabi64_subscription_t *)]; const cloudabi64_subscription_t * timeout; char timeout_r_[PADR_(const cloudabi64_subscription_t *)];
+};
int cloudabi_sys_clock_res_get(struct thread *, struct cloudabi_sys_clock_res_get_args *);
int cloudabi_sys_clock_time_get(struct thread *, struct cloudabi_sys_clock_time_get_args *);
int cloudabi_sys_condvar_signal(struct thread *, struct cloudabi_sys_condvar_signal_args *);
@@ -367,6 +373,7 @@ int cloudabi64_sys_thread_create(struct thread *, struct cloudabi64_sys_thread_c
int cloudabi_sys_thread_exit(struct thread *, struct cloudabi_sys_thread_exit_args *);
int cloudabi_sys_thread_tcb_set(struct thread *, struct cloudabi_sys_thread_tcb_set_args *);
int cloudabi_sys_thread_yield(struct thread *, struct cloudabi_sys_thread_yield_args *);
+int cloudabi64_sys_poll_fd(struct thread *, struct cloudabi64_sys_poll_fd_args *);
#ifdef COMPAT_43
@@ -448,6 +455,7 @@ int cloudabi_sys_thread_yield(struct thread *, struct cloudabi_sys_thread_yield_
#define CLOUDABI64_SYS_AUE_cloudabi_sys_thread_exit AUE_NULL
#define CLOUDABI64_SYS_AUE_cloudabi_sys_thread_tcb_set AUE_NULL
#define CLOUDABI64_SYS_AUE_cloudabi_sys_thread_yield AUE_NULL
+#define CLOUDABI64_SYS_AUE_cloudabi64_sys_poll_fd AUE_NULL
#undef PAD_
#undef PADL_
diff --git a/sys/compat/cloudabi64/cloudabi64_syscall.h b/sys/compat/cloudabi64/cloudabi64_syscall.h
index 1765190..40c017a 100644
--- a/sys/compat/cloudabi64/cloudabi64_syscall.h
+++ b/sys/compat/cloudabi64/cloudabi64_syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 285906 2015-07-27 10:04:06Z ed
+ * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 286318 2015-08-05 13:09:46Z ed
*/
#define CLOUDABI64_SYS_cloudabi_sys_clock_res_get 0
@@ -63,4 +63,5 @@
#define CLOUDABI64_SYS_cloudabi_sys_thread_exit 54
#define CLOUDABI64_SYS_cloudabi_sys_thread_tcb_set 55
#define CLOUDABI64_SYS_cloudabi_sys_thread_yield 56
-#define CLOUDABI64_SYS_MAXSYSCALL 57
+#define CLOUDABI64_SYS_cloudabi64_sys_poll_fd 57
+#define CLOUDABI64_SYS_MAXSYSCALL 58
diff --git a/sys/compat/cloudabi64/cloudabi64_syscalls.c b/sys/compat/cloudabi64/cloudabi64_syscalls.c
index e44e6ea..5c0732b 100644
--- a/sys/compat/cloudabi64/cloudabi64_syscalls.c
+++ b/sys/compat/cloudabi64/cloudabi64_syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 285906 2015-07-27 10:04:06Z ed
+ * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 286318 2015-08-05 13:09:46Z ed
*/
const char *cloudabi64_syscallnames[] = {
@@ -64,4 +64,5 @@ const char *cloudabi64_syscallnames[] = {
"cloudabi_sys_thread_exit", /* 54 = cloudabi_sys_thread_exit */
"cloudabi_sys_thread_tcb_set", /* 55 = cloudabi_sys_thread_tcb_set */
"cloudabi_sys_thread_yield", /* 56 = cloudabi_sys_thread_yield */
+ "cloudabi64_sys_poll_fd", /* 57 = cloudabi64_sys_poll_fd */
};
diff --git a/sys/compat/cloudabi64/cloudabi64_sysent.c b/sys/compat/cloudabi64/cloudabi64_sysent.c
index 1048e4e..2ed5042 100644
--- a/sys/compat/cloudabi64/cloudabi64_sysent.c
+++ b/sys/compat/cloudabi64/cloudabi64_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 285906 2015-07-27 10:04:06Z ed
+ * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 286318 2015-08-05 13:09:46Z ed
*/
#include <sys/sysent.h>
@@ -72,4 +72,5 @@ struct sysent cloudabi64_sysent[] = {
{ AS(cloudabi_sys_thread_exit_args), (sy_call_t *)cloudabi_sys_thread_exit, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 54 = cloudabi_sys_thread_exit */
{ AS(cloudabi_sys_thread_tcb_set_args), (sy_call_t *)cloudabi_sys_thread_tcb_set, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 55 = cloudabi_sys_thread_tcb_set */
{ 0, (sy_call_t *)cloudabi_sys_thread_yield, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 56 = cloudabi_sys_thread_yield */
+ { AS(cloudabi64_sys_poll_fd_args), (sy_call_t *)cloudabi64_sys_poll_fd, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 57 = cloudabi64_sys_poll_fd */
};
diff --git a/sys/compat/cloudabi64/cloudabi64_systrace_args.c b/sys/compat/cloudabi64/cloudabi64_systrace_args.c
index 311a14c..b3176aa 100644
--- a/sys/compat/cloudabi64/cloudabi64_systrace_args.c
+++ b/sys/compat/cloudabi64/cloudabi64_systrace_args.c
@@ -367,12 +367,10 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* cloudabi64_sys_poll */
case 39: {
struct cloudabi64_sys_poll_args *p = params;
- iarg[0] = p->fd; /* cloudabi_fd_t */
- uarg[1] = (intptr_t) p->in; /* const cloudabi64_subscription_t * */
- iarg[2] = p->nin; /* cloudabi64_size_t */
- uarg[3] = (intptr_t) p->out; /* cloudabi64_event_t * */
- iarg[4] = p->nout; /* cloudabi64_size_t */
- *n_args = 5;
+ uarg[0] = (intptr_t) p->in; /* const cloudabi64_subscription_t * */
+ uarg[1] = (intptr_t) p->out; /* cloudabi64_event_t * */
+ iarg[2] = p->nevents; /* cloudabi64_size_t */
+ *n_args = 3;
break;
}
/* cloudabi_sys_proc_exec */
@@ -511,6 +509,18 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
*n_args = 0;
break;
}
+ /* cloudabi64_sys_poll_fd */
+ case 57: {
+ struct cloudabi64_sys_poll_fd_args *p = params;
+ iarg[0] = p->fd; /* cloudabi_fd_t */
+ uarg[1] = (intptr_t) p->in; /* const cloudabi64_subscription_t * */
+ iarg[2] = p->nin; /* cloudabi64_size_t */
+ uarg[3] = (intptr_t) p->out; /* cloudabi64_event_t * */
+ iarg[4] = p->nout; /* cloudabi64_size_t */
+ uarg[5] = (intptr_t) p->timeout; /* const cloudabi64_subscription_t * */
+ *n_args = 6;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -1155,18 +1165,12 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
case 39:
switch(ndx) {
case 0:
- p = "cloudabi_fd_t";
- break;
- case 1:
p = "const cloudabi64_subscription_t *";
break;
- case 2:
- p = "cloudabi64_size_t";
- break;
- case 3:
+ case 1:
p = "cloudabi64_event_t *";
break;
- case 4:
+ case 2:
p = "cloudabi64_size_t";
break;
default:
@@ -1392,6 +1396,31 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
/* cloudabi_sys_thread_yield */
case 56:
break;
+ /* cloudabi64_sys_poll_fd */
+ case 57:
+ switch(ndx) {
+ case 0:
+ p = "cloudabi_fd_t";
+ break;
+ case 1:
+ p = "const cloudabi64_subscription_t *";
+ break;
+ case 2:
+ p = "cloudabi64_size_t";
+ break;
+ case 3:
+ p = "cloudabi64_event_t *";
+ break;
+ case 4:
+ p = "cloudabi64_size_t";
+ break;
+ case 5:
+ p = "const cloudabi64_subscription_t *";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -1682,6 +1711,11 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
/* cloudabi_sys_thread_yield */
case 56:
+ /* cloudabi64_sys_poll_fd */
+ case 57:
+ if (ndx == 0 || ndx == 1)
+ p = "cloudabi64_size_t";
+ break;
default:
break;
};
diff --git a/sys/compat/cloudabi64/syscalls.master b/sys/compat/cloudabi64/syscalls.master
index 21deffb..5fd6f7e 100644
--- a/sys/compat/cloudabi64/syscalls.master
+++ b/sys/compat/cloudabi64/syscalls.master
@@ -157,11 +157,9 @@
void * addr, size_t len); }
39 AUE_NULL STD { cloudabi64_size_t cloudabi64_sys_poll( \
- cloudabi_fd_t fd, \
const cloudabi64_subscription_t *in, \
- cloudabi64_size_t nin, \
cloudabi64_event_t *out, \
- cloudabi64_size_t nout); }
+ cloudabi64_size_t nevents); }
40 AUE_NULL STD { void cloudabi_sys_proc_exec( \
cloudabi_fd_t fd, const void *data, \
@@ -212,3 +210,11 @@
cloudabi_mflags_t scope); }
55 AUE_NULL STD { void cloudabi_sys_thread_tcb_set(void *tcb); }
56 AUE_NULL STD { void cloudabi_sys_thread_yield(); }
+
+57 AUE_NULL STD { cloudabi64_size_t cloudabi64_sys_poll_fd( \
+ cloudabi_fd_t fd, \
+ const cloudabi64_subscription_t *in, \
+ cloudabi64_size_t nin, \
+ cloudabi64_event_t *out, \
+ cloudabi64_size_t nout, \
+ const cloudabi64_subscription_t *timeout); }
diff --git a/sys/compat/linux/linux_event.c b/sys/compat/linux/linux_event.c
index fcb5753..b1ceadf 100644
--- a/sys/compat/linux/linux_event.c
+++ b/sys/compat/linux/linux_event.c
@@ -205,7 +205,7 @@ epoll_create_common(struct thread *td, int flags)
{
int error;
- error = kern_kqueue(td, flags);
+ error = kern_kqueue(td, flags, NULL);
if (error)
return (error);
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index 1e5e37a..489dc1e 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -1582,7 +1582,7 @@ linux_pipe(struct thread *td, struct linux_pipe_args *args)
printf(ARGS(pipe, "*"));
#endif
- error = kern_pipe2(td, fildes, 0);
+ error = kern_pipe(td, fildes, 0, NULL, NULL);
if (error)
return (error);
@@ -1609,7 +1609,7 @@ linux_pipe2(struct thread *td, struct linux_pipe2_args *args)
flags |= O_NONBLOCK;
if ((args->flags & LINUX_O_CLOEXEC) != 0)
flags |= O_CLOEXEC;
- error = kern_pipe2(td, fildes, flags);
+ error = kern_pipe(td, fildes, flags, NULL, NULL);
if (error)
return (error);
diff --git a/sys/compat/linux/linux_fork.c b/sys/compat/linux/linux_fork.c
index 6b37490..a8bf720 100644
--- a/sys/compat/linux/linux_fork.c
+++ b/sys/compat/linux/linux_fork.c
@@ -73,8 +73,8 @@ linux_fork(struct thread *td, struct linux_fork_args *args)
printf(ARGS(fork, ""));
#endif
- if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2, NULL, 0))
- != 0)
+ if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2, NULL, 0,
+ NULL)) != 0)
return (error);
td2 = FIRST_THREAD_IN_PROC(p2);
@@ -108,7 +108,7 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
/* Exclude RFPPWAIT */
if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFSTOPPED, 0, &p2,
- NULL, 0)) != 0)
+ NULL, 0, NULL)) != 0)
return (error);
@@ -179,7 +179,7 @@ linux_clone_proc(struct thread *td, struct linux_clone_args *args)
if (args->parent_tidptr == NULL)
return (EINVAL);
- error = fork1(td, ff, 0, &p2, NULL, 0);
+ error = fork1(td, ff, 0, &p2, NULL, 0, NULL);
if (error)
return (error);
diff --git a/sys/conf/files b/sys/conf/files
index 99cef6d..fecb8b1 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1203,7 +1203,7 @@ t4fw.fwo optional cxgbe \
no-implicit-rule \
clean "t4fw.fwo"
t4fw.fw optional cxgbe \
- dependency "$S/dev/cxgbe/firmware/t4fw-1.14.2.0.bin.uu" \
+ dependency "$S/dev/cxgbe/firmware/t4fw-1.14.4.0.bin.uu" \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "t4fw.fw"
@@ -1227,7 +1227,7 @@ t5fw.fwo optional cxgbe \
no-implicit-rule \
clean "t5fw.fwo"
t5fw.fw optional cxgbe \
- dependency "$S/dev/cxgbe/firmware/t5fw-1.14.2.0.bin.uu" \
+ dependency "$S/dev/cxgbe/firmware/t5fw-1.14.4.0.bin.uu" \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "t5fw.fw"
@@ -1436,6 +1436,7 @@ dev/fxp/inphy.c optional fxp
dev/gem/if_gem.c optional gem
dev/gem/if_gem_pci.c optional gem pci
dev/gem/if_gem_sbus.c optional gem sbus
+dev/gpio/gpiobacklight.c optional gpiobacklight fdt
dev/gpio/gpiobus.c optional gpio \
dependency "gpiobus_if.h"
dev/gpio/gpioc.c optional gpio \
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index 92a422d4..6a8c966 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -40,13 +40,14 @@ arm64/arm64/mp_machdep.c optional smp
arm64/arm64/nexus.c standard
arm64/arm64/pic_if.m standard
arm64/arm64/pmap.c standard
-arm64/arm64/stack_machdep.c standard
+arm64/arm64/stack_machdep.c optional ddb | stack
arm64/arm64/support.S standard
arm64/arm64/swtch.S standard
arm64/arm64/sys_machdep.c standard
arm64/arm64/trap.c standard
arm64/arm64/uio_machdep.c standard
-arm64/arm64/unwind.c optional ddb | kdtrace_hooks
+arm64/arm64/uma_machdep.c standard
+arm64/arm64/unwind.c optional ddb | kdtrace_hooks | stack
arm64/arm64/vfp.c standard
arm64/arm64/vm_machdep.c standard
crypto/blowfish/bf_enc.c optional crypto | ipsec
diff --git a/sys/conf/options.arm64 b/sys/conf/options.arm64
index 1dfcbec..4965940 100644
--- a/sys/conf/options.arm64
+++ b/sys/conf/options.arm64
@@ -1,6 +1,7 @@
# $FreeBSD$
-ARM64 opt_global.h
-SOCDEV_PA opt_global.h
-SOCDEV_VA opt_global.h
-VFP opt_global.h
+ARM64 opt_global.h
+SOCDEV_PA opt_global.h
+SOCDEV_VA opt_global.h
+THUNDERX_PASS_1_1_ERRATA opt_global.h
+VFP opt_global.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_common.h b/sys/contrib/alpine-hal/al_hal_common.h
index 6e27e17..6e27e17 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_common.h
+++ b/sys/contrib/alpine-hal/al_hal_common.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_iofic.h b/sys/contrib/alpine-hal/al_hal_iofic.h
index 5c19e0a..5c19e0a 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_iofic.h
+++ b/sys/contrib/alpine-hal/al_hal_iofic.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_iofic_regs.h b/sys/contrib/alpine-hal/al_hal_iofic_regs.h
index 81ba20f..81ba20f 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_iofic_regs.h
+++ b/sys/contrib/alpine-hal/al_hal_iofic_regs.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_nb_regs.h b/sys/contrib/alpine-hal/al_hal_nb_regs.h
index 9de3bd2..9de3bd2 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_nb_regs.h
+++ b/sys/contrib/alpine-hal/al_hal_nb_regs.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_pbs_regs.h b/sys/contrib/alpine-hal/al_hal_pbs_regs.h
index b1f9c4f..b1f9c4f 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_pbs_regs.h
+++ b/sys/contrib/alpine-hal/al_hal_pbs_regs.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_pcie.c b/sys/contrib/alpine-hal/al_hal_pcie.c
index 3a221d3..3a221d3 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_pcie.c
+++ b/sys/contrib/alpine-hal/al_hal_pcie.c
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_pcie.h b/sys/contrib/alpine-hal/al_hal_pcie.h
index 1ddc8eb..1ddc8eb 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_pcie.h
+++ b/sys/contrib/alpine-hal/al_hal_pcie.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_pcie_axi_reg.h b/sys/contrib/alpine-hal/al_hal_pcie_axi_reg.h
index 04d4bfd..04d4bfd 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_pcie_axi_reg.h
+++ b/sys/contrib/alpine-hal/al_hal_pcie_axi_reg.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_pcie_interrupts.h b/sys/contrib/alpine-hal/al_hal_pcie_interrupts.h
index 357971c..357971c 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_pcie_interrupts.h
+++ b/sys/contrib/alpine-hal/al_hal_pcie_interrupts.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_pcie_regs.h b/sys/contrib/alpine-hal/al_hal_pcie_regs.h
index 15c5735..15c5735 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_pcie_regs.h
+++ b/sys/contrib/alpine-hal/al_hal_pcie_regs.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_pcie_w_reg.h b/sys/contrib/alpine-hal/al_hal_pcie_w_reg.h
index 44e9d95..44e9d95 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_pcie_w_reg.h
+++ b/sys/contrib/alpine-hal/al_hal_pcie_w_reg.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_plat_services.h b/sys/contrib/alpine-hal/al_hal_plat_services.h
index 217bb92..217bb92 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_plat_services.h
+++ b/sys/contrib/alpine-hal/al_hal_plat_services.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_plat_types.h b/sys/contrib/alpine-hal/al_hal_plat_types.h
index 43896ae..43896ae 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_plat_types.h
+++ b/sys/contrib/alpine-hal/al_hal_plat_types.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_reg_utils.h b/sys/contrib/alpine-hal/al_hal_reg_utils.h
index f29c3c5..f29c3c5 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_reg_utils.h
+++ b/sys/contrib/alpine-hal/al_hal_reg_utils.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_types.h b/sys/contrib/alpine-hal/al_hal_types.h
index cea839d..cea839d 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_types.h
+++ b/sys/contrib/alpine-hal/al_hal_types.h
diff --git a/sys/arm/annapurna/alpine/hal/al_hal_unit_adapter_regs.h b/sys/contrib/alpine-hal/al_hal_unit_adapter_regs.h
index 740b959..740b959 100644
--- a/sys/arm/annapurna/alpine/hal/al_hal_unit_adapter_regs.h
+++ b/sys/contrib/alpine-hal/al_hal_unit_adapter_regs.h
diff --git a/sys/contrib/cloudabi/syscalldefs_md.h b/sys/contrib/cloudabi/syscalldefs_md.h
index a7045c2..f2e3705 100644
--- a/sys/contrib/cloudabi/syscalldefs_md.h
+++ b/sys/contrib/cloudabi/syscalldefs_md.h
@@ -186,6 +186,7 @@ typedef struct {
MEMBER(cloudabi_clockid_t) clock_id;
MEMBER(cloudabi_timestamp_t) timeout;
MEMBER(cloudabi_timestamp_t) precision;
+ MEMBER(uint16_t) flags;
} clock;
// CLOUDABI_EVENTTYPE_CONDVAR: Release a lock and wait on a
@@ -202,6 +203,7 @@ typedef struct {
// called without blocking.
struct {
MEMBER(cloudabi_fd_t) fd;
+ MEMBER(uint16_t) flags;
} fd_readwrite;
// CLOUDABI_EVENT_LOCK_RDLOCK and CLOUDABI_EVENT_LOCK_WRLOCK: Wait
@@ -224,15 +226,17 @@ ASSERT_OFFSET(subscription_t, clock.identifier, 16, 16);
ASSERT_OFFSET(subscription_t, clock.clock_id, 24, 24);
ASSERT_OFFSET(subscription_t, clock.timeout, 32, 32);
ASSERT_OFFSET(subscription_t, clock.precision, 40, 40);
+ASSERT_OFFSET(subscription_t, clock.flags, 48, 48);
ASSERT_OFFSET(subscription_t, condvar.condvar, 16, 16);
ASSERT_OFFSET(subscription_t, condvar.lock, 20, 24);
ASSERT_OFFSET(subscription_t, condvar.condvar_scope, 24, 32);
ASSERT_OFFSET(subscription_t, condvar.lock_scope, 25, 33);
ASSERT_OFFSET(subscription_t, fd_readwrite.fd, 16, 16);
+ASSERT_OFFSET(subscription_t, fd_readwrite.flags, 20, 20);
ASSERT_OFFSET(subscription_t, lock.lock, 16, 16);
ASSERT_OFFSET(subscription_t, lock.lock_scope, 20, 24);
ASSERT_OFFSET(subscription_t, proc_terminate.fd, 16, 16);
-ASSERT_SIZE(subscription_t, 48, 48);
+ASSERT_SIZE(subscription_t, 56, 56);
typedef struct {
MEMBER(PTR(IDENT(threadentry_t))) entry_point; // Entry point.
diff --git a/sys/contrib/cloudabi/syscalldefs_mi.h b/sys/contrib/cloudabi/syscalldefs_mi.h
index 151a3dc..adce208 100644
--- a/sys/contrib/cloudabi/syscalldefs_mi.h
+++ b/sys/contrib/cloudabi/syscalldefs_mi.h
@@ -204,9 +204,6 @@
#define CLOUDABI_O_EXCL 0x4
#define CLOUDABI_O_TRUNC 0x8
-// File descriptor passed to poll() to poll just once.
-#define CLOUDABI_POLL_ONCE 0xffffffff
-
// File descriptor returned to pdfork()'s child process.
#define CLOUDABI_PROCESS_CHILD 0xffffffff
@@ -326,6 +323,12 @@
#define CLOUDABI_SUBSCRIPTION_ENABLE 0x10
#define CLOUDABI_SUBSCRIPTION_ONESHOT 0x20
+// cloudabi_subscription_t::clock.flags.
+#define CLOUDABI_SUBSCRIPTION_CLOCK_ABSTIME 0x1
+
+// cloudabi_subscription_t::fd_readwrite.flags.
+#define CLOUDABI_SUBSCRIPTION_FD_READWRITE_POLL 0x1
+
// unlinkat().
#define CLOUDABI_UNLINK_REMOVEDIR 0x1
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
index 5bdd74f..6118b82 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c
@@ -97,6 +97,18 @@ ar9300_freebsd_get_cts_timeout(struct ath_hal *ah)
return ath_hal_mac_usec(ah, clks); /* convert from system clocks */
}
+static void
+ar9300_freebsd_set_tsf64(struct ath_hal *ah, uint64_t tsf64)
+{
+
+ /*
+ * XXX TODO: read ar5416SetTsf64() - we should wait before we do
+ * this.
+ */
+ OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
+ OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
+}
+
void
ar9300_attach_freebsd_ops(struct ath_hal *ah)
{
@@ -182,6 +194,7 @@ ar9300_attach_freebsd_ops(struct ath_hal *ah)
ah->ah_getTsf32 = ar9300_get_tsf32;
ah->ah_getTsf64 = ar9300_get_tsf64;
ah->ah_resetTsf = ar9300_reset_tsf;
+ ah->ah_setTsf64 = ar9300_freebsd_set_tsf64;
ah->ah_detectCardPresent = ar9300_detect_card_present;
// ah->ah_updateMibCounters = ar9300_update_mib_counters;
ah->ah_getRfGain = ar9300_get_rfgain;
diff --git a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c
index e9caa43..6972200 100644
--- a/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c
+++ b/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c
@@ -940,6 +940,13 @@ ar9300_get_capability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
return HAL_OK;
}
return HAL_EINVAL;
+ case HAL_CAP_ENFORCE_TXOP:
+ if (capability == 0)
+ return (HAL_OK);
+ if (capability != 1)
+ return (HAL_ENOTSUPP);
+ (*result) = !! (ahp->ah_misc_mode & AR_PCU_TXOP_TBTT_LIMIT_ENA);
+ return (HAL_OK);
default:
return ath_hal_getcapability(ah, type, capability, result);
}
@@ -1041,6 +1048,18 @@ ar9300_set_capability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
OS_REG_WRITE(ah, AR_DATABUF, ahp->rx_buf_size);
return AH_TRUE;
+ case HAL_CAP_ENFORCE_TXOP:
+ if (capability != 1)
+ return AH_FALSE;
+ if (setting) {
+ ahp->ah_misc_mode |= AR_PCU_TXOP_TBTT_LIMIT_ENA;
+ OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_TXOP_TBTT_LIMIT_ENA);
+ } else {
+ ahp->ah_misc_mode &= ~AR_PCU_TXOP_TBTT_LIMIT_ENA;
+ OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_TXOP_TBTT_LIMIT_ENA);
+ }
+ return AH_TRUE;
+
/* fall thru... */
default:
return ath_hal_setcapability(ah, type, capability, setting, status);
diff --git a/sys/crypto/aesni/aesni.h b/sys/crypto/aesni/aesni.h
index 0594176..3d5adec 100644
--- a/sys/crypto/aesni/aesni.h
+++ b/sys/crypto/aesni/aesni.h
@@ -104,7 +104,7 @@ void AES_GCM_encrypt(const unsigned char *in, unsigned char *out,
const unsigned char *key, int nr);
int AES_GCM_decrypt(const unsigned char *in, unsigned char *out,
const unsigned char *addt, const unsigned char *ivec,
- unsigned char *tag, uint32_t nbytes, uint32_t abytes, int ibytes,
+ const unsigned char *tag, uint32_t nbytes, uint32_t abytes, int ibytes,
const unsigned char *key, int nr);
int aesni_cipher_setup_common(struct aesni_session *ses, const uint8_t *key,
diff --git a/sys/crypto/aesni/aesni_ghash.c b/sys/crypto/aesni/aesni_ghash.c
index f7be6c0..54c8815 100644
--- a/sys/crypto/aesni/aesni_ghash.c
+++ b/sys/crypto/aesni/aesni_ghash.c
@@ -528,7 +528,7 @@ AES_GCM_encrypt(const unsigned char *in, unsigned char *out,
int
AES_GCM_decrypt(const unsigned char *in, unsigned char *out,
const unsigned char *addt, const unsigned char *ivec,
- unsigned char *tag, uint32_t nbytes, uint32_t abytes, int ibytes,
+ const unsigned char *tag, uint32_t nbytes, uint32_t abytes, int ibytes,
const unsigned char *key, int nr)
{
int i, j ,k;
@@ -677,7 +677,7 @@ AES_GCM_decrypt(const unsigned char *in, unsigned char *out,
X = _mm_shuffle_epi8(X, BSWAP_MASK);
T = _mm_xor_si128(X, T);
- if (!m128icmp(T, _mm_loadu_si128((__m128i*)tag)))
+ if (!m128icmp(T, _mm_loadu_si128((const __m128i*)tag)))
return 0; //in case the authentication failed
ctr1 = _mm_shuffle_epi8(Y, BSWAP_EPI64);
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 19d6eb2..6e3f5fe 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -1074,7 +1074,7 @@ ataaction(struct cam_sim *sim, union ccb *ccb)
cpi->version_num = 1; /* XXX??? */
cpi->hba_inquiry = PI_SDTR_ABLE;
cpi->target_sprt = 0;
- cpi->hba_misc = PIM_SEQSCAN;
+ cpi->hba_misc = PIM_SEQSCAN | PIM_UNMAPPED;
cpi->hba_eng_cnt = 0;
if (ch->flags & ATA_NO_SLAVE)
cpi->max_target = 0;
diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c
index 459f98c..6b825c0 100644
--- a/sys/dev/ata/ata-lowlevel.c
+++ b/sys/dev/ata/ata-lowlevel.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/endian.h>
#include <sys/ata.h>
+#include <sys/bio.h>
#include <sys/conf.h>
#include <sys/ctype.h>
#include <sys/bus.h>
@@ -44,6 +45,12 @@ __FBSDID("$FreeBSD$");
#include <dev/ata/ata-pci.h>
#include <ata_if.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+
/* prototypes */
static int ata_generic_status(device_t dev);
static int ata_wait(struct ata_channel *ch, int unit, u_int8_t);
@@ -811,86 +818,176 @@ ata_tf_write(struct ata_request *request)
static void
ata_pio_read(struct ata_request *request, int length)
{
- struct ata_channel *ch = device_get_softc(request->parent);
- uint8_t *addr;
- int size = min(request->transfersize, length);
- int resid;
- uint8_t buf[2] __aligned(sizeof(int16_t));
-#ifndef __NO_STRICT_ALIGNMENT
- int i;
-#endif
+ struct ata_channel *ch = device_get_softc(request->parent);
+ struct bio *bio;
+ uint8_t *addr;
+ vm_offset_t page;
+ int todo, done, off, moff, resid, size, i;
+ uint8_t buf[2] __aligned(2);
+
+ todo = min(request->transfersize, length);
+ page = done = resid = 0;
+ while (done < todo) {
+ size = todo - done;
+
+ /* Prepare data address and limit size (if not sequential). */
+ off = request->donecount + done;
+ if ((request->flags & ATA_R_DATA_IN_CCB) == 0 ||
+ (request->ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) {
+ addr = (uint8_t *)request->data + off;
+ } else if ((request->ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_BIO) {
+ bio = (struct bio *)request->data;
+ if ((bio->bio_flags & BIO_UNMAPPED) == 0) {
+ addr = (uint8_t *)bio->bio_data + off;
+ } else {
+ moff = bio->bio_ma_offset + off;
+ page = pmap_quick_enter_page(
+ bio->bio_ma[moff / PAGE_SIZE]);
+ moff %= PAGE_SIZE;
+ size = min(size, PAGE_SIZE - moff);
+ addr = (void *)(page + moff);
+ }
+ } else
+ panic("ata_pio_read: Unsupported CAM data type %x\n",
+ (request->ccb->ccb_h.flags & CAM_DATA_MASK));
+
+ /* We may have extra byte already red but not stored. */
+ if (resid) {
+ addr[0] = buf[1];
+ addr++;
+ done++;
+ size--;
+ }
- addr = (uint8_t *)request->data + request->donecount;
- if (__predict_false(ch->flags & ATA_USE_16BIT ||
- (size % sizeof(int32_t)) || ((uintptr_t)addr % sizeof(int32_t)))) {
+ /* Process main part of data. */
+ resid = size % 2;
+ if (__predict_false((ch->flags & ATA_USE_16BIT) ||
+ (size % 4) != 0 || ((uintptr_t)addr % 4) != 0)) {
#ifndef __NO_STRICT_ALIGNMENT
- if (__predict_false((uintptr_t)addr % sizeof(int16_t))) {
- for (i = 0, resid = size & ~1; resid > 0; resid -=
- sizeof(int16_t)) {
- *(uint16_t *)&buf = ATA_IDX_INW_STRM(ch, ATA_DATA);
- addr[i++] = buf[0];
- addr[i++] = buf[1];
- }
- } else
+ if (__predict_false((uintptr_t)addr % 2)) {
+ for (i = 0; i + 1 < size; i += 2) {
+ *(uint16_t *)&buf =
+ ATA_IDX_INW_STRM(ch, ATA_DATA);
+ addr[i] = buf[0];
+ addr[i + 1] = buf[1];
+ }
+ } else
#endif
- ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)addr, size /
- sizeof(int16_t));
- if (size & 1) {
- *(uint16_t *)&buf = ATA_IDX_INW_STRM(ch, ATA_DATA);
- (addr + (size & ~1))[0] = buf[0];
- }
- } else
- ATA_IDX_INSL_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int32_t));
-
- if (request->transfersize < length) {
- device_printf(request->parent, "WARNING - %s read data overrun %d>%d\n",
- ata_cmd2str(request), length, request->transfersize);
- for (resid = request->transfersize + (size & 1); resid < length;
- resid += sizeof(int16_t))
- ATA_IDX_INW(ch, ATA_DATA);
- }
+ ATA_IDX_INSW_STRM(ch, ATA_DATA, (void*)addr,
+ size / 2);
+
+ /* If we have extra byte of data, leave it for later. */
+ if (resid) {
+ *(uint16_t *)&buf =
+ ATA_IDX_INW_STRM(ch, ATA_DATA);
+ addr[size - 1] = buf[0];
+ }
+ } else
+ ATA_IDX_INSL_STRM(ch, ATA_DATA, (void*)addr, size / 4);
+
+ if (page) {
+ pmap_quick_remove_page(page);
+ page = 0;
+ }
+ done += size;
+ }
+
+ if (length > done) {
+ device_printf(request->parent,
+ "WARNING - %s read data overrun %d > %d\n",
+ ata_cmd2str(request), length, done);
+ for (i = done + resid; i < length; i += 2)
+ ATA_IDX_INW(ch, ATA_DATA);
+ }
}
static void
ata_pio_write(struct ata_request *request, int length)
{
- struct ata_channel *ch = device_get_softc(request->parent);
- uint8_t *addr;
- int size = min(request->transfersize, length);
- int resid;
- uint8_t buf[2] __aligned(sizeof(int16_t));
+ struct ata_channel *ch = device_get_softc(request->parent);
+ struct bio *bio;
+ uint8_t *addr;
+ vm_offset_t page;
+ int todo, done, off, moff, resid, size, i;
+ uint8_t buf[2] __aligned(2);
+
+ todo = min(request->transfersize, length);
+ page = done = resid = 0;
+ while (done < todo) {
+ size = todo - done;
+
+ /* Prepare data address and limit size (if not sequential). */
+ off = request->donecount + done;
+ if ((request->flags & ATA_R_DATA_IN_CCB) == 0 ||
+ (request->ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) {
+ addr = (uint8_t *)request->data + off;
+ } else if ((request->ccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_BIO) {
+ bio = (struct bio *)request->data;
+ if ((bio->bio_flags & BIO_UNMAPPED) == 0) {
+ addr = (uint8_t *)bio->bio_data + off;
+ } else {
+ moff = bio->bio_ma_offset + off;
+ page = pmap_quick_enter_page(
+ bio->bio_ma[moff / PAGE_SIZE]);
+ moff %= PAGE_SIZE;
+ size = min(size, PAGE_SIZE - moff);
+ addr = (void *)(page + moff);
+ }
+ } else
+ panic("ata_pio_write: Unsupported CAM data type %x\n",
+ (request->ccb->ccb_h.flags & CAM_DATA_MASK));
+
+ /* We may have extra byte to be written first. */
+ if (resid) {
+ buf[1] = addr[0];
+ ATA_IDX_OUTW_STRM(ch, ATA_DATA, *(uint16_t *)&buf);
+ addr++;
+ done++;
+ size--;
+ }
+
+ /* Process main part of data. */
+ resid = size % 2;
+ if (__predict_false((ch->flags & ATA_USE_16BIT) ||
+ (size % 4) != 0 || ((uintptr_t)addr % 4) != 0)) {
#ifndef __NO_STRICT_ALIGNMENT
- int i;
+ if (__predict_false((uintptr_t)addr % 2)) {
+ for (i = 0; i + 1 < size; i += 2) {
+ buf[0] = addr[i];
+ buf[1] = addr[i + 1];
+ ATA_IDX_OUTW_STRM(ch, ATA_DATA,
+ *(uint16_t *)&buf);
+ }
+ } else
#endif
+ ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)addr,
+ size / 2);
+
+ /* If we have extra byte of data, save it for later. */
+ if (resid)
+ buf[0] = addr[size - 1];
+ } else
+ ATA_IDX_OUTSL_STRM(ch, ATA_DATA,
+ (void*)addr, size / sizeof(int32_t));
+
+ if (page) {
+ pmap_quick_remove_page(page);
+ page = 0;
+ }
+ done += size;
+ }
- size = min(request->transfersize, length);
- addr = (uint8_t *)request->data + request->donecount;
- if (__predict_false(ch->flags & ATA_USE_16BIT ||
- (size % sizeof(int32_t)) || ((uintptr_t)addr % sizeof(int32_t)))) {
-#ifndef __NO_STRICT_ALIGNMENT
- if (__predict_false((uintptr_t)addr % sizeof(int16_t))) {
- for (i = 0, resid = size & ~1; resid > 0; resid -=
- sizeof(int16_t)) {
- buf[0] = addr[i++];
- buf[1] = addr[i++];
+ /* We may have extra byte of data to be written. Pad it with zero. */
+ if (resid) {
+ buf[1] = 0;
ATA_IDX_OUTW_STRM(ch, ATA_DATA, *(uint16_t *)&buf);
- }
- } else
-#endif
- ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (void*)addr, size /
- sizeof(int16_t));
- if (size & 1) {
- buf[0] = (addr + (size & ~1))[0];
- ATA_IDX_OUTW_STRM(ch, ATA_DATA, *(uint16_t *)&buf);
- }
- } else
- ATA_IDX_OUTSL_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int32_t));
-
- if (request->transfersize < length) {
- device_printf(request->parent, "WARNING - %s write data underrun %d>%d\n",
- ata_cmd2str(request), length, request->transfersize);
- for (resid = request->transfersize + (size & 1); resid < length;
- resid += sizeof(int16_t))
- ATA_IDX_OUTW(ch, ATA_DATA, 0);
- }
+ }
+
+ if (length > done) {
+ device_printf(request->parent,
+ "WARNING - %s write data underrun %d > %d\n",
+ ata_cmd2str(request), length, done);
+ for (i = done + resid; i < length; i += 2)
+ ATA_IDX_OUTW(ch, ATA_DATA, 0);
+ }
}
diff --git a/sys/dev/ath/ath_rate/sample/sample.c b/sys/dev/ath/ath_rate/sample/sample.c
index 3606e14..815c68b 100644
--- a/sys/dev/ath/ath_rate/sample/sample.c
+++ b/sys/dev/ath/ath_rate/sample/sample.c
@@ -488,8 +488,7 @@ ath_rate_findrate(struct ath_softc *sc, struct ath_node *an,
#define RATE(ix) (DOT11RATE(ix) / 2)
struct sample_node *sn = ATH_NODE_SAMPLE(an);
struct sample_softc *ssc = ATH_SOFTC_SAMPLE(sc);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
const HAL_RATE_TABLE *rt = sc->sc_currates;
const int size_bin = size_to_bin(frameLen);
int rix, mrr, best_rix, change_rates;
@@ -856,8 +855,7 @@ ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
const struct ath_rc_series *rc, const struct ath_tx_status *ts,
int frame_size, int nframes, int nbad)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct sample_node *sn = ATH_NODE_SAMPLE(an);
int final_rix, short_tries, long_tries;
const HAL_RATE_TABLE *rt = sc->sc_currates;
@@ -1303,8 +1301,7 @@ static int
ath_rate_sysctl_stats(SYSCTL_HANDLER_ARGS)
{
struct ath_softc *sc = arg1;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
int error, v;
v = 0;
diff --git a/sys/dev/ath/ath_rate/sample/sample.h b/sys/dev/ath/ath_rate/sample/sample.h
index 1c57dee..5495141 100644
--- a/sys/dev/ath/ath_rate/sample/sample.h
+++ b/sys/dev/ath/ath_rate/sample/sample.h
@@ -134,8 +134,7 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc,
int long_retries, int is_ht40)
{
const HAL_RATE_TABLE *rt = sc->sc_currates;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
int rts, cts;
unsigned t_slot = 20;
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 4aac93b..f40f4fa 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -151,15 +151,15 @@ static struct ieee80211vap *ath_vap_create(struct ieee80211com *,
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void ath_vap_delete(struct ieee80211vap *);
-static void ath_init(void *);
-static void ath_stop_locked(struct ifnet *);
-static void ath_stop(struct ifnet *);
+static void ath_init(struct ath_softc *);
+static void ath_stop_locked(struct ath_softc *);
+static void ath_stop(struct ath_softc *);
static int ath_reset_vap(struct ieee80211vap *, u_long);
-static int ath_transmit(struct ifnet *ifp, struct mbuf *m);
-static void ath_qflush(struct ifnet *ifp);
+static int ath_transmit(struct ieee80211com *, struct mbuf *);
static int ath_media_change(struct ifnet *);
static void ath_watchdog(void *);
-static int ath_ioctl(struct ifnet *, u_long, caddr_t);
+static int ath_ioctl(struct ieee80211com *, u_long, void *);
+static void ath_parent(struct ieee80211com *);
static void ath_fatal_proc(void *, int);
static void ath_bmiss_vap(struct ieee80211vap *);
static void ath_bmiss_proc(void *, int);
@@ -571,34 +571,19 @@ ath_fetch_mac_kenv(struct ath_softc *sc, uint8_t *macaddr)
int
ath_attach(u_int16_t devid, struct ath_softc *sc)
{
- struct ifnet *ifp;
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = NULL;
HAL_STATUS status;
int error = 0, i;
u_int wmodes;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
int rx_chainmask, tx_chainmask;
HAL_OPS_CONFIG ah_config;
DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
- CURVNET_SET(vnet0);
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "can not if_alloc()\n");
- error = ENOSPC;
- CURVNET_RESTORE();
- goto bad;
- }
- ic = ifp->if_l2com;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(sc->sc_dev);
- if_initname(ifp, device_get_name(sc->sc_dev),
- device_get_unit(sc->sc_dev));
- CURVNET_RESTORE();
-
/*
* Configure the initial configuration data.
*
@@ -732,8 +717,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
sc->sc_tq = taskqueue_create("ath_taskq", M_NOWAIT,
taskqueue_thread_enqueue, &sc->sc_tq);
- taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
- "%s taskq", ifp->if_xname);
+ taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
+ device_get_nameunit(sc->sc_dev));
TASK_INIT(&sc->sc_rxtask, 0, sc->sc_rx.recv_tasklet, sc);
TASK_INIT(&sc->sc_bmisstask, 0, ath_bmiss_proc, sc);
@@ -876,17 +861,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
ath_led_config(sc);
ath_hal_setledstate(ah, HAL_LED_INIT);
- ifp->if_softc = sc;
- ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
- ifp->if_transmit = ath_transmit;
- ifp->if_qflush = ath_qflush;
- ifp->if_ioctl = ath_ioctl;
- ifp->if_init = ath_init;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
/* XXX not right but it's not used anywhere important */
ic->ic_phytype = IEEE80211_T_OFDM;
ic->ic_opmode = IEEE80211_M_STA;
@@ -1208,11 +1182,11 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
sc->sc_hasveol = ath_hal_hasveol(ah);
/* get mac address from kenv first, then hardware */
- if (ath_fetch_mac_kenv(sc, macaddr) == 0) {
+ if (ath_fetch_mac_kenv(sc, ic->ic_macaddr) == 0) {
/* Tell the HAL now about the new MAC */
- ath_hal_setmac(ah, macaddr);
+ ath_hal_setmac(ah, ic->ic_macaddr);
} else {
- ath_hal_getmac(ah, macaddr);
+ ath_hal_getmac(ah, ic->ic_macaddr);
}
if (sc->sc_hasbmask)
@@ -1221,12 +1195,15 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
/* NB: used to size node table key mapping array */
ic->ic_max_keyix = sc->sc_keymax;
/* call MI attach routine. */
- ieee80211_ifattach(ic, macaddr);
+ ieee80211_ifattach(ic);
ic->ic_setregdomain = ath_setregdomain;
ic->ic_getradiocaps = ath_getradiocaps;
sc->sc_opmode = HAL_M_STA;
/* override default methods */
+ ic->ic_ioctl = ath_ioctl;
+ ic->ic_parent = ath_parent;
+ ic->ic_transmit = ath_transmit;
ic->ic_newassoc = ath_newassoc;
ic->ic_updateslot = ath_updateslot;
ic->ic_wme.wme_update = ath_wme_update;
@@ -1322,16 +1299,6 @@ bad2:
bad:
if (ah)
ath_hal_detach(ah);
-
- /*
- * To work around scoping issues with CURVNET_SET/CURVNET_RESTORE..
- */
- if (ifp != NULL && ifp->if_vnet) {
- CURVNET_SET(ifp->if_vnet);
- if_free(ifp);
- CURVNET_RESTORE();
- } else if (ifp != NULL)
- if_free(ifp);
sc->sc_invalid = 1;
return error;
}
@@ -1339,10 +1306,6 @@ bad:
int
ath_detach(struct ath_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
-
- DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
- __func__, ifp->if_flags);
/*
* NB: the order of these is important:
@@ -1367,14 +1330,14 @@ ath_detach(struct ath_softc *sc)
ATH_LOCK(sc);
ath_power_set_power_state(sc, HAL_PM_AWAKE);
ath_power_setpower(sc, HAL_PM_AWAKE);
- ATH_UNLOCK(sc);
/*
* Stop things cleanly.
*/
- ath_stop(ifp);
+ ath_stop_locked(sc);
+ ATH_UNLOCK(sc);
- ieee80211_ifdetach(ifp->if_l2com);
+ ieee80211_ifdetach(&sc->sc_ic);
taskqueue_free(sc->sc_tq);
#ifdef ATH_TX99_DIAG
if (sc->sc_tx99 != NULL)
@@ -1394,10 +1357,6 @@ ath_detach(struct ath_softc *sc)
ath_tx_cleanup(sc);
ath_hal_detach(sc->sc_ah); /* NB: sets chip in full sleep */
- CURVNET_SET(ifp->if_vnet);
- if_free(ifp);
- CURVNET_RESTORE();
-
return 0;
}
@@ -1473,7 +1432,7 @@ ath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac0[IEEE80211_ADDR_LEN])
{
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_vap *avp;
struct ieee80211vap *vap;
uint8_t mac[IEEE80211_ADDR_LEN];
@@ -1581,8 +1540,7 @@ ath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
vap = &avp->av_vap;
/* XXX can't hold mutex across if_alloc */
ATH_UNLOCK(sc);
- error = ieee80211_vap_setup(ic, vap, name, unit, opmode, flags,
- bssid, mac);
+ error = ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
ATH_LOCK(sc);
if (error != 0) {
device_printf(sc->sc_dev, "%s: error %d creating vap\n",
@@ -1716,7 +1674,8 @@ ath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ATH_UNLOCK(sc);
/* complete setup */
- ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status);
+ ieee80211_vap_attach(vap, ath_media_change, ieee80211_media_status,
+ mac);
return vap;
bad2:
reclaim_address(sc, mac);
@@ -1731,8 +1690,7 @@ static void
ath_vap_delete(struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
struct ath_vap *avp = ATH_VAP(vap);
@@ -1741,7 +1699,7 @@ ath_vap_delete(struct ieee80211vap *vap)
ATH_UNLOCK(sc);
DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if (sc->sc_running) {
/*
* Quiesce the hardware while we remove the vap. In
* particular we need to reclaim all references to
@@ -1824,7 +1782,7 @@ ath_vap_delete(struct ieee80211vap *vap)
#endif
free(avp, M_80211_VAP);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if (sc->sc_running) {
/*
* Restart rx+tx machines if still running (RUNNING will
* be reset if we just destroyed the last vap).
@@ -1851,13 +1809,9 @@ ath_vap_delete(struct ieee80211vap *vap)
void
ath_suspend(struct ath_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
- DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
- __func__, ifp->if_flags);
-
- sc->sc_resume_up = (ifp->if_flags & IFF_UP) != 0;
+ sc->sc_resume_up = ic->ic_nrunning != 0;
ieee80211_suspend_all(ic);
/*
@@ -1898,8 +1852,7 @@ ath_suspend(struct ath_softc *sc)
static void
ath_reset_keycache(struct ath_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
int i;
@@ -1941,8 +1894,7 @@ ath_update_chainmasks(struct ath_softc *sc, struct ieee80211_channel *chan)
void
ath_resume(struct ath_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
HAL_STATUS status;
@@ -2015,12 +1967,8 @@ ath_resume(struct ath_softc *sc)
void
ath_shutdown(struct ath_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
- __func__, ifp->if_flags);
-
- ath_stop(ifp);
+ ath_stop(sc);
/* NB: no point powering down chip as we're about to reboot */
}
@@ -2031,7 +1979,6 @@ void
ath_intr(void *arg)
{
struct ath_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
struct ath_hal *ah = sc->sc_ah;
HAL_INT status = 0;
uint32_t txqs;
@@ -2070,12 +2017,11 @@ ath_intr(void *arg)
ath_power_set_power_state(sc, HAL_PM_AWAKE);
ATH_UNLOCK(sc);
- if ((ifp->if_flags & IFF_UP) == 0 ||
- (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ if (sc->sc_ic.ic_nrunning == 0 && sc->sc_running == 0) {
HAL_INT status;
- DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags 0x%x\n",
- __func__, ifp->if_flags);
+ DPRINTF(sc, ATH_DEBUG_ANY, "%s: ic_nrunning %d sc_running %d\n",
+ __func__, sc->sc_ic.ic_nrunning, sc->sc_running);
ath_hal_getisr(ah, &status); /* clear ISR */
ath_hal_intrset(ah, 0); /* disable further intr's */
ATH_PCU_UNLOCK(sc);
@@ -2313,11 +2259,13 @@ static void
ath_fatal_proc(void *arg, int pending)
{
struct ath_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
u_int32_t *state;
u_int32_t len;
void *sp;
+ if (sc->sc_invalid)
+ return;
+
device_printf(sc->sc_dev, "hardware error; resetting\n");
/*
* Fatal errors are unrecoverable. Typically these
@@ -2331,13 +2279,13 @@ ath_fatal_proc(void *arg, int pending)
"0x%08x 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x\n", state[0],
state[1] , state[2], state[3], state[4], state[5]);
}
- ath_reset(ifp, ATH_RESET_NOLOSS);
+ ath_reset(sc, ATH_RESET_NOLOSS);
}
static void
ath_bmiss_vap(struct ieee80211vap *vap)
{
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
/*
* Workaround phantom bmiss interrupts by sanity-checking
@@ -2358,8 +2306,6 @@ ath_bmiss_vap(struct ieee80211vap *vap)
ATH_UNLOCK(sc);
if ((vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) == 0) {
- struct ifnet *ifp = vap->iv_ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
u_int64_t lastrx = sc->sc_lastrx;
u_int64_t tsf = ath_hal_gettsf64(sc->sc_ah);
/* XXX should take a locked ref to iv_bss */
@@ -2417,7 +2363,6 @@ static void
ath_bmiss_proc(void *arg, int pending)
{
struct ath_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
uint32_t hangs;
DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending);
@@ -2435,12 +2380,12 @@ ath_bmiss_proc(void *arg, int pending)
* to clear.
*/
if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) {
- ath_reset(ifp, ATH_RESET_NOLOSS);
+ ath_reset(sc, ATH_RESET_NOLOSS);
device_printf(sc->sc_dev,
"bb hang detected (0x%x), resetting\n", hangs);
} else {
- ath_reset(ifp, ATH_RESET_NOLOSS);
- ieee80211_beacon_miss(ifp->if_l2com);
+ ath_reset(sc, ATH_RESET_NOLOSS);
+ ieee80211_beacon_miss(&sc->sc_ic);
}
/* Force a beacon resync, in case they've drifted */
@@ -2460,8 +2405,7 @@ ath_bmiss_proc(void *arg, int pending)
static void
ath_settkipmic(struct ath_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
if ((ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIP) && !sc->sc_wmetkipmic) {
if (ic->ic_flags & IEEE80211_F_WME) {
@@ -2475,11 +2419,9 @@ ath_settkipmic(struct ath_softc *sc)
}
static void
-ath_init(void *arg)
+ath_init(struct ath_softc *sc)
{
- struct ath_softc *sc = (struct ath_softc *) arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
HAL_STATUS status;
@@ -2498,7 +2440,7 @@ ath_init(void *arg)
* Stop anything previously setup. This is safe
* whether this is the first time through or not.
*/
- ath_stop_locked(ifp);
+ ath_stop_locked(sc);
/*
* The basic interface to setting the hardware in a good
@@ -2624,7 +2566,7 @@ ath_init(void *arg)
DPRINTF(sc, ATH_DEBUG_RESET, "%s: imask=0x%x\n",
__func__, sc->sc_imask);
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_running = 1;
callout_reset(&sc->sc_wd_ch, hz, ath_watchdog, sc);
ath_hal_intrset(ah, sc->sc_imask);
@@ -2640,14 +2582,10 @@ ath_init(void *arg)
}
static void
-ath_stop_locked(struct ifnet *ifp)
+ath_stop_locked(struct ath_softc *sc)
{
- struct ath_softc *sc = ifp->if_softc;
struct ath_hal *ah = sc->sc_ah;
- DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n",
- __func__, sc->sc_invalid, ifp->if_flags);
-
ATH_LOCK_ASSERT(sc);
/*
@@ -2655,7 +2593,7 @@ ath_stop_locked(struct ifnet *ifp)
*/
ath_power_set_power_state(sc, HAL_PM_AWAKE);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if (sc->sc_running) {
/*
* Shutdown the hardware and driver:
* reset 802.11 state machine
@@ -2677,7 +2615,7 @@ ath_stop_locked(struct ifnet *ifp)
#endif
callout_stop(&sc->sc_wd_ch);
sc->sc_wd_timer = 0;
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ sc->sc_running = 0;
if (!sc->sc_invalid) {
if (sc->sc_softled) {
callout_stop(&sc->sc_ledtimer);
@@ -2829,12 +2767,11 @@ ath_reset_grablock(struct ath_softc *sc, int dowait)
*/
static void
-ath_stop(struct ifnet *ifp)
+ath_stop(struct ath_softc *sc)
{
- struct ath_softc *sc = ifp->if_softc;
-
+
ATH_LOCK(sc);
- ath_stop_locked(ifp);
+ ath_stop_locked(sc);
ATH_UNLOCK(sc);
}
@@ -2846,10 +2783,9 @@ ath_stop(struct ifnet *ifp)
* to reset or reload hardware state.
*/
int
-ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
+ath_reset(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
{
- struct ath_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
HAL_STATUS status;
int i;
@@ -3011,15 +2947,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type)
}
}
- /*
- * This may have been set during an ath_start() call which
- * set this once it detected a concurrent TX was going on.
- * So, clear it.
- */
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
-
ATH_LOCK(sc);
ath_power_restore_power_state(sc);
ATH_UNLOCK(sc);
@@ -3041,8 +2968,7 @@ static int
ath_reset_vap(struct ieee80211vap *vap, u_long cmd)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
switch (cmd) {
@@ -3057,7 +2983,7 @@ ath_reset_vap(struct ieee80211vap *vap, u_long cmd)
return 0;
}
/* XXX? Full or NOLOSS? */
- return ath_reset(ifp, ATH_RESET_FULL);
+ return ath_reset(sc, ATH_RESET_FULL);
}
struct ath_buf *
@@ -3217,24 +3143,12 @@ ath_getbuf(struct ath_softc *sc, ath_buf_type_t btype)
bf = _ath_getbuf_locked(sc, ATH_BUFTYPE_NORMAL);
ATH_TXBUF_UNLOCK(sc);
if (bf == NULL) {
- struct ifnet *ifp = sc->sc_ifp;
-
DPRINTF(sc, ATH_DEBUG_XMIT, "%s: stop queue\n", __func__);
sc->sc_stats.ast_tx_qstop++;
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
}
return bf;
}
-static void
-ath_qflush(struct ifnet *ifp)
-{
-
- /* XXX TODO */
-}
-
/*
* Transmit a single frame.
*
@@ -3242,10 +3156,9 @@ ath_qflush(struct ifnet *ifp)
* fails, so don't free the node reference here.
*/
static int
-ath_transmit(struct ifnet *ifp, struct mbuf *m)
+ath_transmit(struct ieee80211com *ic, struct mbuf *m)
{
- struct ieee80211com *ic = ifp->if_l2com;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
struct mbuf *next;
struct ath_buf *bf;
@@ -3260,10 +3173,7 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m)
DPRINTF(sc, ATH_DEBUG_XMIT,
"%s: sc_inreset_cnt > 0; bailing\n", __func__);
ATH_PCU_UNLOCK(sc);
- IF_LOCK(&ifp->if_snd);
sc->sc_stats.ast_tx_qstop++;
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
ATH_KTR(sc, ATH_KTR_TX, 0, "ath_start_task: OACTIVE, finish");
return (ENOBUFS); /* XXX should be EINVAL or? */
}
@@ -3303,8 +3213,6 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m)
if ((!(m->m_flags & M_EAPOL)) &&
(ATH_NODE(ni)->an_swq_depth > sc->sc_txq_node_maxdepth)) {
sc->sc_stats.ast_tx_nodeq_overflow++;
- m_freem(m);
- m = NULL;
retval = ENOBUFS;
goto finish;
}
@@ -3328,8 +3236,6 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m)
if ((!(m->m_flags & M_EAPOL)) &&
(sc->sc_txbuf_cnt <= sc->sc_txq_data_minfree)) {
sc->sc_stats.ast_tx_nobuf++;
- m_freem(m);
- m = NULL;
retval = ENOBUFS;
goto finish;
}
@@ -3357,11 +3263,6 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m)
* above.
*/
sc->sc_stats.ast_tx_nobuf++;
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
- m_freem(m);
- m = NULL;
retval = ENOBUFS;
goto finish;
}
@@ -3383,8 +3284,13 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m)
DPRINTF(sc, ATH_DEBUG_XMIT,
"%s: out of txfrag buffers\n", __func__);
sc->sc_stats.ast_tx_nofrag++;
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
+ /*
+ * XXXGL: is mbuf valid after ath_txfrag_setup? If yes,
+ * we shouldn't free it but return back.
+ */
ath_freetx(m);
+ m = NULL;
goto bad;
}
@@ -3426,12 +3332,6 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m)
}
}
- /*
- * Bump the ifp output counter.
- *
- * XXX should use atomics?
- */
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
nextfrag:
/*
* Pass the frame to the h/w for transmission.
@@ -3451,7 +3351,7 @@ nextfrag:
next = m->m_nextpkt;
if (ath_tx_start(sc, ni, bf, m)) {
bad:
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
reclaim:
bf->bf_m = NULL;
bf->bf_node = NULL;
@@ -3535,8 +3435,7 @@ ath_media_change(struct ifnet *ifp)
static void
ath_key_update_begin(struct ieee80211vap *vap)
{
- struct ifnet *ifp = vap->iv_ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
taskqueue_block(sc->sc_tq);
@@ -3545,8 +3444,7 @@ ath_key_update_begin(struct ieee80211vap *vap)
static void
ath_key_update_end(struct ieee80211vap *vap)
{
- struct ifnet *ifp = vap->iv_ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__);
taskqueue_unblock(sc->sc_tq);
@@ -3577,32 +3475,41 @@ ath_update_promisc(struct ieee80211com *ic)
static void
ath_update_mcast_hw(struct ath_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
u_int32_t mfilt[2];
/* calculate and install multicast filter */
- if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
+ if (ic->ic_allmulti == 0) {
+ struct ieee80211vap *vap;
+ struct ifnet *ifp;
struct ifmultiaddr *ifma;
+
/*
* Merge multicast addresses to form the hardware filter.
*/
mfilt[0] = mfilt[1] = 0;
- if_maddr_rlock(ifp); /* XXX need some fiddling to remove? */
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- caddr_t dl;
- u_int32_t val;
- u_int8_t pos;
-
- /* calculate XOR of eight 6bit values */
- dl = LLADDR((struct sockaddr_dl *) ifma->ifma_addr);
- val = LE_READ_4(dl + 0);
- pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
- val = LE_READ_4(dl + 3);
- pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
- pos &= 0x3f;
- mfilt[pos / 32] |= (1 << (pos % 32));
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ ifp = vap->iv_ifp;
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ caddr_t dl;
+ uint32_t val;
+ uint8_t pos;
+
+ /* calculate XOR of eight 6bit values */
+ dl = LLADDR((struct sockaddr_dl *)
+ ifma->ifma_addr);
+ val = LE_READ_4(dl + 0);
+ pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^
+ val;
+ val = LE_READ_4(dl + 3);
+ pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^
+ val;
+ pos &= 0x3f;
+ mfilt[pos / 32] |= (1 << (pos % 32));
+ }
+ if_maddr_runlock(ifp);
}
- if_maddr_runlock(ifp);
} else
mfilt[0] = mfilt[1] = ~0;
@@ -3635,7 +3542,7 @@ ath_update_mcast(struct ieee80211com *ic)
void
ath_mode_init(struct ath_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
u_int32_t rfilt;
@@ -3646,15 +3553,8 @@ ath_mode_init(struct ath_softc *sc)
/* configure operational mode */
ath_hal_setopmode(ah);
- DPRINTF(sc, ATH_DEBUG_STATE | ATH_DEBUG_MODE,
- "%s: ah=%p, ifp=%p, if_addr=%p\n",
- __func__,
- ah,
- ifp,
- (ifp == NULL) ? NULL : ifp->if_addr);
-
/* handle any link-level address change */
- ath_hal_setmac(ah, IF_LLADDR(ifp));
+ ath_hal_setmac(ah, ic->ic_macaddr);
/* calculate and install multicast filter */
ath_update_mcast_hw(sc);
@@ -3666,7 +3566,7 @@ ath_mode_init(struct ath_softc *sc)
void
ath_setslottime(struct ath_softc *sc)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
u_int usec;
@@ -3750,12 +3650,11 @@ static void
ath_reset_proc(void *arg, int pending)
{
struct ath_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
#if 0
device_printf(sc->sc_dev, "%s: resetting\n", __func__);
#endif
- ath_reset(ifp, ATH_RESET_NOLOSS);
+ ath_reset(sc, ATH_RESET_NOLOSS);
}
/*
@@ -3765,7 +3664,6 @@ static void
ath_bstuck_proc(void *arg, int pending)
{
struct ath_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
uint32_t hangs = 0;
if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0)
@@ -3783,7 +3681,7 @@ ath_bstuck_proc(void *arg, int pending)
* This assumes that there's no simultaneous channel mode change
* occuring.
*/
- ath_reset(ifp, ATH_RESET_NOLOSS);
+ ath_reset(sc, ATH_RESET_NOLOSS);
}
static void
@@ -4153,7 +4051,7 @@ static struct ieee80211_node *
ath_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ieee80211com *ic = vap->iv_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
const size_t space = sizeof(struct ath_node) + sc->sc_rc->arc_space;
struct ath_node *an;
@@ -4180,7 +4078,7 @@ static void
ath_node_cleanup(struct ieee80211_node *ni)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__,
ni->ni_macaddr, ":", ATH_NODE(ni));
@@ -4195,7 +4093,7 @@ static void
ath_node_free(struct ieee80211_node *ni)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: an %p\n", __func__,
ni->ni_macaddr, ":", ATH_NODE(ni));
@@ -4207,7 +4105,7 @@ static void
ath_node_getsignal(const struct ieee80211_node *ni, int8_t *rssi, int8_t *noise)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
*rssi = ic->ic_node_getrssi(ni);
@@ -4345,8 +4243,7 @@ ath_txq_update(struct ath_softc *sc, int ac)
{
#define ATH_EXPONENT_TO_VALUE(v) ((1<<v)-1)
#define ATH_TXOP_TO_US(v) (v<<5)
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ath_txq *txq = sc->sc_ac2q[ac];
struct wmeParams *wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac];
struct ath_hal *ah = sc->sc_ah;
@@ -4419,7 +4316,7 @@ ath_txq_update(struct ath_softc *sc, int ac)
int
ath_wme_update(struct ieee80211com *ic)
{
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
return !ath_txq_update(sc, WME_AC_BE) ||
!ath_txq_update(sc, WME_AC_BK) ||
@@ -4470,8 +4367,7 @@ ath_tx_update_stats(struct ath_softc *sc, struct ath_tx_status *ts,
struct ath_buf *bf)
{
struct ieee80211_node *ni = bf->bf_node;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
int sr, lr, pri;
if (ts->ts_status == 0) {
@@ -4826,7 +4722,6 @@ static void
ath_tx_proc_q0(void *arg, int npending)
{
struct ath_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
uint32_t txqs;
ATH_PCU_LOCK(sc);
@@ -4847,9 +4742,6 @@ ath_tx_proc_q0(void *arg, int npending)
sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
if (TXQACTIVE(txqs, sc->sc_cabq->axq_qnum))
ath_tx_processq(sc, sc->sc_cabq, 1);
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
sc->sc_wd_timer = 0;
if (sc->sc_softled)
@@ -4874,7 +4766,6 @@ static void
ath_tx_proc_q0123(void *arg, int npending)
{
struct ath_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
int nacked;
uint32_t txqs;
@@ -4908,9 +4799,6 @@ ath_tx_proc_q0123(void *arg, int npending)
if (nacked)
sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
sc->sc_wd_timer = 0;
if (sc->sc_softled)
@@ -4934,7 +4822,6 @@ static void
ath_tx_proc(void *arg, int npending)
{
struct ath_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
int i, nacked;
uint32_t txqs;
@@ -4960,10 +4847,6 @@ ath_tx_proc(void *arg, int npending)
if (nacked)
sc->sc_lastrx = ath_hal_gettsf64(sc->sc_ah);
- /* XXX check this inside of IF_LOCK? */
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
sc->sc_wd_timer = 0;
if (sc->sc_softled)
@@ -5274,7 +5157,7 @@ ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq)
txq->axq_aggr_depth--;
#ifdef ATH_DEBUG
if (sc->sc_debug & ATH_DEBUG_RESET) {
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
int status = 0;
/*
@@ -5419,9 +5302,8 @@ void
ath_legacy_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
{
struct ath_hal *ah = sc->sc_ah;
- struct ifnet *ifp = sc->sc_ifp;
- int i;
struct ath_buf *bf_last;
+ int i;
(void) ath_stoptxdma(sc);
@@ -5473,15 +5355,12 @@ ath_legacy_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
ath_printtxbuf(sc, bf, sc->sc_bhalq, 0,
ath_hal_txprocdesc(ah, bf->bf_lastds,
&bf->bf_status.ds_txstat) == HAL_OK);
- ieee80211_dump_pkt(ifp->if_l2com,
+ ieee80211_dump_pkt(&sc->sc_ic,
mtod(bf->bf_m, const uint8_t *), bf->bf_m->m_len,
0, -1);
}
}
#endif /* ATH_DEBUG */
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
sc->sc_wd_timer = 0;
}
@@ -5512,8 +5391,7 @@ ath_chan_change(struct ath_softc *sc, struct ieee80211_channel *chan)
static int
ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
int ret = 0;
@@ -5648,9 +5526,6 @@ finish:
ath_hal_intrset(ah, sc->sc_imask);
ATH_PCU_UNLOCK(sc);
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
ath_txrx_start(sc);
/* XXX ath_start? */
@@ -5666,8 +5541,7 @@ ath_calibrate(void *arg)
{
struct ath_softc *sc = arg;
struct ath_hal *ah = sc->sc_ah;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
HAL_BOOL longCal, isCalDone = AH_TRUE;
HAL_BOOL aniCal, shortCal = AH_FALSE;
int nextcal;
@@ -5793,12 +5667,12 @@ restart:
static void
ath_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
u_int32_t rfilt;
/* XXX calibration timer? */
+ /* XXXGL: is constant ieee80211broadcastaddr a correct choice? */
ATH_LOCK(sc);
sc->sc_scanning = 1;
@@ -5808,18 +5682,17 @@ ath_scan_start(struct ieee80211com *ic)
ATH_PCU_LOCK(sc);
ath_hal_setrxfilter(ah, rfilt);
- ath_hal_setassocid(ah, ifp->if_broadcastaddr, 0);
+ ath_hal_setassocid(ah, ieee80211broadcastaddr, 0);
ATH_PCU_UNLOCK(sc);
DPRINTF(sc, ATH_DEBUG_STATE, "%s: RX filter 0x%x bssid %s aid 0\n",
- __func__, rfilt, ether_sprintf(ifp->if_broadcastaddr));
+ __func__, rfilt, ether_sprintf(ieee80211broadcastaddr));
}
static void
ath_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
u_int32_t rfilt;
@@ -5859,8 +5732,7 @@ ath_scan_end(struct ieee80211com *ic)
static void
ath_update_chw(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
DPRINTF(sc, ATH_DEBUG_STATE, "%s: called\n", __func__);
ath_set_channel(ic);
@@ -5870,8 +5742,7 @@ ath_update_chw(struct ieee80211com *ic)
static void
ath_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
ATH_LOCK(sc);
ath_power_set_power_state(sc, HAL_PM_AWAKE);
@@ -5913,7 +5784,7 @@ static int
ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_vap *avp = ATH_VAP(vap);
struct ath_hal *ah = sc->sc_ah;
struct ieee80211_node *ni = NULL;
@@ -6249,7 +6120,7 @@ static void
ath_setup_stationkey(struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
ieee80211_keyix keyix, rxkeyix;
/* XXX should take a locked ref to vap->iv_bss */
@@ -6282,7 +6153,7 @@ ath_newassoc(struct ieee80211_node *ni, int isnew)
{
struct ath_node *an = ATH_NODE(ni);
struct ieee80211vap *vap = ni->ni_vap;
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
const struct ieee80211_txparam *tp = ni->ni_txparms;
an->an_mcastrix = ath_tx_findrix(sc, tp->mcastrate);
@@ -6334,7 +6205,7 @@ static int
ath_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *reg,
int nchans, struct ieee80211_channel chans[])
{
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
HAL_STATUS status;
@@ -6358,7 +6229,7 @@ static void
ath_getradiocaps(struct ieee80211com *ic,
int maxchans, int *nchans, struct ieee80211_channel chans[])
{
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
DPRINTF(sc, ATH_DEBUG_REGDOMAIN, "%s: use rd %u cc %d\n",
@@ -6373,8 +6244,7 @@ ath_getradiocaps(struct ieee80211com *ic,
static int
ath_getchannels(struct ath_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
HAL_STATUS status;
@@ -6536,12 +6406,12 @@ static void
ath_watchdog(void *arg)
{
struct ath_softc *sc = arg;
+ struct ieee80211com *ic = &sc->sc_ic;
int do_reset = 0;
ATH_LOCK_ASSERT(sc);
if (sc->sc_wd_timer != 0 && --sc->sc_wd_timer == 0) {
- struct ifnet *ifp = sc->sc_ifp;
uint32_t hangs;
ath_power_set_power_state(sc, HAL_PM_AWAKE);
@@ -6553,7 +6423,7 @@ ath_watchdog(void *arg)
} else
device_printf(sc->sc_dev, "device timeout\n");
do_reset = 1;
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(ic->ic_oerrors, 1);
sc->sc_stats.ast_watchdog++;
ath_power_restore_power_state(sc);
@@ -6579,7 +6449,7 @@ static int
ath_ioctl_ratestats(struct ath_softc *sc, struct ath_rateioctl *rs)
{
struct ath_node *an;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
int error = 0;
@@ -6685,31 +6555,23 @@ bad:
}
#endif /* ATH_DIAGAPI */
-static int
-ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+ath_parent(struct ieee80211com *ic)
{
-#define IS_RUNNING(ifp) \
- ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
- struct ath_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *)data;
- const HAL_RATE_TABLE *rt;
- int error = 0;
+ struct ath_softc *sc = ic->ic_softc;
- switch (cmd) {
- case SIOCSIFFLAGS:
- if (IS_RUNNING(ifp)) {
- /*
- * To avoid rescanning another access point,
- * do not call ath_init() here. Instead,
- * only reflect promisc mode settings.
- */
- ATH_LOCK(sc);
+ ATH_LOCK(sc);
+ if (ic->ic_nrunning > 0) {
+ /*
+ * To avoid rescanning another access point,
+ * do not call ath_init() here. Instead,
+ * only reflect promisc mode settings.
+ */
+ if (sc->sc_running) {
ath_power_set_power_state(sc, HAL_PM_AWAKE);
ath_mode_init(sc);
ath_power_restore_power_state(sc);
- ATH_UNLOCK(sc);
- } else if (ifp->if_flags & IFF_UP) {
+ } else if (!sc->sc_invalid) {
/*
* Beware of being called during attach/detach
* to reset promiscuous mode. In that case we
@@ -6719,26 +6581,40 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
* torn down much of our state. There's
* probably a better way to deal with this.
*/
- if (!sc->sc_invalid)
- ath_init(sc); /* XXX lose error */
- } else {
- ATH_LOCK(sc);
- ath_stop_locked(ifp);
- if (!sc->sc_invalid)
- ath_power_setpower(sc, HAL_PM_FULL_SLEEP);
ATH_UNLOCK(sc);
+ ath_init(sc); /* XXX lose error */
+ return;
}
- break;
- case SIOCGIFMEDIA:
- case SIOCSIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGATHSTATS:
+ } else {
+ ath_stop_locked(sc);
+ if (!sc->sc_invalid)
+ ath_power_setpower(sc, HAL_PM_FULL_SLEEP);
+ }
+ ATH_UNLOCK(sc);
+}
+
+static int
+ath_ioctl(struct ieee80211com *ic, u_long cmd, void *data)
+{
+ struct ifreq *ifr = data;
+ struct ath_softc *sc = ic->ic_softc;
+
+ switch (cmd) {
+ case SIOCGATHSTATS: {
+ struct ieee80211vap *vap;
+ struct ifnet *ifp;
+ const HAL_RATE_TABLE *rt;
+
/* NB: embed these numbers to get a consistent view */
- sc->sc_stats.ast_tx_packets = ifp->if_get_counter(ifp,
- IFCOUNTER_OPACKETS);
- sc->sc_stats.ast_rx_packets = ifp->if_get_counter(ifp,
- IFCOUNTER_IPACKETS);
+ sc->sc_stats.ast_tx_packets = 0;
+ sc->sc_stats.ast_rx_packets = 0;
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ ifp = vap->iv_ifp;
+ sc->sc_stats.ast_tx_packets += ifp->if_get_counter(ifp,
+ IFCOUNTER_OPACKETS);
+ sc->sc_stats.ast_rx_packets += ifp->if_get_counter(ifp,
+ IFCOUNTER_IPACKETS);
+ }
sc->sc_stats.ast_tx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgtxrssi);
sc->sc_stats.ast_rx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgrssi);
#ifdef IEEE80211_SUPPORT_TDMA
@@ -6752,10 +6628,13 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
sc->sc_stats.ast_tx_rate |= IEEE80211_RATE_MCS;
return copyout(&sc->sc_stats,
ifr->ifr_data, sizeof (sc->sc_stats));
+ }
case SIOCGATHAGSTATS:
return copyout(&sc->sc_aggr_stats,
ifr->ifr_data, sizeof (sc->sc_aggr_stats));
- case SIOCZATHSTATS:
+ case SIOCZATHSTATS: {
+ int error;
+
error = priv_check(curthread, PRIV_DRIVER);
if (error == 0) {
memset(&sc->sc_stats, 0, sizeof(sc->sc_stats));
@@ -6764,30 +6643,21 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
memset(&sc->sc_intr_stats, 0,
sizeof(sc->sc_intr_stats));
}
- break;
+ return (error);
+ }
#ifdef ATH_DIAGAPI
case SIOCGATHDIAG:
- error = ath_ioctl_diag(sc, (struct ath_diag *) ifr);
- break;
+ return (ath_ioctl_diag(sc, data));
case SIOCGATHPHYERR:
- error = ath_ioctl_phyerr(sc,(struct ath_diag*) ifr);
- break;
+ return (ath_ioctl_phyerr(sc, data));
#endif
case SIOCGATHSPECTRAL:
- error = ath_ioctl_spectral(sc,(struct ath_diag*) ifr);
- break;
+ return (ath_ioctl_spectral(sc, data));
case SIOCGATHNODERATESTATS:
- error = ath_ioctl_ratestats(sc, (struct ath_rateioctl *) ifr);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
+ return (ath_ioctl_ratestats(sc, data));
default:
- error = EINVAL;
- break;
+ return (ENOTTY);
}
- return error;
-#undef IS_RUNNING
}
/*
@@ -6828,8 +6698,7 @@ static void
ath_dfs_tasklet(void *p, int npending)
{
struct ath_softc *sc = (struct ath_softc *) p;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
/*
* If previous processing has found a radar event,
@@ -6861,7 +6730,7 @@ ath_node_powersave(struct ieee80211_node *ni, int enable)
#ifdef ATH_SW_PSQ
struct ath_node *an = ATH_NODE(ni);
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
/* XXX and no TXQ locks should be held here */
@@ -6928,7 +6797,7 @@ ath_node_set_tim(struct ieee80211_node *ni, int enable)
{
#ifdef ATH_SW_PSQ
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_node *an = ATH_NODE(ni);
struct ath_vap *avp = ATH_VAP(ni->ni_vap);
int changed = 0;
@@ -7133,7 +7002,7 @@ ath_node_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m)
struct ath_node *an;
struct ath_vap *avp;
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
int tid;
/* Just paranoia */
diff --git a/sys/dev/ath/if_ath_beacon.c b/sys/dev/ath/if_ath_beacon.c
index a672c71..41267b3 100644
--- a/sys/dev/ath/if_ath_beacon.c
+++ b/sys/dev/ath/if_ath_beacon.c
@@ -134,7 +134,7 @@ int
ath_beaconq_config(struct ath_softc *sc)
{
#define ATH_EXPONENT_TO_VALUE(v) ((1<<(v))-1)
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
HAL_TXQ_INFO qi;
@@ -464,7 +464,7 @@ ath_beacon_proc(void *arg, int pending)
}
if (sc->sc_stagbeacons) { /* staggered beacons */
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tsftu;
tsftu = ath_hal_gettsf32(ah) >> 10;
@@ -917,7 +917,7 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap)
((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10))
#define FUDGE 2
struct ath_hal *ah = sc->sc_ah;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
u_int32_t nexttbtt, intval, tsftu;
u_int32_t nexttbtt_u8, intval_u8;
diff --git a/sys/dev/ath/if_ath_debug.h b/sys/dev/ath/if_ath_debug.h
index 40c0b9a..05d3cf5 100644
--- a/sys/dev/ath/if_ath_debug.h
+++ b/sys/dev/ath/if_ath_debug.h
@@ -91,9 +91,7 @@ enum {
extern uint64_t ath_debug;
-#define IFF_DUMPPKTS(sc, m) \
- ((sc->sc_debug & (m)) || \
- (sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
+#define IFF_DUMPPKTS(sc, m) ((sc->sc_debug & (m))
#define DPRINTF(sc, m, fmt, ...) do { \
if (sc->sc_debug & (m)) \
device_printf(sc->sc_dev, fmt, __VA_ARGS__); \
@@ -112,8 +110,7 @@ extern void ath_printtxstatbuf(struct ath_softc *sc, const struct ath_buf *bf,
#else /* ATH_DEBUG */
#define ATH_KTR(_sc, _km, _kf, ...) do { } while (0)
-#define IFF_DUMPPKTS(sc, m) \
- ((sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
+#define IFF_DUMPPKTS(sc, m) (0)
#define DPRINTF(sc, m, fmt, ...) do { \
(void) sc; \
} while (0)
diff --git a/sys/dev/ath/if_ath_keycache.c b/sys/dev/ath/if_ath_keycache.c
index fe99f10..b8a77e8 100644
--- a/sys/dev/ath/if_ath_keycache.c
+++ b/sys/dev/ath/if_ath_keycache.c
@@ -425,7 +425,7 @@ int
ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
{
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
/*
* Group key allocation must be handled specially for
@@ -493,7 +493,7 @@ ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
int
ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
{
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
const struct ieee80211_cipher *cip = k->wk_cipher;
u_int keyix = k->wk_keyix;
@@ -538,7 +538,7 @@ int
ath_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
const u_int8_t mac[IEEE80211_ADDR_LEN])
{
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
return ath_keyset(sc, vap, k, vap->iv_bss);
}
diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h
index 711e69e8..ff9a4db 100644
--- a/sys/dev/ath/if_ath_misc.h
+++ b/sys/dev/ath/if_ath_misc.h
@@ -65,7 +65,7 @@ extern void ath_freebuf(struct ath_softc *sc, struct ath_buf *bf);
extern void ath_returnbuf_head(struct ath_softc *sc, struct ath_buf *bf);
extern void ath_returnbuf_tail(struct ath_softc *sc, struct ath_buf *bf);
-extern int ath_reset(struct ifnet *, ATH_RESET_TYPE);
+extern int ath_reset(struct ath_softc *, ATH_RESET_TYPE);
extern void ath_tx_default_comp(struct ath_softc *sc, struct ath_buf *bf,
int fail);
extern void ath_tx_update_ratectrl(struct ath_softc *sc,
diff --git a/sys/dev/ath/if_ath_rx.c b/sys/dev/ath/if_ath_rx.c
index 2779b7a..600d0a5 100644
--- a/sys/dev/ath/if_ath_rx.c
+++ b/sys/dev/ath/if_ath_rx.c
@@ -154,8 +154,7 @@ __FBSDID("$FreeBSD$");
u_int32_t
ath_calcrxfilter(struct ath_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
u_int32_t rfilt;
rfilt = HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST;
@@ -164,7 +163,7 @@ ath_calcrxfilter(struct ath_softc *sc)
if (ic->ic_opmode != IEEE80211_M_STA)
rfilt |= HAL_RX_FILTER_PROBEREQ;
/* XXX ic->ic_monvaps != 0? */
- if (ic->ic_opmode == IEEE80211_M_MONITOR || (ifp->if_flags & IFF_PROMISC))
+ if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_promisc > 0)
rfilt |= HAL_RX_FILTER_PROM;
/*
@@ -330,7 +329,7 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
int subtype, const struct ieee80211_rx_stats *rxs, int rssi, int nf)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = vap->iv_ic->ic_softc;
uint64_t tsf_beacon_old, tsf_beacon;
uint64_t nexttbtt;
int64_t tsf_delta;
@@ -463,10 +462,9 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
#ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT
static void
-ath_rx_tap_vendor(struct ifnet *ifp, struct mbuf *m,
+ath_rx_tap_vendor(struct ath_softc *sc, struct mbuf *m,
const struct ath_rx_status *rs, u_int64_t tsf, int16_t nf)
{
- struct ath_softc *sc = ifp->if_softc;
/* Fill in the extension bitmap */
sc->sc_rx_th.wr_ext_bitmap = htole32(1 << ATH_RADIOTAP_VENDOR_HEADER);
@@ -529,14 +527,13 @@ ath_rx_tap_vendor(struct ifnet *ifp, struct mbuf *m,
#endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */
static void
-ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
+ath_rx_tap(struct ath_softc *sc, struct mbuf *m,
const struct ath_rx_status *rs, u_int64_t tsf, int16_t nf)
{
#define CHAN_HT20 htole32(IEEE80211_CHAN_HT20)
#define CHAN_HT40U htole32(IEEE80211_CHAN_HT40U)
#define CHAN_HT40D htole32(IEEE80211_CHAN_HT40D)
#define CHAN_HT (CHAN_HT20|CHAN_HT40U|CHAN_HT40D)
- struct ath_softc *sc = ifp->if_softc;
const HAL_RATE_TABLE *rt;
uint8_t rix;
@@ -560,7 +557,7 @@ ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
else if (IEEE80211_IS_CHAN_HT20(sc->sc_curchan))
sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
} else if (sc->sc_rx_th.wr_rate & IEEE80211_RATE_MCS) { /* HT rate */
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
if ((rs->rs_flags & HAL_RX_2040) == 0)
sc->sc_rx_th.wr_chan_flags |= CHAN_HT20;
@@ -617,8 +614,7 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
{
uint64_t rstamp;
int len, type;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
int is_good = 0;
struct ath_rx_edma *re = &sc->sc_rxedma[qtype];
@@ -704,7 +700,7 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status,
rs->rs_keyix-32 : rs->rs_keyix);
}
}
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
rx_error:
/*
* Cleanup any pending partial frame.
@@ -724,9 +720,9 @@ rx_error:
/* NB: bpf needs the mbuf length setup */
len = rs->rs_datalen;
m->m_pkthdr.len = m->m_len = len;
- ath_rx_tap(ifp, m, rs, rstamp, nf);
+ ath_rx_tap(sc, m, rs, rstamp, nf);
#ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT
- ath_rx_tap_vendor(ifp, m, rs, rstamp, nf);
+ ath_rx_tap_vendor(sc, m, rs, rstamp, nf);
#endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */
ieee80211_radiotap_rx_all(ic, m);
}
@@ -749,7 +745,6 @@ rx_accept:
sc->sc_stats.ast_rx_toobig++;
m_freem(re->m_rxpending);
}
- m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = len;
re->m_rxpending = m;
m = NULL;
@@ -766,10 +761,8 @@ rx_accept:
re->m_rxpending = NULL;
} else {
/*
- * Normal single-descriptor receive; setup
- * the rcvif and packet length.
+ * Normal single-descriptor receive; setup packet length.
*/
- m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = len;
}
@@ -830,7 +823,6 @@ rx_accept:
rs->rs_antenna |= 0x4;
}
- if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
sc->sc_stats.ast_ant_rx[rs->rs_antenna]++;
/*
@@ -841,9 +833,9 @@ rx_accept:
* noise setting is filled in above.
*/
if (ieee80211_radiotap_active(ic)) {
- ath_rx_tap(ifp, m, rs, rstamp, nf);
+ ath_rx_tap(sc, m, rs, rstamp, nf);
#ifdef ATH_ENABLE_RADIOTAP_VENDOR_EXT
- ath_rx_tap_vendor(ifp, m, rs, rstamp, nf);
+ ath_rx_tap_vendor(sc, m, rs, rstamp, nf);
#endif /* ATH_ENABLE_RADIOTAP_VENDOR_EXT */
}
@@ -991,10 +983,9 @@ ath_rx_proc(struct ath_softc *sc, int resched)
((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
struct ath_buf *bf;
- struct ifnet *ifp = sc->sc_ifp;
struct ath_hal *ah = sc->sc_ah;
#ifdef IEEE80211_SUPPORT_SUPERG
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
#endif
struct ath_desc *ds;
struct ath_rx_status *rs;
@@ -1189,15 +1180,10 @@ rx_proc_next:
ATH_PCU_UNLOCK(sc);
}
- /* XXX check this inside of IF_LOCK? */
- if (resched && (ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
#ifdef IEEE80211_SUPPORT_SUPERG
+ if (resched)
ieee80211_ff_age_all(ic, 100);
#endif
- if (!IFQ_IS_EMPTY(&ifp->if_snd))
- ath_tx_kick(sc);
- }
-#undef PA2DESC
/*
* Put the hardware to sleep again if we're done with it.
@@ -1219,7 +1205,7 @@ rx_proc_next:
sc->sc_rxproc_cnt--;
ATH_PCU_UNLOCK(sc);
}
-
+#undef PA2DESC
#undef ATH_RX_MAX
/*
diff --git a/sys/dev/ath/if_ath_rx_edma.c b/sys/dev/ath/if_ath_rx_edma.c
index 7aa818f..c3e8d3a 100644
--- a/sys/dev/ath/if_ath_rx_edma.c
+++ b/sys/dev/ath/if_ath_rx_edma.c
@@ -579,9 +579,8 @@ static void
ath_edma_recv_tasklet(void *arg, int npending)
{
struct ath_softc *sc = (struct ath_softc *) arg;
- struct ifnet *ifp = sc->sc_ifp;
#ifdef IEEE80211_SUPPORT_SUPERG
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
#endif
DPRINTF(sc, ATH_DEBUG_EDMA_RX, "%s: called; npending=%d\n",
@@ -617,14 +616,9 @@ ath_edma_recv_tasklet(void *arg, int npending)
ath_power_restore_power_state(sc);
ATH_UNLOCK(sc);
- /* XXX inside IF_LOCK ? */
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
#ifdef IEEE80211_SUPPORT_SUPERG
- ieee80211_ff_age_all(ic, 100);
+ ieee80211_ff_age_all(ic, 100);
#endif
- if (! IFQ_IS_EMPTY(&ifp->if_snd))
- ath_tx_kick(sc);
- }
if (ath_dfs_tasklet_needed(sc, sc->sc_curchan))
taskqueue_enqueue(sc->sc_tq, &sc->sc_dfstask);
diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c
index eeb8d4b..d8c6bac 100644
--- a/sys/dev/ath/if_ath_sysctl.c
+++ b/sys/dev/ath/if_ath_sysctl.c
@@ -367,7 +367,6 @@ static int
ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS)
{
struct ath_softc *sc = arg1;
- struct ifnet *ifp = sc->sc_ifp;
u_int32_t scale;
int error;
@@ -381,8 +380,7 @@ ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS)
goto finish;
error = !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL :
- (ifp->if_drv_flags & IFF_DRV_RUNNING) ?
- ath_reset(ifp, ATH_RESET_NOLOSS) : 0;
+ (sc->sc_running) ? ath_reset(sc, ATH_RESET_NOLOSS) : 0;
finish:
ATH_LOCK(sc);
@@ -422,7 +420,6 @@ static int
ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
{
struct ath_softc *sc = arg1;
- struct ifnet *ifp = sc->sc_ifp;
struct ath_hal *ah = sc->sc_ah;
u_int rfkill;
int error;
@@ -444,8 +441,7 @@ ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
error = EINVAL;
goto finish;
}
- error = (ifp->if_drv_flags & IFF_DRV_RUNNING) ?
- ath_reset(ifp, ATH_RESET_FULL) : 0;
+ error = sc->sc_running ? ath_reset(sc, ATH_RESET_FULL) : 0;
finish:
ATH_LOCK(sc);
@@ -671,8 +667,8 @@ ath_sysctl_intmit(SYSCTL_HANDLER_ARGS)
* doesn't reset ANI related registers, so it'll leave
* things in an inconsistent state.
*/
- if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
- ath_reset(sc->sc_ifp, ATH_RESET_NOLOSS);
+ if (sc->sc_running)
+ ath_reset(sc, ATH_RESET_NOLOSS);
error = 0;
diff --git a/sys/dev/ath/if_ath_tdma.c b/sys/dev/ath/if_ath_tdma.c
index fd23db1..d4c9ccd 100644
--- a/sys/dev/ath/if_ath_tdma.c
+++ b/sys/dev/ath/if_ath_tdma.c
@@ -359,7 +359,7 @@ ath_tdma_update(struct ieee80211_node *ni,
#define TU_TO_TSF(_tu) (((u_int64_t)(_tu)) << 10)
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
- struct ath_softc *sc = ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_hal *ah = sc->sc_ah;
const HAL_RATE_TABLE *rt = sc->sc_currates;
u_int64_t tsf, rstamp, nextslot, nexttbtt, nexttbtt_full;
diff --git a/sys/dev/ath/if_ath_tx.c b/sys/dev/ath/if_ath_tx.c
index c15b158..bee6320 100644
--- a/sys/dev/ath/if_ath_tx.c
+++ b/sys/dev/ath/if_ath_tx.c
@@ -1051,8 +1051,7 @@ ath_tx_calc_protection(struct ath_softc *sc, struct ath_buf *bf)
uint16_t flags;
int shortPreamble;
const HAL_RATE_TABLE *rt = sc->sc_currates;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
flags = bf->bf_state.bfs_txflags;
rix = bf->bf_state.bfs_rc[0].rix;
@@ -1545,8 +1544,7 @@ ath_tx_normal_setup(struct ath_softc *sc, struct ieee80211_node *ni,
{
struct ieee80211vap *vap = ni->ni_vap;
struct ath_hal *ah = sc->sc_ah;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
const struct chanAccParams *cap = &ic->ic_wme.wme_chanParams;
int error, iswep, ismcast, isfrag, ismrr;
int keyix, hdrlen, pktlen, try0 = 0;
@@ -2074,8 +2072,7 @@ ath_tx_raw_start(struct ath_softc *sc, struct ieee80211_node *ni,
struct ath_buf *bf, struct mbuf *m0,
const struct ieee80211_bpf_params *params)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
struct ieee80211vap *vap = ni->ni_vap;
int error, ismcast, ismrr;
@@ -2340,8 +2337,7 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct ath_softc *sc = ifp->if_softc;
+ struct ath_softc *sc = ic->ic_softc;
struct ath_buf *bf;
struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
int error = 0;
@@ -2364,10 +2360,9 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
ATH_TX_LOCK(sc);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) {
- DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, %s", __func__,
- (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ?
- "!running" : "invalid");
+ if (!sc->sc_running || sc->sc_invalid) {
+ DPRINTF(sc, ATH_DEBUG_XMIT, "%s: discard frame, r/i: %d/%d",
+ __func__, sc->sc_running, sc->sc_invalid);
m_freem(m);
error = ENETDOWN;
goto bad;
@@ -2424,7 +2419,6 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
}
}
sc->sc_wd_timer = 5;
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
sc->sc_stats.ast_tx_raw++;
/*
@@ -2473,7 +2467,6 @@ bad:
badbad:
ATH_KTR(sc, ATH_KTR_TX, 2, "ath_raw_xmit: bad0: m=%p, params=%p",
m, params);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
sc->sc_stats.ast_tx_raw_fail++;
ieee80211_free_node(ni);
@@ -5731,7 +5724,7 @@ int
ath_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
int dialogtoken, int baparamset, int batimeout)
{
- struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
@@ -5809,7 +5802,7 @@ int
ath_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
int status, int code, int batimeout)
{
- struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
@@ -5856,7 +5849,7 @@ ath_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
void
ath_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
{
- struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
@@ -5991,7 +5984,7 @@ void
ath_bar_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
int status)
{
- struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
@@ -6064,7 +6057,7 @@ void
ath_addba_response_timeout(struct ieee80211_node *ni,
struct ieee80211_tx_ampdu *tap)
{
- struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct ath_softc *sc = ni->ni_ic->ic_softc;
int tid = tap->txa_tid;
struct ath_node *an = ATH_NODE(ni);
struct ath_tid *atid = &an->an_tid[tid];
diff --git a/sys/dev/ath/if_ath_tx_edma.c b/sys/dev/ath/if_ath_tx_edma.c
index 7d14920..fdc2b4b 100644
--- a/sys/dev/ath/if_ath_tx_edma.c
+++ b/sys/dev/ath/if_ath_tx_edma.c
@@ -537,7 +537,6 @@ ath_edma_dma_txteardown(struct ath_softc *sc)
static void
ath_edma_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
{
- struct ifnet *ifp = sc->sc_ifp;
int i;
DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__);
@@ -579,9 +578,6 @@ ath_edma_tx_drain(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
/* XXX dump out the frames */
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
sc->sc_wd_timer = 0;
}
@@ -834,12 +830,6 @@ ath_edma_tx_processq(struct ath_softc *sc, int dosched)
sc->sc_wd_timer = 0;
- if (idx > 0) {
- IF_LOCK(&sc->sc_ifp->if_snd);
- sc->sc_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- IF_UNLOCK(&sc->sc_ifp->if_snd);
- }
-
/* Kick software scheduler */
/*
* XXX It's inefficient to do this if the FIFO queue is full,
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 5c5e6cd..2e71ff6 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -555,8 +555,8 @@ struct ath_tx_methods {
};
struct ath_softc {
- struct ifnet *sc_ifp; /* interface common */
- struct ath_stats sc_stats; /* interface statistics */
+ struct ieee80211com sc_ic;
+ struct ath_stats sc_stats; /* device statistics */
struct ath_tx_aggr_stats sc_aggr_stats;
struct ath_intr_stats sc_intr_stats;
uint64_t sc_debug;
@@ -650,7 +650,8 @@ struct ath_softc {
/*
* Second set of flags.
*/
- u_int32_t sc_use_ent : 1,
+ u_int32_t sc_running : 1, /* initialized */
+ sc_use_ent : 1,
sc_rx_stbc : 1,
sc_tx_stbc : 1,
sc_hasenforcetxop : 1, /* support enforce TxOP */
diff --git a/sys/dev/bwi/bwimac.c b/sys/dev/bwi/bwimac.c
index f39ef44..baad7fe 100644
--- a/sys/dev/bwi/bwimac.c
+++ b/sys/dev/bwi/bwimac.c
@@ -832,11 +832,11 @@ bwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw,
uint8_t fw_type)
{
const struct bwi_fwhdr *hdr;
- struct ifnet *ifp = sc->sc_ifp;
if (fw->datasize < sizeof(*hdr)) {
- if_printf(ifp, "invalid firmware (%s): invalid size %zu\n",
- fw->name, fw->datasize);
+ device_printf(sc->sc_dev,
+ "invalid firmware (%s): invalid size %zu\n",
+ fw->name, fw->datasize);
return 0;
}
@@ -847,25 +847,26 @@ bwi_fwimage_is_valid(struct bwi_softc *sc, const struct firmware *fw,
* Don't verify IV's size, it has different meaning
*/
if (be32toh(hdr->fw_size) != fw->datasize - sizeof(*hdr)) {
- if_printf(ifp, "invalid firmware (%s): size mismatch, "
- "fw %u, real %zu\n", fw->name,
- be32toh(hdr->fw_size),
- fw->datasize - sizeof(*hdr));
+ device_printf(sc->sc_dev,
+ "invalid firmware (%s): size mismatch, "
+ "fw %u, real %zu\n", fw->name,
+ be32toh(hdr->fw_size), fw->datasize - sizeof(*hdr));
return 0;
}
}
if (hdr->fw_type != fw_type) {
- if_printf(ifp, "invalid firmware (%s): type mismatch, "
- "fw \'%c\', target \'%c\'\n", fw->name,
- hdr->fw_type, fw_type);
+ device_printf(sc->sc_dev,
+ "invalid firmware (%s): type mismatch, "
+ "fw \'%c\', target \'%c\'\n", fw->name,
+ hdr->fw_type, fw_type);
return 0;
}
if (hdr->fw_gen != BWI_FW_GEN_1) {
- if_printf(ifp, "invalid firmware (%s): wrong generation, "
- "fw %d, target %d\n", fw->name,
- hdr->fw_gen, BWI_FW_GEN_1);
+ device_printf(sc->sc_dev,
+ "invalid firmware (%s): wrong generation, "
+ "fw %d, target %d\n", fw->name, hdr->fw_gen, BWI_FW_GEN_1);
return 0;
}
return 1;
@@ -1002,7 +1003,6 @@ static int
bwi_mac_fw_load(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
const uint32_t *fw;
uint16_t fw_rev;
int fw_len, i;
@@ -1057,7 +1057,8 @@ bwi_mac_fw_load(struct bwi_mac *mac)
DELAY(10);
}
if (i == NRETRY) {
- if_printf(ifp, "firmware (ucode&pcm) loading timed out\n");
+ device_printf(sc->sc_dev,
+ "firmware (ucode&pcm) loading timed out\n");
return ETIMEDOUT;
}
@@ -1067,12 +1068,14 @@ bwi_mac_fw_load(struct bwi_mac *mac)
fw_rev = MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWREV);
if (fw_rev > BWI_FW_VERSION3_REVMAX) {
- if_printf(ifp, "firmware version 4 is not supported yet\n");
+ device_printf(sc->sc_dev,
+ "firmware version 4 is not supported yet\n");
return ENODEV;
}
- if_printf(ifp, "firmware rev 0x%04x, patch level 0x%04x\n", fw_rev,
- MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV));
+ device_printf(sc->sc_dev,
+ "firmware rev 0x%04x, patch level 0x%04x\n", fw_rev,
+ MOBJ_READ_2(mac, BWI_COMM_MOBJ, BWI_COMM_MOBJ_FWPATCHLV));
return 0;
}
@@ -1132,7 +1135,6 @@ static int
bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
const struct bwi_fwhdr *hdr;
const struct bwi_fw_iv *iv;
int n, i, iv_img_size;
@@ -1155,7 +1157,7 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
int sz = 0;
if (iv_img_size < sizeof(iv->iv_ofs)) {
- if_printf(ifp, "invalid IV image, ofs\n");
+ device_printf(sc->sc_dev, "invalid IV image, ofs\n");
return EINVAL;
}
iv_img_size -= sizeof(iv->iv_ofs);
@@ -1165,7 +1167,7 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
ofs = __SHIFTOUT(iv_ofs, BWI_FW_IV_OFS_MASK);
if (ofs >= 0x1000) {
- if_printf(ifp, "invalid ofs (0x%04x) "
+ device_printf(sc->sc_dev, "invalid ofs (0x%04x) "
"for %dth iv\n", ofs, i);
return EINVAL;
}
@@ -1174,7 +1176,8 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
uint32_t val32;
if (iv_img_size < sizeof(iv->iv_val.val32)) {
- if_printf(ifp, "invalid IV image, val32\n");
+ device_printf(sc->sc_dev,
+ "invalid IV image, val32\n");
return EINVAL;
}
iv_img_size -= sizeof(iv->iv_val.val32);
@@ -1186,7 +1189,8 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
uint16_t val16;
if (iv_img_size < sizeof(iv->iv_val.val16)) {
- if_printf(ifp, "invalid IV image, val16\n");
+ device_printf(sc->sc_dev,
+ "invalid IV image, val16\n");
return EINVAL;
}
iv_img_size -= sizeof(iv->iv_val.val16);
@@ -1200,7 +1204,8 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
}
if (iv_img_size != 0) {
- if_printf(ifp, "invalid IV image, size left %d\n", iv_img_size);
+ device_printf(sc->sc_dev, "invalid IV image, size left %d\n",
+ iv_img_size);
return EINVAL;
}
return 0;
@@ -1209,19 +1214,19 @@ bwi_mac_fw_load_iv(struct bwi_mac *mac, const struct firmware *fw)
static int
bwi_mac_fw_init(struct bwi_mac *mac)
{
- struct ifnet *ifp = mac->mac_sc->sc_ifp;
+ device_t dev = mac->mac_sc->sc_dev;
int error;
error = bwi_mac_fw_load_iv(mac, mac->mac_iv);
if (error) {
- if_printf(ifp, "load IV failed\n");
+ device_printf(dev, "load IV failed\n");
return error;
}
if (mac->mac_iv_ext != NULL) {
error = bwi_mac_fw_load_iv(mac, mac->mac_iv_ext);
if (error)
- if_printf(ifp, "load ExtIV failed\n");
+ device_printf(dev, "load ExtIV failed\n");
}
return error;
}
@@ -1230,8 +1235,7 @@ static void
bwi_mac_opmode_init(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t mac_status;
uint16_t pre_tbtt;
@@ -1280,7 +1284,7 @@ bwi_mac_opmode_init(struct bwi_mac *mac)
break;
}
- if (ic->ic_ifp->if_flags & IFF_PROMISC)
+ if (ic->ic_promisc > 0)
mac_status |= BWI_MAC_STATUS_PROMISC;
CSR_WRITE_4(sc, BWI_MAC_STATUS, mac_status);
@@ -1331,8 +1335,7 @@ bwi_mac_bss_param_init(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
struct bwi_phy *phy = &mac->mac_phy;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
const struct ieee80211_rate_table *rt;
struct bwi_retry_lim lim;
uint16_t cw_min;
@@ -1915,8 +1918,7 @@ static void
bwi_mac_lock(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
KASSERT((mac->mac_flags & BWI_MAC_F_LOCKED) == 0,
("mac_flags 0x%x", mac->mac_flags));
@@ -1939,8 +1941,7 @@ static void
bwi_mac_unlock(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
KASSERT(mac->mac_flags & BWI_MAC_F_LOCKED,
("mac_flags 0x%x", mac->mac_flags));
diff --git a/sys/dev/bwi/bwiphy.c b/sys/dev/bwi/bwiphy.c
index 1057a83..60d6bf5 100644
--- a/sys/dev/bwi/bwiphy.c
+++ b/sys/dev/bwi/bwiphy.c
@@ -429,7 +429,7 @@ static void
bwi_phy_init_11b_rev2(struct bwi_mac *mac)
{
/* TODO:11B */
- if_printf(mac->mac_sc->sc_ifp,
+ device_printf(mac->mac_sc->sc_dev,
"%s is not implemented yet\n", __func__);
}
diff --git a/sys/dev/bwi/bwirf.c b/sys/dev/bwi/bwirf.c
index cd0723a..615e6df 100644
--- a/sys/dev/bwi/bwirf.c
+++ b/sys/dev/bwi/bwirf.c
@@ -1260,7 +1260,6 @@ static void
bwi_rf_lo_update_11g(struct bwi_mac *mac)
{
struct bwi_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
struct bwi_rf *rf = &mac->mac_rf;
struct bwi_phy *phy = &mac->mac_phy;
struct bwi_tpctl *tpctl = &mac->mac_tpctl;
@@ -1329,7 +1328,7 @@ bwi_rf_lo_update_11g(struct bwi_mac *mac)
PHY_WRITE(mac, 0x812, 0xb2);
}
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ if ((sc->sc_flags & BWI_F_RUNNING) == 0)
tpctl->tp_ctrl2 = bwi_rf_get_tp_ctrl2(mac);
PHY_WRITE(mac, 0x80f, 0x8078);
@@ -1352,7 +1351,7 @@ bwi_rf_lo_update_11g(struct bwi_mac *mac)
PHY_WRITE(mac, 0x15, devi_ctrl | 0xefa0);
}
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ if ((sc->sc_flags & BWI_F_RUNNING) == 0)
tpctl = NULL;
bwi_rf_lo_adjust(mac, tpctl);
@@ -1462,7 +1461,7 @@ _bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a)
static const int rf_lo_measure_order[RF_ATTEN_LISTSZ] =
{ 3, 1, 5, 7, 9, 2, 0, 4, 6, 8, 10, 11, 12, 13 };
- struct ifnet *ifp = mac->mac_sc->sc_ifp;
+ struct bwi_softc *sc = mac->mac_sc;
struct bwi_rf_lo lo_save, *lo;
uint8_t devi_ctrl = 0;
int idx, adj_rf7a = 0;
@@ -1476,7 +1475,7 @@ _bwi_rf_lo_update_11g(struct bwi_mac *mac, uint16_t orig_rf7a)
for (bbp_atten = 0; bbp_atten < BBP_ATTEN_MAX; ++bbp_atten) {
uint16_t tp_ctrl2, rf7a;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ if ((sc->sc_flags & BWI_F_RUNNING) == 0) {
if (idx == 0) {
bzero(&lo_save, sizeof(lo_save));
} else if (init_rf_atten < 0) {
diff --git a/sys/dev/bwi/if_bwi.c b/sys/dev/bwi/if_bwi.c
index ad41bc6..741f5f1 100644
--- a/sys/dev/bwi/if_bwi.c
+++ b/sys/dev/bwi/if_bwi.c
@@ -102,10 +102,10 @@ static struct ieee80211vap *bwi_vap_create(struct ieee80211com *,
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void bwi_vap_delete(struct ieee80211vap *);
-static void bwi_init(void *);
-static int bwi_ioctl(struct ifnet *, u_long, caddr_t);
-static void bwi_start(struct ifnet *);
-static void bwi_start_locked(struct ifnet *);
+static void bwi_init(struct bwi_softc *);
+static void bwi_parent(struct ieee80211com *);
+static int bwi_transmit(struct ieee80211com *, struct mbuf *);
+static void bwi_start_locked(struct bwi_softc *);
static int bwi_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void bwi_watchdog(void *);
@@ -352,14 +352,12 @@ bwi_setup_desc32(struct bwi_softc *sc, struct bwi_desc32 *desc_array,
int
bwi_attach(struct bwi_softc *sc)
{
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
device_t dev = sc->sc_dev;
- struct ifnet *ifp;
struct bwi_mac *mac;
struct bwi_phy *phy;
int i, error;
uint8_t bands;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
BWI_LOCK_INIT(sc);
@@ -371,8 +369,8 @@ bwi_attach(struct bwi_softc *sc)
taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
device_get_nameunit(dev));
TASK_INIT(&sc->sc_restart_task, 0, bwi_restart, sc);
-
callout_init_mtx(&sc->sc_calib_ch, &sc->sc_mtx, 0);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
/*
* Initialize sysctl variables
@@ -450,25 +448,6 @@ bwi_attach(struct bwi_softc *sc)
if (error)
goto fail;
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(dev, "can not if_alloc()\n");
- error = ENOSPC;
- goto fail;
- }
- ic = ifp->if_l2com;
-
- /* set these up early for if_printf use */
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
-
- ifp->if_softc = sc;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = bwi_init;
- ifp->if_ioctl = bwi_ioctl;
- ifp->if_start = bwi_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
callout_init_mtx(&sc->sc_watchdog_timer, &sc->sc_mtx, 0);
/*
@@ -485,13 +464,13 @@ bwi_attach(struct bwi_softc *sc)
setbit(&bands, IEEE80211_MODE_11G);
}
- bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, macaddr);
- if (IEEE80211_IS_MULTICAST(macaddr)) {
- bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, macaddr);
- if (IEEE80211_IS_MULTICAST(macaddr)) {
+ bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, ic->ic_macaddr);
+ if (IEEE80211_IS_MULTICAST(ic->ic_macaddr)) {
+ bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, ic->ic_macaddr);
+ if (IEEE80211_IS_MULTICAST(ic->ic_macaddr)) {
device_printf(dev,
"invalid MAC address: %6D\n",
- macaddr, ":");
+ ic->ic_macaddr, ":");
}
}
} else if (phy->phy_mode == IEEE80211_MODE_11A) {
@@ -510,7 +489,6 @@ bwi_attach(struct bwi_softc *sc)
/* XXX use locale */
ieee80211_init_channels(ic, NULL, &bands);
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_caps = IEEE80211_C_STA |
@@ -520,7 +498,7 @@ bwi_attach(struct bwi_softc *sc)
IEEE80211_C_BGSCAN |
IEEE80211_C_MONITOR;
ic->ic_opmode = IEEE80211_M_STA;
- ieee80211_ifattach(ic, macaddr);
+ ieee80211_ifattach(ic);
ic->ic_headroom = sizeof(struct bwi_txbuf_hdr);
@@ -532,6 +510,8 @@ bwi_attach(struct bwi_softc *sc)
ic->ic_scan_start = bwi_scan_start;
ic->ic_scan_end = bwi_scan_end;
ic->ic_set_channel = bwi_set_channel;
+ ic->ic_transmit = bwi_transmit;
+ ic->ic_parent = bwi_parent;
sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
@@ -577,8 +557,7 @@ fail:
int
bwi_detach(struct bwi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
int i;
bwi_stop(sc, 1);
@@ -590,8 +569,8 @@ bwi_detach(struct bwi_softc *sc)
for (i = 0; i < sc->sc_nmac; ++i)
bwi_mac_detach(&sc->sc_mac[i]);
bwi_dma_free(sc);
- if_free(ifp);
taskqueue_free(sc->sc_tq);
+ mbufq_drain(&sc->sc_snd);
BWI_LOCK_DESTROY(sc);
@@ -609,14 +588,11 @@ bwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
- bvp = (struct bwi_vap *) malloc(sizeof(struct bwi_vap),
- M_80211_VAP, M_WAITOK | M_ZERO);
- if (bvp == NULL)
- return NULL;
+ bvp = malloc(sizeof(struct bwi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &bvp->bv_vap;
/* enable s/w bmiss handling for sta mode */
ieee80211_vap_setup(ic, vap, name, unit, opmode,
- flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
+ flags | IEEE80211_CLONE_NOBEACONS, bssid);
/* override default methods */
bvp->bv_newstate = vap->iv_newstate;
@@ -627,7 +603,8 @@ bwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
/* complete setup */
- ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status);
+ ieee80211_vap_attach(vap, bwi_media_change, ieee80211_media_status,
+ mac);
ic->ic_opmode = opmode;
return vap;
}
@@ -651,9 +628,8 @@ bwi_suspend(struct bwi_softc *sc)
void
bwi_resume(struct bwi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- if (ifp->if_flags & IFF_UP)
+ if (sc->sc_ic.ic_nrunning > 0)
bwi_init(sc);
}
@@ -1217,27 +1193,26 @@ bwi_set_clock_delay(struct bwi_softc *sc)
}
static void
-bwi_init(void *xsc)
+bwi_init(struct bwi_softc *sc)
{
- struct bwi_softc *sc = xsc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
BWI_LOCK(sc);
bwi_init_statechg(sc, 1);
BWI_UNLOCK(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->sc_flags & BWI_F_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
static void
bwi_init_statechg(struct bwi_softc *sc, int statechg)
{
- struct ifnet *ifp = sc->sc_ifp;
struct bwi_mac *mac;
int error;
+ BWI_ASSERT_LOCKED(sc);
+
bwi_stop_locked(sc, statechg);
bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST);
@@ -1247,20 +1222,21 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
mac = &sc->sc_mac[0];
error = bwi_regwin_switch(sc, &mac->mac_regwin, NULL);
if (error) {
- if_printf(ifp, "%s: error %d on regwin switch\n",
+ device_printf(sc->sc_dev, "%s: error %d on regwin switch\n",
__func__, error);
goto bad;
}
error = bwi_mac_init(mac);
if (error) {
- if_printf(ifp, "%s: error %d on MAC init\n", __func__, error);
+ device_printf(sc->sc_dev, "%s: error %d on MAC init\n",
+ __func__, error);
goto bad;
}
bwi_bbp_power_on(sc, BWI_CLOCK_MODE_DYN);
bwi_set_bssid(sc, bwi_zero_addr); /* Clear BSSID */
- bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, IF_LLADDR(ifp));
+ bwi_set_addr_filter(sc, BWI_ADDR_FILTER_MYADDR, sc->sc_ic.ic_macaddr);
bwi_mac_reset_hwkeys(mac);
@@ -1278,7 +1254,8 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
CSR_READ_4(sc, BWI_TXSTATUS1);
}
if (i == NRETRY)
- if_printf(ifp, "%s: can't drain TX status\n", __func__);
+ device_printf(sc->sc_dev,
+ "%s: can't drain TX status\n", __func__);
#undef NRETRY
}
@@ -1288,14 +1265,14 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg)
/* Start MAC */
error = bwi_mac_start(mac);
if (error) {
- if_printf(ifp, "%s: error %d starting MAC\n", __func__, error);
+ device_printf(sc->sc_dev, "%s: error %d starting MAC\n",
+ __func__, error);
goto bad;
}
/* Clear stop flag before enabling interrupt */
sc->sc_flags &= ~BWI_F_STOP;
-
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_flags |= BWI_F_RUNNING;
callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc);
/* Enable intrs */
@@ -1305,135 +1282,110 @@ bad:
bwi_stop_locked(sc, 1);
}
-static int
-bwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+bwi_parent(struct ieee80211com *ic)
{
-#define IS_RUNNING(ifp) \
- ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
- struct bwi_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ struct bwi_softc *sc = ic->ic_softc;
+ int startall = 0;
- switch (cmd) {
- case SIOCSIFFLAGS:
- BWI_LOCK(sc);
- if (IS_RUNNING(ifp)) {
- struct bwi_mac *mac;
- int promisc = -1;
-
- KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
- ("current regwin type %d",
- sc->sc_cur_regwin->rw_type));
- mac = (struct bwi_mac *)sc->sc_cur_regwin;
-
- if ((ifp->if_flags & IFF_PROMISC) &&
- (sc->sc_flags & BWI_F_PROMISC) == 0) {
- promisc = 1;
- sc->sc_flags |= BWI_F_PROMISC;
- } else if ((ifp->if_flags & IFF_PROMISC) == 0 &&
- (sc->sc_flags & BWI_F_PROMISC)) {
- promisc = 0;
- sc->sc_flags &= ~BWI_F_PROMISC;
- }
+ BWI_LOCK(sc);
+ if (ic->ic_nrunning > 0) {
+ struct bwi_mac *mac;
+ int promisc = -1;
- if (promisc >= 0)
- bwi_mac_set_promisc(mac, promisc);
- }
+ KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+ ("current regwin type %d",
+ sc->sc_cur_regwin->rw_type));
+ mac = (struct bwi_mac *)sc->sc_cur_regwin;
- if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- bwi_init_statechg(sc, 1);
- startall = 1;
- }
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- bwi_stop_locked(sc, 1);
+ if (ic->ic_promisc > 0 && (sc->sc_flags & BWI_F_PROMISC) == 0) {
+ promisc = 1;
+ sc->sc_flags |= BWI_F_PROMISC;
+ } else if (ic->ic_promisc == 0 &&
+ (sc->sc_flags & BWI_F_PROMISC) != 0) {
+ promisc = 0;
+ sc->sc_flags &= ~BWI_F_PROMISC;
}
- BWI_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
+
+ if (promisc >= 0)
+ bwi_mac_set_promisc(mac, promisc);
}
- return error;
-#undef IS_RUNNING
+ if (ic->ic_nrunning > 0) {
+ if ((sc->sc_flags & BWI_F_RUNNING) == 0) {
+ bwi_init_statechg(sc, 1);
+ startall = 1;
+ }
+ } else if (sc->sc_flags & BWI_F_RUNNING)
+ bwi_stop_locked(sc, 1);
+ BWI_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
-static void
-bwi_start(struct ifnet *ifp)
+static int
+bwi_transmit(struct ieee80211com *ic, struct mbuf *m)
{
- struct bwi_softc *sc = ifp->if_softc;
+ struct bwi_softc *sc = ic->ic_softc;
+ int error;
BWI_LOCK(sc);
- bwi_start_locked(ifp);
+ if ((sc->sc_flags & BWI_F_RUNNING) == 0) {
+ BWI_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ BWI_UNLOCK(sc);
+ return (error);
+ }
+ bwi_start_locked(sc);
BWI_UNLOCK(sc);
+ return (0);
}
static void
-bwi_start_locked(struct ifnet *ifp)
+bwi_start_locked(struct bwi_softc *sc)
{
- struct bwi_softc *sc = ifp->if_softc;
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
- struct ieee80211_key *k;
struct mbuf *m;
int trans, idx;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return;
+ BWI_ASSERT_LOCKED(sc);
trans = 0;
idx = tbd->tbd_idx;
- while (tbd->tbd_buf[idx].tb_mbuf == NULL) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m); /* XXX: LOCK */
- if (m == NULL)
- break;
-
+ while (tbd->tbd_buf[idx].tb_mbuf == NULL &&
+ tbd->tbd_used + BWI_TX_NSPRDESC < BWI_TX_NDESC &&
+ (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
wh = mtod(m, struct ieee80211_frame *);
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
- k = ieee80211_crypto_encap(ni, m);
- if (k == NULL) {
- ieee80211_free_node(ni);
- m_freem(m);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- continue;
- }
+ if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) != 0 &&
+ ieee80211_crypto_encap(ni, m) == NULL) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
+ ieee80211_free_node(ni);
+ m_freem(m);
+ continue;
}
- wh = NULL; /* Catch any invalid use */
-
if (bwi_encap(sc, idx, m, ni) != 0) {
/* 'm' is freed in bwi_encap() if we reach here */
- if (ni != NULL)
+ if (ni != NULL) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ } else
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
continue;
}
-
trans = 1;
tbd->tbd_used++;
idx = (idx + 1) % BWI_TX_NDESC;
-
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
-
- if (tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
}
- tbd->tbd_idx = idx;
+ tbd->tbd_idx = idx;
if (trans)
sc->sc_tx_timer = 5;
}
@@ -1443,13 +1395,12 @@ bwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct bwi_softc *sc = ifp->if_softc;
+ struct bwi_softc *sc = ic->ic_softc;
/* XXX wme? */
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
int idx, error;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ if ((sc->sc_flags & BWI_F_RUNNING) == 0) {
ieee80211_free_node(ni);
m_freem(m);
return ENETDOWN;
@@ -1472,16 +1423,12 @@ bwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
error = bwi_encap_raw(sc, idx, m, ni, params);
}
if (error == 0) {
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- if (++tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC)
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ tbd->tbd_used++;
tbd->tbd_idx = (idx + 1) % BWI_TX_NDESC;
sc->sc_tx_timer = 5;
- } else {
+ } else
/* NB: m is reclaimed on encap failure */
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- }
BWI_UNLOCK(sc);
return error;
}
@@ -1490,14 +1437,12 @@ static void
bwi_watchdog(void *arg)
{
struct bwi_softc *sc;
- struct ifnet *ifp;
sc = arg;
- ifp = sc->sc_ifp;
BWI_ASSERT_LOCKED(sc);
if (sc->sc_tx_timer != 0 && --sc->sc_tx_timer == 0) {
- if_printf(ifp, "watchdog timeout\n");
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ device_printf(sc->sc_dev, "watchdog timeout\n");
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task);
}
callout_reset(&sc->sc_watchdog_timer, hz, bwi_watchdog, sc);
@@ -1514,7 +1459,6 @@ bwi_stop(struct bwi_softc *sc, int statechg)
static void
bwi_stop_locked(struct bwi_softc *sc, int statechg)
{
- struct ifnet *ifp = sc->sc_ifp;
struct bwi_mac *mac;
int i, error, pwr_off = 0;
@@ -1525,7 +1469,7 @@ bwi_stop_locked(struct bwi_softc *sc, int statechg)
sc->sc_led_blinking = 0;
sc->sc_flags |= BWI_F_STOP;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if (sc->sc_flags & BWI_F_RUNNING) {
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
("current regwin type %d", sc->sc_cur_regwin->rw_type));
mac = (struct bwi_mac *)sc->sc_cur_regwin;
@@ -1557,14 +1501,13 @@ bwi_stop_locked(struct bwi_softc *sc, int statechg)
sc->sc_tx_timer = 0;
callout_stop(&sc->sc_watchdog_timer);
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_flags &= ~BWI_F_RUNNING;
}
void
bwi_intr(void *xsc)
{
struct bwi_softc *sc = xsc;
- struct ifnet *ifp = sc->sc_ifp;
struct bwi_mac *mac;
uint32_t intr_status;
uint32_t txrx_intr_status[BWI_TXRX_NRING];
@@ -1572,7 +1515,7 @@ bwi_intr(void *xsc)
BWI_LOCK(sc);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
+ if ((sc->sc_flags & BWI_F_RUNNING) == 0 ||
(sc->sc_flags & BWI_F_STOP)) {
BWI_UNLOCK(sc);
return;
@@ -1615,7 +1558,7 @@ bwi_intr(void *xsc)
i, txrx_intr_status[i]);
if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) {
- if_printf(ifp,
+ device_printf(sc->sc_dev,
"%s: intr fatal TX/RX (%d) error 0x%08x\n",
__func__, i, txrx_intr_status[i]);
txrx_error = 1;
@@ -1653,7 +1596,8 @@ bwi_intr(void *xsc)
*/
if (intr_status & BWI_INTR_PHY_TXERR) {
if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) {
- if_printf(ifp, "%s: intr PHY TX error\n", __func__);
+ device_printf(sc->sc_dev, "%s: intr PHY TX error\n",
+ __func__);
taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task);
BWI_UNLOCK(sc);
return;
@@ -1668,7 +1612,7 @@ bwi_intr(void *xsc)
bwi_mac_config_ps(mac);
if (intr_status & BWI_INTR_EO_ATIM)
- if_printf(ifp, "EO_ATIM\n");
+ device_printf(sc->sc_dev, "EO_ATIM\n");
if (intr_status & BWI_INTR_PMQ) {
for (;;) {
@@ -1679,7 +1623,7 @@ bwi_intr(void *xsc)
}
if (intr_status & BWI_INTR_NOISE)
- if_printf(ifp, "intr noise\n");
+ device_printf(sc->sc_dev, "intr noise\n");
if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) {
rx_data = sc->sc_rxeof(sc);
@@ -1728,7 +1672,7 @@ bwi_intr(void *xsc)
static void
bwi_scan_start(struct ieee80211com *ic)
{
- struct bwi_softc *sc = ic->ic_ifp->if_softc;
+ struct bwi_softc *sc = ic->ic_softc;
BWI_LOCK(sc);
/* Enable MAC beacon promiscuity */
@@ -1739,7 +1683,7 @@ bwi_scan_start(struct ieee80211com *ic)
static void
bwi_set_channel(struct ieee80211com *ic)
{
- struct bwi_softc *sc = ic->ic_ifp->if_softc;
+ struct bwi_softc *sc = ic->ic_softc;
struct ieee80211_channel *c = ic->ic_curchan;
struct bwi_mac *mac;
@@ -1765,7 +1709,7 @@ bwi_set_channel(struct ieee80211com *ic)
static void
bwi_scan_end(struct ieee80211com *ic)
{
- struct bwi_softc *sc = ic->ic_ifp->if_softc;
+ struct bwi_softc *sc = ic->ic_softc;
BWI_LOCK(sc);
CSR_CLRBITS_4(sc, BWI_MAC_STATUS, BWI_MAC_STATUS_PASS_BCN);
@@ -1777,9 +1721,8 @@ bwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct bwi_vap *bvp = BWI_VAP(vap);
struct ieee80211com *ic= vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
+ struct bwi_softc *sc = ic->ic_softc;
enum ieee80211_state ostate = vap->iv_state;
- struct bwi_softc *sc = ifp->if_softc;
struct bwi_mac *mac;
int error;
@@ -2625,8 +2568,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
{
struct bwi_ring_data *rd = &sc->sc_rx_rdata;
struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
int idx, rx_data = 0;
idx = rbd->rbd_idx;
@@ -2645,7 +2587,7 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
BUS_DMASYNC_POSTREAD);
if (bwi_newbuf(sc, idx, 0)) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto next;
}
@@ -2659,9 +2601,10 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
buflen = le16toh(hdr->rxh_buflen);
if (buflen < BWI_FRAME_MIN_LEN(wh_ofs)) {
- if_printf(ifp, "%s: zero length data, hdr_extra %d\n",
- __func__, hdr_extra);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ device_printf(sc->sc_dev,
+ "%s: zero length data, hdr_extra %d\n",
+ __func__, hdr_extra);
+ counter_u64_add(ic->ic_ierrors, 1);
m_freem(m);
goto next;
}
@@ -2670,7 +2613,6 @@ bwi_rxeof(struct bwi_softc *sc, int end_idx)
rssi = bwi_calc_rssi(sc, hdr);
noise = bwi_calc_noise(sc);
- m->m_pkthdr.rcvif = ifp;
m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr);
m_adj(m, sizeof(*hdr) + wh_ofs);
@@ -2804,7 +2746,6 @@ bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
{
struct bwi_ring_data *rd;
struct bwi_txbuf_data *tbd;
- struct ifnet *ifp = sc->sc_ifp;
uint32_t state, val;
int i;
@@ -2825,8 +2766,9 @@ bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
DELAY(1000);
}
if (i == NRETRY) {
- if_printf(ifp, "%s: wait for TX ring(%d) stable timed out\n",
- __func__, ring_idx);
+ device_printf(sc->sc_dev,
+ "%s: wait for TX ring(%d) stable timed out\n",
+ __func__, ring_idx);
}
CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, 0);
@@ -2839,7 +2781,7 @@ bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx)
DELAY(1000);
}
if (i == NRETRY)
- if_printf(ifp, "%s: reset TX ring (%d) timed out\n",
+ device_printf(sc->sc_dev, "%s: reset TX ring (%d) timed out\n",
__func__, ring_idx);
#undef NRETRY
@@ -2947,8 +2889,7 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING];
struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
struct bwi_txbuf *tb = &tbd->tbd_buf[idx];
@@ -3024,7 +2965,8 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
*/
M_PREPEND(m, sizeof(*hdr), M_NOWAIT);
if (m == NULL) {
- if_printf(ifp, "%s: prepend TX header failed\n", __func__);
+ device_printf(sc->sc_dev, "%s: prepend TX header failed\n",
+ __func__);
return ENOBUFS;
}
hdr = mtod(m, struct bwi_txbuf_hdr *);
@@ -3073,7 +3015,7 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
error = bus_dmamap_load_mbuf(sc->sc_buf_dtag, tb->tb_dmap, m,
bwi_dma_buf_addr, &paddr, BUS_DMA_NOWAIT);
if (error && error != EFBIG) {
- if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
+ device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
__func__, error);
goto back;
}
@@ -3083,8 +3025,8 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
m_new = m_defrag(m, M_NOWAIT);
if (m_new == NULL) {
- if_printf(ifp, "%s: can't defrag TX buffer\n",
- __func__);
+ device_printf(sc->sc_dev,
+ "%s: can't defrag TX buffer\n", __func__);
error = ENOBUFS;
goto back;
} else {
@@ -3095,7 +3037,8 @@ bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m,
bwi_dma_buf_addr, &paddr,
BUS_DMA_NOWAIT);
if (error) {
- if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
+ device_printf(sc->sc_dev,
+ "%s: can't load TX buffer (2) %d\n",
__func__, error);
goto back;
}
@@ -3137,7 +3080,6 @@ static int
bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
{
- struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING];
@@ -3204,7 +3146,8 @@ bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
*/
M_PREPEND(m, sizeof(*hdr), M_NOWAIT);
if (m == NULL) {
- if_printf(ifp, "%s: prepend TX header failed\n", __func__);
+ device_printf(sc->sc_dev, "%s: prepend TX header failed\n",
+ __func__);
return ENOBUFS;
}
hdr = mtod(m, struct bwi_txbuf_hdr *);
@@ -3252,14 +3195,15 @@ bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
struct mbuf *m_new;
if (error != EFBIG) {
- if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
+ device_printf(sc->sc_dev,
+ "%s: can't load TX buffer (1) %d\n",
__func__, error);
goto back;
}
m_new = m_defrag(m, M_NOWAIT);
if (m_new == NULL) {
- if_printf(ifp, "%s: can't defrag TX buffer\n",
- __func__);
+ device_printf(sc->sc_dev,
+ "%s: can't defrag TX buffer\n", __func__);
error = ENOBUFS;
goto back;
}
@@ -3268,7 +3212,8 @@ bwi_encap_raw(struct bwi_softc *sc, int idx, struct mbuf *m,
bwi_dma_buf_addr, &paddr,
BUS_DMA_NOWAIT);
if (error) {
- if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
+ device_printf(sc->sc_dev,
+ "%s: can't load TX buffer (2) %d\n",
__func__, error);
goto back;
}
@@ -3312,7 +3257,6 @@ bwi_start_tx64(struct bwi_softc *sc, uint32_t tx_ctrl, int idx)
static void
bwi_txeof_status32(struct bwi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
uint32_t val, ctrl_base;
int end_idx;
@@ -3327,8 +3271,7 @@ bwi_txeof_status32(struct bwi_softc *sc)
CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX,
end_idx * sizeof(struct bwi_desc32));
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0)
- ifp->if_start(ifp);
+ bwi_start_locked(sc);
}
static void
@@ -3340,7 +3283,6 @@ bwi_txeof_status64(struct bwi_softc *sc)
static void
_bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
{
- struct ifnet *ifp = sc->sc_ifp;
struct bwi_txbuf_data *tbd;
struct bwi_txbuf *tb;
int ring_idx, buf_idx;
@@ -3348,7 +3290,7 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
struct ieee80211vap *vap;
if (tx_id == 0) {
- if_printf(ifp, "%s: zero tx id\n", __func__);
+ device_printf(sc->sc_dev, "%s: zero tx id\n", __func__);
return;
}
@@ -3369,8 +3311,7 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
bus_dmamap_unload(sc->sc_buf_dtag, tb->tb_dmap);
- ni = tb->tb_ni;
- if (tb->tb_ni != NULL) {
+ if ((ni = tb->tb_ni) != NULL) {
const struct bwi_txbuf_hdr *hdr =
mtod(tb->tb_mbuf, const struct bwi_txbuf_hdr *);
vap = ni->ni_vap;
@@ -3388,24 +3329,14 @@ _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id, int acked, int data_txcnt)
(data_txcnt > 1) ? IEEE80211_RATECTL_TX_SUCCESS :
IEEE80211_RATECTL_TX_FAILURE, &acked, NULL);
}
-
- /*
- * Do any tx complete callback. Note this must
- * be done before releasing the node reference.
- */
- if (tb->tb_mbuf->m_flags & M_TXCB)
- ieee80211_process_callback(ni, tb->tb_mbuf, !acked);
-
- ieee80211_free_node(tb->tb_ni);
+ ieee80211_tx_complete(ni, tb->tb_mbuf, !acked);
tb->tb_ni = NULL;
- }
- m_freem(tb->tb_mbuf);
+ } else
+ m_freem(tb->tb_mbuf);
tb->tb_mbuf = NULL;
if (tbd->tbd_used == 0)
sc->sc_tx_timer = 0;
-
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
@@ -3437,7 +3368,6 @@ bwi_txeof_status(struct bwi_softc *sc, int end_idx)
static void
bwi_txeof(struct bwi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
for (;;) {
uint32_t tx_status0, tx_status1;
@@ -3460,8 +3390,7 @@ bwi_txeof(struct bwi_softc *sc)
data_txcnt);
}
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0)
- ifp->if_start(ifp);
+ bwi_start_locked(sc);
}
static int
@@ -3709,7 +3638,6 @@ bwi_regwin_enable(struct bwi_softc *sc, struct bwi_regwin *rw, uint32_t flags)
static void
bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid)
{
- struct ifnet *ifp = sc->sc_ifp;
struct bwi_mac *mac;
struct bwi_myaddr_bssid buf;
const uint8_t *p;
@@ -3722,7 +3650,7 @@ bwi_set_bssid(struct bwi_softc *sc, const uint8_t *bssid)
bwi_set_addr_filter(sc, BWI_ADDR_FILTER_BSSID, bssid);
- bcopy(IF_LLADDR(ifp), buf.myaddr, sizeof(buf.myaddr));
+ bcopy(sc->sc_ic.ic_macaddr, buf.myaddr, sizeof(buf.myaddr));
bcopy(bssid, buf.bssid, sizeof(buf.bssid));
n = sizeof(buf) / sizeof(val);
@@ -3745,7 +3673,7 @@ bwi_updateslot(struct ieee80211com *ic)
struct bwi_mac *mac;
BWI_LOCK(sc);
- if (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if (sc->sc_flags & BWI_F_RUNNING) {
DPRINTF(sc, BWI_DBG_80211, "%s\n", __func__);
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
@@ -3761,16 +3689,12 @@ static void
bwi_calibrate(void *xsc)
{
struct bwi_softc *sc = xsc;
-#ifdef INVARIANTS
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
-#endif
struct bwi_mac *mac;
BWI_ASSERT_LOCKED(sc);
- KASSERT(ic->ic_opmode != IEEE80211_M_MONITOR,
- ("opmode %d", ic->ic_opmode));
+ KASSERT(sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR,
+ ("opmode %d", sc->sc_ic.ic_opmode));
KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
("current regwin type %d", sc->sc_cur_regwin->rw_type));
@@ -3912,8 +3836,7 @@ bwi_led_onoff(const struct bwi_led *led, uint16_t val, int on)
static void
bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t val;
int i;
@@ -3922,7 +3845,7 @@ bwi_led_newstate(struct bwi_softc *sc, enum ieee80211_state nstate)
sc->sc_led_blinking = 0;
}
- if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ if ((sc->sc_flags & BWI_F_RUNNING) == 0)
return;
val = CSR_READ_2(sc, BWI_MAC_GPIO_CTRL);
@@ -4050,13 +3973,12 @@ static void
bwi_restart(void *xsc, int pending)
{
struct bwi_softc *sc = xsc;
- struct ifnet *ifp = sc->sc_ifp;
- if_printf(ifp, "%s begin, help!\n", __func__);
+ device_printf(sc->sc_dev, "%s begin, help!\n", __func__);
BWI_LOCK(sc);
- bwi_init_statechg(xsc, 0);
+ bwi_init_statechg(sc, 0);
#if 0
- bwi_start_locked(ifp);
+ bwi_start_locked(sc);
#endif
BWI_UNLOCK(sc);
}
diff --git a/sys/dev/bwi/if_bwivar.h b/sys/dev/bwi/if_bwivar.h
index d5f09da..07c20fe 100644
--- a/sys/dev/bwi/if_bwivar.h
+++ b/sys/dev/bwi/if_bwivar.h
@@ -541,10 +541,11 @@ struct bwi_vap {
#define BWI_VAP(vap) ((struct bwi_vap *)(vap))
struct bwi_softc {
- struct ifnet *sc_ifp;
uint32_t sc_flags; /* BWI_F_ */
device_t sc_dev;
struct mtx sc_mtx;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
int sc_invalid;
uint32_t sc_cap; /* BWI_CAP_ */
@@ -647,6 +648,7 @@ struct bwi_softc {
#define BWI_F_BUS_INITED 0x1
#define BWI_F_PROMISC 0x2
#define BWI_F_STOP 0x4
+#define BWI_F_RUNNING 0x8
#define BWI_DBG_MAC 0x00000001
#define BWI_DBG_RF 0x00000002
diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c
index 39bd06f..15f6f27 100644
--- a/sys/dev/bwn/if_bwn.c
+++ b/sys/dev/bwn/if_bwn.c
@@ -133,13 +133,13 @@ static int bwn_wme = 1;
SYSCTL_INT(_hw_bwn, OID_AUTO, wme, CTLFLAG_RW, &bwn_wme, 0,
"uses WME support");
-static int bwn_attach_pre(struct bwn_softc *);
+static void bwn_attach_pre(struct bwn_softc *);
static int bwn_attach_post(struct bwn_softc *);
static void bwn_sprom_bugfixes(device_t);
-static void bwn_init(void *);
-static int bwn_init_locked(struct bwn_softc *);
-static int bwn_ioctl(struct ifnet *, u_long, caddr_t);
-static void bwn_start(struct ifnet *);
+static int bwn_init(struct bwn_softc *);
+static void bwn_parent(struct ieee80211com *);
+static void bwn_start(struct bwn_softc *);
+static int bwn_transmit(struct ieee80211com *, struct mbuf *);
static int bwn_attach_core(struct bwn_mac *);
static void bwn_reset_core(struct bwn_mac *, uint32_t);
static int bwn_phy_getinfo(struct bwn_mac *, int);
@@ -197,8 +197,7 @@ static struct ieee80211vap *bwn_vap_create(struct ieee80211com *,
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void bwn_vap_delete(struct ieee80211vap *);
-static void bwn_stop(struct bwn_softc *, int);
-static void bwn_stop_locked(struct bwn_softc *, int);
+static void bwn_stop(struct bwn_softc *);
static int bwn_core_init(struct bwn_mac *);
static void bwn_core_start(struct bwn_mac *);
static void bwn_core_exit(struct bwn_mac *);
@@ -409,7 +408,6 @@ static void bwn_handle_txeof(struct bwn_mac *,
const struct bwn_txstatus *);
static void bwn_rxeof(struct bwn_mac *, struct mbuf *, const void *);
static void bwn_phy_txpower_check(struct bwn_mac *, uint32_t);
-static void bwn_start_locked(struct ifnet *);
static int bwn_tx_start(struct bwn_softc *, struct ieee80211_node *,
struct mbuf *);
static int bwn_tx_isfull(struct bwn_softc *, struct mbuf *);
@@ -930,9 +928,7 @@ bwn_attach(device_t dev)
#endif
if ((sc->sc_flags & BWN_FLAG_ATTACHED) == 0) {
- error = bwn_attach_pre(sc);
- if (error != 0)
- return (error);
+ bwn_attach_pre(sc);
bwn_sprom_bugfixes(dev);
sc->sc_flags |= BWN_FLAG_ATTACHED;
}
@@ -947,10 +943,7 @@ bwn_attach(device_t dev)
}
}
- mac = (struct bwn_mac *)malloc(sizeof(*mac), M_DEVBUF,
- M_NOWAIT | M_ZERO);
- if (mac == NULL)
- return (ENOMEM);
+ mac = malloc(sizeof(*mac), M_DEVBUF, M_WAITOK | M_ZERO);
mac->mac_sc = sc;
mac->mac_status = BWN_MAC_STATUS_UNINIT;
if (bwn_bfp != 0)
@@ -1053,11 +1046,8 @@ bwn_is_valid_ether_addr(uint8_t *addr)
static int
bwn_attach_post(struct bwn_softc *sc)
{
- struct ieee80211com *ic;
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
- ic = ifp->if_l2com;
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(sc->sc_dev);
/* XXX not right but it's not used anywhere important */
@@ -1077,12 +1067,14 @@ bwn_attach_post(struct bwn_softc *sc)
ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; /* s/w bmiss */
- /* call MI attach routine. */
- ieee80211_ifattach(ic,
+ IEEE80211_ADDR_COPY(ic->ic_macaddr,
bwn_is_valid_ether_addr(siba_sprom_get_mac_80211a(sc->sc_dev)) ?
siba_sprom_get_mac_80211a(sc->sc_dev) :
siba_sprom_get_mac_80211bg(sc->sc_dev));
+ /* call MI attach routine. */
+ ieee80211_ifattach(ic);
+
ic->ic_headroom = sizeof(struct bwn_txhdr);
/* override default methods */
@@ -1090,13 +1082,13 @@ bwn_attach_post(struct bwn_softc *sc)
ic->ic_updateslot = bwn_updateslot;
ic->ic_update_promisc = bwn_update_promisc;
ic->ic_wme.wme_update = bwn_wme_update;
-
ic->ic_scan_start = bwn_scan_start;
ic->ic_scan_end = bwn_scan_end;
ic->ic_set_channel = bwn_set_channel;
-
ic->ic_vap_create = bwn_vap_create;
ic->ic_vap_delete = bwn_vap_delete;
+ ic->ic_transmit = bwn_transmit;
+ ic->ic_parent = bwn_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
@@ -1124,26 +1116,24 @@ bwn_detach(device_t dev)
{
struct bwn_softc *sc = device_get_softc(dev);
struct bwn_mac *mac = sc->sc_curmac;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
int i;
sc->sc_flags |= BWN_FLAG_INVALID;
if (device_is_attached(sc->sc_dev)) {
- bwn_stop(sc, 1);
+ BWN_LOCK(sc);
+ bwn_stop(sc);
+ BWN_UNLOCK(sc);
bwn_dma_free(mac);
callout_drain(&sc->sc_led_blink_ch);
callout_drain(&sc->sc_rfswitch_ch);
callout_drain(&sc->sc_task_ch);
callout_drain(&sc->sc_watchdog_ch);
bwn_phy_detach(mac);
- if (ifp != NULL) {
- ieee80211_draintask(ic, &mac->mac_hwreset);
- ieee80211_draintask(ic, &mac->mac_txpower);
- ieee80211_ifdetach(ic);
- if_free(ifp);
- }
+ ieee80211_draintask(ic, &mac->mac_hwreset);
+ ieee80211_draintask(ic, &mac->mac_txpower);
+ ieee80211_ifdetach(ic);
}
taskqueue_drain(sc->sc_tq, &mac->mac_intrtask);
taskqueue_free(sc->sc_tq);
@@ -1158,52 +1148,25 @@ bwn_detach(device_t dev)
bus_release_resources(dev, mac->mac_intr_spec, mac->mac_res_irq);
if (mac->mac_msi != 0)
pci_release_msi(dev);
-
+ mbufq_drain(&sc->sc_snd);
BWN_LOCK_DESTROY(sc);
return (0);
}
-static int
+static void
bwn_attach_pre(struct bwn_softc *sc)
{
- struct ifnet *ifp;
- int error = 0;
BWN_LOCK_INIT(sc);
TAILQ_INIT(&sc->sc_maclist);
callout_init_mtx(&sc->sc_rfswitch_ch, &sc->sc_mtx, 0);
callout_init_mtx(&sc->sc_task_ch, &sc->sc_mtx, 0);
callout_init_mtx(&sc->sc_watchdog_ch, &sc->sc_mtx, 0);
-
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
sc->sc_tq = taskqueue_create_fast("bwn_taskq", M_NOWAIT,
taskqueue_thread_enqueue, &sc->sc_tq);
taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
"%s taskq", device_get_nameunit(sc->sc_dev));
-
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "can not if_alloc()\n");
- error = ENOSPC;
- goto fail;
- }
-
- /* set these up early for if_printf use */
- if_initname(ifp, device_get_name(sc->sc_dev),
- device_get_unit(sc->sc_dev));
-
- ifp->if_softc = sc;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = bwn_init;
- ifp->if_ioctl = bwn_ioctl;
- ifp->if_start = bwn_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- return (0);
-
-fail: BWN_LOCK_DESTROY(sc);
- return (error);
}
static void
@@ -1238,58 +1201,51 @@ bwn_sprom_bugfixes(device_t dev)
#undef BWN_ISDEV
}
-static int
-bwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
-{
-#define IS_RUNNING(ifp) \
- ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
- struct bwn_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *)data;
- int error = 0, startall;
-
- switch (cmd) {
- case SIOCSIFFLAGS:
- startall = 0;
- if (IS_RUNNING(ifp)) {
- bwn_update_promisc(ic);
- } else if (ifp->if_flags & IFF_UP) {
- if ((sc->sc_flags & BWN_FLAG_INVALID) == 0) {
- bwn_init(sc);
- startall = 1;
- }
+static void
+bwn_parent(struct ieee80211com *ic)
+{
+ struct bwn_softc *sc = ic->ic_softc;
+ int startall = 0;
+
+ BWN_LOCK(sc);
+ if (ic->ic_nrunning > 0) {
+ if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
+ bwn_init(sc);
+ startall = 1;
} else
- bwn_stop(sc, 1);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
- }
- return (error);
+ bwn_update_promisc(ic);
+ } else if (sc->sc_flags & BWN_FLAG_RUNNING)
+ bwn_stop(sc);
+ BWN_UNLOCK(sc);
+
+ if (startall)
+ ieee80211_start_all(ic);
}
-static void
-bwn_start(struct ifnet *ifp)
+static int
+bwn_transmit(struct ieee80211com *ic, struct mbuf *m)
{
- struct bwn_softc *sc = ifp->if_softc;
+ struct bwn_softc *sc = ic->ic_softc;
+ int error;
BWN_LOCK(sc);
- bwn_start_locked(ifp);
+ if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) {
+ BWN_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ BWN_UNLOCK(sc);
+ return (error);
+ }
+ bwn_start(sc);
BWN_UNLOCK(sc);
+ return (0);
}
static void
-bwn_start_locked(struct ifnet *ifp)
+bwn_start(struct bwn_softc *sc)
{
- struct bwn_softc *sc = ifp->if_softc;
struct bwn_mac *mac = sc->sc_curmac;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
@@ -1298,44 +1254,40 @@ bwn_start_locked(struct ifnet *ifp)
BWN_ASSERT_LOCKED(sc);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || mac == NULL ||
+ if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 || mac == NULL ||
mac->mac_status < BWN_MAC_STATUS_STARTED)
return;
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m); /* XXX: LOCK */
- if (m == NULL)
- break;
-
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
if (bwn_tx_isfull(sc, m))
break;
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (ni == NULL) {
device_printf(sc->sc_dev, "unexpected NULL ni\n");
m_freem(m);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
continue;
}
- KASSERT(ni != NULL, ("%s:%d: fail", __func__, __LINE__));
wh = mtod(m, struct ieee80211_frame *);
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
k = ieee80211_crypto_encap(ni, m);
if (k == NULL) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
m_freem(m);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
continue;
}
}
wh = NULL; /* Catch any invalid use */
-
if (bwn_tx_start(sc, ni, m) != 0) {
- if (ni != NULL)
+ if (ni != NULL) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ }
continue;
}
-
sc->sc_watchdog_timer = 5;
}
}
@@ -1346,7 +1298,6 @@ bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
struct bwn_dma_ring *dr;
struct bwn_mac *mac = sc->sc_curmac;
struct bwn_pio_txqueue *tq;
- struct ifnet *ifp = sc->sc_ifp;
int pktlen = roundup(m->m_pkthdr.len + BWN_HDRSIZE(mac), 4);
BWN_ASSERT_LOCKED(sc);
@@ -1361,15 +1312,12 @@ bwn_tx_isfull(struct bwn_softc *sc, struct mbuf *m)
} else {
tq = bwn_pio_select(mac, M_WME_GETAC(m));
if (tq->tq_free == 0 || pktlen > tq->tq_size ||
- pktlen > (tq->tq_size - tq->tq_used)) {
- tq->tq_stop = 1;
+ pktlen > (tq->tq_size - tq->tq_used))
goto full;
- }
}
return (0);
full:
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ mbufq_prepend(&sc->sc_snd, m);
return (1);
}
@@ -1496,7 +1444,6 @@ bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
struct bwn_dmadesc_generic *desc;
struct bwn_dmadesc_meta *mt;
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
uint8_t *txhdr_cache = (uint8_t *)dr->dr_txhdr_cache;
int error, slot, backup[2] = { dr->dr_curslot, dr->dr_usedslot };
@@ -1519,7 +1466,7 @@ bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
BWN_GET_TXHDRCACHE(slot), BWN_HDRSIZE(mac), bwn_dma_ring_addr,
&mt->mt_paddr, BUS_DMA_NOWAIT);
if (error) {
- if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
+ device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
__func__, error);
goto fail;
}
@@ -1539,7 +1486,7 @@ bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap, m,
bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
if (error && error != EFBIG) {
- if_printf(ifp, "%s: can't load TX buffer (1) %d\n",
+ device_printf(sc->sc_dev, "%s: can't load TX buffer (1) %d\n",
__func__, error);
goto fail;
}
@@ -1548,7 +1495,8 @@ bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
m_new = m_defrag(m, M_NOWAIT);
if (m_new == NULL) {
- if_printf(ifp, "%s: can't defrag TX buffer\n",
+ device_printf(sc->sc_dev,
+ "%s: can't defrag TX buffer\n",
__func__);
error = ENOBUFS;
goto fail;
@@ -1560,7 +1508,8 @@ bwn_dma_tx_start(struct bwn_mac *mac, struct ieee80211_node *ni, struct mbuf *m)
error = bus_dmamap_load_mbuf(dma->txbuf_dtag, mt->mt_dmap,
m, bwn_dma_buf_addr, &mt->mt_paddr, BUS_DMA_NOWAIT);
if (error) {
- if_printf(ifp, "%s: can't load TX buffer (2) %d\n",
+ device_printf(sc->sc_dev,
+ "%s: can't load TX buffer (2) %d\n",
__func__, error);
goto fail;
}
@@ -1585,11 +1534,10 @@ static void
bwn_watchdog(void *arg)
{
struct bwn_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
if (sc->sc_watchdog_timer != 0 && --sc->sc_watchdog_timer == 0) {
- if_printf(ifp, "device timeout\n");
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ device_printf(sc->sc_dev, "device timeout\n");
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
}
callout_schedule(&sc->sc_watchdog_ch, hz);
}
@@ -1860,8 +1808,7 @@ static int
bwn_setup_channels(struct bwn_mac *mac, int have_bg, int have_a)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
memset(ic->ic_channels, 0, sizeof(ic->ic_channels));
ic->ic_nchans = 0;
@@ -2735,11 +2682,10 @@ bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct bwn_softc *sc = ifp->if_softc;
+ struct bwn_softc *sc = ic->ic_softc;
struct bwn_mac *mac = sc->sc_curmac;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
+ if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0 ||
mac->mac_status < BWN_MAC_STATUS_STARTED) {
ieee80211_free_node(ni);
m_freem(m);
@@ -2750,7 +2696,6 @@ bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
if (bwn_tx_isfull(sc, m)) {
ieee80211_free_node(ni);
m_freem(m);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
BWN_UNLOCK(sc);
return (ENOBUFS);
}
@@ -2758,7 +2703,6 @@ bwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
if (bwn_tx_start(sc, ni, m) != 0) {
if (ni != NULL)
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
sc->sc_watchdog_timer = 5;
BWN_UNLOCK(sc);
@@ -2778,7 +2722,7 @@ bwn_updateslot(struct ieee80211com *ic)
struct bwn_mac *mac;
BWN_LOCK(sc);
- if (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if (sc->sc_flags & BWN_FLAG_RUNNING) {
mac = (struct bwn_mac *)sc->sc_curmac;
bwn_set_slot_time(mac,
(ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20);
@@ -2802,7 +2746,7 @@ bwn_update_promisc(struct ieee80211com *ic)
BWN_LOCK(sc);
mac = sc->sc_curmac;
if (mac != NULL && mac->mac_status >= BWN_MAC_STATUS_INITED) {
- if (ic->ic_ifp->if_flags & IFF_PROMISC)
+ if (ic->ic_promisc > 0)
sc->sc_filters |= BWN_MACCTL_PROMISC;
else
sc->sc_filters &= ~BWN_MACCTL_PROMISC;
@@ -2817,7 +2761,7 @@ bwn_update_promisc(struct ieee80211com *ic)
static int
bwn_wme_update(struct ieee80211com *ic)
{
- struct bwn_softc *sc = ic->ic_ifp->if_softc;
+ struct bwn_softc *sc = ic->ic_softc;
struct bwn_mac *mac = sc->sc_curmac;
struct wmeParams *wmep;
int i;
@@ -2839,8 +2783,7 @@ bwn_wme_update(struct ieee80211com *ic)
static void
bwn_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct bwn_softc *sc = ifp->if_softc;
+ struct bwn_softc *sc = ic->ic_softc;
struct bwn_mac *mac;
BWN_LOCK(sc);
@@ -2857,8 +2800,7 @@ bwn_scan_start(struct ieee80211com *ic)
static void
bwn_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct bwn_softc *sc = ifp->if_softc;
+ struct bwn_softc *sc = ic->ic_softc;
struct bwn_mac *mac;
BWN_LOCK(sc);
@@ -2874,8 +2816,7 @@ bwn_scan_end(struct ieee80211com *ic)
static void
bwn_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct bwn_softc *sc = ifp->if_softc;
+ struct bwn_softc *sc = ic->ic_softc;
struct bwn_mac *mac = sc->sc_curmac;
struct bwn_phy *phy = &mac->mac_phy;
int chan, error;
@@ -2931,15 +2872,11 @@ static struct ieee80211vap *
bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
enum ieee80211_opmode opmode, int flags,
const uint8_t bssid[IEEE80211_ADDR_LEN],
- const uint8_t mac0[IEEE80211_ADDR_LEN])
+ const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = ic->ic_ifp;
- struct bwn_softc *sc = ifp->if_softc;
struct ieee80211vap *vap;
struct bwn_vap *bvp;
- uint8_t mac[IEEE80211_ADDR_LEN];
- IEEE80211_ADDR_COPY(mac, mac0);
switch (opmode) {
case IEEE80211_M_HOSTAP:
case IEEE80211_M_MBSS:
@@ -2953,17 +2890,9 @@ bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
return (NULL);
}
- IEEE80211_ADDR_COPY(sc->sc_macaddr, mac0);
-
- bvp = (struct bwn_vap *) malloc(sizeof(struct bwn_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (bvp == NULL) {
- device_printf(sc->sc_dev, "failed to allocate a buffer\n");
- return (NULL);
- }
+ bvp = malloc(sizeof(struct bwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &bvp->bv_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
- IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override with driver methods */
bvp->bv_newstate = vap->iv_newstate;
vap->iv_newstate = bwn_newstate;
@@ -2975,7 +2904,7 @@ bwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
- ieee80211_media_status);
+ ieee80211_media_status, mac);
return (vap);
}
@@ -2989,30 +2918,10 @@ bwn_vap_delete(struct ieee80211vap *vap)
free(bvp, M_80211_VAP);
}
-static void
-bwn_init(void *arg)
-{
- struct bwn_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- int error = 0;
-
- DPRINTF(sc, BWN_DEBUG_ANY, "%s: if_flags 0x%x\n",
- __func__, ifp->if_flags);
-
- BWN_LOCK(sc);
- error = bwn_init_locked(sc);
- BWN_UNLOCK(sc);
-
- if (error == 0)
- ieee80211_start_all(ic); /* start all vap's */
-}
-
static int
-bwn_init_locked(struct bwn_softc *sc)
+bwn_init(struct bwn_softc *sc)
{
struct bwn_mac *mac;
- struct ifnet *ifp = sc->sc_ifp;
int error;
BWN_ASSERT_LOCKED(sc);
@@ -3038,7 +2947,7 @@ bwn_init_locked(struct bwn_softc *sc)
bwn_spu_setdelay(mac, 0);
bwn_set_macaddr(mac);
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_flags |= BWN_FLAG_RUNNING;
callout_reset(&sc->sc_rfswitch_ch, hz, bwn_rfswitch, sc);
callout_reset(&sc->sc_watchdog_ch, hz, bwn_watchdog, sc);
@@ -3046,19 +2955,9 @@ bwn_init_locked(struct bwn_softc *sc)
}
static void
-bwn_stop(struct bwn_softc *sc, int statechg)
-{
-
- BWN_LOCK(sc);
- bwn_stop_locked(sc, statechg);
- BWN_UNLOCK(sc);
-}
-
-static void
-bwn_stop_locked(struct bwn_softc *sc, int statechg)
+bwn_stop(struct bwn_softc *sc)
{
struct bwn_mac *mac = sc->sc_curmac;
- struct ifnet *ifp = sc->sc_ifp;
BWN_ASSERT_LOCKED(sc);
@@ -3077,7 +2976,7 @@ bwn_stop_locked(struct bwn_softc *sc, int statechg)
bwn_core_exit(mac);
sc->sc_rf_enabled = 0;
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_flags &= ~BWN_FLAG_RUNNING;
}
static void
@@ -4441,7 +4340,7 @@ static void
bwn_spu_setdelay(struct bwn_mac *mac, int idle)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t delay; /* microsec */
delay = (mac->mac_phy.type == BWN_PHYTYPE_A) ? 3700 : 1050;
@@ -4479,7 +4378,8 @@ bwn_set_macaddr(struct bwn_mac *mac)
{
bwn_mac_write_bssid(mac);
- bwn_mac_setfilter(mac, BWN_MACFILTER_SELF, mac->mac_sc->sc_macaddr);
+ bwn_mac_setfilter(mac, BWN_MACFILTER_SELF,
+ mac->mac_sc->sc_ic.ic_macaddr);
}
static void
@@ -4649,8 +4549,7 @@ static void
bwn_set_opmode(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t ctl;
uint16_t cfp_pretbtt;
@@ -7943,8 +7842,7 @@ bwn_switch_channel(struct bwn_mac *mac, int chan)
{
struct bwn_phy *phy = &(mac->mac_phy);
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t channelcookie, savedcookie;
int error;
@@ -8055,7 +7953,7 @@ bwn_mac_write_bssid(struct bwn_mac *mac)
uint8_t mac_bssid[IEEE80211_ADDR_LEN * 2];
bwn_mac_setfilter(mac, BWN_MACFILTER_BSSID, sc->sc_bssid);
- memcpy(mac_bssid, sc->sc_macaddr, IEEE80211_ADDR_LEN);
+ memcpy(mac_bssid, sc->sc_ic.ic_macaddr, IEEE80211_ADDR_LEN);
memcpy(mac_bssid + IEEE80211_ADDR_LEN, sc->sc_bssid,
IEEE80211_ADDR_LEN);
@@ -8329,9 +8227,8 @@ bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct bwn_vap *bvp = BWN_VAP(vap);
struct ieee80211com *ic= vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
enum ieee80211_state ostate = vap->iv_state;
- struct bwn_softc *sc = ifp->if_softc;
+ struct bwn_softc *sc = ic->ic_softc;
struct bwn_mac *mac = sc->sc_curmac;
int error;
@@ -8370,7 +8267,6 @@ bwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
/* XXX nothing to do? */
} else if (nstate == IEEE80211_S_RUN) {
memcpy(sc->sc_bssid, vap->iv_bss->ni_bssid, IEEE80211_ADDR_LEN);
- memcpy(sc->sc_macaddr, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
bwn_set_opmode(mac);
bwn_set_pretbtt(mac);
bwn_spu_setdelay(mac, 0);
@@ -8386,7 +8282,7 @@ static void
bwn_set_pretbtt(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t pretbtt;
if (ic->ic_opmode == IEEE80211_M_IBSS)
@@ -8444,7 +8340,6 @@ bwn_intrtask(void *arg, int npending)
{
struct bwn_mac *mac = arg;
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
uint32_t merged = 0;
int i, tx = 0, rx = 0;
@@ -8544,10 +8439,8 @@ bwn_intrtask(void *arg, int npending)
bwn_led_event(mac, evt);
}
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
- if (!IFQ_IS_EMPTY(&ifp->if_snd))
- bwn_start_locked(ifp);
- }
+ if (mbufq_first(&sc->sc_snd) != NULL)
+ bwn_start(sc);
BWN_BARRIER(mac, BUS_SPACE_BARRIER_READ);
BWN_BARRIER(mac, BUS_SPACE_BARRIER_WRITE);
@@ -8559,8 +8452,7 @@ static void
bwn_restart(struct bwn_mac *mac, const char *msg)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
if (mac->mac_status < BWN_MAC_STATUS_INITED)
return;
@@ -8605,7 +8497,7 @@ static void
bwn_intr_tbtt_indication(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
if (ic->ic_opmode != IEEE80211_M_HOSTAP)
bwn_psctl(mac, 0);
@@ -8628,7 +8520,7 @@ static void
bwn_intr_beacon(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t cmd, beacon0, beacon1;
if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
@@ -8917,7 +8809,6 @@ bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
struct bwn_dmadesc_generic *desc;
struct bwn_dmadesc_meta *meta;
struct bwn_rxhdr4 *rxhdr;
- struct ifnet *ifp = sc->sc_ifp;
struct mbuf *m;
uint32_t macstat;
int32_t tmp;
@@ -8930,14 +8821,14 @@ bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
m = meta->mt_m;
if (bwn_dma_newbuf(dr, desc, meta, 0)) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_ierrors, 1);
return;
}
rxhdr = mtod(m, struct bwn_rxhdr4 *);
len = le16toh(rxhdr->frame_len);
if (len <= 0) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_ierrors, 1);
return;
}
if (bwn_dma_check_redzone(dr, m)) {
@@ -8973,7 +8864,6 @@ bwn_dma_rxeof(struct bwn_dma_ring *dr, int *slot)
}
}
- m->m_pkthdr.rcvif = ifp;
m->m_len = m->m_pkthdr.len = len + dr->dr_frameoffset;
m_adj(m, dr->dr_frameoffset);
@@ -9060,7 +8950,6 @@ bwn_pio_rxeof(struct bwn_pio_rxqueue *prq)
struct bwn_mac *mac = prq->prq_mac;
struct bwn_softc *sc = mac->mac_sc;
struct bwn_rxhdr4 rxhdr;
- struct ifnet *ifp = sc->sc_ifp;
struct mbuf *m;
uint32_t ctl32, macstat, v32;
unsigned int i, padding;
@@ -9157,7 +9046,6 @@ ready:
}
}
- m->m_pkthdr.rcvif = ifp;
m->m_len = m->m_pkthdr.len = totlen;
bwn_rxeof(prq->prq_mac, m, &rxhdr);
@@ -9302,8 +9190,7 @@ bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
struct bwn_softc *sc = mac->mac_sc;
struct ieee80211_frame_min *wh;
struct ieee80211_node *ni;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t macstat;
int padding, rate, rssi = 0, noise = 0, type;
uint16_t phytype, phystat0, phystat3, chanstat;
@@ -9367,8 +9254,6 @@ bwn_rxeof(struct bwn_mac *mac, struct mbuf *m, const void *_rxhdr)
rssi = rxhdr->phy.abg.rssi; /* XXX incorrect RSSI calculation? */
noise = mac->mac_stats.link_noise;
- if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
-
BWN_UNLOCK(sc);
ni = ieee80211_find_rxnode(ic, wh);
@@ -9393,9 +9278,6 @@ bwn_dma_handle_txeof(struct bwn_mac *mac,
struct bwn_dmadesc_generic *desc;
struct bwn_dmadesc_meta *meta;
struct bwn_softc *sc = mac->mac_sc;
- struct ieee80211_node *ni;
- struct ifnet *ifp = sc->sc_ifp;
- struct mbuf *m;
int slot;
BWN_ASSERT_LOCKED(sc);
@@ -9421,37 +9303,22 @@ bwn_dma_handle_txeof(struct bwn_mac *mac,
KASSERT(meta->mt_m != NULL,
("%s:%d: fail", __func__, __LINE__));
- ni = meta->mt_ni;
- m = meta->mt_m;
- if (ni != NULL) {
- /*
- * Do any tx complete callback. Note this must
- * be done before releasing the node reference.
- */
- if (m->m_flags & M_TXCB)
- ieee80211_process_callback(ni, m, 0);
- ieee80211_free_node(ni);
- meta->mt_ni = NULL;
- }
- m_freem(m);
+ ieee80211_tx_complete(meta->mt_ni, meta->mt_m, 0);
+ meta->mt_ni = NULL;
meta->mt_m = NULL;
- } else {
+ } else
KASSERT(meta->mt_m == NULL,
("%s:%d: fail", __func__, __LINE__));
- }
dr->dr_usedslot--;
- if (meta->mt_islast) {
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ if (meta->mt_islast)
break;
- }
slot = bwn_dma_nextslot(dr, slot);
}
sc->sc_watchdog_timer = 0;
if (dr->dr_stop) {
KASSERT(bwn_dma_freeslot(dr) >= BWN_TX_SLOTS_PER_FRAME,
("%s:%d: fail", __func__, __LINE__));
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
dr->dr_stop = 0;
}
}
@@ -9463,7 +9330,6 @@ bwn_pio_handle_txeof(struct bwn_mac *mac,
struct bwn_pio_txqueue *tq;
struct bwn_pio_txpkt *tp = NULL;
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
BWN_ASSERT_LOCKED(sc);
@@ -9488,13 +9354,7 @@ bwn_pio_handle_txeof(struct bwn_mac *mac,
tp->tp_m = NULL;
TAILQ_INSERT_TAIL(&tq->tq_pktlist, tp, tp_list);
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
-
sc->sc_watchdog_timer = 0;
- if (tq->tq_stop) {
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- tq->tq_stop = 0;
- }
}
static void
@@ -9502,8 +9362,7 @@ bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
{
struct bwn_softc *sc = mac->mac_sc;
struct bwn_phy *phy = &mac->mac_phy;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
unsigned long now;
int result;
@@ -9607,8 +9466,7 @@ bwn_set_txhdr(struct bwn_mac *mac, struct ieee80211_node *ni,
struct ieee80211_frame_rts *rts;
const struct ieee80211_txparam *tp;
struct ieee80211vap *vap = ni->ni_vap;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *mprot;
unsigned int len;
uint32_t macctl = 0;
@@ -10106,7 +9964,7 @@ static void
bwn_phy_lock(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
KASSERT(siba_get_revid(sc->sc_dev) >= 3,
("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
@@ -10119,7 +9977,7 @@ static void
bwn_phy_unlock(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
KASSERT(siba_get_revid(sc->sc_dev) >= 3,
("%s: unsupported rev %d", __func__, siba_get_revid(sc->sc_dev)));
@@ -10635,8 +10493,7 @@ static void
bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t val;
int i;
@@ -10645,7 +10502,7 @@ bwn_led_newstate(struct bwn_mac *mac, enum ieee80211_state nstate)
sc->sc_led_blinking = 0;
}
- if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0)
return;
val = BWN_READ_2(mac, BWN_GPIO_CONTROL);
@@ -10780,7 +10637,9 @@ bwn_suspend(device_t dev)
{
struct bwn_softc *sc = device_get_softc(dev);
- bwn_stop(sc, 1);
+ BWN_LOCK(sc);
+ bwn_stop(sc);
+ BWN_UNLOCK(sc);
return (0);
}
@@ -10788,10 +10647,14 @@ static int
bwn_resume(device_t dev)
{
struct bwn_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->sc_ifp;
+ int error = EDOOFUS;
- if (ifp->if_flags & IFF_UP)
- bwn_init(sc);
+ BWN_LOCK(sc);
+ if (sc->sc_ic.ic_nrunning > 0)
+ error = bwn_init(sc);
+ BWN_UNLOCK(sc);
+ if (error == 0)
+ ieee80211_start_all(&sc->sc_ic);
return (0);
}
@@ -10870,8 +10733,7 @@ bwn_phy_lp_init(struct bwn_mac *mac)
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
const struct bwn_stxtable *st;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
int i, error;
uint16_t tmp;
@@ -11024,8 +10886,7 @@ static uint32_t
bwn_phy_lp_get_default_chan(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
return (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? 1 : 36);
}
@@ -11058,8 +10919,7 @@ bwn_phy_lp_readsprom(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) {
plp->plp_txisoband_m = siba_sprom_get_tri2g(sc->sc_dev);
@@ -11098,8 +10958,7 @@ bwn_phy_lp_txpctl_init(struct bwn_mac *mac)
struct bwn_txgain gain_2ghz = { 4, 12, 12, 0 };
struct bwn_txgain gain_5ghz = { 7, 15, 14, 0 };
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
bwn_phy_lp_set_txgain(mac,
IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan) ? &gain_2ghz : &gain_5ghz);
@@ -11111,8 +10970,7 @@ bwn_phy_lp_calib(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
const struct bwn_rxcompco *rc = NULL;
struct bwn_txgain ogain;
int i, omode, oafeovr, orf, obbmult;
@@ -11458,8 +11316,7 @@ bwn_phy_lp_set_gaintbl(struct bwn_mac *mac, uint32_t freq)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t iso, tmp[3];
KASSERT(mac->mac_phy.rev < 2, ("%s:%d: fail", __func__, __LINE__));
@@ -11730,8 +11587,7 @@ bwn_phy_lp_bbinit_r2(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
static const struct bwn_wpair v1[] = {
{ BWN_PHY_AFE_DAC_CTL, 0x50 },
{ BWN_PHY_AFE_CTL, 0x8800 },
@@ -11841,8 +11697,7 @@ bwn_phy_lp_bbinit_r01(struct bwn_mac *mac)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
static const struct bwn_smpair v1[] = {
{ BWN_PHY_CLIPCTRTHRESH, 0xffe0, 0x0005 },
{ BWN_PHY_CLIPCTRTHRESH, 0xfc1f, 0x0180 },
@@ -12027,8 +11882,7 @@ bwn_phy_lp_b2062_init(struct bwn_mac *mac)
((((2 * (freq) + 1000000 * (div)) / (2000000 * (div))) - 1) & 0xff)
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
static const struct bwn_b2062_freq freqdata_tab[] = {
{ 12000, { 6, 6, 6, 6, 10, 6 } },
{ 13000, { 4, 4, 4, 4, 11, 7 } },
@@ -12374,8 +12228,7 @@ bwn_phy_lp_b2062_tblinit(struct bwn_mac *mac)
#define FLAG_A 0x01
#define FLAG_G 0x02
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
static const struct bwn_b206x_rfinit_entry bwn_b2062_init_tab[] = {
{ BWN_B2062_N_COM4, 0x1, 0x0, FLAG_A | FLAG_G, },
{ BWN_B2062_N_PDNCTL1, 0x0, 0xca, FLAG_G, },
@@ -12448,8 +12301,7 @@ bwn_phy_lp_b2063_tblinit(struct bwn_mac *mac)
#define FLAG_A 0x01
#define FLAG_G 0x02
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
static const struct bwn_b206x_rfinit_entry bwn_b2063_init_tab[] = {
{ BWN_B2063_COM1, 0x0, 0x0, FLAG_G, },
{ BWN_B2063_COM10, 0x1, 0x0, FLAG_A, },
@@ -12667,8 +12519,7 @@ static void
bwn_phy_lp_set_rxgain(struct bwn_mac *mac, uint32_t gain)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t ext_lna, high_gain, lna, low_gain, trsw, tmp;
if (mac->mac_phy.rev < 2) {
@@ -12736,8 +12587,7 @@ bwn_phy_lp_clear_deaf(struct bwn_mac *mac, uint8_t user)
{
struct bwn_phy_lp *plp = &mac->mac_phy.phy_lp;
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
if (user)
plp->plp_crsusr_off = 0;
@@ -13280,8 +13130,7 @@ static void
bwn_phy_lp_tblinit_txgain(struct bwn_mac *mac)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
static struct bwn_txgain_entry txgain_r2[] = {
{ 255, 255, 203, 0, 152 }, { 255, 255, 203, 0, 147 },
{ 255, 255, 203, 0, 143 }, { 255, 255, 203, 0, 139 },
@@ -14158,8 +14007,7 @@ bwn_phy_lp_gaintbl_write_r2(struct bwn_mac *mac, int offset,
struct bwn_txgain_entry te)
{
struct bwn_softc *sc = mac->mac_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
KASSERT(mac->mac_phy.rev >= 2, ("%s:%d: fail", __func__, __LINE__));
diff --git a/sys/dev/bwn/if_bwnvar.h b/sys/dev/bwn/if_bwnvar.h
index f6647b0..b8295ec 100644
--- a/sys/dev/bwn/if_bwnvar.h
+++ b/sys/dev/bwn/if_bwnvar.h
@@ -656,7 +656,6 @@ struct bwn_pio_txqueue {
uint16_t tq_size;
uint16_t tq_used;
uint16_t tq_free;
- uint8_t tq_stop;
uint8_t tq_index;
struct bwn_pio_txpkt tq_pkts[BWN_PIO_MAX_TXPACKETS];
TAILQ_HEAD(, bwn_pio_txpkt) tq_pktlist;
@@ -897,17 +896,18 @@ struct bwn_vap {
struct bwn_softc {
device_t sc_dev;
struct mtx sc_mtx;
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
unsigned sc_flags;
#define BWN_FLAG_ATTACHED (1 << 0)
#define BWN_FLAG_INVALID (1 << 1)
#define BWN_FLAG_NEED_BEACON_TP (1 << 2)
+#define BWN_FLAG_RUNNING (1 << 3)
unsigned sc_debug;
struct bwn_mac *sc_curmac;
TAILQ_HEAD(, bwn_mac) sc_maclist;
- uint8_t sc_macaddr[IEEE80211_ADDR_LEN];
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
unsigned int sc_filters;
uint8_t sc_beacons[2];
diff --git a/sys/dev/bxe/bxe.c b/sys/dev/bxe/bxe.c
index f3e5964..274cc5b 100644
--- a/sys/dev/bxe/bxe.c
+++ b/sys/dev/bxe/bxe.c
@@ -5999,19 +5999,26 @@ bxe_tx_mq_start_locked(struct bxe_softc *sc,
rc = tx_count = 0;
+ BXE_FP_TX_LOCK_ASSERT(fp);
+
if (!tx_br) {
BLOGE(sc, "Multiqueue TX and no buf_ring!\n");
return (EINVAL);
}
+ if (!sc->link_vars.link_up ||
+ (ifp->if_drv_flags &
+ (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) {
+ rc = drbr_enqueue_drv(ifp, tx_br, m);
+ goto bxe_tx_mq_start_locked_exit;
+ }
+
/* fetch the depth of the driver queue */
depth = drbr_inuse_drv(ifp, tx_br);
if (depth > fp->eth_q_stats.tx_max_drbr_queue_depth) {
fp->eth_q_stats.tx_max_drbr_queue_depth = depth;
}
- BXE_FP_TX_LOCK_ASSERT(fp);
-
if (m == NULL) {
/* no new work, check for pending frames */
next = drbr_dequeue_drv(ifp, tx_br);
@@ -6103,26 +6110,11 @@ bxe_tx_mq_start(struct ifnet *ifp,
fp = &sc->fp[fp_index];
- if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) {
- BLOGW(sc, "Interface not running, ignoring transmit request\n");
- return (ENETDOWN);
- }
-
- if (if_getdrvflags(ifp) & IFF_DRV_OACTIVE) {
- BLOGW(sc, "Interface TX queue is full, ignoring transmit request\n");
- return (EBUSY);
- }
-
- if (!sc->link_vars.link_up) {
- BLOGW(sc, "Interface link is down, ignoring transmit request\n");
- return (ENETDOWN);
- }
-
- /* XXX change to TRYLOCK here and if failed then schedule taskqueue */
-
- BXE_FP_TX_LOCK(fp);
- rc = bxe_tx_mq_start_locked(sc, ifp, fp, m);
- BXE_FP_TX_UNLOCK(fp);
+ if (BXE_FP_TX_TRYLOCK(fp)) {
+ rc = bxe_tx_mq_start_locked(sc, ifp, fp, m);
+ BXE_FP_TX_UNLOCK(fp);
+ } else
+ rc = drbr_enqueue_drv(ifp, fp->tx_br, m);
return (rc);
}
diff --git a/sys/dev/bxe/bxe.h b/sys/dev/bxe/bxe.h
index 5fb31a3..980a91f 100644
--- a/sys/dev/bxe/bxe.h
+++ b/sys/dev/bxe/bxe.h
@@ -582,6 +582,7 @@ struct bxe_fastpath {
#define BXE_FP_TX_LOCK(fp) mtx_lock(&fp->tx_mtx)
#define BXE_FP_TX_UNLOCK(fp) mtx_unlock(&fp->tx_mtx)
#define BXE_FP_TX_LOCK_ASSERT(fp) mtx_assert(&fp->tx_mtx, MA_OWNED)
+#define BXE_FP_TX_TRYLOCK(fp) mtx_trylock(&fp->tx_mtx)
#define BXE_FP_RX_LOCK(fp) mtx_lock(&fp->rx_mtx)
#define BXE_FP_RX_UNLOCK(fp) mtx_unlock(&fp->rx_mtx)
diff --git a/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c b/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
index bdd746f..985306c 100644
--- a/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
+++ b/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
@@ -639,7 +639,7 @@ t3_send_fin(struct toedev *tod, struct tcpcb *tp)
unsigned int tid = toep->tp_tid;
#endif
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
CTR4(KTR_CXGB, "%s: tid %d, toep %p, flags %x", __func__, tid, toep,
@@ -925,12 +925,12 @@ do_act_open_rpl(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
rc = act_open_rpl_status_to_errno(s);
if (rc != EAGAIN)
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
toe_connect_failed(tod, inp, rc);
toepcb_release(toep); /* unlocks inp */
if (rc != EAGAIN)
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
m_freem(m);
return (0);
@@ -1061,7 +1061,7 @@ send_reset(struct toepcb *toep)
struct adapter *sc = tod->tod_softc;
struct mbuf *m;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
CTR4(KTR_CXGB, "%s: tid %d, toep %p (%x)", __func__, tid, toep,
@@ -1172,12 +1172,12 @@ do_rx_data(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
SOCKBUF_UNLOCK(so_rcv);
INP_WUNLOCK(inp);
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
tp = tcp_drop(tp, ECONNRESET);
if (tp)
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
m_freem(m);
return (0);
@@ -1222,7 +1222,7 @@ do_peer_close(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
struct tcpcb *tp;
struct socket *so;
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
tp = intotcpcb(inp);
@@ -1250,7 +1250,7 @@ do_peer_close(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
case TCPS_FIN_WAIT_2:
tcp_twstart(tp);
INP_UNLOCK_ASSERT(inp); /* safe, we have a ref on the inp */
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
INP_WLOCK(inp);
toepcb_release(toep); /* no more CPLs expected */
@@ -1264,7 +1264,7 @@ do_peer_close(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
done:
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
m_freem(m);
return (0);
@@ -1285,7 +1285,7 @@ do_close_con_rpl(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
struct tcpcb *tp;
struct socket *so;
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
tp = intotcpcb(inp);
@@ -1303,7 +1303,7 @@ do_close_con_rpl(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
tcp_twstart(tp);
release:
INP_UNLOCK_ASSERT(inp); /* safe, we have a ref on the inp */
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
INP_WLOCK(inp);
toepcb_release(toep); /* no more CPLs expected */
@@ -1328,7 +1328,7 @@ release:
done:
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
m_freem(m);
return (0);
@@ -1489,7 +1489,7 @@ do_abort_req(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
return (do_abort_req_synqe(qs, r, m));
inp = toep->tp_inp;
- INP_INFO_WLOCK(&V_tcbinfo); /* for tcp_close */
+ INP_INFO_RLOCK(&V_tcbinfo); /* for tcp_close */
INP_WLOCK(inp);
tp = intotcpcb(inp);
@@ -1503,7 +1503,7 @@ do_abort_req(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
toep->tp_flags |= TP_ABORT_REQ_RCVD;
toep->tp_flags |= TP_ABORT_SHUTDOWN;
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
m_freem(m);
return (0);
}
@@ -1523,7 +1523,7 @@ do_abort_req(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
INP_WLOCK(inp); /* re-acquire */
toepcb_release(toep); /* no more CPLs expected */
}
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
send_abort_rpl(tod, tid, qset);
m_freem(m);
diff --git a/sys/dev/cxgb/ulp/tom/cxgb_listen.c b/sys/dev/cxgb/ulp/tom/cxgb_listen.c
index e11bb25..933a83c 100644
--- a/sys/dev/cxgb/ulp/tom/cxgb_listen.c
+++ b/sys/dev/cxgb/ulp/tom/cxgb_listen.c
@@ -541,11 +541,11 @@ do_pass_accept_req(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
REJECT_PASS_ACCEPT(); /* no l2te, or ifp mismatch */
}
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
/* Don't offload if the 4-tuple is already in use */
if (toe_4tuple_check(&inc, &th, ifp) != 0) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
REJECT_PASS_ACCEPT();
}
@@ -558,7 +558,7 @@ do_pass_accept_req(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
* resources tied to this listen context.
*/
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
REJECT_PASS_ACCEPT();
}
so = inp->inp_socket;
@@ -686,7 +686,7 @@ do_pass_establish(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
struct toepcb *toep;
struct socket *so;
struct listen_ctx *lctx = synqe->lctx;
- struct inpcb *inp = lctx->inp;
+ struct inpcb *inp = lctx->inp, *new_inp;
struct tcpopt to;
struct tcphdr th;
struct in_conninfo inc;
@@ -700,7 +700,7 @@ do_pass_establish(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
KASSERT(qs->idx == synqe->qset,
("%s qset mismatch %d %d", __func__, qs->idx, synqe->qset));
- INP_INFO_WLOCK(&V_tcbinfo); /* for syncache_expand */
+ INP_INFO_RLOCK(&V_tcbinfo); /* for syncache_expand */
INP_WLOCK(inp);
if (__predict_false(inp->inp_flags & INP_DROPPED)) {
@@ -714,7 +714,7 @@ do_pass_establish(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
("%s: listen socket dropped but tid %u not aborted.",
__func__, tid));
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
m_freem(m);
return (0);
}
@@ -730,7 +730,7 @@ do_pass_establish(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m)
reset:
t3_send_reset_synqe(tod, synqe);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
m_freem(m);
return (0);
}
@@ -748,21 +748,23 @@ reset:
goto reset;
}
- if (__predict_false(!(synqe->flags & TP_SYNQE_EXPANDED))) {
- struct inpcb *new_inp = sotoinpcb(so);
+ /* New connection inpcb is already locked by syncache_expand(). */
+ new_inp = sotoinpcb(so);
+ INP_WLOCK_ASSERT(new_inp);
- INP_WLOCK(new_inp);
+ if (__predict_false(!(synqe->flags & TP_SYNQE_EXPANDED))) {
tcp_timer_activate(intotcpcb(new_inp), TT_KEEP, 0);
t3_offload_socket(tod, synqe, so);
- INP_WUNLOCK(new_inp);
}
+ INP_WUNLOCK(new_inp);
+
/* Remove the synq entry and release its reference on the lctx */
TAILQ_REMOVE(&lctx->synq, synqe, link);
inp = release_lctx(td, lctx);
if (inp)
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
release_synqe(synqe);
m_freem(m);
@@ -1128,7 +1130,7 @@ t3_offload_socket(struct toedev *tod, void *arg, struct socket *so)
struct cpl_pass_establish *cpl = synqe->cpl;
struct toepcb *toep = synqe->toep;
- INP_INFO_LOCK_ASSERT(&V_tcbinfo); /* prevents bad race with accept() */
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo); /* prevents bad race with accept() */
INP_WLOCK_ASSERT(inp);
offload_socket(so, toep);
diff --git a/sys/dev/cxgbe/firmware/t4fw-1.14.2.0.bin.uu b/sys/dev/cxgbe/firmware/t4fw-1.14.4.0.bin.uu
index c868045..e3f3f77 100644
--- a/sys/dev/cxgbe/firmware/t4fw-1.14.2.0.bin.uu
+++ b/sys/dev/cxgbe/firmware/t4fw-1.14.4.0.bin.uu
@@ -24,15 +24,15 @@
* SUCH DAMAGE.
*/
begin-base64 644 t4fw
-AAAEHQEOAgAAAQkEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAEHgEOBAAAAQkEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAABAAEDwQXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAABAEEEAQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAENoZWxzaW8gRlcgUlVOTUVNIERFQlVHPTAgKEJ1aWx0IE1vbiBKdWwgMTMgMjE6
-MTU6MDkgUERUIDIwMTUgb24gY2xlb3BhdHJhLmFzaWNkZXNpZ25lcnMuY29tOi9ob21lL2Zpcm13
-YXJlL2N2cy9mdy1yZWxlYXNlKSwgVmVyc2lvbiBUNHh4IDAxLjBlLjAyLjAwAAAAAAAAAAcT5rNg
+AAAAAAAAAAAAAENoZWxzaW8gRlcgUlVOTUVNIERFQlVHPTAgKEJ1aWx0IFRodSBKdWwgMjMgMDA6
+MzA6MTAgUERUIDIwMTUgb24gY2xlb3BhdHJhLmFzaWNkZXNpZ25lcnMuY29tOi9ob21lL2Zpcm13
+YXJlL2N2cy9mdy1yZWxlYXNlKSwgVmVyc2lvbiBUNHh4IDAxLjBlLjA0LjAwAAAAAAAAABlSRz1g
AMgA4QB78AAQAADhADC4eP///x/84UCAAAAB4QB7cAAAEAAf//2U4QGUcCAAAADhAZwE4QB5AAAC
AEDhAHmAAAYAQAACAAoABgAK4QB5BAAMAACAAAEC4QB7POEAe0ThAHvk4gAAAAABAADhAHuQIAAA
AAAAgADhAHsAAABAAeEAe5wAAEAAREREQuAAAADjAARzREREQOMACAAgAAJcAAAAAB//koAAAAAA
@@ -67,8 +67,8 @@ nOMAfgQgAAGcIAABpeMAfgggAAG4IAABvOMAfhQgAAG8IAABxeMAfhggAAHYIAAB2OMAfiQgAAHc
IAAB4uMAfiQgAAH4IAAB+OMAfiwgAAH8IAAB/OMAfiwgAAIYIAACGOMAfiwgAAIcIAACHOMAfiwg
AAI4IAACOOMAfiwgAAI8IAACPOMAfiwgAAJYIAACWOMAfiwgAAJcIAACYuMAfiwgAAJ4IAACeOMA
fjQgAAJ8IAACguMAfjQgAAKYIAHzYuMAfjwgAwAAIAMUmOMCbwggAxSYIAMUmOMCg6AgAxSYIAbL
-jOMCg6AgBsuQIAbRUOMGOpggCAAAIAgOQOMGQFggCA5AIAkkLuMGTpggCSQwIAkk/OMHZIggCwAA
-IAsAAOMHZVQgCwAAIAsAAOMHZVQgCwAAIAuan+MHZVQAAAAAAAAAAAAAAAAgABFWIAARSCAAFTog
+jOMCg6AgBsuQIAbRUOMGOpggCAAAIAgOQOMGQFggCA5AIAkkNuMGTpggCSRAIAklDOMHZJggCwAA
+IAsAAOMHZWQgCwAAIAsAAOMHZWQgCwAAIAuan+MHZWQAAAAAAAAAAAAAAAAgABFWIAARSCAAFTog
ABFIIAAUtSAAEUggABH9IAAUTSAAE9IgABFIIAATfSAAEzQgABLJIAARNSAAEnQgABFIIAARSCAA
EUggABIcAAAAAAEQGAEABAAAAAAAAAAAAAD///////8P/P//8P///wD8IACtgyAAruogAK8aIACu
4CAArqEgAK6XIACuYSAArlcgAK5GIACt8iAArxggAK3oIACtuyAArxogAK2xAAAAAAAAAAoAAAAK
@@ -78,9 +78,9 @@ AAAAAAAAAAAAAQABAAIAAgADAAMAAwADAAQABAAEAAQABAAFAAUABQAFAAUABQAGAAYABwAHAAAA
AgAAAAYAAAAKAAAADgAAABQAAAAcAAAAKAAAADgAAABQAAAAcAAAAKAAAADgAAABQAAAAcAAAAKA
AAADgAAABQEAAAcAAAAKAAAADgAAABQAAAAcAAAAKAAAADgAAABQAAAAcAAAAKAAAADgAAABQAAA
AcAAAAKAAAADgAD/AAECAgAAAAAAAAAAAAAAECBAAAAAAAAAAAAAAAAAAAQAAgABAACAAEAAIAAQ
-AAggQIAAAAAAAAAAAAAAAAAAIAineCAIp3ggCKcxIAinACAIptIgCKamIAimpiAIqFYgCKhWIAim
-piAIqFYgCKhWIAimpiAIpqYgCKZaIAioViAIqFYgCKhWIAioViAIqFYgCKhWIAioViAIqFYgCKhW
-IAioViAIqFYgCKhWIAioViAIqFYgCKhWIAioViAIpokgAwoIAAAAASADDjgAAAD/IAMH4AAAAP8A
+AAggQIAAAAAAAAAAAAAAAAAAIAingCAIp4AgCKc5IAinCCAIptogCKauIAimriAIqF4gCKheIAim
+riAIqF4gCKheIAimriAIpq4gCKZiIAioXiAIqF4gCKheIAioXiAIqF4gCKheIAioXiAIqF4gCKhe
+IAioXiAIqF4gCKheIAioXiAIqF4gCKheIAioXiAIppEgAwoIAAAAASADDjgAAAD/IAMH4AAAAP8A
AAAAAAAAACADCfQAAAACIAMJ+AAAAAMgAwoAAAAABwAAAAAAAAAAIAMJ2AAAAAEgAwncAAAAAiAD
CeQAAAAEIAMOOAAAAP8gAwfgAAAA/wAAAAAAAAAAIAMH4AAAAAAgAw44AAAAACADCPAAAAABIAMI
+AAAAAQgAwkAAAAACCADCQwAAAAgIAMJHAAAAEAgAwkkAAAAgCADCSwAAAEAIAMJNAAAAgAgAwlI
@@ -2914,7 +2914,7 @@ AABDSEFQX0kAAENIQVBfQwAAQ0hBUF9OAABDSEFQX1IAAERpc2NvdmVyeQAAAE5vcm1hbAAATm9u
ZQAAAABDUkMzMkMAAENSQzMyQyxOb25lAE5vbmUsQ1JDMzJDAENIQVAAAAAAQ0hBUCxOb25lAAAA
Tm9uZSxDSEFQAAAATm90VW5kZXJzdG9vZAAAAElycmVsZXZhbnQAAFJlamVjdAAATm8AADUAAABD
SE5ldCAxLjAwAAAAAAAMAAAAAAEAAXwADAEAAAAAEAAAABQgBsboAAADFQ5AAAAf/AAAH/wAAB//
-tBAf/7QQIAbRUCAG1RAgCSUAIAklACAKAAAgCoAAIAqAACAK5oAAAEAAAACAAAAACADhAY4AAAGR
+tBAf/7QQIAbRUCAG1RAgCSUQIAklECAKAAAgCoAAIAqAACAK5oAAAEAAAACAAAAACADhAY4AAAGR
DIAAAAAgC2IAIAthsCALYjD///P/IAth4CALAWAAAEAOH/+S0AAAQBogCwGQAAAQAAAA/+kAAP/g
AABQAAAA//gAAEANAAD/9wAAD/8AAA9CAAD/9QAAIEAAACAAAADEEAAAwAEAAMggIAsB8CALAhAA
AMQAAADIAAAAxDAAAMQxAAIQCOD//gAgCwIw///3/wAA6AAgCwJQAADIEAAAxEUAABABAAAgfAAA
@@ -2948,7 +2948,7 @@ IAslEDAAAAgwAAAMNAAACNAAAAAAAIkUOwAACDSQAAAFXUqAIAREzAAYAAD/B///ADgAAAAwAAAg
C3FQBgAAACAEU4T4AAAAAf//5wABwAAgAACABAAQAB//qbDhAZoA4QGaQOEBmjzhAZo44QGaNOEB
mjAf/64AgAAAA4AAAAIf/6uY//z//+EBDgAf/60Ef////x//lHwf/5T8IARgzCALdQAgC3VAIAt1
cCALdbAgC3XgIAt2ICALdlAgC3aQIAt00A////D/8AAAIAt3MB//sJAf/5n0IAt28B//qMQgBG1s
-IAt4MCALeGAgC3fQIAt3cB//mYQf/5uUAAD/gB//k1AAACMoIAsmACALJjAABAAA//v//+EB4sAf
+IAt4MCALeGAgC3fQIAt3cB//mYQf/5ucAAD/gB//k1AAACMoIAsmACALJjAABAAA//v//+EB4sAf
/6osH/+rsJAAAPD8/4DAAgAAIP7/gMAgCyaAIAsmwAAA+AAAAgEIAAIBDI////8f/6uk4QGYACAL
JxAgCydgIAsnkCALJ9DhAN4AAAIDCAACAgD///AA4QDuAP//f/8AAPwAH/+tHAAA4AAAAAwAAAID
BAABERwAAREYABAIAIAACAAAAgEEH/+dkP//wAAAAP/+AAAlgAACAwAf/6uc4P/iwCALeJAgC3kg
@@ -4517,12 +4517,12 @@ FeAKVQD4IAYVoBslAFiTCSkSECsSM46XKhIy/AACHe/IBQDt5RQneIEAAAj/Ae0SMSf5AQAAn+mf
6C4SNf4miBXv8goAAABsEAYUqLkOLRGk1CVChAUFSglVEfSgCgeSAJ0AH6ggLPIiZMEqG6hFwJD7
cBAV4AoFAG3JEQCQBAsMG+/HBnTIBQAAsarTD/dACCiSAJ0AFqjB/gACHaALBQD80+gVoAiFAG2K
EACwBAwJGQkJQ+nRFHXYEQAA5mwEJ3AFAAD72x4NoAsFAGbgvhqnESqiiyny3KrqCaoRqpkpkTQp
-nSMpnCgcqK0CKwkMuwkvsH4D+hz3cBAV4A2lAA2qLQmqNwpaDOagym0wBIAAKfqcCXkdqalmkLov
-sH8PPxweqKAN/y0cqJ8Pnzb/7+AV74cFAPfgBAfxiAUA+eBAB7N6jQD44AATs/+NAAf/Ai9GoyzA
-gPWABSFSAJ0ALEKIDAxKCcwRZMBDLTx/Dt0B/Y8ADvQPBQDv0lR20/MAAAp+Ev6S5hWgAgUA0Q8A
+nSMpnCgcqK0O6wmsuy+wgAP6HPdwUBXgDaUADaotCao3CloM5qDLbTAEgAAp+pwJeR2pqWaQuy+w
+gQ8/HB6ooA3/LRyooA+fNv/v4BXvhwUA9+AEB/GIBQD54EAHs3qNAPjgABOz/40AB/8CL0ajLMCA
+9YAFKVIAnQAsQogMDEoJzBFkwEQtPH8O3QH9jwAO9A8FAO/SVXbT8wAACn4S/pLmFaACBQDRDwAA
+VEOBe/9WgD//NQNoA4FAB+nB/6UZhXgAgUA0Q8AAAD6AIIdoBuFAOyofhloBIAAWJKcBnIS8pLm
-FaACBQDRDwAAL7B+J7CA7Kh3GWgEgADosH8p8ASAAPYgJhXgCiUA+CAGFaAbhQBYko7HJNEPACk8
-fw6ZAQlZDGafxeymihTQBwAAKqyACnoSDKoC+pJGFa/8/gAAAABsEAYWprsPAgAoYo0mYpCiiAmI
+FaACBQDRDwAAL7CAJ7CC7Kh3GWgEgADosIEp8ASAAPYgJhXgCiUA+CAGFaAbhQBYko7HJNEPACk8
+fw6ZAQlZDGafxeymihTQBwAAKqyACnoSDKoC+pJGFa/8+gAAAABsEAYWprsPAgAoYo0mYpCiiAmI
EQhmCCpiByqiDvoAIh3gDAUA5mwwJVALAADqoBclGgEAAFhc+OhsKCsoBIAA6BYAIzhRAADnFgEj
OPEAAClQBcqbdlFNihGLEHpRNXtZHywwlf2DICDQBAUA2iD04AAGMAtFAFhc6C0wlbFEfULqJVwU
d1nHKTCWy5RokQJokknRD9og+gBiHeAMBQBYXN5j/9wA2iD6AEId4AwFAFhc2dog+gBCHeAMFQBY
@@ -6103,37 +6103,37 @@ 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
-AJ0AwCDRDwAAAKAEDwgZf4eB//5EDaAJJQAAAAAAKfKucZ5M6zIBIgJxgADAoFiWLeatPG0QBIAA
-wKBYliKaMdEPZE0rLFKcjMDJx+ogmCHYEQAAC8AA0qDRDwCKMViWC8Ag0Q/GKtEP0pDRD9KQ0Q8i
-+rnRD8Cg+w4AC/dLAQBYlgwtYAzo2hENGASAAFg49y5SnI7hyeXqIJgr2ASAAOxEAAnoBIAAC+AA
+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
-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
+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
-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
+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
-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
+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
-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
+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
-ZkP6yCYVoQgFAChmRH+XI/rHxhWgC4UA+semFeApBQD4x4YV7/WGAABYzdBj/aEAAAAAAPa85B3v
-9TYAAAAAAABYmHr1QGgdr/YmAFjNx2P9fgAAbBAELEAHiEAeT2wZTR+NIP/P6BWniMEACYgKKIKk
+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
@@ -6154,7 +6154,7 @@ DwBsEATwRcAN7zKBAPBiEA3gJAUAAohXyoECyVPKmQLqUeSgL2Jb/QAAArQ70kDRDwAAIhH//3AN
oBQFAAgiEfSfABWv/1oAAAAMIhH0n4AVr/86AA4tEexM/SIT+QAADcI70Q/AINEPAGwQBBJL0CIi
2NEPAGwQBIIngi6DKIInoyKwItEPAAAAbBAEgieCLoIn0Q8AbBAEEkvFIiLX0Q8AbBAEJfrABSUB
JFEVpUQkTQHjJgEiIwEAAJQg0Q8AAABsEASCJ4IugyaCJaMisCLRDwAAAGwQBIIngi6CJdEPAGwQ
-BBtOviQ8fwQ6FAuqAftCABWgGwUAWKRwI6UC46UDLRAEgAD07gAOMAsFAPtApB3mQwEA7KUEJWBB
+BBtOviQ8fwQ6FAuqAftCABWgGwUAWKRyI6UC46UDLRAEgAD07gAOMAsFAPtApB3mQwEA7KUEJWBB
AADspgAiAUGAAPqAaB2gDRUAWvL2aK4V+oBoHaALBQD8QAgVoA0VAFry8Wmu6dEPAGwQBOdLoRkv
goAAFk6ip1eTdKZVJFZ/0Q8AAABsEAQZTMWJkBpNeBhMwwqZAfhGAAlwFAUABCQClIATTpcUTXMD
IgITTLwEIgHyYAYVoAIFANEPAGwQBBhNjxpMthlLuyaCIR1NaCmSivZCkg2gBwUAJ4LdopkJmRH4
@@ -6397,13 +6397,13 @@ unR70gJ1ugJ0uZQsIh8swhBkwFPqJAAJ2ASAAAvAAGAARyUgIyQgIsCk/mBoHeAbhQDtRAAK8ASA
AFgqWMLS/GAEVGIAnQD2f/qtIgCdABg/cgNPEaj/LvKAGD6yCO4C//AGFa/88gDGqmevSdKg0Q/G
KtEPAAAUPoItICIlQoskQpCtVQlVEaVEJSAjwKT+YGgd4BuFAO0WACrwBIAAWCo+K0BDwoJ4sTL3
f/eVIgCdAIoQGz9YA6oRq6opooAbPycLmQH5UAYV7/teANpA+qBoHeAMFQBbqttj/sKKEPqgaB3g
-DAUAW6rXY/6yAABsEBAXPz0WP3ooIRjyRFAV4AwFACwWBCkgK+00AAQAUYAALyBmZPC38SAFN9AL
+DAUAW6rXY/6yAABsEBIXPz0WP3ooIRjyRFAV4AwFACwWBCkgK+00AAQAUYAALyBmZPC38SAFN9AL
BQB+lwd9lwR8lwHAsfFpMA3gCgUA9AACHaALBQANuxHrqwIJUASAAFv8NdWg63J9KpHKAAApISAq
IgD7TwANdZkBAPUgBhiSAJ0A6z5jFJSRAAD1IBEaEgCdAPUgEZwSAJ0A9SARnZIAnQD1IBMeEgCd
ABw+CizCQi066A29LAfMEQ3MLLDMA60Rpt0s1oFa5bj0RWYdoA0VAPxFxh3gAgUA0Q/A4P5FZh2g
AgUA0Q8AAC8gbA9PQ2T/PiogQ8Ly/0APNGIAnQD6Q+gV4CiFAPlADoQiAJ0AjLRkwaTrHBApUASA
AAvAAIkU+0BPYFIAnQBklPwrIh+Ltcm0AioCC7AA+CCIFeAAOgD6gkgF7/2WAMCg5qeCbSgEgABk
-lNopISDTDwkJRR8+9AM0Ea9EKkKA9SAQTBIAnQD1IBmhEgCdAPkgQmDSAJ0ACttS+WBCCdIAnQAt
+lNopISDTDwkJRR8+9AM0Ea9EKkKA9SAQTBIAnQD1IBnhEgCdAPkgQmDSAJ0ACttS+WBCCdIAnQAt
ICIqICMrIEX1QAvDEgCdAMDJ/UAKdCIAnQD1QAo1EgCdAMDR/EimHeAOFQDx2AAN4AsVAC5CjcCC
COoBeOAcwMDpQrclAHmAAHOXB3SfBHqfAcDB2sAZQPwpRreMFOkgKy5nwoAA6soCDceCgAD7BgAN
MASFAPVGAAowCwUA/yfgB9DEAQB+l3fxIAm/UgCdAPEgIL8SAJ0A/oKAB9ALFQDA4g5NAX5AB8CE
@@ -6411,35 +6411,35 @@ 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
-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
+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
-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
+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
-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
+n+Mn0gCdAMDiDk0B/p/iviIAnQDAhAhOAfif4FCiAJ0AY/xCAAAA9SAKohAOdQD5P+6S0gCdAPn/
+7lFSAJ0AKaKCx/APmQEOmQL5UEYV7/beAGTrKWAEuxg8wSiCi6OICYgRqKpb+BCPFf3gICXgDBUA
+7NWSJ8ALAAD9CiYdoA4FAC72ki72jItQLNWTKnJ/CrsM+PBIFee7AQALqggJqhEKmQgpkgcpkg4q
+nQEsoZItobfroZMmeAGAAP0gQCWgDgUA7sRSJnIBAAD1YAZYkgCdAPVgCFESAJ0A9WALUZIAnQAo
kpkvwFIojAEolpnrpZMngLmAAPqgaB2gCwUA/AACHaANJQBb82AbPLPsP4Ia0ASAAFgk0mP+mwAA
-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
+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
-AC4WEoocW/Q6KhITLhISiRz/+/gNoAs1AI0bKMBSsd0tlpnrpZMsbZYAAI4aZe2oY/24AAAAAAAA
+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
@@ -6517,7 +6517,7 @@ JBEPAgCoRBg5vSRCAAgoCCiAgP8PAAffRAEAGDmMCCgKKIKf+CIABLACBQD7IAQA1IgdAP2AAQHQ
CTUAbZon+CIABLS4HQD7IAQA0ZgxAODJGgyBCoAA6TkCDhgKgADzJgAJ9IsdAMGfApkMeT0PsSL8
XoCCUBn1ANEPAAAAAOtEAAlQBIAAW5CbZ6/h0Q/qJAAKWASAAFuQl9EPAAAAbBAEW/9nHDr4/AAC
HeADBQD5gGgdoBoVAOzNBCboBQAAbaoKI4ZA44ZBJEAhAAAqChHp2ONuQASAABQ5NvSP6BWgAgUA
-Kgr//EBoHaALFQBYkBsqCv9b/zOxImku5txA+gACHeD69QBYkBXZMPh0mAWgGgUAbaoKKYYQ6YYR
+Kgr//EBoHaALFQBYkB0qCv9b/zOxImku5txA+gACHeD69QBYkBfZMPh0mAWgGgUAbaoKKYYQ6YYR
JEAhAAAYOkeIgBk6RsCiCogCmJDRD2wQBMAw9m8uBe/19QAYOWIMJhGoZidmgyVmgidmgSVmgBQ5
WQQkCyNGgSNGgNEPAGwQCOI3pBlABIAA2TDiAAUIkASAAAICYQICYW+EfxI6NvQgaB2gAzUAbToh
5UIHIRgTAADnQgYhMBEAAOU2ACIj4QAA5W0EIRAhAACXUBI32vR0VgWgA2UAbToP4yIHIRPxAADj
@@ -6528,7 +6528,7 @@ NQD7QAQA0AgVAOCIGg0BCoAA/SABBN/69QAKmQMJdwEIdwInRsL0dRQF4RaFAAYmKCRCwqZVJFaf
AQUzAiNGwNEPAABsEAQbOdnrsn8p0ASAAFgkXPwBAh3gDAUAWCOF/EBoHeAMBQBYI5DSsNEPAGwQ
BPJvPgXgAhUAIjaAIjaB0Q8AbBAEhyD4YAgVr/b1AOZGAwJL/QAACXkBCUkMCWYBBoQMp2bmJgAi
gHGAAAVILghIDJgw0Q+UMNEPAAAAbBAGGDpWEzc9GzpV8wGyDaAqBQApMH0KmQIpNH1yuxTaIOwc
-BCjYBIAAWI9WiRBokhJolgHRDywwfS0KgA3MAiw0fdEPLjB9xPAP7gIuNH3RDwAAbBAEKAoACOQW
+BCjYBIAAWI9YiRBokhJolgHRDywwfS0KgA3MAiw0fdEPLjB9xPAP7gIuNH3RDwAAbBAEKAoACOQW
AQIAHTf+AiwJDcwKI8ZkLfrADU0B/KYADvAuBQAO3QItxmUnxmYswmYK6jAbNtEpskErskELmQoK
kgoG6jAGJgxqYQ5tCAgO6jAOLgxq4QJj//AI5BbRDwAAAGwQBPgQAh3lSAUA8xEACT+IBQADkzqj
JCRNASRMPwhCAdEPAGwQBPpAaB2j64UAWCQHHTa5/agoFeAMBQBYIz3SsNEPbBAE6iQACdgEgABa
@@ -6566,11 +6566,11 @@ CBWgDRUAWtxRaa7p0Q+IPyaFBCeFAieFA+SFBSRIQQAA+QAGFe/4igAAAAAAAP/+JA2gChUAbBAE
EjakIyKBezYbKSKKCQlV+yAEANAIFQAAiBoiIv4CIhSigtEPABI4VSIhf9EPbBAI5BYCKbgEgABY
HKETOF0oMX4bOF3zAB1v0gCdACqykiwxgR44WC8xfygxgC3ilMCw+CQABDH/AQD/TQAO8cwBAO3m
lCYdCYAAZIOqHThOGTYD+nCcBaAMRQAs1rDCtyuWECmSESYgDPRBsBWg2QEA/U+GHeDJCQD9T6Yd
-oLkRAPtPxh3gmRkAKaR/WJvS5hYALRAEgADmNPgdFAoAAOkyXSIZkYAAGjeIiBCqiCiAfSJiiKSI
-qCIJIhGikiIsgBs4MSoyXCuysftAAEVwBDUAWJuqWBsfkhFYmy7mojxtEASAAFiapliZoeaiLm0Q
-BIAAWJjH5qIjbRAEgAAsMXvTD37HCliYwOaiEG0QBIAAWJhQ5qIFbRAEgABYmAfmofptEASAAC0x
+oLkRAPtPxh3gmRkAKaR/WJvU5hYALRAEgADmNPgdFAoAAOkyXSIZkYAAGjeIiBCqiCiAfSJiiKSI
+qCIJIhGikiIsgBs4MSoyXCuysftAAEVwBDUAWJusWBsfkhFYmzDmojxtEASAAFiaqFiZo+aiLm0Q
+BIAAWJjJ5qIjbRAEgAAsMXvTD37HCliYwuaiEG0QBIAAWJhS5qIFbRAEgABYmAnmofptEASAAC0x
fvOgEX/SAJ0ALjF//oARoKIAnQArMYHB+A8CAPvgEbjiAJ0A+oASuOIAnQAoMYDTD3uHGuoSASvY
-BIAA7BICKugEgABYlXnmoaltEASAAFv+rBw4A9MP0w8pwqn2IGYV4AIFAOUWBCSEeYAAFjf/Fzf+
+BIAA7BICKugEgABYlXvmoaltEASAAFv+rBw4A9MP0w8pwqn2IGYV4AIFAOUWBCSEeYAAFjf/Fzf+
5TW2EyAhAAATN/gYNLQjMl0ogoYmdr4mdr8kdsCoKOR2wSxGQoAAqDMtMAf6YOgVoP7FAP+gBAaw
CwUA/EYADvAMFQDtNAclUIEAAFrk8JWgiTAcN+r9QEYVoA4VAOw34xzOAoAADpkCmaEowqknfBTi
LAEiIFEAAOgji3MwUQAAhRSHExM0sC0yIC3GUP2gAQfz6IUACNgo6MZNL//CgAD/ieYV4G5FAA7d
@@ -6578,9 +6578,9 @@ KC3GTlrh5mWiT8AgZiDHW/325qDBbRAEgABYHAspMH3rN80U6KKAAB00Ryiydin6/QmIASi2di8K
AC+2cSzSyB40ZikwfQ7MASzWyHmfIi2ydsfrDt0BLbZ2HDetLMJ/wNDttnImAGGAABg3qsDwL4bA
WuHKyaZa4clkoUmDEYs3KjANIzB367IOJQp5gAAYNF8vgq4ZNLMaNDX8aLYF4AsFAPnmAA/wTHUA
/xXGFeAeBQBt6gwuoZDs4S51UAkAALG7L9KCGDel+eAEB7AIFQAI/wIv1oJYG9zaUOt0AAlgBIAA
-WB6EwCDRD2a/1CrShPtgBADQCRUA/SABBN/89QAMnAMMqgEKmQL5sIYV7/8mAAAAAAAAWJdo563O
-bRAEgABj/7EAAFiXVOetyW0QBIAAY/+hAAAAAADqEgEr2ASAAOwSAiroBIAAWJb75q+GbRAEgAAr
-MYHTD/qf7Y5iAJ0A6hIBK9gEgADsEgIq6ASAAFiVSeetlm0QBIAAY/9WAABb/wEbN2/7ckYVr/FC
+WB6EwCDRD2a/1CrShPtgBADQCRUA/SABBN/89QAMnAMMqgEKmQL5sIYV7/8mAAAAAAAAWJdq563O
+bRAEgABj/7EAAFiXVuetyW0QBIAAY/+hAAAAAADqEgEr2ASAAOwSAiroBIAAWJb95q+GbRAEgAAr
+MYHTD/qf7Y5iAJ0A6hIBK9gEgADsEgIq6ASAAFiVS+etlm0QBIAAY/9WAABb/wEbN2/7ckYVr/FC
AIgQImKHqCIJIhHzIABBP/N2ACvmlSvmlivml/vTBhXv8VoAHTdjK9acK9abK9aa+7OmFe/xFgDA
ovxp0gWgCwUAWB/fY/63AAAA+CAoFeAKRQD8abYFoAiFAPhmAAwwblUA6JR3JfgXAAD//oQdoA01
AP/+pB2gCwUAWB/QGzdUK7J/yLQqEgELsADJNsCl/GmaBaALBQD+DIIdoA01AFgfx2P+WYwRLMB3
@@ -6964,7 +6964,7 @@ bBAEEyKgDCIRoyKCINEPAGwQBBUinQwkEaVEI0bAJELA0Q8AbBAEFSKZ+D60BahiHQDqZBELTwKA
AOVFCAzPgoAA6JkIBDnBAADnQggBgemAAPZAaB2gA4UADwIAbToQ45IcJMghAAAkkhsklhojlhsG
YIYFAmcGQIYFAmUGIIYFAmMGAIYFAmHRDwXghgICbwXAhgICbQWghgICawWAhvIQqB2gA4UADGIR
CCIKDwIA0w/TD206EOMiHCEQIQAAJCIbJCYaIyYb0Q8AbBAE8j5iBagyHQAKMxGjIiIscNEPAAAA
-bBAEGiJqGyJq7z0QCWQCgADtzAIKbgKAAA3MAliZ2MAg0Q8AbBAEBOowGB6bKIJBAogoqEID6jAD
+bBAEGiJqGyJq7z0QCWQCgADtzAIKbgKAAA3MAliZ2sAg0Q8AbBAEBOowGB6bKIJBAogoqEID6jAD
IwxqMQ5tCAgJ6jAJKQxqkQJj//DRDwAAAAAAbBAELSANKyAMFB/35x/4FotBgAAocH0uQiCw3wj/
KKvur+4oIAVogyZohHb1AAlqkgCdAPUACkMSAJ0A9QAKk5IAnQBoiAPAINEPwJMpJAUfHqXAMA/u
CyriwBgiQQoMSgjMEQjMAgwMT/33ZhWpqmEAbakCI/a8I/a7KuLAGB9/CgxKCMwRCMwC/eAABjAJ
@@ -7056,8 +7056,8 @@ uAUAAHKzB/JaABWgAFYAcqsKcsMH8lUgFaAAHgAiLMkCiAn4gAYVoAIFANEPwJD4gAYV4AIFANEP
AAAAbBAEIyUC4yUDIWBBAAD8QAYVoAsFAOslBSHB/QAA8sAAAfeIHQDoJQQhgUGAAPpgaB2gDRUA
WsDwaK4V+mBoHaALBQD8QAgVoA0VAFrA6mmu6chLKSEEDJkRKZwQmUDRD9EPAGwQBBgZyBIddCiC
jyMibAmIEagziDdkgFL8OuAFoApFAPxgCBXgCwUA7zIHKfAEgABYBYOEN+oaiBIgQQAAWlYrHBqF
-HRl7Hh1mjzDrpAAKUASAAFpV4YM3IzwQ2jBaVb9ooSrRDwAAAAAAAPoIAh2gSwUAWJXl+mAIFe/8
-9QD6YOYVoA0FAFhyE2P/iwAA2jBaVc8TGcULqBHoMwgFAbGAAAzqMCsyhYuwsKPsuwgJ0ASAAFgG
+HRl7Hh1mjzDrpAAKUASAAFpV4YM3IzwQ2jBaVb9ooSrRDwAAAAAAAPoIAh2gSwUAWJXn+mAIFe/8
+9QD6YOYVoA0FAFhyFWP/iwAA2jBaVc8TGcULqBHoMwgFAbGAAAzqMCsyhYuwsKPsuwgJ0ASAAFgG
3SoilPpgBADQCxUAALsaC6oCKiaUWAcT0Q8AAAAA+gDiHaALFQBayCAsMn8sNoPRDwBsEAQTGr4S
GdkiNoPRDwAAbBAEEx0nAwCH4wAHAQBJgAACAGHRD9EPbBAEExq0IjK4Ija40Q8AAGwQBB0ZTx4Z
nR8dMBkdMhIaShMdLBUdLBwdLiw2jiU2fiI2hSk2cCk2cS82hi42je3SQSTRAQAAKjaA6jaBJNiB
@@ -7067,7 +7067,7 @@ APCAcA3josEAKkQA8KBwDemyYQArVQDwwJAN6sIBACxlANEP0Q8AAABsEAQTGnkiNpzRDwBsEATo
Gn8RgMGAABUckyiAfSVSf7A0CEQoolKkItEP0Q8AAABsEAQYGQz4NSwF4AX1APcSaBWgCuUACWYB
Blo5FBodAyMRpDMrMoIZGS75EmgVr/wFAAy7AQuqAvpwRhWg9gUA+QAEBHDiBQAIYjkkMoIl+g8F
RAEEIgLycEYVoAIFANEPAAAAbBAE8jm6BeDJxQAJKSgYGTv4YABB8AoVAPpwRh2gCQUAKTSAKTSD
-KTU+KIB9DwIADwIAf4cYAioCWF/04qQADQDmAADAqyo0gNEPAAAAANogWF/e4qQABX9hgADRDwAA
+KTU+KIB9DwIADwIAf4cYAioCWF/24qQADQDmAADAqyo0gNEPAAAAANogWF/g4qQABX9hgADRDwAA
bBAEwCHRDwBsEAQXGq4pciMUHML5IAgV4MXFAAUlKPSAAEJwmYEAKUSAKHIjiIAIElIiRIEmciOG
YAZGUCZEgiVyI4VQ9FYAAvAIFQDlRIMhPK0AACpwgAYsDPWPAA5wAgUA7MwdJQxVAAAAwQToRJ8s
WAqAACtGI9EPAMAgIkYj0Q8AbBAEFRjhJFKE+kAEANAHFQDgNhoJAQqAAPzgAQPf+PUACHcDB0QB
@@ -7079,12 +7079,12 @@ AGwQBBIYdyIiQ/JDaBWgAxUAAnJWAyIJAgJH0Q9sEARkQFEpIABkkEvAcOgwACIMy4AAeYkqbQga
B0YM6GE1Y7gFAABqYg+jeKJ5KZAAKIAAeYkMY//eo3iieSmQACiAAHiTC/kCNg3gAhUAwCDRD8cv
0Q8AwCDRD9EPAABsEAQTHEWjItEPAABsEAQbGFUrskPpLAQp4ASAAPNgAEWx+PUA+QGWDeAKBQD7
YCgVoAASAIuwWAWzC0IB0Q8AbBAEHRw2GBw2+aBoHeG6xQBtqgUIAIYJAmHrHDIe0ASAAFgF3tEP
-AGwQBhMYZvQ4AAXgAgUAJDKuGBr0CEgBKDauIlaoIlapIlaqIlarWJvDFxg0KTroKXZBWJudWJuJ
-5qDtbRAEgABYm3DmoOJtEASAAFibK+ag120QBIAAWJqL5qDMbRAEgABb/93+gYAIkAYVACtSgNMP
+AGwQBhMYZvQ4AAXgAgUAJDKuGBr0CEgBKDauIlaoIlapIlaqIlarWJvFFxg0KTroKXZBWJufWJuL
+5qDtbRAEgABYm3LmoOJtEASAAFibLeag120QBIAAWJqN5qDMbRAEgABb/93+gYAIkAYVACtSgNMP
f7dFL3JCGBwSKXrQCf8oCEgB6DauL/8CgAAG/wIvNrf+dugVoA0FAA3kMQECACwyt2bAD20IBSoy
-t2agBmP/8wAAAADAo1pPIliZzuagaG0QBIAAWJmj5qBdbRAEgABYmUXmoFJtEASAAFiY7eagR20Q
-BIAAIjKu0w8PAgB0L0YbGr0LKwErNq5YmK5YmKHmoCVtEASAABoYwRsYwFiUZhwb7OrGfyUGwYAA
-GxrbtLxYlDvSoGcgBMChWsZ30Q9j//wAAAAAAPQwZAXickEACHcRBwRHBUQKKELkB4UU6BYAKtAE
+t2agBmP/8wAAAADAo1pPIliZ0OagaG0QBIAAWJml5qBdbRAEgABYmUfmoFJtEASAAFiY7+agR20Q
+BIAAIjKu0w8PAgB0L0YbGr0LKwErNq5YmLBYmKPmoCVtEASAABoYwRsYwFiUaBwb7OrGfyUGwYAA
+GxrbtLxYlD3SoGcgBMChWsZ30Q9j//wAAAAAAPQwZAXickEACHcRBwRHBUQKKELkB4UU6BYAKtAE
gAALgAAKCUFokQf5IAVh0gCdAChC6tpwC4AAzamIENpQC4AACglBaJECaZNlKELq2nALgABkr+SW
oRwaspygGxvNGhmLiBD6QAQF8pKBACmkgOs2rirQBIAAC4AAKELo06D64GgdoAsVAAuAAPicyBWv
+8UA+mAEBfAMpQDsuwIK0ASAAAuAAPJf+niSAJ0AY/8R//54DaAKBQD8N24FoAoVAPoAIh3v/UUA
@@ -7190,13 +7190,13 @@ lZAgBpUwAAAAACAGl/ggBpgAIAaKqAAAAAAAAAAAAAAAAAAAAAAgBocAIAaCaAAAAAAgBoJgIAaC
WCAGglAAAAAAAAAAAAAAAAAAAAAAIAZ+wCAGfrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgBLKgIAS5qCAEunQg
BK2AAAAAAAAAAAAgBLvIAAAAAAAAAAAAAAAAIAS5HCAEuHggBL6QIAS8dCAEr4ggBLDgIASxvCAE
-ubAgBK8oAAAAACAIIdggCCI4IAMtKCADKoAgAykMAAAAAAAAAAAgAyskAAAAAAAAAAAAAAAAAAAA
-AAAAAAAgAyY4IAPAzCADJ/QgAyTYIAMndCADKQQAAAAAIANCyCAIJSQgCCJsIANEMCADNyAgAzFo
+ubAgBK8oAAAAACAIIeAgCCJAIAMtKCADKoAgAykMAAAAAAAAAAAgAyskAAAAAAAAAAAAAAAAAAAA
+AAAAAAAgAyY4IAPAzCADJ/QgAyTYIAMndCADKQQAAAAAIANCyCAIJSwgCCJ0IANEMCADNyAgAzFo
IAM0mCADMjAgAznAIAMt9AAAAAAgAzygIAM7FCADM4AgAzXwIAM9yAAAAAAgAyTYIAMwICADLTAA
AAAAAAAAAAAAAQIAAQAAAAAAAAAAAAABAAECAwQFAjIyAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAA
AAAAAAAAAxAAAAAAAAAAAAAAAAAAAAAAAAH/AAAAAAAAAQAAAAAf/OEwAAAAAOAAAOABAAAAIAkD
-wAAAAAEgCQH0AAAAAiAI/UAAAAABIAj6uAAAAAEgCPikAAAAASAI9pgAAAABIAj0BAAAAAEgCOco
-AAAAASAI7iAAAAABIAjl8AAAAAEgCOXoAAAAAQAAAAAAAAAAAAEAAQAAAAAAAAAAAAAAAAQAAAAI
+yAAAAAEgCQH8AAAAAiAI/UgAAAABIAj6wAAAAAEgCPisAAAAASAI9qAAAAABIAj0DAAAAAEgCOcw
+AAAAASAI7igAAAABIAjl+AAAAAEgCOXwAAAAAQAAAAAAAAAAAAEAAQAAAAAAAAAAAAAAAAQAAAAI
AIkGAAAAAAAAAAAEAAABCACJFAAAAAAAAAAABAAAAiABDLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAABAAAAAgAiQYAAAAAAAAAAAQAAAEIAIkUAAAAAAAAAAAEAAACIAEMvAAAAAAAAAAA
@@ -7256,17 +7256,17 @@ AAAAAwAAkAQAAAA+AAEQeAD///8AARB8AP///wABEIgAAAAAAACUBAAA//8AAJQQAAD//wAAmFQA
AAH/AACYWAAAAf8AAJYIAAAAAAAAlhAAH///AACWGAAf//8AAJYcAA///wAAliQAD///AACWKAD/
//8AAJYwAP///wAA0CAAAAAHAADQJAAAAAcAAhDYAAAAAwACMNgAAAADAAJQ2AAAAAMAAnDYAAAA
AwABkFAAAAAvAAGg1AAAAYMAAZCMADgAAAABkJgAOAAAAAB5dAAAAC8AAHlwAAAABQAAefQAAAAv
-AAB58AAAAAUgAw7UIAjS5CADDtggCOJIIAMO5CAI4XAgAw7wIAjhICADDwQgCOBwIAMPHCAI3wgg
-Aw8sIAjd8CADDzQgCN3IIAMPSCAI3aAgAw9YIAjdcCADD2QgCNxUIAMPbCAI3CwgAw+AIAjb+CAD
-D4wgCNqMIAMPlCAI2eQgAw+kIAjY4CADD7AgCNfQIAMPwCAI1sggAw/QIAjVnAAAAAAAAAAAIAMP
-6CAI0qwgAw/sIAjSMCADD/QgCNH4IAMP/CAI0cAgAxAIIAjRiCADEAwgCNFQIAMQGCAI0RggAxAc
-IAjSaCADECQgCNDgIAMQLCAI0KggAxA0IAjN2CADEDwgCNBYIAMQSCAI0FAgAxBQIAjQGCADEFgg
-CM/gIAMQYCAIz6ggAxBoIAjPcCADDqwgCMwAIAMQcCAIy8ggAxB4IAjLkCADEIAgCMtYIAMQkCAI
-yyAgAxCYIAjK6CADEKAgCMqwIAMQqCAIyoggAxC0IAjKYCADEMAgCMowIAMQ2CAIygggAxD0IAjJ
-4CADEQQgCMm4IAMRFCAIyZAgAxEkIAjJaCADETQgCMlAIAMRRCAIyRggAxFUIAjI8CADEWAgCMjI
-IAMRbCAIyKAgAxF4IAjIeCADEYQgCMdYIAMRiCAIxWQgAxGUIAjEgCADEaggCMRQIAMRsCAIxCAg
-AxG8IAjD8CADEcAgCMPAIAMRxCAIw5AgAxHIIAjDZCADD1AgCMJ4IAMR2CAIwlAgAxHgIAjCKCAD
-DrggCOU4IAMOwCAI5GggAw6kIAjjuCADDswgCOMQAAAQISBCMGNAhFClYMZw54EIkSmhSrFrwYzR
+AAB58AAAAAUgAw7UIAjS7CADDtggCOJQIAMO5CAI4XggAw7wIAjhKCADDwQgCOB4IAMPHCAI3xAg
+Aw8sIAjd+CADDzQgCN3QIAMPSCAI3aggAw9YIAjdeCADD2QgCNxcIAMPbCAI3DQgAw+AIAjcACAD
+D4wgCNqUIAMPlCAI2ewgAw+kIAjY6CADD7AgCNfYIAMPwCAI1tAgAw/QIAjVpAAAAAAAAAAAIAMP
+6CAI0rQgAw/sIAjSOCADD/QgCNIAIAMP/CAI0cggAxAIIAjRkCADEAwgCNFYIAMQGCAI0SAgAxAc
+IAjScCADECQgCNDoIAMQLCAI0LAgAxA0IAjN4CADEDwgCNBgIAMQSCAI0FggAxBQIAjQICADEFgg
+CM/oIAMQYCAIz7AgAxBoIAjPeCADDqwgCMwIIAMQcCAIy9AgAxB4IAjLmCADEIAgCMtgIAMQkCAI
+yyggAxCYIAjK8CADEKAgCMq4IAMQqCAIypAgAxC0IAjKaCADEMAgCMo4IAMQ2CAIyhAgAxD0IAjJ
+6CADEQQgCMnAIAMRFCAIyZggAxEkIAjJcCADETQgCMlIIAMRRCAIySAgAxFUIAjI+CADEWAgCMjQ
+IAMRbCAIyKggAxF4IAjIgCADEYQgCMdgIAMRiCAIxWwgAxGUIAjEiCADEaggCMRYIAMRsCAIxCgg
+AxG8IAjD+CADEcAgCMPIIAMRxCAIw5ggAxHIIAjDbCADD1AgCMKAIAMR2CAIwlggAxHgIAjCMCAD
+DrggCOVAIAMOwCAI5HAgAw6kIAjjwCADDswgCOMYAAAQISBCMGNAhFClYMZw54EIkSmhSrFrwYzR
reHO8e8SMQIQMnMiUlK1QpRy92LWkzmDGLN7o1rTvcOc8//j3iRiNEMEIBQBZOZ0x0SkVIWlarVL
hSiVCeXu9c/FrNWNNlMmchYRBjB212b2VpVGtLdbp3qXGYc499/n/tedx7xIxFjlaIZ4pwhAGGEo
AjgjyczZ7emO+a+JSJlpqQq5K1r1StR6t2qWGnEKUDozKhLb/cvc+7/rnpt5i1i7O6sabKZ8h0zk
@@ -7287,13 +7287,13 @@ QOEAegAgCz6wIAs/ACALP2AAAA//P////yALP8AgC0AwIAtAcCALQLAgC0DwIAtBMCALQXAgC0Gw
IAtB8CALQjAf/5usIAMNQCADDOAf/5NU4QGaAB//nBz/wP//ABAAAB//rWQAAAgAAAYIAB//nfAA
AZ4M4QGeAAABnnQAAZ6sAAGe1AABnuwAAZ8UIAtCcCALQtAgC4mQIAuJICALiEAgC4iAIAuI0OEA
LgAgAw1QAACQAB//lPQALBQAgAAAgOEAWgCB8OCAIAAAAOEAVgAMAAAA//OAAAAMOABGAAAAPz//
-/4CAAADz/////+D//wABAAAgCAAAIAgKJAAACyAgCAEA4QGSAOEADgAf/62cH/+baAACAAAAfwBA
+/4CAAADz/////+D//wABAAAgCAAAIAgKJAAACyAgCAEA4QGSAOEADgAf/62cH/+bZAACAAAAfwBA
AAMAAACAAIAAwQDA//8j/wAAyAAQIAEg4QCKAOEAfgDhAI4APAAAAP//v/9QaOhH+P///wQAAACS
AAAA8ADwAJ+///sgAAAEH/+TUH/3//+AAAIA///v////gP//9/9/AAYAAP//8AD/AAAAAEkkkgAA
fhgIAQgBEAEQAQAAfkAgASABFRUVFYQhhCEQEBAQ4QGOAAAA/n8EBAGAzMzMzIiIiIhERERE4QDO
AOEAjgThAI4I4QCODOD//gCAAAEAIAgExAAAkAgAAAjAgAHEEcQRxBEA/wD/AEAAQP//P/8gC4pA
IAuKcP8P//8gC4oACAgICMyIRAAgC4qgREQAAMzMiIj/8P8AAAIAMyoqFRUf/6scH/+YeB//rNAf
-/5zQH/+a1B//nZAf/5qcH/+tlAAA//0f/6qU4wACAOL//wAgC0RAIAjjECALi5AAUAAAAKAAACCg
+/5zQH/+a1B//nZAf/5qcH/+tlAAA//0f/6qU4wACAOL//wAgC0RAIAjjGCALi5AAUAAAAKAAACCg
AADQAAAAIAuK0CALi2AAABAAIAMHmB//r5Af/6uUH/+AsB//q9Af/60AIAuNQCALRoAgC0cAIAtH
cCALjPAgC4ywIAuNECALSAAABAAAH/+A4B//gSAf/4FgH/+aDB//qhgf/5TU4QGWAOEB/gDhAl4A
4QI+AOECHgDhAeIA4QEOAOEAkgAIAAAA///w/x//qNAf/5uQ4QEOBOEBDgjhAQ4M//AAAAACgAb/
@@ -7307,1947 +7307,1956 @@ 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
-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
-i4UAW2K5HbsvHL1i7NZDJmALAAAs1kTRD2wQBBq70uus0CENWQAAaCJu5JCEZJAFAAD8QmARUAQV
-AGAAOGlkBQWoCCeGAHJLLOo0AApYBIAAW2ar6GEUYiAFAADlqQgLF3QAAPcgBB3v/3oApav3YAYd
-7/9SANEPACuieymihKO7CbsR65kIAw3dAABoYnZpZOOlnJfA0Q8AGbvCqTkpkH1oQDbkkGViEAUA
-AHJDmWP/wyyyhymihKPM6cwRAiAFAADsmQgDDG0AAGhiHWhkJPKf+6uiAJ0AY/+aZZ9LY/+UpZj3
-AAYd7/+mAKWa90AEHe//fgClm/dgBhXv/1YApZwnxADRD6WdJ9UA0Q/RDwAAIAMOYAzAAAYgBqw8
-IAMOZAjAAAwgBqw8IAMOaCDAABAgBqvEIAMObAbAADggBq2gIAMOcAjAADwgBqw8IAMOdALAAEAg
-Bq2gIAMOeAjAAEQgBqw8IAMOfAiAAEggBqzMIAMOgBiAAFwgBqzMIAMOhBiAAGwgBqzMIAMOiBiA
-AHwgBqzMIAMOjBiAAIwgBqzMIAMOkBiAANwgBqzMIAMOlBiAAOggBqzMIAMOmBiAAPQgBqzMIAMO
-nBiAAQAgBqzMIAMOoAiAATwgBqzMaHdfYmNtODQzNF9jaGVja3JhbTogU3RhcnQKAAAAAABQSFkg
-cHJvY2Vzc29yIG5vdCBydW5uaW5nLCBzdGlsbCBpbiByZXNldCBmb3IgNW1zLCBwb3J0X2JpdF9t
-YXA9JXUgCgAAAAAAAAAAAAAAAFBIWSBGVyBoYXMgYmFkIENSQywgb2tfY3JjPSV1CgAAUEhZIGZp
-cm13YXJlIGxvYWQgc3VjY2Vzc2Z1bCEKAABod19iY204NDgzNF9sb2Fkc2VxdWVuY2U6IFN0YXJ0
-ZWQKAAAAAAAAAAAAAAAAAABod19iY204NDgzNF9sb2Fkc2VxdWVuY2U6IFVwbG9hZCBpbWFnZSB0
-byBQSFkgb24tY2hpcCBtZW1vcgoAAAAAaHdfYmNtODQ4MzRfbG9hZHNlcXVlbmNlOiBkb25lIGxv
-YWRpbmcgaW1hZ2UgKGkgPSAldSkKAAAAAAAAAAAAAGh3X2JjbTg0MzRfbG93cG93ZXJbJXVdOiBl
-bmFibGU9JWQKAAAAAAAAAAAAAAAAAGh3X2JjbTg0MzRfbG93cG93ZXJbJXVdLCBmYWlsZWQgdG8g
-c2V0IDMwLjB4NDAxQWJpdCA3IHNpbmNlIDMwLjB4NDAwRSBiaXQ9MSBhZnRlciA1bXMsCXJlZz0l
-eAoAAGh3X2NsNDVfaW5pdFsldV0gYWNhcHMgJSN4CgAAAAAAaHdfY2w0NV91cGRfc3BkX2FkdiAl
-I3gKAAAAAAAAAABod19hcTEyMDJfbGlua191cFsldV0gdXAKAAAAAAAAAHBbJXVdIFBIWSBPVkVS
-SEVBVEVEIC0gZm9yY2VkIHBvd2VyIGRvd24gKHRlbXA9JWQpCgAAAAAAAAAAAAAAAABGTEFTSCBu
-b3QgcmVhZHk6IGkgJXUgbnZyUmVnICUjeAoAAAAAAAAAAAAAAAAAAABBUV9GTEFTSF9SZWFkeSAt
-IFRpbWVvdXQgKDEpCgAAAEFRX0ZMQVNIX1JlYWR5IC0gVGltZW91dCAoMikKAAAACUFRX1JldHVy
-bkNvbnRyb2xPZkZMQVNICgAAAAAAAABnYXRoZXJfdGFza3NfdG9fdHhfbGlzdDogdGFzayBpbiB1
-c2UgWyV1XQoAAAAAAABnYXRoZXJfdGFza3NfdG9fdHhfbGlzdDogaWR4IFsldV0sIHRhc2sgZmlk
-IFsweCV4XSwgdGFzayBzdGF0ZSBbMHgleF0sIHRhc2sgY29ubiBbMHgleF0sIHRhc2sgZmZsYWdz
-IFsweCV4XSwgY29ubiBmaWQgWzB4JXhdLCBkZHAgWyVkXQoAAAAAAAAAAABnYXRoZXJfdGFza3Nf
-dG9fdHhfbGlzdDogdGFzayBbMHgleF0sIHN0YXRlIFsweCV4XSBvbiBjb25uIFsweCV4XSBub3Qg
-dmFsaWQgdG8gZ2F0aGVyLCBza2lwcGluZwoAAAAAAAAAAAAAAAAAAAAAZ2F0aGVyX3Rhc2tzX3Rv
-X3R4X2xpc3Q6IHRhc2sgWzB4JXhdLCBzdGlsbCBxdWV1ZWQgb24gdHggcGVuZGluZyBsaXN0LiBS
-ZW1vdmluZyBpdC4KAAAAAAAAAAAAAAAAZ2F0aGVyX3Rhc2tzX3RvX3R4X2xpc3Q6IGNvbm5fZmMt
-PmZsb3djX2ZsYWdzIFsweCV4XSwgbGlzdF9lbXB0eSBbMHgleF0sIGFkZF90YXNrX2NvdW50IFsw
-eCV4XQoAdG9fdHhfbGlzdDogbm8gdGFzayB0byBjbG9zZSBmb3IgY29ubiBbMHgleF0sIGJhaWxp
-bmcgdG8gcmVjb3Zlcnkgc3RhdGUgWzB4JXhdCgBhdXRoZW50aWNhdGVfdGFyZ2V0OiBLRVlfQ0hB
-UF9SRVNQIC0gWzB4JXgleCV4JXgleCV4JXgleF0KAAAAAAAAYXV0aGVudGljYXRlX3RhcmdldDog
-S0VZX0NIQVBfUkVTUCAtIFsweCV4JXgleCV4JXgleCV4JXhdCgAAAAAAAGF1dGhlbnRpY2F0ZV90
-YXJnZXQ6IEluY29ycmVjdCBwYXNzd29yZAoAAAAAAAAAAENIQVBfQzogZGlnZXN0IGV4cGFuc2lv
-biBlcnJvcgoAQ0hBUF9OOiBUYXJnZXQgdXNlcmlkIG1pc21hdGNoCgBDSEFQX1I6IGRpZ2VzdCBl
-eHBhbnNpb24gZXJyb3IKAGlTQ1NJIFNlYy1wYXJhbXMgcmVjZWl2ZWRoYXZlIGVycm9ycyEhCgAA
-AAAAAAAAAFRhcmdldCBtb3ZlZCB0ZW1wLiBjb25uICV4LCBzZXNzICV4CgAAAAAAAAAAAAAAAExv
-Z2luIEZhaWxlZCEhLiBjb25uX2ZjIFsweCV4XSwgc2Vzc19mYyBbMHgleF0sIHN0YXR1c19jbGFz
-cyBbMHgleF0KAAAAAAAAAAAAAAAAUHJvdG9jb2wgRXJyb3IgY2JpdCAlZCB0Yml0ICVkIGNzZyAl
-ZCBuc2cgJWQKAAAAcmVjdl9ub3BpbjogY3RybCB0YXNrIGFscmVhZHkgcGVuZGluZwoAAAAAAAAA
-AAAAb2ZsZF9yeF9kYXRhOiBhaWVlLCBpc2NzaSBjb25uIFsweCV4XSBmb3Igc2VzcyBbMHgleF0s
-IHR5cGUgWzB4JXhdIHRyYW5zaXRlZCBpbiB0b2UgbW9kZS4gS2lja2luZyByZWNvdmVyeSAKAAAA
-AG9mbGRfcnhfZGF0YTogY29ubiB0aWQgWzB4JXhdLCByeF9kYXRhLT5zZXEgWzB4JXhdLCByeF9k
-YXRhLT5sZW4gWzB4JXhdLCByeF9kYXRhLT5zdGF0dXMgWzB4JXhdCgAAAAAAAAAAAAAAAAAAAABv
-ZmxkX3J4X2RhdGE6IGNzayB7IGlkIFsweCV4XSwgY3NvY2tfb2Zmc2V0IFsweCV4XSwgZGxlbiBb
-MHgleF0gfQoAAAAAAAAAAAAAAAAAAGFjdF9lc3Q6IHRjYl9mYyBbMHgleF0sIGZsb3djX2ZvaXNj
-c2lfY29ubl9mbGFncyBbMHgleF0KAAAAAAAAAABhY3RfZXN0YWI6IHRjYl9mYy0+Zmxvd2NfYnVm
-IFsweCV4XSwgdGNiX2ZjLT5mbG93Y190eXBlIFsweCV4XSB0Y2JfZmMtPmZsb3djX3N0YXRlIFsw
-eCV4XSwgbnBhZ2VzIFsweCV4XSwgZmxvd2NfdHBfc25kX21heCBbMHgleF0KAAAAAAAAAAAAAAAA
-AABhY3RfZXN0YWI6IGF0aWQgWzB4JXhdLCB0aWQgWzB4JXhdLCBvcCBbMHgleF0sIHJjdl9pc24g
-WzB4JXhdLCBzbmRfaXNuIFsweCV4XSwgY3NvY2stPmZsb3djX3N0YXRlIFsweCV4XSwgdGNwX29w
-dCBbMHgleF0sIHRjYl9mYy0+Zmxvd2NfaWQgWzB4JXhdIAoAAAAAAAAAAAAAAAAAY3NrX2ZjLT5m
-bG93Y19jc29ja19jb29raWUgWzB4JXhdIAoAAAAAAAAAAAAAAAAAY2huZXRfcXVldWVfeG1pdDog
-ZmMtPmZsb3djX2lkIFsweCV4XSwgYnVmX2xlbiBbMHgleF0sIGJ1ZmZlcmVkIFsweCV4XSwgZmlm
-by5udW1fYnl0ZXMgWyUweF0KAAAAbmV0aWZfZG9fZGhjcDogd3ItPnBhcmFtLnZsYW5pZCBbJXVd
-LCBsMmRldl9mYy0+Zmxvd2NfbmV0X2wyZGV2X3ZsYW5kZXYgWzB4JXhdCgBsM2luNF9kZXZfY29u
-ZmlnOiB3ci0+cGFyYW0udmxhbmlkIFsldV0sIGwyZGV2X2ZjLT5mbG93Y19uZXRfbDJkZXZfdmxh
-bmRldiBbMHgleF0KAAAAAAAAAAAAAAAAAABuZXRfbDNpbjRfZGV2X2NvbmZpZzogbDJkZXZfZmMt
-PmZsb3djX2lkIFsweCV4XSwgYWRkcmVzcyBhbHJlYWR5IHVzZWQgYnkgcG9ydCAlZAoAAAAAAAAA
-AAAAAAAAAABuZXRfbDNpbjRfZGV2X2NvbmZpZzogIGFkZHIgWzB4JXhdLCBtYXNrIFsweCV4XSwg
-Z3cgWzB4JXhdLCByZWZfY250IFsweCV4XSBpbiB1c2UKAAAAAAAAAAAAAAAAAAB3cmhfY2huZXRf
-aWZjb25mOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBsMmRldl9mYy0+Zmxvd2NfdHlwZSBb
-JTB4XSwgaWZjb25mX3dyLT5zdWJvcCBbMHgleF0KAAAAAAAAAAAAAAAAAAAAd3JoX2NobmV0X2lm
-Y29uZjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgdW5rbm93biBzdWJvcCBbMHgleF0KAAAA
-AAAAAAAAAAAAAAB3cmhfY2huZXRfaWZjb25mOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBy
-YyAlZAoAAAAAAAAAAAAAAAAAbmV0aWZfaXBfY29uZmxpY3RfdGltZXJfY2I6IGwyZGV2X2ZjLT5m
-bG93Y19pZCBbMHgleF0sIGluZGV2Y3R4dC0+c3RhdGUgWyVkXSwgaW5kZXZjdHh0LT5yZXRyeV9j
-bnQgWyVkXQoAAAAAAAAAAG5ldGlmX2lwX2NvbmZsaWN0X3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxv
-d2NfaWQgWzB4JXhdLCBpbmRldmN0eHQgWzB4JXhdLCBpbiBmcmVlIHN0YXRlCgAAAAAAAAAAAGNt
-ZGhfY2huZXRfaWZhY2U6IGZjIFsweCV4XSwgZmMtPmZsb3djX2lkIFsweCV4XSwgZmMtPmZsb3dj
-X3R5cGUgWzB4JXhdLCBwIFsweCV4XSwgbGVuMTYgWyV1XSwgbG9jIFsweCV4XQoAAAAAAABjbWRo
-X2NobmV0X2lmYWNlOmwyZGV2X2ZjIFsweCV4XSwgbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwg
-bDJkZXYtPmZsb3djX3R5cGUgWyV1XSwgbDJkZXZfZmMtPmZsb3djX25ldF9sMmRldl9mbGFncyBb
-JTB4XQoAAAAAAGNtZGhfY2huZXRfaWZhY2U6IHIyWzBdICV1IHIyWzFdICV1CgAAAAAAAAAAAAAA
-AGNtZGhfY2huZXRfaWZhY2U6IGwyZGV2X2ZjLT5mbG93Y19uZXRfbDJkZXZfZmxhZ3MgY2hhbmdl
-ZCBmcm9tIFslMHhdIHRvIFslMHhdLCByYyBbJWRdCgAAAAAAAAAAAGNobmV0X2wyZGV2X3VwX21i
-X2NiOiByYyBbJWRdLCBwb3J0IFsldV0sIHN0YXRlIFsldV0sIGNvb2tpZSBbMHgleF0KAAAAAAAA
-AAAAAAAAZGhjcF9wcm9jZXNzX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBkaGN0eHQt
-PnN0YXRlIFslMHhdLCBkaGN0eHQtPnJ0cnlfY250IFsldV0KAAAAAAAAAAAAZGhjcF90aW1lcl9j
-YjogREhDUERJU0NPVkVSIHNlbnQsIGJ1dCBubyByZXBseSBmcm9tIGFueSBwb3NzaWJsZSBzZXJ2
-ZXIgb24gdGhlIG5ldHdvcmsuIFJldHJ5aW5nIGFnYWluCgAAAAAAAAAAAGRoY3BfdGltZXJfY2I6
-IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIHNlbmRpbmcgREhDUERJU0NPVkVSIGZvciBkaGN0
-eHQgWzB4JXhdIG9uIHBpZCBbJWRdCgAAAGRoY3BfdGltZXJfY2I6IGwyZGV2X2ZjLT5mbG93Y19p
-ZCBbMHgleF0sIERIQ1BPRkZFUiByZWNlaXZlZCBmb3IgZGhjdHh0IFsleF0gcGlkIFslZF0KAAAA
-AAAAAAAAAGRoY3BfdGltZXJfY2I6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sICBESENQQUNL
-IHJlY2VpdmVkIGZvciBkaGN0eHQgWyV4XSwgcGlkIFslZF0KAAAAAAAAAAAAAGRoY3BfdGltZXJf
-Y2I6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIGRoY3R4dC0+aXBhZGRyIFsweCV4XQoAAAAA
-AAAAAAAAAAAAAAAAZGhjcF90aW1lcl9jYjogc3RhcnRpbmcgdGltZXIgZm9yIGxlYXNlIFsldV0g
-c2Vjb25kcwoAAAAAAAAAAAAAAGRoY3BfdGltZXJfY2I6IGxlYXNlIHRpbWUgb2YgWyV1XSBzZWNv
-bmRzIGV4cGlyZWQsIHNlbmRpbmcgcmVuZXcgcmVxdWVzdAoAAAAAAAAAZGhjcF90aW1lcl9jYjog
-bDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgbm8gcmVwbHkgZnJvbSBkaGNwIHNlcnZlciwgdGlt
-aW5nIG91dAoAAAAAAAAAAAAAAAAAAAAAYXV0aF9uZWdvX3NlY3VyaXR5OiBzZW5kX2ZsYWcgWzB4
-JXhdLCBhdXRoX3BvbGljeSBbMHgleF0KAAAAAAAAAGF1dGhfbmVnb19zZWN1cml0eTogS0VZX0NI
-QVBfUkVTUCAtIGhhc2hbMHgleCV4JXgleCV4JXgleCV4XQoAAABhdXRoX25lZ29fc2VjdXJpdHk6
-IEtFWV9DSEFQX1JFU1AgLSBoYXNoWzB4JXgleCV4JXgleCV4JXgleF0KAAAAYXV0aF9uZWdvX3Nl
-Y3VyaXR5OiBLRVlfQ0hBUF9SRVNQIC0gZXJyb3IgZW5jb2RpbmcgdG8gaGV4CgAAAAAAAGF1dGhf
-bmVnb19zZWN1cml0eTogS0VZX0NIQVBfUkVTUCAtIGVsZW4gWzB4JXhdCgAAAAAAAAAAAAAAAAAA
-AABhdXRoX25lZ29fc2VjdXJpdHk6IEtFWV9DSEFQX0NIQUwgLSBlcnJvciBlbmNvZGluZyB0byBo
-ZXgKAAAAAAAAYXV0aF9uZWdvX3NlY3VyaXR5OiBLRVlfQ0hBUF9DSEFMIC0gZWxlbiBbMHgleF0K
-AAAAAAAAAAAAAAAAAAAAAGxvZ291dF90aW1lZG91dDogbG9nb3V0IHJlcXVlc3QgdGltZWRvdXQs
-IHBvc3NpYmxlIG5ldHdvcmsgaXNzdWVzLiBGb3JjZWZ1bGx5IGJyZWFraW5nIHBhdGggZm9yIHNl
-c3MgWzB4JXhdCgAAAABwaW5nX3RhcmdldDogcGluZyB0aW1lb3V0LCBraWNraW5nIHJlY292ZXJ5
-IGZvciBzZXNzIFsweCV4XQoAAAAAY3NvY2tfZmFpbGVkOiBjc2tfZmMtPmZsb3djX2lkIFsweCV4
-XSwgY3NrX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIHNlc3NfZmMtPmZsb3djX2lkIFsweCV4XSwg
-c2Vzc19mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCBldnQgWzB4JXhdCgAAAAAAAAAAAAAAcmMgWyVk
-XSwgY3NrX2ZjIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0KAAAAAAAAAAAAAAAAAAAA
-AHJlY292ZXJ5X3RpbWVvdXQ6IHNlc3MgaWQgWzB4JXhdIHN0YXRlIFsweCV4XSwgcmNvdW50IFsl
-ZF0sIGZsYWdzIFsweCV4XQoAAAAAAAAAcmVjb3ZlcnlfdGltZW91dDogc2VzcyBpZCBbMHgleF0g
-aW4gbG9nb3V0LCBhYm9ydCB0aGUgY29ubmVjdGlvbgoAAAAAAAAAAAAAAAAAAAByZWNvdmVyeV90
-aW1lb3V0OiBzZXNzX2ZjLT5mbG93Y19mb2lzY3NpX3Nlc3NfZmxhZ3MgWzB4JXhdLCBjb25uZWN0
-aW9uIHJlcXVlc3QgcGVuZGluZywgYmFpbGluZyBvdXQKAAAAAAAAAAAAAAAAZm9pc2NzaTogUmVj
-b3ZlcnkgdGltZWQgb3V0IGFmdGVyIFsldV0gcmV0cnksIGJhaWxpbmcgb3V0CgAAAAAAAFRDUCBj
-b25uIGVzdGFibGlzaG1lbnQgZmFpbGVkICVkCgAAAAAAAAAAAAAAAAAAAGRpc2NvdmVyeV9kYXRh
-OiBzZXNzIHsgaWQgWzB4JXhdLCBmbGFncyBbMHgleF0sIGJ1ZmZlcmVkIFsldV0uIH0KAAAAAAAA
-AAAAAAAAAAAAZGlzY292ZXJ5X2RhdGE6IHNlc3MgeyBpZCBbMHgleF0gfSwgdWxwdHhjaCBbJXVd
-IG5vIGNyZWRpdHMgYXZhaWxhYmxlLCByZXNjaGVkdWxpbmcgcmVxdWVzdC4KAAAASW52YWxpZCBv
-cGNvZGUgMHgleCBpbiBjdHJsIHBhdGgKAAAAAAAAAAAAAAAAAAAARERQIGVycm9yIFsweCV4XSwg
-YWJvcnRpbmcgY29ubm4gWzB4JXhdCgAAAAAAAAAAcnhfZGF0YV9kZHA6IFJlc3BvbmNlIHJlY2ll
-dmVkIGZvciB0YXNrIFsweCV4XSB3aGlsZSBpbnZhbGlkIHRhc2sgb3IgY29ubmVjdGlvbiBzdGF0
-ZS4gdGFzayBzdGF0ZSBbMHgleF0sIGNvbm4gc3RhdGUgWzB4JXhdLCBjb25uIGZsYWdzIFsweCV4
-XQoAaXNjc2lfaGRyX3J4OiBSZXNwb25jZSByZWNpZXZlZCBmb3IgdGFzayBbMHgleF0gd2hpbGUg
-aW52YWxpZCB0YXNrIG9yIGNvbm5lY3Rpb24gc3RhdGUuIHRhc2sgc3RhdGUgWzB4JXhdLCBjb25u
-IHN0YXRlIFsweCV4XSwgY29ubiBmbGFncyBbMHgleF0KAAAAAAAAAAAAAAAAAAAAAGlzY3NpX2hk
-cl9yeDogSW52YWxpZCB0YXNrIHN0YXRlIDB4JXggZm9yIHRhc2sgMHgleCwgaXR0IFsweCV4XSwg
-b3BjIFsweCV4XQoAAAAAcHJvY2Vzc190bWZfcmVzcG9uc2U6IGJ1ZmZlcmVkIFsweCV4XSwgaXN0
-YXNrX2ZjLT5mbG93Y19idWYtPnNjaGVkX25vZGUubmV4dCBbMHgleF0sIGlzdGFza19mYyBbMHgl
-eF0sIGlzdGFza19mYy0+Zmxvd2NfaWQgWzB4JXhdCgAAAAAAAAAAAAAAAAAAcHJvY2Vzc190bWZf
-cmVzcG9uc2U6IHdyIG9wIFsweCV4XSwgdG1mIG9wIFsweCV4XQoAAAAAAAAAAAAAAAAAAHJldHVy
-bl9wZW5kaW5nX3Rhc2s6IGNvb2tpZSBbMHglMDh4XSwgWzB4JTA4eF0KAHJldHVybl9wZW5kaW5n
-X3Rhc2s6IGRlbGF5IHByb2Nlc3NpbmcsIGNvbm4gZmxhZ3MgWzB4JXhdCgAAAAAAAAByZXR1cm5f
-cGVuZGluZ190YXNrOiBEb25lIHNlbmRpbmcgdGFzayBlcnJvciB0byBob3N0LCB1bHB0eGxlbjE2
-IFsldV0KAAAAAAAAAAAAAHJldHVybl9wZW5kaW5nX3Rhc2s6IGRlcXVldWUgdGFzayBbMHgleF0s
-IHN0YXRlIFsweCV4XSBmcm9tIHR4X2xpc3QKAAAAAAAAAAAAAAAAcmV0dXJuX3BlbmRpbmdfdGFz
-azogYWxsIHRhc2tzIHJldHVybmVkLCByZWNvdmVyeSBzdGF0ZSB0cmFucyB0byBbMHgleF0KAAAA
-AAAAAABjbGVhcl9kZHBfbWFwOiBpc3Rhc2tfZmMgWzB4JXhdLCBpc3Rhc2tfZmMtPmZsb3djX2lk
-IFsweCV4XSBidWZmZXJlZCAldQoAAAAAAAAAAGNsZWFyX2RkcF9tYXA6IGlzdGFza19mYy0+Zmxv
-d2NfZm9pc2NzaV90YXNrX25wcG9kICV1LCBucHBvZCAldSwgcHBkYWRkciBbMHgleF0KAAAAAAAA
-AAAAAAAAAAAAAGNsZWFyX2RkcF9tYXA6IGFsbCByZXR1cm5lZCB0YXNrcyBkZHAgY2xlYXJlZCwg
-cmVjb3Zlcnkgc3RhdGUgdHJhbnMgdG8gWzB4JXhdCgAAd3JoX2ZvaXNjc2lfbm9kZTogbm9kZV93
-ci0+Zmxvd2lkX2xlbjE2IDIgWyV4XQoAd3JoX2ZvaXNjc2lfY2hhcDogaWRfbGVuIFsleF0sIHNl
-Y19sZW4gWyV4XQoAAAAAd3JoX2ZvaXNjc2lfY2hhcDogdGd0X2lkX2xlbiBbJXhdLCB0Z3Rfc2Vj
-X2xlbiBbJXhdCgAAAAAAAAAAAAAAAHNlc3Npb25fYmxvY2s6IHNlc3NfZmMtPmZsb3djX2lkIFsw
-eCV4XSwgc2Vzc19mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCBjb25uX2ZjLT5mbG93Y19pZCBbMHgl
-eF0sIGNvbm5fZmMtPmZsb3djX3N0YXRlIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0s
-IGNza19mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdCgAAAAAAAAAAAAAAAAAAAHNlc3Npb25fdW5ibG9j
-azogc2Vzc19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBzZXNzX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0s
-IGNvbm5fZmMtPmZsb3djX2lkIFsweCV4XSwgY29ubl9mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCBj
-c2tfZmMtPmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0KAAAAAAAA
-AAAAAAAAAHN0YXJ0X2xvZ291dDogU2Vzcy1pZCBbMHgleF0gYWxyZWFkeSBsb2dnaW4gb3V0LgoA
-AAAAAAAAAAAAAAAAAABwZWVyX2NvbjogY3NrX2ZjID0+IGZsb3dpZCBbMHgleF0sIGZsb3djX2J1
-ZiBbMHgleF0KAAAAAAAAAAAAAAAAYWxsb2Nfc2VzczogbG9naW5fcmV0cnkgWyVkXSwgcmVjb3Zf
-dGltZW91dCBbJWRdCgAAAAAAAAAAAAAAAAAAAGZvaXNjc2lfY3RybDogc3Vib3AgWzB4JXhdLCBz
-ZXNzX3R5cGVfdG9fZXJsIFsweCV4XSwgc2Vzc190eXBlIFsweCV4XQoAAAAAAAAAAAAAZm9pc2Nz
-aV9jdHJsOiByZWNlaXZlZCBibG9ja2VkIGZyb20gZHJpdmVyLCB0cmlnZ2VyaW5nIHJldHVybiB0
-YXNrcyBub3cuCgAAAAAAAAB3YXRjaGRvZyBjbWQgaGFuZGxlciAodGltZSAldSBhY3Rpb24gJXUp
-CgAAAAAAAAB4Z21hY1sldV0gc2V0dGluZy91bnNldHRpbmcgaHNzIHJlc3luYyBiaXQKAAAAAABX
-QVRDSERPRzogZGV2aWNlIHNodXRkb3duCgAAAAAAAFdBVENIRE9HOiBwb3J0WyV1XSBwYXVzZSB3
-YXRjaGRvZyB0aW1lb3V0CgAAAAAAAFdBVENIRE9HOiBieXBhc3MgdGltZW91dAoAAAAAAAAAV0FU
-Q0hET0c6IEZMUiAtIG5vdCBpbXBsZW1lbnRlZCB5ZXQKAAAAAAAAAAAAAAAAV0FUQ0hET0c6IHRl
-bXBlcmF0dXJlIG9mICVkQyBleGNlZWRzIHRocmVzaG9sZCBvZiAlZEMKAAAAAAAAAAAAAGZpbHRl
-cjogcG9yZ3JhbW1pbmcgdGlkICV1IChsZSB0Y2FtIGluZGV4ICV1KS4uLgoAAAAAAAAAAAAAAAAA
-AABmaWx0ZXI6IHJlcXVlc3RpbmcgY29tcGxldGlvbi4uLgoAAAAAAAAAAAAAAAAAAABsMmRldl9z
-ZW5kX3BvcnRfZXZlbnQ6IHdyIFsweCV4XSBwZW5kaW5nIG9uIHBvcnQgWyVkXSwgY3VycmVudCB0
-cnkgWyVkXQoAAAAAAAAAAEZDT0UgRnJlZTogc3RpbGwgeWllbGRlZCB3aGVuIGZyZWVpbmcuLi5m
-bG93Y19pZCAleCBmbG93Y19mbGFncyAleCAKAAAAAAAAAAAAAAAARkNPRSBCUCBXUiBFUlI6IFdS
-IHdpdGggY29va2llICV4JXggZXJyb3JlZCBiYWNrIAoAAAAAAAAAAAAAAAAAAHBvcnQgJWQgc2V0
-IHBmY19lbiA9IDB4JXgKAAAAAAAAcG9ydCAlZCBzZXQgcGZjX2VuID0gMHgleAoAAAAAAABldHNf
-c2V0X2NmZ19pZWVlWyV1XSB1bmtub3duIFRTQSBhbGcgZm9yIHByaW8gJXU6ICV1CgAAAAAAAAAA
-AAAARkNvRSBERFAgZmFpbGVkIDogb3hfaWQgMHgleCByeF9pZCAweCV4CgAAAAAAAAAARkNvRSBE
-RFAgZmFpbGVkIDogRGRwUmVwb3J0IDB4JXggRGRwVmFsaWQgMHgleAoARkMgeGNoZyBhbGxvYyBm
-YWlsZWQ6IGF2YWlsICVkCgBmY29lIG5vdGlmeSA6IFVwZGF0ZSBuZXcgRENCWCB2YWx1ZXMgVkkg
-c3RhdGUgMHgleCBwcmkgMHgleCBzY2hlZGNsIDB4JXggZGNieF9kb25lIDB4JXgKAAAAAAAAAABm
-Y29lIG5vdGlmeSA6IEZDRiBmbG93aWQgMHgleCwgdWxwY2ggMHgleCAKAAAAAABQUkxJIFJzcCB0
-aW1lZG91dCA6IGZsb3djX2lkIDB4JXggb3hfaWQgMHgleCByeF9pZCAweCV4IAoAAAAAAAAAY2Fu
-bm90IGFsbG9jYXRlIG9mZmxvYWRlZCBmaWx0ZXIgY29ubmVjdGlvbgoAAAAAY2Fubm90IGFsbG9j
-YXRlIG9mZmxvYWRlZCBmaWx0ZXIgSVB2NiBjb25uZWN0aW9uCgAAAAAAAAAAAAAAAAAAAGRpc3Bh
-dGNoX2RlZmVycmVkX2NsYXNzX2NsYXNzX3NoYXBpbmdbJXU6JXVdOiBsaXN0X2VtcHR5CgAAAAAA
-AABsb29wYmFjayBidWZmZXIgZ3JvdXBbJXVdIGlzIGRpc2FibGVkCgAAAAAAAAAAAABpbnZhbGlk
-IGJ1ZmZlciBncm91cFsldV0gY29uZmlndXJhdGlvbjogbXR1ICV1IGx3bSAldSBod20gJXUgZHdt
-ICV1CgAAAAAAAAAAAAAAAGZjICV1IHZmICV1IGdvdCBpdmY9MHgleCxyYW5nZTogJSN4LSUjeCAo
-JXUvJXUgdXNlZCkKAAAAAAAAAAAAAABWSSAldSBjYW5ub3QgZ2V0IFJTUyBzbGljZTogTm8gbW9y
-ZSBzbGljZXMgYXZhaWxhYmxlICh1c2VkICV1LyV1KQoAAAAAAAAAAAAAAAAAAHBmbiAldSB2Zm4g
-JXUgd2l0aCBwb3J0IG1hc2sgMHgleCBjYW5ub3QgYWNjZXNzIHBvcnQgJXUsIHJldCAlZAoAAAAA
-AAAAAAAAAAAAAAAAcGZuICV1IHZmbiAldSBjb3VsZCBub3QgYWxsb2NhdGUgdmlpZCwgcmV0ICVk
-CgAAcGZuICV1IHZmbiAldSBjb3VsZCBtYXAgdmlpZCAgMHgleCB0byBmbG93YywgcmV0ICVkCgAA
-AAAAAAAAAAAAAHBmbiAldSB2Zm4gJXUgY291bGQgbm90IGFsbG9jYXRlIHV3aXJlIGZ1bmMgJWQg
-bWFjIGFkZHIsIHJldCAlZAoAAAAAAAAAAAAAAAAAAAAAbWlpX2ZvcmNlX3NwZWVkWyV1XTogcmNh
-cHMgMHgleAoAAAAAAAAAAAAAAAAAAAAAbWlpX3Bkb3duWyV1XTogcG93ZXJkb3duIGVuICV1CgBw
-b3J0WyV1OjB4JTAyeDoweCUwMnhdOiB1bmtub3duIGFjdGlvbiAweCV4CgAAAABwb3J0WyV1OjB4
-JTAyeDoweCUwMnhdOiB1bmtub3duIHJlYWQgYWN0aW9uIDB4JXgKAAAAAAAAAAAAAAAAAAAAY3Bs
-X2Vycl9ub3RpZnk6IHRpZCAldSBjcGwgMHglMDh4JTA4eAoAAAAAAAAAAAAAY3BsX2Vycl9ub3Rp
-Znk6IHRpZCAldSBjcGwgMHglMDh4JTA4eCAweCUwOHglMDh4CgAAAAAAAAAAAAAAAAAAAGNwbF9l
-cnJfbm90aWZ5OiB0aWQgJXUgbGVuICV1CgAARkNPRSBGcmVlOiBzdGlsbCB5aWVsZGVkIHdoZW4g
-ZnJlZWluZy4uLmZsb3djX2lkICV4IGZsb3djX2ZsYWdzICV4IAoAAAAAAAAAAAAAAABzY3NpX2Fi
-b3J0OiBFbnRlcmluZyBBYm9ydF90YXNrLCBidWZmZXJlZCBbJXVdCgBzY3NpX2Fib3J0OiByYyBb
-MHgleF0gcmVmIHRhc2sgbm90IG91dHN0YW5kaW5nCgBzY3NpX2Fib3J0OiBpZGF0YS0+b3AgWzB4
-JXhdLCBmbGFncyBbMHgleF0sIGZ1bmMgWzB4JXhdLCBsdW5faWR4IFsweCV4XQoAAAAAAAAAAHNj
-c2lfYWJvcnQ6IHdyLT5pcWlkIFsweCV4XSwgaXN0YXNrX2ZjLT5mbG93Y19zZ2VfaXFpZCBbMHgl
-eF0sIGlzdGFza19mYyB0YXNrIGZsYWdzIFsweCV4XQoAAAAAAHNjc2lfYWJvcnQ6IGNvbm4gWzB4
-JXhdLCBjbWRzbiBbMHgleF0sIHNlbnRfY21kc24gWzB4JXhdLCBtYXhfY21kc24gWzB4JXhdLCBp
-dHQgWzB4JXhdCgAAAAAAAAAAAGFib3J0L2Nsb3NlIFdSIHdpdGggY29va2llIDB4JWx4IHdhcyBp
-c3N1ZWQgb24gc3NuIDB4JXggaW4gd3Jvbmcgc3RhdGUgMHgleAoAAAAAYWJvcnQgV1Igb24gc3Nu
-IDB4JXggZGlkIG5vdCBmaW5kIFdSIHdpdGggY29va2llIDB4JXgleAoAAAAAAAAAAGNsb3NlIFdS
-IHdpdGggY29va2llIDB4JWx4IG9uIHNzbiAweCV4O2RpZCBub3QgZmluZCBXUiB3aXRoIGNvb2tp
-ZSAweCVseAoAAAAAAAAAYWJvcnQgV1Igb24gc3NuIDB4JXggd2FzIGlzc3VlZCBvbiB4Y2hnIDB4
-JXggd2l0aCByeF9pZCAweCV4IGluIHdyb25nIHN0YXRlIDB4JXgKAAAAAAAAAAAAAAAAAAAAc2Nz
-aV9sdXI6IEVudGVyaW5nIExVUiBoYW5kbGVyLCBidWZmZXJlZCBbJXVdCgAAc2NzaV9sdXI6IGlk
-YXRhLT5vcCBbMHgleF0sIGZsYWdzIFsweCV4XSwgZnVuYyBbMHgleF0sIGx1bl9pZHggWzB4JXhd
-CgAAAAAAAAAAAABzY3NpX2x1cjogd3ItPmlxaWQgWzB4JXhdLCBpc3Rhc2tfZmMtPmZsb3djX3Nn
-ZV9pcWlkIFsweCV4XSwgaXN0YXNrX2ZjIHRhc2sgZmxhZ3MgWzB4JXhdCgAAAAAAAABzY3NpX2x1
-cjogY29ubiBbMHgleF0sIGNtZHNuIFsweCV4XSwgc2VudF9jbWRzbiBbMHgleF0sIG1heF9jbWRz
-biBbMHgleF0sIGl0dCBbMHgleF0KAAAAAAAAAAAAAABkY2J4X2NlZV9mZWFfc21bJXVdIEZlYXR1
-cmVbJXVdIEZFQVRVUkVfTElOS1VQCgBkY2J4X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVdIFNF
-VF9MT0NBTF9QQVJBTUVURVJTCgAAAAAAAAAAAAAAZGNieF9jZWVfZmVhX3NtWyV1XSBGZWF0dXJl
-WyV1XSBGRUFUVVJFX05PX0FEVkVSVElTRQoAAAAAAAAAAAAAAGRjYnhfY2VlX2ZlYV9zbVsldV0g
-RmVhdHVyZVsldV0gRkVBVFVSRV9QRUVSX05PVF9BRFZFUlRJU0VfRENCWAoAAAAAAAAAAAAAAAAA
-AAAAZGNieF9jZWVfZmVhX3NtWyV1XSBGZWF0dXJlWyV1XSBGRUFUVVJFX1BFRVJfTk9UX0FEVkVS
-VElTRV9GRUFUVVJFCgAAAAAAAAAAAAAAAABkY2J4X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVd
-IEZFQVRVUkVfVVBEQVRFX09QRVJfVkVSU0lPTgoAAAAAZGNieF9jZWVfZmVhX3NtWyV1XSBGZWF0
-dXJlWyV1XSBGRUFUVVJFX1BFRVJfVVBEQVRFX09QRVJfVkVSU0lPTgoAAAAAAAAAAAAAAAAAAABk
-Y2J4X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVdIEZFQVRVUkVfR0VUX1BFRVJfQ0ZHCgAAAAAA
-AAAAAAAAZGNieF9jZWVfZmVhX3NtWyV1XSBGZWF0dXJlWyV1XSBGRUFUVVJFX0NGR19OT1RfQ09N
-UEFUSUJMRQoAAAAAAGRjYnhfY2VlX2ZlYV9zbVsldV0gRmVhdHVyZVsldV0gRkVBVFVSRV9VU0Vf
-TE9DQUxfQ0ZHCgAAAAAAAAAAAABkY2J4X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVdIEZFQVRV
-UkVfVVNFX1BFRVJfQ0ZHCgAAAAAAAAAAAAAAZGNieF9jZWVfZmVhX3NtWyV1XSBGZWF0dXJlWyV1
-XSBGRUFUVVJFX0ZFQVRVUkVfRElTQUJMRUQKAAAAAAAAAGRjYnhfY2VlX2ZlYV9zbVsldV0gRmVh
-dHVyZVsldV0gRkVBVFVSRV9FUlJPUl9DSEFOR0UKAAAAAAAAAAAAAABGZWF0dXJlICV1IHN5bmMn
-ZD0ldSAoZXJyb3IgJXUpCgAAAAAAAAAAAAAAAAAAAABjaG5ldF9sMnRfdXBkYXRlOiBsMmRldl9m
-YyBbMHgleF0sIGwyZGV2X2ZjLT5mbG93Y19pZCBbJXVdIGwyZGV2X2ZjLT5mbG93Y19mbGFncyBb
-MHgleF0sIGludGYgWzB4JXhdCgAAAAAAAAAAAAAAY2huZXRfbDJ0X3VwZGF0ZTogbDJkZXZfZmMt
-PmZsb3djX2lkIFsldV0gYWxyZWFkeSBzY2hlZHVsZWQKAAAAAGNobmV0X2wydF91cGRhdGU6IGlu
-IGRlbGF5ZWRfcHJvY2Vzc2luZywgbDJ0ZW50IFslMDh4XQoAAAAAAAAAAABjaG5ldF9hcnBfdXBk
-YXRlX2NhY2hlOiBhcnAgaXA0IGVudHJ5IGZvdW5kIAoAAABjaG5ldF9hcnBfdXBkYXRlX2NhY2hl
-OiBhcnAgaXA2IGVudHJ5IGZvdW5kIAoAAABjaG5ldF9hcnBfdXBkYXRlX2NhY2hlOiBib3RoIGlw
-NCBhbmQgaXA2IGFkZHIgY2Fubm90IGJlIG51bGwKAAAAY2huZXRfbDJ0X3VwZGF0ZTogbDJ0X3Vw
-ZGF0ZSByZXF1ZXN0IHNlbnQgbDJ0ZW50IFslMDh4XSwgbDJ0ZW50LT5pZHggWyVkXSwgbDJ0ZW50
-LT52bGFuIFslZF0KAAAAbmV0aWZfcHJvY2Vzc19kaGNwOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4
-JXhdLCBwcm9jZXNzaW5nLCBvcHRfbGVuICV1CgAAAAAAAAAAAABjaG5ldF9kaGNwX3JlY3Y6IHZs
-YW5pZCBbJXVdLCBsMmRldl9waWRfZmMtPmZsb3djX25ldF9sMmRldl92bGFuZGV2IFsweCV4XSwg
-bDJkZXZfZmMgWzB4JXhdCgAAAABjaG5ldF9kaGNwX3JlY3Y6IGwyZGV2X2ZjLT5mbG93Y19pZCBb
-MHgleF0sIGRoY3R4dC0+c3RhdGUgWyVkXSwgbWFsYWNpb3VzIGRoY3AgcmVjdiBmb3Igbm8gcmVx
-dWVzdAoAAAAAAAAAAAAAAAAAZGhjdHh0LT5zdGF0ZSA6ICVkCgAAAAAAAAAAAAAAAABsMmRldl9m
-Yy0+Zmxvd2NfaWQgWzB4JXhdLCBCYWQgREhDUCBjb29raWUgcmVjaWV2ZWQsIGFib3J0aW5nCgAA
-Q291bGQgbm8gYWxsb2NhdGUgcGNiISEgRnJlZWluZyBmY2YgISEhCgAAAAAAAAAAdm5fcGFyc2Ug
-dW5rbm93biBzdWJjb2RlICV1CgAAAAB2bl9wYXJzZSB1bmtub3duIGR0eXBlICV1CgAAAAAAAGln
-bm9yaW5nIGZpcCByZWN2IGZvciBwY2IgZmxvdzoleCBpbiBvZmZsaW5lIHN0YXRlCgAAAAAAAAAA
-AAAAAABmaXBfdm4ydm5fcmVjdl9lcnIgCgAAAAAAAAAAAAAAAENvdWxkIG5vdCBhbGxvY2F0ZSBm
-bG93YyEhISEKAAAAQ291bGQgbm90IGFsbG9jYXRlIFNDQiBmbG93YyEhISEKAAAAAAAAAAAAAAAA
-AAAAQ291bGQgbm90IGZpbmQgcmlnaHQgc2NiIGZvciBsb2dvCgAAAAAAAAAAAAAAAAAAaWdub3Jp
-bmcgZmlwIHJlY3YgZm9yIGZjZiBmbG93OiV4IGluIG9mZmxpbmUgc3RhdGUKAAAAAAAAAAAAAAAA
-AENvdWxkIG5vdCBmaW5kIHJpZ2h0IHNjYiBmb3IgZmxvZ2kKAAAAAAAAAAAAAAAAAHBvcnQgMHgl
-eCwgc3RhdGUgMHgleCwgcmV0cnkgbm90IHN1cHBvcnRlZAoAAAAAAEZsb2dpIHJlc3AgcmN2IHdp
-dGggdW5rbm93biB4Y2hnIG94X2lkJXggc2lkICUyeCUyeCUyeCBkaWQgJTJ4JTJ4JTJ4CgAAAAAA
-AAAAAAAATl9QT1JUIDB4JXgleCV4IHJlamVjdGVkIFBMT0dJIHdpdGggcmVhc29uIGNvZGUgJXgK
-AAAAAAAAAAAAAAAAAEFCVFMgd2hpbGUgYXdhaXRpbmcgUFJMSSBSc3A6IGZsb3djX2lkIDB4JXgg
-b3hfaWQgMHgleCByeF9pZCAweCV4IAoAAAAAAAAAAAAAAAAAQUJUUyBmYWtlIFJzcDogbG9jIDB4
-JXggb3hfaWQgMHgleCByeF9pZCAweCV4CgAARkMgZmNiIGFsbG9jIGZhaWxlZDogYXZhaWwgJWQK
-AABGQyBmY2IgYWxsb2MgeGlkOiVkIGZsb3dpZCAlZAoAAGxsZHBfcnhfcGt0X2hhbmRsZXJbJXVd
-IGRyb3AgcHJlLWluaXQgKGNvdW50ID0gJXUpCgAAAAAAAAAAAAAAAAAleCV4JXggUmVjaWV2ZWQg
-TE9HTyBmcm9tICV4JXgleCAKAAAAAAAAAAAAAAAAAABjYW5ub3QgYWxsb2NhdGUgUE9GQ09FIGZp
-bHRlciBjb25uZWN0aW9uIGZvciB4X2lkICV4IAoAAAAAAAAAAAAARmFpbGVkIHRvIHBvc3QgeGNo
-ZyBlcnI6IHNzbmkgMHgleCBjb29raWUgMHglbHggcnZhbCAleCAKAAAAAAAAAHRjcF9yZWxlYXNl
-X3RpZDogdGlkIFsweCV4XSwgZmxvd2MgZmxhZ3MgWzB4JXhdLCBidWZmZXJlZCBbMHgleF0KAAAA
-AAAAAAAAAAAAAAAAdGNwX3JlbGVhc2VfdGlkOiBzaXplb2YodGNiX2ZjLT5mbG93Y19mb2lzY3Np
-X2Nvbm4pIFsldV0sIGJ5dGVzCgAAAAAAAAAAAAAAAAAAAABhY3Rfb3Blbl9ycGw6IGF0aWQgWzB4
-JXhdLCB0aWQgWzB4JXhdLCB0Y2JfZmMtPnsgaWQgWzB4JXhdLCBzdGF0ZSBbMHgleF0sIHR5cGUg
-WzB4JXhdIH0sIGNwbF9vcCBbMHgleF0sIHN0YXR1cyBbMHgleF0KAAAAAAAAAAAAAGFjdF9vcGVu
-X3JwbDogY3NrX2ZjLT57IGlkIFsweCV4XSwgc3RhdGUgWzB4JXhdLCBjc29ja19mbGFncyBbMHgl
-eF0gfSAKAAAAAAAAAAAAYWN0X29wZW5fcnBsOiByZWN2ZCBuZWcgYWR2aWNlIFsweCV4XQoAAAAA
-AAAAAAAAc2VuZF9hYm9ydF9ycGw6IGNza19mYy0+Zmxvd2NfdHlwZSBbMHgleF0sIGNza19mYy0+
-Zmxvd2NfaWQgWzB4JXhdLCB0aWQgWzB4JXhdLCB1bHB0eGNoIFsldV0sIGJ1ZmZlcmVkIFsldV0K
-AAAAAHdyaF9vZmxkX3RjcF9jbG9zZV9jb25fcmVwbHk6IHRjYl9mYy0+Zmxvd2NfaWQgWzB4JXhd
-LCB0Y2JfZmMtPmZsb3djX3R5cGUgWzB4JXhdLCBsZW4xNiBbJXVdLCBsb2MgWyV1XQoAAAAAAAAA
-AAB3cmhfb2ZsZF90Y3BfY2xvc2VfY29uX3JlcGx5OiBycGwtPm9wX1RpZCBbMHgleF0sIHJwbD5z
-dGF0dXMgWzB4JXhdLCBycGwtPnNuZF9ueHQgWzB4JXhdLCBycGwtPnJjdl9ueHQgWzB4JXhdCgAA
-dGNwX2Fib3J0X3JwbF9yc3M6IHRpZCBbMHgleF0sIHN0YXR1cyBbMHgleF0KAAAAdGNwX2Fib3J0
-X3JlcV9yc3M6IHRpZCBbMHgleF0sIHN0YXR1cyBbMHgleF0KAAAAb2ZsZF9hYm9ydF9yZXFfbmVn
-YWR2WyV1XTogd3IgMHglMDh4IGNwbF9hYm9ydF9yZXEgREVMSVZFUkVECgAAAGhvc3Rfd3JbJXVd
-OiB3ciAweCUwOHggY3BsX2Fib3J0X3JlcSBzdGF0dXMgMHgleAoAAAAAAAAAAAAAAAAAAABwa3Rz
-Y2hlZF9jbF9ybFsldToldV06IG1vZGUgfCB1bml0IHwgcmF0ZSAweCUwNnggbWluICV1IG1heCAl
-dSBwa3RzaXplICV1CgAAAAAAAHBhcmFtX2NobmV0WzB4JXg6MHgleF06IGNobmV0IDB4JXggcmVh
-ZCAldSBwZiAldSByZXQgJWQKAAAAAAAAAABwYXJhbV9kbWFxWzB4JXg6MHgleF06IGRtYXEgMHgl
-eCByZWFkICV1IHBmICV1IHJldCAlZAoAAAAAAAAAAAAATUNbJXVdIGluaXRfc3RhdGVfbWFjaGlu
-ZSAweCUwMngKAAAAAAAAAAAAAAAAAAAATUMgaW5pdGlhbGl6YXRpb24gbm90IGNvbXBsZXRpbmcs
-IE1DIGN1cnJlbnQgaW5pdCBzdGF0ZSBpcyAweCUwMngKAAAAAAAAAAAAAAAAAABNQ1sldV0gX2h3
-X21jX2luaXRfbWMKAAAAAAAAAAAAAHBoeTogZmFpbGVkIHRvIGFsbG9jYXRlZCBtZW1vcnkgZm9y
-IHBoeSBmdyBmaWxlLCByZXQgJWQKAAAAAAAAAABod19sZV9maWx0ZXJfY3R1cGxlOiB0dXBsZSAl
-dSBub3Qgc3BlY2lmaWVkIGJ1dCByZXF1aXJlZCBmb3IgbWFzayAweCV4CgAAAAAAAAAAAGh3X3Rw
-X3RjcF9zZXR0aW5nc193OiB0aW1lcl9ycyAldXVzIHRpbWVzdGFtcF9yZXMgJXV1cyBkZWxheWVk
-YWNrX3JlcyAldXVzCgAAAAAAaHdfdHBfdGNwX3NldHRpbmdzX3c6IGRhY2tfdGltZXIgJXV1cyBt
-c2wgJXV1cyByeHRfbWluLG1heCAldSwldXVzIHBlcnNfbWluLG1heCAldSwldXVzCgAAAAAAAAAA
-aHdfdHBfdGNwX3NldHRpbmdzX3c6IGtlZXBfaWRsZSxpbnR2bCAldSwldXMgbWF4cnR0ICV1dXMg
-aW5pdHNydHQgJXV1cyBmaW53YWl0Ml90aW1lciAldXVzCgAAAAAAaHdfdHBfdGNwX3NldHRpbmdz
-X3c6IGNhcHBpbmcgZGFja190aW1lciBmcm9tICV1IHRvICV1AAAAAAAAAAAAAGh3X3RwX3RjcF9z
-ZXR0aW5nc193OiBjYXBwaW5nIG1zbCBmcm9tICV1IHRvICV1AGh3X3RwX3RjcF9zZXR0aW5nc193
-OiBjYXBwaW5nIHJ4dF9taW4gZnJvbSAldSB0byAldQAAAAAAAAAAAAAAAABod190cF90Y3Bfc2V0
-dGluZ3NfdzogY2FwcGluZyByeHRfbWF4IGZyb20gJXUgdG8gJXUAAAAAAAAAAAAAAAAAaHdfdHBf
-dGNwX3NldHRpbmdzX3c6IGNhcHBpbmcgcGVyc19taW4gZnJvbSAldSB0byAldQAAAAAAAAAAAAAA
-AGh3X3RwX3RjcF9zZXR0aW5nc193OiBjYXBwaW5nIHBlcnNfbWF4IGZyb20gJXUgdG8gJXUAAAAA
-AAAAAAAAAABod190cF90Y3Bfc2V0dGluZ3NfdzogY2FwcGluZyBrZWVwX2lkbGUgZnJvbSAldSB0
-byAldQAAAAAAAAAAAAAAaHdfdHBfdGNwX3NldHRpbmdzX3c6IGNhcHBpbmcga2VlcF9pbnR2bCBm
-cm9tICV1IHRvICV1AAAAAAAAAAAAAGh3X3RwX3RjcF9zZXR0aW5nc193OiBjYXBwaW5nIGluaXRf
-c3J0dF9tYXhydHQgZnJvbSAldSB0byAldQAAAABod190cF90Y3Bfc2V0dGluZ3NfdzogY2FwcGlu
-ZyBpbml0X3NydHRfaW5pdHNydHQgZnJvbSAldSB0byAldQAAaHdfdHBfdGNwX3NldHRpbmdzX3c6
-IGNhcHBpbmcgZmlud2FpdDJfdGltZXIgZnJvbSAldSB0byAldQAAAAAAAGxlIGNvbmZpZ3VyYXRp
-b246IG5lbnRyaWVzICV1IHJvdXRlICV1IGNsaXAgJXUgZmlsdGVyICV1IGFjdGl2ZSAldSBzZXJ2
-ZXIgJXUgaGFzaCAldQoAAAAAAAAAAAAAAGxlIGNvbmZpZ3VyYXRpb246IG5lbnRyaWVzICV1IHJv
-dXRlICV1IGNsaXAgJXUgZmlsdGVyICV1IHNlcnZlciAldSBhY3RpdmUgJXUgaGFzaCAldSBuc2Vy
-dmVyc3JhbSAldQoAAAAAAAAAAAAAAABod19zZ2VfcXVldWVfYmFzZV9tYXBbJXVdOiBleGNlZWRl
-ZCBudW1iZXIgb2YgZWdyZXNzIHF1ZXVlcywgJXUKAAAAAAAAAAAAAAAAAAAAAGh3X3NnZV9xdWV1
-ZV9iYXNlX21hcFsldV06IGV4Y2VlZGVkIG51bWJlciBvZiBpbmdyZXNzIHF1ZXVlcyB3aXRoIGZy
-ZWVsaXN0IGFuZCBpbnRlcnJ1cHQsICV1CgAAAGh3X3NnZV9xdWV1ZV9iYXNlX21hcFsldV06IGV4
-Y2VlZGVkIG51bWJlciBvZiBpbmdyZXNzIHF1ZXVlcywgJXUKAAAAAAAAAAAAAAAAAAAAY2ZfcGFy
-c2U6IGZpbGUgbWVtdHlwZSAweCV4IG1lbWFkZHIgMHgleCBtYXBwZWQgQCAlcDoKAAAAAAAAAAAA
-AGNvbmZpZ3VyZWQgd2l0aCBjYXBzIG5ibXxsaW5rIDB4JTA4eCBzd2l0Y2h8bmljIDB4JTA4eCB0
-b2V8cmRtYSAweCUwOHggaXNjc2l8ZmNvZSAweCUwOHgKAAAAAAAAAG5ldCBWSSBhbGxvY2F0aW9u
-IGZhaWxlZCBmb3IgZmNfaWQgJXUgd2l0aCBlcnJvciAlZAoAAAAAAAAAAAAAAABuZXQgVkkgbWFj
-IGFkZHJlc3MgcHJvZ3JhbW1pbmcgZmFpbGVkIGZvciBmY19pZCAldSB3aXRoIGVycm9yICVkCgAA
-AAAAAAAAAAAAAAAAAG5ldCBWSSByeG1vZGUgcHJvZ3JhbW1pbmcgZmFpbGVkIGZvciBmY19pZCAl
-dSB3aXRoIGVycm9yICVkCgAAAABuZXQgVkkgcnNzIGluZGlyZWN0aW9uIHRhYmxlIHByb2dyYW1t
-aW5nIGZvciBmY19pZCAldSBmYWlsZWQgd2l0aCBlcnJvciAlZAoAAAAAAG5ldCBWSSByc3MgY29u
-ZmlnIGNvbW1hbmQgZmFpbGVkIGZvciBmY19pZCAldSB3aXRoIGVycm9yICVkCgAAAABuZXQgVkkg
-Y29tbWFuZCBmYWlsZWQgZm9yIGZjX2lkICV1IHdpdGggZXJyb3IgJWQKAAAAAAAAAAAAAAAAAAAA
-cHJvZ3JhbW1lZCBIVyB0YWdtIFsweCUwOHhdLCBIVyBwZ3N6IGZhY3RvciBbMHglMDh4XSwgRk9p
-U0NTSSB0YWdtIFsweCUwOHhdLCBydGFnbSBbMHglMDh4XSwgbWF4c3pfYml0cyBbJXVdLCBzel9i
-aXRzIFsldV0uCgAAAABiYXNlIFsgMHglMDh4XSwgbGxpbWl0IFsweCUwOHhdLCB1bGltaXQgWzB4
-JTA4eF0sIHNpemUgWyV1XSwgbWF4X3R4c3ogWyV1XSwgbWF4X3J4c3ogWyV1XSwgaW9zaXplIFsl
-dV0KAAAAAAAAAAAAbnBwb2RzIFsldV0sIGlkeF9tYXNrIFsweCUwOHhdLCBpZHhfZmlyc3QgWyV1
-XSwgaWR4X2xhc3QgWyV1XSwgc2NzaV9wbGRfc2l6ZSBbJXVdLCBBTElHTihzY3NpX3BsZF9zaXpl
-LCAxNikgWyV1XSwgcHBkX3pvbmVzIFsldV0uCgAAAAAAAAAAAAAAAAAAZm9pc2NzaV9pbml0OiBm
-b2lzY3NpX2luaXRfZG9uZSBbJXVdLCBkZXYucmVzLmZvaXNjc2lfbnRhc2tzIFsldV0sIGRldi5y
-ZXMuZm9pc2NzaV9uc2VzcyBbJXVdLCBkZXYucmVzLm5jc29jayBbJXVdLCBkZXYucmVzLmZvaXNj
-c2lfbmluaXQgWyV1XSwgcmMgWyVkXQoAAAAAAAAAAGNoX2NsX3JhdGVbJXUvJXVdOiBjYXBwZWQg
-Y2xhc3MgcmF0ZSBmcm9tIHJlcXVlc3RlZCAldSB0byBjb25maWd1cmVkIChlZmZlY3RpdmUpIGNo
-YW5uZWwgcmF0ZSAldQoAAAAAAAAAAAAAAAAAAABjaF9jbF9yYXRlWyV1LyV1XTogaW5jcmVhc2Vk
-IGRlZmljaXRfaW5jciBmcm9tIHJlcXVlc3RlZCAldSB0byByZXF1aXJlZCBtaW4gb2YgJXU7IHJh
-dGUgJXUgKGVmZiAldSkgZGVmaWNpdF9tYXggJXUKAAAAAAAAAAAAAAAAAHBrdHNjaGVkIGNoYW5u
-ZWwgJXUgc2V0cyBzcGVlZCAoZnJvbSAldSkgdG8gJXUga2JwcwoAAAAAAAAAAAAAAABuZXRfbDJk
-ZXZfbm90aWZ5OiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBwb3J0IFslZF0sIGV2ZW50IFsw
-eCV4XSwgdWxwdHhjaCBbJXVdLCBjbGFzcyBbMHgleF0sIHZwcmlvIFsweCV4XSwgdmlkIFsweCV4
-XSwgdmlfcmVhZHkgWyV1XQoAAAAAAABuZXRfbDJkZXZfbm90aWZ5OiBwZ2lkIFsweCV4XSwgcHJp
-byBbMHgleF0sIGNoIFsweCV4XQoAAAAAAAAAAAAAZmNvZSBub3RpZnkgOiBGQ29FIExJTktVUDog
-cG9ydCAweCV4LCBldmVudCAweCV4CgAAAAAAAAAAAAAAAAAAAGZjb2Ugbm90aWZ5IDogRkNvRSBM
-SU5LRE9XTjogcG9ydCAweCV4LCBldmVudCAweCV4CgAAAAAAAAAAAAAAAABmY29lIG5vdGlmeSA6
-IERDQlggOiBwb3J0IDB4JXgsIHByaW9yaXR5IDB4JXggdWxwdHhjaCAweCV4IGNsYXNzIDB4JXgK
-AAAAAAAAAAAAAGRjYnhfdGltZW91dFsldV0KAAAAAAAAAAAAAAAAAAAAcG9ydF9jbWRfaGFuZGxl
-cjogdW5rbm93biB1LmRjYi50eXBlIDB4JXgKAAAAAAAAcG9ydFsldV0gbGluayBkb3duICgldSkg
-KGxzdGF0dXMgJSN4KQoAAAAAAAAAAAAAaTJjIGVycm9yIGNhdXNlZCBieSBtb2R1bGUgdW5wbHVn
-CgAAAAAAAAAAAAAAAAAAc2VuZHRvIHBlbmRpbmc6IHdyX3BlbmQgJXAgZm9yIHBvcnQgJXUsIHdh
-bnQgdG8gc2VuZCB0byBwb3J0ICV1CgAAAAAAAAAAAAAAAAAAAABwb3J0WyV1XSB1cGRhdGUgKGZs
-b3djaWQgJXUgcmMgJXUpCgAAAAAAAAAAAAAAAABwb3J0X3NldF9sb29wYmFjayBwb3J0ICUjeCBj
-dXJyZW50ICUjeCBtb2RlICUjeAoAAAAAAAAAAAAAAAAAAAAAcG9ydFsldV0gc3BlZWQgdXBkYXRl
-OiAlI3gKAAAAAABwb3J0WyV1XSBiZWdpbm5pbmcgZGVib3VuY2UKAAAAAHBvcnRfbGlua19zdGF0
-ZV9oYW5kbGVyWyV1XSBwb3dlcmluZyBkb3duCgAAAAAAAHBvcnRfbGlua19zdGF0ZV9oYW5kbGVy
-WyV1XSBwb3dlcmluZyB1cAoAAAAAAAAAAHBvcnRfbGlua19zdGF0ZV9oYW5kbGVyWyV1XSB1bmtu
-b3duIHN0YXRlIChzdGF0ZSA9ICUjeCkKAAAAAAAAAABwb3J0X2xpbmtfc3RhdGVfaGFuZGxlcjog
-U29tZXRoaW5nIHdlbnQgdGVycmlibHkgd3JvbmcuIHJldCA9ICVkCgAAAAAAAAAAAAAAAAAAAGxl
-IGluaXRpYWxpemF0aW9uOiBuZW50cmllcyAldSByb3V0ZSAldSBjbGlwICV1IGZpbHRlciAldSBh
-Y3RpdmUgJXUgc2VydmVyICV1IGhhc2ggJXUKAAAAAAAAAAAAAGxlIGluaXRpYWxpemF0aW9uOiBu
-ZW50cmllcyAldSByb3V0ZSAldSBjbGlwICV1IGZpbHRlciAldSBzZXJ2ZXIgJXUgYWN0aXZlICV1
-IGhhc2ggJXUgbnNlcnZlcnNyYW0gJXUKAAAAAAAAAAAAAABod190cF9pbml0OiB0Y2IgcmVnaW9u
-IChzdGFydCAweCUwOHMgc2l6ZSAldSkgbXVzdCBiZSBpbiBmaXJzdCAyNTZNQiBvZiBNQSBtZW1v
-cnkKAAAAAAAAAAAAAAAAAABod190cF9pbml0OiBwZ21uZ3QgcmVnaW9uIChzdGFydCAweCUwOHMg
-c2l6ZSAldSkgbXVzdCBiZSBpbiBmaXJzdCAyNTZNQiBvZiBNQSBtZW1vcnkKAAAAAAAAAAAAAABo
-d190cF9pbml0OiBUUCBwZ21uZ3QgaW5pdGlhbGl6YXRpb24gZGlkIG5vdCBjb21wbGV0ZQoAAAAA
-AAAAAAAAYnVmbV9pbml0OiBuICV1IGJ1ZmxsNjRpbnRfc2l6ZSAweCV4CgAAAAAAAAAAAAAAYnVm
-bV9pbml0OiBub3QgZW5vdWdoIG1lbW9yeSB0byBhbGxvY2F0ZSBpbnRlcm5hbCBidWZsbDY0IGJ1
-ZmZlcnMKAAAAAAAAAAAAAAAAAABidWZtX2luaXQ6IG5vdCBlbm91Z2ggbWVtb3J5IHRvIGFsbG9j
-YXRlIGJ1ZmxsNjQgYnVmZmVycwoAAAAAAAAAbWVtX2luaXRfYnVmOiBub3QgZW5vdWdoIG1lbW9y
-eSB0byBhbGxvY2F0ZSBmbG93IGJ1ZmZlcnMKAAAAAAAAAG1lbV9pbml0X2J1Zjogbm90IGVub3Vn
-aCBtZW1vcnkgdG8gYWxsb2NhdGUgdGNiX2NhY2hlIChvZmZlcmVkICV1IHRyeWluZyB0byB1c2Ug
-JXUgYXZhaWxhYmxlICV1KQoAAAAAAAAAAAAAAAAAAABtcGFydGl0aW9uX290aGVyczogc3RhcnQg
-MHglMDh4IHNpemUgJXUgKHVudXNlZCAldSkKAAAAAAAAAAAAAAAAbXBhcnRpdGlvbl9vdGhlcnM6
-IHN0YXJ0IDB4JTA4eCBzaXplICV1ICh1bnVzZWQgJXUpCgAAAAAAAAAAAAAAAG1lbV9pbml0OiBF
-REMgb3ZlcmNvbW1pdHRlZCBieSAlZCBieXRlcwoAAAAAAAAAAG1lbV9pbml0OiBub3QgZW5vdWdo
-IG1lbW9yeSB0byBhbGxvY2F0ZSBmbG93IHRhYmxlCgAAAAAAAAAAAAAAAABjeGNuaWNfZGV2aWNl
-X2luaXQ6IGN4Y25pYyBbMHglMHhdLCBjeGNuaWMtPmZpbHRlciBbJTB4XQoAAAAAAAAAcG9mY29l
-IGluaXQgZG9uZQoAAAAAAAAAAAAAAAAAAABQb3J0WyV1XTogVW5rbm93biBTR01JSSBzdWItdHlw
-ZSAlI3gKAAAAAAAAAAAAAABQb3J0WyV1XTogVW5rbm93biBCVF9YRkkgc3ViLXR5cGUgJSN4CgAA
-AAAAAAAAAABQb3J0WyV1XTogVW5rbm93biBCVF9YQVVJIHN1Yi10eXBlICUjeAoAAAAAAAAAAABw
-b3J0X2luaXRbJXVdOiBwb3J0IHR5cGUgMHgleCBpcyBub3Qgc3VwcG9ydGVkCgBtcGFydGl0aW9u
-X2luaXQ6IG1vdmVkIHBtcnhfc3RhcnQgZnJvbSAweCUwOHggdG8gMHglMDh4IHRvIG1ha2Ugcm9v
-bSBmb3IgTEUgSEFTSCBhbmQvb3IgVFAgVENCcwoAAAAAAAAAAAAAAAAAAAAAbXBhcnRpdGlvbl9p
-bml0OiBtb3ZlZCBwbXJ4X3N0YXJ0IGZyb20gMHglMDh4IHRvIDB4JTA4eCAoRURSQU0pCgAAAAAA
-AAAAAAAAAAAAAABFUSBwZm4gJXUgdmZuICV1OiBkZXN0cm95aW5nIGVxaWQgJXUgd2l0aCBwZW5k
-aW5nIFdSKHMpIChudW1fYnl0ZXMgJXUgYW5kIGZsYWdzIDB4JTA4eAoAAAAAAAAAAABsMmRldl9m
-Yy0+Zmxvd2NfaWQgWyV1XSwgbDJkYy0+cGZuIFsldV0sIGwyZGMtPnZmbiBbJXVdLCBsMmRjLT5s
-cG9ydCBbJXVdLCBsMmRldl9mYy0+Zmxvd2lkIFsldV0gbDJkYy0+dHhfY2ggWyV1XSwgZGV2LnZw
-ZC5wb3J0dmVjIFsleF0KAAAAAAAAAABwb3J0dmVjIFsldV0KAAAAbDJkZXZfdmlfZnNtOiBtYiBb
-MHgleF0sIGRlZmVycmVkLCBzdGF0ZSBbMHgleF0sIHBvcnQgWzB4JXhdCgAAAGwyZGV2X3ZpX2Zz
-bTogdmlpZCBbMHgleF0gcG9ydCBbMHgleF0sIG1hYy1pZCBbJTAyeDolMDJ4OiUwMng6JTAyeDol
-MDJ4OiUwMnhdLiAKAAAAAAAAAAAAAAAAAAAAAGwyZGV2X3ZpX2ZzbTogc2dlX2VxaWQgWzB4JXhd
-LCBzZ2VfaXFpZCBbMHgleF0sIHNnZV9lcWNyIFsweCV4XSwgcnNzX3N6IFsweCV4XQoAbDJkZXZf
-dmlfZnNtOiBsMmRldl9mYy0+Zmxvd2NfbmV0X2wyZGV2X210dSBbJXVdLCBtYl9zY3JhdGNoIFsw
-eCV4XSwgcG9ydCBbMHgleF0KAAAAAAAAAAAAAAAAAAAAbDJkZXZfdmlfZnNtOiB2aWlkIFslZF0s
-IHZpX2ZjLT5mbG93Y192aV9mbGFncyBbMHgleF0KAAAAAAAAAAAAAGwyZGV2X3ZpX2ZzbTogcGZu
-IFsweCV4XSwgdmZuIFsweCV4XSwgbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgbHBvcnQgWzB4
-JXhdLCB2aWlkIFsweCV4XSwgZmxhZ3MgWzB4JXhdCgAAAAAAAABsMmRldl92aV9mc206IEVycm9y
-IGZyZWVpbmcgVkksIHJjIFsweCV4XQoAAAAAAABsMmRldl92aV9mc206IHBpZCBbMHgleF0sIHZp
-aWQgWzB4JXhdLCBtYl9sb2MgWzB4JXhdLCBtYl9vcmlnWzB4JXhdLCBsMmRldl9mbGFncyBbMHgl
-eF0sIHJjIFsweCV4XQoAAAAAAAAAAAAAAAAAQWggaGEuLi5kb3VibGUgZnJlZSBveF9pZCAweCV4
-LCByeF9pZCAweCV4CgAAAAAASG9zdCBQUkxJIFJlc3BvbnNlIHRpbWVkb3V0OiBveF9pZCAweCV4
-IHJ4X2lkIDB4JXgKAAAAAAAAAAAAAAAAAEZDT0UgRnJlZTogc3RpbGwgeWllbGRlZCB3aGVuIGZy
-ZWVpbmcuLi5mbG93Y19pZCAleCBmbG93Y19mbGFncyAleCAKAAAAAAAAAAAAAAAARkMgeGNoZyBm
-cmVlIHhpZDolZCBmbG93aWQgJWQKAABwZm4gJXUgdmZuICV1IHZpYSBjb21tYW5kCgAAAAAAAHNj
-aGVkX2lvcXR4X2JwX3ByaW9yaXR5OiBoYXMgJXUgZW50cmllcyBvbmx5LCByZXF1aXJlcyAldSBl
-bnRyaWVzCgAAAAAAAAAAAAAAAAAAdHBfYmFja29mZjogcGFyc2VkICVkIGluc3RlYWQgb2YgJXUg
-ZW50cmllcwoAAAAAdHBfdGltZXJ2YWxzOiBwYXJzZWQgJWQgaW5zdGVhZCBvZiAldSBlbnRyaWVz
-CgAAdHBfdGltZXJyZXM6IHBhcnNlZCAlZCBpbnN0ZWFkIG9mICV1IGVudHJpZXMKAAAAdHBfbXR1
-cyBoYXMgJXUgZW50cmllcyBvbmx5LCByZXF1aXJlcyAldSBlbnRyaWVzCgAAAAAAAAAAAAAAAAAA
-AHRwX210dXNbJXVdIGlzICV1IGJ5dGVzIHdoaWNoIGlzIG5vdCBzdXBwb3J0ZWQKAGNvbmZpZ3Vy
-YXRpb24gZmlsZSBwYXJzZXI6IHNnZSB0aW1lciB2YWx1ZVslaV0gaXMgdG9vIGxhcmdlLCBjaGFu
-Z2luZyBmcm9tICV1IHRvICV1dXNlY3MKAAAAAAAAAGZpbHRlcm1hc2sgMHgleCBpcyBub3QgZXF1
-YWwvc3Vic2V0IHRvL29mIGZpbHRlcm1vZGUKAAAAAAAAAAAAAABod19sZV9jbGlwX2hhbmRsZXI6
-IHJlbW92ZWQgcG9zPSV1ICg9aWR4ICV1KQoAAABod19sZV9jbGlwX2hhbmRsZXI6IGFkZGluZyB0
-byBwb3M9JXUgKD1pZHggJXUpCgBtb2R1bGVbJXVdOiBwb3J0IG1vZHVsZSBpbnNlcnRlZCBhbmQg
-cmVhZHkKAAAAAABtb2R1bGVbJXVdOiBwb3J0IG1vZHVsZSByZW1vdmVkCgAAAAAAAAAAAAAAAAAA
-AABtb2R1bGVbJXVdOiB1bmtub3duIG1vZHVsZSBpZGVudGlmaWVyIDB4JTAyeAoAAABtb2R1bGVb
-JXVdOiBncGlvICV1IHRyYW5zIDEwRyAweCUwMnggMUcgMHglMDJ4IChsZW5ndGggJXUpIGNhYmxl
-IDB4JTAyeCAobGVuZ3RoICV1KSBtb2R1bGVfdHlwZSAweCUwMngKAAAAAAAAAAAAbW9kdWxlWyV1
-XTogZ3BpbyAldSB0cmFucyAxMEcgMHglMDJ4IDFHIDB4JTAyeCAobGVuZ3RoICV1KSBjYWJsZSAw
-eCUwMnggKGxlbmd0aCAldSkgbW9kdWxlX3R5cGUgMHglMDJ4CgAAAAAAAAAAAGZscl9wZnZmX2Zz
-bVsldToldV06IHVua25vd24gc3RhdGUgJXUKAAAAAAAAAAAAAGh3IHBmIGJpdG1hcCAweCUwMngg
-dmZpZCBiaXRtYXAgMHglMDh4OjB4JTA4eDoweCUwOHg6MHglMDh4CgAAAABhZnRlciB2ZmlkIGZp
-eHVwLCB2ZmlkIGJpdG1hcCAweCUwOHg6MHglMDh4OjB4JTA4eDoweCUwOHgKAAAAAAAAdGltZXIg
-cXVldWUgJXUgbG9zdCBhIHRpY2shIG5leHQgJXAgbGFzdCAlcCBudW1lICV1CgAAAAAAAAAAAAAA
-AGZscl90aW1lcl9zdGFydDogZmxvd2NfaWQgJXUgJXAgYnVmICVwCgAAAAAAAAAAAHBjaWU6IG5w
-ZiAldSAocGZiaXRtYXAgMHglMDJ4KSBudmYgJXUgKHBmIDAuLjcgMHglMDh4JTA4eCkgdmZzdHJp
-ZGUgJXUKAAAAAAAAAAAAZmFpbGVkIHRvIGZpbmQgdGhlICVjJWMgVlBEIHBhcmFtZXRlcgoAAAAA
-AAAAAAAAZmFpbGVkIHRvIHBhcnNlIHRoZSAlYyVjIFZQRCBwYXJhbWV0ZXIKAAAAAAAAAAAAZmFp
-bGVkIHRvIHN1Y2Nlc3NmdWxseSBmaW5kIENoZWxzaW8gVlBECgAAAAAAAAAAbG9nIGluaXRpYWxp
-emVkIEAgMHglMDh4IHNpemUgJXUgKCV1IGVudHJpZXMpIGZ3cmV2IDB4JTA4eCBwY2llX2Z3IDB4
-JTA4eAoAAAAAAABnYXRoZXJfdGFza3NfZm9yX3RtZjogaWR4IFsweCV4XSwgdGFzay1pZCBbMHgl
-eF0sIGNtZC1pZCBbMHgleF0sIGFjdGl2ZSB0YXNrcyBbMHgleF0uIGNvbm4taWQgWzB4JXhdLCBj
-bWQgY29ubi1pZCBbMHgleF0sIHRhc2sgY29ubi1pZCBbMHgleF0KAABnYXRoZXJfdGFza3NfZm9y
-X3RtZjogSW52YWxpZCB0eXBlIFsweCV4XSwgYmFpbGluZyBvdXQuCgAAAAAAAAAAZ2F0aGVyX3Rh
-c2tzX2Zvcl90bWY6IHRhc2sgaWQgWzB4JXhdLCBzdGF0ZSBbMHgleF0sIGxpZHggWzB4JXhdLCBj
-b29raWUgaGkgWzB4JTA4eF0gOiBsbyBbMHglMDh4XQoAAAAAAAAAAAAAAAAAAGdhdGhlcl90YXNr
-c19mb3JfdG1mOiByYyBbMHgleF0sIFsweCV4XSB0YXNrIGdhdGhlcmVkIGZvciB0bWYgdHlwZSBb
-MHgleF0gcHJvY2Vzc2luZy4KAAAAAAAAAAAAAHNjc2lfZGF0YV9vdXQ6IGNvbm5fZmMgWzB4JXhd
-LCBzdGF0ZSBbMHgleF0sIHNlc3NfZmMgWzB4JXhdIGluIHJlY292ZXJ5LiBTa2lwcGluZyBpc3Rh
-c2tfZmMgWzB4JXhdIGZyb20gVFguCgAAAABzZW5kX2Fib3J0X3JlcTogY3NrX2ZjLT5mbG93Y190
-eXBlIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIHRpZCBbMHgleF0sIHVscHR4Y2gg
-WyV1XSwgYnVmZmVyZWQgWyV1XQoAAAAAaHcgcmVnaXN0ZXIgb3BlcmF0aW9uIG5vdCBjb21wbGV0
-aW5nLCByZWcgMHglMDh4IG1hc2sgMHglMDh4IHZhbHVlIDB4JTA4eCAocmVnIDB4JTA4eCkKAAAA
-AAAAAAAATURJTyBDTDQ1OiBmYWlsZWQgdG8gc2V0IHVwIE1NRCBhZGRyCgAAAAAAAAAAAAAATURJ
-TzogZmFpbGVkIHRvIHdyaXRlCgAAAAAAAAAAAABNRElPIENMNDU6IGZhaWxlZCB0byBzZXQgdXAg
-TU1EIGFkZHIKAAAAAAAAAAAAAABNRElPOiBmYWlsZWQgdG8gcmVhZAoAAAAAAAAAAAAAAAlBUV9U
-YWtlQ29udHJvbE9mRkxBU0g6IDFlLmMwMDE9JSN4IDFlLmM0NTA9JSN4IDFlLmM0NTE9JSN4IDFl
-LjEwMD0lI3gKAAAAAAAAAAAAQVFfQVBJX1dyaXRlQW5kVmVyaWZ5Rmxhc2hJbWFnZSAtIEltYWdl
-IGludGVncml0eSBjaGVjayBmYWlsZWQgKGNhbGMgJSN4IHZhbCAlI3gpCgAAAAAAAAAAAAAAAAAA
-QVFfQVBJX1dyaXRlQW5kVmVyaWZ5Rmxhc2hJbWFnZSAtIEltYWdlIGludGVncml0eSBjaGVjayBw
-YXNzZWQKAEFRX0FQSV9Xcml0ZUFuZFZlcmlmeUZsYXNoSW1hZ2UgLSBUaW1lb3V0IHdhaXRpbmcg
-Zm9yIGZsYXNoIGludGVyZmFjZSAoJXUpCgAAAAAAQVFfQVBJX1dyaXRlQW5kVmVyaWZ5Rmxhc2hJ
-bWFnZSAtIFRpbWVvdXQgd2FpdGluZyBmb3IgZmxhc2ggaW50ZXJmYWNlICgldSkKAAAAAABBUV9B
-UElfV3JpdGVBbmRWZXJpZnlGbGFzaEltYWdlIC0gVGltZW91dCB3YWl0aW5nIGZvciBmbGFzaCBp
-bnRlcmZhY2UgKCV1KQoAAAAAAEFRX0FQSV9Xcml0ZUFuZFZlcmlmeUZsYXNoSW1hZ2UgLSBUaW1l
-b3V0IHdhaXRpbmcgZm9yIGZsYXNoIGludGVyZmFjZSAoJXUpIChwcCAlI3ggYXAgJSN4KQoAAAAA
-AEFRX0FQSV9Xcml0ZUFuZFZlcmlmeUZsYXNoSW1hZ2UgLSBUaW1lb3V0IHdhaXRpbmcgZm9yIGZs
-YXNoIGludGVyZmFjZSAoJXUpCgAAAAAAQVFfQVBJX1dyaXRlQW5kVmVyaWZ5Rmxhc2hJbWFnZSAt
-IFRpbWVvdXQgd2FpdGluZyBmb3IgZmxhc2ggaW50ZXJmYWNlICgldSkKAAAAAABBUV9BUElfV3Jp
-dGVBbmRWZXJpZnlGbGFzaEltYWdlIC0gRXJyb3Igb24gYnVybmluZyBGTEFTSCAoY3JjMTYgbWlz
-bWF0Y2gpCgAAAAAAAHNlbmRfY2xvc2VfcmVxOiBjc2tfZmMtPmZsb3djX3R5cGUgWzB4JXhdLCBj
-c2tfZmMtPmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT50Y2Jfc3RhdGUgWzB4JXhdCgAAAHNlbmRf
-Y2xvc2VfcmVxOiBjc2tfZmMtPmZsb3djX3R5cGUgWzB4JXhdLCBjc2tfZmMtPmZsb3djX2lkIFsw
-eCV4XSwgdGlkIFsweCV4XSwgdWxwdHhjaCBbJXVdLGJ1ZmZlcmVkIFsldV0KAAAAAABvZmxkX3Rj
-cF9kb19hY3RpdmVfY2xvc2U6IGNza19mYyBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQgWzB4JXhd
-LCBjc2tfZmMtPnRjYl9zdGF0ZSBbMHgleF0KAAAAAABvZmxkX3RjcF9kb19hY3RpdmVfY2xvc2U6
-IGNza19mYyBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPnRjYl9zdGF0
-ZSBbMHgleF0KAAAAAABvZmxkX3RjcF9kaXNjb25uZWN0OiB0Y2JfZmMtPmZsb3djX2lkIFsweCV4
-XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNzay0+dGNiX3N0YXRlIFsweCV4XQoAAABkZWNv
-ZGVfYmFzZTY0X3N0cmluZzogZGxlbiBbJWRdCgAAAAAAAAAAAAAAAAAAAABkZWNvZGVfaGV4X3N0
-cmluZzogZGxlbiBbJWRdCgAAAGZvaXNjc2lfdmFsaWRhdGVfbG9naW5fc3RhZ2U6IC0gMQoAAAAA
-AAAAAAAAAAAAAGFzeW5jX3BkdTogbG9nb3V0IHJlcXVlc3RlZCBibG9ja2luZyBzZXNzaW9uCgAA
-AGFzeW5jX3BkdTogc2Vzcy9jb25uIGRyb3AgcmVxdWVzdGVkIGJsb2NraW5nIHNlc3Npb24KAAAA
-AAAAAAAAAABjcGxfdHhfcGt0OiB2bGFuaWQgWzB4JXhdCgAAAAAAAG5ldF9sMmRldl9maW5kX2J5
-X2FkZHI6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIGwyZGMtPmxwb3J0IFsldV0sIGwyZF9m
-Yy0+Zmxvd2NfaWQgWzB4JXhdLCBsMmRjLT5pbjRfZGV2LmluX2FkZHIuYWRkciBbMHgleF0sIGFk
-ZHIgWzB4JXhdCgAAAG5ldF9sMmRldl9tdHVfY29uZmlnOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4
-JXhdLCBtdHUgJXUKAAAAAAAAAABjcGxfdHhfcGt0OiB2bGFuaWQgWzB4JXhdCgAAAAAAAGVuY29k
-ZSBoZXggc3RyaW5nOiBkbGVuIFslZF0KAAAAY2huZXRfZmluZF9sMnRfZW50cnk6IGRhZGRyIFsl
-MDh4XSwgWzB4JTA4eF0sIGxvY2FsIG5ldHdvcmsgWyVkXQoAAAAAAAAAAAAAAAAAAABsMnRlbnQg
-WyUweF0sIGwydGVudC0+aWR4IFslZF0KAHRjcF9zZW5kX2FvcGVuX3JlcTogY3NrX2ZjLT5mbG93
-Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCBidWZmZXJlZCBbJXVdLCBy
-ZXNfY250IFsweCV4XSwgaXFfaWR4IFsweCV4XQoAAAAAAAAAAAAAdGNwX3NlbmRfYW9wZW5fcmVx
-OiBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIG5v
-IHZhbGlkIGwydF9lbnR5LiBEZWxheWluZyBhbm90aGVyIHJldHJ5IGZvciAxIHNlY29uZHMuCgAA
-AAAAAAAAAAAAAAAAYW9wZW5fcmVxOiBod19sZV9maWx0ZXJfY3R1cGxlIGZhaWxlZAoAAAAAAAAA
-AAAAb2ZsZF90Y3Bfc2VuZF9hb3Blbl9yZXE6IGNwbF9yZXEtPkZpbHRlciBbMHglMHhdLCBjdHVw
-bGVzWzBdIFsweCV4XSwgY3R1cGxlc1sxXSBbMHgleF0KAAAAAAAAAAAAY3NvY2tfYWxsb2M6IHR4
-X2NoIFsweCV4XSwgbHBvcnQgWzB4JXhdLCBjb29raWUgWyUwOHhdCgAAAAAAAAAAAGNzb2NrX2Fs
-bG9jOiBhdmFpbGFibGUgWyV1XSwgbmNzb2NrIFsldV0sIHBvczphdGlkIFsweCV4XSwgY3NrX2Zj
-IFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIHNwb3J0IFsldV0KAABXQVRDSERPRzog
-Tm8gdGVtcGVyYXR1cmUgc2Vuc29yIGF2YWlsYWJsZS4KAAAAAAB3YXRjaGRvZyBjbWQgcmVmcmVz
-aCAoYWN0aW9uICV1KQoAAAAAAAAAAAAAAAAAAABXQVRDSERPRzogQWN0aXZhdGluZwoAAAAAAAAA
-AAAAAFdBVENIRE9HIC0gRW5hYmxlIGFjdGlvbiAldSB0aW1lICV1CgAAAAAAAAAAAAAAAFdBVENI
-RE9HIC0gRGlzYWJsZSBhY3Rpb24gJXUKAAAAV0FUQ0hET0c6IERlLWFjdGl2YXRpbmcKAAAAAAAA
-AABwb3J0WyV1XSBzZXQgUEFVU0UgUEFSQU1TOiBwcHBlbiAldSB0eHBlICUjeCByeHBlICUjeAoA
-AAAAAAAAAAAAbXBzX2xpbmtfdXBbJXVdIGFjYXBzICUjeCAoODAyLjMgJSN4KSArIGxwYWNhcHMg
-JSN4ID0+ICUjeAoAAAAAAGZvaXNjc2kgY29ubl9mYyBbMHgleF0sIGZsb3djX3NjaGVkY2wgWzB4
-JXhdLCBpbmdfY2ggWzB4JXhdLCBlZ3JfY2ggWzB4JXhdCgAAAAAAbDJkZXZfbm90aWZ5IHdpdGgg
-dW5rbm93biBmbGFnIFsweCV4XQoAAAAAAAAAAAAARkNvRSBGQ0IgbGlua2Rvd246IGlvX3JlcSAw
-eCV4JXggaXFpZCAweCV4IGZsb3dpZCAweCV4IG9wIDB4JXgKAGNhbmNlbCBmY2I6JXggc2NiOiV4
-IHN0YXRlOiV4CgAAUkRFViBtc2cgZmxvd2M6JXggc3RhdGUgMHgleCBldmVudCAweCV4CgAAAAAA
-AAAAdm4ydm46IHBvcnQgMHgleCBkaWQ6MHgleCV4JXggVVAKAAAAAAAAAAAAAAAAAAAAdm4ydm46
-IHBvcnQgMHgleCBkaWQ6MHgleCV4JXggRE9XTgoAAAAAAAAAAAAAAAAAZmNfc2VuZF9hbGxvY19j
-cGw6IGZhaWxlZCB0byBzZXR1cCBmaWx0ZXIgY3R1cGxlCgAAAAAAAAAAAAAAAAAAAGZjb2VfY29t
-cHV0ZV9jdHVwbGUgMHgleDoleAoAAAAAY29tcHV0ZV9jdHVwbGUoKTogZmFpbGVkIHRvIHNldHVw
-IGZpbHRlciBjdHVwbGUKAAAAAAAAAAAAAAAAAAAAAGZjb2VfY29tcHV0ZV9jdHVwbGUgdmxhbiAl
-eCB2aWlkICV4IHBvcnQgJXggbXBzX2lkeCAleAoAAAAAAAAAAABBcHBseSBBUFA6IHBvcnQgJWQg
-cHJpb3IgJWQgc2VsZWN0ICVkIHByb3RvY29sSUQgMHglMDR4CgAAAAAAAAAAY2hfY2xfcmF0ZVsl
-dS8ldV06IGNhcHBlZCBkZWZpY2l0X2luY3IgZnJvbSByZXF1aXJlZCAldSB0byAldTsgcmF0ZSAl
-dSAoZWZmICV1KSBkZWZpY2l0X21heCAldQoAZmNfc2VuZF9hbGxvY19jcGw6IGZhaWxlZCB0byBz
-ZXR1cCBmaWx0ZXIgY3R1cGxlCgAAAAAAAAAAAAAAAAAAAGZjb2VfY29tcHV0ZV9jdHVwbGUgMHgl
-eDoleAoAAAAAY29tcHV0ZV9jdHVwbGUoKTogZmFpbGVkIHRvIHNldHVwIGZpbHRlciBjdHVwbGUK
-AAAAAAAAAAAAAAAAAAAAAEZDb0UgRkNGIHRpbWVyOiBmbG93YyBzdGF0ZSAweCV4LCBwb3J0IDB4
-JXggLGZjZiAweCV4LCBmbG93Y19pZCAweCV4CgAAAAAAAAAAAAAAd29ya2Fyb3VuZDEzNzIzOiBk
-ZXRlY3RlZCBXUiBAIDB4JTA4eCBvZiBzaXplICV1IGJ5dGVzLCBkcmliYmxpbmcgaXQgaW4gJXUg
-Ynl0ZXMgYXQgYSB0aW1lCgAAAAAAcmlfd3JfaW5pdFsldV06IG1zcyAldSBpcyBub3QgOC1ieXRl
-IGFsaWduZWQKAAAAY29yZV9wcm9ncmFtX3RjYjogdGlkICUjeCB0X3N0YXRlICUjeCByY3ZfYWR2
-IDB4JTA4eCByY3Zfc2NhbGUgJSN4IHR4X21heCAlI3ggcmN2X254dCAlI3ggYXRpZCAlI3gKAAAA
-AAAAAAAAAAAAAAlvcHQwICUjeCV4IG9wdDIgJSN4IGlwdjYgJSN4IGZsYWdzX3RpbWVyIDB4JTA4
-eAoAAAAAAAAAAAAAAAAAAABvZmxkX2Nvbm5lY3Rpb25fd3I6IGNvbm5lY3Rpb24gd2l0aCA1LXR1
-cGxlIGxwIDB4JTA0eCBmcCAweCUwNHggbGlwIDB4JTA4eCUwOHggcGlwIDB4JTA4eCUwOHggZmls
-dGVyIDB4JTA4eCBleGlzdHMgQCBMRSBpbmRleCAldQoAAAAAAAAAAAAAAAAAAABvZmxkX2Nvbm5l
-Y3Rpb25fd3I6IGNvbm5lY3Rpb24gd2l0aCA1LXR1cGxlIGxwIDB4JTA0eCBmcCAweCUwNHggbGlw
-IDB4JTA4eCBwaXAgMHglMDh4IGZpbHRlciAweCUwOHggZXhpc3RzIEAgTEUgaW5kZXggJXUKAAAA
-AAAAAG9mbGRfY29ubmVjdGlvbl93cjogY29ubmVjdGlvbiB3aXRoIDUtdHVwbGUgbHAgMHglMDR4
-IGZwIDB4JTA0eCBsaXAgMHglMDh4JTA4eCBwaXAgMHglMDh4JTA4eCBmaWx0ZXIgMHglMDh4CgAA
-AABvZmxkX2Nvbm5lY3Rpb25fd3I6IGNvbm5lY3Rpb24gd2l0aCA1LXR1cGxlIGxwIDB4JTA0eCBm
-cCAweCUwNHggbGlwIDB4JTA4eCBwaXAgMHglMDh4IGZpbHRlciAweCUwOHgKAAAAAAAAAAAAAAAA
-SVFGTElOVCBwZm4gJXUgdmZuICV1OiBpcWVzaXplICV1IHRvbyBzbWFsbAoAAAAASVFGTElOVCBw
-Zm4gJXUgdmZuICV1OiBpcWlkICV1IHRvbyBsYXJnZSAobWF4ICV1KQoAAAAAAAAAAAAAAAAAAElR
-RkxJTlQgcGZuICV1IHZmbiAldTogaXFpZCAldSBub3QgYWxsb2NhdGVkCgAAAElRRkxJTlQgcGZu
-ICV1IHZmbiAldTogZmwwaWQgJXUgdG9vIGxhcmdlIChtYXggJXUpCgAAAAAAAAAAAAAAAABJUUZM
-SU5UIHBmbiAldSB2Zm4gJXU6IGZsMGlkICV1IG5vdCBhbGxvY2F0ZWQKAABJUUZMSU5UIHBmbiAl
-dSB2Zm4gJXU6IGZsMWlkICV1IHRvbyBsYXJnZSAobWF4ICV1KQoAAAAAAAAAAAAAAAAASVFGTElO
-VCBwZm4gJXUgdmZuICV1OiBmbDFpZCAldSBub3QgYWxsb2NhdGVkCgAASVFGTElOVCBwZm4gJXUg
-dmZuICV1OiBmbDFpZCAldSBpcyB2YWxpZCBidXQgbm90IGZsMGlkICV1CgAAAAAAAElRRkxJTlQg
-cGZuICV1IHZmbiAldTogZmwxaWQgJXUgaXMgdmFsaWQgYnV0IGhlYWRlciBzcGxpdCBmZWF0dXJl
-IGlzIG5vdCBlbmFibGVkCgAAAAAAAAAAAAAAAAAAAGh3X3VscHR4X3dvcmthcm91bmRfcHIxNjk0
-OV9lbmFibGVkX3BmOiBwZiAldSBlbmFibGVkICV1CgAAAAAAAABod191bHB0eF93b3JrYXJvdW5k
-X3ByMTY5NDlfZW5hYmxlZF92ZmlkOiB2ZmlkICV1IGVuYWJsZWQgJXUKAAAARVEgcGZuICV1IHZm
-biAldTogY3JlYXRpbmcgRVRIIGVxaWQgJXUgd2l0aCBwZW5kaW5nIFdSKHMpIChudW1fYnl0ZXMg
-JXUgYW5kIGZsYWdzIDB4JTA4eAoAAAAAAAAARVEgcGZuICV1IHZmbiAldTogY3JlYXRpbmcgQ1RS
-TCBlcWlkICV1IHdpdGggcGVuZGluZyBXUihzKSAobnVtX2J5dGVzICV1IGFuZCBmbGFncyAweCUw
-OHgKAAAAAAAARVEgcGZuICV1IHZmbiAldTogZXFpZCAldSB0b28gbGFyZ2UgKG1heCAldSkKAAAA
-RVEgcGZuICV1IHZmbiAldTogZXFpZCAldSBub3QgYWxsb2NhdGVkCgAAAAAAAAAAaHdfY2ltX3Rw
-X3dvcmthcm91bmQxMzcyM19lbmFibGU6IHBvcnQgJXUgcHJvdG9jb2wgMHgleCBlbiAldSBjdXJy
-ZW50IDB4JXggd29ya2Fyb3VuZF9wcjEzNzIzIDB4JXggbmV4dCAweCV4CgAAAHBvcnRfYmxpbmtf
-bGVkX3Jlc3RvcmUKAAAAAAAAAAAAcG9ydF9ibGluazogYmxpbmtkdXI9MHgleCBibGlua19yZWZj
-bnQKAAAAAAAAAAAAcG9ydF9ibGluazogCWJsaW5rX3JlZmNudD0weCV4CgBwb3J0X2JsaW5rOiAJ
-YmxpbmtfcmVmY250PTB4JXgKAG1paV9hZHZfZmNbJXVdOiByY2FwcyAweCV4CgAAAAAAbWlpX2Fk
-dl9zcGVlZFsldV06IHJjYXBzIDB4JXgKAABtaWlfaW5pdFsldV06IGFjYXBzIDB4JXgKAAAAAAAA
-AHBvcnRbJXVdOiBnYXZlIHVwIGZpeGluZyBlcnJvcnMhISEKAAAAAAAAAAAAAAAAAG1paV9hbnJl
-c3RhcnRbJXVdOiBhY2FwcyAweCV4CgAAaHdfeGdtX3BvcnRfbHBiayBwb3J0ICV1IHB0eXBlICUj
-eCBhY3Rpb24gJSN4CgAAcG9ydF9jbWRfaGFuZGxlcjogdW5rbm93biB1LmRjYi50eXBlIDB4JXgK
-AAAAAAAAcG9ydFsldToweCUwMng6MHglMDJ4XTogbDFjZmcsIGludmFsaWQgcmVxdWVzdCwgcGNh
-cHMgMHgleCBhY2FwcyAweCV4IHJjYXBzIDB4JXgKAAAAAAAAAAAAAAAAAAAAcG9ydFsldToweCUw
-Mng6MHglMDJ4XTogbDFjZmcsIHBjYXBzICUjeCBhY2FwcyAlI3ggcmNhcHMgJSN4IG1jYXBzICUj
-eAoAAAAAAAAAAABwb3J0WyV1OjB4JTAyeDoweCUwMnhdOiBsMWNmZywgbWRpIGlzc3VlIHBjYXBz
-IDB4JXggYWNhcHMgMHgleCByY2FwcyAweCV4CgAAAAAAAHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06
-IGwxY2ZnLCBjYW5ub3QgZm9yY2Ugbm8vbXVsdGlwbGUgc3BlZWQocyksIHBjYXBzIDB4JXggYWNh
-cHMgMHgleCByY2FwcyAweCV4CgAAAAAAAAAAAAAAAABldGhfZmxvd2NfaGFuZGxlclsweCV4XTog
-ZmxhZ3MgMHglMDh4IG51bV9ieXRlcyAldSBzY2hlZGNsIDB4JXggLT4gMHgleAoAAAAAAAAAAHNj
-c2lfY21kOiByZWNlaXZlZCBUTUYgb3AgWzB4JXhdIGZ1bmMgWzB4JXhdIG9uIGNvbm4gWzB4JXhd
-IHRocm91Z2ggY29tbWFuZCBwYXRoLgoAAAAAAAAAAAAAAAAAAHNjc2lfY21kOiBjb25uX2ZjIFsw
-eCV4XSwgc3RhdGUgWzB4JXhdLCBzZXNzX2ZjIFsweCV4XSBpbiByZWNvdmVyeS4gU2tpcHBpbmcg
-aXN0YXNrX2ZjIFsweCV4XSBmcm9tIFRYLgoAAAAAAAAAAABzY3NpX2NtZDogaVNDU0kgY29tbWFu
-ZCBzZXF1ZW5jZSB3aW5kb3cgY2xvc2VkLiBjb25uIFsweCV4XSwgb3AgWzB4JXhdLCAgY21kc24g
-WzB4JXhdLCBzZW50X2NtZHNuIFsweCV4XSwgbWF4X2NtZHNuIFsweCV4XSwgaXR0IFsweCV4XQoA
-AAAAAAAAAABzY3NpX3JlYWQ6IGNvbm5fZmMgWzB4JXhdLCBzdGF0ZSBbMHgleF0sIHNlc3NfZmMg
-WzB4JXhdIGluIHJlY292ZXJ5LiBTa2lwcGluZyBpc3Rhc2tfZmMgWzB4JXhdIGZyb20gVFguCgAA
-AAAAAAAAc2NzaV9yZWFkOiBpU0NTSSBjb21tYW5kIHNlcXVlbmNlIHdpbmRvdyBjbG9zZWQuIGNv
-bm4gWzB4JXhdLCBjbWRzbiBbMHgleF0sIHNlbnRfY21kc24gWzB4JXhdLCBtYXhfY21kc24gWzB4
-JXhdCgAAAAAAAAAAAAAAAAAAAABzY3NpX3dyaXRlOiBjb25uX2ZjIFsweCV4XSwgc3RhdGUgWzB4
-JXhdLCBzZXNzX2ZjIFsweCV4XSBpbiByZWNvdmVyeS4gU2tpcHBpbmcgaXN0YXNrX2ZjIFsweCV4
-XSBmcm9tIFRYLgoAAAAAAAAAc2NzaV93cml0ZTogaVNDU0kgY29tbWFuZCBzZXF1ZW5jZSB3aW5k
-b3cgY2xvc2VkLiBjb25uIFsweCV4XSwgY21kc24gWzB4JXhdLCBzZW50X2NtZHNuIFsweCV4XSwg
-bWF4X2NtZHNuIFsweCV4XSwgaXR0IFsweCV4XQoAAABkY2J4X2NvbnRyb2xfc21bJXVdIENPTlRS
-T0xfTElOS1VQCgAAAAAAAAAAAAAAAABkY2J4X2NvbnRyb2xfc21bJXVdIENPTlRST0xfVVBEQVRF
-X0RDQlhfVExWCgAAAABkY2J4X2NvbnRyb2xfc21bJXVdIENPTlRST0xfUEVFUl9OT1RfQURWRVJU
-SVNFX0RDQlgKAAAAAAAAAAAAAAAAZGNieF9jb250cm9sX3NtWyV1XSBDT05UUk9MX1VQREFURV9P
-UEVSX1ZFUlNJT04KAAAAAAAAAAAAAAAAAAAAAGRjYnhfY29udHJvbF9zbVsldV0gQ09OVFJPTF9Q
-Uk9DRVNTX1BFRVJfVExWCgAAAGRjYnhfY29udHJvbF9zbVsldV0gQ09OVFJPTF9BQ0tfUEVFUgoA
-AAAAAAAAAAAAAGRjYnhfaWVlZV92YWxpZGF0ZVsldV0gZXJyb3IgKG91aSAlI3ggc3VidHlwZSAl
-I3ggbGVuICUjeCkKAAAAAABkY2J4X2NlZV92YWxpZGF0ZVsldV0gZXJyb3IKAAAAAHByb2Nlc3Nf
-ZGhjcF9vcHRzOiByb290IHBhdGggbGVuIFslZF0gYnl0ZXMKAAAAAG5ldGlmX3Byb2Nlc3NfZGhj
-cF9vcHRzOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBNU0dfVFlQRSBbJWRdLCBkaGN0eHQt
-PnN0YXRlIFslZF0KAAAAAAAAAAAAAGljbXBfcmVjdjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4
-XSwgcGlkIFsweCV4XSwgaWNtcCB0eXBlIFsweCV4XQoAAAAAAAAAAAAAAAAAQUJUUyBBQ0MgYXdh
-aXRpbmcgUFJMSSBSc3A6IGZsb3djX2lkIDB4JXggb3hfaWQgMHgleCByeF9pZCAweCV4IGlxaWQg
-MHgleAoAAAAAAABwb3J0IDB4JXgsIHN0YXRlIDB4JXgsIGNvbW1hbmQgZmFpbGVkIHJldHJpZXMg
-MHgleAoAAAAAAAAAAAAAAAAAYXJwX3JlY3Y6IGlwaWQgWzB4JXhdLCBpbl9hZGRyLmFkZHIgWzB4
-JXhdLCBzaXAgWzB4JXhdLCByaXAgWzB4JXhdLCBhcnBfb3AgWzB4JXhdCgAAAAAAAAAAAAAAAAAA
-Y2huZXRfYXJwX3JlY3Y6IGlwIGNvbmZsaWN0IGRldGVjdGVkCgAAAAAAAAAAAAAAY2huZXRfYXJw
-X3JlY3Y6IHBpZCBbJXVdLCB2bGFuIFsweCV4XSwgYXJwIG9wIFsweCV4XSwgc2lwIFsweCV4XSwg
-cmlwIFsweCV4XQoAAABJbnZhbGlkIGRpZDp4JTJ4JTJ4JTJ4IHJjdmQgb24gcG9ydDolZC5Ecm9w
-aW5nIGZyYW1lCgAAAAAAAAAAAAAAcmN0OngleCBzaWQ6eCUyeCUyeCUyeCByY3ZkIG9uIGZsb3dj
-OiVkLkRyb3BpbmcgZnJhbWUKAAAAAAAAAAAAAGNzb2NrX2ZyZWU6IHNpemVvZihjc2tfZmMtPnUu
-Y3NvY2spIFsldV0sIGJ5dGVzCgAAAAAAAAAAAAAAAAAAAABHb3QgQ09OTl9FWElTVCBmb3IgeGlk
-OjB4JXgsIHRhZzoweCV4LCByZXRyeWluZy4KAAAAAAAAAAAAAAAAAAAAaHdfdWxwdHhfd29ya2Fy
-b3VuZF9wcjE2OTQ5X2VuYWJsZWRfcGZfaXE6IGlxICV1IGVuYWJsZWQgJXUgKHBmICV1KQoAAAAA
-AAAAAAAAAABjc29ja19wZWVyX2Nsb3NlOiBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgdGNiX2Zj
-LT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCB0Y2JfZmMtPmZs
-b3djX3N0YXRlIFsweCV4XQoAAAAAAGNzb2NrX3BlZXJfY2xvc2U6IGNza19mYy0+Zmxvd2NfaWQg
-WzB4JXhdLCBjc2tfZmMtPmZsb3djX3N0YXRlICBbMHgleF0KAAAAAAAAAAAAdGNwX2Nsc19hYnJ0
-X3JwbDogdGNiIHRpZCBbMHglMDZ4XSwgZmxvd2NfdHlwZSBbMHgleF0sIGNwbG9wIFsweCV4XSAK
-AAAAAAAAAAAAAABjaF9yYXRlWyV1XTogY2FwcGVkIHRpY2sgZnJvbSByZXF1aXJlZCAldSB0byBz
-dXBwb3J0ZWQgJXU7IHJhdGUgJXUgKGVmZiAldSkgZGVmaWNpdF9pbmNyICV1IHRpY2sgJXUKAAAA
-AAAAAAAAAAAAcGt0c2NoZWRfY2hfcmxbJXVdOiBjaGFubmVsIHJsIG5vdCBhdmFpbGFibGUgaW4g
-Y29uanVuY3Rpb24gd2l0aCBmbG93IHNoYXBpbmcKAABwa3RzY2hlZF9jaF9ybFsldV06IHJhdGUg
-JXUgbWF4ICV1CgAAAAAAAAAAAAAAAABwa3RzY2hlZF9jbF93cnJbJXU6JXVdOiB3ZWlnaHQgJXUK
-AAAAAAAAAAAAAAAAAABlcV9wYXJhbXNbMHgleDoweCV4XTogZG1hcSAweCV4IHJlYWQgJXUgcGYg
-JXUgZXFpZF9hcGkgJXUgcmV0ICVkCgAAAAAAAAAAAAAAAAAAAGh3X21hX2FkZHJfdG9fbWVtX3R5
-cGVfb2ZmOiBNQSBhZGRyZXNzIDB4JTA4eCBpcyBub3QgbWFwcGVkCgAAAABod19tYV9hZGRyX3Rv
-X21lbV90eXBlX29mZjogTUEgYWRkcmVzcyAweCUwOHggbWFwcyB0byB0eXBlICV1IG9mZnNldCAw
-eCV4CgAAAAAAAG1lbV9tYWxsb2NfdGVtcDogZmFpbGVkIHRvIGFsbG9jYXRlICV1IGJ5dGVzLCBy
-ZXR1cm5pbmcgTlVMTAoAAABtZW1fbWFsbG9jOiBmYWlsZWQgdG8gYWxsb2NhdGUgJXUgYnl0ZXMs
-IHJldHVybmluZyBOVUxMCgAAAAAAAAAAbGUgY29uZmlndXJhdGlvbjogaGFzaCBtb2RlIHJlcXVp
-cmVzIGF0IGxlYXN0IDE2IGVudHJpZXMsIG5oYXNoICV1CgAAAAAAAAAAAAAAAABsZSBjb25maWd1
-cmF0aW9uOiBoYXNoIG1vZGUgcmVxdWlyZXMgYXQgZW50cmllcyB0byBiZSBhIHBvd2VyIG9mIDIs
-IG5oYXNoICV1CgAAAGxlIGNvbmZpZ3VyYXRpb246IHJlcXVlc3RlZCAldSB0Y2FtIGVudHJpZXMg
-YnV0IG9ubHkgJXUgYXZhaWxhYmxlIChucm91dGUgJXUgbmNsaXAgJXUgbmZpbHRlciAldSBuc2Vy
-dmVyICV1CgAAAABsZSBjb25maWd1cmF0aW9uOiB0Y2FtIHJlZ2lvbnMgbXVzdCBoYXZlIG11bHRp
-cGxlIG9mIDMyIGVudHJpZXMsIG5yb3V0ZSAldSBuY2xpcCAldSBuZmlsdGVyICV1IG5zZXJ2ZXIg
-JXUKAAAAAAAAaHdfdHBfdGNwX3R1bmluZ3M6IHR1bmluZyBmb3IgY2x1c3RlciBlbnZpcm9ubWVu
-dAoAAAAAAAAAAAAAAAAAAGh3X3RwX3RjcF90dW5pbmdzOiB0dW5pbmcgZm9yIExBTiBlbnZpcm9u
-bWVudAoAAGh3X3RwX3RjcF90dW5pbmdzOiB0dW5pbmcgZm9yIFdBTiBlbnZpcm9ubWVudAoAAGh3
-X3RwX3RjcF90dW5pbmdzOiBtYW51YWwgdHVuaW5nCgAAAAAAAAAAAAAAAAAAAF9od19jaW1fZmxh
-c2hfbWVtY3B5OiBtZW1jcHlYIHN0YXJ0CgAAAAAAAAAAAAAAAF9od19jaW1fZmxhc2hfbWVtY3B5
-OiBkc3QgMHglMDggb2Zmc2V0IDB4JTA4eCBzaXplICV1LCB3aWR0aCBvZiAldSBpcyBub3Qgc3Vw
-cG9ydGVkCgAAAAAAAAAAAAAAAF9od19jaW1fZmxhc2hfbWVtY3B5OiBtZW1jcHlYIGVuZAoAAAAA
-AAAAAAAAAAAAAGNvbmZpZ3VyYXRpb24gZmlsZSBwYXJzZXIgZW5jb3VudGVyZWQgZXJyb3IgQCBs
-aW5lICV1OgoAAAAAAAAAAABod19pMmNfdHJhbnNhY3Rpb246IG5kYXRhICV1IGFkZHJfb3AgMHgl
-eCBkYXRhWzBdIDB4JXggZGlmZiAldQoAaHdfaTJjX3RyYW5zYWN0aW9uOiBuZGF0YSAldSBhZGRy
-X29wIDB4JXggZGF0YVswXSAweCV4IGRpZmYgJXUgZHBvcyAldSBjb250ICV1IGZhaWxlZCB3aXRo
-IGVyciAlZAoAAAAAAAAAAAAAAAAAAGkyYyB0cmFuc2FjdGlvbiBmYWlsZWQgdG8gY29tcGxldGUK
-AAAAAAAAAAAAAAAAAEhPU1QgUEFHRV9TSVpFIFsweCUwbHhdIHRvbyBzbWFsbCwgbWluIFsweCUw
-bHhdIHJlcXVpcmVkCgAAAAAAAABwYWdlIHNpemUgWyVsdV0gbWlzbWF0Y2gKAAAAAAAAAFBBR0Ug
-c2l6ZSAlbHUgdW5zdXBwb3J0ZWQsIGRkcCBkaXNhYmxlZAoAAAAAAAAAAEhvc3QgcGFnZV9zaXpl
-ICVsdSwgZGRwX2lkeCAldQoARkNvRSBERFAgaW5pdDogZmNvZSBsbGltaXQgMHgleCwgZmNvZSB1
-bGltaXQgMHgleCBnYmwgbGxpbWl0IDB4JXggZ2JsIHVsaW1pdCAweCV4IHBjYnN6ICV4CgAAAAAA
-RkNvRSBERFAgaW5pdDogZmNvZSBwcG9kIG9mZiAweCV4LCBmY29lIHN0IHBwb2QgYWRkciAweCV4
-IGZjb2UgbnVtIHBwb2RzIDB4JXgKAABmY29lIHhjaGcgbWdyIGluaXQ6IE51bWJlciBvZiBERFAg
-ZXhjaGFuZ2VzIGZvciBGQ29FIGlzICV4CgAAAAAAZmNvZSB4Y2hnIG1nciBpbml0OiBOdW1iZXIg
-b2YgdHVubmVsIGV4Y2hzIGZvciBGQ29FIGlzICV4CgAAAAAAAGZjb2VfbDJ0X2luaXQ6IE5vIHVs
-cHR4IGNyZWRpdCBjaDpbJXVdCgAAAAAAAAAAAGZjb2VfbDJ0X2luaXQ6IGNoOlsldV0gbDJ0X2lk
-eCBbJXVdCgAAAAAAAAAAAAAAAG5vIGwydCBlbnRyaWVzIGNvbmZpZ3VyZWQ7IGZvcmNpbmcgJXUg
-ZW50cmllcywgc3RhcnRpbmcgYXQgJXUKAABkY2J4IHVwZGF0ZVsldV0gc2VudCB0byBkcml2ZXIg
-KHR5cGUgJSN4IHN1YnR5cGUgJSN4IGZsb3djaWQgJXUpCgAAAAAAAAAAAAAAAAAAAGRjYnhfcnVu
-X3ZlcnNpb25fc21bJXVdIERDQlhfVkVSX1NUQVRFX1JVTl9JRUVFCgAAAAAAAAAAAAAAAAAAAABk
-Y2J4X3J1bl92ZXJzaW9uX3NtWyV1XSBEQ0JYX1ZFUl9TVEFURV9SVU5fQ0VFCgBkY2J4X3J1bl92
-ZXJzaW9uX3NtWyV1XSBEQ0JYX1ZFUl9TVEFURV9SVU5fTk9ORQoAAAAAAAAAAAAAAAAAAAAAcG9y
-dFsldV0gbGluayB1cCAoJXUpIChzcGVlZCAlI3ggYWNhcHMgJSN4IGxwY2FwcyAlI3gpCgAAAAAA
-AAAAAHBvcnRfaHNzX3NpZ2RldFsldV06IGhzc19zaWdkZXQgY2hhbmdlZCB0byAweCV4CgAAAAAA
-AAAAAAAAAAAAAABRU0ZQIG1vZHVsZSB1bnBsdWcgLSByZWluaXRpYWxpemluZyByeF9sb3MgIHRv
-IDB4ZmYKAAAAAAAAAAAAAAAAZ3Bpb19xc2ZwX21vZHVsZV91cGRhdGU6IGNoYW5nZWQgcnhfbG9z
-IGZyb20gMHgleCB0byAweCV4CgAAAAAAAGdwaW9fcXNmcF9tb2R1bGVfdXBkYXRlOiBjaGFuZ2Vk
-IHR4X2RpcyBmcm9tIDB4JXggdG8gMHgleAoAAAAAAABDYWxjdWxhdGlvbiBvdXQgb2YgYm91bmRz
-IGZ1cmluZyBpbml0OiAlI3ggJSN4ICUjeAoAAAAAAAAAAAAAAAAAaHdfc2dlX21hbWVtX2luaXQ6
-IGVuY291bnRlcmVkIGVycm9yICVkCgAAAAAAAAAAX2h3X3RwX3BnbW5ndDogdHhfcGFnZV9tYXgg
-JXUgcnhfcGFnZV9tYXggJXUgcHN0cnVjdHMgJXUgc2l6ZSAldQoAAAAAAAAAAAAAAAAAAABtcGFy
-dGl0aW9uX290aGVyc190b3RhbDogZGRwICV1IGRkcF9pc2NzaSAldSBzdGFnICV1IHBibCAldSBy
-cSAldSBycXVkcCAldSAtPiAldQoAAAAAAAAAAAAAAAAAAABfbXBhcnRpdGlvbl9iYW5rc19tY1g6
-IG5iYW5rc19wbXR4ICV1ICgldU1CKSBuYmFua3NfcG1yeCAldSAoJXVNQikgbmJhbmtzX290aGVy
-cyAldSAoJXVNQikgbmJhbmtzX2Z3ICV1ICgldU1CKQoAX21wYXJ0aXRpb25fYmFua3NfbWMxOiBu
-YmFua3NfcG10eCAldSAoJXVNQikgbmJhbmtzX290aGVycyAldSAoJXVNQikgbmJhbmtzX2Z3ICV1
-ICgldU1CKQoAAAAAAAAAX21wYXJ0aXRpb25fYmFua3NfbWMwOiBuYmFua3NfcG1yeCAldSAoJXVN
-QikgbmJhbmtzX290aGVycyAldSAoJXVNQikKAAAAAAAAAAAAAABtZW1fbWFsbG9jX2ludGVybmFs
-OiBmYWlsZWQgdG8gYWxsb2NhdGUgJXUgYnl0ZXMsIHJldHVybmluZyBOVUxMCgAAAAAAAAAAAAAA
-AAAAAGh3X2VkY19iaXN0WyV1XTogYmlzdF9jbWRbMHglMDh4XSBhZGRyIDB4JXggbGVuIDB4JXgK
-AAAAAAAAAAAAAABod19lZGNfYmlzdFsldV06IGRvbmUsIGVuY291bnRlcmVkICV1IGVycm9ycyBv
-biBmaXJzdCBhbmQgJXUgZXJyb3JzIG9uIHNlY29uZCBhdHRlbXB0ICgldWdicHMpCgBtZW1faW5p
-dF9jYWNoZXM6IGNhY2hlX3NpemUgJXUgZmxvd2NfYnVmX3RjYl9jYWNoZV9zaXplICV1IGJ1Zmxs
-NjRfY2FjaGVfc2l6ZSAldQoAAAAAAAAAAAAAAAAAAABxdWV1ZXNfcGVyX3BhZ2U6IHBmICV1IGhh
-cyBhIGJhcnNpemUgb2YgJXUtYnl0ZXMsIG9jcV9zaXplICV1CgAAc2dlIHJlcXVpcmUgbmVxICV1
-IG5pcSAldSByb3VuZGluZyB0byAldSAldQoAAAAAbXBhcnRpdGlvbl9wbXR4OiBtIDB4JTA4eCBz
-aXplICV1CgAAAAAAAAAAAAAAAAAAbXBhcnRpdGlvbl9wbXJ4OiBtIDB4JTA4eCBzaXplICV1CgAA
-AAAAAAAAAAAAAAAAbXBhcnRpdGlvbl9lZGMgKG5vIGV4dG1lbSk6IG0gMHglMDh4IHNpemUgJXUK
-AAAAbXBhcnRpdGlvbl9lZGNfZXN0aW1hdGU6IGh3IG1vZHVsZXMgcmVxdWlyZSAlZCBieXRlcyBp
-biBFREMKAAAAAGNobmV0X2J5ZTpsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBsMmRldl9mYy0+
-Zmxvd2NfcGNpZV9wZm4gWzB4JXhdLCBsMmRldl9mYy0+Zmxvd2NfcGNpZV92Zm4gWzB4JXhdLCBw
-b3J0IFsweCV4XQoAAAAAAAAAAAAAAAAAY2huZXRfYnllOnZsYW5kZXZfZmMtPmZsb3djX2lkIFsw
-eCV4XSwgdmxhbmRldl9mYy0+Zmxvd2NfcGNpZV9wZm4gWzB4JXhdLCB2bGFuZGV2X2ZjLT5mbG93
-Y19wY2llX3ZmbiBbMHgleF0sIHBvcnQgWzB4JXhdCgAAAAAAAABjcl9tb2R1bGVfcnhfbG9zWyV1
-XTogcnhfbG9zIGNoYW5nZWQgdG8gJXUKAAAAAABwZm4gJXUgdmZuICV1IGhhcyBwbmR0eG5zICV1
-IGFmdGVyIDEwMG1zCgAAAAAAAABiYWQgbWFpbGJveCBjbWQ6IHBmbiAweCV4IHZmbiAweCV4OyBv
-cGNvZGUgMHgleCA+IExBU1RDMkUgMHgleAoAbWFpbGJveCBjbWQgbm90IHlldCBzdXBwb3J0ZWQ6
-IHBmbiAweCV4IHZmbiAweCV4OyBvcGNvZGUgMHgleAoAAGJhZCBtYWlsYm94IGNtZDogcGZuIDB4
-JXggdmZuIDB4JXg7IG9wY29kZSAweCV4IGlzIHZhbGlkIHBvc3QgZGV2aWNlIGluaXQgb25seQoA
-YmFkIG1haWxib3ggY21kOiBwZm4gMHgleCB2Zm4gMHgleDsgb3Bjb2RlIDB4JTAyeCByYW1hc2sg
-MHgleCBjbWQgcmFtYXNrIDB4JXgKAABiYWQgbWFpbGJveCBjbWQ6IHBmbiAweCV4IHZmbiAweCV4
-OyBvcGNvZGUgMHglMDJ4IGxlbjE2IDB4JXggdmVyc3VzIGV4cGVjdGVkIGxlbjE2IDB4JXgKAAAA
-AAAAAABpbnN1ZmZpY2llbnQgY2FwcyB0byBwcm9jZXNzIG1haWxib3ggY21kOiBwZm4gMHgleCB2
-Zm4gMHgleDsgcl9jYXBzIDB4JXggd3hfY2FwcyAweCV4IHJlcXVpcmVkIHJfY2FwcyAweCV4IHdf
-Y2FwcyAweCV4CgAAAAAAAAAAAGluc3VmZmljaWVudCBjYXBzIHRvIHByb2Nlc3MgbWFpbGJveCBj
-bWQ6IHBmbiAweCV4IHZmbiAweCV4OyByX2NhcHMgMHgleCB3eF9jYXBzIDB4JXggcmVxdWlyZWQg
-cl9jYXBzIDB4JXggd19jYXBzIDB4JXgKAAAAAAAAAAAAVlBEIHJlZ2lvbiBpcyB0b28gc21hbGwg
-KFNFUkNGR19TUl9QRk5WUERTSVpFIDB4JXgpCgAAAAAAAAAAAAAAAGNmOiBmYWlsZWQgdG8gYWxs
-b2NhdGVkIG1lbW9yeSBmb3IgY29uZmlndXJhdGlvbiBmaWxlLCByZXQgJWQKAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAACCAAABIAAAAAAAAACCAAABAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAGgIAAAAAAAAAAAAAAAACAAAAAAAAAAAACgAAAAAAAAAAAAAIAAwAAAAABYAgAAAAAAwAA
-AAAAAAAAAAAAAwAAAAAAAAAAAAAAAgAAAAAAAAAAACAAAAAAAAAAAAAAAAEAA4AAAAAAAAAAAAAA
-AgAAAAAAAAAAACADgAAAAAAAAAAAABACgACAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA
-AAAAAoAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAoAAAAAAAAAAAAEAAwAAAAAAAAAAAAACgwAAAAAA
-AAAAABACgAAAAAAAAAAAADAAAwAAAAAAAAgAADAAAwAAAAAAAAAAADAFgwAAAAAAAAgAADAFgwAA
-AAAAAAAAADAEgwAAAAAAAAgAADAEgwAAAAAAAAAAADADAwAAAAAAAAgAADADAwAAAAAAAAAAADgD
-AwAAAAAAAAAAADgFgwAAAAAAAAAAADgEgwAAAAAAAAAAADgAAwAAAAAAAAAAADQGggAAAAAAAAAA
-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
+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
+X2NyYz0ldQoAAFBIWSBmaXJtd2FyZSBsb2FkIHN1Y2Nlc3NmdWwhCgAAaHdfYmNtODQ4MzRfbG9h
+ZHNlcXVlbmNlOiBTdGFydGVkCgAAAAAAAAAAAAAAAAAAaHdfYmNtODQ4MzRfbG9hZHNlcXVlbmNl
+OiBVcGxvYWQgaW1hZ2UgdG8gUEhZIG9uLWNoaXAgbWVtb3IKAAAAAGh3X2JjbTg0ODM0X2xvYWRz
+ZXF1ZW5jZTogZG9uZSBsb2FkaW5nIGltYWdlIChpID0gJXUpCgAAAAAAAAAAAABod19iY204NDM0
+X2xvd3Bvd2VyWyV1XTogZW5hYmxlPSVkCgAAAAAAAAAAAAAAAABod19iY204NDM0X2xvd3Bvd2Vy
+WyV1XSwgZmFpbGVkIHRvIHNldCAzMC4weDQwMUFiaXQgNyBzaW5jZSAzMC4weDQwMEUgYml0PTEg
+YWZ0ZXIgNW1zLAlyZWc9JXgKAABod19jbDQ1X2luaXRbJXVdIGFjYXBzICUjeAoAAAAAAGh3X2Ns
+NDVfdXBkX3NwZF9hZHYgJSN4CgAAAAAAAAAAaHdfYXExMjAyX2xpbmtfdXBbJXVdIHVwCgAAAAAA
+AABwWyV1XSBQSFkgT1ZFUkhFQVRFRCAtIGZvcmNlZCBwb3dlciBkb3duICh0ZW1wPSVkKQoAAAAA
+AAAAAAAAAAAARkxBU0ggbm90IHJlYWR5OiBpICV1IG52clJlZyAlI3gKAAAAAAAAAAAAAAAAAAAA
+QVFfRkxBU0hfUmVhZHkgLSBUaW1lb3V0ICgxKQoAAABBUV9GTEFTSF9SZWFkeSAtIFRpbWVvdXQg
+KDIpCgAAAAlBUV9SZXR1cm5Db250cm9sT2ZGTEFTSAoAAAAAAAAAZ2F0aGVyX3Rhc2tzX3RvX3R4
+X2xpc3Q6IHRhc2sgaW4gdXNlIFsldV0KAAAAAAAAZ2F0aGVyX3Rhc2tzX3RvX3R4X2xpc3Q6IGlk
+eCBbJXVdLCB0YXNrIGZpZCBbMHgleF0sIHRhc2sgc3RhdGUgWzB4JXhdLCB0YXNrIGNvbm4gWzB4
+JXhdLCB0YXNrIGZmbGFncyBbMHgleF0sIGNvbm4gZmlkIFsweCV4XSwgZGRwIFslZF0KAAAAAAAA
+AAAAZ2F0aGVyX3Rhc2tzX3RvX3R4X2xpc3Q6IHRhc2sgWzB4JXhdLCBzdGF0ZSBbMHgleF0gb24g
+Y29ubiBbMHgleF0gbm90IHZhbGlkIHRvIGdhdGhlciwgc2tpcHBpbmcKAAAAAAAAAAAAAAAAAAAA
+AGdhdGhlcl90YXNrc190b190eF9saXN0OiB0YXNrIFsweCV4XSwgc3RpbGwgcXVldWVkIG9uIHR4
+IHBlbmRpbmcgbGlzdC4gUmVtb3ZpbmcgaXQuCgAAAAAAAAAAAAAAAGdhdGhlcl90YXNrc190b190
+eF9saXN0OiBjb25uX2ZjLT5mbG93Y19mbGFncyBbMHgleF0sIGxpc3RfZW1wdHkgWzB4JXhdLCBh
+ZGRfdGFza19jb3VudCBbMHgleF0KAHRvX3R4X2xpc3Q6IG5vIHRhc2sgdG8gY2xvc2UgZm9yIGNv
+bm4gWzB4JXhdLCBiYWlsaW5nIHRvIHJlY292ZXJ5IHN0YXRlIFsweCV4XQoAYXV0aGVudGljYXRl
+X3RhcmdldDogS0VZX0NIQVBfUkVTUCAtIFsweCV4JXgleCV4JXgleCV4JXhdCgAAAAAAAGF1dGhl
+bnRpY2F0ZV90YXJnZXQ6IEtFWV9DSEFQX1JFU1AgLSBbMHgleCV4JXgleCV4JXgleCV4XQoAAAAA
+AABhdXRoZW50aWNhdGVfdGFyZ2V0OiBJbmNvcnJlY3QgcGFzc3dvcmQKAAAAAAAAAABDSEFQX0M6
+IGRpZ2VzdCBleHBhbnNpb24gZXJyb3IKAENIQVBfTjogVGFyZ2V0IHVzZXJpZCBtaXNtYXRjaAoA
+Q0hBUF9SOiBkaWdlc3QgZXhwYW5zaW9uIGVycm9yCgBpU0NTSSBTZWMtcGFyYW1zIHJlY2VpdmVk
+aGF2ZSBlcnJvcnMhIQoAAAAAAAAAAABUYXJnZXQgbW92ZWQgdGVtcC4gY29ubiAleCwgc2VzcyAl
+eAoAAAAAAAAAAAAAAABMb2dpbiBGYWlsZWQhIS4gY29ubl9mYyBbMHgleF0sIHNlc3NfZmMgWzB4
+JXhdLCBzdGF0dXNfY2xhc3MgWzB4JXhdCgAAAAAAAAAAAAAAAFByb3RvY29sIEVycm9yIGNiaXQg
+JWQgdGJpdCAlZCBjc2cgJWQgbnNnICVkCgAAAHJlY3Zfbm9waW46IGN0cmwgdGFzayBhbHJlYWR5
+IHBlbmRpbmcKAAAAAAAAAAAAAG9mbGRfcnhfZGF0YTogYWllZSwgaXNjc2kgY29ubiBbMHgleF0g
+Zm9yIHNlc3MgWzB4JXhdLCB0eXBlIFsweCV4XSB0cmFuc2l0ZWQgaW4gdG9lIG1vZGUuIEtpY2tp
+bmcgcmVjb3ZlcnkgCgAAAABvZmxkX3J4X2RhdGE6IGNvbm4gdGlkIFsweCV4XSwgcnhfZGF0YS0+
+c2VxIFsweCV4XSwgcnhfZGF0YS0+bGVuIFsweCV4XSwgcnhfZGF0YS0+c3RhdHVzIFsweCV4XQoA
+AAAAAAAAAAAAAAAAAAAAb2ZsZF9yeF9kYXRhOiBjc2sgeyBpZCBbMHgleF0sIGNzb2NrX29mZnNl
+dCBbMHgleF0sIGRsZW4gWzB4JXhdIH0KAAAAAAAAAAAAAAAAAABhY3RfZXN0OiB0Y2JfZmMgWzB4
+JXhdLCBmbG93Y19mb2lzY3NpX2Nvbm5fZmxhZ3MgWzB4JXhdCgAAAAAAAAAAYWN0X2VzdGFiOiB0
+Y2JfZmMtPmZsb3djX2J1ZiBbMHgleF0sIHRjYl9mYy0+Zmxvd2NfdHlwZSBbMHgleF0gdGNiX2Zj
+LT5mbG93Y19zdGF0ZSBbMHgleF0sIG5wYWdlcyBbMHgleF0sIGZsb3djX3RwX3NuZF9tYXggWzB4
+JXhdCgAAAAAAAAAAAAAAAAAAYWN0X2VzdGFiOiBhdGlkIFsweCV4XSwgdGlkIFsweCV4XSwgb3Ag
+WzB4JXhdLCByY3ZfaXNuIFsweCV4XSwgc25kX2lzbiBbMHgleF0sIGNzb2NrLT5mbG93Y19zdGF0
+ZSBbMHgleF0sIHRjcF9vcHQgWzB4JXhdLCB0Y2JfZmMtPmZsb3djX2lkIFsweCV4XSAKAAAAAAAA
+AAAAAAAAAGNza19mYy0+Zmxvd2NfY3NvY2tfY29va2llIFsweCV4XSAKAAAAAAAAAAAAAAAAAGNo
+bmV0X3F1ZXVlX3htaXQ6IGZjLT5mbG93Y19pZCBbMHgleF0sIGJ1Zl9sZW4gWzB4JXhdLCBidWZm
+ZXJlZCBbMHgleF0sIGZpZm8ubnVtX2J5dGVzIFslMHhdCgAAAG5ldGlmX2RvX2RoY3A6IHdyLT5w
+YXJhbS52bGFuaWQgWyV1XSwgbDJkZXZfZmMtPmZsb3djX25ldF9sMmRldl92bGFuZGV2IFsweCV4
+XQoAbDNpbjRfZGV2X2NvbmZpZzogd3ItPnBhcmFtLnZsYW5pZCBbJXVdLCBsMmRldl9mYy0+Zmxv
+d2NfbmV0X2wyZGV2X3ZsYW5kZXYgWzB4JXhdCgAAAAAAAAAAAAAAAAAAbmV0X2wzaW40X2Rldl9j
+b25maWc6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIGFkZHJlc3MgYWxyZWFkeSB1c2VkIGJ5
+IHBvcnQgJWQKAAAAAAAAAAAAAAAAAAAAbmV0X2wzaW40X2Rldl9jb25maWc6ICBhZGRyIFsweCV4
+XSwgbWFzayBbMHgleF0sIGd3IFsweCV4XSwgcmVmX2NudCBbMHgleF0gaW4gdXNlCgAAAAAAAAAA
+AAAAAAAAd3JoX2NobmV0X2lmY29uZjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgbDJkZXZf
+ZmMtPmZsb3djX3R5cGUgWyUweF0sIGlmY29uZl93ci0+c3Vib3AgWzB4JXhdCgAAAAAAAAAAAAAA
+AAAAAHdyaF9jaG5ldF9pZmNvbmY6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIHVua25vd24g
+c3Vib3AgWzB4JXhdCgAAAAAAAAAAAAAAAAAAd3JoX2NobmV0X2lmY29uZjogbDJkZXZfZmMtPmZs
+b3djX2lkIFsweCV4XSwgcmMgJWQKAAAAAAAAAAAAAAAAAG5ldGlmX2lwX2NvbmZsaWN0X3RpbWVy
+X2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBpbmRldmN0eHQtPnN0YXRlIFslZF0sIGlu
+ZGV2Y3R4dC0+cmV0cnlfY250IFslZF0KAAAAAAAAAABuZXRpZl9pcF9jb25mbGljdF90aW1lcl9j
+YjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgaW5kZXZjdHh0IFsweCV4XSwgaW4gZnJlZSBz
+dGF0ZQoAAAAAAAAAAABjbWRoX2NobmV0X2lmYWNlOiBmYyBbMHgleF0sIGZjLT5mbG93Y19pZCBb
+MHgleF0sIGZjLT5mbG93Y190eXBlIFsweCV4XSwgcCBbMHgleF0sIGxlbjE2IFsldV0sIGxvYyBb
+MHgleF0KAAAAAAAAY21kaF9jaG5ldF9pZmFjZTpsMmRldl9mYyBbMHgleF0sIGwyZGV2X2ZjLT5m
+bG93Y19pZCBbMHgleF0sIGwyZGV2LT5mbG93Y190eXBlIFsldV0sIGwyZGV2X2ZjLT5mbG93Y19u
+ZXRfbDJkZXZfZmxhZ3MgWyUweF0KAAAAAABjbWRoX2NobmV0X2lmYWNlOiByMlswXSAldSByMlsx
+XSAldQoAAAAAAAAAAAAAAABjbWRoX2NobmV0X2lmYWNlOiBsMmRldl9mYy0+Zmxvd2NfbmV0X2wy
+ZGV2X2ZsYWdzIGNoYW5nZWQgZnJvbSBbJTB4XSB0byBbJTB4XSwgcmMgWyVkXQoAAAAAAAAAAABj
+aG5ldF9sMmRldl91cF9tYl9jYjogcmMgWyVkXSwgcG9ydCBbJXVdLCBzdGF0ZSBbJXVdLCBjb29r
+aWUgWzB4JXhdCgAAAAAAAAAAAAAAAGRoY3BfcHJvY2Vzc19jYjogbDJkZXZfZmMtPmZsb3djX2lk
+IFsweCV4XSwgZGhjdHh0LT5zdGF0ZSBbJTB4XSwgZGhjdHh0LT5ydHJ5X2NudCBbJXVdCgAAAAAA
+AAAAAGRoY3BfdGltZXJfY2I6IERIQ1BESVNDT1ZFUiBzZW50LCBidXQgbm8gcmVwbHkgZnJvbSBh
+bnkgcG9zc2libGUgc2VydmVyIG9uIHRoZSBuZXR3b3JrLiBSZXRyeWluZyBhZ2FpbgoAAAAAAAAA
+AABkaGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBzZW5kaW5nIERIQ1BE
+SVNDT1ZFUiBmb3IgZGhjdHh0IFsweCV4XSBvbiBwaWQgWyVkXQoAAABkaGNwX3RpbWVyX2NiOiBs
+MmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBESENQT0ZGRVIgcmVjZWl2ZWQgZm9yIGRoY3R4dCBb
+JXhdIHBpZCBbJWRdCgAAAAAAAAAAAABkaGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQg
+WzB4JXhdLCAgREhDUEFDSyByZWNlaXZlZCBmb3IgZGhjdHh0IFsleF0sIHBpZCBbJWRdCgAAAAAA
+AAAAAABkaGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBkaGN0eHQtPmlw
+YWRkciBbMHgleF0KAAAAAAAAAAAAAAAAAAAAAGRoY3BfdGltZXJfY2I6IHN0YXJ0aW5nIHRpbWVy
+IGZvciBsZWFzZSBbJXVdIHNlY29uZHMKAAAAAAAAAAAAAABkaGNwX3RpbWVyX2NiOiBsZWFzZSB0
+aW1lIG9mIFsldV0gc2Vjb25kcyBleHBpcmVkLCBzZW5kaW5nIHJlbmV3IHJlcXVlc3QKAAAAAAAA
+AGRoY3BfdGltZXJfY2I6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIG5vIHJlcGx5IGZyb20g
+ZGhjcCBzZXJ2ZXIsIHRpbWluZyBvdXQKAAAAAAAAAAAAAAAAAAAAAGF1dGhfbmVnb19zZWN1cml0
+eTogc2VuZF9mbGFnIFsweCV4XSwgYXV0aF9wb2xpY3kgWzB4JXhdCgAAAAAAAABhdXRoX25lZ29f
+c2VjdXJpdHk6IEtFWV9DSEFQX1JFU1AgLSBoYXNoWzB4JXgleCV4JXgleCV4JXgleF0KAAAAYXV0
+aF9uZWdvX3NlY3VyaXR5OiBLRVlfQ0hBUF9SRVNQIC0gaGFzaFsweCV4JXgleCV4JXgleCV4JXhd
+CgAAAGF1dGhfbmVnb19zZWN1cml0eTogS0VZX0NIQVBfUkVTUCAtIGVycm9yIGVuY29kaW5nIHRv
+IGhleAoAAAAAAABhdXRoX25lZ29fc2VjdXJpdHk6IEtFWV9DSEFQX1JFU1AgLSBlbGVuIFsweCV4
+XQoAAAAAAAAAAAAAAAAAAAAAYXV0aF9uZWdvX3NlY3VyaXR5OiBLRVlfQ0hBUF9DSEFMIC0gZXJy
+b3IgZW5jb2RpbmcgdG8gaGV4CgAAAAAAAGF1dGhfbmVnb19zZWN1cml0eTogS0VZX0NIQVBfQ0hB
+TCAtIGVsZW4gWzB4JXhdCgAAAAAAAAAAAAAAAAAAAABsb2dvdXRfdGltZWRvdXQ6IGxvZ291dCBy
+ZXF1ZXN0IHRpbWVkb3V0LCBwb3NzaWJsZSBuZXR3b3JrIGlzc3Vlcy4gRm9yY2VmdWxseSBicmVh
+a2luZyBwYXRoIGZvciBzZXNzIFsweCV4XQoAAAAAcGluZ190YXJnZXQ6IHBpbmcgdGltZW91dCwg
+a2lja2luZyByZWNvdmVyeSBmb3Igc2VzcyBbMHgleF0KAAAAAGNzb2NrX2ZhaWxlZDogY3NrX2Zj
+LT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCBzZXNzX2ZjLT5m
+bG93Y19pZCBbMHgleF0sIHNlc3NfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwgZXZ0IFsweCV4XQoA
+AAAAAAAAAAAAAHJjIFslZF0sIGNza19mYyBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQgWzB4JXhd
+CgAAAAAAAAAAAAAAAAAAAAByZWNvdmVyeV90aW1lb3V0OiBzZXNzIGlkIFsweCV4XSBzdGF0ZSBb
+MHgleF0sIHJjb3VudCBbJWRdLCBmbGFncyBbMHgleF0KAAAAAAAAAHJlY292ZXJ5X3RpbWVvdXQ6
+IHNlc3MgaWQgWzB4JXhdIGluIGxvZ291dCwgYWJvcnQgdGhlIGNvbm5lY3Rpb24KAAAAAAAAAAAA
+AAAAAAAAcmVjb3ZlcnlfdGltZW91dDogc2Vzc19mYy0+Zmxvd2NfZm9pc2NzaV9zZXNzX2ZsYWdz
+IFsweCV4XSwgY29ubmVjdGlvbiByZXF1ZXN0IHBlbmRpbmcsIGJhaWxpbmcgb3V0CgAAAAAAAAAA
+AAAAAGZvaXNjc2k6IFJlY292ZXJ5IHRpbWVkIG91dCBhZnRlciBbJXVdIHJldHJ5LCBiYWlsaW5n
+IG91dAoAAAAAAABUQ1AgY29ubiBlc3RhYmxpc2htZW50IGZhaWxlZCAlZAoAAAAAAAAAAAAAAAAA
+AABkaXNjb3ZlcnlfZGF0YTogc2VzcyB7IGlkIFsweCV4XSwgZmxhZ3MgWzB4JXhdLCBidWZmZXJl
+ZCBbJXVdLiB9CgAAAAAAAAAAAAAAAAAAAGRpc2NvdmVyeV9kYXRhOiBzZXNzIHsgaWQgWzB4JXhd
+IH0sIHVscHR4Y2ggWyV1XSBubyBjcmVkaXRzIGF2YWlsYWJsZSwgcmVzY2hlZHVsaW5nIHJlcXVl
+c3QuCgAAAEludmFsaWQgb3Bjb2RlIDB4JXggaW4gY3RybCBwYXRoCgAAAAAAAAAAAAAAAAAAAERE
+UCBlcnJvciBbMHgleF0sIGFib3J0aW5nIGNvbm5uIFsweCV4XQoAAAAAAAAAAHJ4X2RhdGFfZGRw
+OiBSZXNwb25jZSByZWNpZXZlZCBmb3IgdGFzayBbMHgleF0gd2hpbGUgaW52YWxpZCB0YXNrIG9y
+IGNvbm5lY3Rpb24gc3RhdGUuIHRhc2sgc3RhdGUgWzB4JXhdLCBjb25uIHN0YXRlIFsweCV4XSwg
+Y29ubiBmbGFncyBbMHgleF0KAGlzY3NpX2hkcl9yeDogUmVzcG9uY2UgcmVjaWV2ZWQgZm9yIHRh
+c2sgWzB4JXhdIHdoaWxlIGludmFsaWQgdGFzayBvciBjb25uZWN0aW9uIHN0YXRlLiB0YXNrIHN0
+YXRlIFsweCV4XSwgY29ubiBzdGF0ZSBbMHgleF0sIGNvbm4gZmxhZ3MgWzB4JXhdCgAAAAAAAAAA
+AAAAAAAAAABpc2NzaV9oZHJfcng6IEludmFsaWQgdGFzayBzdGF0ZSAweCV4IGZvciB0YXNrIDB4
+JXgsIGl0dCBbMHgleF0sIG9wYyBbMHgleF0KAAAAAHByb2Nlc3NfdG1mX3Jlc3BvbnNlOiBidWZm
+ZXJlZCBbMHgleF0sIGlzdGFza19mYy0+Zmxvd2NfYnVmLT5zY2hlZF9ub2RlLm5leHQgWzB4JXhd
+LCBpc3Rhc2tfZmMgWzB4JXhdLCBpc3Rhc2tfZmMtPmZsb3djX2lkIFsweCV4XQoAAAAAAAAAAAAA
+AAAAAHByb2Nlc3NfdG1mX3Jlc3BvbnNlOiB3ciBvcCBbMHgleF0sIHRtZiBvcCBbMHgleF0KAAAA
+AAAAAAAAAAAAAAByZXR1cm5fcGVuZGluZ190YXNrOiBjb29raWUgWzB4JTA4eF0sIFsweCUwOHhd
+CgByZXR1cm5fcGVuZGluZ190YXNrOiBkZWxheSBwcm9jZXNzaW5nLCBjb25uIGZsYWdzIFsweCV4
+XQoAAAAAAAAAcmV0dXJuX3BlbmRpbmdfdGFzazogRG9uZSBzZW5kaW5nIHRhc2sgZXJyb3IgdG8g
+aG9zdCwgdWxwdHhsZW4xNiBbJXVdCgAAAAAAAAAAAAByZXR1cm5fcGVuZGluZ190YXNrOiBkZXF1
+ZXVlIHRhc2sgWzB4JXhdLCBzdGF0ZSBbMHgleF0gZnJvbSB0eF9saXN0CgAAAAAAAAAAAAAAAHJl
+dHVybl9wZW5kaW5nX3Rhc2s6IGFsbCB0YXNrcyByZXR1cm5lZCwgcmVjb3Zlcnkgc3RhdGUgdHJh
+bnMgdG8gWzB4JXhdCgAAAAAAAAAAY2xlYXJfZGRwX21hcDogaXN0YXNrX2ZjIFsweCV4XSwgaXN0
+YXNrX2ZjLT5mbG93Y19pZCBbMHgleF0gYnVmZmVyZWQgJXUKAAAAAAAAAABjbGVhcl9kZHBfbWFw
+OiBpc3Rhc2tfZmMtPmZsb3djX2ZvaXNjc2lfdGFza19ucHBvZCAldSwgbnBwb2QgJXUsIHBwZGFk
+ZHIgWzB4JXhdCgAAAAAAAAAAAAAAAAAAAABjbGVhcl9kZHBfbWFwOiBhbGwgcmV0dXJuZWQgdGFz
+a3MgZGRwIGNsZWFyZWQsIHJlY292ZXJ5IHN0YXRlIHRyYW5zIHRvIFsweCV4XQoAAHdyaF9mb2lz
+Y3NpX25vZGU6IG5vZGVfd3ItPmZsb3dpZF9sZW4xNiAyIFsleF0KAHdyaF9mb2lzY3NpX2NoYXA6
+IGlkX2xlbiBbJXhdLCBzZWNfbGVuIFsleF0KAAAAAHdyaF9mb2lzY3NpX2NoYXA6IHRndF9pZF9s
+ZW4gWyV4XSwgdGd0X3NlY19sZW4gWyV4XQoAAAAAAAAAAAAAAABzZXNzaW9uX2Jsb2NrOiBzZXNz
+X2ZjLT5mbG93Y19pZCBbMHgleF0sIHNlc3NfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwgY29ubl9m
+Yy0+Zmxvd2NfaWQgWzB4JXhdLCBjb25uX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIGNza19mYy0+
+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPmZsb3djX3N0YXRlIFsweCV4XQoAAAAAAAAAAAAAAAAA
+AABzZXNzaW9uX3VuYmxvY2s6IHNlc3NfZmMtPmZsb3djX2lkIFsweCV4XSwgc2Vzc19mYy0+Zmxv
+d2Nfc3RhdGUgWzB4JXhdLCBjb25uX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNvbm5fZmMtPmZsb3dj
+X3N0YXRlIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2Nfc3Rh
+dGUgWzB4JXhdCgAAAAAAAAAAAAAAAABzdGFydF9sb2dvdXQ6IFNlc3MtaWQgWzB4JXhdIGFscmVh
+ZHkgbG9nZ2luIG91dC4KAAAAAAAAAAAAAAAAAAAAcGVlcl9jb246IGNza19mYyA9PiBmbG93aWQg
+WzB4JXhdLCBmbG93Y19idWYgWzB4JXhdCgAAAAAAAAAAAAAAAGFsbG9jX3Nlc3M6IGxvZ2luX3Jl
+dHJ5IFslZF0sIHJlY292X3RpbWVvdXQgWyVkXQoAAAAAAAAAAAAAAAAAAABmb2lzY3NpX2N0cmw6
+IHN1Ym9wIFsweCV4XSwgc2Vzc190eXBlX3RvX2VybCBbMHgleF0sIHNlc3NfdHlwZSBbMHgleF0K
+AAAAAAAAAAAAAGZvaXNjc2lfY3RybDogcmVjZWl2ZWQgYmxvY2tlZCBmcm9tIGRyaXZlciwgdHJp
+Z2dlcmluZyByZXR1cm4gdGFza3Mgbm93LgoAAAAAAAAAd2F0Y2hkb2cgY21kIGhhbmRsZXIgKHRp
+bWUgJXUgYWN0aW9uICV1KQoAAAAAAAAAeGdtYWNbJXVdIHNldHRpbmcvdW5zZXR0aW5nIGhzcyBy
+ZXN5bmMgYml0CgAAAAAAV0FUQ0hET0c6IGRldmljZSBzaHV0ZG93bgoAAAAAAABXQVRDSERPRzog
+cG9ydFsldV0gcGF1c2Ugd2F0Y2hkb2cgdGltZW91dAoAAAAAAABXQVRDSERPRzogYnlwYXNzIHRp
+bWVvdXQKAAAAAAAAAFdBVENIRE9HOiBGTFIgLSBub3QgaW1wbGVtZW50ZWQgeWV0CgAAAAAAAAAA
+AAAAAFdBVENIRE9HOiB0ZW1wZXJhdHVyZSBvZiAlZEMgZXhjZWVkcyB0aHJlc2hvbGQgb2YgJWRD
+CgAAAAAAAAAAAABmaWx0ZXI6IHBvcmdyYW1taW5nIHRpZCAldSAobGUgdGNhbSBpbmRleCAldSku
+Li4KAAAAAAAAAAAAAAAAAAAAZmlsdGVyOiByZXF1ZXN0aW5nIGNvbXBsZXRpb24uLi4KAAAAAAAA
+AAAAAAAAAAAAbDJkZXZfc2VuZF9wb3J0X2V2ZW50OiB3ciBbMHgleF0gcGVuZGluZyBvbiBwb3J0
+IFslZF0sIGN1cnJlbnQgdHJ5IFslZF0KAAAAAAAAAABGQ09FIEZyZWU6IHN0aWxsIHlpZWxkZWQg
+d2hlbiBmcmVlaW5nLi4uZmxvd2NfaWQgJXggZmxvd2NfZmxhZ3MgJXggCgAAAAAAAAAAAAAAAEZD
+T0UgQlAgV1IgRVJSOiBXUiB3aXRoIGNvb2tpZSAleCV4IGVycm9yZWQgYmFjayAKAAAAAAAAAAAA
+AAAAAABwb3J0ICVkIHNldCBwZmNfZW4gPSAweCV4CgAAAAAAAHBvcnQgJWQgc2V0IHBmY19lbiA9
+IDB4JXgKAAAAAAAAZXRzX3NldF9jZmdfaWVlZVsldV0gdW5rbm93biBUU0EgYWxnIGZvciBwcmlv
+ICV1OiAldQoAAAAAAAAAAAAAAEZDb0UgRERQIGZhaWxlZCA6IG94X2lkIDB4JXggcnhfaWQgMHgl
+eAoAAAAAAAAAAEZDb0UgRERQIGZhaWxlZCA6IERkcFJlcG9ydCAweCV4IERkcFZhbGlkIDB4JXgK
+AEZDIHhjaGcgYWxsb2MgZmFpbGVkOiBhdmFpbCAlZAoAZmNvZSBub3RpZnkgOiBVcGRhdGUgbmV3
+IERDQlggdmFsdWVzIFZJIHN0YXRlIDB4JXggcHJpIDB4JXggc2NoZWRjbCAweCV4IGRjYnhfZG9u
+ZSAweCV4CgAAAAAAAAAAZmNvZSBub3RpZnkgOiBGQ0YgZmxvd2lkIDB4JXgsIHVscGNoIDB4JXgg
+CgAAAAAAUFJMSSBSc3AgdGltZWRvdXQgOiBmbG93Y19pZCAweCV4IG94X2lkIDB4JXggcnhfaWQg
+MHgleCAKAAAAAAAAAGNhbm5vdCBhbGxvY2F0ZSBvZmZsb2FkZWQgZmlsdGVyIGNvbm5lY3Rpb24K
+AAAAAGNhbm5vdCBhbGxvY2F0ZSBvZmZsb2FkZWQgZmlsdGVyIElQdjYgY29ubmVjdGlvbgoAAAAA
+AAAAAAAAAAAAAABkaXNwYXRjaF9kZWZlcnJlZF9jbGFzc19jbGFzc19zaGFwaW5nWyV1OiV1XTog
+bGlzdF9lbXB0eQoAAAAAAAAAbG9vcGJhY2sgYnVmZmVyIGdyb3VwWyV1XSBpcyBkaXNhYmxlZAoA
+AAAAAAAAAAAAaW52YWxpZCBidWZmZXIgZ3JvdXBbJXVdIGNvbmZpZ3VyYXRpb246IG10dSAldSBs
+d20gJXUgaHdtICV1IGR3bSAldQoAAAAAAAAAAAAAAABmYyAldSB2ZiAldSBnb3QgaXZmPTB4JXgs
+cmFuZ2U6ICUjeC0lI3ggKCV1LyV1IHVzZWQpCgAAAAAAAAAAAAAAVkkgJXUgY2Fubm90IGdldCBS
+U1Mgc2xpY2U6IE5vIG1vcmUgc2xpY2VzIGF2YWlsYWJsZSAodXNlZCAldS8ldSkKAAAAAAAAAAAA
+AAAAAABwZm4gJXUgdmZuICV1IHdpdGggcG9ydCBtYXNrIDB4JXggY2Fubm90IGFjY2VzcyBwb3J0
+ICV1LCByZXQgJWQKAAAAAAAAAAAAAAAAAAAAAHBmbiAldSB2Zm4gJXUgY291bGQgbm90IGFsbG9j
+YXRlIHZpaWQsIHJldCAlZAoAAHBmbiAldSB2Zm4gJXUgY291bGQgbWFwIHZpaWQgIDB4JXggdG8g
+Zmxvd2MsIHJldCAlZAoAAAAAAAAAAAAAAABwZm4gJXUgdmZuICV1IGNvdWxkIG5vdCBhbGxvY2F0
+ZSB1d2lyZSBmdW5jICVkIG1hYyBhZGRyLCByZXQgJWQKAAAAAAAAAAAAAAAAAAAAAG1paV9mb3Jj
+ZV9zcGVlZFsldV06IHJjYXBzIDB4JXgKAAAAAAAAAAAAAAAAAAAAAG1paV9wZG93blsldV06IHBv
+d2VyZG93biBlbiAldQoAcG9ydFsldToweCUwMng6MHglMDJ4XTogdW5rbm93biBhY3Rpb24gMHgl
+eAoAAAAAcG9ydFsldToweCUwMng6MHglMDJ4XTogdW5rbm93biByZWFkIGFjdGlvbiAweCV4CgAA
+AAAAAAAAAAAAAAAAAGNwbF9lcnJfbm90aWZ5OiB0aWQgJXUgY3BsIDB4JTA4eCUwOHgKAAAAAAAA
+AAAAAGNwbF9lcnJfbm90aWZ5OiB0aWQgJXUgY3BsIDB4JTA4eCUwOHggMHglMDh4JTA4eAoAAAAA
+AAAAAAAAAAAAAABjcGxfZXJyX25vdGlmeTogdGlkICV1IGxlbiAldQoAAEZDT0UgRnJlZTogc3Rp
+bGwgeWllbGRlZCB3aGVuIGZyZWVpbmcuLi5mbG93Y19pZCAleCBmbG93Y19mbGFncyAleCAKAAAA
+AAAAAAAAAAAAc2NzaV9hYm9ydDogRW50ZXJpbmcgQWJvcnRfdGFzaywgYnVmZmVyZWQgWyV1XQoA
+c2NzaV9hYm9ydDogcmMgWzB4JXhdIHJlZiB0YXNrIG5vdCBvdXRzdGFuZGluZwoAc2NzaV9hYm9y
+dDogaWRhdGEtPm9wIFsweCV4XSwgZmxhZ3MgWzB4JXhdLCBmdW5jIFsweCV4XSwgbHVuX2lkeCBb
+MHgleF0KAAAAAAAAAABzY3NpX2Fib3J0OiB3ci0+aXFpZCBbMHgleF0sIGlzdGFza19mYy0+Zmxv
+d2Nfc2dlX2lxaWQgWzB4JXhdLCBpc3Rhc2tfZmMgdGFzayBmbGFncyBbMHgleF0KAAAAAABzY3Np
+X2Fib3J0OiBjb25uIFsweCV4XSwgY21kc24gWzB4JXhdLCBzZW50X2NtZHNuIFsweCV4XSwgbWF4
+X2NtZHNuIFsweCV4XSwgaXR0IFsweCV4XQoAAAAAAAAAAABhYm9ydC9jbG9zZSBXUiB3aXRoIGNv
+b2tpZSAweCVseCB3YXMgaXNzdWVkIG9uIHNzbiAweCV4IGluIHdyb25nIHN0YXRlIDB4JXgKAAAA
+AGFib3J0IFdSIG9uIHNzbiAweCV4IGRpZCBub3QgZmluZCBXUiB3aXRoIGNvb2tpZSAweCV4JXgK
+AAAAAAAAAABjbG9zZSBXUiB3aXRoIGNvb2tpZSAweCVseCBvbiBzc24gMHgleDtkaWQgbm90IGZp
+bmQgV1Igd2l0aCBjb29raWUgMHglbHgKAAAAAAAAAGFib3J0IFdSIG9uIHNzbiAweCV4IHdhcyBp
+c3N1ZWQgb24geGNoZyAweCV4IHdpdGggcnhfaWQgMHgleCBpbiB3cm9uZyBzdGF0ZSAweCV4CgAA
+AAAAAAAAAAAAAAAAAHNjc2lfbHVyOiBFbnRlcmluZyBMVVIgaGFuZGxlciwgYnVmZmVyZWQgWyV1
+XQoAAHNjc2lfbHVyOiBpZGF0YS0+b3AgWzB4JXhdLCBmbGFncyBbMHgleF0sIGZ1bmMgWzB4JXhd
+LCBsdW5faWR4IFsweCV4XQoAAAAAAAAAAAAAc2NzaV9sdXI6IHdyLT5pcWlkIFsweCV4XSwgaXN0
+YXNrX2ZjLT5mbG93Y19zZ2VfaXFpZCBbMHgleF0sIGlzdGFza19mYyB0YXNrIGZsYWdzIFsweCV4
+XQoAAAAAAAAAc2NzaV9sdXI6IGNvbm4gWzB4JXhdLCBjbWRzbiBbMHgleF0sIHNlbnRfY21kc24g
+WzB4JXhdLCBtYXhfY21kc24gWzB4JXhdLCBpdHQgWzB4JXhdCgAAAAAAAAAAAAAAZGNieF9jZWVf
+ZmVhX3NtWyV1XSBGZWF0dXJlWyV1XSBGRUFUVVJFX0xJTktVUAoAZGNieF9jZWVfZmVhX3NtWyV1
+XSBGZWF0dXJlWyV1XSBTRVRfTE9DQUxfUEFSQU1FVEVSUwoAAAAAAAAAAAAAAGRjYnhfY2VlX2Zl
+YV9zbVsldV0gRmVhdHVyZVsldV0gRkVBVFVSRV9OT19BRFZFUlRJU0UKAAAAAAAAAAAAAABkY2J4
+X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVdIEZFQVRVUkVfUEVFUl9OT1RfQURWRVJUSVNFX0RD
+QlgKAAAAAAAAAAAAAAAAAAAAAGRjYnhfY2VlX2ZlYV9zbVsldV0gRmVhdHVyZVsldV0gRkVBVFVS
+RV9QRUVSX05PVF9BRFZFUlRJU0VfRkVBVFVSRQoAAAAAAAAAAAAAAAAAZGNieF9jZWVfZmVhX3Nt
+WyV1XSBGZWF0dXJlWyV1XSBGRUFUVVJFX1VQREFURV9PUEVSX1ZFUlNJT04KAAAAAGRjYnhfY2Vl
+X2ZlYV9zbVsldV0gRmVhdHVyZVsldV0gRkVBVFVSRV9QRUVSX1VQREFURV9PUEVSX1ZFUlNJT04K
+AAAAAAAAAAAAAAAAAAAAZGNieF9jZWVfZmVhX3NtWyV1XSBGZWF0dXJlWyV1XSBGRUFUVVJFX0dF
+VF9QRUVSX0NGRwoAAAAAAAAAAAAAAGRjYnhfY2VlX2ZlYV9zbVsldV0gRmVhdHVyZVsldV0gRkVB
+VFVSRV9DRkdfTk9UX0NPTVBBVElCTEUKAAAAAABkY2J4X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVb
+JXVdIEZFQVRVUkVfVVNFX0xPQ0FMX0NGRwoAAAAAAAAAAAAAZGNieF9jZWVfZmVhX3NtWyV1XSBG
+ZWF0dXJlWyV1XSBGRUFUVVJFX1VTRV9QRUVSX0NGRwoAAAAAAAAAAAAAAGRjYnhfY2VlX2ZlYV9z
+bVsldV0gRmVhdHVyZVsldV0gRkVBVFVSRV9GRUFUVVJFX0RJU0FCTEVECgAAAAAAAABkY2J4X2Nl
+ZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVdIEZFQVRVUkVfRVJST1JfQ0hBTkdFCgAAAAAAAAAAAAAA
+RmVhdHVyZSAldSBzeW5jJ2Q9JXUgKGVycm9yICV1KQoAAAAAAAAAAAAAAAAAAAAAY2huZXRfbDJ0
+X3VwZGF0ZTogbDJkZXZfZmMgWzB4JXhdLCBsMmRldl9mYy0+Zmxvd2NfaWQgWyV1XSBsMmRldl9m
+Yy0+Zmxvd2NfZmxhZ3MgWzB4JXhdLCBpbnRmIFsweCV4XQoAAAAAAAAAAAAAAGNobmV0X2wydF91
+cGRhdGU6IGwyZGV2X2ZjLT5mbG93Y19pZCBbJXVdIGFscmVhZHkgc2NoZWR1bGVkCgAAAABjaG5l
+dF9sMnRfdXBkYXRlOiBpbiBkZWxheWVkX3Byb2Nlc3NpbmcsIGwydGVudCBbJTA4eF0KAAAAAAAA
+AAAAY2huZXRfYXJwX3VwZGF0ZV9jYWNoZTogYXJwIGlwNCBlbnRyeSBmb3VuZCAKAAAAY2huZXRf
+YXJwX3VwZGF0ZV9jYWNoZTogYXJwIGlwNiBlbnRyeSBmb3VuZCAKAAAAY2huZXRfYXJwX3VwZGF0
+ZV9jYWNoZTogYm90aCBpcDQgYW5kIGlwNiBhZGRyIGNhbm5vdCBiZSBudWxsCgAAAGNobmV0X2wy
+dF91cGRhdGU6IGwydF91cGRhdGUgcmVxdWVzdCBzZW50IGwydGVudCBbJTA4eF0sIGwydGVudC0+
+aWR4IFslZF0sIGwydGVudC0+dmxhbiBbJWRdCgAAAG5ldGlmX3Byb2Nlc3NfZGhjcDogbDJkZXZf
+ZmMtPmZsb3djX2lkIFsweCV4XSwgcHJvY2Vzc2luZywgb3B0X2xlbiAldQoAAAAAAAAAAAAAY2hu
+ZXRfZGhjcF9yZWN2OiB2bGFuaWQgWyV1XSwgbDJkZXZfcGlkX2ZjLT5mbG93Y19uZXRfbDJkZXZf
+dmxhbmRldiBbMHgleF0sIGwyZGV2X2ZjIFsweCV4XQoAAAAAY2huZXRfZGhjcF9yZWN2OiBsMmRl
+dl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBkaGN0eHQtPnN0YXRlIFslZF0sIG1hbGFjaW91cyBkaGNw
+IHJlY3YgZm9yIG5vIHJlcXVlc3QKAAAAAAAAAAAAAAAAAGRoY3R4dC0+c3RhdGUgOiAlZAoAAAAA
+AAAAAAAAAAAAbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgQmFkIERIQ1AgY29va2llIHJlY2ll
+dmVkLCBhYm9ydGluZwoAAENvdWxkIG5vIGFsbG9jYXRlIHBjYiEhIEZyZWVpbmcgZmNmICEhIQoA
+AAAAAAAAAHZuX3BhcnNlIHVua25vd24gc3ViY29kZSAldQoAAAAAdm5fcGFyc2UgdW5rbm93biBk
+dHlwZSAldQoAAAAAAABpZ25vcmluZyBmaXAgcmVjdiBmb3IgcGNiIGZsb3c6JXggaW4gb2ZmbGlu
+ZSBzdGF0ZQoAAAAAAAAAAAAAAAAAZmlwX3ZuMnZuX3JlY3ZfZXJyIAoAAAAAAAAAAAAAAABDb3Vs
+ZCBub3QgYWxsb2NhdGUgZmxvd2MhISEhCgAAAENvdWxkIG5vdCBhbGxvY2F0ZSBTQ0IgZmxvd2Mh
+ISEhCgAAAAAAAAAAAAAAAAAAAENvdWxkIG5vdCBmaW5kIHJpZ2h0IHNjYiBmb3IgbG9nbwoAAAAA
+AAAAAAAAAAAAAGlnbm9yaW5nIGZpcCByZWN2IGZvciBmY2YgZmxvdzoleCBpbiBvZmZsaW5lIHN0
+YXRlCgAAAAAAAAAAAAAAAABDb3VsZCBub3QgZmluZCByaWdodCBzY2IgZm9yIGZsb2dpCgAAAAAA
+AAAAAAAAAABwb3J0IDB4JXgsIHN0YXRlIDB4JXgsIHJldHJ5IG5vdCBzdXBwb3J0ZWQKAAAAAABG
+bG9naSByZXNwIHJjdiB3aXRoIHVua25vd24geGNoZyBveF9pZCV4IHNpZCAlMnglMnglMnggZGlk
+ICUyeCUyeCUyeAoAAAAAAAAAAAAAAE5fUE9SVCAweCV4JXgleCByZWplY3RlZCBQTE9HSSB3aXRo
+IHJlYXNvbiBjb2RlICV4CgAAAAAAAAAAAAAAAABBQlRTIHdoaWxlIGF3YWl0aW5nIFBSTEkgUnNw
+OiBmbG93Y19pZCAweCV4IG94X2lkIDB4JXggcnhfaWQgMHgleCAKAAAAAAAAAAAAAAAAAEFCVFMg
+ZmFrZSBSc3A6IGxvYyAweCV4IG94X2lkIDB4JXggcnhfaWQgMHgleAoAAEZDIGZjYiBhbGxvYyBm
+YWlsZWQ6IGF2YWlsICVkCgAARkMgZmNiIGFsbG9jIHhpZDolZCBmbG93aWQgJWQKAABsbGRwX3J4
+X3BrdF9oYW5kbGVyWyV1XSBkcm9wIHByZS1pbml0IChjb3VudCA9ICV1KQoAAAAAAAAAAAAAAAAA
+JXgleCV4IFJlY2lldmVkIExPR08gZnJvbSAleCV4JXggCgAAAAAAAAAAAAAAAAAAY2Fubm90IGFs
+bG9jYXRlIFBPRkNPRSBmaWx0ZXIgY29ubmVjdGlvbiBmb3IgeF9pZCAleCAKAAAAAAAAAAAAAEZh
+aWxlZCB0byBwb3N0IHhjaGcgZXJyOiBzc25pIDB4JXggY29va2llIDB4JWx4IHJ2YWwgJXggCgAA
+AAAAAAB0Y3BfcmVsZWFzZV90aWQ6IHRpZCBbMHgleF0sIGZsb3djIGZsYWdzIFsweCV4XSwgYnVm
+ZmVyZWQgWzB4JXhdCgAAAAAAAAAAAAAAAAAAAHRjcF9yZWxlYXNlX3RpZDogc2l6ZW9mKHRjYl9m
+Yy0+Zmxvd2NfZm9pc2NzaV9jb25uKSBbJXVdLCBieXRlcwoAAAAAAAAAAAAAAAAAAAAAYWN0X29w
+ZW5fcnBsOiBhdGlkIFsweCV4XSwgdGlkIFsweCV4XSwgdGNiX2ZjLT57IGlkIFsweCV4XSwgc3Rh
+dGUgWzB4JXhdLCB0eXBlIFsweCV4XSB9LCBjcGxfb3AgWzB4JXhdLCBzdGF0dXMgWzB4JXhdCgAA
+AAAAAAAAAABhY3Rfb3Blbl9ycGw6IGNza19mYy0+eyBpZCBbMHgleF0sIHN0YXRlIFsweCV4XSwg
+Y3NvY2tfZmxhZ3MgWzB4JXhdIH0gCgAAAAAAAAAAAGFjdF9vcGVuX3JwbDogcmVjdmQgbmVnIGFk
+dmljZSBbMHgleF0KAAAAAAAAAAAAAHNlbmRfYWJvcnRfcnBsOiBjc2tfZmMtPmZsb3djX3R5cGUg
+WzB4JXhdLCBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgdGlkIFsweCV4XSwgdWxwdHhjaCBbJXVd
+LCBidWZmZXJlZCBbJXVdCgAAAAB3cmhfb2ZsZF90Y3BfY2xvc2VfY29uX3JlcGx5OiB0Y2JfZmMt
+PmZsb3djX2lkIFsweCV4XSwgdGNiX2ZjLT5mbG93Y190eXBlIFsweCV4XSwgbGVuMTYgWyV1XSwg
+bG9jIFsldV0KAAAAAAAAAAAAd3JoX29mbGRfdGNwX2Nsb3NlX2Nvbl9yZXBseTogcnBsLT5vcF9U
+aWQgWzB4JXhdLCBycGw+c3RhdHVzIFsweCV4XSwgcnBsLT5zbmRfbnh0IFsweCV4XSwgcnBsLT5y
+Y3Zfbnh0IFsweCV4XQoAAHRjcF9hYm9ydF9ycGxfcnNzOiB0aWQgWzB4JXhdLCBzdGF0dXMgWzB4
+JXhdCgAAAHRjcF9hYm9ydF9yZXFfcnNzOiB0aWQgWzB4JXhdLCBzdGF0dXMgWzB4JXhdCgAAAG9m
+bGRfYWJvcnRfcmVxX25lZ2FkdlsldV06IHdyIDB4JTA4eCBjcGxfYWJvcnRfcmVxIERFTElWRVJF
+RAoAAABob3N0X3dyWyV1XTogd3IgMHglMDh4IGNwbF9hYm9ydF9yZXEgc3RhdHVzIDB4JXgKAAAA
+AAAAAAAAAAAAAAAAcGt0c2NoZWRfY2xfcmxbJXU6JXVdOiBtb2RlIHwgdW5pdCB8IHJhdGUgMHgl
+MDZ4IG1pbiAldSBtYXggJXUgcGt0c2l6ZSAldQoAAAAAAABwYXJhbV9jaG5ldFsweCV4OjB4JXhd
+OiBjaG5ldCAweCV4IHJlYWQgJXUgcGYgJXUgcmV0ICVkCgAAAAAAAAAAcGFyYW1fZG1hcVsweCV4
+OjB4JXhdOiBkbWFxIDB4JXggcmVhZCAldSBwZiAldSByZXQgJWQKAAAAAAAAAAAAAE1DWyV1XSBp
+bml0X3N0YXRlX21hY2hpbmUgMHglMDJ4CgAAAAAAAAAAAAAAAAAAAE1DIGluaXRpYWxpemF0aW9u
+IG5vdCBjb21wbGV0aW5nLCBNQyBjdXJyZW50IGluaXQgc3RhdGUgaXMgMHglMDJ4CgAAAAAAAAAA
+AAAAAAAATUNbJXVdIF9od19tY19pbml0X21jCgAAAAAAAAAAAABwaHk6IGZhaWxlZCB0byBhbGxv
+Y2F0ZWQgbWVtb3J5IGZvciBwaHkgZncgZmlsZSwgcmV0ICVkCgAAAAAAAAAAaHdfbGVfZmlsdGVy
+X2N0dXBsZTogdHVwbGUgJXUgbm90IHNwZWNpZmllZCBidXQgcmVxdWlyZWQgZm9yIG1hc2sgMHgl
+eAoAAAAAAAAAAABod190cF90Y3Bfc2V0dGluZ3NfdzogdGltZXJfcnMgJXV1cyB0aW1lc3RhbXBf
+cmVzICV1dXMgZGVsYXllZGFja19yZXMgJXV1cwoAAAAAAGh3X3RwX3RjcF9zZXR0aW5nc193OiBk
+YWNrX3RpbWVyICV1dXMgbXNsICV1dXMgcnh0X21pbixtYXggJXUsJXV1cyBwZXJzX21pbixtYXgg
+JXUsJXV1cwoAAAAAAAAAAGh3X3RwX3RjcF9zZXR0aW5nc193OiBrZWVwX2lkbGUsaW50dmwgJXUs
+JXVzIG1heHJ0dCAldXVzIGluaXRzcnR0ICV1dXMgZmlud2FpdDJfdGltZXIgJXV1cwoAAAAAAGh3
+X3RwX3RjcF9zZXR0aW5nc193OiBjYXBwaW5nIGRhY2tfdGltZXIgZnJvbSAldSB0byAldQAAAAAA
+AAAAAABod190cF90Y3Bfc2V0dGluZ3NfdzogY2FwcGluZyBtc2wgZnJvbSAldSB0byAldQBod190
+cF90Y3Bfc2V0dGluZ3NfdzogY2FwcGluZyByeHRfbWluIGZyb20gJXUgdG8gJXUAAAAAAAAAAAAA
+AAAAaHdfdHBfdGNwX3NldHRpbmdzX3c6IGNhcHBpbmcgcnh0X21heCBmcm9tICV1IHRvICV1AAAA
+AAAAAAAAAAAAAGh3X3RwX3RjcF9zZXR0aW5nc193OiBjYXBwaW5nIHBlcnNfbWluIGZyb20gJXUg
+dG8gJXUAAAAAAAAAAAAAAABod190cF90Y3Bfc2V0dGluZ3NfdzogY2FwcGluZyBwZXJzX21heCBm
+cm9tICV1IHRvICV1AAAAAAAAAAAAAAAAaHdfdHBfdGNwX3NldHRpbmdzX3c6IGNhcHBpbmcga2Vl
+cF9pZGxlIGZyb20gJXUgdG8gJXUAAAAAAAAAAAAAAGh3X3RwX3RjcF9zZXR0aW5nc193OiBjYXBw
+aW5nIGtlZXBfaW50dmwgZnJvbSAldSB0byAldQAAAAAAAAAAAABod190cF90Y3Bfc2V0dGluZ3Nf
+dzogY2FwcGluZyBpbml0X3NydHRfbWF4cnR0IGZyb20gJXUgdG8gJXUAAAAAaHdfdHBfdGNwX3Nl
+dHRpbmdzX3c6IGNhcHBpbmcgaW5pdF9zcnR0X2luaXRzcnR0IGZyb20gJXUgdG8gJXUAAGh3X3Rw
+X3RjcF9zZXR0aW5nc193OiBjYXBwaW5nIGZpbndhaXQyX3RpbWVyIGZyb20gJXUgdG8gJXUAAAAA
+AABsZSBjb25maWd1cmF0aW9uOiBuZW50cmllcyAldSByb3V0ZSAldSBjbGlwICV1IGZpbHRlciAl
+dSBhY3RpdmUgJXUgc2VydmVyICV1IGhhc2ggJXUKAAAAAAAAAAAAAABsZSBjb25maWd1cmF0aW9u
+OiBuZW50cmllcyAldSByb3V0ZSAldSBjbGlwICV1IGZpbHRlciAldSBzZXJ2ZXIgJXUgYWN0aXZl
+ICV1IGhhc2ggJXUgbnNlcnZlcnNyYW0gJXUKAAAAAAAAAAAAAAAAaHdfc2dlX3F1ZXVlX2Jhc2Vf
+bWFwWyV1XTogZXhjZWVkZWQgbnVtYmVyIG9mIGVncmVzcyBxdWV1ZXMsICV1CgAAAAAAAAAAAAAA
+AAAAAABod19zZ2VfcXVldWVfYmFzZV9tYXBbJXVdOiBleGNlZWRlZCBudW1iZXIgb2YgaW5ncmVz
+cyBxdWV1ZXMgd2l0aCBmcmVlbGlzdCBhbmQgaW50ZXJydXB0LCAldQoAAABod19zZ2VfcXVldWVf
+YmFzZV9tYXBbJXVdOiBleGNlZWRlZCBudW1iZXIgb2YgaW5ncmVzcyBxdWV1ZXMsICV1CgAAAAAA
+AAAAAAAAAAAAAGNmX3BhcnNlOiBmaWxlIG1lbXR5cGUgMHgleCBtZW1hZGRyIDB4JXggbWFwcGVk
+IEAgJXA6CgAAAAAAAAAAAABjb25maWd1cmVkIHdpdGggY2FwcyBuYm18bGluayAweCUwOHggc3dp
+dGNofG5pYyAweCUwOHggdG9lfHJkbWEgMHglMDh4IGlzY3NpfGZjb2UgMHglMDh4CgAAAAAAAABu
+ZXQgVkkgYWxsb2NhdGlvbiBmYWlsZWQgZm9yIGZjX2lkICV1IHdpdGggZXJyb3IgJWQKAAAAAAAA
+AAAAAAAAbmV0IFZJIG1hYyBhZGRyZXNzIHByb2dyYW1taW5nIGZhaWxlZCBmb3IgZmNfaWQgJXUg
+d2l0aCBlcnJvciAlZAoAAAAAAAAAAAAAAAAAAABuZXQgVkkgcnhtb2RlIHByb2dyYW1taW5nIGZh
+aWxlZCBmb3IgZmNfaWQgJXUgd2l0aCBlcnJvciAlZAoAAAAAbmV0IFZJIHJzcyBpbmRpcmVjdGlv
+biB0YWJsZSBwcm9ncmFtbWluZyBmb3IgZmNfaWQgJXUgZmFpbGVkIHdpdGggZXJyb3IgJWQKAAAA
+AABuZXQgVkkgcnNzIGNvbmZpZyBjb21tYW5kIGZhaWxlZCBmb3IgZmNfaWQgJXUgd2l0aCBlcnJv
+ciAlZAoAAAAAbmV0IFZJIGNvbW1hbmQgZmFpbGVkIGZvciBmY19pZCAldSB3aXRoIGVycm9yICVk
+CgAAAAAAAAAAAAAAAAAAAHByb2dyYW1tZWQgSFcgdGFnbSBbMHglMDh4XSwgSFcgcGdzeiBmYWN0
+b3IgWzB4JTA4eF0sIEZPaVNDU0kgdGFnbSBbMHglMDh4XSwgcnRhZ20gWzB4JTA4eF0sIG1heHN6
+X2JpdHMgWyV1XSwgc3pfYml0cyBbJXVdLgoAAAAAYmFzZSBbIDB4JTA4eF0sIGxsaW1pdCBbMHgl
+MDh4XSwgdWxpbWl0IFsweCUwOHhdLCBzaXplIFsldV0sIG1heF90eHN6IFsldV0sIG1heF9yeHN6
+IFsldV0sIGlvc2l6ZSBbJXVdCgAAAAAAAAAAAG5wcG9kcyBbJXVdLCBpZHhfbWFzayBbMHglMDh4
+XSwgaWR4X2ZpcnN0IFsldV0sIGlkeF9sYXN0IFsldV0sIHNjc2lfcGxkX3NpemUgWyV1XSwgQUxJ
+R04oc2NzaV9wbGRfc2l6ZSwgMTYpIFsldV0sIHBwZF96b25lcyBbJXVdLgoAAAAAAAAAAAAAAAAA
+AGZvaXNjc2lfaW5pdDogZm9pc2NzaV9pbml0X2RvbmUgWyV1XSwgZGV2LnJlcy5mb2lzY3NpX250
+YXNrcyBbJXVdLCBkZXYucmVzLmZvaXNjc2lfbnNlc3MgWyV1XSwgZGV2LnJlcy5uY3NvY2sgWyV1
+XSwgZGV2LnJlcy5mb2lzY3NpX25pbml0IFsldV0sIHJjIFslZF0KAAAAAAAAAABjaF9jbF9yYXRl
+WyV1LyV1XTogY2FwcGVkIGNsYXNzIHJhdGUgZnJvbSByZXF1ZXN0ZWQgJXUgdG8gY29uZmlndXJl
+ZCAoZWZmZWN0aXZlKSBjaGFubmVsIHJhdGUgJXUKAAAAAAAAAAAAAAAAAAAAY2hfY2xfcmF0ZVsl
+dS8ldV06IGluY3JlYXNlZCBkZWZpY2l0X2luY3IgZnJvbSByZXF1ZXN0ZWQgJXUgdG8gcmVxdWly
+ZWQgbWluIG9mICV1OyByYXRlICV1IChlZmYgJXUpIGRlZmljaXRfbWF4ICV1CgAAAAAAAAAAAAAA
+AABwa3RzY2hlZCBjaGFubmVsICV1IHNldHMgc3BlZWQgKGZyb20gJXUpIHRvICV1IGticHMKAAAA
+AAAAAAAAAAAAbmV0X2wyZGV2X25vdGlmeTogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgcG9y
+dCBbJWRdLCBldmVudCBbMHgleF0sIHVscHR4Y2ggWyV1XSwgY2xhc3MgWzB4JXhdLCB2cHJpbyBb
+MHgleF0sIHZpZCBbMHgleF0sIHZpX3JlYWR5IFsldV0KAAAAAAAAbmV0X2wyZGV2X25vdGlmeTog
+cGdpZCBbMHgleF0sIHByaW8gWzB4JXhdLCBjaCBbMHgleF0KAAAAAAAAAAAAAGZjb2Ugbm90aWZ5
+IDogRkNvRSBMSU5LVVA6IHBvcnQgMHgleCwgZXZlbnQgMHgleAoAAAAAAAAAAAAAAAAAAABmY29l
+IG5vdGlmeSA6IEZDb0UgTElOS0RPV046IHBvcnQgMHgleCwgZXZlbnQgMHgleAoAAAAAAAAAAAAA
+AAAAZmNvZSBub3RpZnkgOiBEQ0JYIDogcG9ydCAweCV4LCBwcmlvcml0eSAweCV4IHVscHR4Y2gg
+MHgleCBjbGFzcyAweCV4CgAAAAAAAAAAAABkY2J4X3RpbWVvdXRbJXVdCgAAAAAAAAAAAAAAAAAA
+AHBvcnRfY21kX2hhbmRsZXI6IHVua25vd24gdS5kY2IudHlwZSAweCV4CgAAAAAAAHBvcnRbJXVd
+IGxpbmsgZG93biAoJXUpIChsc3RhdHVzICUjeCkKAAAAAAAAAAAAAGkyYyBlcnJvciBjYXVzZWQg
+YnkgbW9kdWxlIHVucGx1ZwoAAAAAAAAAAAAAAAAAAHNlbmR0byBwZW5kaW5nOiB3cl9wZW5kICVw
+IGZvciBwb3J0ICV1LCB3YW50IHRvIHNlbmQgdG8gcG9ydCAldQoAAAAAAAAAAAAAAAAAAAAAcG9y
+dFsldV0gdXBkYXRlIChmbG93Y2lkICV1IHJjICV1KQoAAAAAAAAAAAAAAAAAcG9ydF9zZXRfbG9v
+cGJhY2sgcG9ydCAlI3ggY3VycmVudCAlI3ggbW9kZSAlI3gKAAAAAAAAAAAAAAAAAAAAAHBvcnRb
+JXVdIHNwZWVkIHVwZGF0ZTogJSN4CgAAAAAAcG9ydFsldV0gYmVnaW5uaW5nIGRlYm91bmNlCgAA
+AABwb3J0X2xpbmtfc3RhdGVfaGFuZGxlclsldV0gcG93ZXJpbmcgZG93bgoAAAAAAABwb3J0X2xp
+bmtfc3RhdGVfaGFuZGxlclsldV0gcG93ZXJpbmcgdXAKAAAAAAAAAABwb3J0X2xpbmtfc3RhdGVf
+aGFuZGxlclsldV0gdW5rbm93biBzdGF0ZSAoc3RhdGUgPSAlI3gpCgAAAAAAAAAAcG9ydF9saW5r
+X3N0YXRlX2hhbmRsZXI6IFNvbWV0aGluZyB3ZW50IHRlcnJpYmx5IHdyb25nLiByZXQgPSAlZAoA
+AAAAAAAAAAAAAAAAAABsZSBpbml0aWFsaXphdGlvbjogbmVudHJpZXMgJXUgcm91dGUgJXUgY2xp
+cCAldSBmaWx0ZXIgJXUgYWN0aXZlICV1IHNlcnZlciAldSBoYXNoICV1CgAAAAAAAAAAAABsZSBp
+bml0aWFsaXphdGlvbjogbmVudHJpZXMgJXUgcm91dGUgJXUgY2xpcCAldSBmaWx0ZXIgJXUgc2Vy
+dmVyICV1IGFjdGl2ZSAldSBoYXNoICV1IG5zZXJ2ZXJzcmFtICV1CgAAAAAAAAAAAAAAaHdfdHBf
+aW5pdDogdGNiIHJlZ2lvbiAoc3RhcnQgMHglMDhzIHNpemUgJXUpIG11c3QgYmUgaW4gZmlyc3Qg
+MjU2TUIgb2YgTUEgbWVtb3J5CgAAAAAAAAAAAAAAAAAAaHdfdHBfaW5pdDogcGdtbmd0IHJlZ2lv
+biAoc3RhcnQgMHglMDhzIHNpemUgJXUpIG11c3QgYmUgaW4gZmlyc3QgMjU2TUIgb2YgTUEgbWVt
+b3J5CgAAAAAAAAAAAAAAaHdfdHBfaW5pdDogVFAgcGdtbmd0IGluaXRpYWxpemF0aW9uIGRpZCBu
+b3QgY29tcGxldGUKAAAAAAAAAAAAAGJ1Zm1faW5pdDogbiAldSBidWZsbDY0aW50X3NpemUgMHgl
+eAoAAAAAAAAAAAAAAGJ1Zm1faW5pdDogbm90IGVub3VnaCBtZW1vcnkgdG8gYWxsb2NhdGUgaW50
+ZXJuYWwgYnVmbGw2NCBidWZmZXJzCgAAAAAAAAAAAAAAAAAAYnVmbV9pbml0OiBub3QgZW5vdWdo
+IG1lbW9yeSB0byBhbGxvY2F0ZSBidWZsbDY0IGJ1ZmZlcnMKAAAAAAAAAG1lbV9pbml0X2J1Zjog
+bm90IGVub3VnaCBtZW1vcnkgdG8gYWxsb2NhdGUgZmxvdyBidWZmZXJzCgAAAAAAAABtZW1faW5p
+dF9idWY6IG5vdCBlbm91Z2ggbWVtb3J5IHRvIGFsbG9jYXRlIHRjYl9jYWNoZSAob2ZmZXJlZCAl
+dSB0cnlpbmcgdG8gdXNlICV1IGF2YWlsYWJsZSAldSkKAAAAAAAAAAAAAAAAAAAAbXBhcnRpdGlv
+bl9vdGhlcnM6IHN0YXJ0IDB4JTA4eCBzaXplICV1ICh1bnVzZWQgJXUpCgAAAAAAAAAAAAAAAG1w
+YXJ0aXRpb25fb3RoZXJzOiBzdGFydCAweCUwOHggc2l6ZSAldSAodW51c2VkICV1KQoAAAAAAAAA
+AAAAAABtZW1faW5pdDogRURDIG92ZXJjb21taXR0ZWQgYnkgJWQgYnl0ZXMKAAAAAAAAAABtZW1f
+aW5pdDogbm90IGVub3VnaCBtZW1vcnkgdG8gYWxsb2NhdGUgZmxvdyB0YWJsZQoAAAAAAAAAAAAA
+AAAAY3hjbmljX2RldmljZV9pbml0OiBjeGNuaWMgWzB4JTB4XSwgY3hjbmljLT5maWx0ZXIgWyUw
+eF0KAAAAAAAAAHBvZmNvZSBpbml0IGRvbmUKAAAAAAAAAAAAAAAAAAAAUG9ydFsldV06IFVua25v
+d24gU0dNSUkgc3ViLXR5cGUgJSN4CgAAAAAAAAAAAAAAUG9ydFsldV06IFVua25vd24gQlRfWEZJ
+IHN1Yi10eXBlICUjeAoAAAAAAAAAAAAAUG9ydFsldV06IFVua25vd24gQlRfWEFVSSBzdWItdHlw
+ZSAlI3gKAAAAAAAAAAAAcG9ydF9pbml0WyV1XTogcG9ydCB0eXBlIDB4JXggaXMgbm90IHN1cHBv
+cnRlZAoAbXBhcnRpdGlvbl9pbml0OiBtb3ZlZCBwbXJ4X3N0YXJ0IGZyb20gMHglMDh4IHRvIDB4
+JTA4eCB0byBtYWtlIHJvb20gZm9yIExFIEhBU0ggYW5kL29yIFRQIFRDQnMKAAAAAAAAAAAAAAAA
+AAAAAG1wYXJ0aXRpb25faW5pdDogbW92ZWQgcG1yeF9zdGFydCBmcm9tIDB4JTA4eCB0byAweCUw
+OHggKEVEUkFNKQoAAAAAAAAAAAAAAAAAAAAARVEgcGZuICV1IHZmbiAldTogZGVzdHJveWluZyBl
+cWlkICV1IHdpdGggcGVuZGluZyBXUihzKSAobnVtX2J5dGVzICV1IGFuZCBmbGFncyAweCUwOHgK
+AAAAAAAAAAAAbDJkZXZfZmMtPmZsb3djX2lkIFsldV0sIGwyZGMtPnBmbiBbJXVdLCBsMmRjLT52
+Zm4gWyV1XSwgbDJkYy0+bHBvcnQgWyV1XSwgbDJkZXZfZmMtPmZsb3dpZCBbJXVdIGwyZGMtPnR4
+X2NoIFsldV0sIGRldi52cGQucG9ydHZlYyBbJXhdCgAAAAAAAAAAcG9ydHZlYyBbJXVdCgAAAGwy
+ZGV2X3ZpX2ZzbTogbWIgWzB4JXhdLCBkZWZlcnJlZCwgc3RhdGUgWzB4JXhdLCBwb3J0IFsweCV4
+XQoAAABsMmRldl92aV9mc206IHZpaWQgWzB4JXhdIHBvcnQgWzB4JXhdLCBtYWMtaWQgWyUwMng6
+JTAyeDolMDJ4OiUwMng6JTAyeDolMDJ4XS4gCgAAAAAAAAAAAAAAAAAAAABsMmRldl92aV9mc206
+IHNnZV9lcWlkIFsweCV4XSwgc2dlX2lxaWQgWzB4JXhdLCBzZ2VfZXFjciBbMHgleF0sIHJzc19z
+eiBbMHgleF0KAGwyZGV2X3ZpX2ZzbTogbDJkZXZfZmMtPmZsb3djX25ldF9sMmRldl9tdHUgWyV1
+XSwgbWJfc2NyYXRjaCBbMHgleF0sIHBvcnQgWzB4JXhdCgAAAAAAAAAAAAAAAAAAAGwyZGV2X3Zp
+X2ZzbTogdmlpZCBbJWRdLCB2aV9mYy0+Zmxvd2NfdmlfZmxhZ3MgWzB4JXhdCgAAAAAAAAAAAABs
+MmRldl92aV9mc206IHBmbiBbMHgleF0sIHZmbiBbMHgleF0sIGwyZGV2X2ZjLT5mbG93Y19pZCBb
+MHgleF0sIGxwb3J0IFsweCV4XSwgdmlpZCBbMHgleF0sIGZsYWdzIFsweCV4XQoAAAAAAAAAbDJk
+ZXZfdmlfZnNtOiBFcnJvciBmcmVlaW5nIFZJLCByYyBbMHgleF0KAAAAAAAAbDJkZXZfdmlfZnNt
+OiBwaWQgWzB4JXhdLCB2aWlkIFsweCV4XSwgbWJfbG9jIFsweCV4XSwgbWJfb3JpZ1sweCV4XSwg
+bDJkZXZfZmxhZ3MgWzB4JXhdLCByYyBbMHgleF0KAAAAAAAAAAAAAAAAAEFoIGhhLi4uZG91Ymxl
+IGZyZWUgb3hfaWQgMHgleCwgcnhfaWQgMHgleAoAAAAAAEhvc3QgUFJMSSBSZXNwb25zZSB0aW1l
+ZG91dDogb3hfaWQgMHgleCByeF9pZCAweCV4CgAAAAAAAAAAAAAAAABGQ09FIEZyZWU6IHN0aWxs
+IHlpZWxkZWQgd2hlbiBmcmVlaW5nLi4uZmxvd2NfaWQgJXggZmxvd2NfZmxhZ3MgJXggCgAAAAAA
+AAAAAAAAAEZDIHhjaGcgZnJlZSB4aWQ6JWQgZmxvd2lkICVkCgAAcGZuICV1IHZmbiAldSB2aWEg
+Y29tbWFuZAoAAAAAAABzY2hlZF9pb3F0eF9icF9wcmlvcml0eTogaGFzICV1IGVudHJpZXMgb25s
+eSwgcmVxdWlyZXMgJXUgZW50cmllcwoAAAAAAAAAAAAAAAAAAHRwX2JhY2tvZmY6IHBhcnNlZCAl
+ZCBpbnN0ZWFkIG9mICV1IGVudHJpZXMKAAAAAHRwX3RpbWVydmFsczogcGFyc2VkICVkIGluc3Rl
+YWQgb2YgJXUgZW50cmllcwoAAHRwX3RpbWVycmVzOiBwYXJzZWQgJWQgaW5zdGVhZCBvZiAldSBl
+bnRyaWVzCgAAAHRwX210dXMgaGFzICV1IGVudHJpZXMgb25seSwgcmVxdWlyZXMgJXUgZW50cmll
+cwoAAAAAAAAAAAAAAAAAAAB0cF9tdHVzWyV1XSBpcyAldSBieXRlcyB3aGljaCBpcyBub3Qgc3Vw
+cG9ydGVkCgBjb25maWd1cmF0aW9uIGZpbGUgcGFyc2VyOiBzZ2UgdGltZXIgdmFsdWVbJWldIGlz
+IHRvbyBsYXJnZSwgY2hhbmdpbmcgZnJvbSAldSB0byAldXVzZWNzCgAAAAAAAABmaWx0ZXJtYXNr
+IDB4JXggaXMgbm90IGVxdWFsL3N1YnNldCB0by9vZiBmaWx0ZXJtb2RlCgAAAAAAAAAAAAAAaHdf
+bGVfY2xpcF9oYW5kbGVyOiByZW1vdmVkIHBvcz0ldSAoPWlkeCAldSkKAAAAaHdfbGVfY2xpcF9o
+YW5kbGVyOiBhZGRpbmcgdG8gcG9zPSV1ICg9aWR4ICV1KQoAbW9kdWxlWyV1XTogcG9ydCBtb2R1
+bGUgaW5zZXJ0ZWQgYW5kIHJlYWR5CgAAAAAAbW9kdWxlWyV1XTogcG9ydCBtb2R1bGUgcmVtb3Zl
+ZAoAAAAAAAAAAAAAAAAAAAAAbW9kdWxlWyV1XTogdW5rbm93biBtb2R1bGUgaWRlbnRpZmllciAw
+eCUwMngKAAAAbW9kdWxlWyV1XTogZ3BpbyAldSB0cmFucyAxMEcgMHglMDJ4IDFHIDB4JTAyeCAo
+bGVuZ3RoICV1KSBjYWJsZSAweCUwMnggKGxlbmd0aCAldSkgbW9kdWxlX3R5cGUgMHglMDJ4CgAA
+AAAAAAAAAG1vZHVsZVsldV06IGdwaW8gJXUgdHJhbnMgMTBHIDB4JTAyeCAxRyAweCUwMnggKGxl
+bmd0aCAldSkgY2FibGUgMHglMDJ4IChsZW5ndGggJXUpIG1vZHVsZV90eXBlIDB4JTAyeAoAAAAA
+AAAAAABmbHJfcGZ2Zl9mc21bJXU6JXVdOiB1bmtub3duIHN0YXRlICV1CgAAAAAAAAAAAABodyBw
+ZiBiaXRtYXAgMHglMDJ4IHZmaWQgYml0bWFwIDB4JTA4eDoweCUwOHg6MHglMDh4OjB4JTA4eAoA
+AAAAYWZ0ZXIgdmZpZCBmaXh1cCwgdmZpZCBiaXRtYXAgMHglMDh4OjB4JTA4eDoweCUwOHg6MHgl
+MDh4CgAAAAAAAHRpbWVyIHF1ZXVlICV1IGxvc3QgYSB0aWNrISBuZXh0ICVwIGxhc3QgJXAgbnVt
+ZSAldQoAAAAAAAAAAAAAAABmbHJfdGltZXJfc3RhcnQ6IGZsb3djX2lkICV1ICVwIGJ1ZiAlcAoA
+AAAAAAAAAABwY2llOiBucGYgJXUgKHBmYml0bWFwIDB4JTAyeCkgbnZmICV1IChwZiAwLi43IDB4
+JTA4eCUwOHgpIHZmc3RyaWRlICV1CgAAAAAAAAAAAGZhaWxlZCB0byBmaW5kIHRoZSAlYyVjIFZQ
+RCBwYXJhbWV0ZXIKAAAAAAAAAAAAAGZhaWxlZCB0byBwYXJzZSB0aGUgJWMlYyBWUEQgcGFyYW1l
+dGVyCgAAAAAAAAAAAGZhaWxlZCB0byBzdWNjZXNzZnVsbHkgZmluZCBDaGVsc2lvIFZQRAoAAAAA
+AAAAAGxvZyBpbml0aWFsaXplZCBAIDB4JTA4eCBzaXplICV1ICgldSBlbnRyaWVzKSBmd3JldiAw
+eCUwOHggcGNpZV9mdyAweCUwOHgKAAAAAAAAZ2F0aGVyX3Rhc2tzX2Zvcl90bWY6IGlkeCBbMHgl
+eF0sIHRhc2staWQgWzB4JXhdLCBjbWQtaWQgWzB4JXhdLCBhY3RpdmUgdGFza3MgWzB4JXhdLiBj
+b25uLWlkIFsweCV4XSwgY21kIGNvbm4taWQgWzB4JXhdLCB0YXNrIGNvbm4taWQgWzB4JXhdCgAA
+Z2F0aGVyX3Rhc2tzX2Zvcl90bWY6IEludmFsaWQgdHlwZSBbMHgleF0sIGJhaWxpbmcgb3V0LgoA
+AAAAAAAAAGdhdGhlcl90YXNrc19mb3JfdG1mOiB0YXNrIGlkIFsweCV4XSwgc3RhdGUgWzB4JXhd
+LCBsaWR4IFsweCV4XSwgY29va2llIGhpIFsweCUwOHhdIDogbG8gWzB4JTA4eF0KAAAAAAAAAAAA
+AAAAAABnYXRoZXJfdGFza3NfZm9yX3RtZjogcmMgWzB4JXhdLCBbMHgleF0gdGFzayBnYXRoZXJl
+ZCBmb3IgdG1mIHR5cGUgWzB4JXhdIHByb2Nlc3NpbmcuCgAAAAAAAAAAAABzY3NpX2RhdGFfb3V0
+OiBjb25uX2ZjIFsweCV4XSwgc3RhdGUgWzB4JXhdLCBzZXNzX2ZjIFsweCV4XSBpbiByZWNvdmVy
+eS4gU2tpcHBpbmcgaXN0YXNrX2ZjIFsweCV4XSBmcm9tIFRYLgoAAAAAc2VuZF9hYm9ydF9yZXE6
+IGNza19mYy0+Zmxvd2NfdHlwZSBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCB0aWQg
+WzB4JXhdLCB1bHB0eGNoIFsldV0sIGJ1ZmZlcmVkIFsldV0KAAAAAGh3IHJlZ2lzdGVyIG9wZXJh
+dGlvbiBub3QgY29tcGxldGluZywgcmVnIDB4JTA4eCBtYXNrIDB4JTA4eCB2YWx1ZSAweCUwOHgg
+KHJlZyAweCUwOHgpCgAAAAAAAAAAAE1ESU8gQ0w0NTogZmFpbGVkIHRvIHNldCB1cCBNTUQgYWRk
+cgoAAAAAAAAAAAAAAE1ESU86IGZhaWxlZCB0byB3cml0ZQoAAAAAAAAAAAAATURJTyBDTDQ1OiBm
+YWlsZWQgdG8gc2V0IHVwIE1NRCBhZGRyCgAAAAAAAAAAAAAATURJTzogZmFpbGVkIHRvIHJlYWQK
+AAAAAAAAAAAAAAAJQVFfVGFrZUNvbnRyb2xPZkZMQVNIOiAxZS5jMDAxPSUjeCAxZS5jNDUwPSUj
+eCAxZS5jNDUxPSUjeCAxZS4xMDA9JSN4CgAAAAAAAAAAAEFRX0FQSV9Xcml0ZUFuZFZlcmlmeUZs
+YXNoSW1hZ2UgLSBJbWFnZSBpbnRlZ3JpdHkgY2hlY2sgZmFpbGVkIChjYWxjICUjeCB2YWwgJSN4
+KQoAAAAAAAAAAAAAAAAAAEFRX0FQSV9Xcml0ZUFuZFZlcmlmeUZsYXNoSW1hZ2UgLSBJbWFnZSBp
+bnRlZ3JpdHkgY2hlY2sgcGFzc2VkCgBBUV9BUElfV3JpdGVBbmRWZXJpZnlGbGFzaEltYWdlIC0g
+VGltZW91dCB3YWl0aW5nIGZvciBmbGFzaCBpbnRlcmZhY2UgKCV1KQoAAAAAAEFRX0FQSV9Xcml0
+ZUFuZFZlcmlmeUZsYXNoSW1hZ2UgLSBUaW1lb3V0IHdhaXRpbmcgZm9yIGZsYXNoIGludGVyZmFj
+ZSAoJXUpCgAAAAAAQVFfQVBJX1dyaXRlQW5kVmVyaWZ5Rmxhc2hJbWFnZSAtIFRpbWVvdXQgd2Fp
+dGluZyBmb3IgZmxhc2ggaW50ZXJmYWNlICgldSkKAAAAAABBUV9BUElfV3JpdGVBbmRWZXJpZnlG
+bGFzaEltYWdlIC0gVGltZW91dCB3YWl0aW5nIGZvciBmbGFzaCBpbnRlcmZhY2UgKCV1KSAocHAg
+JSN4IGFwICUjeCkKAAAAAABBUV9BUElfV3JpdGVBbmRWZXJpZnlGbGFzaEltYWdlIC0gVGltZW91
+dCB3YWl0aW5nIGZvciBmbGFzaCBpbnRlcmZhY2UgKCV1KQoAAAAAAEFRX0FQSV9Xcml0ZUFuZFZl
+cmlmeUZsYXNoSW1hZ2UgLSBUaW1lb3V0IHdhaXRpbmcgZm9yIGZsYXNoIGludGVyZmFjZSAoJXUp
+CgAAAAAAQVFfQVBJX1dyaXRlQW5kVmVyaWZ5Rmxhc2hJbWFnZSAtIEVycm9yIG9uIGJ1cm5pbmcg
+RkxBU0ggKGNyYzE2IG1pc21hdGNoKQoAAAAAAABzZW5kX2Nsb3NlX3JlcTogY3NrX2ZjLT5mbG93
+Y190eXBlIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+dGNiX3N0YXRl
+IFsweCV4XQoAAABzZW5kX2Nsb3NlX3JlcTogY3NrX2ZjLT5mbG93Y190eXBlIFsweCV4XSwgY3Nr
+X2ZjLT5mbG93Y19pZCBbMHgleF0sIHRpZCBbMHgleF0sIHVscHR4Y2ggWyV1XSxidWZmZXJlZCBb
+JXVdCgAAAAAAb2ZsZF90Y3BfZG9fYWN0aXZlX2Nsb3NlOiBjc2tfZmMgWzB4JXhdLCBjc2tfZmMt
+PmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT50Y2Jfc3RhdGUgWzB4JXhdCgAAAAAAb2ZsZF90Y3Bf
+ZG9fYWN0aXZlX2Nsb3NlOiBjc2tfZmMgWzB4JXhdLCBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwg
+Y3NrX2ZjLT50Y2Jfc3RhdGUgWzB4JXhdCgAAAAAAb2ZsZF90Y3BfZGlzY29ubmVjdDogdGNiX2Zj
+LT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2stPnRjYl9zdGF0
+ZSBbMHgleF0KAAAAZGVjb2RlX2Jhc2U2NF9zdHJpbmc6IGRsZW4gWyVkXQoAAAAAAAAAAAAAAAAA
+AAAAZGVjb2RlX2hleF9zdHJpbmc6IGRsZW4gWyVkXQoAAABmb2lzY3NpX3ZhbGlkYXRlX2xvZ2lu
+X3N0YWdlOiAtIDEKAAAAAAAAAAAAAAAAAABhc3luY19wZHU6IGxvZ291dCByZXF1ZXN0ZWQgYmxv
+Y2tpbmcgc2Vzc2lvbgoAAABhc3luY19wZHU6IHNlc3MvY29ubiBkcm9wIHJlcXVlc3RlZCBibG9j
+a2luZyBzZXNzaW9uCgAAAAAAAAAAAAAAY3BsX3R4X3BrdDogdmxhbmlkIFsweCV4XQoAAAAAAABu
+ZXRfbDJkZXZfZmluZF9ieV9hZGRyOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBsMmRjLT5s
+cG9ydCBbJXVdLCBsMmRfZmMtPmZsb3djX2lkIFsweCV4XSwgbDJkYy0+aW40X2Rldi5pbl9hZGRy
+LmFkZHIgWzB4JXhdLCBhZGRyIFsweCV4XQoAAABuZXRfbDJkZXZfbXR1X2NvbmZpZzogbDJkZXZf
+ZmMtPmZsb3djX2lkIFsweCV4XSwgbXR1ICV1CgAAAAAAAAAAY3BsX3R4X3BrdDogdmxhbmlkIFsw
+eCV4XQoAAAAAAABlbmNvZGUgaGV4IHN0cmluZzogZGxlbiBbJWRdCgAAAGNobmV0X2ZpbmRfbDJ0
+X2VudHJ5OiBkYWRkciBbJTA4eF0sIFsweCUwOHhdLCBsb2NhbCBuZXR3b3JrIFslZF0KAAAAAAAA
+AAAAAAAAAAAAbDJ0ZW50IFslMHhdLCBsMnRlbnQtPmlkeCBbJWRdCgB0Y3Bfc2VuZF9hb3Blbl9y
+ZXE6IGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwg
+YnVmZmVyZWQgWyV1XSwgcmVzX2NudCBbMHgleF0sIGlxX2lkeCBbMHgleF0KAAAAAAAAAAAAAHRj
+cF9zZW5kX2FvcGVuX3JlcTogY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2Nf
+c3RhdGUgWzB4JXhdLCBubyB2YWxpZCBsMnRfZW50eS4gRGVsYXlpbmcgYW5vdGhlciByZXRyeSBm
+b3IgMSBzZWNvbmRzLgoAAAAAAAAAAAAAAAAAAGFvcGVuX3JlcTogaHdfbGVfZmlsdGVyX2N0dXBs
+ZSBmYWlsZWQKAAAAAAAAAAAAAG9mbGRfdGNwX3NlbmRfYW9wZW5fcmVxOiBjcGxfcmVxLT5GaWx0
+ZXIgWzB4JTB4XSwgY3R1cGxlc1swXSBbMHgleF0sIGN0dXBsZXNbMV0gWzB4JXhdCgAAAAAAAAAA
+AGNzb2NrX2FsbG9jOiB0eF9jaCBbMHgleF0sIGxwb3J0IFsweCV4XSwgY29va2llIFslMDh4XQoA
+AAAAAAAAAABjc29ja19hbGxvYzogYXZhaWxhYmxlIFsldV0sIG5jc29jayBbJXVdLCBwb3M6YXRp
+ZCBbMHgleF0sIGNza19mYyBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBzcG9ydCBb
+JXVdCgAAV0FUQ0hET0c6IE5vIHRlbXBlcmF0dXJlIHNlbnNvciBhdmFpbGFibGUuCgAAAAAAd2F0
+Y2hkb2cgY21kIHJlZnJlc2ggKGFjdGlvbiAldSkKAAAAAAAAAAAAAAAAAAAAV0FUQ0hET0c6IEFj
+dGl2YXRpbmcKAAAAAAAAAAAAAABXQVRDSERPRyAtIEVuYWJsZSBhY3Rpb24gJXUgdGltZSAldQoA
+AAAAAAAAAAAAAABXQVRDSERPRyAtIERpc2FibGUgYWN0aW9uICV1CgAAAFdBVENIRE9HOiBEZS1h
+Y3RpdmF0aW5nCgAAAAAAAAAAcG9ydFsldV0gc2V0IFBBVVNFIFBBUkFNUzogcHBwZW4gJXUgdHhw
+ZSAlI3ggcnhwZSAlI3gKAAAAAAAAAAAAAG1wc19saW5rX3VwWyV1XSBhY2FwcyAlI3ggKDgwMi4z
+ICUjeCkgKyBscGFjYXBzICUjeCA9PiAlI3gKAAAAAABmb2lzY3NpIGNvbm5fZmMgWzB4JXhdLCBm
+bG93Y19zY2hlZGNsIFsweCV4XSwgaW5nX2NoIFsweCV4XSwgZWdyX2NoIFsweCV4XQoAAAAAAGwy
+ZGV2X25vdGlmeSB3aXRoIHVua25vd24gZmxhZyBbMHgleF0KAAAAAAAAAAAAAEZDb0UgRkNCIGxp
+bmtkb3duOiBpb19yZXEgMHgleCV4IGlxaWQgMHgleCBmbG93aWQgMHgleCBvcCAweCV4CgBjYW5j
+ZWwgZmNiOiV4IHNjYjoleCBzdGF0ZToleAoAAFJERVYgbXNnIGZsb3djOiV4IHN0YXRlIDB4JXgg
+ZXZlbnQgMHgleAoAAAAAAAAAAHZuMnZuOiBwb3J0IDB4JXggZGlkOjB4JXgleCV4IFVQCgAAAAAA
+AAAAAAAAAAAAAHZuMnZuOiBwb3J0IDB4JXggZGlkOjB4JXgleCV4IERPV04KAAAAAAAAAAAAAAAA
+AGZjX3NlbmRfYWxsb2NfY3BsOiBmYWlsZWQgdG8gc2V0dXAgZmlsdGVyIGN0dXBsZQoAAAAAAAAA
+AAAAAAAAAABmY29lX2NvbXB1dGVfY3R1cGxlIDB4JXg6JXgKAAAAAGNvbXB1dGVfY3R1cGxlKCk6
+IGZhaWxlZCB0byBzZXR1cCBmaWx0ZXIgY3R1cGxlCgAAAAAAAAAAAAAAAAAAAABmY29lX2NvbXB1
+dGVfY3R1cGxlIHZsYW4gJXggdmlpZCAleCBwb3J0ICV4IG1wc19pZHggJXgKAAAAAAAAAAAAQXBw
+bHkgQVBQOiBwb3J0ICVkIHByaW9yICVkIHNlbGVjdCAlZCBwcm90b2NvbElEIDB4JTA0eAoAAAAA
+AAAAAGNoX2NsX3JhdGVbJXUvJXVdOiBjYXBwZWQgZGVmaWNpdF9pbmNyIGZyb20gcmVxdWlyZWQg
+JXUgdG8gJXU7IHJhdGUgJXUgKGVmZiAldSkgZGVmaWNpdF9tYXggJXUKAGZjX3NlbmRfYWxsb2Nf
+Y3BsOiBmYWlsZWQgdG8gc2V0dXAgZmlsdGVyIGN0dXBsZQoAAAAAAAAAAAAAAAAAAABmY29lX2Nv
+bXB1dGVfY3R1cGxlIDB4JXg6JXgKAAAAAGNvbXB1dGVfY3R1cGxlKCk6IGZhaWxlZCB0byBzZXR1
+cCBmaWx0ZXIgY3R1cGxlCgAAAAAAAAAAAAAAAAAAAABGQ29FIEZDRiB0aW1lcjogZmxvd2Mgc3Rh
+dGUgMHgleCwgcG9ydCAweCV4ICxmY2YgMHgleCwgZmxvd2NfaWQgMHgleAoAAAAAAAAAAAAAAHdv
+cmthcm91bmQxMzcyMzogZGV0ZWN0ZWQgV1IgQCAweCUwOHggb2Ygc2l6ZSAldSBieXRlcywgZHJp
+YmJsaW5nIGl0IGluICV1IGJ5dGVzIGF0IGEgdGltZQoAAAAAAHJpX3dyX2luaXRbJXVdOiBtc3Mg
+JXUgaXMgbm90IDgtYnl0ZSBhbGlnbmVkCgAAAGNvcmVfcHJvZ3JhbV90Y2I6IHRpZCAlI3ggdF9z
+dGF0ZSAlI3ggcmN2X2FkdiAweCUwOHggcmN2X3NjYWxlICUjeCB0eF9tYXggJSN4IHJjdl9ueHQg
+JSN4IGF0aWQgJSN4CgAAAAAAAAAAAAAAAAAJb3B0MCAlI3gleCBvcHQyICUjeCBpcHY2ICUjeCBm
+bGFnc190aW1lciAweCUwOHgKAAAAAAAAAAAAAAAAAAAAb2ZsZF9jb25uZWN0aW9uX3dyOiBjb25u
+ZWN0aW9uIHdpdGggNS10dXBsZSBscCAweCUwNHggZnAgMHglMDR4IGxpcCAweCUwOHglMDh4IHBp
+cCAweCUwOHglMDh4IGZpbHRlciAweCUwOHggZXhpc3RzIEAgTEUgaW5kZXggJXUKAAAAAAAAAAAA
+AAAAAAAAb2ZsZF9jb25uZWN0aW9uX3dyOiBjb25uZWN0aW9uIHdpdGggNS10dXBsZSBscCAweCUw
+NHggZnAgMHglMDR4IGxpcCAweCUwOHggcGlwIDB4JTA4eCBmaWx0ZXIgMHglMDh4IGV4aXN0cyBA
+IExFIGluZGV4ICV1CgAAAAAAAABvZmxkX2Nvbm5lY3Rpb25fd3I6IGNvbm5lY3Rpb24gd2l0aCA1
+LXR1cGxlIGxwIDB4JTA0eCBmcCAweCUwNHggbGlwIDB4JTA4eCUwOHggcGlwIDB4JTA4eCUwOHgg
+ZmlsdGVyIDB4JTA4eAoAAAAAb2ZsZF9jb25uZWN0aW9uX3dyOiBjb25uZWN0aW9uIHdpdGggNS10
+dXBsZSBscCAweCUwNHggZnAgMHglMDR4IGxpcCAweCUwOHggcGlwIDB4JTA4eCBmaWx0ZXIgMHgl
+MDh4CgAAAAAAAAAAAAAAAElRRkxJTlQgcGZuICV1IHZmbiAldTogaXFlc2l6ZSAldSB0b28gc21h
+bGwKAAAAAElRRkxJTlQgcGZuICV1IHZmbiAldTogaXFpZCAldSB0b28gbGFyZ2UgKG1heCAldSkK
+AAAAAAAAAAAAAAAAAABJUUZMSU5UIHBmbiAldSB2Zm4gJXU6IGlxaWQgJXUgbm90IGFsbG9jYXRl
+ZAoAAABJUUZMSU5UIHBmbiAldSB2Zm4gJXU6IGZsMGlkICV1IHRvbyBsYXJnZSAobWF4ICV1KQoA
+AAAAAAAAAAAAAAAASVFGTElOVCBwZm4gJXUgdmZuICV1OiBmbDBpZCAldSBub3QgYWxsb2NhdGVk
+CgAASVFGTElOVCBwZm4gJXUgdmZuICV1OiBmbDFpZCAldSB0b28gbGFyZ2UgKG1heCAldSkKAAAA
+AAAAAAAAAAAAAElRRkxJTlQgcGZuICV1IHZmbiAldTogZmwxaWQgJXUgbm90IGFsbG9jYXRlZAoA
+AElRRkxJTlQgcGZuICV1IHZmbiAldTogZmwxaWQgJXUgaXMgdmFsaWQgYnV0IG5vdCBmbDBpZCAl
+dQoAAAAAAABJUUZMSU5UIHBmbiAldSB2Zm4gJXU6IGZsMWlkICV1IGlzIHZhbGlkIGJ1dCBoZWFk
+ZXIgc3BsaXQgZmVhdHVyZSBpcyBub3QgZW5hYmxlZAoAAAAAAAAAAAAAAAAAAABod191bHB0eF93
+b3JrYXJvdW5kX3ByMTY5NDlfZW5hYmxlZF9wZjogcGYgJXUgZW5hYmxlZCAldQoAAAAAAAAAaHdf
+dWxwdHhfd29ya2Fyb3VuZF9wcjE2OTQ5X2VuYWJsZWRfdmZpZDogdmZpZCAldSBlbmFibGVkICV1
+CgAAAEVRIHBmbiAldSB2Zm4gJXU6IGNyZWF0aW5nIEVUSCBlcWlkICV1IHdpdGggcGVuZGluZyBX
+UihzKSAobnVtX2J5dGVzICV1IGFuZCBmbGFncyAweCUwOHgKAAAAAAAAAEVRIHBmbiAldSB2Zm4g
+JXU6IGNyZWF0aW5nIENUUkwgZXFpZCAldSB3aXRoIHBlbmRpbmcgV1IocykgKG51bV9ieXRlcyAl
+dSBhbmQgZmxhZ3MgMHglMDh4CgAAAAAAAEVRIHBmbiAldSB2Zm4gJXU6IGVxaWQgJXUgdG9vIGxh
+cmdlIChtYXggJXUpCgAAAEVRIHBmbiAldSB2Zm4gJXU6IGVxaWQgJXUgbm90IGFsbG9jYXRlZAoA
+AAAAAAAAAGh3X2NpbV90cF93b3JrYXJvdW5kMTM3MjNfZW5hYmxlOiBwb3J0ICV1IHByb3RvY29s
+IDB4JXggZW4gJXUgY3VycmVudCAweCV4IHdvcmthcm91bmRfcHIxMzcyMyAweCV4IG5leHQgMHgl
+eAoAAABwb3J0X2JsaW5rX2xlZF9yZXN0b3JlCgAAAAAAAAAAAHBvcnRfYmxpbms6IGJsaW5rZHVy
+PTB4JXggYmxpbmtfcmVmY250CgAAAAAAAAAAAHBvcnRfYmxpbms6IAlibGlua19yZWZjbnQ9MHgl
+eAoAcG9ydF9ibGluazogCWJsaW5rX3JlZmNudD0weCV4CgBtaWlfYWR2X2ZjWyV1XTogcmNhcHMg
+MHgleAoAAAAAAG1paV9hZHZfc3BlZWRbJXVdOiByY2FwcyAweCV4CgAAbWlpX2luaXRbJXVdOiBh
+Y2FwcyAweCV4CgAAAAAAAABwb3J0WyV1XTogZ2F2ZSB1cCBmaXhpbmcgZXJyb3JzISEhCgAAAAAA
+AAAAAAAAAABtaWlfYW5yZXN0YXJ0WyV1XTogYWNhcHMgMHgleAoAAGh3X3hnbV9wb3J0X2xwYmsg
+cG9ydCAldSBwdHlwZSAlI3ggYWN0aW9uICUjeAoAAHBvcnRfY21kX2hhbmRsZXI6IHVua25vd24g
+dS5kY2IudHlwZSAweCV4CgAAAAAAAHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06IGwxY2ZnLCBpbnZh
+bGlkIHJlcXVlc3QsIHBjYXBzIDB4JXggYWNhcHMgMHgleCByY2FwcyAweCV4CgAAAAAAAAAAAAAA
+AAAAAHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06IGwxY2ZnLCBwY2FwcyAlI3ggYWNhcHMgJSN4IHJj
+YXBzICUjeCBtY2FwcyAlI3gKAAAAAAAAAAAAcG9ydFsldToweCUwMng6MHglMDJ4XTogbDFjZmcs
+IG1kaSBpc3N1ZSBwY2FwcyAweCV4IGFjYXBzIDB4JXggcmNhcHMgMHgleAoAAAAAAABwb3J0WyV1
+OjB4JTAyeDoweCUwMnhdOiBsMWNmZywgY2Fubm90IGZvcmNlIG5vL211bHRpcGxlIHNwZWVkKHMp
+LCBwY2FwcyAweCV4IGFjYXBzIDB4JXggcmNhcHMgMHgleAoAAAAAAAAAAAAAAAAAZXRoX2Zsb3dj
+X2hhbmRsZXJbMHgleF06IGZsYWdzIDB4JTA4eCBudW1fYnl0ZXMgJXUgc2NoZWRjbCAweCV4IC0+
+IDB4JXgKAAAAAAAAAABzY3NpX2NtZDogcmVjZWl2ZWQgVE1GIG9wIFsweCV4XSBmdW5jIFsweCV4
+XSBvbiBjb25uIFsweCV4XSB0aHJvdWdoIGNvbW1hbmQgcGF0aC4KAAAAAAAAAAAAAAAAAABzY3Np
+X2NtZDogY29ubl9mYyBbMHgleF0sIHN0YXRlIFsweCV4XSwgc2Vzc19mYyBbMHgleF0gaW4gcmVj
+b3ZlcnkuIFNraXBwaW5nIGlzdGFza19mYyBbMHgleF0gZnJvbSBUWC4KAAAAAAAAAAAAc2NzaV9j
+bWQ6IGlTQ1NJIGNvbW1hbmQgc2VxdWVuY2Ugd2luZG93IGNsb3NlZC4gY29ubiBbMHgleF0sIG9w
+IFsweCV4XSwgIGNtZHNuIFsweCV4XSwgc2VudF9jbWRzbiBbMHgleF0sIG1heF9jbWRzbiBbMHgl
+eF0sIGl0dCBbMHgleF0KAAAAAAAAAAAAc2NzaV9yZWFkOiBjb25uX2ZjIFsweCV4XSwgc3RhdGUg
+WzB4JXhdLCBzZXNzX2ZjIFsweCV4XSBpbiByZWNvdmVyeS4gU2tpcHBpbmcgaXN0YXNrX2ZjIFsw
+eCV4XSBmcm9tIFRYLgoAAAAAAAAAAHNjc2lfcmVhZDogaVNDU0kgY29tbWFuZCBzZXF1ZW5jZSB3
+aW5kb3cgY2xvc2VkLiBjb25uIFsweCV4XSwgY21kc24gWzB4JXhdLCBzZW50X2NtZHNuIFsweCV4
+XSwgbWF4X2NtZHNuIFsweCV4XQoAAAAAAAAAAAAAAAAAAAAAc2NzaV93cml0ZTogY29ubl9mYyBb
+MHgleF0sIHN0YXRlIFsweCV4XSwgc2Vzc19mYyBbMHgleF0gaW4gcmVjb3ZlcnkuIFNraXBwaW5n
+IGlzdGFza19mYyBbMHgleF0gZnJvbSBUWC4KAAAAAAAAAHNjc2lfd3JpdGU6IGlTQ1NJIGNvbW1h
+bmQgc2VxdWVuY2Ugd2luZG93IGNsb3NlZC4gY29ubiBbMHgleF0sIGNtZHNuIFsweCV4XSwgc2Vu
+dF9jbWRzbiBbMHgleF0sIG1heF9jbWRzbiBbMHgleF0sIGl0dCBbMHgleF0KAAAAZGNieF9jb250
+cm9sX3NtWyV1XSBDT05UUk9MX0xJTktVUAoAAAAAAAAAAAAAAAAAZGNieF9jb250cm9sX3NtWyV1
+XSBDT05UUk9MX1VQREFURV9EQ0JYX1RMVgoAAAAAZGNieF9jb250cm9sX3NtWyV1XSBDT05UUk9M
+X1BFRVJfTk9UX0FEVkVSVElTRV9EQ0JYCgAAAAAAAAAAAAAAAGRjYnhfY29udHJvbF9zbVsldV0g
+Q09OVFJPTF9VUERBVEVfT1BFUl9WRVJTSU9OCgAAAAAAAAAAAAAAAAAAAABkY2J4X2NvbnRyb2xf
+c21bJXVdIENPTlRST0xfUFJPQ0VTU19QRUVSX1RMVgoAAABkY2J4X2NvbnRyb2xfc21bJXVdIENP
+TlRST0xfQUNLX1BFRVIKAAAAAAAAAAAAAABkY2J4X2llZWVfdmFsaWRhdGVbJXVdIGVycm9yIChv
+dWkgJSN4IHN1YnR5cGUgJSN4IGxlbiAlI3gpCgAAAAAAZGNieF9jZWVfdmFsaWRhdGVbJXVdIGVy
+cm9yCgAAAABwcm9jZXNzX2RoY3Bfb3B0czogcm9vdCBwYXRoIGxlbiBbJWRdIGJ5dGVzCgAAAABu
+ZXRpZl9wcm9jZXNzX2RoY3Bfb3B0czogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgTVNHX1RZ
+UEUgWyVkXSwgZGhjdHh0LT5zdGF0ZSBbJWRdCgAAAAAAAAAAAABpY21wX3JlY3Y6IGwyZGV2X2Zj
+LT5mbG93Y19pZCBbMHgleF0sIHBpZCBbMHgleF0sIGljbXAgdHlwZSBbMHgleF0KAAAAAAAAAAAA
+AAAAAEFCVFMgQUNDIGF3YWl0aW5nIFBSTEkgUnNwOiBmbG93Y19pZCAweCV4IG94X2lkIDB4JXgg
+cnhfaWQgMHgleCBpcWlkIDB4JXgKAAAAAAAAcG9ydCAweCV4LCBzdGF0ZSAweCV4LCBjb21tYW5k
+IGZhaWxlZCByZXRyaWVzIDB4JXgKAAAAAAAAAAAAAAAAAGFycF9yZWN2OiBpcGlkIFsweCV4XSwg
+aW5fYWRkci5hZGRyIFsweCV4XSwgc2lwIFsweCV4XSwgcmlwIFsweCV4XSwgYXJwX29wIFsweCV4
+XQoAAAAAAAAAAAAAAAAAAGNobmV0X2FycF9yZWN2OiBpcCBjb25mbGljdCBkZXRlY3RlZAoAAAAA
+AAAAAAAAAGNobmV0X2FycF9yZWN2OiBwaWQgWyV1XSwgdmxhbiBbMHgleF0sIGFycCBvcCBbMHgl
+eF0sIHNpcCBbMHgleF0sIHJpcCBbMHgleF0KAAAASW52YWxpZCBkaWQ6eCUyeCUyeCUyeCByY3Zk
+IG9uIHBvcnQ6JWQuRHJvcGluZyBmcmFtZQoAAAAAAAAAAAAAAHJjdDp4JXggc2lkOnglMnglMngl
+MnggcmN2ZCBvbiBmbG93YzolZC5Ecm9waW5nIGZyYW1lCgAAAAAAAAAAAABjc29ja19mcmVlOiBz
+aXplb2YoY3NrX2ZjLT51LmNzb2NrKSBbJXVdLCBieXRlcwoAAAAAAAAAAAAAAAAAAAAAR290IENP
+Tk5fRVhJU1QgZm9yIHhpZDoweCV4LCB0YWc6MHgleCwgcmV0cnlpbmcuCgAAAAAAAAAAAAAAAAAA
+AGh3X3VscHR4X3dvcmthcm91bmRfcHIxNjk0OV9lbmFibGVkX3BmX2lxOiBpcSAldSBlbmFibGVk
+ICV1IChwZiAldSkKAAAAAAAAAAAAAAAAY3NvY2tfcGVlcl9jbG9zZTogY3NrX2ZjLT5mbG93Y19p
+ZCBbMHgleF0sIHRjYl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPmZsb3djX3N0YXRlIFsw
+eCV4XSwgdGNiX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0KAAAAAABjc29ja19wZWVyX2Nsb3NlOiBj
+c2tfZmMtPmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19zdGF0ZSAgWzB4JXhdCgAAAAAA
+AAAAAHRjcF9jbHNfYWJydF9ycGw6IHRjYiB0aWQgWzB4JTA2eF0sIGZsb3djX3R5cGUgWzB4JXhd
+LCBjcGxvcCBbMHgleF0gCgAAAAAAAAAAAAAAY2hfcmF0ZVsldV06IGNhcHBlZCB0aWNrIGZyb20g
+cmVxdWlyZWQgJXUgdG8gc3VwcG9ydGVkICV1OyByYXRlICV1IChlZmYgJXUpIGRlZmljaXRfaW5j
+ciAldSB0aWNrICV1CgAAAAAAAAAAAAAAAHBrdHNjaGVkX2NoX3JsWyV1XTogY2hhbm5lbCBybCBu
+b3QgYXZhaWxhYmxlIGluIGNvbmp1bmN0aW9uIHdpdGggZmxvdyBzaGFwaW5nCgAAcGt0c2NoZWRf
+Y2hfcmxbJXVdOiByYXRlICV1IG1heCAldQoAAAAAAAAAAAAAAAAAcGt0c2NoZWRfY2xfd3JyWyV1
+OiV1XTogd2VpZ2h0ICV1CgAAAAAAAAAAAAAAAAAAZXFfcGFyYW1zWzB4JXg6MHgleF06IGRtYXEg
+MHgleCByZWFkICV1IHBmICV1IGVxaWRfYXBpICV1IHJldCAlZAoAAAAAAAAAAAAAAAAAAABod19t
+YV9hZGRyX3RvX21lbV90eXBlX29mZjogTUEgYWRkcmVzcyAweCUwOHggaXMgbm90IG1hcHBlZAoA
+AAAAaHdfbWFfYWRkcl90b19tZW1fdHlwZV9vZmY6IE1BIGFkZHJlc3MgMHglMDh4IG1hcHMgdG8g
+dHlwZSAldSBvZmZzZXQgMHgleAoAAAAAAABtZW1fbWFsbG9jX3RlbXA6IGZhaWxlZCB0byBhbGxv
+Y2F0ZSAldSBieXRlcywgcmV0dXJuaW5nIE5VTEwKAAAAbWVtX21hbGxvYzogZmFpbGVkIHRvIGFs
+bG9jYXRlICV1IGJ5dGVzLCByZXR1cm5pbmcgTlVMTAoAAAAAAAAAAGxlIGNvbmZpZ3VyYXRpb246
+IGhhc2ggbW9kZSByZXF1aXJlcyBhdCBsZWFzdCAxNiBlbnRyaWVzLCBuaGFzaCAldQoAAAAAAAAA
+AAAAAAAAbGUgY29uZmlndXJhdGlvbjogaGFzaCBtb2RlIHJlcXVpcmVzIGF0IGVudHJpZXMgdG8g
+YmUgYSBwb3dlciBvZiAyLCBuaGFzaCAldQoAAABsZSBjb25maWd1cmF0aW9uOiByZXF1ZXN0ZWQg
+JXUgdGNhbSBlbnRyaWVzIGJ1dCBvbmx5ICV1IGF2YWlsYWJsZSAobnJvdXRlICV1IG5jbGlwICV1
+IG5maWx0ZXIgJXUgbnNlcnZlciAldQoAAAAAbGUgY29uZmlndXJhdGlvbjogdGNhbSByZWdpb25z
+IG11c3QgaGF2ZSBtdWx0aXBsZSBvZiAzMiBlbnRyaWVzLCBucm91dGUgJXUgbmNsaXAgJXUgbmZp
+bHRlciAldSBuc2VydmVyICV1CgAAAAAAAGh3X3RwX3RjcF90dW5pbmdzOiB0dW5pbmcgZm9yIGNs
+dXN0ZXIgZW52aXJvbm1lbnQKAAAAAAAAAAAAAAAAAABod190cF90Y3BfdHVuaW5nczogdHVuaW5n
+IGZvciBMQU4gZW52aXJvbm1lbnQKAABod190cF90Y3BfdHVuaW5nczogdHVuaW5nIGZvciBXQU4g
+ZW52aXJvbm1lbnQKAABod190cF90Y3BfdHVuaW5nczogbWFudWFsIHR1bmluZwoAAAAAAAAAAAAA
+AAAAAABfaHdfY2ltX2ZsYXNoX21lbWNweTogbWVtY3B5WCBzdGFydAoAAAAAAAAAAAAAAABfaHdf
+Y2ltX2ZsYXNoX21lbWNweTogZHN0IDB4JTA4IG9mZnNldCAweCUwOHggc2l6ZSAldSwgd2lkdGgg
+b2YgJXUgaXMgbm90IHN1cHBvcnRlZAoAAAAAAAAAAAAAAABfaHdfY2ltX2ZsYXNoX21lbWNweTog
+bWVtY3B5WCBlbmQKAAAAAAAAAAAAAAAAAABjb25maWd1cmF0aW9uIGZpbGUgcGFyc2VyIGVuY291
+bnRlcmVkIGVycm9yIEAgbGluZSAldToKAAAAAAAAAAAAaHdfaTJjX3RyYW5zYWN0aW9uOiBuZGF0
+YSAldSBhZGRyX29wIDB4JXggZGF0YVswXSAweCV4IGRpZmYgJXUKAGh3X2kyY190cmFuc2FjdGlv
+bjogbmRhdGEgJXUgYWRkcl9vcCAweCV4IGRhdGFbMF0gMHgleCBkaWZmICV1IGRwb3MgJXUgY29u
+dCAldSBmYWlsZWQgd2l0aCBlcnIgJWQKAAAAAAAAAAAAAAAAAABpMmMgdHJhbnNhY3Rpb24gZmFp
+bGVkIHRvIGNvbXBsZXRlCgAAAAAAAAAAAAAAAABIT1NUIFBBR0VfU0laRSBbMHglMGx4XSB0b28g
+c21hbGwsIG1pbiBbMHglMGx4XSByZXF1aXJlZAoAAAAAAAAAcGFnZSBzaXplIFslbHVdIG1pc21h
+dGNoCgAAAAAAAABQQUdFIHNpemUgJWx1IHVuc3VwcG9ydGVkLCBkZHAgZGlzYWJsZWQKAAAAAAAA
+AABIb3N0IHBhZ2Vfc2l6ZSAlbHUsIGRkcF9pZHggJXUKAEZDb0UgRERQIGluaXQ6IGZjb2UgbGxp
+bWl0IDB4JXgsIGZjb2UgdWxpbWl0IDB4JXggZ2JsIGxsaW1pdCAweCV4IGdibCB1bGltaXQgMHgl
+eCBwY2JzeiAleAoAAAAAAEZDb0UgRERQIGluaXQ6IGZjb2UgcHBvZCBvZmYgMHgleCwgZmNvZSBz
+dCBwcG9kIGFkZHIgMHgleCBmY29lIG51bSBwcG9kcyAweCV4CgAAZmNvZSB4Y2hnIG1nciBpbml0
+OiBOdW1iZXIgb2YgRERQIGV4Y2hhbmdlcyBmb3IgRkNvRSBpcyAleAoAAAAAAGZjb2UgeGNoZyBt
+Z3IgaW5pdDogTnVtYmVyIG9mIHR1bm5lbCBleGNocyBmb3IgRkNvRSBpcyAleAoAAAAAAABmY29l
+X2wydF9pbml0OiBObyB1bHB0eCBjcmVkaXQgY2g6WyV1XQoAAAAAAAAAAABmY29lX2wydF9pbml0
+OiBjaDpbJXVdIGwydF9pZHggWyV1XQoAAAAAAAAAAAAAAABubyBsMnQgZW50cmllcyBjb25maWd1
+cmVkOyBmb3JjaW5nICV1IGVudHJpZXMsIHN0YXJ0aW5nIGF0ICV1CgAAZGNieCB1cGRhdGVbJXVd
+IHNlbnQgdG8gZHJpdmVyICh0eXBlICUjeCBzdWJ0eXBlICUjeCBmbG93Y2lkICV1KQoAAAAAAAAA
+AAAAAAAAAABkY2J4X3J1bl92ZXJzaW9uX3NtWyV1XSBEQ0JYX1ZFUl9TVEFURV9SVU5fSUVFRQoA
+AAAAAAAAAAAAAAAAAAAAZGNieF9ydW5fdmVyc2lvbl9zbVsldV0gRENCWF9WRVJfU1RBVEVfUlVO
+X0NFRQoAZGNieF9ydW5fdmVyc2lvbl9zbVsldV0gRENCWF9WRVJfU1RBVEVfUlVOX05PTkUKAAAA
+AAAAAAAAAAAAAAAAAHBvcnRbJXVdIGxpbmsgdXAgKCV1KSAoc3BlZWQgJSN4IGFjYXBzICUjeCBs
+cGNhcHMgJSN4KQoAAAAAAAAAAABwb3J0X2hzc19zaWdkZXRbJXVdOiBoc3Nfc2lnZGV0IGNoYW5n
+ZWQgdG8gMHgleAoAAAAAAAAAAAAAAAAAAAAAUVNGUCBtb2R1bGUgdW5wbHVnIC0gcmVpbml0aWFs
+aXppbmcgcnhfbG9zICB0byAweGZmCgAAAAAAAAAAAAAAAGdwaW9fcXNmcF9tb2R1bGVfdXBkYXRl
+OiBjaGFuZ2VkIHJ4X2xvcyBmcm9tIDB4JXggdG8gMHgleAoAAAAAAABncGlvX3FzZnBfbW9kdWxl
+X3VwZGF0ZTogY2hhbmdlZCB0eF9kaXMgZnJvbSAweCV4IHRvIDB4JXgKAAAAAAAAQ2FsY3VsYXRp
+b24gb3V0IG9mIGJvdW5kcyBmdXJpbmcgaW5pdDogJSN4ICUjeCAlI3gKAAAAAAAAAAAAAAAAAGh3
+X3NnZV9tYW1lbV9pbml0OiBlbmNvdW50ZXJlZCBlcnJvciAlZAoAAAAAAAAAAF9od190cF9wZ21u
+Z3Q6IHR4X3BhZ2VfbWF4ICV1IHJ4X3BhZ2VfbWF4ICV1IHBzdHJ1Y3RzICV1IHNpemUgJXUKAAAA
+AAAAAAAAAAAAAAAAbXBhcnRpdGlvbl9vdGhlcnNfdG90YWw6IGRkcCAldSBkZHBfaXNjc2kgJXUg
+c3RhZyAldSBwYmwgJXUgcnEgJXUgcnF1ZHAgJXUgLT4gJXUKAAAAAAAAAAAAAAAAAAAAX21wYXJ0
+aXRpb25fYmFua3NfbWNYOiBuYmFua3NfcG10eCAldSAoJXVNQikgbmJhbmtzX3BtcnggJXUgKCV1
+TUIpIG5iYW5rc19vdGhlcnMgJXUgKCV1TUIpIG5iYW5rc19mdyAldSAoJXVNQikKAF9tcGFydGl0
+aW9uX2JhbmtzX21jMTogbmJhbmtzX3BtdHggJXUgKCV1TUIpIG5iYW5rc19vdGhlcnMgJXUgKCV1
+TUIpIG5iYW5rc19mdyAldSAoJXVNQikKAAAAAAAAAF9tcGFydGl0aW9uX2JhbmtzX21jMDogbmJh
+bmtzX3BtcnggJXUgKCV1TUIpIG5iYW5rc19vdGhlcnMgJXUgKCV1TUIpCgAAAAAAAAAAAAAAbWVt
+X21hbGxvY19pbnRlcm5hbDogZmFpbGVkIHRvIGFsbG9jYXRlICV1IGJ5dGVzLCByZXR1cm5pbmcg
+TlVMTAoAAAAAAAAAAAAAAAAAAABod19lZGNfYmlzdFsldV06IGJpc3RfY21kWzB4JTA4eF0gYWRk
+ciAweCV4IGxlbiAweCV4CgAAAAAAAAAAAAAAaHdfZWRjX2Jpc3RbJXVdOiBkb25lLCBlbmNvdW50
+ZXJlZCAldSBlcnJvcnMgb24gZmlyc3QgYW5kICV1IGVycm9ycyBvbiBzZWNvbmQgYXR0ZW1wdCAo
+JXVnYnBzKQoAbWVtX2luaXRfY2FjaGVzOiBjYWNoZV9zaXplICV1IGZsb3djX2J1Zl90Y2JfY2Fj
+aGVfc2l6ZSAldSBidWZsbDY0X2NhY2hlX3NpemUgJXUKAAAAAAAAAAAAAAAAAAAAcXVldWVzX3Bl
+cl9wYWdlOiBwZiAldSBoYXMgYSBiYXJzaXplIG9mICV1LWJ5dGVzLCBvY3Ffc2l6ZSAldQoAAHNn
+ZSByZXF1aXJlIG5lcSAldSBuaXEgJXUgcm91bmRpbmcgdG8gJXUgJXUKAAAAAG1wYXJ0aXRpb25f
+cG10eDogbSAweCUwOHggc2l6ZSAldQoAAAAAAAAAAAAAAAAAAG1wYXJ0aXRpb25fcG1yeDogbSAw
+eCUwOHggc2l6ZSAldQoAAAAAAAAAAAAAAAAAAG1wYXJ0aXRpb25fZWRjIChubyBleHRtZW0pOiBt
+IDB4JTA4eCBzaXplICV1CgAAAG1wYXJ0aXRpb25fZWRjX2VzdGltYXRlOiBodyBtb2R1bGVzIHJl
+cXVpcmUgJWQgYnl0ZXMgaW4gRURDCgAAAABjaG5ldF9ieWU6bDJkZXZfZmMtPmZsb3djX2lkIFsw
+eCV4XSwgbDJkZXZfZmMtPmZsb3djX3BjaWVfcGZuIFsweCV4XSwgbDJkZXZfZmMtPmZsb3djX3Bj
+aWVfdmZuIFsweCV4XSwgcG9ydCBbMHgleF0KAAAAAAAAAAAAAAAAAGNobmV0X2J5ZTp2bGFuZGV2
+X2ZjLT5mbG93Y19pZCBbMHgleF0sIHZsYW5kZXZfZmMtPmZsb3djX3BjaWVfcGZuIFsweCV4XSwg
+dmxhbmRldl9mYy0+Zmxvd2NfcGNpZV92Zm4gWzB4JXhdLCBwb3J0IFsweCV4XQoAAAAAAAAAY3Jf
+bW9kdWxlX3J4X2xvc1sldV06IHJ4X2xvcyBjaGFuZ2VkIHRvICV1CgAAAAAAcGZuICV1IHZmbiAl
+dSBoYXMgcG5kdHhucyAldSBhZnRlciAxMDBtcwoAAAAAAAAAYmFkIG1haWxib3ggY21kOiBwZm4g
+MHgleCB2Zm4gMHgleDsgb3Bjb2RlIDB4JXggPiBMQVNUQzJFIDB4JXgKAG1haWxib3ggY21kIG5v
+dCB5ZXQgc3VwcG9ydGVkOiBwZm4gMHgleCB2Zm4gMHgleDsgb3Bjb2RlIDB4JXgKAABiYWQgbWFp
+bGJveCBjbWQ6IHBmbiAweCV4IHZmbiAweCV4OyBvcGNvZGUgMHgleCBpcyB2YWxpZCBwb3N0IGRl
+dmljZSBpbml0IG9ubHkKAGJhZCBtYWlsYm94IGNtZDogcGZuIDB4JXggdmZuIDB4JXg7IG9wY29k
+ZSAweCUwMnggcmFtYXNrIDB4JXggY21kIHJhbWFzayAweCV4CgAAYmFkIG1haWxib3ggY21kOiBw
+Zm4gMHgleCB2Zm4gMHgleDsgb3Bjb2RlIDB4JTAyeCBsZW4xNiAweCV4IHZlcnN1cyBleHBlY3Rl
+ZCBsZW4xNiAweCV4CgAAAAAAAAAAaW5zdWZmaWNpZW50IGNhcHMgdG8gcHJvY2VzcyBtYWlsYm94
+IGNtZDogcGZuIDB4JXggdmZuIDB4JXg7IHJfY2FwcyAweCV4IHd4X2NhcHMgMHgleCByZXF1aXJl
+ZCByX2NhcHMgMHgleCB3X2NhcHMgMHgleAoAAAAAAAAAAABpbnN1ZmZpY2llbnQgY2FwcyB0byBw
+cm9jZXNzIG1haWxib3ggY21kOiBwZm4gMHgleCB2Zm4gMHgleDsgcl9jYXBzIDB4JXggd3hfY2Fw
+cyAweCV4IHJlcXVpcmVkIHJfY2FwcyAweCV4IHdfY2FwcyAweCV4CgAAAAAAAAAAAFZQRCByZWdp
+b24gaXMgdG9vIHNtYWxsIChTRVJDRkdfU1JfUEZOVlBEU0laRSAweCV4KQoAAAAAAAAAAAAAAABj
+ZjogZmFpbGVkIHRvIGFsbG9jYXRlZCBtZW1vcnkgZm9yIGNvbmZpZ3VyYXRpb24gZmlsZSwgcmV0
+ICVkCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAIIAAAEgAAAAAAAAAIIAAAEAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAaAgAAAAAAAAAAAAAAAAIAAAAAAAAAAAAKAAAAAAAAAAAAAAgADAAAAAAFgCAAAAAADAAAA
+AAAAAAAAAAADAAAAAAAAAAAAAAACAAAAAAAAAAAAIAAAAAAAAAAAAAAAAQADgAAAAAAAAAAAAAAC
+AAAAAAAAAAAAIAOAAAAAAAAAAAAAEAKAAIAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAA
+AAACgAAAAAAAAAAAAAACAAAAAAAAAAAAAAACgAAAAAAAAAAAAQADAAAAAAAAAAAAAAKDAAAAAAAA
+AAAAEAKAAAAAAAAAAAAAMAADAAAAAAAACAAAMAADAAAAAAAAAAAAMAWDAAAAAAAACAAAMAWDAAAA
+AAAAAAAAMASDAAAAAAAACAAAMASDAAAAAAAAAAAAMAMDAAAAAAAACAAAMAMDAAAAAAAAAAAAOAMD
+AAAAAAAAAAAAOAWDAAAAAAAAAAAAOASDAAAAAAAAAAAAOAADAAAAAAAAAAAANAaCAAAAAAAAAAAA
+PAOCAAAAAAAAAAAAPAADAAAAAAAACAAAPAADAAAAAAAAAAAAPASDAAAAAAAAAAAAPAUDAAAAAAAA
+AAAAPQQDAAAAAAAAAAAAPAODAAAAAAAAAAAALAACAAAAAAAAAAAALAWCAAAAAAAAAAAALAUCAAAA
+AAAAAAAAEAaAAAAAAAAAAAAAEAaCwAAAAAAAAAAAEAaCgAAAAAAAAAAAAA6CAAAAAAAAAAAAEAeC
+gAAAACAAAAAAAAeCAAAAACAAAAAAEAcCgAAAAAAAAAAAEAcCgAAAAAAAAAAAEAcCgAAAAAAAAAAA
+AAcCAAAAACAAAAAAEBeDAAAAAAAACAAAEBeDAAAAAAAACAAAEAAAAAAAAAAAAAAAEAYDgAAAAAAA
+AAAAAA4DAAAAAAAAAAAAEAYDQAAAAAAAAAAAEAYDAAAAAAAAAAAAEAYAAAAAAAAAAAAAAAYDgAAA
+AAAAAAAAAAYDAAAAAAAAAAAAAA4CAAAAAAAAAAAAAA4CAAAAAAAAAAAAEAYCAAAAAAAAAAAAEAYC
+AAAAAAAAAAAAEAYCgAAAAAAAAAAAEAYCgAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAACAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAABADAAAAAAAACAAAAAAAAAAAAAAAAAAA////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
@@ -9257,24 +9266,24 @@ AAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAQAwAAAAAAAAgAAAAAAAAAAAAAAAAAAP//////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////wAA
-ACAAAAAAwAAAAAAAACAAAAAA4AAAAAAAAAACAAAAAAAAAEAAAAAAAAAAAAAAAAAAASEAAAAAAAAA
-AAABASAAAAAAAAAAAAAAAgAAAAQABAAAAAAFAAAABAAAAAAAAAAAAKAAAAAAgAAAAACAAEAAAAAA
-AAIAAACAACAAAAAAAAIAAAEAQAAAAAAAAAAAAAEAQgAAAAAAAAAAAAAAIAAAAAAAAAAAAAIQIAAA
-AAAAAAAAAAIMAgAAAAAAAAAAAACFAgAAAAQAAAAAAACAQgAAAAAAAAAAAAIAIgAAAAAAAAAAAACA
-QQAAAAAAAAAAAACAQYAAAAAAAAAAAAIAIQAAAAAAAAAAAAAQIIAAAAAAAAAAAAIlAIAAAAAAAAAA
-AAAFAAAAAAAAAAAAAAiIBIAAAAAAAAAAAAiIBIAAAAAAAAAAAAiiAIAAAAAAAAAAAAiiAIAAAAAA
-AAAAAAijAIAAAAAAAAAAAAijAIAAAAAAAAAAAAikgIAAAAAAAAAAAAikgIAAAAAAAAAAAASkgMAA
-AAAAAAAAAASiAMAAAAAAAAAAAASjAMAAAAAAAAAAAASIBMAAAAAAAAAAAAAJAYAAAAAAAAAAAAIM
-AIAAAAAAAAAAAACIBMAAAAAAAAAAAACIBIAAAAAAAAAAAAILAIAAAAAAAAAAAACKgIAAAAAAAAAA
-AAALgIAAAAAAAAAAAACMAIAAAAAAAAAAAAIgEIAAAAAAAAAAAAIKAIAAAAAAAAAAAAIKgIAAAAAA
-AAAAAAAJAoAAAAAAAAAAAAABAQAAAAAAAAAAAAABAUAAAAAAAAAAAAABAIAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAIAAAAAAAAAAAAAAgRAAAAAAAAAAAAAAgQgAAAAAAAAAAAAAgQQAAAAAAAAAAAAA
-gYAAAAAAAAAAAACAAMAAAAAAAAAAAACAAKAAAAAAAAAAAAAACAAAAAAAAAAAAACBgAAAAAAAAAAA
-AACBgIAAAAAAAAAAAACJgIAAAAAAAAAAAACJgMAAAAAAAAAAAAABggAAAAAAAAAAAAIBgAAAAAAA
-AAAAAAIBgIAAAAAAAAAAAABBgYAAAAAAAAAAAAIBgYAAAAAAAAAAAABJgYAAAAAAAAAAAAIJgYAA
-AAAAAAAAAAIBgQAAAAAAAAAAAABBgQAAAAAAAAAAACAAAAAAAAAAAAAAABAAAAIBAAAAAAAAABAA
-AAIAAAAAAAAAABAAAAAAAAAAAAAAAACAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////
+////////////////////////////////////////////////////////////////////////AAAA
+IAAAAADAAAAAAAAAIAAAAADgAAAAAAAAAAIAAAAAAAAAQAAAAAAAAAAAAAAAAAABIQAAAAAAAAAA
+AAEBIAAAAAAAAAAAAAACAAAABAAEAAAAAAUAAAAEAAAAAAAAAAAAoAAAAACAAAAAAIAAQAAAAAAA
+AgAAAIAAIAAAAAAAAgAAAQBAAAAAAAAAAAAAAQBCAAAAAAAAAAAAAAAgAAAAAAAAAAAAAhAgAAAA
+AAAAAAAAAgwCAAAAAAAAAAAAAIUCAAAABAAAAAAAAIBCAAAAAAAAAAAAAgAiAAAAAAAAAAAAAIBB
+AAAAAAAAAAAAAIBBgAAAAAAAAAAAAgAhAAAAAAAAAAAAABAggAAAAAAAAAAAAiUAgAAAAAAAAAAA
+AAUAAAAAAAAAAAAACIgEgAAAAAAAAAAACIgEgAAAAAAAAAAACKIAgAAAAAAAAAAACKIAgAAAAAAA
+AAAACKMAgAAAAAAAAAAACKMAgAAAAAAAAAAACKSAgAAAAAAAAAAACKSAgAAAAAAAAAAABKSAwAAA
+AAAAAAAABKIAwAAAAAAAAAAABKMAwAAAAAAAAAAABIgEwAAAAAAAAAAAAAkBgAAAAAAAAAAAAgwA
+gAAAAAAAAAAAAIgEwAAAAAAAAAAAAIgEgAAAAAAAAAAAAgsAgAAAAAAAAAAAAIqAgAAAAAAAAAAA
+AAuAgAAAAAAAAAAAAIwAgAAAAAAAAAAAAiAQgAAAAAAAAAAAAgoAgAAAAAAAAAAAAgqAgAAAAAAA
+AAAAAAkCgAAAAAAAAAAAAAEBAAAAAAAAAAAAAAEBQAAAAAAAAAAAAAEAgAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAgAAAAAAAAAAAAACBEAAAAAAAAAAAAACBCAAAAAAAAAAAAACBBAAAAAAAAAAAAACB
+gAAAAAAAAAAAAIAAwAAAAAAAAAAAAIAAoAAAAAAAAAAAAAAIAAAAAAAAAAAAAIGAAAAAAAAAAAAA
+AIGAgAAAAAAAAAAAAImAgAAAAAAAAAAAAImAwAAAAAAAAAAAAAGCAAAAAAAAAAAAAgGAAAAAAAAA
+AAAAAgGAgAAAAAAAAAAAAEGBgAAAAAAAAAAAAgGBgAAAAAAAAAAAAEmBgAAAAAAAAAAAAgmBgAAA
+AAAAAAAAAgGBAAAAAAAAAAAAAEGBAAAAAAAAAAAAIAAAAAAAAAAAAAAAEAAAAgEAAAAAAAAAEAAA
+AgAAAAAAAAAAEAAAAAAAAAAAAAAAAIAAwAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
@@ -9284,75 +9293,75 @@ AAIAAAAAAAAAABAAAAAAAAAAAAAAAACAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////wAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAACACSAAAAAAAAAANmACAAQAAAAAAIAJIAAAAAAAAAA3IBJQRAAAAA
-AAAAAAAAAAAAAAADlgAgAEAAAAAACAAAAAIAiAOHAABWACAAQAAAAAAAAAAAAAAAAAAAA5YAIABA
-AAAAAAAAAAAAAAAAAAADlgAgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAAAAAAAAAAA5YA
-IABAAAAAAAgAAAACAIgDhQAAlgEgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAAAAAAAAAA
-A5YAIABAAAAAAAgAAAACAIgDhQAAlgEgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAAAAAA
-AAAAA5YAIABAAAAAAAgAAAACAIgDhQAAlgEgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAA
-AAAAAAIAA5YAJgRAAAAAAAhHIAEEAAACsgAC0gUgJEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAA
-RyABBgyhgrBAAZIEICRAAAAAAABHIAEEDKBCs4ACEgUgJEAAAAAACAAAAAIAiAOFAACWASAAQAAA
-AAAIAAAAAgCIA4UAAJYBIABAAAAAAAgAAAACAIgDhQAAlgEgAEAAAAAAAAAAAAAAAAAAAAOWACAA
-QAAAAAANxRK6ArCA0xRUi+JKRiRAAAAAAAXFEroCt4DTFFSLYkmmJEAAAAAABcUSogawgNMUVIvi
-SkYkQAAAAAANxRKiBreA0xRUi2JJpiRAAAAAAAXFEqIGsIDTFFSL4kpGJEAAAAAADcUSoga3gNMU
-VItiSaYkQAAAAAAFxRKiBrCA0xRUi+JKRiRAAAAAAA3FEqIGt4DTFFSLYkmmJEAAAAAACcQQoAIA
-gJAAAItiacYkQAAAAAABxBCgBrCAkwZUi2JpxiRAAAAAAAHEEKAGsICTBlSLYmnGJEAAAAAAAcUQ
-uAawgJMWVItiSMYkQAAAAAAIoRCIAgCBWBIAC1IApiRAAAAAAAnAEJACsIADFlSKkgHGJEAAAAAA
-CcAQuAawgAMQlIviAkYkQAAAAAAJwBC4ArSAAxCUi2IBpiRAAAAAAAnAELgCtIADEJSLYgGmJEAA
-AAAACcAQuAK0gAMQlItiAaYkQAAAAAAJwBC4ArSAAxCUi2IBpiRAAAAAAAGgEJAGtIADEJSLYgGm
-JEAAAAAAAcAQgAKwgAMUVIpSAMYkQAAAAAABwBCAArCAAxRUilIAxiRAAAAAAAHAEIACsIADFFSK
-UgDGJEAAAAAACEcgAQQAAAKyAALSBSAkQAAAAAAAgQAAAgCFWAdAC1IApiRAAAAAAACBAAACAIVY
-B0ALUgCmJEAAAAAAAAAAAAQAoEABgAHWACAAQAAAAAAAAAAABgChgABAAVYAIABAAAAAAAAAAAAE
-AKBAAYAB1gAgAEAAAAAACIEAAAIAhVmABAtSAKYkQAAAAAAJYUAAAAAAGAAAA0IBJqRAAAAAAAAA
-AAAAAAAAAAADlgAgAEAAAAAAAAAAAAQAoEABgAHWACAAQAAAAAAIAAAAAgCIA4cAA9YAJgRAAAAA
-AAgAAAACAIgDhwAD1gAmBEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAAAAAAAAAAA5YAIABA
-AAAAAAAAAAAEAKBAAYAB1gAgAEAAAAAACcAQuAK0gAMQlItiAaYkQAAAAAAAAAAAAAAAAAIAA5YA
-JgRAAAAAAAAAAAAAAAAAAAADlgAgAEAAAAAACAAAAAIAiAOFAACWASAAQAAAAAAAAAAABACgQAGA
-AdYAIABAAAAAAAAAAAAEAKBAAYAB1gAgAEAAAAAAAAAAAAQAoEABgAHWACAAQAAAAAAIoRCIAgCB
-WBAACRIBpiRAAAAAAAAAAAAEAKBAAYAB1gAgAEAAAAAAAAAAAAYAoYAAQAFWACAAQAAAAAAIAAAA
-AgCIA4VACNICRiRAAAAAAAnFEqIClIjSEICLIkimJEAAAAAAAcAQgAakiAEFVItSAMYkQAAAAAAJ
-wBCAAqSIAIVUi1IAxiRAAAAAAAnAEIAGtIgDARSLUgGmJEAAAAAADcAAAAKwgMMWVIviA0YkQAAA
-AAAAAAAAAAAAAAAAA5YAIABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+////////////////////////////////////////////////////////////////////AAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAIAJIAAAAAAAAAA2YAIABAAAAAAAgAkgAAAAAAAAADcgElBEAAAAAA
+AAAAAAAAAAAAAAOWACAAQAAAAAAIAAAAAgCIA4cAAFYAIABAAAAAAAAAAAAAAAAAAAADlgAgAEAA
+AAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAAAAAAAAAAA5YAIABAAAAAAAAAAAAAAAAAAAADlgAg
+AEAAAAAACAAAAAIAiAOFAACWASAAQAAAAAAAAAAAAAAAAAAAA5YAIABAAAAAAAAAAAAAAAAAAAAD
+lgAgAEAAAAAACAAAAAIAiAOFAACWASAAQAAAAAAAAAAAAAAAAAAAA5YAIABAAAAAAAAAAAAAAAAA
+AAADlgAgAEAAAAAACAAAAAIAiAOFAACWASAAQAAAAAAAAAAAAAAAAAAAA5YAIABAAAAAAAAAAAAA
+AAAAAgADlgAmBEAAAAAACEcgAQQAAAKyAALSBSAkQAAAAAAAAAAAAAAAAAAAA5YAIABAAAAAAABH
+IAEGDKGCsEABkgQgJEAAAAAAAEcgAQQMoEKzgAISBSAkQAAAAAAIAAAAAgCIA4UAAJYBIABAAAAA
+AAgAAAACAIgDhQAAlgEgAEAAAAAACAAAAAIAiAOFAACWASAAQAAAAAAAAAAAAAAAAAAAA5YAIABA
+AAAAAA3FEroCsIDTFFSL4kpGJEAAAAAABcUSugK3gNMUVItiSaYkQAAAAAAFxRKiBrCA0xRUi+JK
+RiRAAAAAAA3FEqIGt4DTFFSLYkmmJEAAAAAABcUSogawgNMUVIviSkYkQAAAAAANxRKiBreA0xRU
+i2JJpiRAAAAAAAXFEqIGsIDTFFSL4kpGJEAAAAAADcUSoga3gNMUVItiSaYkQAAAAAAJxBCgAgCA
+kAAAi2JpxiRAAAAAAAHEEKAGsICTBlSLYmnGJEAAAAAAAcQQoAawgJMGVItiacYkQAAAAAABxRC4
+BrCAkxZUi2JIxiRAAAAAAAihEIgCAIFYEgALUgCmJEAAAAAACcAQkAKwgAMWVIqSAcYkQAAAAAAJ
+wBC4BrCAAxCUi+ICRiRAAAAAAAnAELgCtIADEJSLYgGmJEAAAAAACcAQuAK0gAMQlItiAaYkQAAA
+AAAJwBC4ArSAAxCUi2IBpiRAAAAAAAnAELgCtIADEJSLYgGmJEAAAAAAAaAQkAa0gAMQlItiAaYk
+QAAAAAABwBCAArCAAxRUilIAxiRAAAAAAAHAEIACsIADFFSKUgDGJEAAAAAAAcAQgAKwgAMUVIpS
+AMYkQAAAAAAIRyABBAAAArIAAtIFICRAAAAAAACBAAACAIVYB0ALUgCmJEAAAAAAAIEAAAIAhVgH
+QAtSAKYkQAAAAAAAAAAABACgQAGAAdYAIABAAAAAAAAAAAAGAKGAAEABVgAgAEAAAAAAAAAAAAQA
+oEABgAHWACAAQAAAAAAIgQAAAgCFWYAEC1IApiRAAAAAAAlhQAAAAAAYAAADQgEmpEAAAAAAAAAA
+AAAAAAAAAAOWACAAQAAAAAAAAAAABACgQAGAAdYAIABAAAAAAAgAAAACAIgDhwAD1gAmBEAAAAAA
+CAAAAAIAiAOHAAPWACYEQAAAAAAAAAAAAAAAAAAAA5YAIABAAAAAAAAAAAAAAAAAAAADlgAgAEAA
+AAAAAAAAAAQAoEABgAHWACAAQAAAAAAJwBC4ArSAAxCUi2IBpiRAAAAAAAAAAAAAAAAAAgADlgAm
+BEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAIAAAAAgCIA4UAAJYBIABAAAAAAAAAAAAEAKBAAYAB
+1gAgAEAAAAAAAAAAAAQAoEABgAHWACAAQAAAAAAAAAAABACgQAGAAdYAIABAAAAAAAihEIgCAIFY
+EAAJEgGmJEAAAAAAAAAAAAQAoEABgAHWACAAQAAAAAAAAAAABgChgABAAVYAIABAAAAAAAgAAAAC
+AIgDhUAI0gJGJEAAAAAACcUSogKUiNIQgIsiSKYkQAAAAAABwBCABqSIAQVUi1IAxiRAAAAAAAnA
+EIACpIgAhVSLUgDGJEAAAAAACcAQgAa0iAMBFItSAaYkQAAAAAANwAAAArCAwxZUi+IDRiRAAAAA
+AAAAAAAAAAAAAAADlgAgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAgAMAAEAAAAAgAAAgAmJEAAAAAAAEcwAAYDIAK3AAgCAcAkQAAAAAAIAwAA
-AgagCrUACAIAxiRAAAAAAAAAAAAAAAAAAgAAAgAmJEAAAAAAACBQAAQAAAACAAACACYkQAAAAAAI
-YCAAhAAAAAAAAAYAIABAAAAAAAhgIACEAAAAAgEwAgAmJUAAAAAACGAAAAQAhAGABAQCAcYkwAAA
-AAABwAAAAkOAAwIMiAIBpiRAAAAAAAgAYAAEAAAAAgAAAgAmJEAAAAAACABgAAQAAAAAAAAEASAA
-QAAAAAAAAAAAAAAAAAAAAAQBIABAAAAAAAQIFIAGCgAABwFMAiCmJkAAAAAACIAAAAYAhAGABAgC
-AaYmQAAAAAAAQAAAAgCgAAJACAIBpiRAAAAAAAAAAAAAAAAAAgAAAgAmJEAAAAAABAAAAAKEAAMC
-iggCBKYkQAAAAAAAAAAAAAAAAAIAAAYBIEhAAAAAAAAgUAAEAAAAAgAAAgAmJEAAAAAACGAgAIQA
-AAACAAAGACYEQAAAAAAIYCAAhAAAAAIAAAIBJiVAAAAAAAhgAAAEAIQBgAQEAgHGJMAAAAAACABg
-AAQAAAAAAAAEASAAQAAAAAAAAAAAAAAAAAAAAAIAJkxwAAAAAAAAAAAAAAAAAAAABgEgAAAAAAAA
+AAAAAAAAAAAAAAAACAAwAAQAAAACAAACACYkQAAAAAAARzAABgMgArcACAIBwCRAAAAAAAgDAAAC
+BqAKtQAIAgDGJEAAAAAAAAAAAAAAAAACAAACACYkQAAAAAAAIFAABAAAAAIAAAIAJiRAAAAAAAhg
+IACEAAAAAAAABgAgAEAAAAAACGAgAIQAAAACATACACYlQAAAAAAIYAAABACEAYAEBAIBxiTAAAAA
+AAHAAAACQ4ADAgyIAgGmJEAAAAAACABgAAQAAAACAAACACYkQAAAAAAIAGAABAAAAAAAAAQBIABA
+AAAAAAAAAAAAAAAAAAAABAEgAEAAAAAABAgUgAYKAAAHAUwCIKYmQAAAAAAIgAAABgCEAYAECAIB
+piZAAAAAAABAAAACAKAAAkAIAgGmJEAAAAAAAAAAAAAAAAACAAACACYkQAAAAAAEAAAAAoQAAwKK
+CAIEpiRAAAAAAAAAAAAAAAAAAgAABgEgSEAAAAAAACBQAAQAAAACAAACACYkQAAAAAAIYCAAhAAA
+AAIAAAYAJgRAAAAAAAhgIACEAAAAAgAAAgEmJUAAAAAACGAAAAQAhAGABAQCAcYkwAAAAAAIAGAA
+BAAAAAAAAAQBIABAAAAAAAAAAAAAAAAAAAAAAgAmTHAAAAAAAAAAAAAAAAAAAAAGASAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAACLSQBAkWBAIExiRAAAAAAAHAAAAItJAECRYE
-AgTGJEAAAAAABAh0gEwJAABQAFwCYeYkQAAAAAAMCHSARAAAAFIAQAJhJiRAAAAAAAgCEKAEAAAA
-AAEAAgAmJEAAAAAACAIQoAQAAAAAAQACACYkQAAAAAAECHQAQgEAAAcAiAJgxiRAAAAAAA3IFAAC
-CQAABECcAmDmJEAAAAAACcgQgAa0kAQClIgCZcYkQAAAAAANyHQASLSQAwCUiAJgpiTAAAAAAA3I
-dABItJADAJSIAmCmJMAAAAAACEcAAAQAAAAAAAACASAkQAAAAAAIRwAABAAAAAIAAAIFICRAAAAA
-AABHIAEMByHCtwAIAgHAJEAAAAAAAEcgAQwHIcK3AAgCAcAkQAAAAAAARyABDAchwrcACAIBwCRA
-AAAAAAAAIAEIAIQABUCIAgHGJMAAAAAAAAAgAQgAhAAFQIgCAcYkwAAAAAAAACABCACEAAVAiAIB
-xiTAAAAAAAAAIAGGggABAsCIAgPGJMAAAAAAAAAgAYKCAAACwIgCA8YkwAAAAAAJwCABgqSAAQVA
-iAIBxiTAAAAAAAgAAAAMAIQABUCIAgHGJMAAAAAAAAAgAYaCAAECwIgCA8YkwAAAAAAAACABgoIA
-AADAiAICpiTAAAAAAAnAIAGCpIABBUCIAgHGJMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAItJAECRYEAgTGJEAAAAAAAcAAAAi0kAQJFgQC
+BMYkQAAAAAAECHSATAkAAFAAXAJh5iRAAAAAAAwIdIBEAAAAUgBAAmEmJEAAAAAACAIQoAQAAAAA
+AQACACYkQAAAAAAIAhCgBAAAAAABAAIAJiRAAAAAAAQIdABCAQAABwCIAmDGJEAAAAAADcgUAAIJ
+AAAEQJwCYOYkQAAAAAAJyBCABrSQBAKUiAJlxiRAAAAAAA3IdABItJADAJSIAmCmJMAAAAAADch0
+AEi0kAMAlIgCYKYkwAAAAAAIRwAABAAAAAAAAAIBICRAAAAAAAhHAAAEAAAAAgAAAgUgJEAAAAAA
+AEcgAQwHIcK3AAgCAcAkQAAAAAAARyABDAchwrcACAIBwCRAAAAAAABHIAEMByHCtwAIAgHAJEAA
+AAAAAAAgAQgAhAAFQIgCAcYkwAAAAAAAACABCACEAAVAiAIBxiTAAAAAAAAAIAEIAIQABUCIAgHG
+JMAAAAAAAAAgAYaCAAECwIgCA8YkwAAAAAAAACABgoIAAALAiAIDxiTAAAAAAAnAIAGCpIABBUCI
+AgHGJMAAAAAACAAAAAwAhAAFQIgCAcYkwAAAAAAAACABhoIAAQLAiAIDxiTAAAAAAAAAIAGCggAA
+AMCIAgKmJMAAAAAACcAgAYKkgAEFQIgCAcYkwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAIAAAABAAEJBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAgAAAAEAAQkEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@@ -9365,122 +9374,122 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFtnbG9iYWxdCnJzc19n
-bGJfY29uZmlnX21vZGU9YmFzaWN2aXJ0dWFsCnJzc19nbGJfY29uZmlnX29wdGlvbnM9dG5sbWFw
-ZW4saGFzaHRvZXBsaXR6LHRubGFsbGxrcApyZWdbMHgxMDA4XT0weDQwODEwLzB4MjFjNzAKcmVn
-WzB4MTAwY109MHgyMjIyMjIyMgpyZWdbMHgxMGEwXT0weDAxMDQwODEwCnJlZ1sweDEwNDRdPTQw
-OTYKcmVnWzB4MTA0OF09NjU1MzYKcmVnWzB4MTA0Y109MTUzNgpyZWdbMHgxMDUwXT05MDI0CnJl
-Z1sweDEwNTRdPTkyMTYKcmVnWzB4MTA1OF09MjA0OApyZWdbMHgxMDVjXT0xMjgKcmVnWzB4MTA2
-MF09ODE5MgpyZWdbMHgxMDY0XT0xNjM4NApyZWdbMHgxMGE0XT0weGEwMDBhMDAwLzB4ZjAwMGYw
-MDAKcmVnWzB4MTBhOF09MHgyMDAwLzB4MjAwMApzZ2VfdGltZXJfdmFsdWU9NSwxMCwyMCw1MCwx
-MDAsMjAwCnJlZ1sweDdkMDRdPTB4MDAwMTAwMDAvMHgwMDAxMDAwMApyZWdbMHg3ZGMwXT0weDBl
-MmY4ODQ5CmZpbHRlck1vZGU9ZnJhZ21lbnRhdGlvbixtcHNoaXR0eXBlLHByb3RvY29sLHZsYW4s
-cG9ydCxmY29lCmZpbHRlck1hc2s9cHJvdG9jb2wsZmNvZQp0cF9wbXJ4PTM0CnRwX3BtcnhfcGFn
-ZXNpemU9NjRLCnRwX25yeGNoPTAKdHBfcG10eD0zMgp0cF9wbXR4X3BhZ2VzaXplPTY0Swp0cF9u
-dHhjaD0wCnRwX210dXM9ODgsMjU2LDUxMiw1NzYsODA4LDEwMjQsMTI4MCwxNDg4LDE1MDAsMjAw
-MiwyMDQ4LDQwOTYsNDM1Miw4MTkyLDkwMDAsOTYwMApyZWdbMHgxOTE2OF09MHgwNDAyMDEwMApb
-ZnVuY3Rpb24iMCJdCm52Zj0xNgp3eF9jYXBzPWFsbApyX2NhcHM9YWxsCm52aT0xCm5pcWZsaW50
-PTgKbmV0aGN0cmw9OApuZXE9MTYKbmV4YWN0Zj04CmNtYXNrPWFsbApwbWFzaz0weDEKW2Z1bmN0
-aW9uIjEiXQpudmY9MTYKd3hfY2Fwcz1hbGwKcl9jYXBzPWFsbApudmk9MQpuaXFmbGludD04Cm5l
-dGhjdHJsPTgKbmVxPTE2Cm5leGFjdGY9OApjbWFzaz1hbGwKcG1hc2s9MHgyCltmdW5jdGlvbiIy
-Il0KbnZmPTE2Cnd4X2NhcHM9YWxsCnJfY2Fwcz1hbGwKbnZpPTEKbmlxZmxpbnQ9OApuZXRoY3Ry
-bD04Cm5lcT0xNgpuZXhhY3RmPTgKY21hc2s9YWxsCnBtYXNrPTB4NApbZnVuY3Rpb24iMyJdCm52
-Zj0xNgp3eF9jYXBzPWFsbApyX2NhcHM9YWxsCm52aT0xCm5pcWZsaW50PTgKbmV0aGN0cmw9OApu
-ZXE9MTYKbmV4YWN0Zj04CmNtYXNrPWFsbApwbWFzaz0weDgKW2Z1bmN0aW9uIjQiXQp3eF9jYXBz
-PWFsbApyX2NhcHM9YWxsCm52aT0yOApuaXFmbGludD0xNzAKbmV0aGN0cmw9MTAwCm5lcT0yNTYK
-bmV4YWN0Zj00MApjbWFzaz1hbGwKcG1hc2s9YWxsCm5ldGhvZmxkPTEwMjQKbnJvdXRlPTMyCm5j
-bGlwPTMyCm5maWx0ZXI9NDk2Cm5zZXJ2ZXI9NDk2Cm5oYXNoPTEyMjg4CnByb3RvY29sPW5pY192
-bSxvZmxkLHJkZHAscmRtYWMsaXNjc2lfaW5pdGlhdG9yX3BkdSxpc2NzaV90YXJnZXRfcGR1CnRw
-X2wydD0zMDcyCnRwX2RkcD0zCnRwX2RkcF9pc2NzaT0yCnRwX3N0YWc9Mwp0cF9wYmw9MTAKdHBf
-cnE9MTMKW2Z1bmN0aW9uIjUiXQp3eF9jYXBzPWFsbApyX2NhcHM9YWxsCm52aT00Cm5pcWZsaW50
-PTM0Cm5ldGhjdHJsPTMyCm5lcT02NApuZXhhY3RmPTQKY21hc2s9YWxsCnBtYXNrPWFsbApuc2Vy
-dmVyPTE2Cm5oYXNoPTIwNDgKdHBfbDJ0PTEwMjAKcHJvdG9jb2w9aXNjc2lfaW5pdGlhdG9yX2Zv
-ZmxkCnRwX2RkcF9pc2NzaT0yCmlzY3NpX250YXNrPTIwNDgKaXNjc2lfbnNlc3M9MjA0OAppc2Nz
-aV9uY29ubl9wZXJfc2Vzc2lvbj0xCmlzY3NpX25pbml0aWF0b3JfaW5zdGFuY2U9NjQKW2Z1bmN0
-aW9uIjYiXQp3eF9jYXBzPWFsbApyX2NhcHM9YWxsCm52aT00Cm5pcWZsaW50PTM0Cm5ldGhjdHJs
-PTMyCm5lcT02NgpuZXhhY3RmPTMyCmNtYXNrPWFsbApwbWFzaz1hbGwKbmhhc2g9MjA0OAp0cF9s
-MnQ9NApwcm90b2NvbD1mY29lX2luaXRpYXRvcgp0cF9kZHA9MQpmY29lX25mY2Y9MTYKZmNvZV9u
-dm5wPTMyCmZjb2VfbnNzbj0xMDI0CltmdW5jdGlvbiIxMDIzIl0Kd3hfY2Fwcz1hbGwKcl9jYXBz
-PWFsbApudmk9NApjbWFzaz1hbGwKcG1hc2s9YWxsCm5leGFjdGY9OApuZmlsdGVyPTE2CltmdW5j
-dGlvbiIwLyoiXQp3eF9jYXBzPTB4ODIKcl9jYXBzPTB4ODYKbnZpPTEKbmlxZmxpbnQ9NApuZXRo
-Y3RybD0yCm5lcT00Cm5leGFjdGY9NApjbWFzaz1hbGwKcG1hc2s9MHgxCltmdW5jdGlvbiIxLyoi
-XQp3eF9jYXBzPTB4ODIKcl9jYXBzPTB4ODYKbnZpPTEKbmlxZmxpbnQ9NApuZXRoY3RybD0yCm5l
-cT00Cm5leGFjdGY9NApjbWFzaz1hbGwKcG1hc2s9MHgyCltmdW5jdGlvbiIyLyoiXQp3eF9jYXBz
-PTB4ODIKcl9jYXBzPTB4ODYKbnZpPTEKbmlxZmxpbnQ9NApuZXRoY3RybD0yCm5lcT00Cm5leGFj
-dGY9NApjbWFzaz1hbGwKcG1hc2s9MHg0CltmdW5jdGlvbiIzLyoiXQp3eF9jYXBzPTB4ODIKcl9j
-YXBzPTB4ODYKbnZpPTEKbmlxZmxpbnQ9NApuZXRoY3RybD0yCm5lcT00Cm5leGFjdGY9NApjbWFz
-az1hbGwKcG1hc2s9MHg4Cltwb3J0IjAiXQpkY2I9cHBwLGRjYngKYmdfbWVtPTI1CmxwYmtfbWVt
-PTI1Cmh3bT0zMApsd209MTUKZHdtPTMwCmRjYl9hcHBfdGx2WzBdPTB4ODkwNixldGhlcnR5cGUs
-MwpkY2JfYXBwX3RsdlsxXT0weDg5MTQsZXRoZXJ0eXBlLDMKZGNiX2FwcF90bHZbMl09MzI2MCxz
-b2NrZXRudW0sNQpbcG9ydCIxIl0KZGNiPXBwcCxkY2J4CmJnX21lbT0yNQpscGJrX21lbT0yNQpo
-d209MzAKbHdtPTE1CmR3bT0zMApkY2JfYXBwX3RsdlswXT0weDg5MDYsZXRoZXJ0eXBlLDMKZGNi
-X2FwcF90bHZbMV09MHg4OTE0LGV0aGVydHlwZSwzCmRjYl9hcHBfdGx2WzJdPTMyNjAsc29ja2V0
-bnVtLDUKW3BvcnQiMiJdCmRjYj1wcHAsZGNieApiZ19tZW09MjUKbHBia19tZW09MjUKaHdtPTMw
-Cmx3bT0xNQpkd209MzAKZGNiX2FwcF90bHZbMF09MHg4OTA2LGV0aGVydHlwZSwzCmRjYl9hcHBf
-dGx2WzFdPTB4ODkxNCxldGhlcnR5cGUsMwpkY2JfYXBwX3RsdlsyXT0zMjYwLHNvY2tldG51bSw1
-Cltwb3J0IjMiXQpkY2I9cHBwLGRjYngKYmdfbWVtPTI1CmxwYmtfbWVtPTI1Cmh3bT0zMApsd209
-MTUKZHdtPTMwCmRjYl9hcHBfdGx2WzBdPTB4ODkwNixldGhlcnR5cGUsMwpkY2JfYXBwX3Rsdlsx
-XT0weDg5MTQsZXRoZXJ0eXBlLDMKZGNiX2FwcF90bHZbMl09MzI2MCxzb2NrZXRudW0sNQpbZmlu
-aV0KdmVyc2lvbj0weDE0MjUwMDFjCmNoZWNrc3VtPTB4NjNhNjUyYjMKAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAW2dsb2JhbF0KcnNzX2ds
+Yl9jb25maWdfbW9kZT1iYXNpY3ZpcnR1YWwKcnNzX2dsYl9jb25maWdfb3B0aW9ucz10bmxtYXBl
+bixoYXNodG9lcGxpdHosdG5sYWxsbGtwCnJlZ1sweDEwMDhdPTB4NDA4MTAvMHgyMWM3MApyZWdb
+MHgxMDBjXT0weDIyMjIyMjIyCnJlZ1sweDEwYTBdPTB4MDEwNDA4MTAKcmVnWzB4MTA0NF09NDA5
+NgpyZWdbMHgxMDQ4XT02NTUzNgpyZWdbMHgxMDRjXT0xNTM2CnJlZ1sweDEwNTBdPTkwMjQKcmVn
+WzB4MTA1NF09OTIxNgpyZWdbMHgxMDU4XT0yMDQ4CnJlZ1sweDEwNWNdPTEyOApyZWdbMHgxMDYw
+XT04MTkyCnJlZ1sweDEwNjRdPTE2Mzg0CnJlZ1sweDEwYTRdPTB4YTAwMGEwMDAvMHhmMDAwZjAw
+MApyZWdbMHgxMGE4XT0weDIwMDAvMHgyMDAwCnNnZV90aW1lcl92YWx1ZT01LDEwLDIwLDUwLDEw
+MCwyMDAKcmVnWzB4N2QwNF09MHgwMDAxMDAwMC8weDAwMDEwMDAwCnJlZ1sweDdkYzBdPTB4MGUy
+Zjg4NDkKZmlsdGVyTW9kZT1mcmFnbWVudGF0aW9uLG1wc2hpdHR5cGUscHJvdG9jb2wsdmxhbixw
+b3J0LGZjb2UKZmlsdGVyTWFzaz1wcm90b2NvbCxmY29lCnRwX3Btcng9MzQKdHBfcG1yeF9wYWdl
+c2l6ZT02NEsKdHBfbnJ4Y2g9MAp0cF9wbXR4PTMyCnRwX3BtdHhfcGFnZXNpemU9NjRLCnRwX250
+eGNoPTAKdHBfbXR1cz04OCwyNTYsNTEyLDU3Niw4MDgsMTAyNCwxMjgwLDE0ODgsMTUwMCwyMDAy
+LDIwNDgsNDA5Niw0MzUyLDgxOTIsOTAwMCw5NjAwCnJlZ1sweDE5MTY4XT0weDA0MDIwMTAwCltm
+dW5jdGlvbiIwIl0KbnZmPTE2Cnd4X2NhcHM9YWxsCnJfY2Fwcz1hbGwKbnZpPTEKbmlxZmxpbnQ9
+OApuZXRoY3RybD04Cm5lcT0xNgpuZXhhY3RmPTgKY21hc2s9YWxsCnBtYXNrPTB4MQpbZnVuY3Rp
+b24iMSJdCm52Zj0xNgp3eF9jYXBzPWFsbApyX2NhcHM9YWxsCm52aT0xCm5pcWZsaW50PTgKbmV0
+aGN0cmw9OApuZXE9MTYKbmV4YWN0Zj04CmNtYXNrPWFsbApwbWFzaz0weDIKW2Z1bmN0aW9uIjIi
+XQpudmY9MTYKd3hfY2Fwcz1hbGwKcl9jYXBzPWFsbApudmk9MQpuaXFmbGludD04Cm5ldGhjdHJs
+PTgKbmVxPTE2Cm5leGFjdGY9OApjbWFzaz1hbGwKcG1hc2s9MHg0CltmdW5jdGlvbiIzIl0KbnZm
+PTE2Cnd4X2NhcHM9YWxsCnJfY2Fwcz1hbGwKbnZpPTEKbmlxZmxpbnQ9OApuZXRoY3RybD04Cm5l
+cT0xNgpuZXhhY3RmPTgKY21hc2s9YWxsCnBtYXNrPTB4OApbZnVuY3Rpb24iNCJdCnd4X2NhcHM9
+YWxsCnJfY2Fwcz1hbGwKbnZpPTI4Cm5pcWZsaW50PTE3MApuZXRoY3RybD0xMDAKbmVxPTI1Ngpu
+ZXhhY3RmPTQwCmNtYXNrPWFsbApwbWFzaz1hbGwKbmV0aG9mbGQ9MTAyNApucm91dGU9MzIKbmNs
+aXA9MzIKbmZpbHRlcj00OTYKbnNlcnZlcj00OTYKbmhhc2g9MTIyODgKcHJvdG9jb2w9bmljX3Zt
+LG9mbGQscmRkcCxyZG1hYyxpc2NzaV9pbml0aWF0b3JfcGR1LGlzY3NpX3RhcmdldF9wZHUKdHBf
+bDJ0PTMwNzIKdHBfZGRwPTMKdHBfZGRwX2lzY3NpPTIKdHBfc3RhZz0zCnRwX3BibD0xMAp0cF9y
+cT0xMwpbZnVuY3Rpb24iNSJdCnd4X2NhcHM9YWxsCnJfY2Fwcz1hbGwKbnZpPTQKbmlxZmxpbnQ9
+MzQKbmV0aGN0cmw9MzIKbmVxPTY0Cm5leGFjdGY9NApjbWFzaz1hbGwKcG1hc2s9YWxsCm5zZXJ2
+ZXI9MTYKbmhhc2g9MjA0OAp0cF9sMnQ9MTAyMApwcm90b2NvbD1pc2NzaV9pbml0aWF0b3JfZm9m
+bGQKdHBfZGRwX2lzY3NpPTIKaXNjc2lfbnRhc2s9MjA0OAppc2NzaV9uc2Vzcz0yMDQ4CmlzY3Np
+X25jb25uX3Blcl9zZXNzaW9uPTEKaXNjc2lfbmluaXRpYXRvcl9pbnN0YW5jZT02NApbZnVuY3Rp
+b24iNiJdCnd4X2NhcHM9YWxsCnJfY2Fwcz1hbGwKbnZpPTQKbmlxZmxpbnQ9MzQKbmV0aGN0cmw9
+MzIKbmVxPTY2Cm5leGFjdGY9MzIKY21hc2s9YWxsCnBtYXNrPWFsbApuaGFzaD0yMDQ4CnRwX2wy
+dD00CnByb3RvY29sPWZjb2VfaW5pdGlhdG9yCnRwX2RkcD0xCmZjb2VfbmZjZj0xNgpmY29lX252
+bnA9MzIKZmNvZV9uc3NuPTEwMjQKW2Z1bmN0aW9uIjEwMjMiXQp3eF9jYXBzPWFsbApyX2NhcHM9
+YWxsCm52aT00CmNtYXNrPWFsbApwbWFzaz1hbGwKbmV4YWN0Zj04Cm5maWx0ZXI9MTYKW2Z1bmN0
+aW9uIjAvKiJdCnd4X2NhcHM9MHg4MgpyX2NhcHM9MHg4Ngpudmk9MQpuaXFmbGludD00Cm5ldGhj
+dHJsPTIKbmVxPTQKbmV4YWN0Zj00CmNtYXNrPWFsbApwbWFzaz0weDEKW2Z1bmN0aW9uIjEvKiJd
+Cnd4X2NhcHM9MHg4MgpyX2NhcHM9MHg4Ngpudmk9MQpuaXFmbGludD00Cm5ldGhjdHJsPTIKbmVx
+PTQKbmV4YWN0Zj00CmNtYXNrPWFsbApwbWFzaz0weDIKW2Z1bmN0aW9uIjIvKiJdCnd4X2NhcHM9
+MHg4MgpyX2NhcHM9MHg4Ngpudmk9MQpuaXFmbGludD00Cm5ldGhjdHJsPTIKbmVxPTQKbmV4YWN0
+Zj00CmNtYXNrPWFsbApwbWFzaz0weDQKW2Z1bmN0aW9uIjMvKiJdCnd4X2NhcHM9MHg4MgpyX2Nh
+cHM9MHg4Ngpudmk9MQpuaXFmbGludD00Cm5ldGhjdHJsPTIKbmVxPTQKbmV4YWN0Zj00CmNtYXNr
+PWFsbApwbWFzaz0weDgKW3BvcnQiMCJdCmRjYj1wcHAsZGNieApiZ19tZW09MjUKbHBia19tZW09
+MjUKaHdtPTMwCmx3bT0xNQpkd209MzAKZGNiX2FwcF90bHZbMF09MHg4OTA2LGV0aGVydHlwZSwz
+CmRjYl9hcHBfdGx2WzFdPTB4ODkxNCxldGhlcnR5cGUsMwpkY2JfYXBwX3RsdlsyXT0zMjYwLHNv
+Y2tldG51bSw1Cltwb3J0IjEiXQpkY2I9cHBwLGRjYngKYmdfbWVtPTI1CmxwYmtfbWVtPTI1Cmh3
+bT0zMApsd209MTUKZHdtPTMwCmRjYl9hcHBfdGx2WzBdPTB4ODkwNixldGhlcnR5cGUsMwpkY2Jf
+YXBwX3RsdlsxXT0weDg5MTQsZXRoZXJ0eXBlLDMKZGNiX2FwcF90bHZbMl09MzI2MCxzb2NrZXRu
+dW0sNQpbcG9ydCIyIl0KZGNiPXBwcCxkY2J4CmJnX21lbT0yNQpscGJrX21lbT0yNQpod209MzAK
+bHdtPTE1CmR3bT0zMApkY2JfYXBwX3RsdlswXT0weDg5MDYsZXRoZXJ0eXBlLDMKZGNiX2FwcF90
+bHZbMV09MHg4OTE0LGV0aGVydHlwZSwzCmRjYl9hcHBfdGx2WzJdPTMyNjAsc29ja2V0bnVtLDUK
+W3BvcnQiMyJdCmRjYj1wcHAsZGNieApiZ19tZW09MjUKbHBia19tZW09MjUKaHdtPTMwCmx3bT0x
+NQpkd209MzAKZGNiX2FwcF90bHZbMF09MHg4OTA2LGV0aGVydHlwZSwzCmRjYl9hcHBfdGx2WzFd
+PTB4ODkxNCxldGhlcnR5cGUsMwpkY2JfYXBwX3RsdlsyXT0zMjYwLHNvY2tldG51bSw1CltmaW5p
+XQp2ZXJzaW9uPTB4MTQyNTAwMWMKY2hlY2tzdW09MHg2M2E2NTJiMwoAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABbZ2xvYmFsXQpyc3NfZ2xiX2NvbmZp
-Z19tb2RlPWJhc2ljdmlydHVhbApyc3NfZ2xiX2NvbmZpZ19vcHRpb25zPXRubG1hcGVuLGhhc2h0
-b2VwbGl0eix0bmxhbGxsa3AKcmVnWzB4MTAwOF09MHg0MDgxMC8weDIxYzcwCnJlZ1sweDEwMGNd
-PTB4MjIyMjIyMjIKcmVnWzB4MTBhMF09MHgwMTA0MDgxMApyZWdbMHgxMDQ0XT00MDk2CnJlZ1sw
-eDEwNDhdPTY1NTM2CnJlZ1sweDEwNGNdPTE1MzYKcmVnWzB4MTA1MF09OTAyNApyZWdbMHgxMDU0
-XT05MjE2CnJlZ1sweDEwNThdPTIwNDgKcmVnWzB4MTA1Y109MTI4CnJlZ1sweDEwNjBdPTgxOTIK
-cmVnWzB4MTA2NF09MTYzODQKcmVnWzB4MTBhNF09MHhhMDAwYTAwMC8weGYwMDBmMDAwCnJlZ1sw
-eDEwYThdPTB4MjAwMC8weDIwMDAKc2dlX3RpbWVyX3ZhbHVlPTUsMTAsMjAsNTAsMTAwLDIwMApy
-ZWdbMHg3ZDA0XT0weDAwMDEwMDAwLzB4MDAwMTAwMDAKcmVnWzB4N2RjMF09MHgwZTJmODg0OQpm
-aWx0ZXJNb2RlPWZyYWdtZW50YXRpb24sbXBzaGl0dHlwZSxwcm90b2NvbCx2bGFuLHBvcnQsZmNv
-ZQpmaWx0ZXJNYXNrPXByb3RvY29sLGZjb2UKdHBfcG1yeD0zMAp0cF9wbXJ4X3BhZ2VzaXplPTY0
-Swp0cF9ucnhjaD0wCnRwX3BtdHg9NTAKdHBfcG10eF9wYWdlc2l6ZT02NEsKdHBfbnR4Y2g9MAp0
-cF9tdHVzPTg4LDI1Niw1MTIsNTc2LDgwOCwxMDI0LDEyODAsMTQ4OCwxNTAwLDIwMDIsMjA0OCw0
-MDk2LDQzNTIsODE5Miw5MDAwLDk2MDAKcmVnWzB4MTkxNjhdPTB4MDQwMjAxMDAKW2Z1bmN0aW9u
-IjAiXQp3eF9jYXBzPWFsbApyX2NhcHM9YWxsCm52aT0yOApuaXFmbGludD0xNzAKbmV0aGN0cmw9
-OTYKbmVxPTI1MgpuZXhhY3RmPTQwCmNtYXNrPWFsbApwbWFzaz1hbGwKbmV0aG9mbGQ9MTAyNApu
-cm91dGU9MzIKbmNsaXA9MzIKbmZpbHRlcj00OApuc2VydmVyPTMyCm5oYXNoPTAKcHJvdG9jb2w9
-bmljX3ZtLG9mbGQscmRkcCxyZG1hYyxpc2NzaV9pbml0aWF0b3JfcGR1LGlzY3NpX3RhcmdldF9w
-ZHUKdHBfbDJ0PTMwNzIKdHBfZGRwPTIKdHBfZGRwX2lzY3NpPTIKdHBfc3RhZz0yCnRwX3BibD01
-CnRwX3JxPTcKW2Z1bmN0aW9uIjEiXQp3eF9jYXBzPWFsbApyX2NhcHM9YWxsCm52aT00Cm5pcWZs
-aW50PTM0Cm5ldGhjdHJsPTMyCm5lcT02NgpuZXhhY3RmPTMyCmNtYXNrPWFsbApwbWFzaz1hbGwK
-bmhhc2g9MApwcm90b2NvbD1mY29lX2luaXRpYXRvcgp0cF9kZHA9MgpmY29lX25mY2Y9MTYKZmNv
-ZV9udm5wPTMyCmZjb2VfbnNzbj0xMDI0CltmdW5jdGlvbiIxMDIzIl0Kd3hfY2Fwcz1hbGwKcl9j
-YXBzPWFsbApudmk9NApjbWFzaz1hbGwKcG1hc2s9YWxsCm5leGFjdGY9OApuZmlsdGVyPTE2Cltm
-dW5jdGlvbiIwLyoiXQp3eF9jYXBzPTB4ODIKcl9jYXBzPTB4ODYKbnZpPTEKbmlxZmxpbnQ9NApu
-ZXRoY3RybD0yCm5lcT00Cm5leGFjdGY9NApjbWFzaz1hbGwKcG1hc2s9MHgxCltmdW5jdGlvbiIx
-LyoiXQp3eF9jYXBzPTB4ODIKcl9jYXBzPTB4ODYKbnZpPTEKbmlxZmxpbnQ9NApuZXRoY3RybD0y
-Cm5lcT00Cm5leGFjdGY9NApjbWFzaz1hbGwKcG1hc2s9MHgyCltwb3J0IjAiXQpkY2I9cHBwLGRj
-YngKYmdfbWVtPTI1CmxwYmtfbWVtPTI1Cmh3bT0zMApsd209MTUKZHdtPTMwCmRjYl9hcHBfdGx2
-WzBdPTB4ODkwNixldGhlcnR5cGUsMwpkY2JfYXBwX3RsdlsxXT0weDg5MTQsZXRoZXJ0eXBlLDMK
-ZGNiX2FwcF90bHZbMl09MzI2MCxzb2NrZXRudW0sNQpbcG9ydCIxIl0KZGNiPXBwcCxkY2J4CmJn
-X21lbT0yNQpscGJrX21lbT0yNQpod209MzAKbHdtPTE1CmR3bT0zMApkY2JfYXBwX3RsdlswXT0w
-eDg5MDYsZXRoZXJ0eXBlLDMKZGNiX2FwcF90bHZbMV09MHg4OTE0LGV0aGVydHlwZSwzCmRjYl9h
-cHBfdGx2WzJdPTMyNjAsc29ja2V0bnVtLDUKW3BvcnQiMiJdCmRjYj1wcHAsZGNieApiZ19tZW09
-MjUKbHBia19tZW09MjUKaHdtPTMwCmx3bT0xNQpkd209MzAKZGNiX2FwcF90bHZbMF09MHg4OTA2
-LGV0aGVydHlwZSwzCmRjYl9hcHBfdGx2WzFdPTB4ODkxNCxldGhlcnR5cGUsMwpkY2JfYXBwX3Rs
-dlsyXT0zMjYwLHNvY2tldG51bSw1Cltwb3J0IjMiXQpkY2I9cHBwLGRjYngKYmdfbWVtPTI1Cmxw
-YmtfbWVtPTI1Cmh3bT0zMApsd209MTUKZHdtPTMwCmRjYl9hcHBfdGx2WzBdPTB4ODkwNixldGhl
-cnR5cGUsMwpkY2JfYXBwX3RsdlsxXT0weDg5MTQsZXRoZXJ0eXBlLDMKZGNiX2FwcF90bHZbMl09
-MzI2MCxzb2NrZXRudW0sNQpbZmluaV0KdmVyc2lvbj0weDE0MjUwMDFjCmNoZWNrc3VtPTB4Mjdk
-ZmU4MDUKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFtnbG9iYWxdCnJzc19nbGJfY29uZmln
+X21vZGU9YmFzaWN2aXJ0dWFsCnJzc19nbGJfY29uZmlnX29wdGlvbnM9dG5sbWFwZW4saGFzaHRv
+ZXBsaXR6LHRubGFsbGxrcApyZWdbMHgxMDA4XT0weDQwODEwLzB4MjFjNzAKcmVnWzB4MTAwY109
+MHgyMjIyMjIyMgpyZWdbMHgxMGEwXT0weDAxMDQwODEwCnJlZ1sweDEwNDRdPTQwOTYKcmVnWzB4
+MTA0OF09NjU1MzYKcmVnWzB4MTA0Y109MTUzNgpyZWdbMHgxMDUwXT05MDI0CnJlZ1sweDEwNTRd
+PTkyMTYKcmVnWzB4MTA1OF09MjA0OApyZWdbMHgxMDVjXT0xMjgKcmVnWzB4MTA2MF09ODE5Mgpy
+ZWdbMHgxMDY0XT0xNjM4NApyZWdbMHgxMGE0XT0weGEwMDBhMDAwLzB4ZjAwMGYwMDAKcmVnWzB4
+MTBhOF09MHgyMDAwLzB4MjAwMApzZ2VfdGltZXJfdmFsdWU9NSwxMCwyMCw1MCwxMDAsMjAwCnJl
+Z1sweDdkMDRdPTB4MDAwMTAwMDAvMHgwMDAxMDAwMApyZWdbMHg3ZGMwXT0weDBlMmY4ODQ5CmZp
+bHRlck1vZGU9ZnJhZ21lbnRhdGlvbixtcHNoaXR0eXBlLHByb3RvY29sLHZsYW4scG9ydCxmY29l
+CmZpbHRlck1hc2s9cHJvdG9jb2wsZmNvZQp0cF9wbXJ4PTMwCnRwX3BtcnhfcGFnZXNpemU9NjRL
+CnRwX25yeGNoPTAKdHBfcG10eD01MAp0cF9wbXR4X3BhZ2VzaXplPTY0Swp0cF9udHhjaD0wCnRw
+X210dXM9ODgsMjU2LDUxMiw1NzYsODA4LDEwMjQsMTI4MCwxNDg4LDE1MDAsMjAwMiwyMDQ4LDQw
+OTYsNDM1Miw4MTkyLDkwMDAsOTYwMApyZWdbMHgxOTE2OF09MHgwNDAyMDEwMApbZnVuY3Rpb24i
+MCJdCnd4X2NhcHM9YWxsCnJfY2Fwcz1hbGwKbnZpPTI4Cm5pcWZsaW50PTE3MApuZXRoY3RybD05
+NgpuZXE9MjUyCm5leGFjdGY9NDAKY21hc2s9YWxsCnBtYXNrPWFsbApuZXRob2ZsZD0xMDI0Cm5y
+b3V0ZT0zMgpuY2xpcD0zMgpuZmlsdGVyPTQ4Cm5zZXJ2ZXI9MzIKbmhhc2g9MApwcm90b2NvbD1u
+aWNfdm0sb2ZsZCxyZGRwLHJkbWFjLGlzY3NpX2luaXRpYXRvcl9wZHUsaXNjc2lfdGFyZ2V0X3Bk
+dQp0cF9sMnQ9MzA3Mgp0cF9kZHA9Mgp0cF9kZHBfaXNjc2k9Mgp0cF9zdGFnPTIKdHBfcGJsPTUK
+dHBfcnE9NwpbZnVuY3Rpb24iMSJdCnd4X2NhcHM9YWxsCnJfY2Fwcz1hbGwKbnZpPTQKbmlxZmxp
+bnQ9MzQKbmV0aGN0cmw9MzIKbmVxPTY2Cm5leGFjdGY9MzIKY21hc2s9YWxsCnBtYXNrPWFsbApu
+aGFzaD0wCnByb3RvY29sPWZjb2VfaW5pdGlhdG9yCnRwX2RkcD0yCmZjb2VfbmZjZj0xNgpmY29l
+X252bnA9MzIKZmNvZV9uc3NuPTEwMjQKW2Z1bmN0aW9uIjEwMjMiXQp3eF9jYXBzPWFsbApyX2Nh
+cHM9YWxsCm52aT00CmNtYXNrPWFsbApwbWFzaz1hbGwKbmV4YWN0Zj04Cm5maWx0ZXI9MTYKW2Z1
+bmN0aW9uIjAvKiJdCnd4X2NhcHM9MHg4MgpyX2NhcHM9MHg4Ngpudmk9MQpuaXFmbGludD00Cm5l
+dGhjdHJsPTIKbmVxPTQKbmV4YWN0Zj00CmNtYXNrPWFsbApwbWFzaz0weDEKW2Z1bmN0aW9uIjEv
+KiJdCnd4X2NhcHM9MHg4MgpyX2NhcHM9MHg4Ngpudmk9MQpuaXFmbGludD00Cm5ldGhjdHJsPTIK
+bmVxPTQKbmV4YWN0Zj00CmNtYXNrPWFsbApwbWFzaz0weDIKW3BvcnQiMCJdCmRjYj1wcHAsZGNi
+eApiZ19tZW09MjUKbHBia19tZW09MjUKaHdtPTMwCmx3bT0xNQpkd209MzAKZGNiX2FwcF90bHZb
+MF09MHg4OTA2LGV0aGVydHlwZSwzCmRjYl9hcHBfdGx2WzFdPTB4ODkxNCxldGhlcnR5cGUsMwpk
+Y2JfYXBwX3RsdlsyXT0zMjYwLHNvY2tldG51bSw1Cltwb3J0IjEiXQpkY2I9cHBwLGRjYngKYmdf
+bWVtPTI1CmxwYmtfbWVtPTI1Cmh3bT0zMApsd209MTUKZHdtPTMwCmRjYl9hcHBfdGx2WzBdPTB4
+ODkwNixldGhlcnR5cGUsMwpkY2JfYXBwX3RsdlsxXT0weDg5MTQsZXRoZXJ0eXBlLDMKZGNiX2Fw
+cF90bHZbMl09MzI2MCxzb2NrZXRudW0sNQpbcG9ydCIyIl0KZGNiPXBwcCxkY2J4CmJnX21lbT0y
+NQpscGJrX21lbT0yNQpod209MzAKbHdtPTE1CmR3bT0zMApkY2JfYXBwX3RsdlswXT0weDg5MDYs
+ZXRoZXJ0eXBlLDMKZGNiX2FwcF90bHZbMV09MHg4OTE0LGV0aGVydHlwZSwzCmRjYl9hcHBfdGx2
+WzJdPTMyNjAsc29ja2V0bnVtLDUKW3BvcnQiMyJdCmRjYj1wcHAsZGNieApiZ19tZW09MjUKbHBi
+a19tZW09MjUKaHdtPTMwCmx3bT0xNQpkd209MzAKZGNiX2FwcF90bHZbMF09MHg4OTA2LGV0aGVy
+dHlwZSwzCmRjYl9hcHBfdGx2WzFdPTB4ODkxNCxldGhlcnR5cGUsMwpkY2JfYXBwX3RsdlsyXT0z
+MjYwLHNvY2tldG51bSw1CltmaW5pXQp2ZXJzaW9uPTB4MTQyNTAwMWMKY2hlY2tzdW09MHgyN2Rm
+ZTgwNQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
====
diff --git a/sys/dev/cxgbe/firmware/t4fw_interface.h b/sys/dev/cxgbe/firmware/t4fw_interface.h
index bd43668..2ee58ba 100644
--- a/sys/dev/cxgbe/firmware/t4fw_interface.h
+++ b/sys/dev/cxgbe/firmware/t4fw_interface.h
@@ -8198,12 +8198,12 @@ enum fw_hdr_chip {
enum {
T4FW_VERSION_MAJOR = 0x01,
T4FW_VERSION_MINOR = 0x0e,
- T4FW_VERSION_MICRO = 0x02,
+ T4FW_VERSION_MICRO = 0x04,
T4FW_VERSION_BUILD = 0x00,
T5FW_VERSION_MAJOR = 0x01,
T5FW_VERSION_MINOR = 0x0e,
- T5FW_VERSION_MICRO = 0x02,
+ T5FW_VERSION_MICRO = 0x04,
T5FW_VERSION_BUILD = 0x00,
};
diff --git a/sys/dev/cxgbe/firmware/t5fw-1.14.2.0.bin.uu b/sys/dev/cxgbe/firmware/t5fw-1.14.4.0.bin.uu
index ed9375b..dc35d5a 100644
--- a/sys/dev/cxgbe/firmware/t5fw-1.14.2.0.bin.uu
+++ b/sys/dev/cxgbe/firmware/t5fw-1.14.4.0.bin.uu
@@ -24,15 +24,15 @@
* SUCH DAMAGE.
*/
begin-base64 644 t5fw
-AAEEiAEOAgAAAQQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAEEiAEOBAAAAQQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAABGoEeQSBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAENoZWxzaW8gRlcgUlVOTUVNIERFQlVHPTAgKEJ1aWx0IE1vbiBKdWwgMTMgMjE6
-Mjc6MzMgUERUIDIwMTUgb24gY2xlb3BhdHJhLmFzaWNkZXNpZ25lcnMuY29tOi9ob21lL2Zpcm13
-YXJlL2N2cy9mdy1yZWxlYXNlKSwgVmVyc2lvbiBUNXh4IDAxLjBlLjAyLjAwAAAAAAAAAOe+ZdRg
+AAAAAAAAAAAAAENoZWxzaW8gRlcgUlVOTUVNIERFQlVHPTAgKEJ1aWx0IFRodSBKdWwgMjMgMDA6
+NDM6NDUgUERUIDIwMTUgb24gY2xlb3BhdHJhLmFzaWNkZXNpZ25lcnMuY29tOi9ob21lL2Zpcm13
+YXJlL2N2cy9mdy1yZWxlYXNlKSwgVmVyc2lvbiBUNXh4IDAxLjBlLjA0LjAwAAAAAAAAAEXtwlZg
AMgAH/zhSOEAe/AAEAAA4QAwuHj///8f/OFAgAAAAeEAe3AAABAAH//87CAAAADhAZwE4QUAAAAC
AEDhBQgAAAYAQAACAAwABgAM4QUABAAMAACAAAEC4QB7POEAe0ThAHvk4gAAAAABAADhAHuQIAAA
AAAAgADhAHsAAABAAeEAe5wAAEAAREREQuAAAADjAARzREREQOMACAAgAAJcAAAAAB//k2AAAAAA
@@ -67,8 +67,8 @@ nOMAffwgAAGcIAABpeMAfgAgAAG4IAABvOMAfgwgAAG8IAABxeMAfhAgAAHYIAAB2OMAfhwgAAHc
IAAB4uMAfhwgAAH4IAAB+OMAfiQgAAH8IAAB/OMAfiQgAAIYIAACGOMAfiQgAAIcIAACHOMAfiQg
AAI4IAACOOMAfiQgAAI8IAACPOMAfiQgAAJYIAACWOMAfiQgAAJcIAACYuMAfiQgAAJ4IAACeOMA
fiwgAAJ8IAACguMAfiwgAAKYIAIB8uMAfjQgAwAAIAMXCOMCfZAgAxcIIAMXCOMClJggAxcIIAdS
-bOMClJggB1JwIAdYIOMG0AAgCAAAIAgWEOMG1bAgCBYQIAk/UuMG68AgCT9gIAlA4OMIFRAgCwAA
-IAsAAOMIFpAgCwAAIAsAAOMIFpAgCwAAIAu9L+MIFpAAAAAAAAAAAAAAAAAgADeuIAA3oCAAO5Ig
+fOMClJggB1KAIAdYMOMG0BAgCAAAIAgWEOMG1cAgCBYQIAk/cuMG69AgCT+AIAlBAOMIFUAgCwAA
+IAsAAOMIFsAgCwAAIAsAAOMIFsAgCwAAIAu9L+MIFsAAAAAAAAAAAAAAAAAgADeuIAA3oCAAO5Ig
ADegIAA7DSAAN6AgADhVIAA6pSAAOiogADegIAA51SAAOYwgADkhIAA3jSAAOMwgADegIAA3oCAA
N6AgADh0AAAAAAEQGAEABAAAAAAAAAAAAAD///////8P/P//8P///wD8IADH2yAAyRcgAMlIIADJ
DyAAyNUgAMjOIADIlyAAyI8gAMiHIADIOiAAyUYgAMgyIADIDiAAyUggAMgHAAAAAAAAAAoAAAAK
@@ -77,9 +77,9 @@ AQACAAMABAAFAAYABwAIAAkACgAOABEAFQAZAB4AIwAtADwAUABkAMgBLAGQAfQAAAAAAAAAAAAA
AAAAAAAAAAAAAQABAAIAAgADAAMAAwADAAQABAAEAAQABAAFAAUABQAFAAUABQAGAAYABwAHAAAA
AgAAAAYAAAAKAAAADgAAABQAAAAcAAAAKAAAADgAAABQAAAAcAAAAKAAAADgAAABQAAAAcAAAAKA
AAADgAAABQEAAAcAAAAKAAAADgAAABQAAAAcAAAAKAAAADgAAABQAAAAcAAAAKAAAADgAAABQAAA
-AcAAAAKAAAADgAD/AAECAgAAAAAAAAAAAAAAIAijQyAIo5AgCKLjIAiiriAIo5AgCKHPIAihzyAI
-o5AgCKOQIAihzyAIo5AgCKOQIAihzCAIoc8gCKF9IAijkCAIo5AgCKOQIAijkCAIo5AgCKOQIAij
-kCAIo5AgCKOQIAijkCAIo5AgCKOQIAijkCAIo5AgCKOQIAijkCAIoacgAwtYAAAAASADD9gAAAD/
+AcAAAAKAAAADgAD/AAECAgAAAAAAAAAAAAAAIAijUyAIo6AgCKLzIAiiviAIo6AgCKHfIAih3yAI
+o6AgCKOgIAih3yAIo6AgCKOgIAih3CAIod8gCKGNIAijoCAIo6AgCKOgIAijoCAIo6AgCKOgIAij
+oCAIo6AgCKOgIAijoCAIo6AgCKOgIAijoCAIo6AgCKOgIAijoCAIobcgAwtYAAAAASADD9gAAAD/
IAMJEAAAAP8AAAAAAAAAACADC0QAAAACIAMLSAAAAAMgAwtQAAAABwAAAAAAAAAAIAMLKAAAAAEg
AwssAAAAAiADCzQAAAAEIAMP2AAAAP8gAwkQAAAA/wAAAAAAAAAAIAMJEAAAAAAgAw/YAAAAACAD
CkAAAAABIAMKSAAAAAQgAwpQAAAACCADClwAAAAgIAMKbAAAAEAgAwp0AAAAgCADCnwAAAEAIAMK
@@ -87,13 +87,13 @@ hAAAAgAgAwqYAAAEACADCqwAAAgAIAMKxAAAEAAgAwrYAAAgACADCugAAEAAIAMK9AAAgAAgAwsI
AAEAACADCxgAAgAACAQCAAAAAAAAAAAAAAAAACADCiwAAAAQIAMKNAAAABEgAwoUAAAAACADChgA
AAABIAMKHAAAAAIgAwokAAAAAwAAAAAAAP//AAAAAAAA//8gAwmUAAABACADCaAAAACAIAMJsAAA
AEAgAwnAAAAAICADCdAAAAAQIAMJ4AAAAAggAwnsAAAABCADCfgAAAACIAMKBAAAAAEAAAAAAAAA
-ACAJJvAgCSaqIAkm5iAJJuYgCSaqIAkmqiAJJvAgCSbwIAkmqiAJJvAgCSaqIAkm8CAJJuYgCSaq
-IAkmqiAJJqogCSaqIAkmqiAJJvAgCSaqIAkmqiAJJqogCSaqIAkmqiAJJvAgCSbwIAkm8CAJJvAg
-CSbwIAkm8CAJJvAgCSbwIAkmqiAJJqogCSaqIAkmqiAJJqogCSaqIAkmqiAJJqogCSaqIAkmqiAJ
-JqogCSaqIAkmqiAJJqogCSaqIAkmqgACAgUFCAgLCw4OEREUFBcXGhodHSAgIyMmJikpLCwvLzIy
+ACAJJxAgCSbKIAknBiAJJwYgCSbKIAkmyiAJJxAgCScQIAkmyiAJJxAgCSbKIAknECAJJwYgCSbK
+IAkmyiAJJsogCSbKIAkmyiAJJxAgCSbKIAkmyiAJJsogCSbKIAkmyiAJJxAgCScQIAknECAJJxAg
+CScQIAknECAJJxAgCScQIAkmyiAJJsogCSbKIAkmyiAJJsogCSbKIAkmyiAJJsogCSbKIAkmyiAJ
+JsogCSbKIAkmyiAJJsogCSbKIAkmygACAgUFCAgLCw4OEREUFBcXGhodHSAgIyMmJikpLCwvLzIy
NTU4ODs7AAAAAAAAAAEDEREICBAJAwEAAAAAAAAgBO9oIAG/JCAAXUAgAZ2UIAG77CABt4AgAX8c
IAQBRB//6aAf/+YgIADKAB//2PwgAIiEIAB7IAAAAAAAAAAAIAGfMCAApyAAAAAAAAAAAB//0rQf
-/8SIH//CHB//wDAgAHcoIABv4CAAbmQgAL+4H//g5CAHHPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+/8SIH//CHB//wDAgAHcoIABv4CAAbmQgAL+4H//g5CAHHQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAIAHF/CABr8ggANI8IADRYB//73gf/82IH//KMCAApPAgBWDQIAFA
6CABIhwgAQswIAD/ACAA8MAgAObwIADUWCAE8MAgBDOAIAE2KCAEV0wgAe9cIACIQAAAAAAgANKc
IAXVaCAAx0AgAaZMIAASICAAudggAA1YIANalB//8qggANJYIAQ2GAAAAAAAAAAAIAN99CAATgAg
@@ -112,13 +112,13 @@ AAAgAw+sAQAAACADFpAAAAAAAAAAANdqpHjox7dWJCBw28G9zu71fA+vR4fGKqgwRhP9RpUBaYCY
3s+p9rtLYL6/vHAom37G6qEn+tTvMIUEiB0F2dTQOebbmeUfonz4xKxWZfQpIkRDKv+Xq5Qjp/yT
oDllW1nDjwzMkv/v9H2FhF3Rb6h+T/4s5uCjAUMUTggRofdTfoK9OvI1KtfSu+uG05EHDBEWBwwR
FgcMERYHDBEWBQkOFAUJDhQFCQ4UBQkOFAQLEBcECxAXBAsQFwQLEBcGCg8VBgoPFQYKDxUGCg8V
-H//AAAAEACAgB1ggIAdb4B/84gAf/6yEH/+s9B//sEADgAAAgQAAAB//sDAA//gAAQAAAAAQAACB
+H//AAAAEACAgB1gwIAdb8B/84gAf/6yEH/+s9B//sEADgAAAgQAAAB//sDAA//gAAQAAAAAQAACB
BAEAgQQAAAEEAAABBAEAAAf//4AAAAAqAAAAH/+E0AYAAAAf/80QIARv7AIAAACAEAAAgAAABUFA
AABBQAEAgwAAAR//mPwEAAAIIAMNvAwAAACBgAAA//+//7////8f/5Ow//8AAP//AP/wAAAA/3//
-/x/84uQAQAAAH/+o5AABAAAAAP//H/+xMB//lGAP///////QFB//Zswf/ODoIAdV/B//ZyQf/N4A
+/x/84uQAQAAAH/+o5AABAAAAAP//H/+xMB//lGAP///////QFB//Zswf/ODoIAdWDB//ZyQf/N4A
H/9mgP//wNAf/62kH/+fFAAACGjg//4A4QGSAB//mZAA////H/+dbB//rbQEQQAIBAEACMAAAADA
BAAApQAAADAAAAAf/5vw4QP+AOEEbgAAAIWEAACFgCALc1AgC3QQIAtzkCALc9Af/64wAAAcYAAA
-/4AgB1hwIAdT6CALdFDhAC4AH/+uJB//qUQf/68AH/+qcAAAFsAf/63w4AAAoOEAMLgAAIAA4QBg
+/4AgB1iAIAdT+CALdFDhAC4AH/+uJB//qUQf/68AH/+qcAAAFsAf/63w4AAAoOEAMLgAAIAA4QBg
EAAAQADhAwgA4QNIAOEDiADhA8gA4QAQCB/84UDhAHtwH/+0bB//tGQf/OAIH/+0aB//tIQf/7R8
H/+0gB//tJwf/7SUH/+0mB/84gAf/6yEH/+qWB//nWwgAdd8H/+u/AAA/4AAAB1AH/+TsB//sECB
gAAABAAACIKAAACBAAAAIAMNsAwAAAAf/5mMH/+ZfB//nwz//7//v////wQBAAjDAAAAH/+xMB//
@@ -139,7 +139,7 @@ ACBgAAAf/6wEH/+dfB//nXAgC4ugAAMHgCALjBAf/5tUACAAAABAAAAAAAkAAAAwAP/8+H+j/7sA
o/+6AOADAACD/7YAD////w//+AD/AAAAD//+ASALjFAgCyxwIAssoCALjOAADwAAAAoAAP//AA8f
/62IA//AAIP/wAAgC41gIAuN0B//rmAf/7HAH/+xoP9g8AAf/4BgH/+TcASAAAgARAAA/x///wDA
AAABgMIAAACBAP+//////wAAAIAAAAAACWwf/OIMDwAAACALLOAf/638AAAIbB//rvQf/59oH/+Z
-eB//gHAgB1RAAAAnEB//2DAgC5RQH/+uVB//nWTerb7vIAMIwDQAAAA/AAAAH/+uyACZAAAAAIkG
+eB//gHAgB1RQAAAnEB//2DAgC5RQH/+uVB//nWTerb7vIAMIwDQAAAA/AAAAH/+uyACZAAAAAIkG
EAAHAgHAgACZAAAAH/+xxACIAAiCgAABH/+xWB//r1AADwP/AxEAAAMVAAAgCzEAIAsxYCALMbAg
CzIQIAsxMCAA+aAgCzOwIAsz4CALNDAgCzSQIAD/SCkAAAAgAQXoIAuUoCALlQAgC5VwH/+wZPDw
8PD/AP8AqqqqqszMzMwf/7PQAAAgIB//sdggARacIAuWACALlnAgBFyIH/+t4B//rkAACQAAAAAg
@@ -147,19 +147,19 @@ AAAASACCAAAAIAE54CALlvAgC5dgIAAo7CALnDAgC5xgIAs6ECALOeAgCzogIAs6gCALOwAgCzpQ
IAs6oCALOtAgCzygIAs88CALmnAgC5qQIAs9ICALPXAgC5swIAubUCALPNAgC5uAIAuawCALmvAg
Cz2gIAueACALnpAgC50wIAudQCALnMAgC52gIAudACALnNAgC52AIAueECALndAgC55QAAAfQCAL
QCAgC0BAIAtAYAAJAAgf/7DMMAAAAB//scwf/66gIAtCkCALQnD///f/IAtC8CAEYkQAAIP/IAda
-KCAHWyAVoAAAH/+sEAAACAYAAA/+AACIzH8AAADwAAAAIAuh0AAMAAAf/7EYIAuh8CALoTAgC6GQ
+OCAHWzAVoAAAH/+sEAAACAYAAA/+AACIzH8AAADwAAAAIAuh0AAMAAAf/7EYIAuh8CALoTAgC6GQ
IAuiMCALoFAgC6DgAADgACALnsAgC59w//wAACALoLAf/5sIAAQD/woAAAAf/6/0MwAAAOEAAAAf
/7IUA//gAH///wAAAP/+AD/2kB//sSAAAB9oA//wACALisAgC4qAIAuK4B//syAgC0NgH/+qtBoA
-AAAgC0OwIAGTbB//sRwAD///H/+w0B//q9wf/66UIAuisB//rVQf/6ooH/+sHCAHU+Qf/6iwIAtG
+AAAgC0OwIAGTbB//sRwAD///H/+w0B//q9wf/66UIAuisB//rVQf/6ooH/+sHCAHU/Qf/6iwIAtG
sMAEAAAf/6woH/+xkB//sPggC6PAIAtG8B//q7DgAQAAH/+fECALpQAgC0cwIADEIB//nwggAMEo
IAukgCALpNAf/5soIAtJEB//nxQgC1Ww4P/+ACALepAf/62YH/+VbCALYqAgC2MwH/+sDB//sNQg
-B1hwIAtmUCALZqAgC2XgIAtmEEgAAAAgAdAwH/+rdCAB0jAf/6lEH/+Z7B//rDQf/6mcAAAXoAAA
-FewgB1hcH/+qBOEAXgAf/6sUAE01oAAASLkf/5mQ4QAuAB//rEDhAwYA4QAOAOAFAAAD/wAAH/+p
+B1iAIAtmUCALZqAgC2XgIAtmEEgAAAAgAdAwH/+rdCAB0jAf/6lEH/+Z7B//rDQf/6mcAAAXoAAA
+FewgB1hsH/+qBOEAXgAf/6sUAE01oAAASLkf/5mQ4QAuAB//rEDhAwYA4QAOAOAFAAAD/wAAH/+p
pCADDbwf/L//PAAAAAAH//+DAAAAH/+pTCAB9Bgf/65kIAt5sOAGAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAgYAAAAAAAAD/////////////////////H//8DB///Awf//vQH//70B//+9Af//vQH//0GB//
-+Igf//awH//2sB//9rAgBx7gAAAAAAAAAAAAAAAAAAAAACAHIVAgByFQAAAAAAAAAAAAAAAAAAAA
-ACAHHuAgBx7gH//5hB//+YQf//mEH//5hB//+YQf//mEAAAAACAB2JwAAAAAAAAAAAAAAAAAAAAA
++Igf//awH//2sB//9rAgBx7wAAAAAAAAAAAAAAAAAAAAACAHIWAgByFgAAAAAAAAAAAAAAAAAAAA
+ACAHHvAgBx7wH//5hB//+YQf//mEH//5hB//+YQf//mEAAAAACAB2JwAAAAAAAAAAAAAAAAAAAAA
AgEAAAAAAAAAAAAAAAAAAAQAAAAAAAAAgYAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@@ -306,7 +306,7 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAACAKABHyZxPyZ9MPA+YxAQIAFvJlF/Jmd2sGkGC0Zndj+FQPCVXk
-ZA8UAGP/+QAAAGwQCCggBSogBysxBfsWBCAUEEgw+gpBDgC8ShCLIhjyWPcKCSE7ALbgDKYRqGYs
+aA8UAGP/+QAAAGwQCCggBSogBysxBfsWBCAUEEgw+gpBDgC8ShCLIhjyWPcKCSE7ALbgDKYRqGYs
Yjr/AgAKALW/EBzyUitiOQysCizClwy7AfsWBSFcADbgLoJKGfJNZOEeKZJ/L4JJ+fsBDgCKz9Aq
IBQKpIf6JBQqALmWoBvyRS4iFogVLCEpH/JEn4D5Ih4sACBzMP/MEQAGEFAw/IYDIAIQaDD9hgIp
gAQ+YP3yOxgJAFZwmYGJFQALjfsSBCAgAkIwAAiKKDwQ/ZYGIEAQYDD8lgcgBBBgMPmcICoDAGbw
@@ -549,15 +549,15 @@ WxDMEEgwCSkoqYgogOD4hwpiAAAgsMAg0Q8AAMDA1cAF5BYBAgDA0RrlUQErEaq6/aaBIMgQSDBt
CBAuooIODkL44Qph/gJKcGSQhmP/6MAg9iCWYgAAGLD8poEgyBBIMG0IEC+igg8PQvTwCmH+Akpw
ZJBlY//owCD2IKViAAAYsBnlPNMP/OU8GAAgTvAslosY5Toolov9poEgyBBIMG0IDyuiggsLQvix
CWH+Akpwyp5j/+nAIPYgf2IAABiwwNItpoEsooEF5BZmMDLSMNEPAPP/em/7EBAw8/+bb/sQEDDz
-/9Fv+xAQMPoKAiAIEFgw/OUjEgAAaTBZ1JNj/8bdQPzlIBACEFAw8w4GAAgQWDBZ1I3ApFh61tIw
-0Q8AAAAA+goCIAgQWDD85RcSAABpMFnUhWP/jgAA+goCIAgQWDD85RISAABpMFnUf2P/dgAAbBAG
+/9Fv+xAQMPoKAiAIEFgw/OUjEgAAaTBZ1Jdj/8bdQPzlIBACEFAw8w4GAAgQWDBZ1JHApFh61tIw
+0Q8AAAAA+goCIAgQWDD85RcSAABpMFnUiWP/jgAA+goCIAgQWDD85RISAABpMFnUg2P/dgAAbBAG
HeUOCysRrbMqMn8Z5QwX5N2IoMBA+XkIAAEQKDD0gDRoACBO8CwyeP8yeyYAWM8QZfEzLDZ8KzJ5
KzZ73UAN5BYBAgAkpgAN5BYsCgn/AgAGAFxkkC8ye8HA/eT5EG8AN+AiMnwqIQSOIPoLRgAeCBPw
JDZ8JDZ7YAAEAAAuNnz9rwEB/gJC8Aj/Av8lBCAsAD7gIjJ8sMz/MnsgHgA0oMnGY/+/2iBYekhl
oN8qIQT6CUYAEgDCsMiZ0Q8A2iBYejvRDwDaIFh5/tEPAPosAAAAEFgwWHq90Q8AAAD60ogh8AJw
-sADhBPBbGg//EGAwDLsDC6oBKtaIWdatJDZ8JDZ7KjJ/Y/8zABbkzy9gXGTwilnJyFh5vChwwfXk
+sADhBPBbGg//EGAwDLsDC6oBKtaIWdaxJDZ8JDZ7KjJ/Y/8zABbkzy9gXGTwilnJzFh5vChwwfXk
yxBOAP4wKVB9/wIAAABIhmD/AgACAEiGYP8CAAQASYZgKVB9sZkpVH0rYFxkvwhYeajIqy1SILDd
-/VYgIFgAN2BYeSNj/vAAAAAc5Ln+MnwgBRBQMPgyeiAEEFgw+BYAIfICaLBZ1BwqMn9j/qoAACky
+/VYgIFgAN2BYeSNj/vAAAAAc5Ln+MnwgBRBQMPgyeiAEEFgw+BYAIfICaLBZ1CAqMn9j/qoAACky
e/I2fC8mALZgIjZ70Q8b5K0rsq7/AgAB/7WG0CVkXGP/YABYeS0qViBj/6LAoFv/OWP/esChW/83
Y/9yAAAkVH1j/2oAAGwQBBTkn/nkmBuwBDyg+ORoFAAgIvAjQn+piPQwSWgAIELwijB4qQIqQnsc
5JArMQT6Rn8qAEBi8Po1BCIAAFDwWHnszq0pMQT5DUYAEADCcMjX0Q/aMFh54NEP2jBYeaPRDwAA
@@ -576,7 +576,7 @@ ixAKDIYIDIYAS2sAS2nRD44RKE0B/RIAIQACQjAvhMcODoYMDoYATW8ATW3RDwAA+BIFIAEQWDD7
6wMAABBgMPz0xSrgAVwwK/TEC7sJ+LsKAAAQYDDz/w5qACA28AAAAgqGAAqGAEtjAEth0Q8AAGwQ
BBjjdwIDRwwzEagzKzIgGeOEirEosAD5iAoKAAg4IAIKPiiCEAMCPv0KAiIAAGCwC4AAIjYg0Q8A
AGwQBBjjaAIDRwwzEagzKzIgGeN1irEosAD5iAoKAAg4IAIKPiiCEAMCPv0KAiIAAGCwC4AAIjYg
-0Q8AAGwQBFnOuRLjjBPjeQwCACkiggipjgOoCoiEC4AAY//rEuOuA+gwBO4wBbEwkyCUIZUiEuOq
+0Q8AAGwQBFnOvRLjjBPjeQwCACkiggipjgOoCoiEC4AAY//rEuOuA+gwBO4wBbEwkyCUIZUiEuOq
E+NbhCAEMwKTIBLjqMAwKDdAKDdEKDdIKDdMIz0BcjPtEuOjwDCTIMcvE+OiAyMDEuOhhCAENAGU
IBLjoIQgBDQBlCAS456EIAQ0AZQgEuOdhCAENAGUIMcvwDEDIwMS45qEIAQ0AZQgY//8AAAAEuOX
gyADExQPMxGTIBLjlMAwIyYAV//ZEOOTkQCSAZMClAMR45GCEAHqMKIRAfAxwEAE5BYAAgAR442C
@@ -671,35 +671,35 @@ mf2ZFC/AECgw95EVIEACWnD8ShEEAEAu8PrdDAAgAkIw+JYJLAAgKfD43TIAgAJjMP2VFCoATOIQ
aKsxqKcnfPB3wzX/EgEgNgA9ILBJbZkFAAiGAE9hh7Gnp/25BCHgAjnwfHFv97YBIgAAQfBk0Enz
/rZiAAAqMAAIzQyMEQ1PFG35BQIIhgBMY4wR/08MAIACQXD48Q9sACBrMLD+bekFBAiGAExlL7kE
DagMqFgojDD4tgEvugC34ClcQJmx+bYAIAAQQDAotQRj/6IHiAyYmWP/YihcQJixY/+PAAAAbBAU
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -713,18 +713,18 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -732,12 +732,12 @@ YjD50gIiAABQsPmGAiDAAlhw/dIAIAEQcDD9hgAgABBoMFv+7itdAi2wBRTao9MP+irgJAGoB2Au
MrkPAgD85wpwDRBAMC9QJXjxJ/oSMCoAIFTw/AoAIAAQcDD5Cg8gEBBoMPosAAwFAFZwWUEMwCDR
DwDA0P4KACIAAFCw+z0DICACEXD8LAABwAJa8FlBBAAEiwBCYQBCYQBCYQBCYQBCYcAg0Q8AAB3a
hiMSMognidOM0YiO+9ICIEACUHCbopyhmaP82oAQAxBIMP3SACIAIETwKTa+LzK8LjK7KDK9/aYA
-IAAQMDD9MrogMBBYMPgWACAFEFAwWcmiFdp1LT0DJhQ6JhQ5JhQ4JhQ3JhQ2JhQ1JhQ0JhQzJhQy
+IAAQMDD9MrogMBBYMPgWACAFEFAwWcmmFdp1LT0DJhQ6JhQ5JhQ4JhQ3JhQ2JhQ1JhQ0JhQzJhQy
+D0DIAIQUDD6FDEgARBIMPkUOyD/EFgwKxQw+xQ8IQACQjAvgHYugHcuFD8vFD4ogHX4FD0gYAJY
cPmyAiCAAkBwmYKOsf+yAyHQAmtw/4YDIgAAULD+hgEiAABiMPuyACABEHAw+4YAIEACWHBY6eos
Mr/7CmQiAABQsPzMASIAAGkw/Da/IgAAYXBZRdH6NsAgABAQMNEPAB3aQyMSMognidOM0YiO+9IC
IEACUHCbopyhmaP82j0QAxBIMP3SACIAIETwKTa+LzK8LjK7KDK9naD9MrogMBBYMPgWACAFEFAw
-WclgKz0D+toxEQACWvAtsHcssHYsFD4tFD+JoIihj6IrsHX7FD0g/gJwcPqiAyAiAnOwmOGf4vnm
+WclkKz0D+toxEQACWvAtsHcssHYsFD4tFD+JoIihj6IrsHX7FD0g/gJwcPqiAyAiAnOwmOGf4vnm
ACACEHgw/xQxIAEQSDD5FDsgABBAMCgUOigUOSgUOCgUNygUNigUNSgUNCgUM5rj+BQyIP8QcDAu
FDz+FDAgYAJwcIji+eIBIIACeHAp9gEo9gIq4gAq9gAu4gP+9gMiAABQsFjMuioWKCwWKv0WKyD+
AmBw+xYpIEICazCP0YXQ/tICIGICWzCespWwn7ElPQP/WQoiAABQsP3SAyAiAmMw/bYDIAEQcDD/
@@ -751,35 +751,35 @@ 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
-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
+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
-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
+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
-+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
++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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -816,60 +816,60 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-ExBAMPNCFSIAABDw93IOKgAUQ9AY1U2aEwj4CoiAnBKeEQqAAJMQKrKV/FwAAgAAWLBZv7Jkpc/z
-RhUgABAQMNEPAAAAACviEgubUv4WAS/oADbgGtU48xYAIgAAWLD6orciAABhcFm/pWSlghrVMdsg
-+qK5IgAAYXBZv6Bkpuka1S3bIPqiuyIAAGFwWb+b9KaWY3wQMDAa1SfbIPqivSIAAGFwWb+VZKbp
-GtUi2yD6or8iAABhcFm/kCN9A/8CAAEAAhjw/wIAAAQ7KqArMNnBWP8CAAQCwKrQabchJTTZixD7
-RhUgABAQMNEPkxAqso38XAACAABYsFm/gGSnJ4sQ+0YVIAAQEDDRD5MQKrKb/FwAAgAAWLBZv3hl
-rxj6HAAACxBYMFjM9vsKASAAEBgw+rM4ABwANqD6EgIiAABZsFm7vsipHNUBjREMrDYs1hdlMyuN
-EP1GFSAAEBAw0Q8AAAAuQG5k7s2TECqysfxcAAIAAFiwWb9hZa66+hwAABYQWDBYzN77CgEgABAQ
-MPqyOAAVADag+hICIgAAWbBZu6YsfQMqxShlItSNEP1GFSAAEBAw0Q8AkxAqsqP8XAACAABYsFm/
-TWSiuxrU2tsg+qKPIgAAYXBZv0hlrlj6HAAABRBYMFjMxvsKASAAEBAw+rI4BQYANqD6EgIiAABZ
-sFm7jixAb/8CAAACeG8QZKToihP7CgUgDRBgMFjMoNKg0Q+TECqyqfxcAAIAAFiwWb8yZa7I+hwA
-ABIQWDBYzLBkojsrQG7TD2S3k/oSAiIAAFmwWbt5LEIWCsw2LEYWixD7RhUgABAQMNEPkxAqsqf8
-XAACAABYsFm/IGSiNxrUrQIrAg8CAPqioSIAAGFwWb8aZa5o+hwAAA4QWDBYzJhkodv6EgIiAABZ
-sFm7Yyt9Aiq1FIsQ+0YVIAAQEDDRD5MQKrKZ/FwAAgAAWLBZvwtkoioa1JfbIPqipSIAAGFwWb8G
-ZKOHGtST2yDTD/qikyIAAGFwWb8BZa4C+hwAAAcQWDBYzH5koXUrQG5ktwMa1IiLEvqi3yIAAGGw
-Wb73ZaZmK0BvwMgMuwIrRG+LEPtGFSAAEBAw0Q8AAJMQKrKv/FwAAgAAWLBZvuxkoe8a1HnbINMP
-+qKRIgAAYXBZvudlrZr6HAAABhBYMFjMZGShDStAbmS2ihrUbosS+qLfIgAAYbBZvt1kppkrQG8s
-Cv0MuwErRG+LEPtGFSAAEBAw0Q8AkxAqspf8XAACAABYsFm+0mShtxrUX9sg0w/6oosiAABhcFm+
-zWSi2hrUWdsg+qKrIgAAYXBZvshkrFca1FXbIPqisyIAAGFwWb7DZaxEGtRQixL6os0iAABhsFm+
-vmWkdYsRK7ISC5lSyJlokgf/AgACAPYeYIwRK8YS80YVIAAQEDDRD5MQKrKH/FwAAgAAWLBZvrFk
-oXoa1D3bIPqiiSIAAGFwWb6sZayv+hwAAAIQWDBYzCnKohrUNYsS+qLfIgAAYbBZvqRlrI+KE/sK
-AiANEGAwWMwJ0qDRD8Ag0Q8AAAD6HAAADxBYMFjMG2Sv6voSAiIAAFmwWbrnixAsfQIqxRX7RhUg
+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
-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
+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
-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
+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
-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
+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
-+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
++qLFIgAAYbBZvbHz00UQrAC2oIsRK7ISC+lRyJlokgf/AgAD/tEeYI4R/BIALABAHvAt5hL8RhUg
+ABAQMNEPGtMuixL6os8iAABhsFm9oGWtc4sRK7ISC5lSaJEKaJIH/wIAA/6xHmAf0y6CEf19Ay4J
AH7w/yYSIQACa3As0NnA4Q7MAizU2fNGFSAAEBAw0Q8AihP7CgggDRBgMFjK8dKg0Q8jfQMjPIAr
-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
+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
@@ -877,24 +877,24 @@ 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
-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
+pfzSoBAwEFgwWcGXwCDRDwAAAAAAAAD6TAAABhBYMFjqLMAg0Q8AjCf5yRQvwBBQMPvCCSBAAkMw
CogB+IxAIIACSnD5xRQhgAJa8PvGCSoABcLQLsEVq+ubyRjSTNmw8AgHAAQQeDBt+gIASWEc0mGc
sIog+KoRAAQQYDAMqgKasSkwFCowFf8wFimABD5gCpkC+jAXKYAEPmAPmQL+0noZgAQ+YP62AigJ
AFZw+bYEIBACQPDxCBYAMAJ68AAPiioiEokiDaoC+iYSLvMAtmD6LAAAAxBoMAvgAGP+4GwQBiQi
-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
+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
-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
+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
-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
+HNIaAPWOhCeNIP4yBSbgASgw9EkUIAUQUDD0FgAgMBBYMFnBAogiZYCeKCAHGdGw+jIFKCABQDAM
hRH70a0UACBNcPlSOiA+AiKwBEQUC4sK+7KXKgA8JlApUjkc0b37nQEOADVeUPAMBwIAAENwbUkC
AEhhG9Gpm9CJIPgyBCBAAmDw/tGnECACW3D+1gIpgAQ+YPrWAygJAE0w+dYBIgAAULALgAD0Vjki
PAA5oCoiB/sKCiAAEGAw+qwgIAoQaDBYZJrSoNEPwCDRD/osAAIAAGkw+4wYIAAQYDBYbOLAINEP
AGwQBMePCFgDCDgCCEgDqGjwcQQCACBAsAIiGKIy0Q8AbBAEBDgDCFgDqGjwcQQCACBAsAIiGKIy
0Q8AAGwQBAQ4AwhYAQhIA6ho8HEEAgAgQLACIhiiMtEPAAAAbBAEBUgDCDgBCFgDqGjwcQQCACBA
sAIiGKIy0Q8AAABsEAQjIhAoMAUkCpL5IhIgmggiMP0KgCCKADJweJ89cJ8Z+tG6EKwAPnAKmgH6
-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
+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
@@ -912,13 +912,13 @@ KyISLPp/DLsB+yYSIAAQEDDRDx7Q8S0iEg7dAi0mEmP/yADaIFhrqPzQhh4AADagYAAmiF4Z0OSx
iPhWDigJAEowKEQzCIgUKEQyCIgUKEQxCIgUKEQwY/8/wCDRDwAA+2wYIgAAULD8CgEgBRBoMFhr
0sAg0Q8A+2wSIgAAULD8CgEgABBoMFhrzMAg0Q8AbBAOJBYRJzAPKDAOhSf5MA0gAhBgMPwUISAB
EFgwKxQr+RQtIP8QMDAmFCD2FCwgABBwMC4UIi4UIy4UJC4UJS4UJi4UJy4UKC4UKS4UKoVeKBQu
-JxQv91LeIEACaHCI04vS/NIBIGACSHCckZuSKJYD/dIAIgAAUTD9lgAiAAAw8Fm71lm7zBzQsY8y
-jjGNMPgyAyIAACKw+xYSIAUQUDD4FgAgMBBYMFm/jfpcAAIAAFjw/AoAIAEQaDBZOGJloJJkcOpo
-cFP7EhIiAABRMP3QUxAAEGAwWcALe3s9HNCcLlLaL1LbKlLc+hYAIgAAafD5Ut0gMBBYMPkWASAF
-EFAwWb93G9BDKV0D8AsHAMACSnAASWEASWFgADgc0I4mXQMtUtouUtsvUtwrUt2bEIowmhGJMZkS
-iDL4FgMg0AIxsPgyAyAwEFgw+BYEIAUQUDBZv2PNaMAgx+/6CgUgMBBYMPzQfRIAAGiwWb9d0Q8A
+JxQv91LeIEACaHCI04vS/NIBIGACSHCckZuSKJYD/dIAIgAAUTD9lgAiAAAw8Fm72lm70BzQsY8y
+jjGNMPgyAyIAACKw+xYSIAUQUDD4FgAgMBBYMFm/kfpcAAIAAFjw/AoAIAEQaDBZOGJloJJkcOpo
+cFP7EhIiAABRMP3QUxAAEGAwWcAPe3s9HNCcLlLaL1LbKlLc+hYAIgAAafD5Ut0gMBBYMPkWASAF
+EFAwWb97G9BDKV0D8AsHAMACSnAASWEASWFgADgc0I4mXQMtUtouUtsvUtwrUt2bEIowmhGJMZkS
+iDL4FgMg0AIxsPgyAyAwEFgw+BYEIAUQUDBZv2fNaMAgx+/6CgUgMBBYMPzQfRIAAGiwWb9h0Q8A
wKDyFhAiAABZsFjf59Og8qwAAA4ANqAuMRBj/8wAAAAAKhIQ+xIRIgAAabD+CgAgYAJgcFjfumU/
-3GP/qgAA/SIAIAUQUDD80GkQMBBYMFm/R2P/kAAAbBAELCIUKyIT/c/3EuABLDD8uwwCDgA44GSw
+3GP/qgAA/SIAIAUQUDD80GkQMBBYMFm/S2P/kAAAbBAELCIUKyIT/c/3EuABLDD8uwwCDgA44GSw
fiwgBwwMQQzKEf/P8RoAIGqwLaI6D88K//KXItYBO2AuojkY0BIZz/T/7QEOAC1/kC4hBw4OSv/Q
UR/ABDug/M/wHgkAS7Ce0P4iACgJAELw+NYFIAgQSDCZ0/zWAiACEEgw+OwRDgkAe7D+1gQsCQBL
MJzRKaY5KCIUq4goJhRpMg7AINEPjyLK8GgyNMAg0Q+KJ/sKASAAEGAw+qwgIAEQaDBYYtrSoNEP
@@ -928,8 +928,8 @@ Gc/fmaCIIMCR8tAWGYAEOiDypgIoCQBKMPimASAAEBAw0Q8AAAAAAGwQBi8iGC/wdCgKjnjxdigg
BfnQDBBwADYgGNAJJCISCEQBJCYSjTkrMQv+IhEoAEDqUCkiE6uZ+SYTIgBSZRBk4MSK7H2nPYjr
+uwAAAAQWDD8CgAgAhBoMAuAACsiFCoiExnP+QuqDCutQPzP+BoAEF5Q+sMYcAAQSDD5JhEiAAAS
cNEPwCDRDwAAAAAAAPosAAAAEFgw/AoAIAIQaDBb/3/AkPkmESIAABJw0Q8A/M/oEAIQUDD+IgAg
-MBBYMFm+vSoiEC2gBS4KlX7RtsDy/yRkIAEQWDBY51bAINEPHM/djeD+4AUgBRBQMPQWACAwEFgw
-Wb6wKCISKfq/CYgBKCYSY/9VANogWOSdY/9MbBAILiIYLeB0KAqOeNENKSAFGM/N9c/NEAkAtmDA
+MBBYMFm+wSoiEC2gBS4KlX7RtsDy/yRkIAEQWDBY51bAINEPHM/djeD+4AUgBRBQMPQWACAwEFgw
+Wb60KCISKfq/CYgBKCYSY/9VANogWOSdY/9MbBAILiIYLeB0KAqOeNENKSAFGM/N9c/NEAkAtmDA
INEPACQiEvkiESQJAEEw9CYSIH4AtTCKLIk2JjAgLzEK+Pr8IIsQYDD2C0UAlARScCoiECugBSwK
lXyxwcDS/SRkIAEQWDBY5y/AINEPAAAAAPSRvmBAAlDwiZeJnvmcMCAGEFgwwCBtuQUACoYASWHR
DwAAAAAPD07//AMgMRA4MPj/AQYBPmdQ/6gIACUQYDD6IhAgIRBoMPgmDCQJACkw9CYSICoEavB8
@@ -949,13 +949,13 @@ gAQ7oA/uAv8wJy+ABDugCO4CCO4RD+4CZeHXKzBMLDBN/TBOK4AEPuAMuwL8ME8rgAQ+4A27Agi7
EfoiECoJAGbwZLyXLKIY/wIAC/5I3xArVhIuMEgvMEn4MEovgAQ7oA/uAv8wSy+ABDugCO4CCO4R
D+4CLlYULTA0LjA1wID5MDYtgAQ/YP/O1hwJAHdw/jA3LYAEP2D4VhUsCQBPcPhWEy2ABD9g/1YL
LAkAd3CdXWP95ygwOCkwOfowOimABDogCYgC+TA7KYAEOiAKiAIIiBEJiAL/zsQQAgJCMCgmFp9b
-Y/21jxUczsD9UgAgBRBQMPQWACAwEFgwWb2NLSISxOAO3QItJhItMD4sMDwrMEAuMD0vMEH4uxEN
+Y/21jxUczsD9UgAgBRBQMPQWACAwEFgwWb2RLSISxOAO3QItJhItMD4sMDwrMEAuMD0vMEH4uxEN
gAQ7IP4wPywJAHMw/zBCKgkAfvD4uxENgAQ7IP0wQywJAGswD7sC+MwRC4AEPuD+zAIKCQBu8Ay5
DPoiECH9pqJgLaISfNEIDc8MZvACLKYSLKIT/wIAB/2Z3xAMuAxmiyj7phMgABAQMNEPAADz/Blv
-/xAoMPzOlxIAAGuw/lIAIAIQUDD2FgAgMBBYMFm9YWP7KAAAKjA4KzA5/DA6K4AEOqALqgL7MDsr
+/xAoMPzOlxIAAGuw/lIAIAIQUDD2FgAgMBBYMFm9ZWP7KAAAKjA4KzA5/DA6K4AEOqALqgL7MDsr
gAQ6oAyqAgiqEQuqAvnOhxACAlKwKiYWmVtj/L3AsCsmEfP8tWIAACuwACoiEGP64wAAbBAGKiIH
JCAHKKkUBQtH9aIOJCABIDDzogkilQA2IP8CAAIBUprg/M51EgAAeLD4IgAgARBIMP6iAiH8Amrw
-+goFIDAQWDD4FgAsBQBucFm9OhzOa/0wACAFEFAw/iBQIDAQWDBZvTQdzegMTBH/zeccACBrMCrC
++goFIDAQWDD4FgAsBQBucFm9PhzOa/0wACAFEFAw/iBQIDAQWDBZvTgdzegMTBH/zeccACBrMCrC
Og9PCv/ylyQBIEKgLsI5/+oBDgEa/5ApIEAtIAcUzen2zlsQAQ4GYP8CAAIBAAJg+woAJAD8BiAp
IQcoIQgezen9L0AJQAFMMPr/EAnABD5g/Q1BCAkAfnDw3REICQB2cPmmACgJAGow/iIAKAkAMjD4
pgQgBBBoMPamBiAwEHgw/6YDIEACSrD0pgIgAhB4MPjuEQAAECAw9KYFLgkAa7D+pgEvgAQ64PSm
@@ -976,7 +976,7 @@ BSBWAH4wKyISLjIqC4pE+qoPAAAQYDD+qgoAARBoMPqiACvwAVwwWF+QJCYSiCeLIPn6wCBAAnow
9CYMLgBAT/D0hRQggAJ78J+Jn4guUnP6MhUgABBgMP67DAABEGgwWF+BKjIWsKr6NhYgABAQMNEP
AAAAAAAA8/6TYAAQMDArIEAIuxCbYGP+i4ieLYAEK4AF+oAGLYAEP2AL3QL4gActgAQ/YPPNMRwJ
AFdwCN0RCN0CA90BI9xn80MUAIkQWDDz/mdgCAIY8AAAAAAAAPP+eGAAEEgwj2D9PAACAABQsP7N
-SR74AXww/yRAIDACWzD+ZgAgARBgMFhoIMAg0Q8ALNxI+9xnIgAAcLD7SxQCAAB5sFm74C4gB4sQ
+SR74AXww/yRAIDACWzD+ZgAgARBgMFhoIMAg0Q8ALNxI+9xnIgAAcLD7SxQCAAB5sFm75C4gB4sQ
8/47bCABcDAAAABsEASJJy0gByMhByiZFA0LQf6SCSNAARww9IFLY8AEPOD/zK0Y4AEsMPy8EQIA
thpg+cyqHAAgezAqwjoJuQr5kpckAJbCoCjCOR/MsPmKAQ4Aj84Q+My1GAIBbDAKmRAJMwIIMwKT
oIggw5D/pgIgBBAYMPmmAymABDog+c0WGAkAGjCYoS8gQfghCCAAECAw9KYFIAAQaDD0pgchCwC3
@@ -988,15 +988,15 @@ QCABEGAw/+YAIAQQaDBYZ7DAINEPKSBACJkQmeBj/owAAAAA8/71YIkQaDBsEASKKo6vGMzM+CYL
IEACSLD55gAgcAJ6sP8mCCIAAFiw/iYJIAAQYDD5pg8vmBBAMPgkBSACEGgwWGfmwCDRDwAAAGwQ
BBvMvSoxDNMPK7J/HMya+TAQIBYQIDD7ox9wABAoMHyhF/osAAIAAFlw/DwAAgAAaTBY43PAINEP
AGiRQWiSIWiUCcBA8//ZYAAQKDB8odF7q87aMFjjoNWg8//EYAAQIDD8oQdwFhAgMHujAmAAAcBA
-2jBY47fz/6dgABAoMNowWOPJ9awAACIANqD8zJsQBRBQMP0yASAwEFgwWbtd8/9/YAAQIDAAAADz
+2jBY47fz/6dgABAoMNowWOPJ9awAACIANqD8zJsQBRBQMP0yASAwEFgwWbth8/9/YAAQIDAAAADz
/3RgDBAgMGwQBCkwE/SQa2D4ECgwaJEDwCDRD4Qn0w8PAgCEThzMiy0wEShNBClNAy2U/P4wEiAF
-EFAw/oTdIDAQWDBZu0j6TQQgMAJY8PwwESH6AlKwWOPX+k0FKgAgLPD8MBIhvAJSsFjj0/osAAIA
-AFkwWOVTwCDRD4QnDwIAhE4czHUtMBEtRAL+MBIgBRBQMP5EAyAwEFgwWbsy+k0CIDACWPD8MBEh
+EFAw/oTdIDAQWDBZu0z6TQQgMAJY8PwwESH6AlKwWOPX+k0FKgAgLPD8MBIhvAJSsFjj0/osAAIA
+AFkwWOVTwCDRD4QnDwIAhE4czHUtMBEtRAL+MBIgBRBQMP5EAyAwEFgwWbs2+k0CIDACWPD8MBEh
kAJSsFjjwfpNAyoAICzw/DASIVACUrBY473AINEPAABsEATzixQAQBBQMPUtAyAAEEgw81RXIAcQ
QDArVFYqVFIpVFP4VFQgQxAgMCRUVdEPAAAAbBAEjzj8zFUQBRBQMP0wECAwEFgw/+9RAgAAc/BZ
-uxIpMBD6zE8QSAA+YGiSWWmUEog2IqJ/CYgRqCIoIAUpCpV5gV7AINEPAAAA2jBY5ff5Cgcv8AA2
+uxYpMBD6zE8QSAA+YGiSWWmUEog2IqJ/CYgRqCIoIAUpCpV5gV7AINEPAAAA2jBY5ff5Cgcv8AA2
oIuni74sso4MnVb8flgOAA1uUMDTftAQ+70CIAAQYDBY5cLAINEPAABY5RDAINEPAIs2KqJ/CbsR
-+woAKgAgWrBY5JTAINEPAAAAAMCl/MwvEDAQWDBZuu76LAAAAhBYMFjjisAg0Q8AbBAEiC4jLDhz
++woAKgAgWrBY5JTAINEPAAAAAMCl/MwvEDAQWDBZuvL6LAAAAhBYMFjjisAg0Q8AbBAEiC4jLDhz
iQXAINEPAACLLoiz/EwAAgAAaXD7vOAiAABQsAuAAIwi/SAFL90AtyBk39WOLnPp1mP/zQAAAGwQ
FiUWFysgBxrMFyMWGYg09zIFIgAASTD5FgwiAABw8P7hDyABEBgwkx/6oX4sCwFAMPwWGiogAVww
KxYW+MUUCg8BdDArFhMKWgz7Ehkr4AFQMCoWFCoSFy2wHfyxPSP/EBgw/BYSJh8BPDD9FAAkCgFA
@@ -1007,7 +1007,7 @@ txCUGgZFFPAASWACAilwKBISZIc8KRIZiZV9lqIrEhIsEhD9HAAAARBQMPoWESIAAFFwWOioZqdw
CizClwy7Ad6w9rwAB6UANuAt8kpk13gdy78o8kkp0mOMHPmLAQ4DtU4QKiAUnhcKrIf6JBQsA8qS
oC0SGigSFP8KAyAMADdg/wIACAPSQ9BkMH+JGg8CAA8CAMiRZDBg+2wAAgAAULD8CgMgGBBoMFjo
q44e/xILJgUANOAdy1v7EhMgABBAMJiimKP4pgQtAAQ7oPimBSogBD7g/f0CCgkAZvD9pgAtsAQ4
-4PzLmxoJAGbwm6H6CgUgHBBYMFm6VCkSFf8CAAIDhZpgwCAlRjnRDyoSEWSgc/sSByIAAFCw/AoD
+4PzLmxoJAGbwm6H6CgUgHBBYMFm6WCkSFf8CAAIDhZpgwCAlRjnRDyoSEWSgc/sSByIAAFCw/AoD
IBgQaDBY6I0rEAAWy4kfy4qOGyZinBnLW/sfFA4JAHuw9rYLDsAEP+D5/wIARAB+8CwSECtt/y0S
EiiyPyuxfZ6gn6Gdopyjm6SYpWAAFiwSEC0SEithBYhjnqCfoZuimKOdpJylJqwYLRITjB4C3RD9
FggtAAQ7IPwWCSVHALXgGsshiBsvCgD/FgUgAhB4MP8WBigJAFIwKBYN+2wAAgAAULD8CgMgGBBo
@@ -1033,11 +1033,11 @@ IhIhY/6AACgSGiwSGBvKaGSAY/yZAg//EHAw9HAhaAkAXnCZoZSgnqKeo56k/qYFIAAQaDCdpp2n
naidqWP+Ri4SGSIWIS3iEiziEyviGIjthu4v4hSC7y7iEZ6inaOcpJulmKaWp5+pmaGSqJSgIhIh
Y/4RAAArEhvH3/uZAgAAEGAw9HAbaAkAHnCZoZSgnaKdo52knaWcppynnKicqWP945mhlKCOE/8S
ASAAEEAwmKKYo5ikmKaYp5ion6WeqWP9wioSGRnKO9MPiqUjEiAlEh/0Eh4gDgBOsGRweBzKNosb
-DLsCK5b6Y/nUgx/A0vP592IFAD9wAMCl/MovEBwQWDD+XhECAABpcFm43GP4nAAAAAAA+hIUIAAQ
+DLsCK5b6Y/nUgx/A0vP592IFAD9wAMCl/MovEBwQWDD+XhECAABpcFm44GP4nAAAAAAA+hIUIAAQ
cDCeEZ4SnhOeFFjl0CQWHiUWH/MWICw0ADag+hIUIAAQWDBY5cIkFh4lFh8jFiBj/BgvEhBl+Lxj
+GQayfGIGwqIAiiW+mP5WwAAAFjlxcipG8oU0w8rsIBksF0qEhRY5bv5Eh0rzAC2oPoSFCABEFgw
WOWuKRIdY/u2AAAAAAAAAPP4MWAwEDAw+xISIgAAUXD8EhAiAABocFjmpWP4eAAAKxIZjBz9Ehci
-AABQsFhhhNKg0Q8AAAAA+sn7EUEQWDBZjab7GkEhABBgMPrJ9hwJAGKwWY2mY/+AAAAAAAAAAPos
+AABQsFhhhNKg0Q8AAAAA+sn7EUEQWDBZjar7GkEhABBgMPrJ9hwJAGKwWY2qY/+AAAAAAAAAAPos
AAAcEFgw/AoAIAEQaDBYZK5j/6kAAPP4W2AAEFgwAAArEhb6LAAAABBgMPu8GCIAAGlwWGSlY/+E
2iBb4iZj+GaKJ40cwMD6rCAiAABbcFhcT9KgJUY50Q8AAAAAAPP4X2AEEBgwbBAEFMm5giAkQn8T
ydUEIgwDIgLRDwAAbBAMGMmpKYKAKoJ3KI3mKIDBCaoR/4cPeAAgVnAknQHwAAphAAIhMCSdAyRM
@@ -1046,7 +1046,7 @@ gBnJjShBKf8CAAYAf04QGsk+8AoHAgAASHAASWEASWEASWEASWEYyZ4fyb6OIBvJvPsWAiAEEFAw
/RYJKgkAZvD7FggiAEuE4IlHKJkU9ICAYEACYnCNmSvCAP76wCAoECgw9NBDbgBAczBtCDB9sTgv
0AD50AcgZAQr8C/BBf74CAnABD5g+IxALAAgT3D42w9yAABTcP2sAAAPADagY//ID9oMY//uAAD9
ugwAABBIMAqdOPbcAAA0ALdg+kwAAgAAWHD8CgQgAhBoMFhXiNEP8/+CYAAQaDAAACocOvwKBiB0
-AliwWa8wY/9bwnaOaPoKBSAwEFgw/Ml+EgAAabD/IDkuYAFwMFm4JIpoCo9Xd/FtikcuoRX7+sAg
+AliwWa80Y/9bwnaOaPoKBSAwEFgw/Ml+EgAAabD/IDkuYAFwMFm4KIpoCo9Xd/FtikcuoRX7+sAg
QAJSsAurAavr/WxAKAA23ZD/ogAgMAA3YH3xKCzQANMPDwIAdcEdKdAHDJkR+d0IAIACQvD42yRy
AABTcP2sAA/YALag/fsMAAAQUDALrTj23AAPTAA3YGP/dgAADtoMY//ZAAAsIDkKDUN9yYiOIAju
EQ4+Ap5r0Q8O3Qxj/5AAAAAAAGwQBBjJVCmCfyowBy2RAi6RBCyRBfuSACEbADdg/9z/If4Cc7D8
@@ -1054,26 +1054,26 @@ zBEPwAQ7oP+VAioAIHbw/LsMDxAQEDDwACxgABB4MCuRBS2RBLG7+wtPAf4Cc3D7lQUmAGhu0IyQ
DO4R/swIC8AEPuALywwAC4sP32DwC4APnAC7YB7JNymRBSvifwmZEanZ/eJ9ILgANuCM0YvQm8CL
0Jyxn9Cf0Svif7C7K+Z/+QtPCABbA2Ci0vz6wCAwAkNw/NIJKABAYjArJjr/1RAlQBBIMPnVESCA
AiIwJNYH9NYGJcAEPqD7TAAGAEqnEP+NBigAIEFw/IxAIQACe/D11RAqAERn0Mky+UwAABAANqBt
-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
+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
-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
+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
-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
+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
-DMwJDMwRrLsrvR/7vFogBhBgMFmuDx7IaxzHxiNkMxrIafpkLSCJEEgw+WQsIBAQQDD4ZC4gABB4
+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
-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
+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
-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
+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
@@ -1131,7 +1131,7 @@ EO4AdjArIAcLC0H9xF0TwAQ+4KQzKTI6Db0KhCD90pckuAE6YCwyOf3KAQ4AKO8Q20BY/bzAwf0K
ACABEHAw+MUPEAAQSDD5FgEgABB4MPkWAiIAAFqw+BYAIgAAUTBYWm8lNjkqIHArCvsLqgH6JHAg
ABAQMNEPwCDRDwD7vBgiAABQsPwKASAEEGgwWF+axyTRDwBsEAQrIAcYxDgUxPgLC0H9xDcTwAQ+
4PRCfyIAIETwKDI6Db0KLdKX/oJMZAAgWTAsMjn9ygEOACDvENtA/AoAIAIQaDD+CgIgEBB4MFmx
-csCx+MTnGYAEPSD4pgAoCQBecJmhjyCfosDi/jY5IAAQEDDRDwAAAAD7vBgiAABQsPwKASACEGgw
+dsCx+MTnGYAEPSD4pgAoCQBecJmhjyCfosDi/jY5IAAQEDDRDwAAAAD7vBgiAABQsPwKASACEGgw
WF92xyTRDwBsEBT+MBAgBxA4MP/EIBABEGAw+sQREAAQMDD9ChgiPAA3oP8CAAAEMYegaOIDwCDR
DysgBwUJR/kWGCogAVww+xYZIjQCOmAuIAX/AgAIBavDoCggcv8CAAIFpnoQ2iBYXHz/AgACBASq
oIsiZbf/KiEajDUtIhD/Igkp8AQ+oPsWBCoACmJQDwlCyJkKC0L/AgAABU4q4C4SGfnD7xAYEFAw
@@ -1160,7 +1160,7 @@ AEfw8/8CAAEQYDDzEh0uCQB7sPzuEQAEEHgw/woALgkAe7D+FgIgABBwMFhY38DB/8OAEgAAWrD6
IgAkABBIMPkWACAAEGgw+RYCIAAQQDD4FgEgARBwMFhY0ywSEv0SECIAAFqw+iIAL/8QQDCYEC4h
JP8hJS0AAWww/AxIDXAEP2ANzALw/xEAABBoMPwWAi4JAHuw/AoBL/8QeDD+FgEgGhBwMFhYwNug
+iIAL/8QYDD8FgAgABBIMCkWASghIikhCcDQ8IgRABwQcDD4mQIP/xB4MPkWAiABEGAwWFiyKhYT
-KiEoWbDR/cNOEgAAYrD6IgAv/xBwMC4WAC4SES3QLBvDTP7dAgH+AmMw8ukQDBAEP2D5zBEICQBu
+KiEoWbDV/cNOEgAAYrD6IgAv/xBwMC4WAC4SES3QLBvDTP7dAgH+AmMw8ukQDBAEP2D5zBEICQBu
cAyZAguZAikWASgiFRnDQ//6/yAeEHAw+GgUAAAQaDD7EhMoCQBKMPgWAiABEGAwWFiW/AoBIgAA
WrD6IgAgABBAMPgWACAAEGgw+BYBIAAQcDD4FgIgARB4MFhYi4kw/wIAAgFLqlAZwtYqEhUuIQcf
wyUnpjknkmiJIIggLSAHKvL7/CAMJgAgRfD7IA0nkAQ94PggFSoAIDqwKhYULqUHLaQHLKQMK6QN
@@ -1174,7 +1174,7 @@ DwD6LAACAABY8PxMAAIAAGlwWFoZ0qDRDwAAAAULR/sWGCI0AjrgKyAFwcT/AgAGANhm0G64ci0g
cn7fbNogWFppZaB0jiJl4G8oIBSkiCgkFI8wevZSKiAHGMHkCgpBDKcRqHcpcjr/AgAEAbNCYB3C
oSxyOQ2tCi3Sr/3LAQ4BqW8QLyBxAzwC/grqIgAAULD/5jkCAABpMP8KASIAAHGwWFomwIQodjkp
Ehj/AgACAYMaYMAg0Q8A+iwAAgAAWPD8TAACAABpcFhZ69Kg0Q8A/MKTEAQQUDD9IgAgKhBYMFmx
-DR/Bzi4hGvP59WABEGAwAAAAAAAAAPw8AAIAAGkw/goAIgAAWrD/CgEiAABQsFhaCvP9TmAIAjnw
+ER/Bzi4hGvP59WABEGAwAAAAAAAAAPw8AAIAAGkw/goAIgAAWrD/CgEiAABQsFhaCvP9TmAIAjnw
KxIbHcKBLhIZH8J/LdCAAOEE8McaAAMQcDD+9IAu4AE8MP34M3IAAHNwx5/4wngYEQBP8PkSGSwA
QE9wCJkKGMI9KJaXGcJxDX0CDQ1H/ZSAIWwAN6Bk0W/B8/8WBSABEHAw/hYRIAAQaDAtFhDz+p1g
FRA4MAAAAAAAAADz/fVgBhBgMMSAmB9j/Z4AiR74IHEiAABg8PosAAIAAGkw/grqIAEQeDD45jkJ
@@ -1193,11 +1193,11 @@ wP0pkn+OK/CRBAH+AkNw8IgaAAEQeDAA/xr//P8uACBDsA/uAp4q+6wfIAEQYDD9CgAiAABQsFhc
PGP7iQAAbBAEGMFRiSArgmj4goAgEBBgMPwkBSgAIF5w+ZkRAAAQWDD7JBQoACBKMPuEFCIAAFCw
W9wy0Q9sEAQZwVeKMimSfwmqEaqZLJAG+JICIAAQWDD9+v4gCxBwMP6UBSH+AmMw/JQGKABAajD4
lgIiAABScFvcIsAg0Q8AAGwQBogiLyAHhzCVEvQWAy4gAXww9YHuZuABPDD/FgEhJAA14Pt8ASIA
-AFCwWayE9qG2YgAAIrD2PAAPjRAoMPIWACDUADXgB3IJ9zwQI8AEOKDwACFiACAYsAAAAGmBCIoQ
+AFCwWayI9qG2YgAAIrD2PAAPjRAoMPIWACDUADXgB3IJ9zwQI8AEOKDwACFiACAYsAAAAGmBCIoQ
i2VY+k7UoGZA3yZsMPd8MCYAUhWQKGAQyI5ogURpgukoYBFlj9RgAHMAKGARyIxogSBnT9R1QdFg
AK4AAIoQ+2IFIgAAYfBY+ofz/+RiAAAisACKEItlWPp+8//UYgAAIrAoYBHIjGiBIGdPnHVBmWAA
dgAAihD7YgUiAABh8Fj6efP/5GIAACKwAIoQi2VY+nDz/9RiAAAisAAAAIoQ+2IFIgAAYfBY+irz
-/1liAAAisAAAAIoQ/Ar9IAAQWDBZrYr8EgIiAAAisPb6ACYAd66QiDAGiAGYMGAADQAAAAAAAPIW
+/1liAAAisAAAAIoQ/Ar9IAAQWDBZrY78EgIiAAAisPb6ACYAd66QiDAGiAGYMGAADQAAAAAAAPIW
ACAAECAwiREYwGkMlxH8wGkWACBF8CpyOoIQDJwK/MKXJACpQqArcjkMuwH1vAABTgA24C2CSv/A
dREjADdgLoJJL/J/iRP/6wEOAIn/kCggFAiJh/gkFCwAnpIg+1wAAgAAYPD6LAAO4AEgMP0SAyAB
EHgwWFijihL6CkcABBBYMPt2OSIyADqgiieNE8DA+qwgIgAAW3BYU1XSoNEPwCDRD8e08hYAL/+u
@@ -1220,8 +1220,8 @@ TmEB+ouPSS8WFI5NLhYViEwoFhYvQgv/FhcgwAJwcABOYQBOYSsWISsWIisWIy0WLSkWLCwWUyhS
SSpSSCoWHygWICv6/ysWI/sWIiBgAlBw+xYhIMACWHBY+aMvUXkPAgAPAgD2rAAIByR+kC9RhH+i
DShRhQ+ICP8CAAwHGkKQWPne9vr0IAdnKqDaIFj5tiVRhKWl8xYnIAdyrWAev7kYv50v4mYsEiYu
4oDzQhguACB9cPdCGS+QBD/g/+4IAAEQaDAt5RovQSslxgEvFkEcwAwmQhorQhcpQhYuQhQpFkQr
-FkP5FgIoAEBDsCgWRfgWAyIAAGlw+xYBKngBcDD6FkIgABBYMPoWAC58AXAw/hYqIAUQUDBZrnDA
-pfy/+xAAEFgw+L/4HuABFDD/FkYiAABo8P8WACIAAHHw+BYBIgAAebBZrmXAkf4KACCAEGAw/HwB
+FkP5FgIoAEBDsCgWRfgWAyIAAGlw+xYBKngBcDD6FkIgABBYMPoWAC58AXAw/hYqIAUQUDBZrnTA
+pfy/+xAAEFgw+L/4HuABFDD/FkYiAABo8P8WACIAAHHw+BYBIgAAebBZrmnAkf4KACCAEGAw/HwB
AgAAW7D8nDkKBQBecPwSKioJAGbw/woCIgU1AyApFjUiFiv9Cgoh+gJDMPjcOAAAEEAw+BY0IAAQ
aDAtFjMZv2Dyv94QARBoMPk5AQAAEFAw+to5CAUAT3DwhAQICQBWcPc9GAAFHSpgA3pTKhY2/wIA
AAS5pZAGWlD6FkcoFAEwMPgWSCIElDGQKCIxCIhB+BZJIASS0ZAGyUH5FkoiBJw1kCoiMQoqQfkK
@@ -1263,7 +1263,7 @@ KuY1+eY2IAICe/D+hAZgARBIMMCQKBJQCJkRApkC+b3tGAkASjAu7EDyHGAoCQBKMPjmJyIAAEjw
IADTwlAYvWIevcKdcImw/HYCIAgQUDCac/52BSACEFAw+FgCCYAEPmD4dgQoCQBWcJlx8AYXADAC
SfAACYrzPAIgQAI58I9A0w8PAgD/AgAAANOr0CkgAQCZMoUhACQELkIZLUIY/EIaKuABSDAqFi8O
3Rj8BkkMIAFsMP0WLiAYADagL0IUGb0xD8hT+Iz+LgBAT/AI9Tj7sgAiAABR8P0KASwaAWAw/goE
-IDAQeDBZqhcdvOQrEi78Ei8gBBBIMPANBwIAAGqwAE1hAE1hAE1hHr1CAL0R+L2jHAkAbbD4pgIs
+IDAQeDBZqhsdvOQrEi78Ei8gBBBIMPANBwIAAGqwAE1hAE1hAE1hHr1CAL0R+L2jHAkAbbD4pgIs
CQB3cP2mACAQAnkw8Q8WACACcrAADoqVpihCFAwNBv2kHSh8AUAw+KQcIAgCcPAvEicu9jn5JAAg
ABAQMNEPAAAoIi4ImFAoFkjAkPkWRyH7cDGQBgpR+hZJI/tx0ZAoIjH4CkACAABLsPgYQAgFAFfw
CYgC+BZKIftoNZDz9s5qLgEwMAAAAAAAAAD5CgEgABBAMPIWVCpgAWgw+qz/IAAQEDD6mDgAABBQ
@@ -1283,15 +1283,15 @@ MP+82hAcEHAwWFIdwMH9CgAgHhBwMP+82BAAEEgw+RYBL/8QQDD5FgIiAABasPgWACIAAFFwWFIR
4AQ6IPgWAS//EHgwWFH/wMH9CgAgHBBwMP/6/yAAEEgw+RYBL/8QQDD5FgIiAABasPgWACIAAFFw
WFH0wMH9CgAgHhBwMP/6/yAAEEgw+RYBL/8QQDD5FgIiAABasPgWACIAAFFwWFHp8/ksYgAASrCL
SS1BFv5BFyDuADSgHLyiKUIRKkIOL0INKEISJhYJKBYDKxYIKhYH+RYBIAUQUDD/FgUgABBIMPkW
-ACAAEHgw/xYEIAAQWDD7FgYgABBAMPgWAiAoEFgwWar08xYnIfi4raAiEib7ElMvnhBQMPokAS+e
+ACAAEHgw/xYEIAAQWDD7FgYgABBAMPgWAiAoEFgwWar48xYnIfi4raAiEib7ElMvnhBQMPokAS+e
EEgw8/r8YAAQGDAAAAAAAPPwGGAAEEgw+swAADACW3D8CgAgShBoMFhW9sck0Q8AAAAiEib8vHwQ
-BRBQMPMWJyAYEFgwWarcKxJT9iQBL/QQSDDz+qxgABAYMCISJvy8cxAFEFAw8xYnIBgQWDBZqtIr
-ElP2JAEv9BBIMPP6g2AAEBgwHLxriEyPTZYS+xYBIAUQUDD4FgAgKBBYMFmqxv8CAAH4XK2gIxYn
+BRBQMPMWJyAYEFgwWargKxJT9iQBL/QQSDDz+qxgABAYMCISJvy8cxAFEFAw8xYnIBgQWDBZqtYr
+ElP2JAEv9BBIMPP6g2AAEBgwHLxriEyPTZYS+xYBIAUQUDD4FgAgKBBYMFmqyv8CAAH4XK2gIxYn
Y/9BAABsEAosIAcYu3QMDEEMxhH+u3MWACBBsChiOsDT/s4KABUQSDD+4pcqAWhOECtiOQ67Afq8
AALKADbgKzADF7wy/LvBEtQAtuAlQhQFiFP4FgcufAEsMPxVAQIAxIfgwFAtQSobu2j5u2kQAhBw
MPi7xhAAi0NQjzGboI0gl6X5pgIuCQBH8P+mBC2ABD9g+btbHAkAd3D9pgEgCBBoMJ2j8AkXADAC
SrDyGR4AQAJSsLJVjkD/AgAAAIwrkCkwAQCZMgAkBC1CGidCGf9CGCrgAUww+xYKLyABaDCeGAf/
-GPcyAS4gAXww/xYJIBUANuAoQhQIyVP8iAEB/AJKcAmHOIsg/axQAAQQcDD/CjAgARBoMFmofYkY
+GPcyAS4gAXww/xYJIBUANuAoQhQIyVP8iAEB/AJKcAmHOIsg/axQAAQQcDD/CjAgARBoMFmogYkY
jBodu0iLGRi7rfANBwIAAGqwAE1hAE1hAE1hALIR/7wJEgkAEnD/pgIiCQBAsPKmACAQAnEw8Q4W
ACACarAADYqXpiJCFAwIBvikHSJ8ARAw8qQcIAgCeXD/ZjkgBBBwMP40ACAAEBAw0Q8AAAAAAP+7
aBH/k0dQKEIajTGboIcg+aYCLAkAf3CdpJilmKf4dxEAEBBAMPimAyYJAHXw96YBIAAQODD3pgYg
@@ -1308,24 +1308,24 @@ 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
-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
+IgAAYbBZp5ofuzkYuzeOIC1BFiiCfy2lAilBFwjuDChCGP9CGS4JAHuwnqCMTZyii0ybo/1CCSgJ
ADIw+aUDIIAQSDD4pgQuCQBP8J+l/Y0UDoAEO2CeqZ2o/EIaIAQQWDD8pgcgARBIMCtWOSk0ACog
Bogisar6JAYoCQBKMPgmAiAAEBAw0Q8AAAAAAAAA+9wYIgAAULD8CgAgBRBoMFhVgsck0Q8ALUEW
LkEXhkn7FiQhxQA14By7BShCEYpOi00vQhKWGPoWByAAEEgwmRCbFZ8T+BYBIAAQeDD/FgQgABBA
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -1452,7 +1452,7 @@ kIrgKO3+mBaZoZzhnOCLQiiCfvPyfyABEFAw97sMAAAQSDD7qTgJkAQ6IPkWByIAIETwiDKJN54V
/UERIAAQEDD+kgwoAEAyMPg2AiBgAkJw9UUSIKcAN2AtmRSKmfjoDAGQAnOw9NCKYgUAQ7AqFghl
IEiKGPWyyBA0ADagGbKqKKAAFbLFCYgKKIIQ/KAHIgAAWrD9CgMiAABQ8AuAAC1BFStBEfoWCCoA
Lu7QzCuIGGWPu4wyYABWAAAAGbKaKCAACYgKKIIQ/CAHIgAAWLD6PAAABBBoMAuAACxBFStBEfy7
-jnIAABKwjDLOwWABIgAAAPP/dmAAEFAwLUEQLUURY/9TAACMMszEZSBLZaBIHrNAfOA42sBZoIPy
+jnIAABKwjDLOwWABIgAAAPP/dmAAEFAwLUEQLUURY/9TAACMMszEZSBLZaBIHrNAfOA42sBZoIfy
CgAiAABasPz6/yIAAFDwWEwlizKKE4gWiUL/EgUqCQBasJoyn5EnhoEphoCfQiJFEtEPfscgx90N
zAGcMokTjxaIQf4SBSgJAGZwmTKegCT2gCj2gZ5BihfAwPxFESCjALagixSxu/sWBCQaALrgH7Ko
jkJj/mYAjEB0yVWNF/MSACBQADdgjxGKEvAxBAABEGAw8MwaAyAQQDD5osAv/xBwMP6yIxwRAHMw
@@ -1468,16 +1468,16 @@ IgAAWbD6EgUgAxBoMAuAANagzS9lb9SMEo0TixGMwC3Sr/y8AQABEEAw/Iw5CAAyatBgACkZsdgo
IAAJiAooghD8IAciAABYsPoSBSAEEGgwC4AA8/+XYgAAErBj/4plwEaNQHTZXYgQiREvgsDHr/4S
AygRAFZwCf8BL4bAL+KxLuKtx48I/wMP7gGPEp7y0Q+JE4gRKZKxwNH5iAEAABBYMAjbOHvAuGV/
tYsUsbv7FgQlXAC64Bmx+Y1A8/7AYAAQGDDRDwAAAAAA9LFqEAEQEDD6CgQgIBBYMPyyaxIAAGlw
-WaCvjhAAYQT94sAv/xBAMPAvGgMgEGAw/FwoDhEAR/AP3QH95sAsACA7MC7CsSzCrcf//F0RDhEA
+WaCzjhAAYQT94sAv/xBAMPAvGgMgEGAw/FwoDhEAR/AP3QH95sAsACA7MC7CsSzCrcf//F0RDhEA
e7D+zAEMACAncJzS0Q8AbBAEE7JXLjJpLTJtou4J7hGu3RixTRyxXvwuEQMgEHgw/y8oDgAgQ7CI
4Kz8+sKwIF8ANiArwrFksEl6vFEpwq/LkxuySBqxSKuqqvptCB0oorAvoq/5GRQOACBH8PqsMC4B
AMfw/6ajIA4ANmBj/9sAAAAAAAAA+MKtIAAQSDApxrGY4orXKqwQWEYu0Q8AgtciLBDaIFvPUmih
-AtEPANogW89vErIwC6gR9KA5YgAgQLAM6jArIoWLsCKs//y7CAIAAFCwWaKgKjKV8CEEAAEQWDAA
-uxoLqgIqNpVZotXRDwAAAAAAAPoKByABEFgwWEbXLCJ/LCaD0Q8AbBAEE7EVIzF+ojLRDwAAAAAA
+AtEPANogW89vErIwC6gR9KA5YgAgQLAM6jArIoWLsCKs//y7CAIAAFCwWaKkKjKV8CEEAAEQWDAA
+uxoLqgIqNpVZotnRDwAAAAAAAPoKByABEFgwWEbXLCJ/LCaD0Q8AbBAEE7EVIzF+ojLRDwAAAAAA
AABsEATAINEPAGwQBPSyFBMgECgwBSIo+LEQFAAgILAkQpfBXwNVDPVFFnIAIECwAzQJDEQRpCIi
LQsiIRjRDwAAErFy0Q8AAABsEAb8sgUQAhBoMPowAyAAEEgw9SwAD/8QWDD7JBYgABAQMPJVGyI/
ADag86QLAA8QeDD/FgAgDxBAMCowCBmx9/8CAAoAvMKQCakKiZAKkAAAAIYz9odCBuABMDD6fAAC
-AABZsFmePByx7CdUDCZUDSihByhVB/ABRWACEGgwiTOZEGABOYszbrgH8AExb+oQEDAqUAcKCkFZ
+AABZsFmeQByx7CdUDCZUDSihByhVB/ABRWACEGgwiTOZEGABOYszbrgH8AExb+oQEDAqUAcKCkFZ
Svccsd8qVBbwARpgAhBoMIszK1QWYAENizP/AgAEAIQC4Gi2Lfi1MGAIEFAwaLco+LglYAkQcDD/
AgAOAHVy0C9QIMCE/VQFLgkAR/AvVCBgANItVAVgAMwpUCAKmQIpVCBgAMCLMytVG2AAuI4zLlUa
YACwKsJ9jzMpwoDwkAQOACBX8PoIBgH+Anvw+MKCLgBAR/APDxkN/zf4/zYA/xBAMAj/Ni9UI2AA
@@ -1508,11 +1508,11 @@ mQj5ZRQmACBiMPgWCyoBfTbQ+xYTICAANOADOQL7zAAAFQA1IG1JBQAJhgBLYYYdiBuGYKhmKBIT
/wIABgGVRZCJHZaQi8DWwPsIRwIAAEswbYkHKJAIaIELuJnAcfP742ADECgwiJMHuwEIuwKbwCgg
IQ2IAQWIAigkIWP/2sCbeaFEuGb/AgAGAGU9kCpgCGSgl2ihZGii6WijVmmp3oljbpPeaZPbiyf8
+sAgQAJS8PwKACoAQGKw/LUUIIACUrCauZq4Y/+6jB6OIo8njSApIBYv+RSZEPhiAyAFEFAw+BYB
-IAAQWDBZnnSIYygkFmP/j4ljKSUIY/+HHLAwi2P6IAcsACBi8CzAgC0K+/2qAQ3gBDsg/KoCAPwQ
-YDAMqgELqgIqJAdj/1gAi2MLikL6Fg8q4AFcMCsWEFmcbSyhBy0SEI4fLiQMLSQNLCUHY/8wABqv
+IAAQWDBZnniIYygkFmP/j4ljKSUIY/+HHLAwi2P6IAcsACBi8CzAgC0K+/2qAQ3gBDsg/KoCAPwQ
+YDAMqgELqgIqJAdj/1gAi2MLikL6Fg8q4AFcMCsWEFmccSyhBy0SEI4fLiQMLSQNLCUHY/8wABqv
Dh+v0PP8gGAAEHAwAAD/AgAD/nJ/kIlgKAr8CNgB/voAKAkAQnD+CggoAEB2cPgkByDxEEAw/JkC
CABAQvD5ZgAoCQByMCgkIWAAAYlg8/ymbOABSDAAACoSElvNPBuv/gusEay7+xYHIFQANqAM6jAr
-soWLsLCq+hYGKgAgZvBZoG0cr/yNFirCf/DRBAABEFgwALsaC6oCKsZ/WaChY/uDKcKAi5GIkJiw
+soWLsLCq+hYGKgAgZvBZoHEcr/yNFirCf/DRBAABEFgwALsaC6oCKsZ/WaClY/uDKcKAi5GIkJiw
iJCbgZ6QnpEowoKwiCjGgmP6//oKByABEFgwWESdihcpon8ppoNj+1EAAPosAAAwAlrw/AoBIAMQ
aDBYSjL6LAACAABY8PxMAAIAAGlwWEbz0qDRDyUhCB+u4fC2EQgCAWgw+ogQBAkANXD2rtUYCQB6
MJjAjyCWwhau2sKAmMP2VQIAAxBAMPb2Ag+ABD/gCP8Cn8GDK48pnsWVxJ/Ik8n4nxAABBAYMPbG
@@ -1538,13 +1538,13 @@ ID4QUDD7IBYmAfrWUPwKPSYB9sZQ/gr/LgIS4lCIOfgJQQAEECgwCVUMBQVB9VwPL/gQSDAJVQH1
XH8oACAqMPVFFABoAkIw+BYEIDQEcvD83P4gARBQMPogQSwFAGKwWEigZKP3ixgZrZ0MuhH9rZ0a
ACBKsCyiOv29CgAIAkFw/dKXKgHMxxAsojmYGf3EAQ4Bxm8QLCEilxArIEEpMgn6rjUQCBBAMPwW
BSAEEHAw+7sJDiABTDD/7gwLwAQ+4P+unh4gAXAw/hYDKgAgWrD6on8gAxBgMPoWBigAIHZw+CRk
-IHgCSnD5FgcgBxBAMPgkXCIAAFhw/66RHgkAe7D/JSovgAQ7oP4WACDKAlCwWZPDjRYnJTUnJGj4
+IHgCSnD5FgcgBxBAMPgkXCIAAFhw/66RHgkAe7D/JSovgAQ7oP4WACDKAlCwWZPHjRYnJTUnJGj4
IQcgLhBIMPkkVyBSEFAwKiQF+a12EEIQUDD6JHQpQAFAMPoSBSnABDog+a2PGAkASjD4RgAgRBBw
MPrbFAzAAWgw/yIAK0AEPuD+RgMuSAFoMP19QA+ABDug9d0RDAkAczD+rnEaCQBu8Pj/EQoJAGbw
/K5sHgkAfXCfQR+tW59C/xIHK0AEOqD4IEEqCQBisJpGJ0UK/kYHKQAEOiD3jhQICQBaMP9FCygJ
AEow+EYEIJACaLDyDRYAQAJhMABMY/khKiAAEFgwK0QxK0Qy+0QzIAAQUDAqRDUqRDb6RDcgABBA
MPhEMCAAEHgwL0Q0LkQuKUQtJ0QvCYkUKUQsLSBXLUQ7DY0ULUQ6DY0U/UQ5IAQQYDD9jRQAeAJR
-MP1EOCC4AliwWZN294sUAMACQLDzCBYAgAJJMABJigAIiAAJiogTJ0RTK0RSHa0qC4sUK0RR+4sU
+MP1EOCC4AliwWZN694sUAMACQLDzCBYAgAJJMABJigAIiAAJiogTJ0RTK0RSHa0qC4sUK0RR+4sU
AEACSPD7RFAgsAJRMAYJiADKigQJiACKiv1GGiAQAlowK0Yb+SB0KgAgQTAppHQvIQcoMAeYMSgg
BywhCPmtIBvABDlg/w9KCgIBRDD8/xEKoAQ+4Pv/AgQAIFEw+62CHgkAT/D/RgAoIAFAMPoiAC8A
BDog90YFLAkAczD3RgcgMBBIMPlGAywJAFswnESbRv1GAiAEEFgw/az0G4AEOqD8EgkqCQBasPpG
@@ -1561,11 +1561,11 @@ YPgKSSMwADTgLjAS+wpVIykAN6ApIAX8Cv8mAY9eUCsgFvgkBSAaBGLwAMWOWEdlZKNIwEEZrGLA
7PxoEQABEFAw+axgGAAgSjD9gjoiAAB5MPSvOQAEEDgw+WkKBgUAf7D5kpcqAXi/UCWCOQlVAfus
bBLrADVg+FwAAgAAUXDwCwcAQAIxcG15AgBIYWRBsS0hBx+sVQ0NSgzdEf6tYxwJAH9wLVYAKiIA
+a1dEGQQWDD8rFAQCBB4MPxWAiuABDqg+1YDKgkAerAqVgH5JSogBxBAMPgkXCIAAFhw/yRkIAMQ
-YDD+FgAgygJQsFmShB6sXYoR/yEiIC4QYDD8JFcgQhBoMP0kdCBSEGAwLCQF/SBBIAAQYDAsJTUP
+YDD+FgAgygJQsFmSiB6sXYoR/yEiIC4QYDD8JFcgQhBoMP0kdCBSEGAwLCQF/SBBIAAQYDAsJTUP
2BT8JGgvQAQ/4PoJRgpIAVQw9IgRCgcBUDD4uxENAAQ/YPuZAgtQBDqg+q04GAkAUjD8VQogVBBY
MPmtMxgJAEow+1ULLAkAR3D6VgcsCQB3cP1WBC4JAE/w/1YGIJACSLDyCRYCAABBsABIY/shKiAA
EHgwL1QxL1Qy/1QzIAAQcDAuVDUuVDb+VDcgABBoMC1ULvxULyAAEFAwKlQw+1QtIAAQSDApVDQL
-ixQrVCwoIFcoVDsIiBQoVDoIiBT4VDkgeAJRcPiIFAAEEGAw+FQ4ILgCWLBZkkL2bQEgwAJAsPMI
+ixQrVCwoIFcoVDsIiBQoVDoIiBT4VDkgeAJRcPiIFAAEEGAw+FQ4ILgCWLBZkkb2bQEgwAJAsPMI
FgCAAklwAEmKAAiIAAmK+l0BIAAQWDD7VFMgABBYMPtUUiAAEFgw+1RRIAAQWDArVFD+IHQhAAIx
sP5UcCEAAlKwHqxeLCEHLTAHnTEpIAcvIQj9q+8dQAFgMPzMEQoCAUww+QlBCqAEPuD7zAILAAQ+
YPgyAC4JAF/w+6vdHAkAazCcoIwg+6YCLgkAd/D/pgQgABBoMJ2lnqb9pgcgMBBwMPjMEQAEEGgw
@@ -1592,8 +1592,8 @@ ioArEhX4FhYgBBBIMPDdEQogAVAw+pkMCgkAbvD6q8gaCQBm8Jt0+xIRKCABTDApFhooggD6dgcg
ABBQMCp1CvkSFCgAIEow+XYGIHgCQjAodQvwCxYAQAJJ8ABJYSkxKvp0LyAAEGgwLXQz+XQtIAAQ
eDD/dDAgABBYMPt0NCAAEGAw/HQyIAAQcDD+dDEgABBgMPx0NyAAEHAw/nQ2IAAQWDD7dC4gABB4
MC90NSsSEi8SGQmJFCl0LP4wVy4AIEfwLxYZLnQ7Do4ULnQ6Do4ULnQ5/o4UAHgCUfD+dDggBBBg
-MFmQzPkSEyCAAlHwAgmIAEqKAAmIAAqKKzIcKhIXK3RTC4sUK3RSC4sUK3RRC4sU+3RQIHQIUXAs
-Ehr9q4sQigJR8PscAABCEHAw/jR0LCABYDD9CggsCQBrMP00ZS2ABDsg/BYAIAMQYDBZkLItMTX2
+MFmQ0PkSEyCAAlHwAgmIAEqKAAmIAAqKKzIcKhIXK3RTC4sUK3RSC4sUK3RRC4sU+3RQIHQIUXAs
+Ehr9q4sQigJR8PscAABCEHAw/jR0LCABYDD9CggsCQBrMP00ZS2ABDsg/BYAIAMQYDBZkLYtMTX2
KQsANhBwMC40V/qSAyACAmtwLTU1LRIWHKt4LHYWi9ArdheI0I4/LzIcKnYZiZL5dhguACBH8C82
HC8SGC3SALEi+EQMDgAgfjD/FhgsACB3cP02DyAYADyg8goAIDACMbAZqlUpdhopEhrA9Q9fL7iY
KHYb+DB0KAAgPnD4lHQtzgC34CoSEAWqDLaq/wIAA/7fQqCOH40eLeY5KzAWLAr/fLEIKjBBLBIZ
@@ -1611,9 +1611,9 @@ BD/g+LsRAAgQaDD8VgIqCQBu8PtWASzAATgw/2IBLAkAezD4IEEoCQBWcPTqEQgJAGZw+6qzEAQQ
YDDwiBEGIAF8MPfHDAgJAEow+am+FiABPDD3/wgKCQBasPpWBiB4Anvw/xYGKAkASjCYVC9VCxiq
pfhWByAAEEAw+FUKIJACcLDwDhYAQAJpcABNYf8hKiAAEFAwKlQ1KlQ2+lQ3IAAQSDApVC74VC8g
ABBwMP5UMCAAEGgw/VQ0IAAQWDArVDErVDIvVC0rVDMPjxQvVCwrIFcrVDsLixQrVDoLixQrVDn7
-ixQAeAJRcPtUOCC4AliwWY+6KSxg8wkWAIACUXAASooACYgACootIhwcqoEtVFMNjRT9VFIgigJR
+ixQAeAJRcPtUOCC4AliwWY++KSxg8wkWAIACUXAASooACYgACootIhwcqoEtVFMNjRT9VFIgigJR
cP2NFAIAAFhw/VRRIEIQSDD9jRQIIAE4MP1UUCgJAGIw+SR0IAgQYDD8JGUpgAQ6IPgWACADEGAw
-WY+hG6le+iE1IDYQYDAsJFePY4hh+WIAIAICUrAqJTUpVhYoVheNYS9WGY5iLlYYLSYcLGIBLCYP
+WY+lG6le+iE1IDYQYDAsJFePY4hh+WIAIAICUrAqJTUpVhYoVheNYS9WGY5iLlYYLSYcLGIBLCYP
+1YaIBACUfAqVhv4IHQoACA9cCiUdC8KCC9GOSsgFi4K/36xCCogQSwSBlhEDPwSAiIAAFCw/RIB
IgAAWPBb/LXRD8DY+RIEIEcQUDAqJAWZN44iiBP4NgkgABB4MP82CC/fALeg2iD7EgUgARBgMFhE
htEPACsgQSu8EpsV8//DYAAQaDBsEAYoIAT/AgAGAHYOIPs8AAQAciIgBQhH/QoAIgB7giAqsAMs
@@ -1682,8 +1682,8 @@ QAQ/IPCdEQTAAUQw+IpCBgcBQDD7JQsgABBIMPklCidQBDmg/NgUC4AEOqD8psIZQAQ6IPpVAgYJ
AEGw8/8CBAkANXD/JgYsCQAvcPwmBywJAHdw/SYEIJACUfDyChYAQAJAsABIY/hxKiAAECgw9SQx
IAAQGDDzJDIgABB4MP8kMyAAEHAw/iQ0IAAQaDD9JDUgABBgMPwkNiAAEFgw+yQ3IAAQUDAqJC4p
JC/4JC0gABAwMCYkMAiIFCgkLCZwVyYkOwaGFCYkOgaGFPYkOSB4AlCw9oYUALgCWfD2JDggBBBg
-MFmLyih8YPMIFgCAAkiwAEmKAAiIAAmKKHIcKCRTCIgUKCRS+IgUAKgCULD4JFEgDBBgMPiIFAD+
-Alhw+CRQICICWvBZi7krcHQrJGQqEiobpWYMqhGrqiSmOStwFikK/3mxCvpwQSBIEGAwWEAzxMX8
+MFmLzih8YPMIFgCAAkiwAEmKAAiIAAmKKHIcKCRTCIgUKCRS+IgUAKgCULD4JFEgDBBgMPiIFAD+
+Alhw+CRQICICWvBZi70rcHQrJGQqEiobpWYMqhGrqiSmOStwFikK/3mxCvpwQSBIEGAwWEAzxMX8
dAUgABAQMNEPLKEFLaEE/6IAIAICYzD8DE8B/gIjcPylBSYAju8QDEQR9PwID8AEOyAOzAwEDIvA
0A3dZPAMhA+QALtgLqEFGqZsJXUTLKLn+qLmL5AEO6D1dRQsACB3cP11EiugBD9g/cwICgAgWrD8
dhYi8wA2oBulPwwvEav/LxYpL/I68hYoJgFLQ+AuEikUpfwu4jkELwov8q//5AEOAUD/kB6l0wpb
@@ -1700,15 +1700,15 @@ I4AEPOD+xgciCQBU8PPGASACEBAwbSoFCgmGAEhrjHfA0Pn6wCBAAmMw+rY5KABATzD9xQQggAJK
cJnB+cYAIFIQQDD4dAUgABAQMNEPxdItdAVj+52OcmXpIStwQfp8AAABEGAw+7wSIAAQaDBYP/bA
INEPwEDAwPwWJyfgAWgwGqWy+2wAAAAQYDD6oqEgARBoMFg3JxilrSoSJyiCovZsASACAlKwCGYu
/wIAAf7uhqAqFidj/8cAAADz+NdgABBQMIlyyJrydAUgABAQMNEPAAD6fAAAARBgMPuMGCIAAGnw
-WD/Y8nQFIAAQEDDRDwAAAGwQCAUGR/TVGgAFEFAw/KWWEDAQWDBZk7z3IhAiAkYZoBak7SViiypS
+WD/Y8nQFIAAQEDDRDwAAAGwQCAUGR/TVGgAFEFAw/KWWEDAQWDBZk8D3IhAiAkYZoBak7SViiypS
FSihAmSEj1gyzhyk3y1SFizCbitihf3cASwAIFMw/VYWLZAEOyD6IAcqACBm8CmwB/wK+yoCAVAw
/qoRCABAZnD+IAwoCQBWcCm0B/ogBy+YEGgw/rQMIPwQYDD9tAUoAEBmcPK2CiAAEGAw/LYIKiAB
UDD8tgkoCQBWcCm0B/W8AAQcADbgirf8oggvwAQ9IPuhFS/AEHAw+aILIEACarD2qRQuAEBzcP4W
BSoAIHbw+7xAJgH5ZlCvZvalFCoAIGPw/wIACgH8VtDJOPnMAAAWADUgbUkFAAOGAElhKtIADwIA
D6oI/wIABgIPXpCa0NPAiVD6pK4dgAQ6YPsxCCwJAGEwnDErVQgqonMKmQz5aBQAkAIhcPkNRQwB
zZIgKnBwtqoAoQQAiBoI2AIoVg4kVhMkVhIvMCH0PCAuwAF8MP9UUCABV4fg/wIAAgFTg+C4SlmS
-cBylOy1AAP5AASAwEFgw/1BQIgAAMrD2FgAgBRBQMFmTWi0xCBylM/5RCCAFEFAw/1IMIDAQWDBZ
-k1SIIvogByLBALYgGKQFCgpBDKkRCJkIK5I6+hYEJAFKxuAcpAArkjkMrAoswpf8swEOAUDm0Csi
+dBylOy1AAP5AASAwEFgw/1BQIgAAMrD2FgAgBRBQMFmTXi0xCBylM/5RCCAFEFAw/1IMIDAQWDBZ
+k1iIIvogByLBALYgGKQFCgpBDKkRCJkIK5I6+hYEJAFKxuAcpAArkjkMrAoswpf8swEOAUDm0Csi
Ei4iCRykQf0iCioIAVwwKxYGDLsKK7KADt0M+xYHIGACWvD/AgAKASJfUCsgFiwK/3yxEvogByAA
EGAwWD7r+KPqEwgANqAsIQcdo/IMDEr+pBIdwAQ7IPqj8BwJAGswnDCJIP2kQxAFEHgw+jYCIEAQ
WDD7NgMngAQ6YPsSBiYJAHmwljEsIhL77TgMSgFgMPq7EQ1gBDsg+qQ3GgkAZvD8IRoqCQBu8P0S
@@ -1718,22 +1718,22 @@ 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
-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
+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
-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
+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
-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
+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
@@ -1743,18 +1743,18 @@ YwAEhgBJYS8iFh6iVC80Pw+PFC80Pg+PFC80PQ+PFC80PP9SDiAAEEgw+TQkIAAQYDAsNCL8NCYg
ABBoMC00Iy00J/80MyAAEFAwKjQlD48ULzQyD48ULzQxD48ULzQw8A4XAJACUPDyGh4ABRBIMCxy
ESw0OwyNFC00Og2NFC00OQ2NFC00OCsgB/xWDyogAVwwDLsRqLsptjkrIBYqCv96sQr6IAcgMBBg
MFg898lTiFjIj49ZwOCeW5jwiVifkZ5YLlYJHKNJjSAvchQuchEochOYEPZSDiAFEFAw9hYBIDAQ
-WDBZkWAp+pn5VAUgABAQMNEPAAAA+RYHIgAAUnBZkGf7XAAP/xBoMPz6/yIAAHKw/1BQIgAAULBZ
-kHCJF2StYcHW2iD7XAACAABg8Fg8isAg0Q/aIFg9Ifih/x3lADagYAAUixT6LAAAARBgMPu8GCAF
+WDBZkWQp+pn5VAUgABAQMNEPAAAA+RYHIgAAUnBZkGv7XAAP/xBoMPz6/yIAAHKw/1BQIgAAULBZ
+kHSJF2StYcHW2iD7XAACAABg8Fg8isAg0Q/aIFg9Ifih/x3lADagYAAUixT6LAAAARBgMPu8GCAF
EGgwWD1WjFhlz9GPLxijI/hWCyBAAmlw/fYAIHACcLCeWJ9Z/SYPIAAQEDDRD4g3KYkU9TwAAKwA
NmCDiSQ8MPP87GBwAkjwAAAA8/wPYAAQWDDz/3lgjhBoMMCwm6vz/GxiAAAacAAAAADz/KZv/xBA
MPy6DAA3ADTgCksU/rwIIgAAQPD+TjYCAABLMNMPbekFBgiGAElniRWqOPtPDACAAkpwbfkFCAiG
AElpixUKbgyuuyu8QJvQY/wPjxUv/ECf0GP8BYsU+iwAAAEQYDD7vBIgABBoMFg9IWP/JgAAAADz
/1ZgABAYMGwQBvwKAiBCEDAw9QoDIAEQWDD4otEQABA4MPcWACAuEEgw+CUqJABogSAqMBX5JFcg
-iAA1IP8CAAAAbwUg/wIAAgBhASBuRTgKaxR7UAUsMBQsJGAqLGX9otcSAABYcP0WACADEGAwWYfz
+iAA1IP8CAAAAbwUg/wIAAgBhASBuRTgKaxR7UAUsMBQsJGAqLGX9otcSAABYcP0WACADEGAwWYf3
JyRoJyRpJyU1JyYcJiR0HqIELiU30Q9uQ8P/orcSAABhcPskZCAjEEAw+CRcIMoCULD/FgAiAABY
-cFmH5CckaCckaSclNScmHCYkdNEPACkwMMGi/wIABgBE1lD7JGQgugJQsPwKAyAiEFgw+yRcIDoC
-WPBZh9YqLGH8CgMgMgJY8FmH0iowFWP/UgAAHaItLSUqLDQwY/8mwPb/JFwgCBBwMC4kZGP/NAAA
-AAD6LF0gOgJY8PwkXCAgEEAw+CRkIgAAYXBZh8EpMBjTD3+XtCosYfwKAyAyAljwWYe8Y/+jGqH1
+cFmH6CckaCckaSclNScmHCYkdNEPACkwMMGi/wIABgBE1lD7JGQgugJQsPwKAyAiEFgw+yRcIDoC
+WPBZh9oqLGH8CgMgMgJY8FmH1iowFWP/UgAAHaItLSUqLDQwY/8mwPb/JFwgCBBwMC4kZGP/NAAA
+AAD6LF0gOgJY8PwkXCAgEEAw+CRkIgAAYXBZh8UpMBjTD3+XtCosYfwKAyAyAljwWYfAY/+jGqH1
LDEcKqJ/CcwRrKosoTYsNRyKoComHmP/XmwQCCciEPUIRwBCEFgw+nwAAgH/GiAoMDD2od0YAgLC
0CViiypSFSyhAmTEUlgvvRihzilSFiiCbi9ihfmcASgAIFIw+VYWJZAEPiD+IAckACAv8C1QB/8K
+y4CAXAw/u4RDABAf3D5IAwsCQB3cC1UB/4gBy+YEEAw+VQMIPwQeDD4VAUsAEB/cPJWCiAAEHgw
@@ -1774,9 +1774,9 @@ MBBgMFg7Z8lSiFjIjo1ZwMCcW5jQjlid4ZxYnFkvMDDI+yL6mfJUBSAAEBAw0Q8pchEqchSxmfl2
ESACAlKw+nYUL5kQQDD4VAUgABAQMNEPAAAAANogWDug+KB+HigANqBgAEHAwfxEIC+BEFgwK0Qh
Y/8AAAAAAAD6LAACAABZcP0KjiIAAGDwWDr5wCDRDwCLFPosAAABEGAw+7wYIAUQaDBYO8qMWMjC
wCDRD48vGKGY+FYLIEACaXD99gAgcAJwsJ5Yn1n9Jg8gABAQMNEPiDcpiRT1PAABJwA2YIOJY/0k
-LjAx/KGLEAUQUDD/IgAgMBBYMPgNRQ7AAXAwWY+g+iwAAgAAWPD8TAACAABpcFv9Q8Ag0Q8AAByh
-f40gLiIYhlCPoP7gdCAwEFgw9hYAIAUQUDBZj5LAINEPAAAAAPP8IWAAECgwwPCfq/P8fGIAABpw
-AAAAAPP8pm//EEAwHKFvL3IRLjAwjSApchSZEChyE5gR9lIOIAUQUDD2FgIgMBBYMFmPfmP+7AAA
+LjAx/KGLEAUQUDD/IgAgMBBYMPgNRQ7AAXAwWY+k+iwAAgAAWPD8TAACAABpcFv9Q8Ag0Q8AAByh
+f40gLiIYhlCPoP7gdCAwEFgw9hYAIAUQUDBZj5bAINEPAAAAAPP8IWAAECgwwPCfq/P8fGIAABpw
+AAAAAPP8pm//EEAwHKFvL3IRLjAwjSApchSZEChyE5gR9lIOIAUQUDD2FgIgMBBYMFmPgmP+7AAA
AAAA/NoMADcANOAKTRT+3AgiAABA8P5ONgIAAEsw0w9t6QUGCIYASWeJFao4/U8MAIACSnBt+QUI
CIYASWmNFQq+DK7dLdxAnWBj+++PFS/8QJ9gY/vlixT6LAAAARBgMPu8EiAAEGgwWDt1Y/6oAAAA
APP8A2AAEBgwbBAIKCAE0w/0gBxq4AEsMPuHDGAYEEgw/wIABAHeCiB5gQTAINEPACciEC4KQvp8
@@ -1799,9 +1799,9 @@ ABAQMNEPKXIRKnIUsZn5dhEgAgJSsPp2FC+ZEEAw+FQFIAAQEDDRDwAAAADaIFg6RvifJB4oADag
YABZwMH8RCAvgRBYMCtEIWP/AAAAAAAA+iwAAgAAWPD8TAACAABpcFj+FcAg0Q8A+iwAAgAAWXD9
Co4iAABg8Fg5mcAg0Q8AixT6LAAAARBgMPu8GCAFEGgwWDpqjFhlzACPLxigOfhWCyBAAmlw/fYA
IHACcLCeWJ9Z/SYPIAAQEDDRD4g3KYkU9TwAASoANmCDiWP9DwAAAC4wMfygKxAFEFAw/yIAIDAQ
-WDD4DUUOwAFwMFmOQPosAAIAAFjw/EwAAgAAaXBb++PAINEPAAAcoB+NIC4iGIZQj6D+4HQgMBBY
-MPYWACAFEFAwWY4ywCDRDwAAAADz/AlgABAoMMDwn6vz/GRiAAAacAAAAADz/I5v/xBAMBygDy9y
-ES4wMI0gKXIUmRAochOYEfZSDiAFEFAw9hYCIDAQWDBZjh5j/uwAAAAAAPvaDAA3ADTgCk0U/twI
+WDD4DUUOwAFwMFmORPosAAIAAFjw/EwAAgAAaXBb++PAINEPAAAcoB+NIC4iGIZQj6D+4HQgMBBY
+MPYWACAFEFAwWY42wCDRDwAAAADz/AlgABAoMMDwn6vz/GRiAAAacAAAAADz/I5v/xBAMBygDy9y
+ES4wMI0gKXIUmRAochOYEfZSDiAFEFAw9hYCIDAQWDBZjiJj/uwAAAAAAPvaDAA3ADTgCk0U/twI
IgAAQPD+TjYCAABK8NMPbekFBgiGAElniRWqOP1PDACAAkpwbfkFCAiGAElpjRUKzgyu3S3cQJ1g
Y/vXjxUv/ECfYGP7zYsU+iwAAAEQYDD7vBIgABBoMFg6FWP+qAAAAADz++tgABAYMGwQBhmf5fKS
XSIAAHCw/UwAAgAAYPD/CgAqAIyQ0CWSXJUQK1EE9VIAIf4CIzDzIwwAARBAMPy7EQIAABMw8AAO
@@ -1880,8 +1880,8 @@ ES7SFPsSGiACAmMw/NYRIAICc7D+1hQvmRBQMPq0BSAAEBAw0Q8AAAAAKhIbWDXEZK1cYABNiifb
MPqsICIAAGEwWDEajCD6FhktgAQ7IPuhCCwJAGEwnKErJQhj9bYA8/WvYAAQGDD6EhsgMAJZ8P0S
EyABEGAwWDXuLhIaLRISLeYTLxIaj/jI88Ag0Q8AKBIbKhIai48cm8T8pgsgQAISsPK2ACBwAkow
maibqfKGDyAAEBAw0Q8AAAAAAAAA+hIbIDACWXD8CgEgBRBoMFg12GP/rcDQ8/cRYBYQSDApEhsc
-m7IoEhqNkCmSGI/giID+kHQgBRBQMPgWACAwEFgwWYm5wCDRDy0SGxybqS7iEf3SACAFEFAw9BYA
-IDAQWDBZibFj/rz6EhsgJAJZcPwKASAAEGgwWDW+Y/9FAADz/qRgjRBoMPP272//EEgwwNDz9pdg
+m7IoEhqNkCmSGI/giID+kHQgBRBQMPgWACAwEFgwWYm9wCDRDy0SGxybqS7iEf3SACAFEFAw9BYA
+IDAQWDBZibVj/rz6EhsgJAJZcPwKASAAEGgwWDW+Y/9FAADz/qRgjRBoMPP272//EEgwwNDz9pdg
AhBIMAAAbBA6KCAEIhZkIxZR9RZQJnQANiDyChgmAswOIP8CAAQCyCIgjDAvEmQjFk8vFlT98Acs
4AFgMPwWTCDWAmMwDEwU/BZNLCABbDD9FkskArsCICgSVA8CAA8CACiABcR+/wIABgKkPhDFkXmB
KysKVHuBJSoSVCsST/wcFCAwAmhwW/vY/wIAAAlHKqAqEk8oElSJFZmnKIAFLBJPg8bzB0EABBAw
@@ -1897,15 +1897,15 @@ nIieifqGBSBgAkIwKhJOKBJUwZv5pjkgVBAwMCaEBSsSVNMPDwIAK7AWLAr/fLEWLBJQKhJUAMyO
KqBBWDSt/wIAAAfSKqAkEksemakMTRH+Ek0sACB3cC0WTi3SOv8CAAoHdvdQLxJOFppkL/I5BkYK
JmKv9vQBDgdrN9AYmbXwCAcCAABBMG3pAgBIYSoSUSwSVPuarhAAEDAwJhZE+8UqIC4QaDD9xFcg
BhBwMP7EXCAIEHgwL8RkKqAV+moUAAMQSDD/AgAIB6FSUCoSVByatisdAfwWRCAgAlrw+qxlIAMQ
-YDBZf9IlElTAoCpUaCpUaSpVNSpWHPlRByBCEFAwKlR0GpmF+BJMKUABTDD7mdwZwAQ+YPtVNygJ
+YDBZf9YlElTAoCpUaCpUaSpVNSpWHPlRByBCEFAwKlR0GpmF+BJMKUABTDD7mdwZwAQ+YPtVNygJ
AFZwmUCHUPYSTSCYAkIwmEP4mX0XgAQ94PhGAiYJADmwlkEjUEEfmhEoUAUDNgn8ZhEAUBBoMPVR
Ii4AIDfw//J/ICYEajDEvnuBCcXG/wIADgeIYhAYmYkamnf13RQJQAQ9YPaadRcABDzg/wtGDkgB
eDDzEkwsBwF4MPZGBy1ABD9g9cwRD4AEO6D+CgAqCQB28P3MAgB4Ahjw80ULKgkAZvD7ElQmCQBd
8P5FCigJAFZw+UYGJgkARfD3RgQgkAIy8PAGFgBAAhEwAEJhLbEq/kQvIAAQEDDyRDcgABAwMPZE
NiAAEDgw90Q1IAAQQDD4RDQgABBIMPlEMyAAEFAw+kQyIAAQYDD8RDEgABB4MC9EMP1ELSAAEHgw
-L0QuDY0ULUQsLLBXLEQ70w8MjBQsRDoMjBT8RDkgeAJRMPyMFAC4Alrw/EQ4IAQQYDBZf3AoElT/
+L0QuDY0ULUQsLLBXLEQ70w8MjBQsRDoMjBT8RDkgeAJRMPyMFAC4Alrw/EQ4IAQQYDBZf3QoElT/
TEAgwAJCMAIIiABPigAIiAAPiiwSVCzCHCsSTyxEUwyMFCxEUgyMFCxEUQyMFPxEUCCoAlEw/BJM
-IGACWvBZf18rElQvEkwPAgD+sHQuACB9MC70WC0STiwSTSzWOSuwFi0K/32xDSoSVPqgQSIAAGDw
+IGACWvBZf2MrElQvEkwPAgD+sHQuACB9MC70WC0STiwSTSzWOSuwFi0K/32xDSoSVPqgQSIAAGDw
WDPWKhJUKBJPxJUppAUogBJkgEUUmRiDpwSEKPpMAAAgAhjwW8GMLxJU/ZlbEgAAYTD+mjUSAABa
sP/yACIAAFDwW8FBIhJUgiciLBDaIFu3FP8CAAAGfQagwCDRD8FpeGL2/wIACABllhBj/+sAAAAA
/DwAACACWHD9MQgiAABT8P4KACIAAHlwWBnbLQqI/wIABga7bpCOFGTvvIjni4j1gRUvwBAwMPmC
@@ -1963,29 +1963,29 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -2018,21 +2018,21 @@ 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
-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
+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
-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
+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
-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
+YDD4iBQAeAJRMPhEOCC4AliwWXhchhn5TEAgwAJAsAIIiABJigAIiAAJiiwiHIseLERTDIwULERS
+DIwULERRDIwU/ERQIKgCUTD8Eg8gYAJa8Fl4TI8f/iB0LgAgfTAu9FgmVjkrIBYtCv99sQr6IEEi
AABg8Fgsw4gexJYpJAUogBIPAgBkgEEUkgYjIgcEhCj6TAAAIAIY8Fu6ef2SSRIAAGEw/pMjEgAA
WrD/IgAiAABQ8Fu6L4InIiwQ2iBbsANpoQVgB4R4kQPAINEPJCIQ9ZMYGOABLDD4TAACA1qaYCVS
eipSFSuhAmS23lggNhiSRylSFhuTDyiCbiuydPmcASgAIFIw+VYWJZAEPiD5IAckACAu8ChQB/oK
@@ -2065,11 +2065,11 @@ PS5SFyzMGPZWFiACAnOw/lYXIAAQGDAvEgsuEgYq/Bj8OgoOBQB2sP8WCyIAAHrw9Z9/bgABeDDz
Y/gZAAAA+iwAAgAAWPD9MQgiAABh8FgKlGSh6YmnK5kUyrmLmSggBcPO+xYOJgDgZhDE4v8CAAYA
23YQw/3/AgAOAO56EPP22mIAABKw8//TYAAQWDDAoSpWFmP+z/osAAIAAFlw/QqOIgAAYPBYKr/A
INEPAIsd+iwAAAEQYDD7vBggDBBoMFgrkGP9UowiZclQixr6LAAAARBgMP0SCSAwAlrwWCuJwCDR
-D4k3LJkU9TwAARkANyCDmWP6DAAckWqPgC4iGI0ghlD+4HQgBRBQMPYWACAwEFgwWX9owCDRDwAA
-AADz+ZNgABAoMPP50W//EEAwHJFeL0IULkIRjSAoQhOYEPZSDiAFEFAw9hYBIDAQWDBZf1lj/0GJ
+D4k3LJkU9TwAARkANyCDmWP6DAAckWqPgC4iGI0ghlD+4HQgBRBQMPYWACAwEFgwWX9swCDRDwAA
+AADz+ZNgABAoMPP50W//EEAwHJFeL0IULkIRjSAoQhOYEPZSDiAFEFAw9hYBIDAQWDBZf11j/0GJ
ImWYwisgQfosAAABEGAw+7wSIAAQaDBYK2XAINEPLDAULCRgY/ZpAAD6LAACAABh8P4yCyIAAGlw
-/zIHIgAAWPBYBx3AINEPANogW64/EpEAC6gR9KBhYgAgQLAM6jArIoWLsLCi/LsIAgAAULBZgXAc
-kTAqwpzwIQQAARBYMAC7GguqAirGnFmBpcAg0Q/FwiwkBWP2m4sd+iwAAAEQYDD7vBIgABBoMFgr
+/zIHIgAAWPBYBx3AINEPANogW64/EpEAC6gR9KBhYgAgQLAM6jArIoWLsLCi/LsIAgAAULBZgXQc
+kTAqwpzwIQQAARBYMAC7GguqAirGnFmBqcAg0Q/FwiwkBWP2m4sd+iwAAAEQYDD7vBIgABBoMFgr
QGP8FAAA8/j5YAAQGDD6CgcgARBYMFglnSwif/wmgyAAEBAw0Q/9CoQiAABh8P21CCIAAGlwWSJP
wCDRDwD6LAACAABY8P0KiCIAAGHwWSNlwCDRDwD+CoUiAABh8P61CCIAAGlwWSJDwCDRDwBsEASL
J4u++7wQIgAAUPBYfiKMJy7JFIvILcEV/u0BL8AQQDD0wgshQAJzsP/MICoATXdQ+OwADgBAR/D+
@@ -2081,17 +2081,17 @@ QDD7ogshQAJzsP+sICoAevcQCP8Br8z8zEAmAIIe0Cs9ASu8oP6lFCoAgV8Q/wIABgCF5tCbqBuQ
uRyPiBqPoh6PoAAMi/wSCCIAAEjwAElhAElhAElhAElhAElhAElhAElhAElhAElhAElh/jYAIGYQ
eDD4IgAgARBIMPo2AiBeEHAw+zYEIgAAWzD8mzkAChBQMPiIEQ4FAFvw/jYFKAkAUjD4NgEgWwA0
4Jc6/DYLIE4QUDD8ClYgiBBwMP41ECoFAFswmjn0DRYAYAJI8PAJpACgAnjw8gQWAIACQPDwCKIC
-AABZsPAFFgAGEGAw8A+gAMACUPBZdY+PIsj2wCDRD8As0Q/6LAACAABY8PwKCiADEGgwW717wCDR
+AABZsPAFFgAGEGAw8A+gAMACUPBZdZOPIsj2wCDRD8As0Q/6LAACAABY8PwKCiADEGgwW717wCDR
DwDAMJOr8/8QYgAAGvADyAwI+AwojQEojOCYqGP++in8QJmoY/7yAAAAbBASHo9HHI9HhSeN4Sni
AyVSDvviAiAgAlBwK6YCKaYD/aYBKaAEOOD+4gAkACBFcC1Suv9SvCADEEgwKVa+KFK9LqYA/lK7
-IDAQWDD4FgAgBRBQMFl+YvldAyAAEFAwKhQiKhQjKhQkKhQlKhQmKhQnKhQoKhQp+hQqIP8QcDAu
+IDAQWDD4FgAgBRBQMFl+ZvldAyAAEFAwKhQiKhQjKhQkKhQlKhQmKhQnKhQoKhQp+hQqIP8QcDAu
FCD+FCwgARB4MP8UKyACEEAw+BQhIQACSnAokHYvkHcvFC8oFC4pkHX5FC0gQAJwcPriASBgAkBw
moGP44nimYKfg47g/oYAILcANSAZjxaLkoyR/ZIAIIACUHCdoJyhm6IpkgP5pgMiAABQsFiBvSoW
FC0WFysWFSRdAywWFvhJCiCgAmBwi8H/wgMgARA4MPnCAiDAAjBw+WYCIAAQaDD/ZgMgAgJCMPh9
OAAAEHAw+2YBIgAAULD8wgAiAABZsPxmACCAAmBwW7M7LUkK0w9o0GovSQv7HGAiAABQsP4KASBg
AmBw//wBIAAQaDD/7TgAABBwMFuzLyhJC2iARvscECIAAFCw/V0DIGACYHD93OggARBwMFiefSlS
v/osAAIAAGjw/I7hEAICSnD5Vr8gZBBYMFj6ZSpWwNEPACpFCmP/jgAAKkULY/+yAABsEASDJ/My
-DiAFEFAw/I/+EDAQWDBZff4oMsl9jwkpMs7MkyoyGsmoHI/5/TIaIAUQUDD+Ms4gMBBYMFl99ccv
+DiAFEFAw/I/+EDAQWDBZfgIoMsl9jwkpMs7MkyoyGsmoHI/5/TIaIAUQUDD+Ms4gMBBYMFl9+ccv
0Q+MICsgPwyNR/C7EQ2ABD9g/AxHCgkAbvAMuwL7Nh0g+AJQ8FiMWvo0/CAAEGAwLDZg/DZhIAEQ
WDD7NhoiAABQsFv+0fyOtxIAAFCw/QoAIGQQWDBY+jkuMskqNhz/CgggAhBoMP02Gi4JAHuw/jbJ
IAAQEDDRDwAAAGwQBIcnH46gKnkUiHgpcRX6rQEvwBBoMPxyCyFAAlKw+3wgKgA9VlANuwGrmfmc
@@ -2101,23 +2101,23 @@ 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
-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
+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
-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
+SjD6FgYqAFXGIMCl/I9UEDAQWDBZfVYtcrPAkfnaAgAOAHtwKnazKzwW+hwAABAQYDBZdFIuYAcp
ctsqctqPEIgR/WAGIAAQWDD6/wwAARAYMPmIDAAAEGAw+Dw4DYAEP2D/OzgMCQB3cP0WBS4AKmbQ
L3LdKHLcjRKOEwjdDP/uDAAAEGAw/jw4AAAQWDANOzh8sCyJFWWRmBqN/Sl9A/AKBwDAAkpwAElh
-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
+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
-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
+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
-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
+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
@@ -2125,23 +2125,23 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -2150,29 +2150,29 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -2180,19 +2180,19 @@ e6Hp+zwAAgAAULD8CgAiAABpcFvBumSv0ywgBXfBdvuLYBIAAFCwWLyRjWeKZrHb/btScAICcrCb
Z55m0Q8AAAAAAAD6LAACAABY8PxMAAIAAGlwW8GpZK+S+DRAYCgQQDApYRcpnAEpZRcvIAX/AgAP
/73D0CckBfsakCIAAFCwWLx60Q+bZ5pm0Q8qYROxqiplE9EPwrUrJAVj/4AsYRaxzCxlFtEPKyQF
+wpkIgAAULBYvG7RDwAAAAD6LAAAKBBoMP0kBSGQEFgwWLxn0Q8AAABsEAqHNPaKahZwATwwB3gJ
-DIgRqGYrYn/0MDMgOAA24BqKNC1tAi3QAC6idyqigA7dCAndEf2qCAABEGAwWU95KW0CKZyAKZB5
-/pcHcgAAMrB/nwPRDwAA+jwAAgAAWHBY+W7Ir8Ci/IsaEDIQWDBZePbRDwAA23D8MQoiAABRsFj5
+DIgRqGYrYn/0MDMgOAA24BqKNC1tAi3QAC6idyqigA7dCAndEf2qCAABEGAwWU99KW0CKZyAKZB5
+/pcHcgAAMrB/nwPRDwAA+jwAAgAAWHBY+W7Ir8Ci/IsaEDIQWDBZePrRDwAA23D8MQoiAABRsFj5
V/esAACjADag2nD8TAAAQAJY8Fj4PmWvuPYKKSAoEHAw/wonICUQaDD/AgAAJBBgMP8CAAAATIUg
/wIAAgCDASD/AgACAJKFIGhEhWlFgipwBdMP/wIABgDY5pD/AgAGAONukHriB/8CAAgAz36Q/wIA
D/+vspAqfGj8CgMgQAJYcFj4F2WvSSocGPwKCCBwAlnwWPgT/wIAAADmJqDaIFj4BdEPAAAAKzEK
-+wtLAgAAUbBY+E73rAAPTwC2oMCi/IrkEDIQWDBZeL/RDwDacPscAAADEEAwbYoVLKBoJLAg/wIA
++wtLAgAAUbBY+E73rAAPTwC2oMCi/IrkEDIQWDBZeMPRDwDacPscAAADEEAwbYoVLKBoJLAg/wIA
DgDo4RD6rAEgAgJa8CpwBcKUeaElfaExeuImf6Ij2nD7HAAACBBgMG3KDy2wGCygSLGq+7wBLgCx
41DaIFj35dEP/wIAD/9UMpD8PCYiAABR8PsKAiIAAGlwW/9D0Q8qcAV8oRf/AgAGAHjukP8CAA3/
PtGQ/wIADf86+pDaIFj31NEPAAAqcAV8oQh9oTp64i9/oizacPscAAADEGgwbdoVLKBoLbAg/wIA
DgCrY1D6rAEgAgJa8NogWPfF0Q8AAAD/AgAP/xQykNpw+xwAAAMQcDBt6hUsoGgtsCD/AgAOAJjj
UPqsASACAlrw2nD7HAAACBB4MG36FSygSC2wGP8CAA4Ab2NQ+qwBIAICWvD6fAAAAxBYMPwKACIA
AGlwW/8S0Q8rfGj8CgMgQAJQcFj3s2Wtt9ogWPem0Q8AAAAAAPp8AAIAAFhwWPdVya6Jp4mewIEo
-lH7RD/p8AAADEFgw/AoAIgAAaXBb/v/RD8Ci/IqAEDIQWDBZeFrRDwAAAAD6fAAAAxBYMPwKACIA
+lH7RD/p8AAADEFgw/AoAIgAAaXBb/v/RD8Ci/IqAEDIQWDBZeF7RDwAAAAD6fAAAAxBYMPwKACIA
AGlwW/710Q8AAAD9wwZ//xBQMMCh/wIAAf9JpqAqEQH/AgAB/0RykPw8JiIAAFHw+woCIgAAaXBb
/ujRDwAAAAAAAPTDBn//EFAwwKFlrQ5j/ir9wwZ//xBQMMCh/wIAAf+QJqACKgJY93bRDwAAAAAA
AP3DBn//EFAwwKFlrN5j/qX9wwZ//xBYMMCxZL7N+nwAAgAAaXD7CgQgTAJg8Fv+ztEPAAAAAAAA
@@ -2216,9 +2216,9 @@ nUCMcPiIIxBEEFgw+ogBEAgQaDD6RgItgAQ7IPtGAywJAGswnEEpcEEDLAqOwC8SGfwWGiAEEGgw
8JkRDiABcDD+3QwOCQBP8P6JAR4JAEfwn0T/EhQsIAFsMC0WHYzA/kYHIAAQcDAuRQr9EhcsACBr
MP1GBiB4AmMwLEUL8A8WAEACaTAATWEtcSr+RC8gABBIMClEM/1ELSAAEFAw+kQxIAAQWDD7RDAg
ABB4MP9ENCAAEEAw+EQyIAAQeDD/RC4gABBAMPhENyAAEFgwK0Q1+xIcIAAQUDAqRDb9jRQN4AFg
-MP1ELCoAIF8wKxYcKnBXKxIVKkQ7CooUKkQ6CooUKkQ5+ooUAAQQYDD6RDggeAJRMFluBPkSFiCA
+MP1ELCoAIF8wKxYcKnBXKxIVKkQ7CooUKkQ6CooUKkQ5+ooUAAQQYDD6RDggeAJRMFluCPkSFiCA
AlEwAgmIAEqKAAmIAAqKL3IcLhIeL0RTD48UL0RSD48UL0RRD48U/0RQIHQIcXAoEh35iRcSAABY
-cPwKAyBCEFAw+nR0KCABQDD5CgkoCQBKMPl0ZSmABDog+BYAIIoCUTBZbeosEhspcTUDLQsqEhgq
+cPwKAyBCEFAw+nR0KCABQDD5CgkoCQBKMPl0ZSmABDog+BYAIIoCUTBZbe4sEhspcTUDLQsqEhgq
dFf+0gMgAgJKcCl1NSkSGhiIsChGFo+QL0YXi5CKfy5GGS3SAv1GGCwAIGLwLHYcKZIA+2YMAAIC
ELD8FhsoACBWcPl2DyAYADyg8goAIDACGPAdh44tRhotEh3AtQtbL7jcLEYb/HB0LAAgJ3D81HQt
0gC24C4SHgXuDLHu/wIAA/7hQ6ApEhMoEhIoljkrcBYvCv9/sQgqcEEsEhxYIkItEhKOHCwSG5zr
@@ -2240,7 +2240,7 @@ wMAswBJlzndj/oEtMF5l3qbz/qtgBBA4MAAmIRQjIRL0CgAvzAA1oPpSQiIAAFjw/AoAIAEQaDBY
GS8oUkP0TAEgAgIY8AgzLnZJ22P/oABkzupgADIAAGTO4mAAKgAAZM7aYAAiAAD/AgAH/we+kP8C
AAf/A96QY/95d6GB/wIAB/+/XpBj/2uKECwgByshCP6GlBBuAiGw9EQUDAIBZDD8DEEMoAQ/YPDM
EQwJAHdw/aYAKgkAZvD8IgAgMAJpsP2mAyAAEHAwnqUdh+Qehn3+pgItgAQ7IP4SAiwJAGEw/KYB
-KgkAbvCbpABOjZannaYCCo8sIAwAzBH2pgcqCQBm8PumBCIAAGGw+zxUIFACUrBZbK+OEPmGcx/A
+KgkAbvCbpABOjZannaYCCo8sIAwAzBH2pgcqCQBm8PumBCIAAGGw+zxUIFACUrBZbLOOEPmGcx/A
BD0g+4ZpHgAge7CeE/P+EmCJEFAwjSeFESzRFS3cIAvdAf3NCAXABD1g/dxAJAAgLPD4XAAKAMbp
UJgSY/1EAAAAAPP9TGIAADIw8/10YAAQQDCPImTxUv8CAAf/PgEgiCcpiRQmUr30kTdgQAJSMIWJ
JVAH+woAL8AQIDD8bAACAABpcFgZS4gniogpgRX7ggsgQAI6MAR9Af2ZCAIAAGHw+ZxAJgCR1tCL
@@ -2258,17 +2258,17 @@ BSYBAkaQsKoMqhH6yggLwAQ+IAuqDAAKiweHYPAKgA+cALogKpEFGYYPFYcO+ZJsK5AEOqDyUkQo
ACBSMPgWASngAUAw+BYCKAAgQnAJiBGoIo0nG4Wn/lpAL8AQQDD5LCAgQAJjcPfVFCwAQEMw/tUV
IIACYzD81gkgkAJQsPzWCCCiAnGw8AsHAJwCYLAASWEASWEASWEASWEASWEASWErYAScE/liACQA
xIbgK2IWJVJE/hYFLZAEOuD4YSIkACBlcC9QfI1Y+yYNIJwCWbCbEC3QBJku+CUiIBwQcDD/JEEm
-AJd3UPwKBiDkAllwWWu3ihP8CgYg2AJZcFlrtIUQixX8CgMgwgJQsFlrsNtQ/AoDILoCULBZa62I
+AJd3UPwKBiDkAllwWWu7ihP8CgYg2AJZcFlruIUQixX8CgMgwgJQsFlrtNtQ/AoDILoCULBZa7GI
aRWG0fgmCy/AEFAw9yYMIAYANiCSjJJpjBQuYAwtYA0rYQcoYAcvYBYpYQkpJQkvJBYrJQcoJAcu
JAz9JA0gBhBwMP4kBCBPEGgwLSQFKCIHLCUILFLPK4II/4EVIEACMjD5ggsgAgJjMPxWzyQAQFWw
9yYCLgAgL/D//EAmAHBeUCmJFAxHEft6CAgAID5w+YUUKgBq19DJNfm8AAATADUgbUkFAAOGAElh
KmIAB6oI/wIABgB+fpCaYI4gCO0R/BIBLAkAbTCdsY0SLCUJHIae+90IIAUQUDD7JTYgMhBYMFl0
-b9EPAAAnlQXz/flgABBAMADVsFinoYoTixVYp59j/uDApfyGkRAyEFgwWXRkwCDRDwAYhigvYSku
-YHyJYJktLyUi/iRBIOQCWbD4Jg4gBhBgMFlrXooT/AoGINgCWbBZa1uIa5gr9yYMIAYANiCSjJJr
+c9EPAAAnlQXz/flgABBAMADVsFinoYoTixVYp59j/uDApfyGkRAyEFgwWXRowCDRDwAYhigvYSku
+YHyJYJktLyUi/iRBIOQCWbD4Jg4gBhBgMFlrYooT/AoGINgCWbBZa1+Ia5gr9yYMIAYANiCSjJJr
8/6+b8AQUDCXi/P/V2IAAFpwAPv6DAA2ADTgCk4U/OwIIgAAQPD8TDYCAABK8NMPbckFAgiGAElj
CjgI/k0MAIACSXBt2QUECIYASWUKfgyuXi7sQJ5gY/8KAC9cQJ9gY/8BbBAS9DIEIgAAeTACJgLy
hZAUcAEgMARECQxEEQQiCCQif/4xCyC1ADUgGoYkGYVYKC0CKIAAKZJ3/hYUIgAAWTD6olwgARBg
-MPYWEygAIEow9RYSKZAEOiD/FhEqACBCsFlKmC8wMyswMS4wNy0wNikwMPqgByIAAGKwJTA09jA1
+MPYWEygAIEow9RYSKZAEOiD/FhEqACBCsFlKnC8wMyswMS4wNy0wNikwMPqgByIAAGKwJTA09jA1
KYAEPmD43REKIAFQMPoWFyWABD1g9iKDJAkANXD+MQosCQB3cPuZAgBwAljw97wAAEYANaCKZ/qi
DiCIAD5g+JJsYA4QcDD/AgACAFYGYGiUCf8CAAQBKgZg0Q9p8vpkb/crFhD8FgkgdAJo8C0WFmAB
IwAAAAD5kcRgABBQMP8CAAABe4fg+xYQI54CO+CPNg8fUv4WGCSvADfg+swAAgAAYXBY+S/RDwAA
@@ -2280,26 +2280,26 @@ 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
-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
+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
-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
+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
-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
+/4WAIBQCUrBZadcYhJaKGSiC2RuE/vwKBCAFEGgwC4AA2iBYE3vRD/4SFCIAAFMw/xIYIgAAYXBY
+KnRDwAAAPP9fGAAEFgwKhITLBIR/RISIgAAWPBY+/3RDymhIbGZKaUhY/tdAABlOs/3EhAgABAg
MPAAHGALEGgwAIM5zzwrcAH0tAgACxBoMPe3CgoARikQLHAAfcnmZGqeiWrznAAP3gA2YPkWBSAS
Annw/xYHIBgCcfD+FgYgBAIR8Nog/AoGINgCWPBY969lr62KF/wKAyCQAljwWPerZa+dihb8CgYg
gAJY8Fj3p2WvjYgVc4FfKYAFwqx6mYT6PAAAARBYMFj9M9owWPzw2jD7ClEgABBgMFj3QmP/ZItn
i74qsRyxqiq1HNEPAAAAAAAAAPP85mAAEFgw+iwAABwQWDD8CgEgDhBoMFgekvP8rmAwEFgw2mBY
-/ehj/yQAih5boXQchDULrRH0oDhsACBrMA3qMCvChYuwsKr6FgoqACBu8Fl0pRyEZo0aKsKE8NEE
-AAEQWDAAuxoLqgIqxoRZdNlj/dScHPoKByABEFgwWBjcjxwu8n8u9oNj/bwAbBAKKTEPLTAsG4ST
+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
@@ -2311,30 +2311,30 @@ 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
-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
+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
-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
+GPKsAAD/ALagHIPELzA/LjA+LTA9+BIIIAUQUDD4FgAgMhBYMFlxhMAg0Q8AAAAAAPosAAIAAFjw
/EwAAgAAaXBb/T/AINEPAPsxCiIAAFHwWPBd+woBIAAQYDD6vDgAABBIMAy5OPWcu2YFAFawY/yK
AAAAAAAAAPosAAIAAFjw/EwAAgAAaXBZEyrAINEPANog/lwAAEACWPBb9jPAINEPAByDnv0xCiAF
-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
+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
-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
+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
-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
+gAQ9YP4SByQJAE1w/IMPFYAEPWD4/xEECQA1cPUWAS4JAEfwWXDLKTA0KjA1CJkRCpkC/wIAAAEG
hmD/AgAD/OyaYBiDAiwwPSswPI8X/kEbIgAAUTD9MD4rgAQ+4P8PSwoJAGbw/DA/LgBAQ7D/7gIL
gAQ+4P27AgBsAmjw/g5PC4AEPuD8CgAqCQBm8FjsMsAg0Q8AKDBX/ILtGdAEOiD4jAggBRBQMPgW
-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
+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
-Av8CAA//PeOQaKMEwNMtdpDApfyCvBAwEFgwWXB0wCDRDy6gBcT2/wIAD/xL+5CJpyiZFGSBHouZ
+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
@@ -2368,7 +2368,7 @@ NgUMR/8CAAIAlhsgiieLqP2hFS/AEBAw/6ILIEACcrAC4gH4qRQsACAXcP3cQCYAu1/QjxAM/xGv
iPilFCoAIHrw/wIACgC1V1CIEMk4+bwAABYANiBtiQUAA4YASWEq4gAPAgAPqgj/AgAGAMZukJrg
0Q8lIQf58QgtgAQ/YPklCCAGAkLw+EgUAegCWvD7RgMoCQBDcJhJ99sCD+EQQDD7RgEtAAQ+oPhE
GCtAASgw+H9kG8AEOqD+8h8qAgF0MP5GCyqgBD7g+39mGgkAWrAegOcl8h71RgosCQBucPxFDyAA
-EEgwmUWYQh+A4PuqAgCoAljw+kYALAkAd3D9RgQuCQB/MP9GCCCAAlEwWWWQiicr+sD3ZjkgQAJK
+EEgwmUWYQh+A4PuqAgCoAljw+kYALAkAd3D9RgQuCQB/MP9GCCCAAlEwWWWUiicr+sD3ZjkgQAJK
sPsKACgAQF5w+6UUIIACSnCZqZmo0Q/RDwAA+6wYIgAAafD8CgEiAABQsFgakGP+so0n/vrAIEAC
Y3D+CgAsAEBzMP7VFCCAAmMwnNmc2NEPwoJ4+dopcX99l9T7PAACAABhMPo6/yIAAGlw+iUIIgAA
ULBY+0jRD8W1+yQFIgAAULBYDxnRD8DAnKvRDwAAAAAA+90MADYANOAoEgANSRQqnAj6PAAIAwBS
@@ -2382,22 +2382,22 @@ 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
-JgA3YPP+JGIAAFkwAAApIhMpFhEoIFAoFhBj/sUAKrAY9bwAAgBm/pArXB38CgMgCAJQcFlkxmP+
-EgAA2hD8CgMgogJYsFlkwbQa/AoDIJwCWLBZZL4rIFUrFQVj/e0fgAsdf1kpIRf4CgAgIAJQcJig
+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
-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
+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
-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
+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
-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
+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
@@ -2411,35 +2411,35 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -2447,7 +2447,7 @@ VAYgARBYMFuWf8Ag0Q8AAAD6LAACAABY8PxMAAIAAGlwWQ8/wCDRDwDz/8JgABBYMGwQShl7qywg
ByUWhocw9Uz/KOABKDD8DEECAAAxcPl3AQIAkQIgiSIYewj1kbdgBgJpcBl7HfzKEQYFADtw/XsD
GgAgQrAqFof6ojogBgJZsCsWhQ3NCv3SlyoA5t6QKxKHK7I5DbsB+xaEIZwANuAugkpk4Xkpkn8v
gkn5+wEOALhP0CogFAqkh/okFCwAyRKg+DwQICoAPSD6TP8iAABIcG2pBQAIhgBJYSIWgPodAiIA
-AFhwWV/z2KD6Fogg/gA2oMCj+xwAAgAAYjBZaEXJfPsShCIAAFCw/WwAABACYPBYEOTwAAdiAABa
+AFhwWV/32KD6Fogg/gA2oMCj+xwAAgAAYjBZaEnJfPsShCIAAFCw/WwAABACYPBYEOTwAAdiAABa
sAAAAPhBF2IAAEBw+kz/IgAASvDTD22pBQAIhgBJYY0z/FwRAgAAULD8MgIqACBm8FgQmiwSh4on
+xKFIgAAaTD7xjkgQAJSsPtMAAAAEGAwWA3S0qDRD4oni6j9oRUvwBB4MPmiCyBAAnKw/haDLgBA
e7D+FoEsACB3cP3cQCYAYl5QKakUDEgRqJn5pRQqACBaMPgWgioAXldQyTzJStmwbUkFAAOGAElh
@@ -2470,7 +2470,7 @@ aDD+CgEiAABasP8KAiIAAFCwWLNHJTZJLyAG/iICIBEQQDAoJAX//AEgARBAMP8kBi4JAEOwniLz
/dJgERBQMAAA8/6LYgAAaTD6LAAAHBBYMPwKASALEGgwWBUeY/4DAABsEASJPxp7bYU+lZD7Mg4g
cAIw8PR6ixAAEEAw8lcMAAAQEDD5tgEhkAIpcPg2DyIFADlw+DYOKgARnRAvon0ee2CW8Z4/LaJ9
nT4son/2pn0gAgJjMCymf9EPK6KAKa0ClrGZPyiigJg+JKKC9qaAIAICITAkpoLRDwAAbBAEiiLH
-jfopUwAYAHqwCKgBmCLRDwDInlln4dug/CICIgAAULBZZSrRDwBsEASJJ/iSDCAjECgw9gokICUQ
+jfopUwAYAHqwCKgBmCLRDwDInlln5dug/CICIgAAULBZZS7RDwBsEASJJ/iSDCAjECgw9gokICUQ
ODDynDAgABBYMPKJDAGQAkIw+Ys5ACkQGDD0CisgPwA24GAAEIq+wLD6LAwBkAJSsAyrOcq1LLAA
c8noLbAQ+rAfIcQII3B1oQV2oQJ3qdTaIFv/vPP/22IAAFqw0Q8AAGwQBPQiBy/AEEAwJUwg+FUB
AAAQGDDzRRQggAIpcJVJlUjRD2wQBCggcNMPfIcUKiAH+yIAKgIBUDBZDjLIp9Kg0Q8AwCDRDysg
@@ -2495,18 +2495,18 @@ AC4JAGuw/qYEIDAQSDD5pgMgAhBAMPumAiIAAEkw/aYGIAAQaDD9pgUtgAQ7IP2mBywJAHsw/KYB
IEACWrBtigUGCYYAS2eGQiYmHIlB96xAIgDwBlAuCgD+Fg8gAPouYP4SDyADEFgw+iIHIAAQYDD8
PxEAAxBoMPX/CAAIAnOw/vY5IEACUrBYC1/SoNEPABl57i8WExh5/P0hFyAAEHAwnhGeE54UnhWe
Fp4XKIKMnhj+FgkiAABQcPi4DAABEHgw/QxGCAkASjD4FhEuSAFoMP19QA+QBDug8N0RDAkAczD/
-FgAsCQBrMPwWAiBgAlhwWAZTZKDJwKX8edUQMhBYMFlnfcCl/HnTEDIQWDBZZ3qLImW8PvtsGCIA
+FgAsCQBrMPwWAiBgAlhwWAZTZKDJwKX8edUQMhBYMFlngcCl/HnTEDIQWDBZZ36LImW8PvtsGCIA
AFCw/AoBIAQQaDBYE4fAINEPneBj/Bwr4n0q4pcMzBSsuwm7EfuqCAIAAGkw+iYZIgAAYPDypggi
AABYsFv3YMAg0Q8uIhOeHS0gUJ0cY/yUhTIlJhyJMZoe+6wAAgB5BlD2kQtgABAYMIon20D8CgAi
AABpMPN2OSBAAlKwWAsb0qDRD8GwC8sC+zYEIAAQSDDz/cJgiBBYMAAA8/3RYAAQIDAAABx5ov0S
-DCAFEFAw/hINIDIQWDBZZ0gqEhUsEhQvEhMtEhHz/CBgABBYMAAAAAD7bBgiAABQsP0SECABEGAw
+DCAFEFAw/hINIDIQWDBZZ0wqEhUsEhQvEhMtEhHz/CBgABBYMAAAAAD7bBgiAABQsP0SECABEGAw
WBNQwCDRDwD6LAAAHBBYMPwKASABEGgwWBNKwCDRDwDaIFuQy4oejDTz/S9gBBB4MNog+3wAAgAA
YbBbkjOJQfoWDy3ABDqg954UZgAgZfD7fAACAABQsPwKACIAAGmwW5IDjR+trZ0fY/3z2iD7Eg4i
AABhcFuSJIseiTHzrAANwAQ6oPee/WoAIGbw2iD8CgAiAABpcFuR9vP+6GIAIB6wAABsEAYZeXwq
IAX4IAciAABw8PYKACIAAFlw/CIHIAMQKDD0oMdoIAFAMAsKR/3MMCIAfAKgGXe8/3lhF8AEPiCp
dylyOg+PCv/9BCQBAC0w//ILKgCuLlAtcjn/2QEOAKj/UCggBxx3xAgrQAq7EAy7ApuQJiIA+3e4
F4AEOaD7lgImCQAxcPaWAS4AryFQLDAD/JYDICACSnD/AgACAMAaoP48ECAqAD0g+kz/IgAAQ7Bt
-qQUACIYASWHAMPx5TxAFEFAw/SIAICgQWDBZZuEldjkuIAT/IAUgCQC3oMzxZDCH0jDRDwAAAAAA
+qQUACIYASWHAMPx5TxAFEFAw/SIAICgQWDBZZuUldjkuIAT/IAUgCQC3oMzxZDCH0jDRDwAAAAAA
APqS1y85ALcgZKHUKpLVjaGMoJzQj6Cd8ZahlqAsktewzCyW1y+t/40g/fY+IfACYrCcJyYkICYk
IWP/AIfMwJD9fwwBkAI58A95OfcKKy75ADZgYAARj57AkP/WDAGQAnvwBvk5ZJ7fJpAAd2nnZJ7W
bUkFAAOGAElhwCDRD4knGnhA+woAL/8QYDD8lgAgEAJCcPsmByoAkM6QHnkbKuLVEng4mKGSky/i
@@ -2516,7 +2516,7 @@ NqD6LAACAABY8P0SACIAAGEwWA2w0qDRDxt3+C8hCP0KICwgAUAw/ZYDLQAEOyD8CgAuCQBn8JyV
bUkFAAiGAElhFngIKKzI/wIACgBYRZAceOcowtsfeOOagZ+hLcLbnaApwt36xtsgAgJKcCnG3Ymw
wDD7mgwBkAJKcPP+NGIFAFZw+iwAAAAQYDD7jBgiAABpcFgSgGP/LgAAHXjUItLYH3idmCGfky7S
2J6SLNLa+NbYIAICYzD81toiAAAQ8NEPACqS2I2hjKCc0I+gnfGWoJahLJLasMwsltpj/iebEFll
-V9ug/CICIgAAULBYEPuLEIgRiiJj/sMAH3i8LPLeGXi9msGZoSjy3pigLfLg+vbeIAICa3At9uBj
+W9ug/CICIgAAULBYEPuLEIgRiiJj/sMAH3i8LPLeGXi9msGZoSjy3pigLfLg+vbeIAICa3At9uBj
/1AAAAAAAGwQBIooiacomRT7kgkgMgA2IPmiAiAAEGgwLSQE/SQFL/4QYDDyphkoAEBmcJmi/LAH
IAMQaDBb/aXSoNEPAADz/85gABBYMGwQBi4gBNMP9woYJgEmB6D1DEcGATU/kPwWASIAcgMgKzAQ
+AoBICsQaDD2Ci0mAdDu0PcKMiYB9LbQ/wIABgCgvtDChv8CAAYA38bQihEpIAfAwPkIQQIAhYKg
@@ -2530,12 +2530,12 @@ e4Yr8NEEAf4CYnAAzBoAihr6rP8mACBhsApmApYqKCAgLiAFwJQJiAL4JCAj/zcboAgKQ/8CAAv/
MZqgiifAsPskICAgAlKwWAtswMAsJBQsJAVj/kSNEf8CAAP/H5tgjifI6NogW/v92iBb/PYpIAX4
CgggywA2YC8gIAj4AvgkICP/DBpgCAZD/wIAC/8GmaCKJ8Cw+yQgICACUrBYC1Zj/6YAAPosAAIA
AFjw/EwAAgAAaXBb/1PcoPoiCCBnALcgjaJk0F3AINEPjzL8eAYQBRBQMP0iAC74AXww/xYCIDAQ
-WDBZZZGIEsJm/wIABgBSthDCe/8CAAYAWb4Qwp3/AgAGAGDOEMOieom5+iwAAgAAWPD8TAACAABp
+WDBZZZWIEsJm/wIABgBSthDCe/8CAAYAWb4Qwp3/AgAGAGDOEMOieom5+iwAAgAAWPD8TAACAABp
cFkLYcAg0Q8AK6AH+wtBAAEQYDD7vBgiAABpMFgRkMAg0Q8cd+MswtdkwlQed+Ep4tWGkYuQm2CK
kPamASAAEHgwn5CfkS3i17DdLebXJp3/jyD/Zj4h8AJycJ4n+CQgIAAQaDD9JCEgBxBgMCwkBWP9
CgAAAAAAAPosAAIAAFjw/EwAAgAAaXBZC77AINEPAPosAAIAAFjw/EwAAgAAaXBZC3nAINEPAPos
AAIAAFjw/EwAAgAAaXBZC2HAINEPAAAAANog+4wYIAAQYDBYEWP6LAACAABY8PxMAAIAAGlwWAxf
-iCJljsGJEGSevPosAAAAEFgwW5FdwCDRDwAAAAD8d7MQBRBQMP0iACAoEFgw/zAfIgAAcPBZZT0o
+iCJljsGJEGSevPosAAAAEFgwW5FdwCDRDwAAAAD8d7MQBRBQMP0iACAoEFgw/zAfIgAAcPBZZUEo
MB/Co/8CAAYAwlYQwrT/AgAGAL1eECwKJf8CAAYAt+YQ+iwAAAIQWDBYAKRj/DEAAAAAAPosAAAC
EFgwWABxY/weAAAfdokWd5UuIQj8CiApAAQ+IPymAyAAEGAw/KYFLgkAS7D2pgYuCQB7sJ6k8/xp
YEACSrAAAI4niuyPoYigmPCGoP9mASAAEHgw/6YAIGACc7D/pgEhsAJCsG1JBQIIhgBJYymsyP8C
@@ -2591,33 +2591,33 @@ ABIwLmY50Q8AiBAojECYsWP+XQAAbBAEaEMGaEJCwCDRDyggBrCICAhH+CQGL/AAtiCJIiwwAceu
+wr9KABAVnD5JgIiWAE/IHvJ0fosAAAAEFgwW45owCDRDwAAAAAAAPs8ECIAAFCwWQlLwCDRDwD6
LAACAABY8FkJW8Ag0Q8AbBAEGHMBGXS2+goBIgAAcPDwMQQCAABosPMzCQMgEBAw8tIoAgAAeTDw
qhoP/xAgMPkpCAQRACKw/JKuI8AEPOD4kq8iACBAsPuSsCIAIBTw8z0ILABAYTD8lq4oAEBBMPiW
-ryQAQFkw9JawIwAEO+AiNsvyNsogDQA34CiSrgioAiiWrsCk/HSXECAQWDBZYiLAINEPAABsEAiX
+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
-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
+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
-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
+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
-FIsVWWPa/QoIIAAQYDBZYkH8CgAj6BBoMFliTdog/kKvIgAAYvD9CgAiAABY8FkUAcAg0Q8AACtC
+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
-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
+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
-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
+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
-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
+Kv5zphAAECAw9goAIgAASPD5FgAgABA4MP7hfiABEGAw8AA2YAAQGDAAAPoKACIAAGGwWWNFjxEu
EgL7MwIAARBgMPb2CAYJAFXw9VwBIAICITD4SSxgCAIQsABABA4IG3+H5osgaLApKlAwnhIAoQQA
-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
+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
-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
+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
@@ -2628,19 +2628,19 @@ sGQwSCS2OdEPAt0MDUoU0w9tqQUCAoYARmMKTwz4XEAuACBqMPrsECAiAD/gsP7TD23pBQQIhgBK
ZS/JBA2SDKJSIiww8sYBL7sAt+DAIPLFBCCAAkFwmMCYwSS2OdEPCiIMkmlj/10iXECSwWP/kAAA
AABsEAgrEhCSFfdythIAAEnw9hIFIgAAEbCbF5kU93GcFgAgObBgAAUAZFBvzSwqYoAKPAH8SfFx
/gIpcI0UZNBN+tYAIAAQEDDRDwCPF2TwQgjqMBlw4SmSMcClCio3CpkoqYiYFgwCAIoXKXKC+HDa
-GABAVnAIqY4IqAqIhAuAAAzqMIsWDLsMa7HZY/+ewCDRDwDaIFlY92P/kd4w/RIFIgAAeTD6FgAg
-CBBYMPxyjRABEFAwWWAMxyvRD2wQBAXqMBZwxShiMcCVCSk3CYgoFHFv8AAVZAAgRXAGqAqIhAuA
+GABAVnAIqY4IqAqIhAuAAAzqMIsWDLsMa7HZY/+ewCDRDwDaIFlY+2P/kd4w/RIFIgAAeTD6FgAg
+CBBYMPxyjRABEFAwWWAQxyvRD2wQBAXqMBZwxShiMcCVCSk3CYgoFHFv8AAVZAAgRXAGqAqIhAuA
AAnqMAlZDGqREwwCACpCggo6AQiqjmUv32mm3NEP0Q8AAAAAAABsEAQTcX32cU4QEAIosPpxexoA
EBTQK2J9lbGaIylifZkiKGJ/9WZ9IAICQjAoZn/RDy9igC5tApXxniMtYoCdIixigvVmgCACAmMw
LGaC0Q8AAABsEAQTcWj2ckYQcAIosPpyRRoAERTQK2J9lbGaLylifZkuKGJ/9WZ9IAICQjAoZn/R
DwAAL2KALm0ClfGeLy1igJ0uLGKC9WaAIAICYzAsZoLRDwBsEAgack0YcIgpooYron0qoowogMEJ
uxH6oCQoACBecPoWBSAeAH4wKp0BKqyAmhRgAAcrnQMrvICbFIwV/wIAAACmpyD0zAAAABAYMPZy
-OxAAEBAw8AC6YAAQODAsUAcnVRvzVDkg/BBoMP3MAQ//EFgw+1QWLAkAYLD8VAciAABRcFkslYpX
+OxAAEBAw8AC6YAAQODAsUAcnVRvzVDkg/BBoMP3MAQ//EFgw+1QWLAkAYLD8VAciAABRcFksmYpX
iq4srQT7rQQv/xBIMPmm+iBAEGgwLaa2Kab7La0DKdULKdUKJ6a+KdUr+dUqIegCWvArpv4rpv35
-ppIhQAJjMCym6Cym6SemzhxyG41QL1ANLlAMkhKdEZMQ+GCAIDAQWDD4FgMgBRBQMFlfkStggAAw
+ppIhQAJjMCym6Cym6SemzhxyG41QL1ANLlAMkhKdEZMQ+GCAIDAQWDD4FgMgBRBQMFlflStggAAw
BAsLG3+/dowV8iwBIAICGPDzwX9wAgIhMI8UHnIIKfANKOJzL/AMLuKG+DUICAAgQTD5iBEFkAQ9
YP5VCA4AIEOwLlYQ/1QMJdwQUDAqVRopVA0pYIAAIAQJDRv/AgAD/4H/UG0ID7EiACAECQ8b/wIA
-A/94f9Bj/+kAAAAA+goFIDAQWDD8cfESAABo8Flfa2P/ctEPbBAEiCcbcDX3+sAgBBBQMPWJFCIA
+A/94f9Bj/+kAAAAA+goFIDAQWDD8cfESAABo8Flfb2P/ctEPbBAEiCcbcDX3+sAgBBBQMPWJFCIA
ADCw8oIJIEACIjD5gRUkAEA5MPRMQCCAAilw9YUUIYACELDyhgkqAAQgkKKSkokAC4v9cD8SAAAo
sNMPbaoCAEVhnSCMYPjMEQAEEGgw8yYCLAkAazCcIdEPAGwQBBlxEyggBB9xz/0iDiAAECAw/iIL
JgB4AiD88ukgVhAoMPoiDCAAEBgw++wABgDYz1AJ2BH0oHNsACBDMJ6riytksAIqtgyKJ5Mr8yYM
@@ -2649,11 +2649,11 @@ ADUgG3DwJSAHK7F+9OK7IgAAULD7KxQEIAEsMFiOMWShrNEPAI3Jctlp/sYJIgAAW7AuwAX4CkIg
BgA24JO8/wIAD/++w5CJyWWfc4rLZa9u+8IAID8QQDAoxAUu8tL68uwgARBoMP67DAAAEGAwWAJd
GnGVia6wmZmuY/9BACvyEoog/wIAC/+F2pDz/wNgARAgMI3L+MIKIBoIE3Cey4srY/+MAAD/AgAO
AESSEJ7K8/99YgAAW7Ap4kIq4r0rIQn5nP8gABBgMPnmQiABEGgwWAJFiycqvCD+IgIqAEAysPO1
-FCCAAlKwmrn6tgggKQA3oPxxdRAFEFAw/SIAIDIQWDBZXuqKIlld5sfP+6wAAgAAULBYCYojJAUt
-IQn+IgAgBRBQMPxxahAyEFgwWV7f0Q8tIAX/AgAP/3urUC0hNv4hNyAFEFAw/HFiEDIQWDBZXtfR
+FCCAAlKwmrn6tgggKQA3oPxxdRAFEFAw/SIAIDIQWDBZXu6KIlld6sfP+6wAAgAAULBYCYojJAUt
+IQn+IgAgBRBQMPxxahAyEFgwWV7j0Q8tIAX/AgAP/3urUC0hNv4hNyAFEFAw/HFiEDIQWDBZXtvR
DwCILQmIEfWuVWwAIEMwicv/AgAOAHASUJ7LiyvIsJO8KsAFw7D/AgAP/yBakI3LZd42jsxl7jGI
zWWOLPvCACArEEAwKMQFLvLT+vLtIAEQaDD+uwwAABBgMFgCDWP+CC0hNv4hNyAFEFAw/HFFEDIQ
-WDBZXrnRD40nGXFCmUAs0RX4IgAgARA4MPvSCCBAAnNw+dILLgBAN7D/zAgJgAQ6IPzMQCgJADow
+WDBZXr3RD40nGXFCmUAs0RX4IgAgARA4MPvSCCBAAnNw+dILLgBAN7D/zAgJgAQ6IPzMQCgJADow
+EYBINQEWnAq2RQqrBD61RQgIAJS8HrDXMhJAASGAEthitgqrBD/AgAGAEbmkJrgiyJlvev7XBgi
AABQsPwKASBAEGgwWAqt0Q+NzXLZCZ7N8/8dYgAAW7CIzP8CAA//iZIQnszz/wliAABbsACT22P/
vAAAAPvMDAAyADUgDE0UuNr6ejYCAABJMG2pBQIJhgBLY6xJ+vxAICQAP2ANewzTD225BQQJhgBK
@@ -2688,7 +2688,7 @@ UrD65gEqABZakCzhBarKmuEebfGeoI0g+N0RAAEQcDD1pgIsCQB3cP2mASAAEBAw0Q8ebeieoI0g
o0QkVd4jICKJK/xyeyABEFAw9DAcYf4CWPAAwQQAuxoAqhr6rP8oACBecAqZApkq0Q+NKZ0q0Q8A
AABsEAQoIAb4jP8iAABQsPgkBiABEFgwW4j0wCDRDwAAAAAAAABsEAQUbyUBIhGiMqQigiDRDwAA
AGwQBhhvUgEpEakz8AAJYgAgQPAAymzNeioigApLAftZ8nH+AjGwiRzyCgAgFAA2YGAACADacFlV
-qmP/25qQ0Q/AINEP3TD+TAACAAB5cPoWACAIEFgw/G8+EAEQUDBZXL3HK9EPAAAAbBAEGG84AScR
+rmP/25qQ0Q/AINEP3TD+TAACAAB5cPoWACAIEFgw/G8+EAEQUDBZXMHHK9EPAAAAbBAEGG84AScR
pzeodyZygMePCEgDCGYBBlYCJnaADAIA0Q8AbBAEKSEEhyDzWBQJwAQ+YPl3CAngBDogCHcMJ3z8
9nIAKIABHDDwkQQAARBAMACIGvCQBAoAQDYw+wMZD/8QUDDwkQQIEQBSMPBIGgYAQEGwCGYC9nYA
IBkANWAlIQLNQiohA7FbCwtP+yUCICgEWrDSMNEPsFz8JQIiAAAQ8NEPwND9JQUiAAAQ8NEPAAAA
@@ -2742,14 +2742,14 @@ ipEmYn+MkJygi5CIMvq2ASAAEFgwm5H7lgAh/gJCMJgyhSf1XP8nkAQ94PUmByIAID2w+0UDIAgA
NWDSMNEPJCAaDwIADwIAJkzo+yQbJuABMDD/ZhNv/xBIMBhseAhoCimGqymGsyQgGvI8AAIAAFLw
CuQWAQIAHWtJLNKCAEEEAL4a8EEEAAEQeDAA/xoJ/wMPzAEOzAIs1oIK5BbRDwAAbBAEFmwhASUR
pTWmVZRQDAIA0Q9sEAgYbE6SFPYSBCIAABGw8AAIZgAgQbDKXM0pKmKACjkB+Unycf4CKXDyCgAg
-FgA14GAACgAA2iBZUqVj/9wAmnDRD8Ag0Q/eMP0SBCIAAHkw+hYAIAgQWDD8bDkQARBQMFlZuMcr
-0Q8AAABsEAQaax4WbFDz+v4gABA4MCRirgACACmi0AOZASmm0BhrMyeGXFlVRFlb7xVsSB1qwAgs
+FgA14GAACgAA2iBZUqlj/9wAmnDRD8Ag0Q/eMP0SBCIAAHkw+hYAIAgQWDD8bDkQARBQMFlZvMcr
+0Q8AAABsEAQaax4WbFDz+v4gABA4MCRirgACACmi0AOZASmm0BhrMyeGXFlVSFlb8xVsSB1qwAgs
EAxMAg3MAixmrhtsPSe2hCpSIhRqa/ZsJBAAEBAw92rLEEYANqATbD0rcnsqUtyrKwm7EauqLjKA
-LWCAACAE/Q0bDgBAI7D+NoAgHAB/cCyiH8jDwLFZHnktUiKxIvM9QCv/4+yQxz4fbC4u8oID7gEu
+LWCAACAE/Q0bDgBAI7D+NoAgHAB/cCyiH8jDwLFZHn0tUiKxIvM9QCv/4+yQxz4fbC4u8oID7gEu
9oJYhfzRDwAAAGwQBMBABOQWAQIAFmrwJWKCACEEADca8CEEAAEQQDDwiBoP/xBIMAmIAwhVAQdV
AiVmggTkFtEPbBAEKyAHFmo7HGpC+wpBCgIBXDD4atQaoAQ+4PkhCCoJAGbwmzCHIPQ2CCsABDqg
9TYJKAkAVnD2NgIoCQBGcPg2BiAgEBAw8jYDIAMQQDD5NgQgABBIMPk2CieABD3g+TYLJgkARfD3
-NgEgYAIQ8NEPAABsEAQsIAf7IgAiAABQ8P0KASAEEHAw/CxAADAQeDBZV1cdaiMYaokea/XwDQcC
+NgEgYAIQ8NEPAABsEAQsIAf7IgAiAABQ8P0KASAEEHAw/CxAADAQeDBZV1sdaiMYaokea/XwDQcC
AABKsABJYQBJYQBJYSkgBy8hCAkJQfCZEQAAEFgw8qwwLgkAT/D+pgIuCQBH8P+mACAgAkqwAgSG
AEljAASGAElhK6QW0Q8AAABsEAQoIAcaaggIKEAKiRAKmQKZMIcg9mn4F4AEPeAHVwKXMfAGFwAQ
AjjwAAeK+yEIKcAEPWD6a1odAAQ6IP1p8hBgAhDw/TYEKgkAZvD8nOgqCQBW8Ps2BiGgAkpw/DYF
@@ -2809,11 +2809,11 @@ mRTIqSsgBvqSCSAAuAbg+iwAAAQQWDBb/91loM+MMyshCQwMQ/S7EQ2wBDsg/AoQKgkAZvAMuwKb
YGAAEAAAAC48EPAOFgIAAGmwAE1hLyAFbvhsKCByfo9m2iBb/19loJQpIAX7IgIosAE6YCogcn6v
TfWwgGvABDngG2bZ/WbZGgAgWrAsojoNfQr90pckAKfDICyiOZoR/csBDgChbxD8bAAAAhBoMP4K
ACIAABqw/woCIgAAULBb/x7A5C42OY8QaPJIiif7TAAAABBgMPqsICIAAGkwW/nR0qDRD/osAAAC
-EFgwW/+pZK9SwCDRDwAAAAAAAPosAAIAAFjw/EwAAgAAaXBb/tnSoNEPAMAg0Q/aMFlU+fusAAP/
-ZcKg/wIAAgBIAqD/AgAF/12WoP8CAAP/Wcag2iBZVNnAINEPAIsxC8tTaLF8jDL8jFcANxBoMP8C
+EFgwW/+pZK9SwCDRDwAAAAAAAPosAAIAAFjw/EwAAgAAaXBb/tnSoNEPAMAg0Q/aMFlU/fusAAP/
+ZcKg/wIAAgBIAqD/AgAF/12WoP8CAAP/Wcag2iBZVN3AINEPAIsxC8tTaLF8jDL8jFcANxBoMP8C
AA//S+sQ+iwAAAgQWDBb/4plr4IuPBDyDhYCAABpsABNY2P+0mSukI+g/49XACoQQDD/AgAP/0HD
-0BlnR4ii/wIAD/87ShCMIv68/y/+EGgw/iQGLABAazCcImP+Wooz/wIAAf8W7pDaIFlUx8Ag0Q/6
-LAACAABY8PxMAAIAAGlwWVR90qDRDwD6LAAAMAJZ8PwKASAEEGgwWAHaY/8BAABsEAgbaGqbEPgi
+0BlnR4ii/wIAD/87ShCMIv68/y/+EGgw/iQGLABAazCcImP+Wooz/wIAAf8W7pDaIFlUy8Ag0Q/6
+LAACAABY8PxMAAIAAGlwWVSB0qDRDwD6LAAAMAJZ8PwKASAEEGgwWAHaY/8BAABsEAgbaGqbEPgi
ACAAEEgwmRL5FgMiAABQsPMWBCACEGgw9BYFIAIQYDD1FgYpgAQ6IPYWBygJAGIw+BYBIgAAWHBb
/2LRDwBsEATAINEPAGwQBpMQ/QoBIIACWfD6IDsiAABhcPYiByIAAEmw/BYCL8AQQDD5FgEqYAFQ
MPVsICvABDqg+joIBABARXDwACdgUAJSsCggO7GIKCQ7LGEV/dwBLgAgLzD+rBAggAJ78PrsAAoA
@@ -2823,7 +2823,7 @@ UDD5Zs4YAEBKMPMDSgqgBDqg9AVDCAkAUjD5ZjIYCQBKMPh2ACSABD1g+iIALgkAL/D/dgQqCQBm
8PR2BiLABDjg+3YCLgkAE7D+dgMgCAITcPsSAiuABDqg+3YFKgkAULCacQAJjfloCRBgAinwAAWK
CdkCmX7RDwzqDGP/EQAAbBAE/WYXEBEQQDD7PBEKAASaEMGVc5toiyeJIo+zKLEDirKa8PqyAigO
AUAw+IgJDAAgbzANiAr4jRQv/xBwMP+mASAAEGgw/bYDKhEAcTD9tgIoAEBWcJkiL4KyGWfssP//
-hrIsACBLMCrCULCq+sZQIAEQeDD9tQMgFQA2oNEP2zD8IgIiAABQsFlRgtEPKs0BKaA+K5zoCwtH
+hrIsACBLMCrCULCq+sZQIAEQeDD9tQMgFQA2oNEP2zD8IgIiAABQsFlRhtEPKs0BKaA+K5zoCwtH
/7YTYgAAE7AcZ8QMvAouxqsuxrMpoD7e0A7kFgECABpmliiiggCRBADbGgCRBAD8GgLMAwyIAQuI
Aiimgg7kFtEPAABsEAQsIAcdZdYMC0EMuhH/ZdUaACBqsCiiOg+/Cv/ylyQAUsIgLqI5DClACpkQ
/+0BDgBKf5AoIQcfZkj+Zd4ZQAFAMPQxECnABDog+YgCCQAEPuD7ZdAYCQByMJjQ+SIAJAkASTD/
@@ -2879,7 +2879,7 @@ FvP/3GABECAwD04LhOOP4qSk9OYDKgADURCx/5/iY/yvY/3giTjKmYs5wKCaO5mwjDibwZo4+jYJ
L5kQQDD4NAUgABAQMNEPAMCQ8/yCYgAAanAt+pn9NAUgABAQMNEPAMCBKDYWY/7vixz6LAAAARBg
MPu8GCAeEGgwW/5SwCDRDxti+YoUCZkJ+6oICcAEPmCqmSmdCSmceCqR3iiR3SmR4QqIAfoKASv9
W8oQixz6LAAAARBgMPu8EiAAEGgwW/5BwCDRDwAAABxk1o0gLiIYiDCPoP7gdCAwEFgw+BYAIAUQ
-UDBZUiSJOGSd1oI5mSCIOPKGASAAEHgwnzifOf82CyAAEBAw0Q/AINEPAAAAbBAEyDHRDwCIJ/aJ
+UDBZUiiJOGSd1oI5mSCIOPKGASAAEHgwnzifOf82CyAAEBAw0Q/AINEPAAAAbBAEyDHRDwCIJ/aJ
FC/AEDgw84IJIEACKjAHVQH1XEAgIAIxsPaFFCHgAhjw84YJKgAUqNAqgRX7YvMaACAasJqJm6CJ
IPiZEQABEFgw9KYCKAkAXnCZodEPHGLqnDCLIPi7EQABEGAw9DYCKgkAZvCbMdEPAAAAbBAEZCB2
ZDBzZFBwKCICGmKs9AlHAD4CaPD9TRQAXwC2IAyYEfxipxgAIFIwKoI6DJwK/MKXKgAlbpArgjke
@@ -2925,8 +2925,8 @@ BfvHIAX7uiAF+6cgBfuaIAX7hyAF+QsgBft0IAX7ZyAF+1QgBftHIAX7MyAF+vIgBfqyIAX68iAF
+rIgBfkLIAX5CyAF+QsgBfkLIAX5CyAF+QsgBfqlIAX5KCAF+QsgBfkLIAX5CyAF+oggBfpvIAX6
ZSAF+lQgBfkLIAX6QSAF+icgBfoUIAX5+iAF+ecgBfnPIAX5vCAF+akgBflFAAAAAAAAAAAgBf8s
IAX/NiAGALIgBgCMIAYAhSAGAH4gBgB3IAYAcCAGAGkgBgBiIAYAWyAGAFEgBgBHIAYAMSAGAAYg
-Bf/aIAX/0SAF/7YgBf+sIAX/nSAF/40gBf+GIAX/cyAF/2wgBf8eIAX/QwAAAAAAAAAAIAag2CAG
-njAgBpzEIAaacCAGmBggBpTgIAaV2CAGloggBpRUIAaY3AMPCBKDjpOSUlYAABAAAABjb25maWd1
+Bf/aIAX/0SAF/7YgBf+sIAX/nSAF/40gBf+GIAX/cyAF/2wgBf8eIAX/QwAAAAAAAAAAIAag6CAG
+nkAgBpzUIAaagCAGmCggBpTwIAaV6CAGlpggBpRkIAaY7AMPCBKDjpOSUlYAABAAAABjb25maWd1
cmF0aW9uIGZpbGUgcGFyc2VyIGZvdW5kIGFkZGl0aW9uYWwgY29uZmlndXJhdGlvbiBhZnRlciBb
ZmluaV0KAAAwAAAAZmNvZQAAAAB2bmljX2lkAHZsYW4AAAAAdG9zAGV0aGVydHlwZQAAAG1hY21h
dGNoAAAAAG1wc2hpdHR5cGUAAGZyYWdtZW50YXRpb24AAABzcnZyc3JhbQAAAABmY29lbWFzawAA
@@ -2940,13 +2940,13 @@ X2ZvZmxkAABmY29lX2luaXRpYXRvcgAAZmNvZV90YXJnZXQAcG9mY29lX2luaXRpYXRvcgAAAABw
b2Zjb2VfdGFyZ2V0AAAAaXNjc2lfdDEwZGlmAAAAAHBwcABkY2J4AAAAAGIyYgBzb2NrZXRudW0A
AABjZWUAaWVlZQAAAABhdXRvAAAAAGFuX2RpcwAAIAMWlAAEAAAAAAQAAAQAAP8CAAAAAAAAAAAA
AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8CAAAAAAAAAAAAAAABAAL/AgAA
-AAAAAAAAAAAAAAAC/wIAAAAAAAAAAAAAAAAAFgAAAAAgBpQYAAAAACAGk2ggBpD4IAaP6CAGbqgg
+AAAAAAAAAAAAAAAC/wIAAAAAAAAAAAAAAAAAFgAAAAAgBpQoAAAAACAGk3ggBpEIIAaP+CAGbrgg
BgdAIAXzACAF8eAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgBH0EIASJgCAEiYAgBImAIASaGCAE
syAgBL+oIATHCCAEegwgBHeAIAQxhCAE5OwgBC80IAQsKCAF8bQgBfCEIAXp6CAEiYAgBekQIAXn
-tCAF5uggByRgIAOc1CAD96wgBqusAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgBFVA
+tCAF5uggByRwIAOc1CAD96wgBqu8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgBFVA
IAQ/7CAETzAgBE2cIARMJAAAAAAgBEnIIARUfCADX8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-A///AAAD/wAAAD8AAAAPIAc0/CAG3cAgBzToIAbd0CAG3eQgBt0oIAbeaCAG3Pj/GDBgYAAAAAAB
-AgMAAAAAIAahhCAEe2QgAIgIAAAAAAAAAIEAAAAAAAAAAAAAAAAgBCWYIAQkzCAEInAAAAAAIAQD
+A///AAAD/wAAAD8AAAAPIAc1DCAG3dAgBzT4IAbd4CAG3fQgBt04IAbeeCAG3Qj/GDBgYAAAAAAB
+AgMAAAAAIAahlCAEe2QgAIgIAAAAAAAAAIEAAAAAAAAAAAAAAAAgBCWYIAQkzCAEInAAAAAAIAQD
hCAEA3wgBAN0AAAAACAD+nQgA/wAIAP7nCAD/BQgA/qQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAACAD+yQAAAAAAAAAAAAAAAAwMTIzNDU2Nzg5YWJjZGVmQUJDREVGAAAAAAAAAAAAAEFCQ0RF
RkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5
@@ -2957,7 +2957,7 @@ AQBBAIEAIQCBACEAEBBhAQEAgQEBAIEDAgEAECBAAAAAAAAAAAAABAACAAEAAIAAQAAgABAACCBA
gAAAAAAAAAAAAAAAAAAgAwkQAAAAACADD9gAAAAAIAMJFAAAAAEgAxCAAAAAAiADCRwAAAAEIAMJ
JAAAAAggAwksAAAAECADEIgAAAAgIAMJMAAAAEAgAwk8AAAAgCADCUgAAAEAIAMJVAAAAgAgAwlk
AAAgACADCXAAAEAAIAMJfAAAgAAAAAAAAAAAAAAAKhwAACo8AAAqXAAAKnwAAAIEAAAARAAAAAQA
-AABAIAalICAGpNwgBqOsIAaiVCAGohAgBqHkIAaiPAAAAAAAAAIAAAAEAAAACABZZXMAMDEyMzQ1
+AABAIAalMCAGpOwgBqO8IAaiZCAGoiAgBqH0IAaiTAAAAAAAAAIAAAAEAAAACABZZXMAMDEyMzQ1
Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6AAAAAG5vbmUAAAAAYWxsACoAAABkaXNhYmxl
ZAAAAABlbmFibGVkADB4AABOQQAAVjAAAFYxAABWMgAAVjMAAFY0AABWNQAAVjYAAFY3AABWOAAA
VjkAAFZBAABWQgAAVkMAAFZEAABWRQAAVkYAAFZHAABWSAAAVkkAAFZKAABWSwAAVkwAAFZNAABW
@@ -2989,8 +2989,8 @@ dGFsR3JvdXBUYWcAAAAAQXV0aE1ldGhvZAAAU2VuZFRhcmdldHM9QWxsAENIQVBfQQAAQ0hBUF9J
AABDSEFQX0MAAENIQVBfTgAAQ0hBUF9SAABEaXNjb3ZlcnkAAABOb3JtYWwAAE5vbmUAAAAAQ1JD
MzJDAABDUkMzMkMsTm9uZQBOb25lLENSQzMyQwBDSEFQAAAAAENIQVAsTm9uZQAAAE5vbmUsQ0hB
UAAAAE5vdFVuZGVyc3Rvb2QAAABJcnJlbGV2YW50AABSZWplY3QAAE5vAAA1AAAAQ0hOZXQgMS4w
-MAAAAAAADAAAAAABAAF8AAwBAAAAABAAAAAUIAdK0AAAAwUOQAAAAAAAEAAAACggB03YAAADGA5Q
-AAAf/AAAH/wAAB//tLAf/7SwIAdYICAHW+AgCUDgIAlA4CAKAAAgCoAAIAqAACAK5oAgAwAA4QAu
+MAAAAAAADAAAAAABAAF8AAwBAAAAABAAAAAUIAdK4AAAAwUOQAAAAAAAEAAAACggB03oAAADGA5Q
+AAAf/AAAH/wAAB//tLAf/7SwIAdYMCAHW/AgCUEAIAlBACAKAAAgCoAAIAqAACAK5oAgAwAA4QAu
AB//k7AAAGGo4QGOAAAAQA8AAZEMgAAAACALevAgC3sgAABAAAAAgAAAAAgAIAt8IP//8/8gC3xQ
AACoLAAAqC8AAKgrAACoKgAAqOwAAIEAAACoNQAAqDcgCwEw4QBeACALAXAAAEAOAABAGiALAaAA
ABAAAAD/6QAA/+AAAFAAAAD/+AAAqDv//8kkAABADQAA//cAAA//AAAPQgAA//UgCwIAAACABwAA
@@ -3003,10 +3003,10 @@ SP/4XuD/3///4QL+ACADACAAAYafAACvAOEBDgAAAIj3ACAAAAE/AUAAD0JAFH01cBR9NW8f/6wU
IAt+MCALfpAIAAAAH/zi5CADZ1wf/62cIAsGMCALB2AgCwZgDzwAACALBvAgA+S8IAPmkCALB8AP
AAAAIAsIIB//hmAf/4dQH/+E0CALCHAgCwiwIAsI8CADDbAgAw0wIAuAICADDRAgC4BQIAt/ACAL
f2AgC3/AH/+t8OAAAAAgAEXsH/+u9AD///8gC4BwIAsJgCALCeAgCwowIAsJsCADv2QACAAAIAPE
-JCALC8AgB1RAAA/8AB//mXgf/5rMAAAwACALDAAgCwyQIAsNMFUAAAAOAAAAIAuBECADDigAAAgG
+JCALC8AgB1RQAA/8AB//mXgf/5rMAAAwACALDAAgCwyQIAsNMFUAAAAOAAAAIAuBECADDigAAAgG
IAsNYCALDkAAAA/+H/+trCALDtAgCw6gAADwACALgTAgCw7wIAsPUCALD4AgCw/gIAsQMCALEPAg
C4FQIAsQkCADgNggA5iIIAsRUCALEZAgCxIAH/+toCALElAgC4IgIAOexCADpBQgC4HgIAsTACAL
-EpAgCxNwIAsT0CALFEAgB1ugIAsUwCAHWHAgCxTw7////yALFVAgCxWgIAsYcP3///8gCxYAIAsW
+EpAgCxNwIAsT0CALFEAgB1uwIAsUwCAHWIAgCxTw7////yALFVAgCxWgIAsYcP3///8gCxYAIAsW
cCADpoQgCxbQIAsXMCALF5AgCxfgIAsYICALgnAgAw4gAABgACADDbQMAAAAH/+GwB//h8AgAw+w
H/+GoD/////P////IAsY0B//h3wgCxkQIAsZUCALgpAgCxnQf///q///LlwAANGk///QTQAAnE4g
CxpQIAsaECALGZAf/4a8IAMNuAAAaAAf/4a4AAAgAB//hyAgCxqQIAPfOCADx/AgCxtAH/+tlCAD
@@ -3015,19 +3015,19 @@ YB//rlQgCx0AIAsdQB//reQgCx5QIAsdkABMS0AgA8d0IAsd4CALHpAEAQAIIAOo/CALHxAgCx7A
IAsfcCALgNAgA9zUIAuAoCALIiAAAI4CIAsikCALIuAgCyMwIAsiUCALI4ADgAAAH/+wQCALI9Ag
CyQw//f//yALJSAgCyXgIAPYgCALJqAf/6wgAADAACAD29wgA9aMIAPIDCALhRAgC4VQIAuE4CAL
JuACAAAAIAsnICALKAAAABdwIAuF8CADC3QgC4ZAIAuGcCALhpAgC4YgIAP5JCALhcAgAwtUIAMK
-5CADCuwgCygwH/+sQCALKFAgCyiAIAsooB//qxQgB1YUIAso0B//qkDhAH4AH/+sTAAA8/8EAAAA
+5CADCuwgCygwH/+sQCALKFAgCyiAIAsooB//qxQgB1YkIAso0B//qkDhAH4AH/+sTAAA8/8EAAAA
FAAAACoAAAAgBAH4IAspgB//rlAgC4dgIAuHMCAAHxgaAAAAIAsqECALiBAf/65AAB6EgCAEXIgf
/7EkAA///yALKmAf/6/kH/+uBCALiKAf/62MOAAAAAAAH0AwAAB0AAAQNv//7/8f/7EIMAAAECAL
ieAf/5nkiIiIiB//ragf/5VsAAAMvAAAiQYgCyqgH/+VWACcAADgAAkkH/+qiCALKsAgCyrgAAME
-wOEDAgDg//4A4QCOAAAAloAAAJZAIAdYIAAAlqAAAJZg4QMALAADAAAf/N4A4QB6AAAB4ADhAZIA
-AAHjAB//rbQgCysgIAsrUB//soQgCyugIAssAB//lRwgB1sgF5AAABSwAAAgB1pwgAAABCAHWyoA
-AB9aIAMAeCAHW3AgAwCAFqAAAAhQAQAgoAAAP/AAACOgAAAD/wAfAMAABCAHH5ggBEVYIAcfXN6t
-vv8f/7KIGsAAACAHWigAAP/qIAdbMAAACBQAAIgAABAAAB//rAwf/664IAQLzCADAJAgC4hQIAuI
+wOEDAgDg//4A4QCOAAAAloAAAJZAIAdYMAAAlqAAAJZg4QMALAADAAAf/N4A4QB6AAAB4ADhAZIA
+AAHjAB//rbQgCysgIAsrUB//soQgCyugIAssAB//lRwgB1swF5AAABSwAAAgB1qAgAAABCAHWzoA
+AB9aIAMAeCAHW4AgAwCAFqAAAAhQAQAgoAAAP/AAACOgAAAD/wAfAMAABCAHH6ggBEVYIAcfbN6t
+vv8f/7KIGsAAACAHWjgAAP/qIAdbQAAACBQAAIgAABAAAB//rAwf/664IAQLzCADAJAgC4hQIAuI
cP8///8gAwDAIAssMDAAAAgwAAAMNAAACNAAAAAAAIkUOwAACDSQAAAFXUqAIARiRAAYAAD/B///
ADgAAAAwAAAgC4sgBgAAACAEb+z4AAAAAf//5wABwAAgAACABAAQAB//qlDhAZoA4QGaQOEBmjzh
AZo44QGaNOEBmjAf/66gIAMK/CADCvSAAAADH/+tpP/8//9/////H/+VnCAEfQQgC45wIAuOsCAL
juAgC48gIAuPUCALj5AgC4/AIAuQACALjkD//wAAD///8P/wAAAgC5CgH/+alCALkGAf/6mkIASJ
-gCALkaAgC5HQIAuRQCALkOAf/5pEH/+bdAAA/4AAAC7gIAstICALLVD/+///AAQAAOEB4sAf/6xQ
+gCALkaAgC5HQIAuRQCALkOAf/5pEH/+bgAAA/4AAAC7gIAstICALLVD/+///AAQAAOEB4sAf/6xQ
kAAA8Pz/gMACAAAg/v+AwCALLaAgCy3gAAD4AAADAQgAAwEMj////yALLjAgCy6AIAsusCALLvDh
AN4AAAMDCAADAgAf/6xE///wAOEA7gD//3//AAD8AB//rbwAAOAAAAAMAAADAwQAAREcAAERGAAQ
CACAAAgAH/+ddAADAQT//8AAAAD//gAAJYAAAwMAH/+sPOD/4sAf/6roIAuSICALklAgC5JwIAuS
@@ -3047,26 +3047,26 @@ EJkAAAA0AAAAIAufwCALQfAAGQAAIAtCQCADDkAAABIPIAtCsB//qlgf/7DMBQAAAIP/ABsDFQAA
IAtDIP//QAAgC6JwIAtEACALRIAgC0TQAAGRrOEBkay/////IAtFAAsAAAAgBd84IAtFcCALReAg
C0ZQIAtGgCALovAgC6NwIATJjCADCxQf/5yoAAE4gOAABgAAAicQIAukEH///w8f/60Y/AD//+EA
lgDhAJoAAAAJ/+EAngAAALAAH/+uOCADArAgC0eA4QAOAAMAAAAAOP//4QASABMAAAARAAAAH/wA
-AB//rXwgC0fAIAulMAABlI8AAZTPIAMC0B//nZAgAwdQIAtIACAHUnAgC0gwH/+ruCADCCAf/5Qk
+AB//rXwgC0fAIAulMAABlI8AAZTPIAMC0B//nZAgAwdQIAtIACAHUoAgC0gwH/+ruCADCCAf/5Qk
H/+cnB//mygf/5yU4QGeAP+///8AAZ80IAtJYCALSaAf/5UUIAtOgCALTtAgC08wH/+qzCALUKAf
/6twAD///x//mzwAAP/9AAD/lwAA/9X//6uTwgAADgXcAQAD/wAAwAAAASALUQAgC1FAIAtRkCAL
UdAgC1IgIAtSYB////Af/65kAgAAEB//nbAf/5WoAAL//wAAnEAgC4ogIAtUwCALVTAgC1XwIAuH
kCALVoAgC1bAIAtXACALV0AbAAAAAAUAAiALrNAAAP4AIAYaHCALV5AgC1ewAAAhACALrZAgC60g
-IAutYCAGKowgB1QYIAdUKCAHVFAgC1fg///I////8f///9/PIAtYEP//n/8AACAE///fOCALWEAf
-/5VwIAdYUCAHWFggC1hwAAGQ+P/8+H8gC1iwIAtZICAHU+QgC1lQAAMAAh//nXAgC1nQIAtZgCAL
+IAutYCAGKowgB1QoIAdUOCAHVGAgC1fg///I////8f///9/PIAtYEP//n/8AACAE///fOCALWEAf
+/5VwIAdYYCAHWGggC1hwAAGQ+P/8+H8gC1iwIAtZICAHU/QgC1lQAAMAAh//nXAgC1nQIAtZgCAL
WgAf/6rs4QMKAB//quQgC63w9////wEwGMAgC1pgIAtaQCALrjAgC1qAIAtbACALWsAgC1ugIAtb
-4CALW0AgC1twIAuucAABhqAgBlhk4QMABAX14QAAJiWgAmJaACADCIjhAwAwAAQF7uEDAQThAeIA
+4CALW0AgC1twIAuucAABhqAgBlh04QMABAX14QAAJiWgAmJaACADCIjhAwAwAAQF7uEDAQThAeIA
H/+VYABgAAAf/5WEH/+quAAFAAQABBQAH/+dfB//nYAgCAAAIAgusCAIBmAgCG8AIAgFUCAIBEAg
-CAMwIAgCICAIARAf/648H/+qDCAHVEQf/6iYH/+rUCAB2fzhAHYAIAuy4B//rUQgC2JAIAOeYCAH
-W2ogC2TQIAda7BSQAABAAAAEIAtlQCALZXAgC2NAIAdbYCALY4AgC2PgAACP/iALZDAjKBUAIAtk
-kCALs1AgC7PQIAdaqB//s6gf/7CwH/+zGP/oD/8AEIAAIAtmwCAGkhDhAFYAIAMIkOEAWgAByEAG
-4QGZ4AAAflAAAH5AAAB+GCAGnjAf/6wQIAMP4CADD+QgAw/YIAMP6CADD/QgAw/8AFAgBuEBmgwA
+CAMwIAgCICAIARAf/648H/+qDCAHVFQf/6iYH/+rUCAB2fzhAHYAIAuy4B//rUQgC2JAIAOeYCAH
+W3ogC2TQIAda/BSQAABAAAAEIAtlQCALZXAgC2NAIAdbcCALY4AgC2PgAACP/iALZDAjKBUAIAtk
+kCALs1AgC7PQIAdauB//s6gf/7CwH/+zGP/oD/8AEIAAIAtmwCAGkiDhAFYAIAMIkOEAWgAByEAG
+4QGZ4AAAflAAAH5AAAB+GCAGnkAf/6wQIAMP4CADD+QgAw/YIAMP6CADD/QgAw/8AFAgBuEBmgwA
cCAG/+AAAAACIAYgC2lwH/+csOEBmgThAZoIAAQgBiALaaAAAw0Q4QMeAP//7f8gAwi4IAtqACAL
adAgC2owAAD+5SALamAgC2rQH/+sqAAEk+D/+2wg/+F7gAADDQQAAw0UAAMwAAAOAAAA4AAA/wD/
/+EDKgAAAIADAABjfCALrdD//7//AP8AAPv//84EAAAB/j4ADwAAIAz//98w4QMOAAAYAAMAALmT
AAA/4OEDEgDz/+f/IAu0kCALtMAgAw9gIAu0UCALtPAAAwg0IAu1ICALtUAAAyI8IAu2UAADCAAA
5OHAIAu10B//rLAgC7YwIAu1cOEDIgD//0P///8//wADIgAgC7WgAAMiBCALtgAgC7ZwIAtrQOED
-IjwgC7cAIAu20CALtyAAAw0AH/+ZDOAAAQDf//4AIAdY0OEB4kAABAAEAAQACCALa3AABACAAAP/
+IjwgC7cAIAu20CALtyAAAw0AH/+ZDOAAAQDf//4AIAdY4OEB4kAABAAEAAQACCALa3AABACAAAP/
ACALa6DAAAAGAB///wAAH/8AABAA4QAuAESAAFBsEAYa+7srMQAsoAiNoY6g/hYAKCYBNDD9FgEo
RAFYMPwUCCoBAVww+7sJCAAgCjD6rBAoACBaMPiAACgAIFZwKZAA8IgyAAEQYDD5UgwAZgA+IGiD
O3ZnNihABYNDJ0EDCDMMA3MK/ncRAZ4CGPAHMy3zwwwAYAJ6cAP/KK8i0Q8AKjADDaoR+iIMAZoA
@@ -3074,32 +3074,32 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -3108,131 +3108,131 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-+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
++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
-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
+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
-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
+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
-BMCl/PbeEBgQWDD9ICIiAABw8FkDFRn2t/r2uBQAEEAw+TkBAAAQIDD5hDkADgBA8ApEAiMgIRX2
+BMCl/PbeEBgQWDD9ICIiAABw8FkDGRn2t/r2uBQAEEAw+TkBAAAQIDD5hDkADgBA8ApEAiMgIRX2
qPszEQAEEEAwCDMCI1bB+/anEAAQYDD9CjIgARBwMPr2ohAKEEAw+FbDIAAQeDBbqS/3oBNiAAAS
-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
+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
-wvv2YxAAEGAw/QoyIAEQcDD69l4QCRBAMPiWwyAAEHgwW6jr96AZYgAAGrDAofz2YBAUEFgwWQK3
+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
-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
+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
-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
+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
-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
+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
-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
+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
-+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
++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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+5gEgMBBYMFj/RcCy/RwgIAAQYDD+CgIv/xBQMPo2+iIAAFDwWAKG86wAACIANqAKpQr88wwV4AQ9
YPtcViIAAFCwW4Fd9KwAAAgAtqDAINEP3FDzpgogjAJZcPumCSCPEFAw+kUQICACSHDwCRYAYAJB
-MPkWFCBAAlhw8AigAIACUTBY9iaMImXPwfosAAIAAFkw/AoKIAMQaDBbPhTAINEPLTK9LjK8LzK7
+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
-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
+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
@@ -3247,32 +3247,32 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-AxYAYAJBsPAIoACAAlGwWPPCiyLIuMAg0Q8AAAAAAAD6LAACAABZsPwKCiADEGgwWzutwCDRDwBs
+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
@@ -3282,18 +3282,18 @@ EZkSiIOYE4sTihKJEfcSACAgAkBwl4CZgZqCm4MsQuglTQQlXKD/AgAP/xA4MP8CAAYAQOVQwDD/
8C0QYAIwcPAACWAAEFgwAABvMkUp8gAt8gMu8gL48gEgQAJQcCimAS6mAi2mA/mmACAQEEgwbZoU
/qAALAAgZvAt0Aixu/qsAS4AV+uQjMDTD/xZu3AAEFgwyTwDNgr88BwX4AQ5oPtsViIAAFCwW35t
9awAAA4AtqD3RvsgABAQMNEP3GDzpgogjAJZsPumCSCPEFAw+lUQICACSHDwCRYAYAJBcPkWGCBg
-Alhw8AigAIACUXBY8zSMImXPu/osAAIAAFlw/AoKIAMQaDBbOyL3RvsgABAQMNEPLUK9LkK8L0K7
+Alhw8AigAIACUXBY8ziMImXPu/osAAIAAFlw/AoKIAMQaDBbOyL3RvsgABAQMNEPLUK9LkK8L0K7
KEK6mBCfEZ4SnRNj/tsAAAAAAAAA/eMGcgAAUfDAof0KBC9HADag/WQAIAAQWDArZAP7ZAEgABBY
MPtkAiAQAlMw8goWAAgCSbDwCaIAAgIY8PP/FGAoAjGwAAAAbBAIGPAEiYGKgouDmxOaEpkRiICY
-EIVC/PAAEgAAaLD1VQoABRBQMP5VEQAwEFgwWPwBiyspIDmMQf0hGyAcABLwwKTwAAZqCQBScNqQ
+EIVC/PAAEgAAaLD1VQoABRBQMP5VEQAwEFgwWPwFiyspIDmMQf0hGyAcABLwwKTwAAZqCQBScNqQ
+O/mECIABvAE1hHwAAhmCQBBsAAAwGAf7+2fM/4gDCAAEDgw+yANKOABVDD6790ZAAQ+YPc1Ai+A
-BDug/DUDKgkAdvD879gYCQBecPqZAgAwEFgw+TYAIAUQUDBY++MoGhAIaAL4NgIgMxB4MC8UEC8U
+BDug/DUDKgkAdvD879gYCQBecPqZAgAwEFgw+TYAIAUQUDBY++coGhAIaAL4NgIgMxB4MC8UEC8U
ESgQDy0QDf4QDCIAAFCw+RAOICACYHD5FBQgIAJY8P4UEiAgAhkw/RQTIgAAcHD4FBUiAABo8Fs0
fSekLSekNSekMSekLyekKfekBiABEHgw/6QuIgAAErD/pAcvjxBwMP4kMCACEGgw/SQrIAUQYDD8
-JCogOhBYMCskKAeKFCokLIlCKiQ0+SQ3IEACWTD5iRQCAABhcPkkNiBwAlCwWPK6KFwQ+CQFIgAA
+JCogOhBYMCskKAeKFCokLIlCKiQ0+SQ3IEACWTD5iRQCAABhcPkkNiBwAlCwWPK+KFwQ+CQFIgAA
UPD4iBQAEAJhcPgkBCIAAFhwW34LKiQzCokU+SQyIAAQEDDRD2wQBIYnhm4kbQMlbQImbQT2YAAh
AAI5sCMKAAAwBAYIG3+HOylBgrCZCQlP+UWCIDAAtmApcIDwMQQAARBQMPCqGg//EFgwC6oDCpkB
-KXSAKFKD2zD8UoIiAABQsAuAAPVcDCACAhjw+TSvYBgCITArcIDJsRvvfvzvfxIAAFCwWPfrwCDR
+KXSAKFKD2zD8UoIiAABQsAuAAPVcDCACAhjw+TSvYBgCITArcIDJsRvvfvzvfxIAAFCwWPfvwCDR
DwCKJyqsEFuhOcAg0Q9sEAiIIiwgB4owGe98/AxBAgAAMTD1gVtrAAFQMC2SSvvveBGAADdgKJJJ
K7J/C4gB+4wAAXcANiAY73IogID8xxEAbgJCMPhIFAYAIE3w/XI6KAAgIjCkjrPu/wIACgCW91Ad
72kpcjkNzQot0pcNngH+FgIuAItuUCggFC4gBKSI+AlHAgCvg6CaE/kkFCwAvhJgH+9eHu9eKSEH
@@ -3308,64 +3308,64 @@ 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
-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
+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
-+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
++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
-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
+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
-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
+AABRMFj6ePGEBA+ABDrg/QoBIEAQSDCIEgJvEfrt+h4AIBfw/PLrIAF4piAKygEq9usA2xELmwIr
9uku9upj/xQAAPo5BSIAAFmwW/71Y/8EKzkFx48LjDoLzR0vOugP3Sj9/hMCAABTsP/t7xK4ADeg
ZKCD+rwAAgAAWbBb/ulj/tIc7b0twn4swoCm3QndEfkxBSwAIGswKcUILDAJAsoRq6ouptAd7eAM
DEANzAIAzBEMmQIpptFj/pkpMQYCbRHy7b8aACBfcC2ywBTt2R7t2fSQHGoAQHtw/+3UEAEzhmD3
7dUSATuCYP8CAAIA54ZgKrbAY/5cFO3RnBybEp4b/RYKIAAQSDD5Fg8hVxA4MPAAUGAAEBAwZOJo
-+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
++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
-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
+AAIAAGCwWPpjiBqHGx3tKQAkBPh3GAAAEGAwWPmclxmNGowbWPmMmxWLGf1MAAIAADqw+/oTAgAA
+YLBY+YbwhAQCAABysPqKFAPoEGgw++sYAAAQYDBY+X+IFauP+PsGfgAgUfCx7okaihsPmwz+qgwK
AANaULCq/goBIAAQaDD77TgAABBgMArsOP8CAA//Im8QF+0HY/4qAAAAAAD6EgIiAABZsFv9+mP7
-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
+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
-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
+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
-pgnAINEPAAAAbBAIE+w/DwIAJzKLlxYnchb87DwQBRBQMPsKMCIAAGnwWPgY/wIAAAEKJeCEFvUs
+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
-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
+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
-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
+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
-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
+LvoAfeAwDY0U9NBCYBACWvBj/+gAAAD9MgAgBRBQMPzr6hAwEFgwWPfHY/8XAAAZ6+eZO2P/qMeg
faAMDU0U8AAGYAgCWvCxuw0dFGXf9/o8AA//EGAwW6JbY/6qizz/AgAB/77+0IoUKzISWzEELDEr
KjYTHevW/TYLIAYCYzAMLBIsNSpj/1YAAIkV+CIOIAUQUDD8688QMBBYMP0iAiABEHgw+YgMAAAQ
-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
+cDD4/jgCAAB5sFj3pGRgQBvrx4oie6AECixTycYrIAfaIPsLQQABEGAw+7wYIAAQaDBbo6nRDwAA
+AAAA8/9kYAAQWDAsLDicFfP/k2AAEDAwwKX867cQMBBYMP0iACAEEHAwWPeO+iIQIAQQWDBYICbR
DwBsEASKN6VC+qIOIAAQYDAsJAAjQADDmvsKLCYAlEzQZDE6BEUCbQgQI1ABsVfVcPkxCXIAAEHw
yDFj/+gpcAEsdAD7kSBwABAYMMmYwDBtCBEnUAKxM/txDHACAilwyHRvNQJj/+eoO/y0ASBVADTg
+QpgIAAQODD1jAAAehBgMPsKOSAvEEAw0w9tOjAjUAFziwxzswnwABlhoAIY8AAAc5sMc8MJ8AAJ
@@ -3373,22 +3373,22 @@ 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
-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
+8FjuKhjrTP3rTRvQBD0g8joIBAAgQvD0QIAgPRBgMCykAPqsASoAIG7w+7LBIgAAYTBY7h6kOfKb
CAAAEFAw+rQCIAQCEnDRDwAAbBAEhiDwMQQAARAgMABDGnYwBMAg0Q8ABjMC8yYAIgAAEPDRDwAA
AGwQFoI3GerVHOsxgi7wCQcAQAJAcABIYSQtBCktAy+Qfi6QfS2QfCuQf/sWACEAAiEwKkAAmhEo
-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
+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
-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
+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
-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
+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
-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
+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
@@ -3396,10 +3396,10 @@ AhCwBycMDXUJK1AAZb8CY/8twEDGmgSUOGP+gyLQAC5AgPLhOnAAEGAw30Bk7w4u8IGxzPLp9HAC
Anvwo87/AgAH/35XkPbO9GACAmtwassY8AAVYfQCYzAAAAAAAAAA/wIAB/9tVNCx3fy0ACACAjLw
8/6HYAEQEDAAAAAAAAD6zAACAABYsPUKACAAEHgw8/3pYAAQIDCJEg9IFCiUAPP/cGACAiEwixIP
KhQPrBQstAAqtAHz/1pgBAIhMAAAbBAIIyIY0w/TDy8wBSQKcv4yACoAPnkQ+goFIDAQWDD86hES
-AABo8Fj12S8wBSgKc/TxFHAAEBAw+Qp1JgB3R9D/AgAGAH5P0MCl/OoHEDAQWDD+MgAiAABo8Fj1
-zcosgzjTDyUyGBzp5CIwB/1QBCAFEFAw/lIAIDAQWDD/UAUiIAEQMFj1wihQBXhDPNEP/SIAIAUQ
-UDD86fUQMBBYMFj1uy8wBfkKcCHIBCPwefHc+jIIIAAQWDD8CgAgAhBoMFuIZNEPAAAAAAAc6cyP
-WC1QBI5Q//IAIAUQUDDyFgAgABBAMPgWASAwEFgwWPWo+jwAAAgQWDD9HBAiAABgsFujp/7pvxBR
+AABo8Fj13S8wBSgKc/TxFHAAEBAw+Qp1JgB3R9D/AgAGAH5P0MCl/OoHEDAQWDD+MgAiAABo8Fj1
+0cosgzjTDyUyGBzp5CIwB/1QBCAFEFAw/lIAIDAQWDD/UAUiIAEQMFj1xihQBXhDPNEP/SIAIAUQ
+UDD86fUQMBBYMFj1vy8wBfkKcCHIBCPwefHc+jIIIAAQWDD8CgAgAhBoMFuIZNEPAAAAAAAc6cyP
+WC1QBI5Q//IAIAUQUDDyFgAgABBAMPgWASAwEFgwWPWs+jwAAAgQWDD9HBAiAABgsFujp/7pvxBR
ADagjTDAwPymASwJAHdwnaAb6boMKRH4EgQoACBecJiQ0Q+COC8KdC80BS8kBS8wBfP/DGABEBAw
iTgoCncoNAUolAUvMAXz/vZgARAQMADaMPzpqxAAEFgwW6Nx0Q8AbBAOKCAFKQqV9QoAJgCxzhAp
MhL56lEAKACucPnLUQAAuAag/wIAAAC0BuCEJ4ROJk0CJWQRhzD3RocgARBIMClkEiwgbhfpsPZs
@@ -3409,8 +3409,8 @@ LgkAe7CeES2QByuRKQ0NQQDdEQ27Agy7ApsUCuowlRcpTQKaFfcJFgBAAlBwAMqKBAmIAIqKAgmI
AEqKAAmIAAqK+iwAAgAAWHD8CgQgAhBoMFuUm9EPKkKQ0w9krzQc6VmLNwyqKPoWECAgAlrwKxYR
Wy6FLBIQHejfHul2jzD6EhEiAABasFsuPB/pQS4yEo03D+4C/jYSICACG3DaMFskDPMWEiH/dp6g
8AA5YgAAUPCKJyqsEFua34ssx871JTUqAEBm8JssY/6HAAAAAAAAAPo8AAAAEFgw/AoAIAIQaDBb
-LnzRD1skGhPpWwuoEfSgNmIAIETwDOowKzKFi7Cwo/y7CAIAAFDwWPdLKnKY8DEEAAEQWDAAuxoL
-qgIqdphY94Fj/msAAAD6CgcgARBYMFubgywyfyw2g2P+VGwQCpIY9RYJIAIzJSDyCgAgABAwMPAA
+LnzRD1skGhPpWwuoEfSgNmIAIETwDOowKzKFi7Cwo/y7CAIAAFDwWPdPKnKY8DEEAAEQWDAAuxoL
+qgIqdphY94Vj/msAAAD6CgcgARBYMFubgywyfyw2g2P+VGwQCpIY9RYJIAIzJSDyCgAgABAwMPAA
SGA9EDgwAAAAAAAAAP8CAAYAlj7QwNAmbOr7+uogLAIhMPwKACAAEHAwjxkqEggLawz7OwgOACB8
sFswn6KiZiEd/wIAAACNJSCjbyvwAGS/uv8CAAYAc77QakG32/D9CgAkACB9MG0IGi6wAbHa/awA
AAICYvD7zAAADwA3oHfhCnXKBGP/3gAAd+mJKMABwLD7xAAgAgJysPSDn2ACAmMw/wIACAGrp5DA
@@ -3432,22 +3432,22 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -3456,38 +3456,38 @@ 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
-/aYAIDAQWDD+IhIiAABCsPgmByAFEFAwWPJ9G+ZSLCAHH+bBjhr9UAcgABBAMCglGygkIihQDP7h
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -3502,21 +3502,21 @@ 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
-ByokDPslGiB0AlCw/CUYIHQCWTD4JDkgBhBgMFjm8R7j4o1LDt0C/SYLID4AF3AY5EEvIRsI/wEv
+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
-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
+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
-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
+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
-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
+Ry/yK/IiDiIAWv/QwKX848wQMBBYMFjvcvzjPxAmEBAwG+NRLUAMK7J3KlKBrbsJuxH5400aACBa
sCihKXmBeY1Hjd4Y45wu3QL/40gQoAJbsPAMBwIAAErwAElhAElhAElhAElhjEAZ40Io1pr/1pYt
gAQ7IPnWlCwJADMwLNaVKaAHL6EpCQlBAJkRCf8CCP8C/9aYIOACS7ACA4YASWMAA4YASWH33ggA
BBBgMPLkBiACEGgwW46b0Q8AKjww+zw4ICACYHBb/cf/EgQgKwA2oHSpAmjxIBzjm/6gOSAwEFgw
-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
+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
@@ -3540,113 +3540,113 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+kCBiEBAw0Q8AAAD9IgAgBRBQMP5NAiAwEFgw/N/4EeACc7BY64nAINEPAAApTQMqQogrQocoQoaY
EChGqitGq/pGsSEgAkpwKUal+kIAIgAAY/D6FgEgOhBYMFttovusAAAZADagjBH+EgAgARBoMJ2o
nqqeqYzCZMDrG99VLCAMGt/WK7J3KqKErLsJuxGrqi+hKf8CAAYARy/QjSeN3hzfNyvdAiu8UPAM
BwIAAErwAElhAElhAElhAElhGN9HgiAm1poo1pT4IhEABBBAMPfWliIJAECwItaVL6AHLqEpDw9B
+d0CLwAEP+D5nHAuCQB7sPJNAi4JADOw/taYIeACELAGAoYASWcEAoYASWUp3QP5nIAgBBBgMPOU
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-laiPEJ+qn6mOYmThEy0yHWTc88Cl/N3uEDAQWDBY6WmNJ43eK90E/jIdIQACWvAqsID/CmQgDxBA
+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
-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
+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
-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
+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
-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
+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
-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
+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
-+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
++jUCLgkAe7D+uwIABRBQMPzc8BoJAGbw+zYAIDAQWDBY6Gz1NgIgIAJQ8PwqTiAAEFgwWN92x18l
+NBAlNBH1NBIgLAJQ8PU0EyAGEGAw9TQUIHQCELD1NBUiAABYsFjfYSU0MS0wHhjb+Rzb+vWPFABA
EHAwLjQkLjQmLzQw/DQdIAgQWDD7NBwiQBBQMPo0ISACEEgwKTQg+DQlIAIQSDD5NDYgARBAMCg0
Ovg0OyIsEFAw+jQ3IAAQWDD7NDQgQxBgMP+PFAIAAFiw/DQ1IAYQYDD8NDwsYAFsMP80LywJAHdw
/48UAPAQcDD+CgUsAEB3cP80LiAREHgw/zQnLAkAd3D9NB4gRBBwMP40MyAAEGgw/TQyIKwCUPBY
-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
+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
-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
+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
@@ -3658,73 +3658,73 @@ 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
-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
+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
-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
+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
-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
+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
-YXBY3XOxW/va9xQAIFkwJbCgo0qxqvuyKSIAAGFwWN1ssVn/EgwkACBJMPNGCAA9EEAwKGQA+XIY
+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
-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
+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
-GwA34NkQbQgMKJABsVX0gAlgAgJKcGP/7AAAsWr7HAACAABhcFjdBhvai7Fc9bCwJAAgYTCjSrGq
-+7ItIgAAYXBY3P+xVv4SDCQAIDEw80YIAD0QeDAvZAD5chYiAABgcPgOBwIAAGhw8A2oAAoQeDD9
+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
-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
+8goAIBkANmDZEG0IDCqQAbEi9KAHYAICSnBj/+yxavscAAIAAGCwWNzRpCKyItEPbBAOIhYRJCIQ
+lB0S2lCHRyRAbyYgSCsiE/dyDiIAAFDw/GwABAYBIDBY3MQV2kb82ecb0AQ9INMP9xYFJAAgKvD0
+QIAqACAw8PUKPSoAIGbw9aQAIAICUrD7st0iAABhMFjctisiFfZKCAAAEDgw9BINJgAgGrAnZAIm
+IFD0QG8gBAJSsPoWByoAIBqwmh78bAAEBwEgMFjcqRvaKooeC0sLJLCApqr1pAAgAgJSsPuyISIA
+AGEwWNyhjR4qEhH8Eg0kACAxMPgSBywAIG0wJ9QCLMBuqESyRPqiEiMLADcg+yIXJgAgGTD8IFgu
+PAFQMPwWDyAEAnOw/hYIIgAAUbBY3I4d2bKLGIof/bsLDdAEOuAd2a2qaiWkAPuywSwAIGswLMCA
+/BYJIAICUrBY3IOIH48Z/hIRLgAgR/D7IhkmACAz8CdkAi7iEiwgYPwWECAEAnvw/u5RBAAgeTDz
+RggABAJzsP4WCiIAAFGwWNxzKhIQG9mWLBIK/dmTGgAgUbAlpAALywsrssENzAsswID8FgsgAgJS
+sFjcaC0SEIwbrcz2IGgsACA3MPsiGyAEAmMw99QCJAAgYTD8bAAKACAZMFjcXhLZ4PnZJRQAIDEw
+RYMJgAgGTAlZAAuIADwCQcCAABAcABIYZgU9xQBIAAQKDD+FAAgGQA3oNkQbQgMKpABsVX0oAdg
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+LRSQJcYTLeTYLLA0LBYx+7IOKgAgILBY2tQsEjEf2FX6EjQgChBwMPkQkCIAIGCw9CwIAD0QWDD7
xAAg/gJocPIKBwBCAkNw8AiiAEICa3D4Fiwv9hBYMNiQDpktC5ooqoio+CiAAPjUACIAAFNw9Z/l
YAICa3ArHH8rvCH3pAEqABXS0G0IIC+wACjd/y6A//+E/yH+AlKw/rQAIAICWvD6uwdx/gJrcGP/
2CocfyqsISugAMCQ0w/5FjAgGwA24G0IDCugAbGZ9LAIYAICUrBj/+wAKRYw+swBIP4CWHD8EjAg
-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
+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
@@ -3732,28 +3732,28 @@ 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
-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
+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
-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
+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
-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
+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
-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
+l1ICAABRsPd8BiIAAGCwWNmOHNaw+9axGgAgEbAjpAAMfAsjwID7ewsAAgJSsPuywSIAAGDwWNmE
+ojj1gggIACAyMPSEAiAEAhCw0Q/AQPP/lmYAIBlwAAAAACtyMCxwvPwWACIAAFGwWNl3jxCKEf9V
CAA9EHAw/a0CJgAgGXAuZAAp0HDAwPSQG2EAAmtw2dBtCAwokPGxzPSACWACAkpwY//sAACdFSut
-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
+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
-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
+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
-MP1EIiCBEEgw/UQjKC0BQDD4nDgApAJa8P/PAgH+AkIw+Pw4AFACUTD8FgogBhBgMFjY8yliEIpu
+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
@@ -3766,7 +3766,7 @@ QWAHEHgwqkUrXCD7FgUiAABQsFv7ry1gbvysAAAAgIdgGNYTLoCAauEupar7giEiAABCsG3pEi+w
AP+EICACAlrw9PAIYAICQjBgAAsA+AoAKAAgdrAolCAb1gb/1e8QPRBoMPwSCy4AIHMw/hYGJAAg
L7D9VCAiAABAcPIMBwIAAFBw8AqiAAoQcDD6FgQv9hBgMNmwDrstDLooqpmp+SmQAPmEACIAAFIw
9b/lYAICQjDAsPukASoAFFBQARsCLbAALo3/LOD//eT/If4CUrD8tAAgAgJa8Pqz43H+AkIwLxAA
-/AoAIBMAN+DYECmAAbHM9Z/3YAICQjCcHfscAABCAlFwWNg+iBaFHahVslUsMQrz/CxgBxB4MAAA
+/AoAIBMAN+DYECmAAbHM9Z/3YAICQjCcHfscAABCAlFwWNhCiBaFHahVslUsMQrz/CxgBxB4MAAA
APsSBSIAAFCwW/nr8//jYgAAKrCJImWeAosY+iwAAAAQYDD7vBggQhBoMFuNPMAg0Q+LGPosAAAA
EGAw+7wSIAAQaDBbjTbAINEPAABsEAYrIhImIhD51cAQATuy0Ig0KiAH9QoAIAE3AiCJIv3VExC+
Ajlw90cUCiABUDD1klBtwAQ6oP/VEBwAIGswLsI6mhAPrwr/8pcqAWg/kC7COfzVOBoIAVww/+QB
@@ -3781,12 +3781,12 @@ jxQIiBQoRDQvRDEPjxQvRDAuRCMOixQrRCLwCgcAgAJJMABJYSggBwgIQQyIEa2IJ4Y5KyAWLwr/
f7EK+iAHIGACYXBbjByKJ/sKBCAAEGAw+qwgIAQQaDBbhFMtIhIsYhH7YhQvfxBwMA7dAf0mEiAC
AmMw/GYRIAICWvD7ZhQgABAQMNEPAAAA2iBbjFj91HweCAA2oMAg0Q8lkICxVQUIQQhfDLT/8/2F
ZAUAR/AAABzUtf3UXhD/EHAwLkQ0LUQ1/EQ2L/8QWDArRDeKbrGqmm5bIAMqRDMKjBQb1RAsRDIM
-jBQsRDEjsIArsiH8jBQAoAJRMPxEMCIAAGDwWNdpHdRfihP+CgAoACAZMP6EUCACAnjwL0QnD48U
+jBQsRDEjsIArsiH8jBQAoAJRMPxEMCIAAGDwWNdtHdRfihP+CgAoACAZMP6EUCACAnjwL0QnD48U
L0QmD48UL0QlD48UL0QkY/7hixD6LAAAARBgMPu8GCIAAGnwW4xowCDRD4sQ+iwAAAEQYDD7vBIg
-ABBoMFuMYsAg0Q8AAGwQBCggBSkKkHmBSfzU7RAFEFAw/SIAIDAQWDBY4EWDJ4M++9ToEgAAULBb
+ABBoMFuMYsAg0Q8AAGwQBCggBSkKkHmBSfzU7RAFEFAw/SIAIDAQWDBY4EmDJ4M++9ToEgAAULBb
gNgpPQIY1OX4pgQgABBYMPumBSBAAmKwAgmGAExjAAmGAExhm6aJIsiaiicqrBBbhenAINEPiKL8
-CgQiAABasP0KAyIAAFCwC4AAY//bAABsEASJKsifipjIq8Cw/AoAIAIQaDBY4HPRDwAAbBAOHNTM
-jSAuIAUvMgAoMAX0FgEgBRBQMPgWACAwEFgwWOAeH9QGHtQEHdRVG9TCjDf3GoAgkhAoMPoKkCBl
+CgQiAABasP0KAyIAAFCwC4AAY//bAABsEASJKsifipjIq8Cw/AoAIAIQaDBY4HfRDwAAbBAOHNTM
+jSAuIAUvMgAoMAX0FgEgBRBQMPgWACAwEFgwWOAiH9QGHtQEHdRVG9TCjDf3GoAgkhAoMPoKkCBl
EDAw/MIOIKYAPSBvRCJuQh8kMAUPAgB6QWYtMG7+CpUgAIoHYP8CAAYA6nUQwCDRD2lE+C8wbmnx
8igwBXWJ7Iwo+jwAAAIQSDD5xGQgARBYMFgIocAg0Q8AJDAF/wIABgB2VRAtMG5p0cF1Sb6OKMCx
++RkIgAAUPBYCJfAINEPKrJ4iD0S048psn76socoACBSMCIgwQmZEfmrCAmQBDog/ycPegAgQrAp
@@ -3802,14 +3802,14 @@ AExhiiLIpsAg0Q/ALNEP2iD8CgogAxBoMFsebMAg0Q8AAGwQBBTTCxXTxiRAwShSePJSgSIAAEiw
+YgRAAEQWDD/RxVyACBAsCIiJ4IuIiIQ8AAPYf4CELAAIiKngi4iIhCwImQgViZSh4ZmAioLBqoL
8AAKb/8QYDAmLEh6YT3ybAAACQA2YChgJsqIZD/pLSAmwGD50eFgEBBwMG3qFKJn93AQKAAgGbAo
gAD3iRFwAgIxsNEPiGR5idDRD8Ag0Q/4cwZyAAAzMNawZW+qY//pbBAUHNPuAHWOJCIJLSIALiAF
-+CIbJuABKDDzIAcgBRBQMPgWACAwEFgw+CIcIgAAefD4FgEiIAEcMFjfNykiCicWGvMWGSIBil5Q
++CIbJuABKDDzIAcgBRBQMPgWACAwEFgw+CIcIgAAefD4FgEiIAEcMFjfOykiCicWGvMWGSIBil5Q
LkIHLuIOIyISJyITK+Kr+3wBCgBAXPB8sQIj4rH54qsgMBBYMPzT1BABEEAw/woAIgAAaPD5egEI
-AEBM8PqZDAIAAHHw+Y84AAUQUDBY3x/1CgAgJwA04Po8AAAAEFgwW/+p+hYbIgAASrD1rAADqgA2
-oC6REGAAAwAAx+/6CgUgMBBYMPzTvRIAAGlwWN8P01AX07r1CgAhAAC04CsiG/8CAAIBQMbg9SYb
+AEBM8PqZDAIAAHHw+Y84AAUQUDBY3yP1CgAgJwA04Po8AAAAEFgwW/+p+hYbIgAASrD1rAADqgA2
+oC6REGAAAwAAx+/6CgUgMBBYMPzTvRIAAGlwWN8T01AX07r1CgAhAAC04CsiG/8CAAIBQMbg9SYb
IgBiAaCKJ/xcAAABEFgw+qwgIAEQaDBbgsZgAKcY067+dQIoCQBD8JhwKCITmHIoIhKYcygiHCt1
A5p1+XYEKAkAYjD4dgcgABBAMCgWFxnSmCoxEZUYLjAonhn9Fg8gARBgMPwWECAGEFgwmx0b0qyV
HCUWEfkWDiAUBFqwG9OXC6sCLUEYKhwg/QxGDkgBaDD57hEMBwFsMPDdEQwJAHMw+xYLLAkAazD8
-FgogoAJYcFt9rWSiHcCl/NOJEDAQWDBY3teNL8jb2iD7IhAgARBgMAvQAIwuyMn7IhAgABBQMAvA
+FgogoAJYcFt9rWSiHcCl/NOJEDAQWDBY3tuNL8jb2iD7IhAgARBgMAvQAIwuyMn7IhAgABBQMAvA
ANogWINawCDRD48q/BIZIgAAULD4GgAgQBBwMPj/AQAoEFgw/RwQKgUAf7BbjMj3rAACqwA2oI8q
+9KnEQAQSDD/jFIAARBwMAyeOf8CAAgBF3bQwKDwAApgDRBoMAC4Gn6KCbGq8KEECf/6V1Ad02Qp
QRovFhYpFhj90d8iNAA2YN+Q/ZM2cAAQWDAd01z7CgAgDhBIMPAAE2AEAmtwAAAAAAAAAPjzFHAO
@@ -3817,24 +3817,24 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -3845,51 +3845,51 @@ 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
-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
+/NGLEDAQWDBY3N5j/Q2OKioSFfkSFCA8AF+wKBIXAIQECp8Y/4YOKoAEPqCbj41ojmlgABQAhAT6
+nRgOgAQ6oP1mCC6ABDugnmkc0YAvEhT4EhUgBRBQMPgWACAwEFgwWNzILApyLCQFG9DfDHoR+RIE
KgAgWrCZoGP8xgAAAAAAAADz/bxgABBQMADaQPzRHBA6EFgwW17iyK6WqvOmCSABEHAwnqiNQsrW
KRIZZZw5Y/w+KhYXY/8QACha3PsKACv+7nYQLBYa8/2eZdwQcDAAAPwKCiIAAFqw/QoDIgAAUTBb
-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
+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
-EGAwWNN4lDiUOZQ6lDuUPJQ9lD6UPyQ2ECQ2ESQ2EiQ2EyQ2FCQ2FSQ2FiQ2FyQ2GCQ2GSQ2GiQ2
+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
-DCAgAlKwW4HjiTjycoogEAA2YI05mdCOOJ3hlDiUOShydIo3hTD6og4gABBYMPhVDAVoEGAwWNMz
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+WDBY21/AINEPAADaMFsKUhPPkwuoEfSgPmIAIETwDOowKzKFi7Cwo/y7CAIAAFDwWN2HKmKbADEE
+AFsaC6oCKmabWN2+jCwFzAL8JgwgABAQMNEPAAAAAPoKByABEFgwW4G5jSwuMn/+NoMsCQAvcP0m
+DCAAEBAw0Q8AAGwQBBnP7igiCvoiCCAAEFgw+YgCAAAQYDD4JgogAhBoMFjbg9EPAABsEAT0IM1g
lRBAMCswBSoyBywKkPqiDiAwBELw/QqTICAEYvD/AgAGAGJu0MAg0Q8bz2kvIhgdz8Ypoo748gog
ABAgMCQmFv0mFyQ8AUww+exRClkBSDD3qhAMIAQ7IPRVEAg3AUww+ZkQCFgBQDD8VQIJYAQ6IPpV
AggJAEow8yYQJAkARXD1JhIvihBwMP70dCIAAFCwW3ujLCIS+iICIgAAWrD0tQoggBBoMPS2BCwJ
-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
+AGsw/CYSL3MAtqCIstog/AoEIAMQaDALgADAINEPAAAAAPoKAiAwEFgw/M+8EgAAaPBY2v3AINEP
ACoiGFv/usAg0Q8AAGwQChrO2SiigCmidyqt5iqgwfIWBymQBD5g9RYBKAAgSjD/pw9wARBIMC2N
AS3cgJ0SYAAHLo0DLuyAnhIazt8SzraLF5ITgjSSGIu3IiAHGM7ei777FgYiIAEQMJIQK70CKxYE
+bQSL+AEPKD8IhEOACBH8P8WBSIAIFCwjheO4vXhwGHAEDAwhTYvIjr5EgUkAwA1cCZcTwZGFPmS
lyoAujfQKCI5ihP5hwEOALPOEPAKBwIAAEHwbWkCAEhhixgtsAcssQf8DEoMAgFsMPrdEA3ABDsg
/c+AHAkAazD/EgIsCQBrMJxwi7D4zrkf4RBQMPp0GCBgAklw+XYDK4AEPuD4dgIqCQBdsJtxKPAH
L/EpCAhBAIgR+M6XHgkAR/DA4P52BS4JAEfwn3QN6jCLNZ11LDIH9XUPIIACUfD8XAAKACBm8FjR
-p4g2jzeOFgWIDPg2Bi4AIC/wnzcl5oEtMCjI3WWACxvOrynigAuZAinmgPgSBCBAAknwAgiGAElj
+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
-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
+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
@@ -3899,59 +3899,59 @@ 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
-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
+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
-JhYsMAJlzjHaIFvjgi1Abv8CAAH/Ex9gK30C/BpQIgAAUHBY0GQezUQp4oAq4ncu7eYu4MHA8v8U
+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
-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
+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
-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
+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
-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
+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
-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
+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
-9RAFEFAw+wowIAQQaDBY2B36IhAgBBBYMFgAusAg0Q8r8hIuQioLikT6qg8AABBgMP6qCgABEGgw
+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
-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
+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
-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
+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
-ACqgBSoWACmCACkWAfiABSAwEFgw+BYCIAUQUDBY1xmDJ4M+LT0C+z0DIQACa3D21JMgAxBgMCzU
+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
-+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
++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
@@ -3960,25 +3960,25 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -3988,39 +3988,39 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -4044,7 +4044,7 @@ oPKxQ3IAAEJw9LAzaOABTDD6zAggAgJKMP7WCwA7ADdgImUAIvLiAtILIyUBLPLiLVQADNwL9MYB
IAEQEDDRDw2dOGP/ygAAI6UBlKH5VAAgABAQMNEPAMcv0Q9sEAQXxuXTDylyHShy4voaACnwBD5g
+JgLDjAAvmAJqgxtqQ0rgQBysQv5nAEgEAJCMMcv0Q8jhQGUgflUACAAEBAw0Q8AAABsEAQaxb2M
NCuievqigC1gAWAwrLsJuxGrqiigBPiLBmAAEBAw0Q/A0C2kWCswFC6iFRjGyP/FbxAQADbgLOEA
-CMwBD8wCLOUAjKIrohQpohP9phMv/hBwMP2mFCwAQHMwnKL8CgAiAABScFjP2cAg0Q8AAGwQBCgh
+CMwBD8wCLOUAjKIrohQpohP9phMv/hBwMP2mFCwAQHMwnKL8CgAiAABScFjP3cAg0Q8AAGwQBCgh
BxnGtwgISgyIEQmIApgwhyD2xocXgAQ94PnFsxYJAD0wlzHwBhcAEAIQ8AACipU1+TYEIDACEPDR
DwBsEASLM/oiByAAEGAw/CQnIgAAaTD7BksD8AFcMPtMAABAAlKwW3Vm+iAmIAEQODD4xZoQ4QA0
4AylEfvFmhQAIEVwLFI6C6sK+7KXIgBpxyApUjkfxpQcxmf7lAEOAGFeUC4hBw4OSgzuEQ/uAp5A
@@ -4053,22 +4053,22 @@ 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
-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
+EATAIdEPAGwQBMCl/MZGEDAQWDD9LAACAABw8FjRRWQwiGkxRiMiBw8CACMyDgvqMBrGPiiif/8C
+AAoAiEbQHcTTK6Z/KqJ+/dIxIAAQYDBY0cL8CgAgZBBoMFjSgS4gOCS9AfRMyCYWADug0Q8AAAAA
+APzGLxAFEFAw/SIAIDAQWDBY0SsuOoD9CgIgDxA4MPQKACACAikwKjK+aKEgsUTzPEAj6AI5INEP
+/SIAIAUQUDD8xiAQMBBYMFjRHdEPjyfTD4/+/Ta+KgAgd/AqsIB3qlb2CgAgBBBAMG2KCgBgBAoJ
G3+XA7Fmx28GaQnwYQQAARBgMADMGg+ZCvidAiwJAGKwLLSAKZ0DHMYLJZWDJZWCJIaC/IaDIBgA
-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
+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
-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
+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
-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
+FYgwjkKNQ4lAKkAHLzEInxf6FgQo+AFMMJkW+RYBIDIQWDD4FgAgBRBQMFjQbBvFcCuxf4oX/Dr/
IKgAdvD9EgYgvgRisGjWKGRAR/o8AAIAAFkw/BIEIIQQeDD/RQggARBwMP40FSAAEGgwWHOHYAAh
jRSKNywKAPvcAABAAlKwW3QW8//BYgAAIrAAACs6/3uhDPNcAA8cALVggylgACKNN/76wCBAAmNw
/goALABAczD+1RQggAJjMJzZnNhj/9EAAPsiCiAvADTgyrwpsgsPAgAPAgDInm0ICfmSCyIAAFpw
@@ -4076,49 +4076,49 @@ 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
-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
+CYoQYAAFABrD8ZoQGMPwjicfxQb6ijgD6BBoMA2tLA/dKP0WACAgAlOwW3WphBCDJ/pMAAAgAhjw
Wwk5/cOUEgAAYTD+xPsSAABasP8iACIAAFDwWwjvgiciLBDaIFr+w2ihX9EPAAAAAAAA/p80cAAQ
KDDz/u9gABAgMIkn+/rAIEACQnD7iAEAABBQMPqVFCCAAkIwmJmYmGP/PtogW3CL0Q/RDwCKJ/t8
AAAAEGAw+qwgIgAAafBbc5bz/vJiAAAisNogWv7JEsQJC6gR9KA5YgAgQLAM6jArIoWLsCKs//y7
-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
+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
-BgBQNJBj/9aK4QqKFAeqAfr56XAAEBgwjTP+MgIgBRBQMPzEohAyEFgwWM+SLVI9L1I8n9AuUjyK
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+hxBYMFv+cYo3KqwQW3PahDnLRiUWaYVL/UIAIgAAYbD+MgAgBRBQMP9ABSAyEFgwWM4i+wqHIgAA
UTBb/er0XAAP1AC1YIQ5JRJp+TILIFUANSD8CgAgMAC2YJQ7YAA7AAAA+iwAAAUQWDD8CgAgAhBo
MFsWhWWihMK1KyQFG8MfY/uBAAAAjZvI2/3SCyIAAEtw0w9l3/KUm5lM/DYJIAAQIDCNWvPZDXAA
EHgwhDmNOJ1aYAAjydWO2NMPDwIAc+EM/ewAAAkAN6CO6HPp8sjXJDIJLjIILtYI/zYIIAAQcDD9
MAUgQhBAMP00MCKYADUgKDQFKhJWiqeKrimgcCugcQiZEQuZArGZKaRxCYkUKaRwY/ubLBJeLSAH
-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
+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
-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
+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
-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
+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
@@ -4131,8 +4131,8 @@ JAXz9/5hkBBYMAAA2jD7HH8gCBBgMPu8QSACEGgwW2x3Y/vEAGwQBvYsAAFRADUgKixI+hYBIIAC
YLD8FgIgoAJYsPsWACBwAjiw8sItH+8QcDD7wiwQABAoMPAASm/9EGAwAGiVaWmaMS0wBC8wBfgw
Bi2ABD9gD90C/zAHLYAEP2AI3QII3RH/3QID6BB4MA/dLP1kNiIAQFiwLzABpfXz8woKAFkhUCkw
AP8CAAAATIZgaJJsaZSptDnzCRYCAABB8ABIivAASWIAQHCwAAAoMAIpMAP6+t8gCgJY8PoiAQmA
-BDog+hIAKAkASjD4ZRggAxBgMFjD8I0R+8ICEBACePDxDxYP/RBgMPIdHg/vEHAwKjABpaXzowoL
-/8YlUGAAMooS/AoGL/sQWDD7PAIiAEBYsFjD4PvB8x/9EGAw8//Pb+8QcDAtMAMtZDTz/0liAEBg
+BDog+hIAKAkASjD4ZRggAxBgMFjD9I0R+8ICEBACePDxDxYP/RBgMPIdHg/vEHAwKjABpaXzowoL
+/8YlUGAAMooS/AoGL/sQWDD7PAIiAEBYsFjD5PvB8x/9EGAw8//Pb+8QcDAtMAMtZDTz/0liAEBg
sMogGsF7i2AuonL6oowgABBgMP67DAABEGgwW3AbwrQrZAXRD9EPEsHhY//VAABsEAT6Cg4v/RBY
MPskASAAEGAwKiQALCQCKTAAKSQDKDABKCQEJDACJCQF0Q8AAABsEDorIAXCZPQKJyYDtDbQwqX6
sShwABBoMMKG/wIABgODRtDzCigmA94m0PQKKSYD7h7QdLEG2iBYEALRD4kqg5pkNEYpFlYuHQH6
@@ -4140,29 +4140,29 @@ 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
-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
+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
-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
+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
-MC3kHi+EHPmkISBoAljw+hJYIAgQYDBYwxkqEln8CgggeAJY8FjDFitccvoSWiAGEGAwWMMSKhJb
-/AoDIJwCWPBYww8qElz8CggguAJY8FjDCyQRoigRoyoSXSgVkSgyDPqMQAwJAVQw+hUUCAUBJDD0
+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
-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
+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
-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
+iRQppHBj+6YAAAAsEl4tIAcuME4vME/4MFAgBBBQMPgWACAyEFgwWMtq+RJoLgAQWDD7FlQgABBQ
MPoWVSAgAkBw8AkXABUQSDDTD22aAgAIiiodAS0SVv7AbxCcAljw/hYEIAMQYDD90gAgBBBwMP4U
-KCAAEHgw/xQjIAsQcDD/Ov8tgAQ/YP8VECwJAHdw/RYFIKACUrBYwk76HQEgogJY8PqsVCADEGAw
-WMJJ+x0BIAAQYDAsFEEsFEL8FEMgBBBoMP0UQCCgAirwLVAC/1ABIKgCWvAosAL6sAEgUgJIcCqU
-ASiUAioSXyVQACuwACuUAPsSYCBaAnBwL+QBLeQC9eQAIBAQYDBYwjEuEmItEmEr4AEs4AAs1AAr
+KCAAEHgw/xQjIAsQcDD/Ov8tgAQ/YP8VECwJAHdw/RYFIKACUrBYwlL6HQEgogJY8PqsVCADEGAw
+WMJN+x0BIAAQYDAsFEEsFEL8FEMgBBBoMP0UQCCgAirwLVAC/1ABIKgCWvAosAL6sAEgUgJIcCqU
+ASiUAioSXyVQACuwACuUAPsSYCBaAnBwL+QBLeQC9eQAIBAQYDBYwjUuEmItEmEr4AEs4AAs1AAr
1AEp4AMq4AIq1AIp1AMv4AUo4AQo1AQv1AUs4Acu4AYu1AYs1ActEmQsEmMq0AEr0AArxAAqxAEo
0AMp0AIpxAIoxAMu0AUv0AQvxAQuxAUr0Act0AYtxAYrxAcsEmYrEmUpwAEqwAAqtAAptAEvwAMo
wAIotAIvtAMYvq0twAUuwAQutAQttAUqwAcswAYstAb6tAcgABB4MC8UZC8UdP8UlCAgEEgwKRRE
@@ -4172,7 +4172,7 @@ gzllP+8mJAX6LAAAARBYMPwKACACEGgwWxNTZaixJCQF8/imYGQQWDDaMFhVOIM5ZT/BY//Ojjhj
+TkAjztl/WbEg3jRKRq/4oswLqJy+qKMIAAQYDD+uwwAARBoMFtuGBy/PovO/jIIIf4CWvCbzic0
BWP9NgAA+iwAAgAAY3D7CgEgAhBoMFsTN2WoQSMkBfP4NmGQEFgwAAAAAAAAAPosAAIAAGNw+woD
IAIQaDBbEy1lqBkkJAXz+A5hkBBYMAAA2jD7HH8gCBBgMPu8QSACEGgwW2oBY/vMAGwQHCgwIhW/
-wQiICQyIEahTJTJ/+iwAAEIANWASvwwtoAwuInsqIoSu3fndEQIAAFlw/aoIAAEQYDBYoRPCbfwa
+wQiICQyIEahTJTJ/+iwAAEIANWASvwwtoAwuInsqIoSu3fndEQIAAFlw/aoIAAEQYDBYoRfCbfwa
gCAmEDgw9EARYP0QaDBoQwn/AgAEAFmFINEPrDsusHl/5/UN7AEstHmKp/IagCAgAlKwW3BAoj4t
4HkiMoP4+v8g+xB4MPjkeiwAQH9w/eR5ICkAtKBj/78AAPo8AAABEFgwWFUjIzIJyDkpMAV2memD
OWU/9IIpZC+dKiIVdan0KyAFd7HujSf00g4vwBBwMPckBSBAAmNw/goALABAczD+1RQggAJjMJzZ
@@ -4181,21 +4181,21 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -4203,7 +4203,7 @@ AiEwY//rx8D/AgAP/3bfEAtLFPP+4mAIAiEwaHIt2iD8HBAgBBBYMFh8kGP/lQAAAPP+ymAAECAw
ih/8HBAgAhBYMFh8E2P/egAAAIwe/RIPLeAEOyAAwQSMF4kY+goAIAQQWDDwuxoKBQBrMKuqKpav
ixnAgPq2jCAAEFgw+ZKvIAgQUDBtqhfwgQQKIgFIMPCqGgAEAkIw+UkUCgkAVvCNGSvWi2P/dI8V
L/0BLvGNwCTyEgYuCQATsC71jdEPAMAg0Q9sEAQYvNslgn0mgoD4gnskACAVcAlVEQVlCPVSBygA
-IBIwCYgRCGYI9VIOIDsANSDdIP4wACAFEFAw/L4JECQQWDBYyObaYPwwACABEFgwWC9eKl0BKaGN
+IBIwCYgRCGYI9VIOIDsANSDdIP4wACAFEFAw/L4JECQQWDBYyOraYPwwACABEFgwWC9eKl0BKaGN
wLILmQL5pY0iAAAQ8NEPwCDRDwBsEAT3vf0RGBBQMAoqKKenJ3KXBHcoB3cK+DroJ/AEPeAIdywY
vfYbvfYcvGsCKQvzmQkHwAQ44PyqCAnABD5g+HgCCAAgXnD4lgAmACBRsPdmwCCcECgwJWa/0Q8A
AABsEAgWvKjZIPNifSIAABDwwLD1YoAgABA4MPhieyIAIEzw+TMRAAEQUDDzUwgADxB4MPMyBygA
@@ -4222,25 +4222,25 @@ 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
-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
+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
-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
+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
-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
+WL529hYJIDACUHD1FgggGgJY8PIWCiAIEGAwWL5vhhT1HBggABAgMPR5DAHwAkFwmBsEOAzwADxg
+ABAQMGjyGvy8hRAEEFAw/RIKIAcQcDD07gwAJBBYMFjHXI8b9kYUAAICITD0OAwB/gIpcPR5DABY
BHlw8pRdKmABMDAqlE0ogAwolFUvUAdl/7DAwfyUXS//EFgwK5RNY/++AIoZixgqrQH6rA8gExBg
-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
+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
-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
+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
@@ -4253,7 +4253,7 @@ Cok48/6oYAIQYDBsEASIMCowCf8KGi/qEGAw+AJDAABwJhD3ChYkAGgVIPgwCCAgAmjw+gtFAAIQ
cDD6ekAAARAgMPgMQQhEAUAw9ME4YfoCSzD55DgBKAA2IPr3OAYAkBYgBIYMBgZHpr7/AgAKAIh1
0GRgaB+6K/hKACVAEHAw97txHgUAUjD+vgoJIAQ4oKju9+4IAgAAW3D/7wgCAABBsPm8AAAAgAYg
C7oCAA+L8AuAACACc7DxChYB/AJCMPMKFgAgAnvw8lkeACACWvDyGR4PzgC2IA1rEQ29CgQOR8jp
-+iwAAAEQWDBb/17wAAxgABBgMP27SxAsBHkw+lwAAgAAWPBYxDjAINEPAAAAAiwR/cwIAgAAWPD5
++iwAAAEQWDBb/17wAAxgABBgMP27SxAsBHkw+lwAAgAAWPBYxDzAINEPAAAAAiwR/cwIAgAAWPD5
ChciAABDMG2aFCmCgPqCgSAQAkIw+bYDIBACWvCasPs8AAAcEEgwbZoVKcLQ+sLRIBACYzD5tjEg
EAJa8Cq2Ltog/T0CIAEQWDD93JggAxBgMFv/PfP/iWAAEGAwAAAAAADz/3xv6hBgMPQKAC/0ADYg
/4fsbgAgQvAK9zh+c+Hz/tViAAAyMAAAH7sgr+8o8oCYsC/ygZ+xY/8fAABsEAQXudkZuyIYuyL3
@@ -4263,7 +4263,7 @@ AieW0iaS0hW6+aU1JlKAlkElUoGVQC+W0i6S0tEPAAAAbBAEKzIALPrq+3pAAABkptD+ueMSAGDB
IP+5qxCAEDgw9rrqFABWFSAkMQQEzUL00LlkgAEgMP8CAAAQEGAw/wIABgBUl2AoChH6yDkIACAn
cP8CAAABEGAw/wIACgBHThD5CgAjABBAMPrJOAAgAmDw+briFgUATjD3SgsCAIdi0CkgDBu63AaZ
EQmpCAuZCA+aCPvMAAAAqgdg3sAACovwDIAAIAJKcPEOFgH8Amtw8w4WACACUrDyWx4AIAJjMPIb
-Hg/PALdg8AAJYAAQYDDAiXhBHfpcAAIAAFjwWMOswCDRDwAAAAAAAADz/+Zv6hBgMPi3OXAQAmDw
+Hg/PALdg8AAJYAAQYDDAiXhBHfpcAAIAAFjwWMOwwCDRDwAAAAAAAADz/+Zv6hBgMPi3OXAQAmDw
wKD5ur8QCBBYMG26Dy2SpQ0NUvTQumAQAlKwuJnAoC/if44gp6v/6gwAEBBoMFv/jWAAUAAqIAwb
urMGqhGrqv+rCAAQEEgw/wIAAgAAazD/AgAAAEYGYN7AAguL8AyCACACUrD1DhYB/AJKcPcOFgAg
Alrw8t0eACACYzDynR4PxwC2YPP/UWAAEGAwAAAA+woAIAgQeDDTD236DyiSpQgIUvSAHGAQAlrw
@@ -4279,14 +4279,14 @@ AEfw+LAbL4AEP+D8qgIOCQBP8PmwWSuABDqg/PwBKgkAQrD4sBUqAAN7ELGqL7ARLLQfKrQbDIwU
CooUKrQaLLQeCooUDIwULLQdKrQZDIwUCooUKrQYLLQcKrAQ/LAUIAICSnAptFkpsBL4zBELgAQ6
oP+wFioJAHqw+LAXLAkAQzD4qhENgAQ7IP+wEywJAHsw+aoCDYAEOyD4qhEMCQBDMP+qAgwAIGOw
/ssGegAgU3Cxqiq0Eyy0FwyOFAqNFC20Ei60Fhy59A6OFA2NFC20ES60FQ2NFA6OFC60FC20EP0h
-NiACEFAw/iE3IDIQWDBYxLCNN/4yCSACEFAw/LnnEDIQWDBYxKsvIAXEhf8CAA/+wcPQxZX5JAUg
+NiACEFAw/iE3IDIQWDBYxLSNN/4yCSACEFAw/LnnEDIQWDBYxK8vIAXEhf8CAA/+wcPQxZX5JAUg
ABAQMNEPAABsEAYmIAcYuDz0ua0WIAEwMAZjCQwzEQQ0CPpCfyIAIETwIz0fIzxw+jkIcAAQaDDA
INEPiaGMoJyQi6AoqRCZsZ2g/aYBIDEANiCMp8rHH7nIi8EeuZwv8n8LixT+uwEB8AJysPscAAuQ
BDrg/1wACgAgU/BbVjYsQn9zwbGNImXfrPtsGCIAAFCw/AoBIEAQaDBbcJLAINEPAABsEAYTubcC
-JAkMRBGkMysyICQwfyYwfvUwfCEvADbgGrhaLTCELqJ3KqKADt0ICd0R/aoIAAEQYDBYmuUtoAf/
+JAkMRBGkMysyICQwfyYwfvUwfCEvADbgGrhaLTCELqJ3KqKADt0ICd0R/aoIAAEQYDBYmuktoAf/
CvsuAgEoMP7uEQwAQH9w/Ar8LAkAd3D1CUEMAEBncPakFiwJAE9wLaQH+jIpIgAAErAroAcMuwEL
-mQIppActMH0GD0f8uZgSAABxMP0oQAAyEFgw+BYAIAQQUDBYxFUjMiRkMKQVuZDwAAllMAQ5IIM5
-ZDCUjTAoMRn+IAciAABhcP8gFiAEEFAw/zQWKWABQDD+NAcoCQBBMPg1GSAyEFgwWMREizrMtmP/
+mQIppActMH0GD0f8uZgSAABxMP0oQAAyEFgw+BYAIAQQUDBYxFkjMiRkMKQVuZDwAAllMAQ5IIM5
+ZDCUjTAoMRn+IAciAABhcP8gFiAEEFAw/zQWKWABQDD+NAcoCQBBMPg1GSAyEFgwWMRIizrMtmP/
w4u5ZL++KTAHLDAWLTEZirottSkstBb5tAcgDgC2oGP/3gAAiqhkr9cusAcvsBYosSmJqSilIi+k
Fv6kBy/mADZgbQgWLaAWLKAHLqEiLpUiLZQWLJQHiZtkn8dj/+LRD2wQBvOKQgCAEEgw+TkBAgCg
4NAlrQElXID/AgAOAJ2RYPSRi2hIARgwLiAMKiANFrgD8wxGDgC9Q5AvIFErIFD0oRxqACB+8P1i
@@ -4300,7 +4300,7 @@ d66ZCZkR8/9AbAAgT3AsUCYbuQcMzAkMzBGsuyqwfSwK/QyqAQOqAiq0fdEPJ2J3rnf5FgAnkAQ9
YQBJYR248x+49Re48xi3hfm4NRAAEHAw/nTBIgAAULD4gtgiAABZMPl1XCAEEGAw/3YtKYAEPaD8
PxEICQBNcP90wCgJAG5w+XYsIAUQaDALgAApci0JiUfIk9KQ0Q8AGbjgGLc1K3FcAz0JHrjcHLiw
nhn83RELYAFcMPsWCiwAIGNwnBcrxn8qzQIlpAEmpAD64AEmACBKMPzgACYAIDNwLGQAKmQBKOAD
-KeACKWQCKGQDLeAFLuAE/mQEIgAAULD9ZAUgARBgMFiZ+IsZHLi7KCEJLiAMLyAN9SEHIgAAGrAt
+KeACKWQCKGQDLeAFLuAE/mQEIgAAULD9ZAUgARBgMFiZ/IsZHLi7KCEJLiAMLyAN9SEHIgAAGrAt
MCYpIQgqIBQN3QkqNBQpNQgoNQkuNAwvNA0lNQf1EgotwAQ/YP4SCCAQEHgw/zQELAAgbzAt0H/w
DgcCAABJMABJYQBJYQBJYQBJYRK3Ohm3QPwKBClABDtg/HYtIgkAEXDydiwoCQBKMCh1XC5gAS9g
AC+0AC60ASpgAy1gAi20Aiq0AyhgBSlgBBa3LSm0BCi0BSZi2QM6Av0KBSIAAFkwC2AALXItDY1H
@@ -4317,23 +4317,23 @@ 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
-5hwRAGsw/nYtLKABYDBYxLXAxP0KBSIAAHKw+3YvIgAAUPD+di4iAABZMAtgAC1yLfP89mzoAWww
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -4351,7 +4351,7 @@ QGOwBe4CLvR9LdAmDd0JDN0Rrb0q0H3+Cv4qAEBisA6qASrUfdEPKHJ3r4gJiBGouJgSY/2zJXJ3
r1UJVRHz/opkACAu8AAAAAAAAADz/ulgABAQMMCAmBRj/gUAbBAKijAbtiIoIgL5tekaYAFQMAqq
Cfe1zRvABDqg+pkIACoQYDD2kf8gbgA2ICkiBy2ZFPTTaGBAAlJwLZIJZNNdLtAA+NICIA4IY7B7
gUD7CgAgAhBgMFtr0x22DRu2DZegjCCTpSSkHJWmm6T9pgIv/xBIMPjMEQACEGgw+aQdLAkAazD8
-pgEiAABRcFi+88Ag0Q8AAAD5FgEggBBYMPtuAQIBdmGQBopCKa0BKZyA/wIADgFxkmCZGPTg6WhI
+pgEiAABRcFi+98Ag0Q8AAAD5FgEggBBYMPtuAQIBdmGQBopCKa0BKZyA/wIADgFxkmCZGPTg6WhI
ATAwKyAMLCAN9gdGDgBtwtAtIFEpIFCbF/TC5mgAIG5wG7SAsJiYEyqyePuygCMiADcgGLXViReo
mSmQ3ayZqakJmRGpuSmcgJkViRWJkAqZDHlxHP8CAAoAR+3QihP/AgAKAELR0MvCG7TxKrJ8K7KE
ZMKXGbXEiBepiCiA3ayIqKgJiBGouyu8gIiwCogMeHkJnhnwABZgABBYMMCB/XsMDAUAYjD+Fgkq
@@ -4364,15 +4364,15 @@ qHcbtXAZtAHwCQcCAABK8ABJYQBJYQBJYQBJYRm1axiz/x60ntpw+ILbIAEQYDD85q0oCQBNsPnm
rCAFEGgwC4AAHLSWLMKtiRD6tVoc6AFgMPTBFGD9EFgwJpAmBmYJDGYRpqYvYH33Cv4uAEBf8Af/
AS9kfYknjhEtmRT2tWQQABA4MPwiAiBAAlpw9+aDIJcAN2D6kgkhIgA3IGSgiiigAMKaeYkUHbVY
jKL/AgAGAH/vEP8CAAf+qDcQ2rD8CgIgABBYMFtrFh61Uhi0/ZigjyCWopOlJKQc9aYGIAIQQDD3
-pB0vgAQ/4P6mBC4JAEfw/6YBIgAAUXBYvjbAINEPAAAAAAAA8/0laMABNDCaGGP9HQAAAPsKACAC
+pB0vgAQ/4P6mBC4JAEfw/6YBIgAAUXBYvjrAINEPAAAAAAAA8/0laMABNDCaGGP9HQAAAPsKACAC
EGAwW2caY/ysAABkwI/asPwKAiAAEFgwW2cVY/+OmRNj/UyZEmP+ThizxYkXKIJ3qYgJiBHz/W1q
ACBG8Cnyd66ZCZkR8/5iagAgTvAtcCYN3QkM3RGtrSzQffvMAQABEHAwDswCLNR9Y/7QGLO0iRco
-gnepiAmIEai4mBVj/OUp8neumQmZEam5mRRj/d0AAAAA/wIAD/+LMxBj/E3aUPs8AAAAEGAwWL3b
-2iBYtVjAINEPAAAAAAAAAPP+JmAAEDgwwKCaEGP9LQBsEAYmMAgnMAn2CUEGRAEwMPgyACDNADWg
+gnepiAmIEai4mBVj/OUp8neumQmZEam5mRRj/d0AAAAA/wIAD/+LMxBj/E3aUPs8AAAAEGAwWL3f
+2iBYtVzAINEPAAAAAAAAAPP+JmAAEDgwwKCaEGP9LQBsEAYmMAgnMAn2CUEGRAEwMPgyACDNADWg
+go4JgBilaD7CnggAGemEP8CAAQAWpUg+LTqEACjYdAas3qYEPAKBwIAAFIwAEphAEphAEphAEph
-CZoJGbT2DKoRqpkikh9kIH4as4QtkIAuoncqooCu3fndEQIAAFiw/aoIAAEQYDBYlg4Ys2wbtOz9
+CZoJGbT2DKoRqpkikh9kIH4as4QtkIAuoncqooCu3fndEQIAAFiw/aoIAAEQYDBYlhIYs2wbtOz9
tOoYoAE8MPmc/y1ABDmg9LY/KAkAZnAptYD4gt4sCQBssP22PiIAAGEw+xIAIAUQaDALgAAYtN4o
-gj/5PBAo6AFAMPyMAABxADYgCAwG8AAIbeABYDAAHLTW+lwAAgAAWPBYvZfAINEPe4bqLTIBcdbk
+gj/5PBAo6AFAMPyMAABxADYgCAwG8AAIbeABYDAAHLTW+lwAAgAAWPBYvZvAINEPe4bqLTIBcdbk
+bRJFcIAvSAoIARogUj/AgAEAF4CIGmFywcIRQhvCA3/Ef/8+CBAEHAwf+O3A4gL8AkXAAoANaBt
aQIACIrz/6ZgABBgMBi0v21pBQAIiAAJimP/kgAABwhFqGsNuxErvPj/AgAL/7/ekAOIC/AJFw/N
ADWgbWkCAAiKY/+/KCAEaIFw/wIABABQAiD/AgAF/6qeIAcIRahtDd0R/dz4IEAQYDD/AgAL/57v
@@ -4381,21 +4381,21 @@ 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
-+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
++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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -4403,29 +4403,29 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -4433,47 +4433,47 @@ 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
-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
+AlrwK8QxC4sU+8QwICACUrBbYdCDKcszFbF7hDv9MgAgBRBQMP4iACAyEFgw/zAFIgAAYXBYvBj7
CooiAABQ8Fvr4PNMAA/UALUggynAQPsiCyAVADTgZbPXkytgAAYAAACTu5s8lCkpIAwqIhYbr+sY
sNb4FlAgGhBgMCwkVCVyhCuydwAIjfmqEQIAAEBw+loICAAgXnD6Fk8pkAQ+YPkhGSQAIE1w+RZO
-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
+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
-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
+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
-HH8j/xB4MPQUoyALEHAw9xSoLYAEP2D/FVAsCQB3cP0WJSBUAlKwWLJG+hx/IgAAWPD6rC4gAxBg
-MFiyQSQUwSQUwiQUw/wKECADEFgw+xTAIP4CUHD6rEUgqAJZsFiyOPtsQCD+AlBw+qxVIAgQYDBY
-sjP7bDgg/gJQcPqsXSAIEGAwWLIu+h0BIMgCWbD6rAQgCBBgMFiyKicViCQU5CQU9PosAAALEGAw
+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
-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
+4ADaIFtbp8Ag0Q8AABywV40g/iE2IAUQUDD/ITcgMhBYMFi68YYuIzJ/CWYRpjP2PE4gCgJQcPwK
+AyIAAFmwWLHuGK+3G7BK/AoDIBUQSDDwCBcAMAJAcG2aAgAIipsWiiD8FCsgCxBYMPUUMCuABDqg
+9xUUKgkAWrAqFgcpMAT6HDEkAN0GYCs8UVix29tg/AoDIGoCUHBYsdglFEgkFEkkFEokFEskFE77
HBgiAABQsP0KAiAJEGAw/BRNIAsQYDBYQM/aIFtbdsAg0Q/aIFtbdMAg0Q+KJyqsEFtgcoguGa+P
IzJ/8AkXCZAEOiD4HH8iACBE8PiMQSAVEEgwbZoCAAiKG7Ab+xYwIAMQYDD9Ig4gogIw8PocfyAL
-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
+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
-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
+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
-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
+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
-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
+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
@@ -4481,7 +4481,7 @@ INEPAIwiZMBSjiD4ryQQCRB4MJ8S+O4RAAEQeDD4FgAuCQB7sJ4Rjif9+sAgQAJTsP2tAQAAEHgw
iCJlj5ErIHz6LAAAARBgMPu8EiAAEGgwW2WtY/94bBA6KCAF+q5oEC4QSDD7ygAuAm1KECoWY/sW
ACAQAkBw8AoXABUQSDBtmgIACIr0rqIQQgJgcPwWWiALEEAw9BYCIJACULD6FmQj/xBIMP8iACB4
AlBw+hZbIAAQIDD0FBsgARAoMPUUIC+ABD/g+RUMLgkAR/AvFgMtIEkuIEguxAAtxAErIEorxAIk
-FDkkFDr0FDsgAxBIMPkUOCCoAliwKxZcKBAALRAC/xABIEoCcHAv5AEt5AL45AAgEBBgMFiwbBOt
+FDkkFDr0FDsgAxBIMPkUOCCoAliwKxZcKBAALRAC/xABIEoCcHAv5AEt5AL45AAgEBBgMFiwcBOt
3RauqhitOy8gQSkgQBuuo/sWZSCYAjhwJxZdKXQAL3QBLiBCLSBDLXQD/nQCIKgCaHAtFl8qIEUs
IEQsdAQqdAUvIEcpIEYpdAYvdAcsIDkuIDgu1AAs1AEqIDopIDsp1AP61AIg+AJIcCkWYS8gPScg
PCfUBC/UBSwgPy4gPi7UBizUBycgZSogZCqUACeUAS4gZy8gZi+UAi6UAy0gaCwgaSyUBf2UBCCA
@@ -4489,12 +4489,12 @@ AmCwLBZeKiBqJyBrJ5QHKpQG966jEHACULD6FmAgyAJIsCkWYviC+CD/EHgw/xVCJBAQcDAuFUEu
FSEkFFwkFGwlFUT0FIwgIBBoMC0UPC0UPY0nKBZmKSIA/dIOIAQQYDD2Nq0iAABQsP0WZygJAD5w
+TasIAUQaDALgAAqMq0pEmcKikf9risTDgA2oC6QOi+QOwjuEQ/uArHuLpQ7Do4ULpQ6LxJj+doA
IP4CQHD5FiwgcgJCMPAPFwAVEEgwbZoCAAiKKxJkHq5vLhYu/SIAIAMQYDD6HH8j/xB4MPQUyyAL
-EHAw9RTQLYAEP2D/FWQsCQB3cP0WLyCkAlKwWLAAJBTpJBTqJBTr+AoDIP4CcHD4FO8gYhB4MP8U
+EHAw9RTQLYAEP2D/FWQsCQB3cP0WLyCkAlKwWLAEJBTpJBTqJBTr+AoDIP4CcHD4FO8gYhB4MP8U
6CBiAkOwLYAC/4ABIKwCc7Av5AEt5AIogAAo5ACJICwiBysSZSgSZvzCDigJAD5w+TasIgAAULD8
FmggBRBoMPY2rSAEEGAwC4AAKjKtKRJoCopHZKKeK5A6LJA7CLsRDLsCsbsrlDsLixQrlDotEmMs
qgD8FgAgEAJAcPANFwAVEEgwbZoCAAiKLBJaGK3nKBYCLyIA+xJkI/8QSDD0FBsgCxBAMPUUIC+A
BD/g+RUMLgkAR/AvFgMtsAEusAAuxAAtxAErsAIrxAIkFDkkFDokFDsrElwoEAEuEAL5EAAgAxBQ
-MCoUOPoSWyBKAnhwKfQALvQC+PQBIBAQYDBYr7kvEl4uEl0s8AEt8AAt5AAs5AEq8AMr8AIr5AIq
+MCoUOPoSWyBKAnhwKfQALvQC+PQBIBAQYDBYr70vEl4uEl0s8AEt8AAt5AAs5AEq8AMr8AIr5AIq
5AMo8AUp8AQp5AQo5AUt8Acv8AYv5AYt5AcuEmAtEl8r4AEs4AAs1AAr1AEp4AMq4AIq1AIp1AMv
4AUo4AQo1AQv1AUs4Acu4AYu1AYs1ActEmIsEmEq0AEr0AArxAAqxAEo0AMp0AIpxAIoxAMu0AUv
0AQvxAQuxAUr0Act0AYtxAYrxAf1FUQkEBBQMCoVQSoVISQUXCQUbPQUjCD/EEAw+BVCICAQSDAp
@@ -4502,26 +4502,26 @@ FDwpFD2JIIQnKxJl+BJmIAUQaDD0Qg4oCQA+cPk2rCAEEGAw9jatIgAAULALgAAuMq0Ojkdk4XIv
QDooQDsI/xEI/wKx/y9EOw+PFC9EOoonwrz7JAUgIAJSsFteH4Mn+q3XECACGPBa8bAcrdQdrAse
rdSPIPusAAIAAFDwWvFngycPAgAjPBDaMFrnOv8CAAAAyAag+iwAAAAQWDD8CgAgABBoMFv9+8Ag
0Q8AAAAAAAAbrWMqMrYo0msLqgEJqhH9rcIYACBSMIuMHK2+DbsBDLsCm4wqkG4rkG8IqhELqgL4
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -4530,13 +4530,13 @@ IFP6LAAAARBgMPu8EiAAEGgwW2MfY/7sbBAKKCAFwpX/AgAOASRKEC0hGSsgFhesHSogUyYgB4Un
IQcbquUKCkr2quMbwAQ6oPurMRoJAFqwKjYA+SIALUAEO2D2NgIgMBBAMPg2AyAEEFAw/dgUCYAE
PmD9rD8YCQBWcPk2AS7AATgw+iBTIAAQMDD2NQouSAE8MPY2CC+ABD/g9jYJLgkAe7D2NgouBwE8
MPY2Cy9QBD/g9jYMKUAEOiD2Ng0uCQBH8PY2Di4JAHuw9jYPICAQSDD5NQssCQBrMPw2BisABDqg
-/qoCAAYQYDD7qgIAgAJYsPo2BCBAAlDwWK25wHT6PCYgsAIwsPwKBiIAAFmwWK20+6wYEIkQSDD5
+/qoCAAYQYDD7qgIAgAJYsPo2BCBAAlDwWK29wHT6PCYgsAIwsPwKBiIAAFmwWK24+6wYEIkQSDD5
NCwgABB4MP80NCAQEEAw+DQuIAIQYDAsNDUsNDgsNDn7NC0gARBwMP40MyADEGgw/TQxIHQCUPD+
-qkIQABBoMP00MCIAAFmw/jQ3IIAQaDD9NDYgBhBgMFitm49TilKx+3+7AiqsAYxRjVCaUvtWAyAC
+qkIQABBoMP00MCIAAFmw/jQ3IIAQaDD9NDYgBhBgMFitn49TilKx+3+7AiqsAYxRjVCaUvtWAyAC
AmMw/FYBIEgCW3CbUIonwLD8CgAgABBoMPdGOSBAAlKwW1pMjyf4+sAgQAJz8PgKAC4AQEOw+PUU
IIACc7Ce+Z74KyAWLQr/fbEK+iBTICAQYDBbYgMrIDewu/oK/ijgAVww+yQ3ILgEUnDAINEPjCJk
wN6OIPir3RAIEHgwnxb47hEAARB4MPgWBC4JAHuwnhWOJ/36wCBAAlOw/a0BAAAQeDD/5RQggAJr
-cP3mCSAgAlhw/eYIIAEQYDBbXZLAINEPHKvSLSAF/iAHIAUQUDD4IgAgMhBYMPgWACIAAHiwWLZY
+cP3mCSAgAlhw/eYIIAEQYDBbXZLAINEPHKvSLSAF/iAHIAUQUDD4IgAgMhBYMPgWACIAAHiwWLZc
iics+sDzog4gJhBoMP0kBSBAAlqw/AoAKgBAZvD8pRQggAJa8Jup+6YIICACUrBbW/4tMR2CKrHd
/TUdL0oANKDwABpgLRAYMAAAAAAAAPosAAABEFgwWEDjgilkLycuIAVz6emCKWUv9GP/GQAA+iwA
ADACWbD8CgEgBBBoMFtiSmP/Co8iZf8FKyBT+iwAAAEQYDD7vBIgABBoMFtiQ2P+7GwQBiggBSsg
@@ -4550,19 +4550,19 @@ sAADitEPbBAE/atKEAIQWDArNAAqIBUeq0cYqaL4SREKQAQ6oPqaAgAFEFgw/6tDGgkAWrCaMfAI
BwAgAiDwAERhAERhAERhAERhKCAHCAhB8FURCSAEOiAIVQKVNoUg/zYOIAAQIDD0NgggAxBYMP02
ECCgAiDw/jYPLbAEOWD8NgcgPAA1oC0gFcDh9zRZLEAEP2D+NFgsCQBucP40UCwJAHdwLTYVDOow
CFoR/EUFKgkAWrD6RgMgwAIQ8NEP0kDRDwAAbBAE8yICL/EQIDAEMwGTItEPAABsEATaIPw8AAAB
-EFgwWLMj0qDRD2wQCIdEAZQEiUaLSC9BC45H8kEKIgAAULAPTxT+kxQCAABg8PLoQAYsARAw++1Q
+EFgwWLMn0qDRD2wQCIdEAZQEiUaLSC9BC45H8kEKIgAAULAPTxT+kxQCAABg8PLoQAYsARAw++1Q
Ch8BXDD6uxEHcAQ5oPvdEQnABDog8DMRCAkAajD+nhgMDwEUMPmZVg1QBD9g8xYGIgMBFDD/MxEG
CQBpsP4WBSwCARQw8g5BDAkAH3D+7hEGCQBZsPJCQQABEFgw+CIRDgEAX/D4ZgIILAE4MPKIEA/A
BD/g/+4CD2ABPDD+3QIODwE4MPfnQA7gBD/g/4gCDvAEO6D3ZgIOCQATsPeqChgJAHIw+arfGAkA
-SjCdF/dmAgIAAGhw9hYDKAkASjD4FgQgABBwMFix+dKg0Q8AAABsEATaIPw8AAAAEFgwWLLe0qDR
+SjCdF/dmAgIAAGhw9hYDKAkASjD4FgQgABBwMFix/dKg0Q8AAABsEATaIPw8AAAAEFgwWLLi0qDR
D2wQCAF0BIVFjkTzQgYiAABg8PJCByIAAFCw96EHLBMBdDDzdlgP4AEsMPV4UgpUASww/qlQBBMB
LDDymRAP4AQ/4Pe7EAhABDog9hYFJ0ABPDDxdxEGNAFwMPIzGAgJAFow8xYGKhgBdDDykhQK0AQ+
4PNmEQLgBDig92YCBhIBdDDxdxAOCQAX8P6SUAYJAE3w/mlQDAkAf3D+f1ACwAQ4oP0WByIAAGhw
8rsCBgkARfD+/xAAGBBAMP+ZEA4wAXAw8u4RCAkAfnD4dwIICQBecPlbEQVwBD1g9qqZFAkANXD3
-FgMqCQB28PuZAgAAEHAw+RYCJAkANXD1FgQgABBYMFixsdKg0Q8AAABsEAQUqo3TDypCgNsgW1iC
+FgMqCQB28PuZAgAAEHAw+RYCJAkANXD1FgQgABBYMFixtdKg0Q8AAABsEAQUqo3TDypCgNsgW1iC
+KEcYgAAGrD6Qn8iAABYsPwKACABEGgwW1hX0jDRDwD6Qn8gAgJYsPwKACAAEGgwW1hR+kKAIgAA
WLD8CgAgARBoMFtYTWP/vgAAAGwQBPSqdxAAEEAwHqp2KObUHap1KNbUHKp1KMbUG6p0KLbUGap0
-KgoA+JbUIAwQSDBtmhmJKwSrCo07KbbA8zz8IfgCELD9ttQgAgJSsBiqRChGvcD1L0a8WI2Q8qwA
+KgoA+JbUIAwQSDBtmhmJKwSrCo07KbbA8zz8IfgCELD9ttQgAgJSsBiqRChGvcD1L0a8WI2U8qwA
ABkAtqAoQuXHL/iJQwAeAH4waJMHIkLo0Q/RDwDRDwAAbBAEE6pWKjJ/W1Pz1KD4IQxiAAAqsNKg
0Q8AAAAAKjJ/W1Pt+kkycgAAErBgAEwAAAAAAPoyfyIAAFlw/AoAIAEQaDBbWBn6Mn8iAAAosFtT
4vpBJnIAABKwsVh4KdT6MoAiAABZcPwKASAAEGgwW1gP0lDRDwAAAAAAAPoyfyIAAFlw/AoAIAEQ
@@ -4581,7 +4581,7 @@ EAIFARww+jMRDgkAR/D/ZgEuCQAbsP5kCSAgAmmwBguGAE1nBAuGAE1li2B7tmQuwAGIYSsKgP5t
QAgFAXQw+P9QAgDGAhAep93wDgcCAABysABOYQBOYcCAKMQBLiBQ9AoAIDAAN6CcEpYTE6mI8J4R
DPAEP2D+qK4cCQB3cJ0RHagPYADNAAAAhhP8EgIgARAoMC/AAPj/DHABEBAwKMABeI8BwCDzEgAi
AABTMFsSDB2ni/peFA6AAVQw8PEED+AEO6AO3Qwt3Rwp0n/wXBoP/xBwMP7MAwIAAFmw8CoaCABA
-ZnD6mQIAABBgMPnWfyIAAFDwWLH7wCDRD6tmCqkCB2wCLNazKNK0JRIBDwIAA4gB+FUCAAAQYDD1
+ZnD6mQIAABBgMPnWfyIAAFDwWLH/wCDRD6tmCqkCB2wCLNazKNK0JRIBDwIAA4gB+FUCAAAQYDD1
1rQgEBBAMG2KHfUKACBcADfgJZEADlUC/cgKAAQCSnD1hrUgAgJjMCbWsykgULFE/wIAC/+cyRAp
IA3KTiwgUcCB/EwICAUATjAJyQwsIAwIyBEImQILmQL5hkIBBgBicPP/fWbAAUgwAGP/qhapQGSf
ySwgDCVig/ZieyAgADZgGKj0qMgogN2pialpCZkRqVkpnICJkAaZDGP/shmnlCmSd6yZCZkR8//p
@@ -4590,37 +4590,37 @@ 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
-8Pn/AgAAEGAw/4Z/IgAAUXBYsXvAINEPAAApoAD7CoAowAFMMAuZAimkAGP/kGwQBPkiACIAACCw
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -4628,12 +4628,12 @@ BDug8JkRDgkAe7D4D0oIAwFQMP2IAg8QBD/g/+4CDgYBVDD6jUAO8AQ/4P+ZAg4JAVQw/d0QDsAE
P+AP3QL6f0AKJAFQMP7/EAswBDqg/hIuKgkAcrD/3QIOLAFkMAL/Ef48QA5AAXAw+cwRD3AEO6D6
EjIuCQBTsPwSMy4JAGfw9MwQChAEOqD8EjQqCQBisPkKAiwJAE9wCYgC+BYnLFAEOyD8EjUqCQBi
sP+lCxwJAH9wLRYi/Rx/LHAEOyD8pUYaCQBisP/uAgACAmtw/hYkIAAQcDD8qgINsAQ5oPwSLyoJ
-AGKw+woAKgkAWrD6FiMiAABQsFit3R2mnPaqHGIAADKwLhI60w8PAgD/AgAH/PW/kIcsHKbCJiAN
+AGKw+woAKgkAWrD6FiMiAABQsFit4R2mnPaqHGIAADKwLhI60w8PAgD/AgAH/PW/kIcsHKbCJiAN
/zIMIgAAULD8wT8gARBAMPgSOiYFADIw/09TBtAEOaD2EjguCQA38P0cQCADEFgw/xYXIAAQcDD4
-dwgMACAzMFitw/apuWIAADKwizz9EjggABBwMA8CAP8yASgPAVgw+ypADAEBWDD7CVAGDAFYMP/P
+dwgMACAzMFitx/apuWIAADKwizz9EjggABBwMA8CAP8yASgPAVgw+ypADAEBWDD7CVAGDAFYMP/P
UAbgBDmg9/8QCQAEPmD+zBAK0AQ6oP+IEAoJAGKw/KacGAkASjD5MggqDQFcMP4WHyrQBD7g+/8C
AAAQcDD8wT8qoAQ94PnJUQ4JADfw96YUCMAEPmD2/wIICQBecP8WHSACEFgw+iwACAkAVnD5iAIM
-ACBrMPgWHiDAAmhwWK2X9qkJYgAAMrAuIA0oEjgZpoCLP488jD4sFjAvFikrFjEmkT/5kHwqCwF4
+ACBrMPgWHiDAAmhwWK2b9qkJYgAAMrAuIA0oEjgZpoCLP488jD4sFjAvFikrFjEmkT/5kHwqCwF4
MPkWNioKAXww+xYyKtAEOqD4MRomACBBsPgWKilQBD5g+pkCCgEBeDD/D0AGCQBJsPoWNChHAUQw
+RYzKEQBQDD4FjUgDwA3oBqlIvpmAgABEHgwiTEoIQcsMQoBdAQqEjEtMRsrEjAKnhT+3REO4AQ7
oPq6GAwJAHdw/hI2KxcBXDArFiUqFib+XxQLwAQ/4P+lyhoJAH7wKhIp+clQDlAEO6DwmREOCQB7
@@ -4641,21 +4641,21 @@ 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
-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
+sPoWIyIAAFCwWK0qHaXl8/cgYgAAMrAsEjktEjv+EjoiAABZMPosAAABEHgwW/1I8/cgYgAAMrAo
IRMIqAwoFjlj91CKKiuhAvkWKCJKADbgW0+SHaXTKhY3+hY5IBYANaCKLdMPLKECZMI6W0+LHaXN
mmAuEijTD2ToNIotL6ECZPI9W0+FKBIoHaXGmoBj+B4uEjksIRPz+B1sACBzMMlFY/gchizz+Cdm
ACBJsIks8/gtaAAgXnArEjkqIRPz9/9qACBasIknDwIALJkUFKWq9MBhYEACUnArkglksFYtsAAu
Cip+2QUvsgJ08UP7CgAgAhBgMFtbZRml2BylTZygiyCUopOl9qQcL/8QQDD1pgYgAhBgMPmmBCuA
-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
+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
-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
+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
@@ -4668,13 +4668,13 @@ mR/5EhQrMAQ+4PHMEAggBDog+BIiLAkAQzD07hAIcAQ+YPnuAgjgAVQw/hItLAkAczD8mREMCQBr
MP2kyxgJAGZw/xIcLXAEO+D+ThQI4AFAMP2IEQ4AQGuw/RIgLxAEP+D+WkIO4AFwMPXuEAgJAFIw
+hIqKAkASjD5EiUs4AFsMPgWCy1ABD9g+BIhK5AEOqD9zAIM4AEkMPyZEA0gBD9g/aoCCGAEOiD9
HCAuCQBDsPgSKS4JAHuw/xImKgkAdvD+EicqCQBm8PwSKCkABDog+xYMIAAQWDD9/xAO4AQ7oP+Z
-AgzwBDsg/pkCDAkAQzD8mQIAABBwMPqZAgIAAGGw+RYKIgAAULBYq57WoGZgIIowGaRc+asBDgAH
-TpCKMf8CAAIAcYaQyLaJMQnbUmSwtNog/Ar9IAAQWDBYrMD3pEgfjRBgMPkiAiAOBGKwBqY4jCcP
+AgzwBDsg/pkCDAkAQzD8mQIAABBwMPqZAgIAAGGw+RYKIgAAULBYq6LWoGZgIIowGaRc+asBDgAH
+TpCKMf8CAAIAcYaQyLaJMQnbUmSwtNog/Ar9IAAQWDBYrMT3pEgfjRBgMPkiAiAOBGKwBqY4jCcP
AgAtyRQrzCD6wgkgZgA3YGSQzP8KKiBeADagLqAAf+kLGKQ4LKICeMF6d8FA2rD8CgIgABBYMFtZ
-+BmkNSwSGx2j352giyCXopOllaYmpB0spBz4uxEAAhBgMPmmBCoJAGbw+6YBIgAAUXBYrRjAINEP
++BmkNSwSGx2j352giyCXopOllaYmpB0spBz4uxEAAhBgMPmmBCoJAGbw+6YBIgAAUXBYrRzAINEP
ZJBq2rD8CgIgABBYMFtWAWP/tIcsB5cMY/xrAAAAAAD/AgACAxkOUP8CAAH/n5JQYAY/d8mRY//C
-AAAAAAAAAPwSEyIAAFCw+3wAAAEQaDBYebHHhPasAAYCfUaQZq8KHKQXizDz/vhqAEBm8ADaUPs8
-AAIAAGGwWKzQ2iBYpE3SoNEPAIotLaECZNYCW03Jhi/6FgQgEhBYMPpmCAYAtl3QwYP/AgAGALFF
+AAAAAAAAAPwSEyIAAFCw+3wAAAEQaDBYebXHhPasAAYCfUaQZq8KHKQXizDz/vhqAEBm8ADaUPs8
+AAIAAGGwWKzU2iBYpFHSoNEPAIotLaECZNYCW03Jhi/6FgQgEhBYMPpmCAYAtl3QwYP/AgAGALFF
0MBg9xYTLrkAtaAsIA0dpDqLLIcUiTL3uwgCAABR8Py6OAgAQG5w+zYDKAkAVnCZMvP7zGAAEDAw
KCBcDgRRAEAECAgb/wIAAAIifhAmJQkZotv6IA0gABBAMCgkFPgkFSABEHAw/hYhKgUAU7D+IgAo
ACBNMCmQgPoWIiABEFAwKhYg+hIFKeAEPmD6JQgoCQBNMCkkB/P8vGABEFAwGKOKiS8qIFz4gkAk
@@ -4683,38 +4683,38 @@ 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
-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
+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
-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
+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
-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
+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
-iCCTpZWmL6YEKaQc+6YCIAIQSDD4iBEP/xBYMPukHSgJAEow+KYBIgAAUXBYq6fAINEPAAAAAPyi
-/RASEFgw/SAMIgAAefD6FgAgAhBQMFitW/P2vW/qEFAwAAAAAAD8ovQQAhBQMP0gDCASEFgw/iAN
-IgAAefBYrVFj/9QAACggXA4EUQBABAgIG/8CAAH/jH4QwJD5FiIgABBAMPgWISABEEgw+RYgIAAQ
-UDDz98BgABBwMAAA+woAIAIQYDBbVHBj/yyMLPosAAAAEFgw98wIAAEQaDBYqmHz+PxiAAAysIws
-+iwAAAAQWDD3zAgAABBoMFiqWvP432IAADKw8/oaYgAAMzAcosspEh3+IA0iAAB58P0gDCAAEEAw
-+BYBIAUQUDD5FgAgEhBYMFitJCkSECsSMY6XKhIw/DIFL8AQQDD/7CAgABBoMP3lFC4AQEfw/RIz
+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
-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
+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
-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
+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
@@ -4728,26 +4728,26 @@ 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
-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
+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
-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
+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
-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
+ASIAAFmwWIFZ/KwAAFwANqD6LAACAABZsFh2X4kw8/ztagBAInBkntcdnrsrIAwq0nj90oAgIAA2
YBygD6y8LMDdqcmpqQmZEanZKZyAiZAKmQxj/sAZnq8pknermQmZEfP/6WgAIE9w8/03b+oQIDAc
-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
+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
@@ -4843,8 +4843,8 @@ KrD/Dw9H/4QqIB8AN+DAIPLkJCAAEBAw0Q+KFSmhK7CZKaUrY/7kAAAt4Cb+mz8SAABbsALdEa7d
Hpqkrt0s0oAemv8OzAH81oAgABBQMPq0JCAAEBAw0Q8AjRWPGv3QDCABEGAw+xIAIAAQcDD+9hEi
AABT8P72Ei2ABD9g/bsCAIAQaDD+9FkqCQBu8FgCNmP+CMAg0Q8AbBAEFpqZiTCKKCZif/kISwZI
AUww930BK5AEOqD4jwx2ACBRsPAAB2EAAjnwCQdGKCA20w/+jxx/6hAgMCkgWGSQVSUmE/MmFCIA
-AFFwWKORwCDRD4kwwED6MgEgDgAucGagS3qW1YsxeLYP23D6LAACAABg8Fv+T2AADtpg+ywAAgAA
-YPBb/ZrUoCwgNsDUDcwCLCQ2Y/+j2lD7PAACAABhMFijVMAg0Q8AAAAAAAD6bAACAABYsPx8AAAB
+AFFwWKOVwCDRD4kwwED6MgEgDgAucGagS3qW1YsxeLYP23D6LAACAABg8Fv+T2AADtpg+ywAAgAA
+YPBb/ZrUoCwgNsDUDcwCLCQ2Y/+j2lD7PAACAABhMFijWMAg0Q8AAAAAAAD6bAACAABYsPx8AAAB
EGgwW/7+iTDz/5tiAAAisAAAAGwQBh+ZO5QRkxAUmT0WmMkGJgImRsUCXhH4CoAgABAoMP0KACH/
EBAw+goAIAEQYDD+FgIgCBAwMPtCxi4AIHuwbWojAFEEAMkaebAS8owAAAICUrAv4sIPAgB58AGx
3fVcASACAkIw/woAIAAQGDAE+worsscuEgL4PAAF4AQ/4PYKICA7ADbg9ZkZHgAgcXD1CgAuACAr
@@ -4899,13 +4899,13 @@ B8wKLcL0DQ1PDbsCK8b00Q/7bAACAABQsFv1bWevwmP/ydEPBB4UB+4KLeL0H5fyD90BDV0CLeb0
0Q8EGBQHiAovgvQZl+wJ/wEPXwIvhvTRDylgIgKZEa6ZrZklloAlZRlj/kQAAAAA+kwAAgAAWbBb
9Vdj/p4AACpgIhuYEwKqEauqG5dzq6olpoAlZRlj/uUAAAAAAAAA+2wAAgAAUTBb9Utj/0QAAGwQ
CooyjjD/IDYggBBoMPoEXwwuAVAw+qdBCWABdDD5FgcqLAFUMPqKQQAkAOJwDoZCJm0B8AAHYQAC
-MbAOBkb4l/oQHgB78PmX+RoAFiYQdJsk/PrqIAAQIDAqIFlkoVZkQVMlJhPzJhQiAABRcFigZ8Ag
+MbAOBkb4l/oQHgB78PmX+RoAFiYQdJsk/PrqIAAQIDAqIFlkoVZkQVMlJhPzJhQiAABRcFiga8Ag
0Q8AAPmWCBAEEEAw/woAKAkAQ/D4JDYgAJUrkJ0WnBWbFJoT/xYJJgCXTRDaYPwgJiIAAFkwW/84
KCBZ+UwSIAEQcDD5JRgg7AA2ICsgJhyWCQy6Ef4kWCoAIGKwLKI6/wIAAgHgRyAflgYtojkPvwov
8pf/1AEOAdZ/UCshBxyXAAsLSgy7EQy7AptAKSIAGJbQ+JkRAAMQWDD6FgIoCQBecClGAfAIFwAQ
AkkwAAmKHZX1/UYEIBgQYDD8RgUiAABQsFrpaxiW7ysiES4iEvohGCIAAEqwjBf+RgsvfxB4MPoq
FAgJAEZw/H1ACMABYDD13REMAEB7MPlGBisABDqg+RIJKgkAUvD6RgoowAQ6IPhGBywJAGsw+UYJ
-LQAEOyCcSIkiwOEOmQKZIogSwPMvhjnwACBgARAgMAAAAAAAAMDA+lwAAgAAWPBYn+rAINEPAAAA
+LQAEOyCcSIkiwOEOmQKZIogSwPMvhjnwACBgARAgMAAAAAAAAMDA+lwAAgAAWPBYn+7AINEPAAAA
wECJFf8CAAIAz0Jg/ZeWEgB0EeCPFhiXjSkgJvkWCCABEFAw/hIIIgAAWfD5nQMtIAQ6YP0gDCwA
IGsw8OEECgUAPrD+lWAeDAC5oMCg+BIJLgUAWjDAsQC7GvqPOQuABDtg8LsRCgkAcrD/bhpgARBw
MCggDQYNRP+/AggJAFIw8AAPbgkAR/AK/wL9bIAuCQB+8BqVugDRBPDrGg//EEAw+JVEGhEARvAA
@@ -4935,10 +4935,10 @@ EGgwW0PEIyRf0Q8p4HXAwfpCHiACAkpw+eR1IAEQaDBbQ70blj0qQCLTD6urK7DgZL+9W/P4IyRf
ICYn8nuJKCbygP0kJyYAID7w/s1QB5AEPeD3ZggJkAQ+YPYWASYfAXQw/uZQAgBBC5AsIF8o8nv6
8oAgoARrMJMT8/J3LgAgTrD78gAoACBC8AmIEfO7DAoAIEKw8xIDIBwAD7CaEP0WAiFEADcgLvB1
0w8PAgCw7v0WAizgAXAw/vR1IRcANyAtJF/6LAACAABZMPx8AAIAAGmwW/8uwMD6XAACAABY8Fie
-S8Ag0Q8iMQSOEfyV/RAYEFgw/uAoIgAAaLBYoCkflA8PAgAPAgD0lCcQjgR4sPQgZWEsEEAw+RIB
+T8Ag0Q8iMQSOEfyV/RAYEFgw/uAoIgAAaLBYoC0flA8PAgAPAgD0lCcQjgR4sPQgZWEsEEAw+RIB
KgAXlhApkCX6EgEg9AA2YCqhE3ojB4wRDysRK8UTjREt0h+N3GTQ6fP/kWAAEGAw8/+Jb+oQYDCL
-ESuwKGSw5IwRsb0NDUf9xCggBBBQMPyV3xAYEFgwWKAMY//KAIsRK7AoZL/JjBEtvP8NDUf9xCgg
-BBBQMPyV1hAYEFgwWKACjhEu4Chl756IEcCk/JXREAAQeDD/hCUgGBBYMFif+okRKZIfipxkoKuL
+ESuwKGSw5IwRsb0NDUf9xCggBBBQMPyV3xAYEFgwWKAQY//KAIsRK7AoZL/JjBEtvP8NDUf9xCgg
+BBBQMPyV1hAYEFgwWKAGjhEu4Chl756IEcCk/JXREAAQeDD/hCUgGBBYMFif/okRKZIfipxkoKuL
nWSwpooRC7AAY/9wACqiHvwKACABEGgwW0M/jRJj/tku8HXAwfqiHiACAnOw/vR1IAEQaDBbQzeK
EBuVtyqgIqurK7Dg/RICLrEANuBb83GNEmP+pIwRwNH9xCUr8AQ8oCvFE2P/C48RLvAiAu4RpO4u
4oIu9Gdj/wKPES/yH4/8yfOLEcDQ/bUTIAEQYDAstCUrsChj/vyPES7wIgLuEaTuLuKCLvRnY//X
@@ -4947,10 +4947,10 @@ k1oQChAoMPuIEQAcEEgwCYgCKEbBG5NY/AoAIDIQaDD6k1QQARBwMPVGwyAAEHgwW0Xh1qDzk1IQ
AFmuoByVgylCwiogL/zCACosAUww/BYAKgAgDvArsADA0vwK5yABEHAw/KoBC9AEPuD6JC8qCQBa
sPokLyAUAG5wLSUgYAACLiUgLyAhDwIADwIA+/8RAAUQQDAI/wIvRsEbkzb8CgAgMhBoMPqTMhAB
EHAw9UbDIAAQeDBbRb/2oEBiAAAqsMCA2YAaky8tQsIcky79q0AMCwFsMP3JOQgFAFqwCYgC+CUe
-IgAAEXDRDwDApPsKFCIAAGDwWJ+A0mDRD9ww+goEIBQQWDBYn3zSUNEPAAAAbBAEwLDyAkcAHxBg
-MP0KASIAAFCwWHO/ykj9MQAiAABQsPsKACATEGAwWHO6+iwAAAAQWDD8Ch8gABBoMFhztcAg0Q8U
+IgAAEXDRDwDApPsKFCIAAGDwWJ+E0mDRD9ww+goEIBQQWDBYn4DSUNEPAAAAbBAEwLDyAkcAHxBg
+MP0KASIAAFCwWHPDykj9MQAiAABQsPsKACATEGAwWHO++iwAAAAQWDD8Ch8gABBoMFhzucAg0Q8U
kwX7KREAExBQMAqZAilGwRqTAhuTA/wKACAyEGgw/goBIAoQQDD4RsMgABB4MFtFjGagCStCwis1
-AGP/qgDApPyS+RAUEFgwWJ9WY/+ZAGwQBiogIfscAAAAEGAwW//X+ZUlEAASLqD4EQAgTgI84AmI
+AGP/qgDApPyS+RAUEFgwWJ9aY/+ZAGwQBiogIfscAAAAEGAwW//X+ZUlEAASLqD4EQAgTgI84AmI
ASgVACogIfscAAABEGAwW//O0qDRD9Kg0Q8AAAAAAAAA+hEAIg4AOOBpM9f+OxEKAEBKsAuqAioV
AGP/xmwQBNQg/AooICYQWDD4PBZgJRBQMHoxLXsxW/8CAAYARuTQxirRDy0gQ/8CAAYATGdQ/wIA
BgBVX1D/AgAGAG9XUMAg0Q8qICH9ks4QABBYMPwKACAAEHAwWALBwLD6ICEgFxBgMP0KCCAIEHAw
@@ -4958,68 +4958,68 @@ WAK80qDRDwAAwLD6ICEgGBBgMP0KASABEHAwWAK19qCIYgAAErAqQCH7CgAgEhBgMP0KICAgEHAw
WAKu0Q8qICH9krMQABBYMP6SsRAAEGAwWAKowCDRDyogIf2SrBAAEFgw/AoAIAAQcDBYAqHAINEP
KiAh+woAIBgQYDD9CgEgABBwMFgCm/agHmIAABKwKkAh+woAIBIQYDD9CiAgABBwMFgCk9Kg0Q/R
DwAAKCEYzYQqICH9kpgQABBYMP6SlhAAEGAwWAKKKkAh+woAIBcQYDD9CgggABBwMFgChdKg0Q8A
-AABsEAQclL39ICIgBRBQMP4hHSAYEFgwWJ7iKCAhE5J9wHoLiBEoNsEaknz7knwQABBgMP0KMiAB
+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
-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
+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
-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
+UnBYAjtmr5UlIR3ApfySYxAYEFgw/SAiIgAAcXBYnp0F7ED0bAAEABBYMPy0OQAUAEFwHZI4DUQC
JSAh0w8PAgD7VREABBBAMAhVAiU2wRuSLPwKACAyEGgw+pIoEAEQcDD3NsMgABB4MFtEtfagYmIA
ADqwKTLCJTbBGpIoCpkBCUkCCQlPKTbC+5IdEAAQYDD9CjIgARBwMPqSGBAJEEAw+DbDIAAQeDBb
-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
+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
-DGrBDm0ICArqMAqaDGqhAmP/8NEPwKH8ke0QFBBYMFieQ9EPAAAAbBAE2iBb/+BnoATSoNEPAPog
-ISAAEFgw/AofIAEQaDBYcoQTkdUWkdn2r95gChAoMCggIfuIEQATEEgwCYgCKDbBG5HQ/AoAIDIQ
-aDD6kcwQARBwMPU2wyAAEHgwW0RZ96EZYgAAIrDApPsKFCIAAGGwWJ4l2kBmr5D6ICEgABBYMP2T
-+BAfEGAwWHJqZq96KSAhJwoYDwIAC5kRB5kCKTbBG5G4/AoAIDIQaDD6kbQQARBwMPU2wyAAEHgw
-W0RB96D2YgAAIrDApPsKFCIAAGGwWJ4N2kBmrzD6ICEgABBYMP2T4BAfEGAwWHJSZq8aKiAh0w8L
-qhEqNsEbkaL8CgAgMhBoMPqRnhABEHAw9TbDIAAQeDBbRCv3oSBiAAAisNxg+goEIBQQWDBYnffa
+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
-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
+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
-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
+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
-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
+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
-YgAAErDAofyQfhAUEFgwWJzV0Q8A0Q8AAGwQBCkgIRSQbfuZEQABEHAwDpkCKUbBG5Bs/AoAIDIQ
-aDD6kGgQChBAMPhGwyAAEHgwW0L19qAOYgAAErAqQsIKKkCaMNEPwKT8kGEQFBBYMFicvtEPAABs
+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
-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
+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
-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
+EHAw+pASEAkQQDD4RsMgABB4MFtCn/agF2IAABKw0Q8AwKT8kA0QFBBYMFicbtEPAMCh/JAPEBQQ
+WDBYnGrRDwAAbBAGF5AA+SwAAgAAETD0MExlsAQ6YJIRA0kCKXbBInbCGo/6G4/7/QoyIAEQcDD/
+CgAgABBAMPh2wyIAAGIwW0KE96DAYgAAErDApPyP8hAUEFgwWJxTYABLAAAAAAJLAit2wcCqKnbD
+G4/p/AoAIDIQaDD6j+YQARBwMPIWASAAEHgwW0Jy96AVYgAAErDApPyP4RAUEFgwWJxCYAAGACxy
wiwVAPgRACAALSygx58JVQMFhQH0MFdl4AEsMANKAip2wYkRKXbC+4/REAAQYDD9CjIgARBwMPqP
-zBAAEEAw+HbDIAAQeDBbQln3oGxiAAASsMCh/I/MEBQQWDBYnCXRDwDRD4IRwLMrdsNj/1gAjhHT
+zBAAEEAw+HbDIAAQeDBbQln3oGxiAAASsMCh/I/MEBQQWDBYnCnRDwDRD4IRwLMrdsNj/1gAjhHT
Dw8CAA5OAi52wQVtAi12wsDJLHbD+4+5EAAQYDD6j7YQMhBoMP4KASAAEHgwW0JD96ARYgAAErDA
-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
+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
-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
+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
-RsMgABB4MFtB92evh2AAIsCk+woUIgAAYfBYm8Mi+rnRD8Ck+woUIgAAYfBYm7/SMNEPwKH8j2QQ
-FBBYMFibu9Iw0Q8AAGwQBhqPnSktAiuQFyyifSqigKvMCcwRrKoqohrykNcQgBB4MPmQFiA9ADag
+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
-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
+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
@@ -5039,15 +5039,15 @@ AQoAAVww+yIRC5AEPuD8qgIKCQAW8AuqAio0ASlgAfk0ByAAEBAw0Q9sEAQajnkpLQIrkBcson0q
ooCrzAnMEayqKqIQ/o+zEAgQaDD5kBYgABAQMPSgQmCAEGAwhaEiogL2ogAgEwA2YGiRGMuRaJEC
aJI/xirRD6zqqroqoMBoowJpp+ZoRkX/AgAGAFSFIPhIbW/qEBAw0Q/RDwAAAAAArOqquiqgwGij
yGinxWiiAmmnv/8CAAYAWAEg/wIABgByBSDy+uooAF8BINEPZCBdLCAA/AxCABACUPD8zTkACgJY
-sP00ByAIEGAwWJFnKjwQ/AoIIBoCWLBYkWTAINEPymouYAD+DkIAEAJQ8P7tOQAKAlmw/TQHIAgQ
-YDBYkVsqPBD8CgggGgJZsFiRV8Ag0Q8AAGRf9i9QAP8PQgAQAlDw//05AAoCWXD9NAcgCBBgMFiR
-Tio8EPwKCCAaAllwWJFKwCDRD8skKCAMuDr4jTkACAJYsP00ByAIEGAwWJFDwCDRD8lmKWAMuDr5
-nTkACAJZsP00ByAIEGAwWJE7wCDRD2Rf+CxQDLg6/M05AAgCWXD9NAcgCBBgMFiRM8Ag0Q8AbBAE
+sP00ByAIEGAwWJFrKjwQ/AoIIBoCWLBYkWjAINEPymouYAD+DkIAEAJQ8P7tOQAKAlmw/TQHIAgQ
+YDBYkV8qPBD8CgggGgJZsFiRW8Ag0Q8AAGRf9i9QAP8PQgAQAlDw//05AAoCWXD9NAcgCBBgMFiR
+Uio8EPwKCCAaAllwWJFOwCDRD8skKCAMuDr4jTkACAJYsP00ByAIEGAwWJFHwCDRD8lmKWAMuDr5
+nTkACAJZsP00ByAIEGAwWJE/wCDRD2Rf+CxQDLg6/M05AAgCWXD9NAcgCBBgMFiRN8Ag0Q8AbBAE
Go4SKS0CK5AXLKJ9KqKAq8wJzBGsqiqiEPKPTBCAEHgw+ZAWID0ANqCNoYyi/qIAIBQANmBokRnK
mmiRAmiSOMYq0Q8AryqquiqgwGijAmmn5WhGNGhHOPhISW/qEBAw0Q/AINEPryqquiqgwGijz2in
-zGiiAmmnxmhGPGhHWfhIRG/qEBAw0Q8AZcBawCDRD2Tf+LQ6/AoEIAICW3BYkQnAINEPZO/ktDr8
-CgQgAgJbsFiRBMAg0Q/JyIvA+zYBIAAQEDDRD8jqjOD8NgEgABAQMNEPwCDRD2Tf+I7Q/jYBIAAQ
-EDDRD7HL/AoEIAgCUPBYkPTAINEPbBAEGY3vwrP3j9YZIAQ4oPmICAAiEFAw+Y/RHABkgWD2CmAg
+zGiiAmmnxmhGPGhHWfhIRG/qEBAw0Q8AZcBawCDRD2Tf+LQ6/AoEIAICW3BYkQ3AINEPZO/ktDr8
+CgQgAgJbsFiRCMAg0Q/JyIvA+zYBIAAQEDDRD8jqjOD8NgEgABAQMNEPwCDRD2Tf+I7Q/jYBIAAQ
+EDDRD7HL/AoEIAgCUPBYkPjAINEPbBAEGY3vwrP3j9YZIAQ4oPmICAAiEFAw+Y/RHABkgWD2CmAg
QARRcPtRaH/qEBAwKoKFG4/MC6oBKoaF0Q8AAAAAAADyCgAgCBBgMNMPbcowACAEAw0bf9clAhVA
8gRABeAEPWDyLxQECQApMPL/EQWABDkgpP+n/47xBu4CnvGxIsAgI4KFFI+3BDMBI4aF0Q8AAPIK
ACAIEDAw0w9tajIAIAQDCxt/tycCH0DyDkAP4AQ/4PItFA4JAHuw8t0RD4AEO6Cu3andLNKABswC
@@ -5057,9 +5057,9 @@ Av2GhSAAEBAw0Q/7KUR/9xAwMPIKACAIEHgw0w9t+jIAIAQDBBt/RycCHEDyC0AN4AQ7IPIqFAoJ
AGbw8qoRC4AEPuCrqqmqJaKABlUBJaaAsSItgoUejXAO3QL9hoUgABAQMNEPAGwQCCUgIhqNaCMk
XyQkLS2ieyqigPyNIRwAIC9w+Y9oHZAEP2D/jlUSACBusCgxIP4xHSDAEDgw+40aEAAQMDD6MR4g
QBAgMP/tAQgAQEow+DUgJgCEX1Bx5xBxpw3wABJiAEA7sAAAAAAAAPIKACYAhn9Q/2wADABAP7D9
-vzkADgBnsAz/ApIRHI9O+hYAIAgQWDD9XAAABRBQMFiZXfoKgCA2AGSwKTEgKDBwJzAtBJkCKTUg
+vzkADgBnsAz/ApIRHI9O+hYAIAgQWDD9XAAABRBQMFiZYfoKgCA2AGSwKTEgKDBwJzAtBJkCKTUg
8AAGZgBARfDAcPgnIHAAEHgwKTEgKDBwLzAtCpkCKTUg8AAJbgBAR/AAAAAAAP8WBCIAACPw8jBf
-IAQQUDD8jzUQGBBYMP1cAAIAABnw9xYAIgAAcLBYmUH0IFRvABB4MByNTQJbEay7KLKCD4gBCEgC
+IAQQUDD8jzUQGBBYMP1cAAIAABnw9xYAIgAAcLBYmUX0IFRvABB4MByNTQJbEay7KLKCD4gBCEgC
KLaCLrKED+4BDj4CLraEKrKAHI2tHY0h8tY5CgBAYrAGqgL6toAgABAQMNEPAAAAAAAAAPIKgC3/
fH6QY/8MhBT9CgEiAAAZ8AfTOfP/n2QFACNwD6gB/wIAD/942hDz/ulgQBAQMABsEAQejS78jTEf
IAQ8oPuMvBAAEEgw+AoAL/8QaDDwAAlgARBQMLGZaJRJD5UKrlUlUsPyCgAv7wA1YAuWEW0IMAAh
@@ -5068,9 +5068,9 @@ ACBAADVg9gqAIIcQSDBtCC0AIQQApxp3UBgLbwIvxrMuwrT9fwMPoAFwMP9VAQgBAHIwsWb2kwlw
AgIQsMhRY//LIlruCII50Q8AAGwQDo0whDH7jgoQARBgMPYgIiAAEDgw9ARfADoAL3D5jtUQKRBA
MPoKAyoAecEQCUkKiZAKkAAA3HD7jZIQAFMnUIQxBARf/wIAAgB6BSDAyPTDbHAnEFAwGY31bkZh
KiAiK5J/KZKCq6oJqhH9MAgqACBScIqn+qIOJqkAN2D/AgAABAiHYP8CAAIEEINg/wIAAgQYh2D/
-AgAEBB4DYP8CAAQCVIdgwKT8jrMQGBBYMFiYwvAALG/qEGAwAAAAAAB6QS8cjq7+ICMiAABpsP8g
-NiACEFAw9BYAIBgQWDBYmLfGyvpcAAIAAFjwWJbOwCDRDwAsIh8PAgAPAgCMycnB+iwAAgAAWPAL
-wADz/9RiAABisPP/zG/aEGAwAAAcjpj+ICMiAABpsP8gNiACEFAw9BYAIBgQWDBYmKBj/6IuICv+
+AgAEBB4DYP8CAAQCVIdgwKT8jrMQGBBYMFiYxvAALG/qEGAwAAAAAAB6QS8cjq7+ICMiAABpsP8g
+NiACEFAw9BYAIBgQWDBYmLvGyvpcAAIAAFjwWJbSwCDRDwAsIh8PAgAPAgCMycnB+iwAAgAAWPAL
+wADz/9RiAABisPP/zG/aEGAwAAAcjpj+ICMiAABpsP8gNiACEFAw9BYAIBgQWDBYmKRj/6IuICv+
D0AAPAB/sH7nFn3nE3znEC0hIA0KRfAAD2qABDqgAAAA/SEgIAAQUDD5CgAgDwA34H7nB33nBHzn
AcCRHo6B+HwADgcBbDD/IR4oBQB7sB6MLdZw/3dAAgAAIfD+jCkWBQA7sJ8e90wADgYBfDD/5DkO
EAQ+YA+vAvhEAg4JADfw9CAkLgkAJ/ANaED4tzkEsAQ5IPYgIyQJACHw9CAhLgkAJ/D4ZhEFAAQ5
@@ -5078,7 +5078,7 @@ IAZEAvQgIC4JACfwLiAsC0QR9CEcLgkAI7AkNQb/IR0uCQB7sJ4yLzUHHo5cKCEZKDUI9yA0IAAQ
MDCWNpc3JCA1JDQSLyAvLzQTKCAirogogOD2CoAgABA4MP4SDigBAUAw/jULJgUAQfAmNBRj/oQo
IENljnz7TAACAABQsFhYJo0w8/3EYgAAYrAAKSIfhDIqIRz6FgYnAgA2YCvqAAurAvoWBiwDeibQ
HI48iBYvIDYpIR0uICOUEpgQ+RYBKKABSDD4FgkoJgFIMJgX+YhACCkBTDCZFPgWCCAFEFAw+CEf
-IBgQWDD4FgMiAABpsFiYN4oZBAtF+xYKIEgIWrCMFwRtQX3JF44YBI9Af+kPBJtBZLa2iBT/AgAG
+IBgQWDD4FgMiAABpsFiYO4oZBAtF+xYKIEgIWrCMFwRtQX3JF44YBI9Af+kPBJtBZLa2iBT/AgAG
A1jeEIoW+woBJgAQSDD7JC4uAR/WUASbQWSyNIwU/wIABgEX3xAsIh8swhT7FgwjuwA3INogC8AA
ixzwA69iAABisCwiH4zJZMHt+iwAAgAAWPALwACNMPP802IAAGKwLCRt8/zIYgAAYfAqJG3z/L1i
AABh8Ps8CCIAAFCwWE4ajTDz/KhiAABisPP8oGIAAGHwKiAhKLJ9KTAIJLKCqoj7jBIZkAQ6IP+X
@@ -5104,29 +5104,29 @@ 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
-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
+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
-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
+LNaAKkUZY/umHIyELyA2LiAjiRaZEPghHSACEFAw9BYCIBgQWDD4FgEiAABpsFiWh/P9N2/qEFAw
+AAAA8/0sYAAQUDAcjHcvIDYuICOIFpgQ/SEdIAIQUDD9FgEgGBBYMPQWAiIAAGmwWJZ4Y//BHIxt
+iRYvIDYuICP0FgIgAhBQMP0WASAYEFgw+RYAIgAAabBYlm6KHWP80QAAbBAGLjEL/SIAKHQAO6Bo
+6xDAo/yMXhAIEFgwWJZlwCDRDxyMW442jzeJOJkQ+DIJIAMQUDD4FgEgCBBYMFiWXMAg0Q+ONv8y
+ByADEFAw/IxREAgQWDBYllbAINEPAAAAbBAEwCDRDwBsEAQrIAccikYLC0EMuhGsqiiiOv8CAAIA
mEIgHYpELKI5Db0KLdKX/cMBDgCQbxAbihPwCwcCAABI8ABJYQBJYSghBxmKPQgISv2LQRnABDog
/4o4GAkASjAoNgD8IgAgCBBwMC42A/82AiACEEAw+MkRDAkAazD8NgQoCQBGcPk2ASFgAnrwLvJ/
KyEJ+KY5IAAQYDD68oAh/gJzsP72fyABEGgwWzlyiieOIvv6wCBAAkqw+5kBAAAQIDD0pRQggAJK
-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
+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
-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
+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
-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
+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
@@ -5134,45 +5134,45 @@ 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
-O6D4FQwuCQB7sC4WAy0gBA8CAPocISQC2Ydg/AoDIKICWLBYjBcqHCX8CgMgnAJYsFiMFBOKISgi
+O6D4FQwuCQB7sC4WAy0gBA8CAPocISQC2Ydg/AoDIKICWLBYjBsqHCX8CgMgnAJYsFiMGBOKISgi
FiMyiQmIEagzizfDzywkBYu+KrBwLLBxCKoRDKoCsaoqtHEKihQqtHDAkPkUOSCAAlBw+RQ6IIAC
-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
+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
-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
+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
-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
+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
-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
+ACAyEFgw/zAFIgAAYXBYlCr7CociAABQ8FvD8vNMAA/UALUggyn7IgsgSAA04M28kytgADLaIPsc
fyAIEGAw+7wxIAIQaDBbM23AINEPibsPAgAPAgBkkAr5kgsiAABacGWf9JO7mzzAwPwmCSAAEBgw
i2pyuQqDKY0onWpgACAAAMmwirhyoQz7rAAACQA2oIqocqnyyLcjIgkuIggutgj7IAUgABB4MJ8o
+yQwIEYAtOCIK8+MxJP/AgAGANZO0BqJDIsgLqJy+qKMIAAQYDD+uwwAARBoMFs3QRyIaIvOw9/9
JAUh/gJa8PvGDiAAEBAw0Q/E4v4kBSAAEBAw0Q8AAGRK1P8CAA/9aNqQikcqrBBbOZgsMRyOMy4m
-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
+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
-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
+FlcoIATTD/qscSQAb4Yg/AoDIKICWLBYisj6HQEiAABZsPqsdSADEGAwWIrD+x0BIAEQeDAvtIjz
tI0gABBwMP60iSIAAFEw/rSKIAsQYDD+tIsgAhBoMP60jiCwAlrwWBm4w4n4JAUgABAQMNEPAAAA
-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
+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
-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
+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
-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
+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
-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
+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
@@ -5198,7 +5198,7 @@ h/MDSggCAXww+pkQA8AEPOD5YQgiCQBM8P8PQQIJAETw87YALwAEP+D/h8EYCQB+cINg9bYGIAAQ
QDD4tgUgMBBQMJqznLL1mQIDgAQ84Pm2BCIJAGzwk7Es4AcPzAL85gEgQAIa8AIOhgBDYwAOhgBD
YYpnJbxA9RYXIEACUrAlEhf7EgwiAABhMFs40/0SESIAAGFw9KYBIgAAGrD6bAACAABY8FgvKYpn
KqwQWzdM2mBbMkpj/iMAAMisjBSbFSvAOLG7K8Q4ixUsEhSdGfsWBSAPADcgLhITLeBcsd0t5Fwc
-h5MvYTeOYI0g+BIJIAIQUDD4FgAgMhBYMFiRholnK5kU9LL1YEACUnCLmYyw/IxXADQQcDD8FhIm
+h5MvYTeOYI0g+BIJIAIQUDD4FgAgMhBYMFiRiolnK5kU9LL1YEACUnCLmYyw/IxXADQQcDD8FhIm
AcH3EMDw/xYQIAoQaDAqYQgrYBb4Cv8j/xBgMPyqDAAGEEgw+p04ADIEQvCMG50XKmBBAMyOWz0l
/RIHJFwANqAYhWgMXxGo/y7yOv8CAAoAo++QGoduKfI5CloKKqKv+p4BDgCZ1lAbhTUuFhifH/AL
BwIAAEuwnRcASWEASWEASWEASWEASWHwCaACAAArsPpsAAIAAFuwW/3aLGEILTr//wIABgC6bxAu
@@ -5206,18 +5206,18 @@ EhLD9P8CAAYAsP+QiWcomRRkgkmLmR2HVhyE8CqwBy6wEomw/RIHLAUAc3D5iVcKCQBisPkWEiDA
AmFw+rYBIgAAUbBYLtAvEhLDgvYWCiYApkfQw6X2FgomAKFX0IwajMeHFvv6wCBAAlMw+6sBAAAQ
aDD9xRQggAJa8JvJm8j7PAACAABhMFs4YmP8hgAAAI0dZNKc/wIAAAFqB2D6EggiAABY8PxMAAAW
EGgwWDVzLSAE8/vmYAAQODDcQP0KhCIAAFjwWDVtHIcqjjKPM4kgmRD4IAUgAhBQMPgWASAyEFgw
-WJEawCDRDwCKYocW/RYHIr4ANqArYQgsOv//AgAGANFm0C0SEsPk/wIABgDH91CJZy+ZFPTx2mBA
+WJEewCDRDwCKYocW/RYHIr4ANqArYQgsOv//AgAGANFm0C0SEsPk/wIABgDH91CJZy+ZFPTx2mBA
AlJwi5klsAeMFfsKACIAAGlwWzTLimfbMPqsICIAAGEwWzg0jGCLZwjMEQxMAvymASBAAlLw+xIF
IgAAYXBbOC1j+7OJZ2WcL2P6hy0SEGXenIcWiR+IFyiWOS4gFi8K//YWCif/bn+QKmBB+2AWIDwQ
YDBbPHeWGmP+xAAAAIUaKlEUJVESwGD6FhYutAA2oPpywyIAAFlw/AoAIAEQaDBbNDEocsSxVQhV
-LigSFrFmeGncY/6JyKiLFCmwQLGZKbRAKxIUyLktEhMs0GSxzCzUZI1i+hYIIBgAN2Da0FiP0dug
+LigSFrFmeGncY/6JyKiLFCmwQLGZKbRAKxIUyLktEhMs0GSxzCzUZI1i+hYIIBgAN2Da0FiP1dug
/Pr/IgAAUbBbO3WKGMTa/WQFIA4ANqCPFC7wQbHuLvRBLxIUZP0PKRITKJBlsYgolGVj/QHz/Q1g
ABBYMPP7YWAAEFgwiWJkkXdk4K/7EgwiAABhMFs702P6uAAA8/20YAAQWDDIqIsUKrA6saoqtDor
EhRkvL8tEhMs0F6xzCzUXmP8scTbLWQFY/ypxOouZAVj/KHz+zVgABBYMC8SEGX+boln+PrAIEAC
UnD4qAEAABBYMPuVFCCAAkIw+JYJIgAAYTD4lggiAABY8Fs30GP6QAAAAAAtsAf8EgUgABBYMFs0
XvoWECA8ALag8/xxYAYQaDDz/ihgABBYMPn6wCAAEFgw+6UEKABATrD7EgwggAJKcJmh+aYAIgAA
-YTBbN7xj+e7EqiokBfP8NGAKEGgwjzOOMvyGjxAFEFAw/SIAIDIQWDBYkIGLGMi4jRQs0DmxzCzU
-OS0SFGTdPy8SEy7wXbHuLvRdY/0xAAAchoOOMo8ziiCaEIk3mRP4MgYgMhBYMPgWAiAFEFAwWJBw
+YTBbN7xj+e7EqiokBfP8NGAKEGgwjzOOMvyGjxAFEFAw/SIAIDIQWDBYkIWLGMi4jRQs0DmxzCzU
+OS0SFGTdPy8SEy7wXbHuLvRdY/0xAAAchoOOMo8ziiCaEIk3mRP4MgYgMhBYMPgWAiAFEFAwWJB0
ixjIuI0ULNBDscws1EMtEhRk3PkvEhMu8Gex7i70Z2P86ytcGPpsAAABEGAwWzx3Y/00nh76bAAA
MAJZcP0SESABEGAwWzxximeOHvP+a2BAAlKwAADz+jBgABBIMIti9xIGLQQAtuArYEH6bAAAARBg
MPu8EiAAEGgwWzxjY/zmAAAAAABsEAiTFPogByIAAEEw9TIAIgAAIXApIAQoFgL1BUcKIAFQMPoW
@@ -5228,15 +5228,15 @@ QRiFMS0gBQmbCfy7EQBOEDAw+4gIAFAQcDD4gn8gKARzcPbRDHBWEFgw/wIADgFXW1AbhhkWhgz6
3hQMwAFAMPiPQgwHAUQw9KoRD0AEO6D2RgcgeAIxcPZFCykABDpg+YPwHVAEP2D4/xEMCQB3cP/M
AgoJAFqw/cwCAAAQWDD6RgYoCQBiMPtFCigJAEow+EYEIJACeLDyDxYAQAJxMABOY/ohKiAAEGgw
LUQxLUQy/UQzIAAQYDAsRDUsRDYsRDcrRC77RC8gABBIMClEMPpELSAAEEAwKEQ0CooUKkQsLyBX
-L0Q7D48UL0Q6D48U/0Q5ILgCWLD/jxQABBBgMP9EOCB4AlEwWIbb9hYBIMACQLDzCBYAgAJJMABJ
-igAIiAAJiiwiHIsULERTDIwULERSDIwU/ERRIKgCUTD8jBQAYAJa8PxEUCIAAGFwWIbK/iB0LgAg
+L0Q7D48UL0Q6D48U/0Q5ILgCWLD/jxQABBBgMP9EOCB4AlEwWIbf9hYBIMACQLDzCBYAgAJJMABJ
+igAIiAAJiiwiHIsULERTDIwULERSDIwU/ERRIKgCUTD8jBQAYAJa8PxEUCIAAGFwWIbO/iB0LgAg
LTAu9FgnNjkrIBYtCv8PAgB9sQgqIEEsEgFbO0WIFCkKSCkkBSiAEg8CAGSOJBSDzyMiBwSEKPpM
AAAgAhjwWsj7/YNWEgAAYTD+hL0SAABasP8iACIAAFDwWsixgicPAgAiLBDaIFq+hP8CAAH+8p6g
YADMixP6LAAAARBgMPu8GCIAAGnwWzu1wCDRDwAAAAD6LAACAABYcP0xCCIAAGDw/goAIgAAeTBb
IUktCoh9oV6KEPYSAi2aADagiqfbMPqsICIAAGGwWzbDjBCNwJoU+N0RAgAAGrD9bQICAABY8P2m
ASIAAFCwWyB33qD6EgAgFwA3oNsw/GwAAgAAaTBYMrTAINEPAADz/P9iAAASsNog/BICIgAAWPBY
M8nAINEPjyJl/SorIEH6LAAAARBgMPu8EiAAEGgwWzuIwCDRD9ogWr5tE4OtC6gR9KBBYgAgRPDA
-IQzqMCsyhYuwI6z//LsIAgAAUPBYkZ0chCAqwn8AMQQAKxoLqgIqxn9YkdPAINEPxcIsJAVj/U0A
+IQzqMCsyhYuwI6z//LsIAgAAUPBYkaEchCAqwn8AMQQAKxoLqgIqxn9YkdfAINEPxcIsJAVj/U0A
AAAA+goHIAEQWDBbNdMtMn/9NoMgABAQMNEPbBAEHYM+KS0CLpAXL9J9LdKAr+4J7hGu3Y3X+goA
IAEQKDD5MA0hMAIScP3SDiAGEEAw/zAOIYAQcDBtihStrK7MK8DdLMDXe8Mn/LNVcAICUrApMA1k
kHppkUPK8Io0i6HJvMtom6AqIH8LQADAINEPAMqSaZEnyPQtMA9p0d2KNIyinKCLNCU0DSogf4uw
@@ -5246,32 +5246,32 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-N6D6EgkgARBAMChEDGP/cv8WByAFEFAw/IREECQQWDD9PAACAABxcFiOK4sVGIQ8K7ACwJH4WAoA
+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
-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
+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
-ByAFEFAw/IPcECQQWDD9PAACAABxcFiNvRiDzw8CAA8CAAhYCiiCfwM6AvsSByAAEGAwC4AA+RIQ
+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
-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
+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
-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
+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
@@ -5289,26 +5289,26 @@ NfZREiIAABDw/C0CIAAQGDD9wBcgGQA2IClQSdMP0w/6CgEgCgA2YCtQXQujORqAji6ifStQIimi
gPRQIS4AIGuw/yAAL5AEO6D4IAwoACB2cImXmBifGYmeLyABLiANKZ0C+ZBVITACYzD0VCAgnAA1
IJQTnxeeFisWBPkWAiBYAD0g/BYFIgCMASD/AgACAKoFIP8CAAQAuYEg/wIABADdhSD/AgAGAOwB
IGhBM29FAm9CGWhFc2hGE4oT8qz/IAEQSDD6VCEiBQAScNEPwLHyCgAgARBgMPxUISIFABLw0Q+N
-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
+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
-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
+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
-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
+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
-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
+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
@@ -5321,41 +5321,41 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+AADAQPUtAiABEDgw9VyQIAAQEDAqHBD7PAAAAhBgMFiApSoRCPqZRgsAAVQw+JFGYgAgEvBrlSDw
kAQCAA6iYAQIG/CRBAIAQv4QAHgaCEQC8AAMZOABIDApUh+xmSlWH7Ii8gJPAAQCWvD2I6VyACBc
8MAg0Q8AkAQECBvwkQQAsAD+MAB4GghEAvP/0mTgASAwAP8CAAf/r82Q3UD8f6YSAABxcPooCAIA
-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
+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
-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
+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
-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
+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
-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
+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
@@ -5365,7 +5365,7 @@ ACAAEEgwmRv5FgogBRBAMPUUNS+ABD/g/xYMLgkAR/CfGWP/lAAAbBAEGnxULCAMK6J3KqKArLsJ
uxH5fFEaACBasCihKfx8ORD6BEowjieO7hh8TR98Sy3tAvV8nBCgAltw8AwHAgAASvAASWEASWEA
SWEASWGJIP/mliAEEGAw9eaaKYAEPmD45pQoCQBmcCnmlSigBy+hKQgIQQCIEQj/AgX/Av/mmCDg
AktwAgOGAEljAAOGAElh2dD0lIYgAhBoMFsnndEPAABsEAooUBhogQfAINEPAAAAACtcGvwKBiAg
-AlBwWH9DuEv8ChAgMAJQcFh/QPwcGCIAAFCw/35sECACcHD9PAggAhBIMPkWACIAAFtwWwljwCDR
+AlBwWH9HuEv8ChAgMAJQcFh/RPwcGCIAAFCw/35sECACcHD9PAggAhBIMPkWACIAAFtwWwljwCDR
DwBsECAqIgeLOCcyAfWiDiABEDAw9Pr/IAgQQDDwsQQGAEBF8PiwIWIAAElwLV0ELNAAAGsaBLsD
C8sBCwtH+9QAIAcANyBks5sskr79e/wUAS8DII7Sj9GI0JgQnxGeEo3TnROLExp76Y0SjhH/EgAg
IAJgcJ/AnsGdwioWNJvD8AoHAEACSHAASWEASWEASWEASWEYe+IZe+0ae+uaGCkWCSiC7I4zLhYL
@@ -5385,11 +5385,11 @@ GSigB/l7RBggAUAwAIgRCLgCCYgCKBYcD+owLxYd/PrwIDAQcDD+FT8mAEDlUCscf/u8ASAgAklw
CAmGAEtpBgmGAEtnLApj/BSWICkANOAvMRMvFKCOK3HmBSghGygVUY4zLhYrjDIsFiqLNSsWLYk0
KRYsKxxg/AoHIAIQaDBbJpHz/gRgABBoMJY20Q8qrBBbLOuJJ4meY/xWACqsEFss5/P9r2AAEGgw
H3scLxYg+yIAIAAQcDAuFiP+FiIgBRBgMP0UlSuABD7g+xYkKgkAZvArFiFj/2oAbBAIJiL9C+ow
-F31W0w8PAgAoco//AgAKAKBG0B16uSt2jypyjv3SMSAAEGAwWIek/XswEAAQYDBYh6EnLQQnfPT7
+F31W0w8PAgAoco//AgAKAKBG0B16uSt2jypyjv3SMSAAEGAwWIeo/XswEAAQYDBYh6UnLQQnfPT7
FgcmAH+10Bh9R5IU+BYFIKACQjCYFmAAJAAogBj9mQwOACAb8C7gAACQBAgIGw4OG3jhXoYg/wIA
BgBkNdDybAAAEgA1YC5iAvoSByAOADugeuNBhiTIQXRp2PY/FAAAEFAwbfkcoq390BguACAasC7g
-AP8CAAACAlKw/wIADgBD65D2DUIIACAT8PkKCC+LALdg0Q8AwKX8EgUgMBBYMP8SByIAAGmwWIbr
-jBaNZo5nj2j4YgkgBRBQMPgWACAwEFgwWIbkGn0XjCGGICqibpbAjSCLJYqk/NYBIAAQSDD5JgAg
+AP8CAAACAlKw/wIADgBD65D2DUIIACAT8PkKCC+LALdg0Q8AwKX8EgUgMBBYMP8SByIAAGmwWIbv
+jBaNZo5nj2j4YgkgBRBQMPgWACAwEFgwWIboGn0XjCGGICqibpbAjSCLJYqk/NYBIAAQSDD5JgAg
ABBgMPkmASABEGgwWyonjBQrwvywu/vG/C//oDHQwCDRD/7TBn//EFAwwKFlryBj/2wsco6xzCx2
jmP+uABsEBCJJxp6qImei6Iokr6MoY2g+qIDJACugiCbEpwRnRCaEx56lYkSjxOKEfsSACAgAkBw
m4CagZ+DmYLwDgcAQAJIcABJYQBJYQBJYQBJYRh6jhl6mRp6l5oYmRkoguyOM54bjTItFgr8MgUg
@@ -5403,16 +5403,16 @@ lwD1NgYgABAQMNEPKrwQWywZlDz1NgYgABAQMNEPbBAELiL9CuowF3yVKHKQ/wIACgBoxpAvLQQv
4gRkQAJ02e79NRQAABBQMNMPbVkUrqv7sBgsACAasCzAAPvJWnACAlKw/QtCCgAgcXD7bAwPqgC2
4MziwCDRD4jhKnJvi+CbgIngiqSL5fiWASAAEHgw/+YAIAEQaDD/5gEiAABj8Fspgiwi/LDM/Cb8
IAAQEDDRDwAAAAAAAAD8swZ//xBQMMChZa9pY/+ZLXKPsd0tdo9j/ycAbBAG/nwAAgAAOPCXEQvq
-MBN8Vigyj54QGnm7+zaPKgC6xtBoUCAtojH6Mo4gABBgMFiGpP16MBAAEGAwWIah+nmxFAAgXXBo
-YB0rMo8tojH6Mo4gABBgMFiGmv16JhAAEGAwWIaYq2b6LAACAABZ8PxMAAABEGgwW/7i86wAACMA
-NqD6CgUgMBBYMPx8OhIAAGjwWIYClTL2NgMiAAAQ8NEPwKX8fDUQMBBYMFiF+y4i/P8SACR8AT+g
+MBN8Vigyj54QGnm7+zaPKgC6xtBoUCAtojH6Mo4gABBgMFiGqP16MBAAEGAwWIal+nmxFAAgXXBo
+YB0rMo8tojH6Mo4gABBgMFiGnv16JhAAEGAwWIacq2b6LAACAABZ8PxMAAABEGgwW/7i86wAACMA
+NqD6CgUgMBBYMPx8OhIAAGjwWIYGlTL2NgMiAAAQ8NEPwKX8fDUQMBBYMFiF/y4i/P8SACR8AT+g
y/YpIv4afCqNkSqibouQm9COkIqki5X95gEgABBAMPiWACIAAGIw+JYBIAEQaDBbKTorIvywuysm
/Cwi/G/FcxN8GyMyboo0LaECzNbwABZgABBQMFsk/Is4+qoKAgAAQrALqguYpfOsAABJADagKS0E
laKWo5SkjHGcp4wQi3Cbpopzmjn9cgIh6AJKcP02CCAoADcgLiL9LSL8k+GeMJkx8yb9IAICa3D9
JvwiAAAQ8NEP0jDRDwAAKCL+LyL8k4CYMZkw8yb+IAICe/D/JvwiAAAQ8NEPAAApMo6xmSk2jmP+
gwBsEASEICgwBiUwByJCEAiIEQhTAvNFGiAOADSg8yUaIAAQEDDRD8Ag0Q8AAGwQFicwAgvqMBp6
-s9MPDwIAKKJ//wIACgJgRtAdeUcrpn8qon790jEgABBgMFiGMv15vhAAEGAwWIYv+hwAAgAAMvD7
-PBAgEBBgMFh8pSUwBykwBCgwCCswCSwwBSowCvC7EQiABDog+zAGKAkAWjD0MAsrgAQ6oPDMEQiA
+s9MPDwIAKKJ//wIACgJgRtAdeUcrpn8qon790jEgABBgMFiGNv15vhAAEGAwWIYz+hwAAgAAMvD7
+PBAgEBBgMFh8qSUwBykwBCgwCCswCSwwBSowCvC7EQiABDog+zAGKAkAWjD0MAsrgAQ6oPDMEQiA
BD5g/JkCC4AEPuD6RAIECQBdcPhEAgQJAE1w+TADIAkANWBoUAGlZSwQAPRACWD+EGgwaEABpGT6
Cv8mAIRvEP8CAAYAflcQeJcgZFEJ+iwAAgAAWHD8fAACAABpcP5MAAAAEHgwW/9UKTAD/wIAAABo
ZlApIskPAgD+CgIiAGF2UC8is/8CAAAAW/vQLBAA/wIAAgBWclAoCv7/AgAGAGTHEPMtAyoATKVQ
@@ -5433,71 +5433,71 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-EAgkIgf8eZcQBRBQMPRCDiAwEFgwWINVKDAV+TAUIACLniBlkQ8qMDj8Cv4kAISeoCswFi0wFyow
+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
-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
+0C1wBC9wBQjdEQ/dAv3PQgoADWuQHnbv//wDLWABbDDw8QQMCQB3cADdGitCtfpCtCAAEGAwWISA
+wKX8eW8QChAoMAW1LPsKMCIAAGlwWIMuKHAaKXAbCIgRCYgCZYB0KUL6LUL5+jqAIAEQMDD3FgQg
2AA6YIsni74svQQswAAA0AQMDht/508N3gkL7gou7QMv4YIu4YMP7gx16z8pQvoAkAQMDxv/AgAA
-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
+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
-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
+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
-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
+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
-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
+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
-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
+C4b7FgggUAJSsPAKogAgAkhw8AkWAHACQbD5FgkgBhBgMPAIoAAMAljw9GYSIJgCUbBYeQ6lO/xM
+AACkAlGwWHkLjiJl72z6LAACAABZsPwKCiADEGgwWsD1wCDRDwAAAAAAAP1MAAAFEFAw/HhCEDAQ
+WDBYgfnAINEPAGwQCv5AECIAAFDw/0ARIgAAWTD4QCogARAwMPlALC+ABDug//r/LgkAe7D05QgC
APOaIMCEbYoPLbAuLKBgsar7vAEuAPJjUIsg+7w6IgAAUTBtmQ8tsAAsoEaxqvu8AS4A2+NQjSD8
-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
+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
-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
+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
-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
+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
-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
+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
-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
+IDAQWDD+IhAiAAB4sFiBPSoiEMDh/woAIAAQaDD5CgAgLAA2oCsxCiyhG/wMSwtgAVwwDLsMC6k4
Ce84D+049d9FYgUASnDAINEPAADz/+hgABBIMP3DBn//EFAwwKFkr379IgAgBRBQMPx3chAwEFgw
-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
+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
-OwqKFPpUOiAAEBAwKixO/AoDIEACWPBYd+UrTEj8CgMgogJQsFh34ooniq60O/qseCAGEGAwWHfe
+OwqKFPpUOiAAEBAwKixO/AoDIEACWPBYd+krTEj8CgMgogJQsFh35ooniq60O/qseCAGEGAwWHfi
0Q8oIrYSdhAZdeQiIn8JiAEJiBH+dkMSACBAsIwsHXTmDswBDcwCnCwrUG4sUG8IuxEMuwKxuytU
bwuLFCtUbmP/jwAAAPyzBnIAAFOw2vBlrvRj/xVsEAQoIGr6LAAAARBYMPwKACAkEEgw+SQFIAIC
QjD4JGogAhBoMFsHXNEPAGwQBNMPbUoPJyAAJDAAsTP0eQhwAgIQsMAg0Q/0cwh//xAQMMAh0Q/R
@@ -5509,63 +5509,63 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+cvqijCAAEGAw/rsMAAEQaDBbIwbAINEPAADRDyqsSPwKAyDQAliwWHa69RIAIgAAWTD8CggggAJQ
+8Fh2tdtQ/AoIIHACUPBYdrL0EgIg2AJQ8PwKBiCAAliwWHat20D8CgYg5AJQ8Fh2qsLL/DQFICQQ
WDD7JAUiAABQsFuy4NEPACKWJGP96AAAbBAEEnXsAzUJDFURpSIiIn/TD8oh8wocJWABIDBtCAkm
IARzYQaCKcgsY//vKCEZCAhLeEnv0Q/AINEPbBAIKCA1JSA0LSAz8iw4JYAEPWD4VQICAHCPYP8C
AAAAbKdg9AoAIPUANWAoPCD4FgIgMAJI8PkWASAUAlDw+hYAICACOPD3FgMgCAIw8PYWBCAPEDgw
-8AASYAsQMDAAKyABpLTysgoKAFopEC0gAGjSHGjUKWjWNnbRRXfR4MCi/HXAEDIQWDBYf2jGKtEP
-ihT8CgYgBAJYsFh2aGAASIoT/AoGIAgCWLBYdmRgADgsIAItIAMIzBENzAIsNQBj/52KEPwKBiAE
-AliwWHZbihH8CgggGAJYsFh2WIoS/AoDIBICWLBYdlUtIAGk1PLSCgv/va0QYAAja9UH/wIAA/+S
-D2D/AgAF/44HYMCi/HWeEDIQWDBYf0XGKtEPwCDRDwAAAGwQGhh0Egg5EfkWACAVEEgw8AgXABAC
+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
-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
+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
-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
+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
-YDBYdZT6LAACAABYcPwKBCACEGgwWx3g0Q8AAABsEAoqICYWc6APAgAKqAkMiBHzIAcmACBBsCht
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -5573,40 +5573,40 @@ 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
-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
+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
-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
+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
-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
+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
-e/a7CAB0AlDwWHK8wNP9NEEgBBBgMCw0QCRAJgRLCQy7Eft7CABAAlBw9rsIAAYQYDBYcrGIGPBE
+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
-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
+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
-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
+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
-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
+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
-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
+IgAAULD8CgsgAhBoMFgBB8LbLSQF0Q8A2hD8CgMgnAJZMFhyALQa/AoDIKICWTBYcf1j/wIuECDA
8g/uAi4UIGP/kwAAbBAE0w9tSg8nIAAkMACxM/R5DHACAhCwwCDRDwAAAAD0cwh//xAQMMAh0Q/R
DwAAbBAEhDQSb/oPAgD6bsYUcAEgMARECQxEEf6idyIAICCwLS0CLdAAKqKADwIA/t0IAAEQYDD0
-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
+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
@@ -5616,12 +5616,12 @@ KJUa0Q/aQFgE4IRJZU/JY//RAAD6LAAAABBYMPwKACAAEGgwW/vtGm8eKqKMK6ECZL7VWxmNG25E
HG5X+m8ZEgAAcrAZbuUswmsqooeNn67M8AsHDZAEOyD93AEqACBisP2WDyBAAmqwAE1hAE1hAE1h
AE1hAE1hAE1hmhEoIBYsIQctIA3+IAwgARB4MC+kBC6kDC8gBy4gJi2kDSylBw7rCf1wrBvABD7g
/qRTKgAgXfArsiArphUopBYvpAcupFOSqP2lFiARADTg2zD6FgEiAABhMFutKiwgJoMRG23jDMwJ
-DMwR9G68GgAgZvD7vR8gsAJQ8Pu8WiAGEGAwWHFFikstoQJk0AxbGVeOTAKvEa/uLjYYKSAmCZkJ
+DMwR9G68GgAgZvD7vR8gsAJQ8Pu8WiAGEGAwWHFJikstoQJk0AxbGVeOTAKvEa/uLjYYKSAmCZkJ
DJkRqXkqkiRkoGuJqciZ+ZIJIgAAUnBln/STqfU1FyAAEFgwmzn7NgogJBBQMPo0BS26ADTgjDeM
zo3F+sIEIAICW3D2NRkqAA5q0C3BGvvGBSACAnKw/sYEIAICa3AtxRrRDy/BGpvF+sYEIAICe/Av
xRrRDwAjliRj/54AAGwQBhht3PhRCXAAEFAwwCHRDwDbMPxMAAIAAGlw+hYAIgAAcfD/HAACAABQ
sFv8+GWv2ooQG28V+KDSYCYQYDAvslwJqhGq+o6nju4t4Rix3S3lGCmgBfyRHXAlEGgwLaQFLLF/
-/c8HcAAQEDDRDwBb/DbAINEPAP2iACAyEFgw/HBhEAUQUDBYeffAIdEPAGwQEi0gDC8gB4swKjAY
+/c8HcAAQEDDRDwBb/DbAINEPAP2iACAyEFgw/HBhEAUQUDBYefvAIdEPAGwQEi0gDC8gB4swKjAY
HG4q9DATIgAASTD5FgcgAxBwMP4WDiIAAEFw/sJnIgAAKPD4FgYmAgFQMPzCcCrgAVww/t0IDiAB
fDD/FhEtkAQ/YPsWEiwAIGsw/BYQIzsANuD5CsAiAFv2kP8CAAQAV4EgKbxMmRAnnB8HRxQpIAQP
AgBrlgf/AgAEAbOKYCsgFigK/3ixGYkWKiBB9MkaCOABTDCZHFslgf8CAAAFqiqgGW/PGm2a+G3C
@@ -5630,12 +5630,12 @@ ZOZEKBIQj4ICKgL8EgcgARBIMP0SBi4JAE/w/4YCIgAAWPBbIojSoNEPmRBj/1QAAAAAAAAA8AoH
AgAAQbDTD215AgBIYSwhBx1tpw8CAAwMSgzMEfoSACwJAGswLGYAKyIAHG2f+mYDIgAAULD8ZgIr
gAQ+4Pt7AgIAAGEw+2YBIgAAWXBa6I0bbq8sIEEabc0dbXqDLSqicC4hIv4WFiOQBDzg/lAYIgAg
VPCTGCMyCC3SdwzMCS8wDAzMEf4eQAoAIGbw/hYKLAAgf3D7sn8tkAQ/YPsWFyoAIGqw+hYJIAEQ
-YDBYT/YpEheMNyggBS0SFvzCDiBQEFgw/BYNIBwEWjDE7n6BBMXyLyQF+iBBKkgBTDD5DkYOBwFM
+YDBYT/opEheMNyggBS0SFvzCDiBQEFgw/BYNIBwEWjDE7n6BBMXyLyQF+iBBKkgBTDD5DkYOBwFM
MP3YFA1ABDtg/W7YGUAEOiD5CgAvUAQ/4PllCiuABD7g+225HgkAW7D4/wIAsBBAMP/uAgsABDqg
-+GULKgkAcrD9zAIKCQBasPxmBiCQAliw+mYEIEACUbD6FgsgBhBgMFhwXSwgQRts8gzMCQzMEay7
-+70fIEwCUbD7vFogBhBgMFhwVR9uuvts8xCAEGAwLGQ2+2Q3IBAQSDD5ZC4giRBAMChkLP9kLSAB
-EGgw/WQzIAIQUDD6ZDEgABBQMCpkMC0wBMHs/wIABgQL91AqbDz8ChgguAJYsFhwPypsVPwSEiBg
-AllwWHA8wOL+ZDUgABBwMC5kNChQMA8CAGiBLSgWFfsKJiAkEEgw/QrKIgQAAiD/AgAEAdUCIPgW
++GULKgkAcrD9zAIKCQBasPxmBiCQAliw+mYEIEACUbD6FgsgBhBgMFhwYSwgQRts8gzMCQzMEay7
++70fIEwCUbD7vFogBhBgMFhwWR9uuvts8xCAEGAwLGQ2+2Q3IBAQSDD5ZC4giRBAMChkLP9kLSAB
+EGgw/WQzIAIQUDD6ZDEgABBQMCpkMC0wBMHs/wIABgQL91AqbDz8ChgguAJYsFhwQypsVPwSEiBg
+AllwWHBAwOL+ZDUgABBwMC5kNChQMA8CAGiBLSgWFfsKJiAkEEgw/QrKIgQAAiD/AgAEAdUCIPgW
FSQEJQYgLwpR/wIABgHSfhCLHYyxirD6rQEgAgJjMPy2ASFoAlKwmrApEhP3ljkkAIKGIP8CAAQA
jgEgKyAWLAr/0w98sQ0sEhL6IEEgeAJjMFskni4SEI3ix/4P3QH95gIgABAQMNEPAAAA8/zgYAgQ
ODD/AgAF/pEBICwSEQzLEai7KxYTK7I6d7MTCc0KLBITLdKvLMI5/cYBCABn6xCOImXtIisSEfos
@@ -5650,17 +5650,17 @@ BIgR9GyJHgkAJ/D+bpkYCQByMJ5n+GYGLgkAfPD4EhIuCQAn8PQSBCAAEHAwLmUK/2YEIHgCQjAo
ZQsIBIYASWkoISr+ZC8gABB4MC9kMS9kMv9kMyAAECAwJGQ1JGQ2JGQ3KGQt+IgUAAAQIDD0ZDAg
ABB4MC9kLvhkLCAAEHgwL2Q0LiBXLmQ7Do4ULmQ6Do4ULmQ5Do4ULmQ4KLABJLAAJKQAKKQBJBIY
LrADL7AC/6QCIIACSbD+pAMgwAJAsAIIiABJigAIiAAJiigiHChkU/wSEiIAAFswCIgUKGRSCIgU
-KGRRCIgU+GRQIKgCUbBYb2MrEhL6IHQqACBdsCq0WCkSE/eWOSICLoUgKFASDwIAZIVLFGxsgycE
+KGRRCIgU+GRQIKgCUbBYb2crEhL6IHQqACBdsCq0WCkSE/eWOSICLoUgKFASDwIAZIVLFGxsgycE
hCj6TAAAIAIY8Fqxmf1r9BIAAGEw/m1bEgAAWrD/IgAiAABQ8FqxT4MnDwIAIzwQ2jBapyL/AgAB
/lYeoGAFiQAAAAAA8/nBYgAAEnCMHSrBILGqKsUgYAAMaITvjh0s4SKxzCzlIitkNf8SCiACEFAw
KmTJKmTIih8pZDn7jBQACBBwMPxkNCoFAHuwKmQ4LjAEwfz4FhUv/hD7kIsYDWoI+7xsIAYQYDBY
-by4oEhVj/AYAAAAAKxIR+iwAAAEQYDD7vBgiAABp8FskNWP5oR9sH59i/2xYEEQQcDCeY44tL/Jw
+bzIoEhVj/AYAAAAAKxIR+iwAAAEQYDD7vBgiAABp8FskNWP5oR9sH59i/2xYEEQQcDCeY44tL/Jw
Ce4R/BYBLgAgd/CP9y3Sf/0WAiBQEHAw/fIOIDIEcjDE7vwWASAeBHIw/BYBIFIQeDAvJAWIEo4T
+A9GDEgBQDD4eEANgAQ7IP7cFA4JAGfw9YgRDUAEOyAMiAL4a/MeCQBH8A8/Agj/Ap9kH24NHG4A
+FINL0AEO6D8ZgcuCQB7sJ5m/hIEIHgCQjD4ZQsgABBAMChlCi/gASzgACyUAC+UASjgAy/gAi+U
AiiUAyzgBSjgBCiUBCyUBS/gByzgBiyUBi+UByjgCS/gCC+UCCiUCSzgCi7gCy6UCyyUCikhKilk
-LQmJFClkLCggVy0WFChkOwiIFChkOgiIFChkOQiIFPhkOCAYEGAwWG7dIxIUixH8ChAgsAJRsFhu
-2Rxr0/xmGiAIEGgwLWYbKyB0K2R0KhITG243J6Y5ii4pYhfAgPmcQCYAi16QHWwBLdJwCa4Rrt2N
+LQmJFClkLCggVy0WFChkOwiIFChkOgiIFChkOQiIFPhkOCAYEGAwWG7hIxIUixH8ChAgsAJRsFhu
+3Rxr0/xmGiAIEGgwLWYbKyB0K2R0KhITG243J6Y5ii4pYhfAgPmcQCYAi16QHWwBLdJwCa4Rrt2N
143eLNACKtAAJtAEK9ABJ9AF+GYRC4AEOqD70AYqCQBasPfQByYJADmw+KoRB4AEOaD70AMmCQBZ
sPyqAgeABDmg+KoRBgkAObD7qgIGACAycPlrBnoAIFIwsaov0A0r0Akq1AMm1AcKjBQGjhQu1AYs
1AIm0A4q0AgMjBQOjhQu1AUs1AEOjhQu1AQu0AwMjBT81AArgAQ6oPzQCi+ABDug+6oCDgkAe7D/
@@ -5671,32 +5671,32 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-+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
++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
@@ -5708,43 +5708,43 @@ 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
-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
+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
-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
+AUAwKBYW+RYAIAUQUDD4FgEgMhBYMFh07itxfyoSF/w6/yCqAHbw/RIWIMQEYrBo1ihkQEj8EhQi
AABZMP8KhCIAAFDw/0UIIAEQcDD+NBUgABBoMFgYCmAAIi0SFIo3wMAPAgD73AAAQAJSsFsYmPP/
vmIAACKwKzr/e6EOgztlPxmDK/AAJ2AAEDAwjTf++sAgQAJjcP4KACwAQHMw/tUUIIACYzCc2ZzY
Y//PAAD7IgwgKQA04Mq0KbILDwIADwIAyJ5tCAn5kgsiAABacMiRY//vk7ubPJYr0Q/RDwCTLJYr
0Q8AAAAbaO4VaJyPMBhom5gUlRb4/xEABBAoMPsWCi4JAC/wnxUuMAcODkEA7hEOqgILqgL6Fggg
AxBwMAnqMBhrABtrAJkZ9hYLKAkAQzCYHI9Anh0mFD3/Fg4glAJQcP8iACAGEGAw/xYRKgAgX3BY
-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
+a6L7HBAiAABQ8PwKBCACEGgwWxPqY/2LAABsEASJJ8Cg/PrAICYQWDDzkg4gQAJCcPskBSgAQGIw
+pUUIIACQjCYmfiWCCAgAlJwWxo6LTEdgiqx3f01HSAuADSg8AAZYC0QGDAAAAAAAPosAAABEFgw
W/8fIiIJyCsuIAVz6emCKWUv9NEP0Q8AbBAaGGlIKQoV8AgXAgAAQHBtmgIACIodat0cat0E3Dks
-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
+FgCLIPk6/yABEFAw+RUIIAsQYDD6FBgrgAQ+4PocGSoJAGbw+xYBIAMQYDD8FBMgogJY8Fhrais8
+TvwKAyA6AlBwWGtnKgoAKhQxKhQy+hQzIAIQWDD7FDAgZgA1IB9pkCgiDfoWKiADEGAw//J/IHAC
cHD6FDMg/gJIcPoUMimQBDog+xQwLgAgR/D6FDEgcAJb8PMLFgCAAlBw8loeAIACQ/DxCBYAkAJb
-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
+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
-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
+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
-AFP60CwgBf8CAA4ATiMQiy0qYlwJuxGrqoqqyan7rGAg/gJQcPqsKSAEEGAwWGr2KhIqYAAHAAAa
+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
-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
+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
-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
+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
-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
+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
@@ -5757,9 +5757,9 @@ gAQ5oAxmAghmEQpmArFmJpRjBoYUJpRiBoYUJpRhBoYUJpRgKVAF/wIADAGaSND/AgAMAZZaUCPi
G9jg+VwAD/8QIDD4MxEACBBQMG2qDyuQNCqAZLGI+ZwBLgQSUtD4XAAACBBIMNMPbZoSKoA8KeBc
se4PAgD4jAEuBApKkPMWASIAAEFw+goDIAgCSHDTD22qDyuQACqATrGI+ZwBLgQCUtAbZ0+4GPAL
FwAVEEgwbZoCAAiKGmjl+hYCIKICWXD4IgAgAxBgMP86/yALEHAw/RQgIAMQSDD5FBstgAQ+IP8V
-DCwJAHdw/RYDIEICUHBYaW8rXE78CgMgSgJQcFhpa/tncBAAEHgwLxQ7LxQ6/xQ5IAIQSDApFDgr
+DCwJAHdw/RYDIEICUHBYaXMrXE78CgMgSgJQcFhpb/tncBAAEHgwLxQ7LxQ6/xQ5IAIQSDApFDgr
slz+Ig0gAxBgMPkUOCCAAmhw/xYsIP4CUHD/FDsvkAQ7oP8UOioAIHbw/xQ5IHACQvDzCBYAkAJ4
-cPJfHgCAAnLw8Q4WAGICUrDyHR4AkAJa8FhpTy4SLPscCCIAAFCw/o4UAAsQYDD+FhQgAhBoMFv4
+cPJfHgCAAnLw8Q4WAGICUrDyHR4AkAJa8FhpUy4SLPscCCIAAFCw/o4UAAsQYDD+FhQgAhBoMFv4
TtEPL5BQJpBRDwIA/JBSL4AEP+AG/wL2kFMvgAQ/4Az/Agj/EQb/ArH/L5RTD48UL5RSD48UL5RR
D48UL5RQKVAFKhYv+BYuJgEn3lD6Fi8gPxAwMPgWLiYC87ZQ+hYvIEQQWDD4Fi4mARfeUPsSLyIA
AFFwWAMH+KwAAyQANqDaIPwSLiIAAFlw+A5HAAcQaDBb/s/7CooiAABRcFgCadEPLpBYL5BZCO4R
@@ -5785,7 +5785,7 @@ ymsQHWYhLdF//wIAA/zDe1DaUFgBIdEP2iD7XAAAABBgMFv8mC5wfWXpZ/saciIAAFDwWAf70Q/a
IPwSLyIAAFlwW/zOLxIvL/AC/wIAAgDSa9AoEi+Ig/8CAAH+Pu4Q2lBYAQ7RD9og/BIvIgAAWXBb
/MLRD9og+1wAAAAQYDBb/IDRDwAAAAAAAPsSMSIAAFDwWAEujTcPAgCN3inQUCrQUfvQUimABD5g
CpkC+tBTKYAEPmALmQIImREKmQL0Ei4gAgJKcCnUUwmJFCnUUvmJFAADEGAw+dRRIAoCITD5iRQC
-AABZMPnUUCCcAlDwWGfg+hx/IgAAWTD6rDUgAxBgMFhn2ysSLRxnRhlmRAuLFCsWLYg8+YgBDAAI
+AABZMPnUUCCcAlDwWGfk+hx/IgAAWTD6rDUgAxBgMFhn3ysSLRxnRhlmRAuLFCsWLYg8+YgBDAAI
ZtAcZ0IMjAKcPGAACAAdZOINjQKdPNog+zwAAAMQcDD+NFQiAABh8Fv9ONowWApi0Q/aIPtcAAAA
EGAwW/xKinhb/C3RDwAAANog+1wAAAAQYDBb/ET6fAAAARBYMFv7W9pwW/sZ+3IIIgAAUfBb+vnR
DwAAAPsSLyADEHgw/1RUIgAAUXBYAZD4rAAAeQA2oNog/BIuIgAAWXD4DkcABxBoMFv9WPpcAAAA
@@ -5793,45 +5793,45 @@ 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
-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
+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
-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
+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
-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
+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
-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
+CQBmcPkWASADEGAwWGbkKhwd/AoDIJwCWLBYZuDzFDIiAABQsPscAAAgEHgw/xQwIAsQYDD/FDYg
EBBwMP4UMSAIEEgw+RQ0IBQQaDD9FDMgIhBAMPgWECACEGgwW/XRw4ooJAXRDwAAbBAEKiw0/AoI
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -5841,7 +5841,7 @@ MPkmrSAFEGgwC4AAKSKtCYlHyZ0qQDorQDsIqhELqgKxqipEOwqKFPpEOiAAEBAw0Q8AKCK2EmMl
GWL5IiJ/CYgBCYgR/mNYEgAgQLCMLAMNRP3dEAwAQHMwDcwCnCwrQG4sQG8IuxEMuwKxuytEbwuL
FCtEbtEPAAAAbBAE0w9tSg8nIAAkMACxM/R5DHACAhCwwCDRDwAAAAD0cwh//xAQMMAh0Q/RDwAA
bBBAhDQSYub1YgYUcAEgMARECQxEEf5SZyIAICCwLS0CLdAAKlJwJCJ/Dt0I+d0RAAEQYDD9qggC
-AABZMFhENy0wTC8wTf4xLiIAADKw9yKDLYAEP2D/3QIAARBYMP7PQABMAE+wZHSW9BZuIAAQEDCE
+AABZMFhEOy0wTC8wTf4xLiIAADKw9yKDLYAEP2D/3QIAARBYMP7PQABMAE+wZHSW9BZuIAAQEDCE
emVA8mUgaod5ZX/yYABfAAAAAAAAAPQWbiR0ADXgIgoAhHpkQEGMSs3HzyiESWVP9PwWBCA9ALSg
YAAtziaMyGTP5orJZK/zbQgKKKE2fYEMiqtkr+Vj/+4AAAAAAPKsAA/cADagnBTMJod5ZX+xZCQb
FGHPhS0kQnAJVRGlRIVIKTBUh0eMV/dyDiAAEFAw/MIOIABZBmBpklgtMS9u3woYY/7/AgAKAINq
@@ -5852,87 +5852,87 @@ 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
-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
+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
-+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
++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
-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
+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
-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
+MPgWAyAFEFAwWGyJ0Q8npFQupAUqEnNYBh7aIFsNMy1QBPphUBAcEHgw/9lUcAMQODAoUgr/AgAO
AiAiECkScymQMP8CAA4BxTJQBEsC/hJzIAgQYDBtyhUvsEAi4Dz/AgAOAjt4kPu8ASACAnOwLxJz
xOT+9AUgLBBoMC1EBdEPAIJH06D6YdIQIAIQsFqlqxxh0B1gBh5hz49A+6wAAgAAULBapWOCRyIs
ENogWps2/wIAAAKshqCIWnSJGoJJySXaIPsKUSAAEGAwW/ELginTDw8CAGUv6PtiqhIAAFEwW+0N
AAONKB0B+IwILQAQSDD5FkAgFRBIMG2aAgAIiiodAfhhrBCQAlkw+BZCIAMQYDD9QgAgARBwMP6k
-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
+ICP/EHgw/xWMIAsQcDD/Em0tgAQ/YP+kGywJAHdw/RZDIEICUrBYYz8YYAstEm0sHQEnxD/5wAIg
YhBwMC7EOCvAAR5hhi3EOS3EOv3EOyBKAlMwK6QBKaQCG2FpGWGULMAALKQAj0AiQgcogvj5YWge
CQBP8PIiDiAFEGgw/+Y+IgAAUTD55j8gBBBgMAuAAB9hci/yPw+PR2TxUyggOikgOwiIEQmIArGI
KCQ7CIgUKCQ6+2KJEgAAUTBb7M/CnClEBdEPK/GADwIADwIA+ioAKyABXDD7FQor/f9akCwScC4S
bykScgAMiwBJYQBJYQBJYQBJYRphWRlhUSmmPy6mPixAbi5AbC9AbyhAcClAbS1AcfiIEQ8ABD/g
-+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
++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
-+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
++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
-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
+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
-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
+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
-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
+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
-HGDvLWBOLmBP/2BQIAUQUDDzFgAgMhBYMFhqcvt60CIAAFGwWAghZK/GKGIWImRUKWAFKWQwInJc
+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
-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
+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
-AyCQAlmwWGElLBwQL8AC/sABIGoCaHAu1AEv1AIswAD81AAgKxBYMCtkBfP+E2IAABGwAAAA+6xw
-IGgCUbD6Fn4gCBBgMFhhFSsShfpsPCAIEGAw+hZ/INACWvBYYRArEoX6bFwgCBBgMPoWgCC4Alrw
-WGEKLRKF+90BINACUbD90hkgEBBgMP1mGSEwAlrwWGEDKmAMK2IWHF3i/WAFIAEQcDAuZFQtZDAu
+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
-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
+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
-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
+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
-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
+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
-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
+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
-/7xgFBBoMNtQ8woIIgAAIrD6HAQgAxBgMFhfy4gRKXF/IxRPCIgU+BYSKAEBTDD4FgEkBQBJsPQU
-TiA0EHgwLyQF8/95YBgQaDDbUPwKAyAIAlBwWF+8iRH5iRQAcAJZMPkWASCYAlBw+RYSIAgQYDBY
-X7XDpSokBfP/QmAcEGgw21D8CgMgCAJQcFhfrowRJhRODIwUnBH8FhIgMxBYMCskBfP/GGA0EGgw
+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
@@ -5946,47 +5946,47 @@ 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
-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
+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
-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
+CxBAMPk6/y+ABD/g+RUMLgkAR/D/FgMgAxBgMFhezSsSMSgSLylgASpgACqEACmEASoSMC9gAv+E
+AiADEHAw/hQ4IAAQaDAtFDktFDr9FDsgEBBgMFhevy4SMy0SMizgACvgASvUASzUACrgAingAynU
AyrUAijgBC/gBS/UBSjUBCzgBy7gBi7UBizUBy0SNSwSNCvQACrQASrEASvEACnQAijQAyjEAynE
Ai/QBC7QBS7EBS/EBCvQBy3QBi3EBivEBywSNysSNirAACnAASm0ASq0ACjAAi/AAy+0Ayi0Ai7A
BC3ABS20BS60BCrAByzABiq0B/y0BiAgEEgw+RQ8IP8QQDD5FD0gABBwMP4UXCABEHgw/hRsIAIQ
aDD/FUQiAABR8P4UjCALEGAw+BVCIBACWHBb7YnD2S10BWP91AAA92MGf/8QcDDA4WTtFyrMTvsc
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -5994,12 +5994,12 @@ h4ZgaZK2YAUMZeRZKTBU/wIAAANThmBpkqLAxSxkVCswWPkKASgD94Lg/goBIAAQaDAJ7Thk0GEr
MhkrZRkbWwwqMFqIbA8CAAp6QP6qEAgAQFowCogCKGYMKjBaG1lnCmpA+4gBCvAEOqD7W8oYCQBS
MChmDCowWi9gBfuIAQoFAVAw8KoRAD0QWDD7ZAUoCQBSMChmDC9kMP0KASAAEGAwCdw4ZM8UKGAM
GVkwFVmzJ2IWKZJ3JVKE82EZJ5AEPeD5WhcYACBKMPmIEQYAID1w+BwQJAAgRXDwCRcAEBBIMNMP
-bZoCAAiKG1kiKlEp0w8PAgD/AgAH/2JekBxamI1g/mAFIAUQUDD/YFQgMhBYMFhlMRpZGPliACDh
+bZoCAAiKG1kiKlEp0w8PAgD/AgAH/2JekBxamI1g/mAFIAUQUDD/YFQgMhBYMFhlNRpZGPliACDh
EFgwKxQo+hYGIAgQIDD6WRMZgAQ+YPoWBCgJACZwmRUsYAcqUSn7WQ4cIAFgMADMEQyqAguqApoY
D+ownxmZHR5aMv4WDCBAEEAwKBUXLWBULRRBLGAFLBRC+2AwIAEQaDAtFEArFEMqYhb6FhEgYAJQ
cImliKSPo46i/KIBIKACWHCcsZ6yn7OYtJm1iqCasIlgKRYaKGBUKBRtL2AFLxRw/mAwIAAQYDD+
-FHEg8AJQcPwUbiBoAlmw/RRsIgAAYTBYXAL7bDwg/gJQcPqsASAIEGAwWFv9+3xyIP4CUHD6rAsg
-BhBgMFhb+ftsTiD+AlBw+qwOIAMQYDBYW/T7bFwg/gJQcPqsFSAIEGAwWFvv/RFKKAYBGDDzqUAK
+FHEg8AJQcPwUbiBoAlmw/RRsIgAAYTBYXAb7bDwg/gJQcPqsASAIEGAwWFwB+3xyIP4CUHD6rAsg
+BhBgMFhb/ftsTiD+AlBw+qwOIAMQYDBYW/j7bFwg/gJQcPqsFSAIEGAwWFvz/RFKKAYBGDDzqUAK
CwEYMP8RSyYJARww8x4UB7AEPeD/FTkuCQBw8PmqEQmgBD5g/2IMKAkAVnD+DkAEBQFsMPnuEQWw
BD1g/z9UDgkAK7DzekAOCQB7sP4UdCwNAWgw+2BpLaAEOyD/YGgsDgFsMPndEQQFARww/1URDAkA
azD/P0AMBgFcMPt+QAoFAVww/u4RDfAEP2D9/xEMCQB3cP/MAg4EARww9f8CDAkAazD8CjAqCQBm
@@ -6015,19 +6015,19 @@ CooUKvQ+Y/sGK/A+LPA/CLsRDLsCsbsr9D8LixQr9D5j+uwAACzwPi3wPwjMEQ3MArHMLPQ/DIwU
LPQ+Y/rQLfA+LvA/CN0RDt0Csd0t9D8NjRQt9D5j+rbaIFsE5tEPAC6gcLHuLqRwLjIbwcj47hEC
AP8aYPo8AAIAAFmw9Pr/IAgQeDBt+g8vsDQtoGSxqvu8AS4BrGvQ+mwAAAgQQDDTD22KDy+gPC0w
XLEz+qwBLgGl69D+FgAiAABRsP0cAAADEEgwbZoPL9AALqBOsar93AEuAahz0CtgBftkMCA9EFAw
-KmQFY/olAAAA+zxFIP4CUHD6rCEgAxBgMFhbDygSLS8SKC6CGA+PFC8WKC2CGRxZdPsKLSAuEHgw
+KmQFY/olAAAA+zxFIP4CUHD6rCEgAxBgMFhbEygSLS8SKC6CGA+PFC8WKC2CGRxZdPsKLSAuEHgw
/eoIDAAgP3D9hhkhYQA3oBhXon2LbCkSKP8CAA387eZQY/nOK6BcLKBdCLsRDLsCsbsrpF0LixQr
pFzaIPs8AAIAAGEw/VwAAgAAcbBb+Rtj+Z8ALKBcLaBdCMwRDcwCscwspF0MjBQspFzaIPs8AAIA
AGEw/VwAAgAAcbBb/HBj+W8tMDgoMDkPAgD5MDotgAQ/YAjdAvgwOy2ABD9gCd0CCN0RCN0C/wIA
-BgC+31D/AgAGALr/UC8SKP4WKyCoAljw+hYqLAArZ9DccFha1Nog+xIrIgAAYTD9XAACAABxsFv7
+BgC+31D/AgAGALr/UC8SKP4WKyCoAljw+hYqLAArZ9DccFha2Nog+xIrIgAAYTD9XAACAABxsFv7
KSkSLcCAKJYZY/kCK6BeLKBfCLsRDLsCsbsrpF8LixT7pF4j/KQCYPxgMCAGEGgwLWRULGQFY/nA
-3HBYWsDRDy6gcbHuLqRxY/jDAC+gcrH/L6RyY/i3KKBysYgopHJj+KwAACmgcrGZKaRyY/ifLGRU
+3HBYWsTRDy6gcbHuLqRxY/jDAC+gcrH/L6RyY/i3KKBysYgopHJj+KwAACmgcrGZKaRyY/ifLGRU
+gpAIIYQWDD6ZAUiAABRsFv0o2P4hgAtEij/AgAN/EJnUC0wOCgwOfkwOi2ABD9gCN0C+DA7LYAE
P2AJ3QII3REI3QL9FikgGARbcP8CAA/8JvtQGFoUKTEuLhYr+hYqL/94wlDaIPxMAACoAljw/VwA
AgAAcbBb+u4cWP4tMDgoMDkqEir5MDotgAQ/YP4SKywJAEdw+DA7LYAEP2D53QIALRBYMPjdEQAu
EHgw8/6gbAkAR3AAAAAA+xwQIgAAUbD8CgggAhBoMFsC0GP3zAAAAB9Z8isxLn+xeBhZ8i4WK/oW
KiB4BELwKhItwJApphlj96cqMFr/AgAD/AdikP8CAAP8A2aQ/wIAAfv/apAKDEP8zP8gABBYMAy5
-OGP36AD8fAAAqAJY8FhaZx5Y0S0SKNMP/wIADfu091DaIPsSKyIAAGEw/VwAAgAAcbBb+rhj/5Qo
+OGP36AD8fAAAqAJY8Fhaax5Y0S0SKNMP/wIADfu091DaIPsSKyIAAGEw/VwAAgAAcbBb+rhj/5Qo
EiwvgHL//AEiAABRsP+EcifQEFgwWAEFZa94Y/coAAAAAAAA/fMGcgAAUTDAoWSsnmAADP3zBnIA
AFEwwKFkrKssZFT6bAAAQBBAMPhkBSCGEFgwW/Q8Y/bsAAB/4wHAQWVP3GP8qABsEAYrIAeJJwsI
QfSRLWBAAmJwKpkUZKEiipn+ChIhHQA2oI+gLaAwD49X/xYBJgFTd1ApoQgtOv/+CksmAV/uUCkg
@@ -6038,8 +6038,8 @@ K5kUJVJ/9LH8YEACUnCImSaAB8Cw/FwAAgAAabBbBsCKJ9sw+qwgIgAAYTBbCimMIIsnCMwRDEwC
/KYBIEACUvD7XAACAABhsFsKItEP0Q8AAAAAAADwDgcP/BBoMP5XrRAkBGnwiRAGaAJtmQIASGEr
IAcLLUAK3RD8EgIsCQB3cJ1giSD/EgEgMBBAMPpW3xAwAmMw/GYDKYAEPmD6ZgIoCQBN8PlmASA8
BEPwiif7TAAAABBgMPqsICIAAGkwWwaXKyAH1aD7IQgsIAFYMP5ZRh0ABDsg/AoAKgkAZvCcZfwS
-AioJAHbwm2QARY0CBo8uZgYsZgctIAzTD/psKC0ABD9g/GYHKgkAbvD7ZgQgqAJY8FhZwipcGfwK
-AyB6AljwWFm+9Fd7EIICWPD8CgMgOgJRcFhZuRlW7i1QB44SLlULLCEHnVH/IAcvwAQ54PwMSg4A
+AioJAHbwm2QARY0CBo8uZgYsZgctIAzTD/psKC0ABD9g/GYHKgkAbvD7ZgQgqAJY8FhZxipcGfwK
+AyB6AljwWFnC9Fd7EIICWPD8CgMgOgJRcFhZvRlW7i1QB44SLlULLCEHnVH/IAcvwAQ54PwMSg4A
IHGw+iEILcAEOyD/LUAOIAF8MPD7EQygBD9g/cwCCgkAWrD7VqQcCQAjMJzg/SIAKgkASrCa5Pvm
AiAEEEAw+eYGIDAQWDD75gMgABBIMPnmBS2ABD9g+eYHLAkAR3D95gEgQAJjsAIFhgBMYwAFhgBM
YRlWiwz4Ef8SACgAIEow/4Y5IgAAULBbAz3RDwAAABNXwSgiHiMyfwmIEfgzCAIAAFCwWwM22jBb
@@ -6049,12 +6049,12 @@ AzXRDwDz/gZgABBAMPosAAIAAFjw/EwAAgAAaXBb/MfRDwAAAPosAAABEGAw/RIAIDACWjBbDohj
oPlGAyYJAEGw9kYBIEACETACA4YAQmMAA4YAQmESVm4MfxGi/5Xw0Q8AbBAEKSITDwIA+FetHjYB
TDD782dgAgJT8AoKQfiYAQqgBDqgCogC+CYTIGsANOAqIgcqrBBbB/P0Igcj6BBAMAgzKNMP+jwA
ACACITBam4H9VdwSAABg8P5YtBIAAFqw/yIAIgAAUTBamzeCJyIsENogWpELaKEnwCDRDy0gVf4g
-BSAFEFAw/FipEDIQWDBYYirAIdEP2iBb8a3AINEPANogWpEfElZfC6gR9KA5YgAgQLAM6jArIoWL
-sLCi/LsIAgAAULBYZFAcVtMqwn/wIQQAARBYMAC7GguqAirGf1hkhcAg0Q8AAPoKByABEFgwWwiH
-LCJ//CaDIAAQEDDRD2wQBhVXHYstKlJrCbsRq6qKqsmiK6xg/AoEIgAAUHBYWQqKEGAABQAaVfaa
+BSAFEFAw/FipEDIQWDBYYi7AIdEP2iBb8a3AINEPANogWpEfElZfC6gR9KA5YgAgQLAM6jArIoWL
+sLCi/LsIAgAAULBYZFQcVtMqwn/wIQQAARBYMAC7GguqAirGf1hkicAg0Q8AAPoKByABEFgwWwiH
+LCJ//CaDIAAQEDDRD2wQBhVXHYstKlJrCbsRq6qKqsmiK6xg/AoEIgAAUHBYWQ6KEGAABQAaVfaa
EB9V9I0nHlYX+vo4A+gQYDAMrCwDzCgOzCj8FgAgIAJTcFsHrYQQgyf6TAAAIAIY8FqbPf1VmBIA
AGEw/lb/EgAAWrD/IgAiAABQ8Fqa84InIiwQ2iBakMdooQLRDwDaIFqQ5BJWJQuoEfSgNmIAIECw
-DOowKyKFi7Cwovy7CAIAAFCwWGQVKlKT8CEEAAEQWDAAuxoLqgIqVpNYZEvRDwAAAAD6CgcgARBY
+DOowKyKFi7Cwovy7CAIAAFCwWGQZKlKT8CEEAAEQWDAAuxoLqgIqVpNYZE/RDwAAAAD6CgcgARBY
MFsITSwifywmg9EPAGwQEBtVuiwxJ/VX1RIAAGlwji4pIAcqUjr2MSYiAABBMPkJQQ+QBDug+8EP
egAgcrAvITf/AgAOAi/j0CchNv8CAA4CKjmQjydk8PQr+RQpFhT08gkkUAA24JoemB/0FhAgIAJT
8FsHbi0gBf8SFCALEEAw/gpWI/8QSDD2CgcmAid3UC4hCBpVrfnpDAP/EGAw+YY5CcAEP+D2FhIk
@@ -6064,9 +6064,9 @@ FgQiAABh8FsFU4on+qwgIgAAKfD8Eg8iAABY8FsIuowgix8IzBEMuwL7pgEjgAC1YNEPAP8CAAYC
GoIgHVVTKRIS8A0HAgAAQTBtmQIASGEqIEEvIQccVpMKrQn3V3odwAQ/YPNVeBwAIGsw/MJ/L0AB
fDD+ISIvwAQ/4PNVcR4JAB/w/I1CCsABZDD8fEANgAQ/YP7dFAoJAG7w9cwRDUAEP2D9CgAsCQBr
MP0WBSsABDqg/0YAKgkAZvD7VVAaCQBasB9X3vwiACBYEEgwmUOXR/NGAiBIEEAw/UUKL0AEO6D4
-RQsgBxBoMPuqAgCQAliw+kYEIEACUTD4zBEOCQB7sP5GBiwJAGsw/EYBIAwQYDBYWFArLFz6VmoQ
-iRBIMPlELCAAEDAw9kQ6IAAQeDD/RDkgABBwMP5EOCAYEGAw+kQtIC4QQDD4RDsgeAJRMFhYQB1X
-u/5ASCAAEDAwJkRE9kUlIIoCUTD2RhQvhBB4MP9EPCACAnOw/kRIICgCWHD9FgUgAxBgMFhYMvtV
+RQsgBxBoMPuqAgCQAliw+kYEIEACUTD4zBEOCQB7sP5GBiwJAGsw/EYBIAwQYDBYWFQrLFz6VmoQ
+iRBIMPlELCAAEDAw9kQ6IAAQeDD/RDkgABBwMP5EOCAYEGAw+kQtIC4QQDD4RDsgeAJRMFhYRB1X
+u/5ASCAAEDAwJkRE9kUlIIoCUTD2RhQvhBB4MP9EPCACAnOw/kRIICgCWHD9FgUgAxBgMFhYNvtV
ExAAEEgwKURULCBoLERVLiE2LkUsLyE3+0UvIEIQUDAqRGQpRS4vRS0nIAXFhv8CAAYBYcXQxdAt
JAUuIQgvOv//AgAGATh/kBtVGiYSEIkgHVXaF1VRLCEHLyAHKE0B+IyQLUABYDD/I0AOIAF8MPoz
EAsABDvg/MwRDgkAU7DzzAIAMBBQMPfuAgAEEBgw/cwCDYAEPmD1YHViCQAfcBZXhfYWBiACEDAw
@@ -6080,20 +6080,20 @@ MFgAS9EPmh6YH/P7sGAAECAwAADz+/RgABBAMACKJ9tQ/BIEIEACUrBbB9PRD4weLcAF/cQwIEMQ
WDArxAVj+6IAAAD/AgAH/eIaIIYn+PrAIEACcbD4CgAuAEBDsPhlFCCAAnOwnmmeaGP7nikhFCMh
EsBA+RYTLwcANmD6UsMiAABY8PwKACABEGgwWwPXJlLEKhIT9EwBIAICGPAGMy56Sdhj/tgAAAAA
APP7r2AAECAwKRIRKBISKJY5Y/7FAAAAAPosAAAwAlvw/RISIAEQYDBbDIooEhVj+2eKJ40fwMD6
-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
+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
-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
+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
-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
+oEAudEAtdEkrdScqoSf8dSYgABBYMCt0RPt0SCYAWiaQKnxB/AoDIKICWLBYVvArLE78CgMgegJR
+8FhW7YgTH1XWKIBFjRAeVmUAiDL4/TsAhBAQMPp8RSwJAHdw+N0RAgAAWHD9FgAgAxBgMFhW4PJh
K3AJEEgw+XRVIEIQUDD6dFwgABBgMPx0VyADEFgwK3RWI1Y50Q8AAAAAAAAA/hIDIAAQeDD/dFQv
/xBIMCl0VSjhJih1LC7hJyR1Ly91Lv51LSBCEGgwLXRkI1Y50Q/AoCp1J2P/R4wimxT1vAAASQA3
-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
+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
@@ -6108,43 +6108,43 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-AliwWFTZjhAdVFoOjBT/U/kReARrMPhT+BAuBHsw+hIFIB4EQzApopCxmSmmkGP/nPoSBSzgAXQw
+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
-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
+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
-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
+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
-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
+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
@@ -6169,42 +6169,42 @@ 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
-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
+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
-JiYYJiYZJiYaJiYbJiYcJiYdJiYeJiYf/FHPEAUQUDD9CmAgMBBYMFhbPP0KcCIAAFlw/SQFIAAQ
+JiYYJiYZJiYaJiYbJiYcJiYdJiYeJiYf/FHPEAUQUDD9CmAgMBBYMFhbQP0KcCIAAFlw/SQFIAAQ
YDD6MhEgARBoMFr+g/oyEiIAAFkw/AoAIAEQaDBa/n/RD48/+SIKIBACc3D+9gEgeAJA8JjTn9Ke
P2P/O4s9+SIKIBACU3D6tgEgaAJg8JzTm9KaPWP/IAAAbBAGHFGxGE9cjyCNNfUgBSAFEFAw/jIE
-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
+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
-YCAwEFgwWFq2+ApwIgAAWXD4NAUgABBgMPoiESABEGgwWv39+iISIgAAWTD8CgAgARBoMFr9+cAg
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
@@ -6212,19 +6212,19 @@ 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
-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
+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
-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
+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
-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
+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
-EBxPI5sTH0xiG0xi+UxtEAMQUDD5FgIp0AQ5YAuILPmIKAIAAGiw+BYBICAQWDBYWHIbTFdj/3MA
-bBAEKTAIGkyC/PrqIgAAIXD1TR0QPAA2YGiRDvpMAAIAAFjwWFaBwCDRD4kwCpoBZKBUKjAJZKBe
+EBxPI5sTH0xiG0xi+UxtEAMQUDD5FgIp0AQ5YAuILPmIKAIAAGiw+BYBICAQWDBYWHYbTFdj/3MA
+bBAEKTAIGkyC/PrqIgAAIXD1TR0QPAA2YGiRDvpMAAIAAFjwWFaFwCDRD4kwCpoBZKBUKjAJZKBe
+KFTb+oQYDD4+uoqAEAqcPP/z2wFAFIwiTD6mgEAKgAqcCowCWSgVvihS2/qEGAwY/+veZbAKzAJ
Zb+m+zwIIgAAULBa9wTz/5hiAABisGP/tQAAAAAA8/+tb9oQYDD7PAgiAABQsFr2p4kw8/+YYgAA
YrAAAADz/2hv2hBgMPs8CCIAAFCwWvb78/9VYgAAYrAAbBAEHk4JL+IhKeI3BVoC+zwAAUEAN+AJ
@@ -6233,8 +6233,8 @@ ACBN8C1yCiyyAyJyC/SAKmwAQE9wf8cFGEvBCN0Ce8cFKQqACd0CfMcExIAI3QJ9xwIF3QJ+xwIG
3QL4Ov8pMAFkMPiRDXAAEGAwfzsSYAARAAAAGUwJwMH53QIKAAN80MBwGE0KGU25w/ovhhAihhHD
+y+GEC2GEYiA+D8RCABASjD/TWMYCQB6MAWIAg+PAgz4OR9M/ZjwH0zk+Uz7GABASjAPiAL4lgAg
CAA14J16knuJsB9L4HmWPC/yei3i3aP/Cf8Rr92N2g0MWQDMEQTIAv2MOgAOAGNwBswCedcEwIgI
-zAJ61wTAlAnMAnvXBMDSDcwCnLPAwFhWBcAg0Q8AAPP/82+5EGAwbBAEiTD6XAACAABY8PxOiRBQ
-AKpweZYXj8CIwZizn7KNwo7DnrWdtIjFicSZtpi3wMBYVfTAINEPGUtwKZKucZYH8//sb7kQYDCJ
+zAJ61wTAlAnMAnvXBMDSDcwCnLPAwFhWCcAg0Q8AAPP/82+5EGAwbBAEiTD6XAACAABY8PxOiRBQ
+AKpweZYXj8CIwZizn7KNwo7DnrWdtIjFicSZtpi3wMBYVfjAINEPGUtwKZKucZYH8//sb7kQYDCJ
MgnJU2+SLf8aDCBKAD5gibKNs53BmcCPtIi1mMOfwo22jreexZ3EibBj/50AAAAAjjN/6Nnz/65v
6hBgMGwQBBlM9xpNVxhOHPdLYBcgARAw+mYCAAAQEDD2lvsgChAoMNMPbVoNKpL7CKsB97EIcAIC
ELDHINEPCq1J/TYALSABUDD8RgAgABAQMNEPbBAK/UuUEgAAeLAs8A31FgUiAAAQ8PvwDCHgAjNw
@@ -6253,7 +6253,7 @@ cPh2ACBqADfgL/z2blJ0LBIIDKwIDAxJ+cwCAAoQQDD8RvsgABBgMG2KFSJC+w4mAf8CAAACAmMw
/wIAB/+7bZD/AgAP8BBgMP8CAAf/s22QY/9xAAAA/woAIAgCOfD/dgAgABBIMPP/fmAUEHgwGUyF
+AoAIAgCOfCYcPP/jGAUEHgwaVFogheIGBxMfgioCAgISfyIAgAAEFgw+Eb7IAoQYDBtyg0sQvsO
yQH9kRBwAgJa8PAAG2/wEGAwAAAAAAyrSfsWACsgAWAw+hYBIAAQYDDyFgcgGAC3II4QjXAA8QQA
-7hryFgcsCQB3cJ1wihWLF1hU6cAg0Q8AAAAA8/6ZYBQQeDAp0nermQmZEfP8mWgAIEzwAAAAAJ8S
+7hryFgcsCQB3cJ1wihWLF1hU7cAg0Q8AAAAA8/6ZYBQQeDAp0nermQmZEfP8mWgAIEzwAAAAAJ8S
nhT9FgMh/sqc4PenCAIAAFhw+nwAAAgCYHBb/vmDUABgBAMDGfMDSQIAAGKw8xYAIRkAtqAoOv94
MROJE/8CAAoAhMzQixT/AgAKAH+e0I0R/H4QDWAEP2AO3QINPQItRvtj/TWbJGP9XJ8S8/0rYAAQ
YDAAAAAAAADyFgch/6qc4JYYkhdj/uAAAJ8SnhT9FgMiAABR8PwcBCIAAFhwW/7YjROLUI4UjxL7
@@ -6267,22 +6267,22 @@ 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
-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
+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
-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
+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
-UwwAQGLw/hYCK3QBbDD/jlcN4AFMMPgWBCjwAUww+RYFKeABeDD4FgMu8AF8MFhT6vgKASAAEHgw
+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
-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
+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
-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
+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
-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
+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
@@ -6301,13 +6301,13 @@ KsAWLQr//wIABgBrbpCaMcCg8/+IYgAAGrAAAAAAAAD/AgAMAIYZoPs8AAIAAFCw/EwAAgAAaXBb
RyrEFmP/iQAAAAAAAAD+IA0gbAA1IPkhCCCSADegLiETDp4MnjFj/3QuIA1k4GHZsIsvKvJxqbkK
mQr5kgAgWgA1IPmRCCBqADegLCETDJwMnDFj/0dlXwfz/0Nv/xBQMIksCbkMY/8HAAAAAADz/ypv
/xBQMPP/EWD/EFAwKiETizEKvAwOyzirqiolCGP/DIksCbkMY/+XKiETizEKvAwOyzirqiqVCGP+
-8ZkxY/7smTFj/ufz/0Fg/xBQMMY6HEraLiANLSAM9BYAIgAAebD1FgEgAhBQMPMWAiASEFgwWFQZ
-0jDRDy4gDRxK0C0gDPQWACACEFAw9RYBIgAAebD7FgIv6hBAMPgWAyASEFgwWFQN8/6Ib+oQUDAA
+8ZkxY/7smTFj/ufz/0Fg/xBQMMY6HEraLiANLSAM9BYAIgAAebD1FgEgAhBQMPMWAiASEFgwWFQd
+0jDRDy4gDRxK0C0gDPQWACACEFAw9RYBIgAAebD7FgIv6hBAMPgWAyASEFgwWFQR8/6Ib+oQUDAA
AGwQBBZIRYIwF0rD9EApYgBAMLD5Gh0qAAUR0BhKv3KLHiQt8CRM+PZKvRoAB8kQBkYKhmAKYAAA
yVXGKtEPAAAYR+OoKIiA+DYBIAAQEDDRD8cv0Q8AAABsEAQeR42LMP9KsBABEGgw/EqhEDIQQDD7
ClcCAAAwsPirD3AAEBAwGUqpCakKiZAKkADGKtEPZEOFK2AhKmAgCLsRC6oC+jYBIAAQEDDRD2RD
yCpgdiwK//8CAAYCUeaQ2aD5NgEgABAQMNEPGkh/KWAN+63tI3MANSBkk+0kon+PYAT/DA9UFA5E
-EQTkDCRNB/RCJSiAAXwwAJEE8NgaAgAAWLD8SWAUAEBBMPTUOQAFEFAw/fwAAgAAcTBYU8T0NgEg
+EQTkDCRNB/RCJSiAAXwwAJEE8NgaAgAAWLD8SWAUAEBBMPTUOQAFEFAw/fwAAgAAcTBYU8j0NgEg
ABAQMNEPAAAAAAAAAGRPXihgDWSDv/I2ASAAEBAw0Q9kT0spYA1kk8LyNgEgABAQMNEPZE84KmAN
ZKM38jYBIAAQEDDRDwAAAAAAZE8gK2ANZLM58jYBIAAQEDDRD2RPDSxgDfliCyOUADcgsJ39NgEg
ABAQMNEPZE7zLmANZOOK8jYBIAAQEDDRD2RO4C9gDflhEiODADfgsJj4NgEgABAQMNEPZE7GKWAN
@@ -6320,34 +6320,34 @@ MdEPZE2gimeKroqrmjHRD2RNk4tni76Mvou9rLuwu5sx0Q9kTYCMZ4zOjcqMya3MsMycMdEPZE1t
jWeN3o3ZnTHRD2RNYI5nju6P6I7nr+6w7p4x0Q9kTU2PZ4/+j/efMdEPZE1AiGeIjomGiIWpiLCI
mDHRD2RNLYlniZ6JlZkx0Q9kTSCKZ4quK6EpKqEoq6qwqpox0Q9kTQuLZ4u+K7EomzHRD2RM/Yxn
jM4twScswSatzLDMnDHRD2RM6I1njd4t0SadMdEPZEzajmeO7i/hJS7hJK/usO6eMdEPZEzFj2eP
-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
+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
-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
+WFLU8jYBIAAQEDDRD41njd6O043Srt2w3f02ASAAEBAw0Q+OZ47ujuL+NgEgABAQMNEPj2yp/7D/
/zYBIAAQEDDRD4hs+DYBIAAQEDDRDyphE6mqsKr6NgEgABAQMNEPK2ET+zYBIAAQEDDRDwAAAAAA
APP7X2//EEgwqaywzPw2ASAAEBAw0Q8AAPk2ASAAEBAw0Q8oYAwusIAAgQQA3xoP7gL+tIAgABAQ
MNEPAAAAAADz/uVg/xBQMGwQBiUwCicwCxxJX/YwCCAFEFAw9DECIAgQWDD0FgAiAABosP5sAAIA
-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
+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
-NAsv9RAQMNEPsWRpR8bAINEPAAAA/WwAAAEQUDD8STYQCBBYMFhScccr0Q8AbBAE9iwAADYANSAd
+NAsv9RAQMNEPsWRpR8bAINEPAAAA/WwAAAEQUDD8STYQCBBYMFhSdccr0Q8AbBAE9iwAADYANSAd
RgaLMBxJDf9GUBAAEBAw+wpXABoQQDD+SSoaAAlCkBlJKQmpComQCpAAZEKAxirRD2Vfyscv0Q9k
-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
+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
-0Q9kTpiSMdEPZE6RK/JmKuL+CbsRq6qKp2SgzSqsIFrw0QpMFPw2ASAAEBAw0Q9kTmtYG3D6NgEg
+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
-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
+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
@@ -6355,38 +6355,38 @@ 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
-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
+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
-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
+OAJY8CxCnvsWBywBACsw/EaeIgAAUfBYjc+LMYw19qwACgDD3xCcMYoXWI3KjjKNMf7dCAIAADqw
+/RYEICACUHBYjcQuQpuMMf7ICAP/EHgw+PMKcgAAWrAMXgwuRpvdcPlCnCIAAGOw/kKeIgAAebD5
+FgAiAABQsFjFj40UjDWPGIs3ijIE/wop8p8u8qcLqDb9mTcIACBDMPn2ny4BAEOwLvanKUKeLkKb
L0KcnzSeMPk2BigDAFqwmDf4RNkQABBQMPm5CA4AIGuw/kabLgAgfzD/RpwoAQB+cPlGnioAcPYQ
/wIACgB7/VAuQp4ZRa3/AgAKAIX2UNKg0Q+dGGP++IYx/BYFICsANyArQp4qQpv1uzcKACAysPtG
nioAB9qQCrwMrGaWMWAABgALrTctRp6JFfosAAAREFgw/AoAIB8QaDD2mQgAABBwMPkWBCAAEEAw
-+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
++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
-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
+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
-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
+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
-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
+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
-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
+Q/pmQSEAEEAwKGZEf5cb+mY+IAgQWDD7Zj0gIBBIMClmPGP9XljJYGP9oidVx2P9UgAAAAAAAABY
+jSzz/Y9iAAAisFjJWGP9hAAAbBAEiEAeRggZQ3ONIP7ifyj4AUAwCYgK+ILEIgAAUPD+3QwCAABZ
MPjdEQAFEHAw/EAHLAkAd3ALgACJQY8yCYlH+QkGABYAN+DIXooniq6VoPamAS+NEBAw0Q/SkNEP
bBAMFENYKyAMKiAN8AQHAgAASHAASWEASWEASWEASWEXQ1UZRMAVRej8RMAZgAQ64PwWASvABDzg
+xQQIAAQaDD9FBEoCQBCsP5SfygJAEowmBD9IgAo+AFAMAeICviCxCAFEDAw/t0MAgAAULD43REC
-AABYcPbdAgAEEGAwC4AAgxEPAgAPAgADg0cDAwZmMjgjEQTzA0sCAABQsPwKASIAAFjwWCXV8AQH
+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
@@ -6396,14 +6396,14 @@ FgQoCQBA8JgQ/SIAKPgBQDAHiAoogsQP3Qz43RECAABRsP7dAgIAAFhwC4AAhREFhUcFBQb2URVi
AABIcAAEiwBJYQBJYQBJYQBJYRhEUBlF3/5FaxACEGAwnBGZE/7ifygJAEDwmBD9IgAo+AFAMAeI
CiiCxP7dDAIAAFGw+N0RAAUQcDD+3QICAABYcAuAAIURBYVHBQUG9lDLYgAASHAABIsASWEASWEA
SWEASWEYRCoeRVMZRcaZEf7ifygJAEDwmBD9IgAo+AFAMAeICviCxCIAAFGw/t0MAgAAWHD43REA
-BRBwMP7dAgABEGAwC4AAhREFhUcFBQZmUILSMNEPAI0g+goCIAAQWDD8RbESAABw8FhO0NIw0Q+N
-IPoKAiAAEFgw/EWsEgAAcXBYTsrSUNEPjSD6CgIgABBYMPxFpxIAAHFwWE7E0lDRD40g+goCIAAQ
-WDD8RaISAABxcFhOvdJQ0Q8AjSD6CgIgABBYMPxFnBIAAHFwWE630lDRD40g+goCIAAQWDD8RZcS
-AABxcFhOsdJQ0Q8AAGwQBPQgXWPwARQw9AogICAANOACiFfKggLJU8qYAupR9KAwYf4CWTACtDvS
+BRBwMP7dAgABEGAwC4AAhREFhUcFBQZmUILSMNEPAI0g+goCIAAQWDD8RbESAABw8FhO1NIw0Q+N
+IPoKAiAAEFgw/EWsEgAAcXBYTs7SUNEPjSD6CgIgABBYMPxFpxIAAHFwWE7I0lDRD40g+goCIAAQ
+WDD8RaISAABxcFhOwdJQ0Q8AjSD6CgIgABBYMPxFnBIAAHFwWE670lDRD40g+goCIAAQWDD8RZcS
+AABxcFhOtdJQ0Q8AAGwQBPQgXWPwARQw9AogICAANOACiFfKggLJU8qYAupR9KAwYf4CWTACtDvS
QNEPACIR8//dYBAQIDAAAAgiEfP/1WHwAiEwDCIR8//PYfgCITAAAA4tEfxM/SH8AhEwDcI70Q/A
INEPbBAEEkIwIiLY0Q8AbBAEgieCLoMogiejIrAi0Q8AAABsEASCJ4IugifRDwBsEAQSQiUiItfR
DwBsEAQl+sAFJQEkURWlRCRNAfMmASGAAiEwlCDRDwAAAGwQBIIngi6DJoIloyKwItEPAAAAbBAE
-gieCLoIl0Q8AbBAEG0VbJDx/BDoUC6oB+qwQIBAQWDBYmWIjpQLzpQMiAAASsPR8FAAAEFgw+6UF
+gieCLoIl0Q8AbBAEG0VbJDx/BDoUC6oB+qwQIBAQWDBYmWYjpQLzpQMiAAASsPR8FAAAEFgw+6UF
JMABGDD8pQQgIAJisPymACAoADUg+kwAAAEQaDBa7WForhX6TAAAABBYMPwiACABEGgwWu1caa7p
0Q8AbBAEF0H19kVAFeAEPKCnV/N2BCQAIDVwJFZ/0Q8AAABsEAQZQ02JkBpD/PhDSxgAQFZw+SIC
ABAQIDAEJAKUgBNFMxRD9/NDRBIJABiwBCIB8jYAIAAQEDDRDwBsEAQYRBEaQz0ZQicmgiEdQ+sp
@@ -6420,36 +6420,36 @@ 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
-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
+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
-MFhNahlBW4wUB4oUAKsRC5sCK8bJKma/KWbA0Q/fQPoKAyAgEFgw/BYAIgAAaLD8REsSAABw8FhN
-XIQVY/9KAAAA9URFH3UAtuApfQQYRD/0FgEgARBQMPoWACIAAGiw+II9IgAAcPD5kgIiAAB68PxE
-PBAgEFgw9RYDKdAEOiAJiCz4FgIgAxBQMFhNR8CxjhQFjBQAzRENvQIt5sksZr8rZsDRD2wQBvZA
-2hEYEDgwByco0w/3Q94WACA5sCNm/yNm/idyf/tD2hIAAFHwWE9I9bwAAgAAIrD7CmQiAABQ8FhP
-Q/wKACBkEGgwWE252kD8CgAiAAAa8PtcAAIAAGjwWE2z/7FXYgAAcvAYQRktbQQaQ8gCKQv+Q8gZ
+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
-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
+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
-BCAwEFgwWEzo/wIAAgCAgOAuIDjTD2nmWGQxRGgxOWkyQS9S6S/yF8v4K1IWy7PAQPpDzhCSEDgw
+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
-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
+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
-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
+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
-5voKBCAyEFgw/EM+EgAAcPBYTEnaIPtMAAIAAGDwW4Ga0Q9pNpypSimgef+flHABEGAw+wr9KAkA
-YnALiAEopHlj/34AAAAcQy8vQAEuQAItICL4QAAgBBBQMPgWACAyEFgwWEw0KiAiCqsJDLsRq1ss
+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
-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
+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
@@ -6460,32 +6460,32 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-AEfw/9RQIaoCUrD/jxQAAgI58P/UTyIAAGHwWEHJiBH5fAYigBBQMPP9MmgAIEowjhP6PQMgERBA
-MPjkYiABEEgw+eRkIAAQaDD95GMgBBBYMCvkYf8wJiANEGAw/+RlIc4CUrD95GYgUAJY8FhBtSlx
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+AH+FIP8CAAQAtAEgaEVY+goEIBgQWDD8QN4SAABpMFhJ5MYq0Q+IMbAq+AlDAAcQWDAPAgAPAgBt
ug/4SBQB/gJSsPmkTyhgAUQwKaROIzABwKB4Nw34Yn0gLAA1IGhBJGhCIdKg0Q8pMQEJyUJvlAJv
knf4l3Rv6hBQMCswAXi/02P/3gCEICYK//hEDAAAEBgw2kD7PAAAABBgMP0KACAAEHgw/xYBIAAQ
cDD/FgIgZBBIMPkWACAAEHgwWueZZq+gojwswE72yAwCAABRMPhcOAIAAFjwWuds9qAHYAICGPBp
@@ -6496,41 +6496,41 @@ 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
-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
+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
-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
+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
-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
+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
-IgAAWHD8+oAgcgJSsPzUECAEEGAwWD/Y9S0BIBUQYDD1XDggHAJRcPoWCSIAAFlwWD/RKC0BjBeJ
+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
-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
+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
-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
+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
-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
+NFUgwAI4sPg0VCIAAFHwWD7PwNAtVFAtVEktVE8tVEUtVEQtVEcpMFKMESZUTfl6QAgGAUwwKVRO
KlRM98YEIMgCQLCYxvjGAiDgAniw/8YDIMwCcLCexSkx/p3A/cYBINQCWLD7xgch/1p2UCstAYwa
J1IalxL8wOwvwBB4MP80wCAAEHAwLjS+9jS/IAQQaDD+NMEhtAJa8PzMCQDkAjiw/cwJAgAAUfBY
-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
+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
-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
+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
@@ -6538,37 +6538,37 @@ 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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-AlrwDIgRCgpDqoiYECiQTSy0xCi0vPo9AS+AEGAw/NS4IgAAWHD8CgQgcgJSsFg83/Q9ASAVEGAw
-9Ew4IBwCMTD6bAACAABZMFg82IkSJ5QMJ5QFJ5QPJZQOJ5QNiRMoPQEmlgL0lgMgRgJCMCiWASkh
+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
-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
+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
-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
+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
-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
+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
@@ -6582,7 +6582,7 @@ IiJL0Q8ADCIRooIiIkvRDyJwNnkhmGgpLHohAmkqj8AiAjIKCCIKIiJL0Q/AIgIyCggiCiIiS9EP
wCECMgoIIgoiIkvRD8AhAjIKCCIKIiJL0Q8AAABsEAgaOcIpooIcOD3+CgsgCRBoMPuifSGMADZg
orsJuxELmwgqsCMERQn5CgAiAJ0KoGahMiqwLNMPaKIaaKUX/wIABADGgqD/AgAAAMoGoP8CAAQA
ygKgpZUMVQolUmvaIPtMAAIAAGDwW/+r9jpyGgEBJDD0CEAL4AQ+4PQnFAgJAFow8ncRCYAEOiD4
-dwgIIAEsMPZ2CAIAi4Dg+RYEIAB3rqDdIPUWACIAAHkw/Dt+EAUQUDD7ChgiAABw8FhEdhk6Xql5
+dwgIIAEsMPZ2CAIAi4Dg+RYEIAB3rqDdIPUWACIAAHkw/Dt+EAUQUDD7ChgiAABw8FhEehk6Xql5
j5saO3j1qEIKLQEsMPS7EQmABDog+4gCDgBAV/AI/wKfmy2SHB87cQV+QvfuEQwAQH9wDt0CLZYc
KpInxsD1K0QKAEBisAuqAiqWJyhtBIiAHDtnihQbOP/8qhEIAEBiMAqIAvptBCgJAFowmKAukh8f
OhgP7gIulh+MksDRDcwC/JYCItgAOOCMmMDRDcwCnJiKmMe+C6oBmpjRDwAAAAD/AgAH/2TukPuq
@@ -6591,13 +6591,13 @@ Umtj/q/z/ulgABBIMNEPaDVKaDc/aDgFaDk5fjE28/6LYAAQSDAosDb/AgAP/zhqEGP+eADz/nRg
ARBIMCqwNmip8f8CAA//M3KQ8/5eYAIQSDAAAPP+VGACEEgw8/5MYAEQSDBsEAbaIPtMAAIAAGDw
W/8+wHH4OgUaAQEkMPQJQAvgBD7g9CUUCAkAXnDyVREJgAQ+YPlVCAIAADKw96ASZAAgRXAsUoAd
Oc0NzAEsVoDRD90g/jwAAgAAeTArUoAcN6wMuwIrVoAoUoAaOxAZOKgKiAH8Ow0YCQBKMPhWgCAY
-EFgw9hYAIAUQUDBYQ/8q+sApUoP2q1EP8xBgMP67EQgAQGZwC5kCKVaDL1KIxoD4/wEIlQEwMAj/
+EFgw9hYAIAUQUDBYRAMq+sApUoP2q1EP8xBgMP67EQgAQGZwC5kCKVaDL1KIxoD4/wEIlQEwMAj/
Ai9WiC5Sifb/RQ4AQFOwD+4CLlaJLVKK9p5FDABAV3AO3QItVoorUo3HyPy7AQxGATAwDLsCK1aN
KVKM9ghFCABAVnAJiAIoVowvUoIH/wIvVoItUoLH7g7dAS1WgtEPbBAEGzrlGDnCGjrkHDdz8AAP
YAAQMDAAsWb/AgAIAEOBoABgBAIEG39H7G8zC8g4wHLwABJgABAoMGg4Amk7ZPcKACABECgwBhRA
9g9ABeAEOSD2LhQOCQAn8PLuEQ+ABD/gr+4I7ggt4oAKXxH/fwIMAEBXcA/dAgvdAi3mgAnqMCXC
MQlVCQnqMAlZDGqRhm0IDQnqMAlZDP8CAAH/vSZgY//r0Q8AbBAEhSeFXi5SJf88AAAEEFAw9CAi
-IBgQWDD8OrcQAgJzsP5WJSAAECgw9SRuIgAAaTBYQ6XaQPsKACAAEGAwW/55KyIfi7dksAoCKgIL
+IBgQWDD8OrcQAgJzsP5WJSAAECgw9SRuIgAAaTBYQ6naQPsKACAAEGAwW/55KyIfi7dksAoCKgIL
sABgAAMAAMCgZqEDHzepAkoRr68u8oAYOi0I7gEu9oAL6jAcNy8pwjEtwjENmQoLmQkN6jANnQxq
0RBtCAgI6jAImAxqgQRj//AAAMDXGDeMqKouooAfN6UP7gIupoApwoMJi1Jotxv5CgYuFgFMMA/Z
OSuigsfgDrsBC5kCKaaCKcKDCbhSaIcfHzluLgpw+wpgLgBAfnAP6zksooIt+g8NzAEMuwIrpoIc
@@ -6614,17 +6614,17 @@ DABBBAA6GgBBBPDbGg//EGAwDLsDC5kBCpkCKebAKnJ7KWLcCaoRqpklkDf7CggiAABSMA+6OQpV
AiWUN2P+/wAAZD9IwCBtCC0rkHwsYtwAIAQLCxv+cnsgKAB+8K4uCe4RrswtxG0txGYjYiKxIv8C
AAv/jRiQY//LAAAA9awAC/+7lqAk4oQAoQQAORoAoQTw2hoP/xBYMAuqAwpEAQlEAiTmhGP/dGUu
HmP+3gAAAGwQCvdcAAIAADCwC+owGDfFKIJ//wIACgE6RtAeOc4dNlkaN8Ai4gEt0jErpn/6on4g
-ABBgMFhDQx02Uh85xy3QwfK1DAABEHAw/vQAIBQAc3AuMABo4yvH/v9vAQA4EEAwePEeyXvApfw5
-vBAIEFgw/zAAIgAAaTD1FgAiAABxsFhCpigKE/8CAAoAtKoQFzY/DwIAJna9GjmyGzY//QpkIAAQ
+ABBgMFhDRx02Uh85xy3QwfK1DAABEHAw/vQAIBQAc3AuMABo4yvH/v9vAQA4EEAwePEeyXvApfw5
+vBAIEFgw/zAAIgAAaTD1FgAiAABxsFhCqigKE/8CAAoAtKoQFzY/DwIAJna9GjmyGzY//QpkIAAQ
YDD+CgogAxBIMPl2viAAEHgwWujIHTea8qwAAdwANqD1FgYgABBIMPMWBSE1ADUg1ZD2FgQsAAEw
MPwWByH+Alkw+xYIIAMQGDDwABJgARAwMAAAAAAAAPYKASBSADTgjRgPAgD+EgcqAAPtUCYKAPTg
eWPwBDmgGzYf8na+IAAQYDD4OY8QZBBoMPo5jBAKEHAw+BYAIAAQeDBa4j3yrAAAnAA2oGYgxrFV
-dFOpHTd0FDl/C+owKdJ//wIACgC7TtAeNgcu4jEr1n8q0n78CgAiAABrsFhC8ptB+kYAIO0ANOAY
+dFOpHTd0FDl/C+owKdJ//wIACgC7TtAeNgcu4jEr1n8q0n78CgAiAABrsFhC9ptB+kYAIO0ANOAY
OXTA8C+EANEPiBUPAgCliCiAACh2vRo5cPs1/RAAEGAw/woBIGQQaDD5OWweCQB8sP92viAKEHAw
+RYAIAAQeDBa4hryrAAPegC2oCtyvv8CAAP/t4bQYAAuihX5cr0qACAqsCmkAGP/VwAA+zlcEBQQ
UDAFqgxa4jxj/okUOVPz/0xgAxAYMAAi+rkcOVWPFY4UjRYv8ACWEvUWASAEEFAw/RYAIAgQWDDy
-FgMiAABpMFhCOIgYeFNssDMK6jAbNc8psjErsjELmQoKmQoK6jAKmgxqoQgM6jAMnAxrwfbz/pBg
-ABAoMMCh/Dk+EAgQWDBYQigeOTbA0P3kAC/7EBAw0Q8YNyYvgn6x/y+GfmP9gQAAKHK+/wIAA/8Q
+FgMiAABpMFhCPIgYeFNssDMK6jAbNc8psjErsjELmQoKmQoK6jAKmgxqoQgM6jAMnAxrwfbz/pBg
+ABAoMMCh/Dk+EAgQWDBYQiweOTbA0P3kAC/7EBAw0Q8YNyYvgn6x/y+GfmP9gQAAKHK+/wIAA/8Q
hhDz/hlvuRAQMMCgKna9GjkrGzW4/QpkIAAQYDD+CgogARBIMPl2viAAEHgwWuhBY/9pLNJ+scws
1n5j/oIAbBAGFzWnKAr/8CEEBgCgxJDzOR4aACA4sPqg3CABEHgwAPsaLTCA/nDcKmABXDD7FAAg
CRBYMPoKRAYAXOyQLHDdDg5E0w/8DEQGAIbfkChw3v8CAAYAl18QCAhE+XDfJgCb3hAJCUT/AgAG
@@ -6639,7 +6639,7 @@ Aw2qAQqZAinmwGP+ryniwAtYDACBBADKGgCBBAD9GgTdAw2ZAQqZAinmwGP+swAAAAAAAADz/1Ji
AABj8PP/XmIAAGPw0qDRD2wQBBo1Fg8CACigwSz65/0ahyAAEFgw/IducA4QSDDBlG2aDy6hcAzu
Af3hCHAEAlKwsbvHuxk1IP+7J2ABEGAwL5KFALEEAMgaCP8BD885zvfBnPkkLCAAEBAw0Q8AAAAA
AAD6ksEh4AJy8ADhBADNGg2qAQrKOWSv1i8gIvIKACA6ADfg0Q8AKCAjxPD5gY1wFBBwMC0gIv/d
-AgAAEFgwbeoPKKFwDIgB+NGIcAQCUrCxu/P/fm/7EFgwwKT8OGMQGBBYMFhBS8Ag0Q8AAABsEA4q
+AgAAEFgwbeoPKKFwDIgB+NGIcAQCUrCxu/P/fm/7EFgwwKT8OGMQGBBYMFhBT8Ag0Q8AAABsEA4q
Ih3AMCMkLimhAyihAv8CAAYBRs4QHDg3HzUpHjUpFzV5lxaeEJ8SLyAiHThU/RYJLAkAY/CcGCkg
K/kOQABEAH5wfpcafZcXfJcULSEgDQtF8AATaoAEPuAAAAAAAAAA/SEgIAAQWDD8CgAgDwA3oH6X
B32XBHyXAcDBGTcb/WhABAcBaDD2NdgSAABo8PQhHiwFACZw+TTFEgAAcPAIbjn0eEACAAAw8PiW
@@ -6652,3528 +6652,3528 @@ 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
-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
+AABYcPwKBCACEGgwWt/ujjAtICL8N7EQBBBQMP8gICAYEFgwWECXY/7Ui1j7jVcAGxBwMH7RL4o3
DwIADwIALaEV//rAIEACUrAPrwGv3/tcQCgAFP1Qwsha4gz1rAAPFAA2oGP/wi8gIgsOQ375xotZ
-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
+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
-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
+EFAw/SAiIBgQWDD+IEMiAAB48FhAG/sKJiAjEFAw+DxsYCIQaDBzowf/AgAKAETo0HOzAnU7JXQx
Ivk8FWAAEFAw9iRDIgAAErDRDwBmoIJoPO7zJEMiAAASsNEPLCIfLMIQ+vrqL+YANyD6LAACAABY
8AvAAGP/0wAALSIfLdIQZNBS8yRDIAAQEDDRDywgQ3yiAn3KQ3yyAnXKAnTJmSwiHyzCEMrE+iwA
AgAAWPALwABgABkqICIrIGr8IGsiAABo8Ful/GevhWAABQDGqmevfNKg0Q/GKtEPKiAiKyBq/CBr
IgAAaPBbpfNnr2Bj/+AAbBASKCEY9zT7EAEQKDDzICIgABBgMPwWBCAKADYgLiBmZOBuKSArwKAP
AgD/l1hwABBoMH6XCH2XBXyXAioKAfsKACBEADag9AoAIAAQUDANrxH/uwICAABQsFv8FwqmAmZi
-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
+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
-MPS0AgAAEFAw9AxAAJIAfnD/AgAAAET6UP8CAAAAtHZQ/wIAAAIYclD/RxhwARBQMMDi/k0BDgAH
+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
-2WTf1mTv0yogbmSlbRs2U7Gs/CRuKgAgXPArsOD/AgAMAJPS0NJg0Q8AAAB/RxPA4v5NAQ4AB3UQ
+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
-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
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACACJBgAAAAAAAAAABAAAAQgA
-iRQAAAAAAAAAAAQAAAIgAQy8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAIkG
-AAAAAAAAAAAEAAABCACJFAAAAAAAAAAABAAAAiABDLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAABAAAAAgAiQYAAAAAAAAAAAQAAAEIAIkUAAAAAAAAAAAEAAACIAEMvAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAAO/wABAAAAAAAACgEAgQAKAQABAAoBAAEACgEAAQAO
-AwEBAB7/gYEAHgKBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEbBAMDARsCAwMBGwMD
-AwEbAgEBAR8EgYEBK/+BgQEqAYGBASkBgYEBHwOBAQEfA4EBASz/gYEBPQKBBQE8/4UAATz/hQAB
-OQEFBQE+DwUFAS4EgYEBGwIBAQAOAoEBAS4CgYEADgIAAQAOAoEBAA4CAQEBGgGBgQEOAgEBAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAwEAAA4DAQEATwQBAQBfBAEB
-ADwEAQAAAAAAAABs/wEBAEwEAQEAHgIBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AHMAAAB9AAAAhwAAAJEAAAAAHwAAAAAAAAEAAAAAAAAAAgEAAAAAAAAEAgAAAAAAAAYUAAAAAAAA
-BxIAAAAAAAAIAwAAAAAAAAoVAAAAAAAADxMAAAAAAAAQBAAAAAAAACAFAAAAAAAAQAYAAAAAAACA
-BwAAAAAAAMAWAAAAAAABAAgAAAAAAAIACQAAAAAAAwAXAAAAAAAEAAoAAAAAAAgACwAAAAAADAAY
-AAAAAAAQAAwAAAAAABgAGgAAAAAAIAANAAAAAABAAA4AAAAAAIAADwAAAAAAwAAaAAAAAADgABsA
-AAAAAQAAEAAAAAABgAAcAAAAAAHAAB0AAAAAAeAAHgAAAAACAAARAAAAAAYhegAAAAUAAAAEAAAA
-AQAAAFIAAAATAAAAGwAAABYAAAAQAAAAAAAAAAAAAABSAAAAWwAIGzIAAAAGAAAADAAAAAIAAABn
-AAAAAAAAAB0AAAAUAAAAEAAAAAAAAAAAAAAAVwAAAGMACYloAAAABwAAAAIAAAACAAAA/QAAAAMA
-AAAeAAAAGgAAABAAAAADAAAAAAAAAFsAAABoAAoh/wAAAAcAAAACAAAAAgAAAGcAAAAcAAAAHgAA
-AB4AAABQAAAAAAAAAAIAAABcAAAAbAAKupUAAAAIAAAACgAAAAMAAAD1AAAAAQAAAB4AAAAaAAAA
-EAAAAAEAAAAAAAAAXQAAAG0ACyBPAAAACAAAAAoAAAADAAAAagAAAAIAAAAeAAAAGgAAABAAAAAC
-AAAAAAAAAF4AAABuAAun8QAAAAgAAAAKAAAAAwAAACkAAAACAAAAHwAAABwAAAAQAAAAAgAAAAIA
-AABfAAAAcQAMNQAAAAAIAAAACgAAAAMAAABSAAAAEwAAABsAAAAbAAAAUAAAAAAAAAAAAAAAYQAA
-AHMADELzAAAACAAAAAoAAAADAAAA9QAAAAEAAAAbAAAAGwAAABAAAAABAAAAAgAAAGEAAABzAAy3
-NgAAAAkAAAAGAAAAAwAAAP0AAAADAAAAHAAAABwAAAAQAAAAAwAAAAAAAABkAAAAcAANHO8AAAAJ
-AAAABgAAAAMAAAApAAAAAQAAABwAAAAcAAAAUAAAAAEAAAACAAAAZAAAAHEADj3VAAAACQAAAAYA
-AAADAAAAKgAAAB8AAAAfAAAAHwAAABAAAAAAAAAAAgAAAGYAAAByAA7VvgAAAAoAAAAJAAAABAAA
-AGoAAAACAAAAHAAAABwAAAAQAAAAAgAAAAAAAABmAAAAdwAPQkAAAAAKAAAACQAAAAQAAAD9AAAA
-AgAAAB0AAAAdAAAAUAAAAAIAAAACAAAAZgAAAHcAD7xSAAAACgAAAAkAAAAEAAAAKQAAAAEAAAAd
-AAAAHQAAAFAAAAABAAAAAgAAAGsAAAB4ABBGBAAAAAoAAAAJAAAABAAAAGoAAAAfAAAAHgAAAB4A
-AAAFAAAAAgAAAAIAAABrAAAAeQcAOwACADgABAM7AQAAAAABNgFsAZYA8AEgAVMA4QExAWEAvADk
-AQsA9QEiAUkAxgDrAQ8AwgDqARMAnQC/AN4AywDtAQ0AqgDJAOQAowDEAOAAgQCiAL0ArwDMAOMA
-lACwAMYAiwCoAL8AAACBAJ0AmgCzAMcAgQCbAK8AbgCPAKUAAAAAAAAAiQCfALEAbQCIAJsAAABh
-AHIAAAAAAAAAegCPAJ8AAAByAIcAAAAAAAAAAAAAAAAAAAAAAAAAAAD7ASYBagDZAP8BNgDuAS4B
-jACrANMBEwDWAPkBKgC5ANoBCgC3AOIBMACMAK0A4QC6ANkBBgCiAL4A5wCWALcA6gBlAIwAugCk
-AL8A5gCOAKgAzQB6AJgAwwAAAAAAlACRAKoAzQB7AJUAtwAAAHoAowAAAAAAAACAAJgAuABkAIEA
-owAAAAAAfQAAAAAAAABtAIYApQAAAGYAjgAAAAAAAAAAAAAAAAAAAAAAAAAAAQABKQFVAM4A8wEV
-AMcA7gEWAKEAwwDgAM0A7QEMAKsAygDjAKIAwQDdAH0AngC3AK0AyQDfAJMArQDBAIYAogC5AAAA
-AACLAJcArgDAAH0AlgCpAEwAgQCZAAAAAAAAAIUAmgCrAGIAfwCTAAAAAAAAAAAAAAAAAHYAiQCZ
-AAAAVgB5AAAAAAAAAAAAAAAAAGYAegCJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3wEDATEA
-vwDfARAAvADkASwAjwCvAOIAvQDcAQcApAC/AOcAlgC2AOYAVwCGALQApAC/AOQAjgCmAMoAdgCT
-ALwAAAAAAAAAjwCnAMgAeACRALIAAABtAJkAAAAAAAAAfACUALIAWgB6AJgAAAAAAAAAAAAAAAAA
-ZwCAAJ4AAAAAAIEAAAAAAAAAAAAAAAAAAABqAIoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADb
-AQABGwC3ANcA8ACwAM8A6ACQAK4AxgCzAM4A5ACZALIAxgCNAKcAvAAAAAAAjQCZAK8AwACAAJcA
-qQAAAHwAlAAAAAAAAACFAJkAqABaAHsAjwAAAAAAAAAAAAAAAAB0AIcAlQAAAAAAAAAAAAAAAAAA
-AAAAAABhAHUAgwAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAMwA6wEYALIAzwD2AKkAzAEAAIIAoQDKAK0AyADtAJgAsQDVAIMAoADHAAAAAACWAJUArQDO
-AIAAmAC5AAAAdQCdAAAAAAAAAH8AlgC0AFUAfQCfAAAAAAAAAAAAAAAAAGYAgACdAAAAAAB9AAAA
-AAAAAAAAAAAAAAAAYgCGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABfAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAP/w//D/wA/w/4CdsP8A+lD+AJmQ/AAJkPgAAADwAAAA/8D/wP+AX8D/APtA/gBbQP
-wAC0D4AAAA8AAAAMAAAAD8AAAA7AAAAPgAAADoAAAA8AAAAOAAAADAAAAAEAAAAAATiAAABoKgAA
-TiAAAYagAAGGoAACCNUAAgjVAAAAKAAAADIAAQRqAABoKgAASmcAAYagAAGGoAACCNUAAgjVAAAA
-KAAAADIAAVsBAABoKgAAUCAAAgjVAAGGoAACCNUAArZxAAAAJgAAADIAASluAABoKgAATSkAAgjV
-AAGGoAACCNUAArZxAAAAJgAAADIAAQRBAABoKgAASmcAAgjVAAGGoAACCNUAArZxAAAAJgAAADIA
-AXQGAABsgQAAVAEAAosKAAII1QACiwoAArZxAAAAHgAAAC0AAUWFAABsgQAAUWEAAosKAAII1QAC
-iwoAArZxAAAAHgAAAC0AASFaAABsgQAATuoAAosKAAII1QACiwoAArZxAAAAHgAAAC0AAQRqAABs
-gQAATJcAAosKAAII1QACiwoAArZxAAAAHgAAAC0AAYagAABvmwAAVs4AAosKAAII1QACiwoAAw1A
-AAAAHgAAACgAAVs4AABvmwAAVHUAAosKAAII1QACiwoAAw1AAAAAHgAAACgAATiAAABvmwAAUjwA
-AosKAAII1QACiwoAAw1AAAAAHgAAACgAARwYAABvnAAAUCEAAosKAAII1gACiwoAAw1AAAAAHgAA
-ACgAAWx0AABy4wAAV2MAAw1AAAKLCgACiwoAAw1AAAAAGwAAACMAAUtSAABy4wAAVVgAAw1AAAKL
-CgACiwoAAw1AAAAAGwAAACMAAS+2AABy4wAAU2UAAw1AAAKLCgACiwoAAw1AAAAAGwAAACMAARhZ
-AABy4wAAUYgAAw1AAAKLCgACiwoAAw1AAAAAGwAAACMAAXq6AAB2XwAAWj4AAw1AAAKLCgACiwoA
-Aw1AAAAAGQAAACMAAVsrAAB2XwAAWFYAAw1AAAKLCgACiwoAAw1AAAAAGQAAACMAAUFeAAB2XwAA
-VoEAAw1AAAKLCgACiwoAAw1AAAAAGQAAACMAASmTAAB2YAAAVMEAAw1BAAKLCwACiwsAAw1BAAAA
-GQAAACMAAREqAABvmwAAT90AAgjVAAII1QACiwoAAw1AAAAAHgAAACgAARcEAABsgQAATiAAAosK
-AAKLCgACiwoAAw1AAAAAGwAAACMAAAAAK2gjgxhqDQYLKgAAAAAAAAAAADIAAAPoAAAAKAAATiAA
-AAAAAAPQkACYloAAD0JAAJiWgAAAHCAAAABLAD0JAAAD0JAAmJaAAQEAAAMDAgIFBQQEBwcGBgAA
-ADIAAAPoAAAAZAAAw1AAAAAAAAPQkAPQkAAATEtAA9CQAAAAHCAAAABLAD0JAAAPQkAjw0YAAwIB
-AAcGBQQLCgkIDw4NDAAAADIAAAPoAAAACgAAAfQAAAAAAAAD6ACYloAAD0JAAJiWgAAAHCAAAABL
-AD0JAAAD0JAAmJaAAwIBAAcGBQQJCQgICwsKCgAAAAAAAAAAAAEAEAARAB4ADQASAAcAHwAOAAsA
-EwAVABsACAAXACAADwAdAAwABgAKABQAGgAWABwABQAJABkABAAYAAMAAgABAHsAdQD7APUARQBv
-AH0AdwBfAGkAxQDvAKMAPwD9APcAuwA5AN8A6QDPAJ0ARwBxAA8AWQAlAL8AEwBjAH8AeQBtAF0A
-PQC5AJsADQBhAGsACwAJAFEAHwAxAFMAxwDxACEAtQCPANkArQAzAKUAQQBVAJcAkwDjACkAyQD/
-APkA8wDDAO0A3QDnACMAvQA7ALcATwAdAI0A1wCRAOEA6wDbABsAiwCJAIcArwDRAJ8ANQAtALEA
-0wAXAKcASQBzAEMAZwChADcAzQBXABEAWwCZAAcALwCzAKsAlQAnAMEA5QBNANUAGQCFACsAFQBl
-AMsABQCpAEsAgwADAIEAAAD6APQAfAB2AMQA7gD8APYA3gDoAEYAcAAkAL4AfgB4ADwAuABgAGoA
-UAAeAMYA8ACOANgApABAAJIA4gD+APgA7ADcALwAOgAcAIwA4ADqAIoAiADQAJ4AsADSAEgAcgCg
-ADYAEABaAC4AsgAmAMAA1AAYABQAZACoAEoAgAB6AHQARABuAF4AaACiAD4AugA4AM4AnAAOAFgA
-EgBiAGwAXACaAAwACgAIADAAUgAgALQArAAyAFQAlgAoAMgA8gDCAOYAIgC2AE4A1gCQANoAGgCG
-AK4ANAAsABYApgBCAGYAzABWAJgABgCqAJQA5ABMAIQAKgDKAAQAggACAAEAAwACAAQAAAAAAAAA
-AAABAAIAHAAbABYAFQAeAB0AGAAXAAwACwAQAA8AIAAfABoAGQAUABMACgAJAA4ADQASABEACAAH
-AAYABQAEAAMAAQAAAAIABAAAAAAAAAAAAAAwBAAAMBAAAFncAABagAAAWoQAAFqIAABajAAAWpAA
-AZQwAAAQJAAAEDAAABA8AAAQ3AAAEQwAAHssAAB7NAAB4owAAeaMAAHqjAAB7owAAfKMAAH2jAAB
-+owAAf6MAACNzAAAjoAAAH50AACP3AABkVgAAZJwAACP/AAEExwABBMYAAQTEAAEkxwABJMYAAST
-EAAAd+AAAHfkAAB39AAAeAQAAZw8AAEQdAABEIQAAJQIAACYXAAAlgwAAJYUAACWIAAAliwAAJbE
-AADQKAAAkAgAAwjcAANI3AADiNwAA8jcAAMI5AADSOQAA4jkAAPI5AABkFQAAGAcAAGg2AABkJAA
-AHfgAAB35AAAd/QAAHgEAAB42AAAeOAAAHj0AAUAeAAFCHgABRMIAAGUBAAB48AAAefAAAHrwAAB
-78AAAfPAAAH3wAAB+8AAAf/AAAGUDAAAAAAAAAAAAAAAAAAAMAC///9AAAAwCL///0AAAZQQn///
-/wABlDQAAAAQAAGUCJ//4/8AAZQ4AAAAEAAAECjh////AAAQLOH///8AABA0Af///wAAEDgB////
-AAAQQAAEAAAAABEQAP///wAAERQA////AAB7KAB9/+IAAHswP//u/wAAezgAAAABAAB7QD//7v8A
-AHwkAH3/4gAB4ogACAAAAAHmiAAIAAAAAeqIAAgAAAAB7ogACAAAAAHyiAAIAAAAAfaIAAgAAAAB
-+ogACAAAAAH+iAAIAAAAAI3I////8AAAjdD////wAACOfAAAAPAAAI6EAAAA8AAAfnB/v/9/AAB+
-eH+//38AAH4AAsAAAAABkVQB////AAGRnAH///8AAI/YA3///wAAj/j/////AAQTFAAAAAcABBMM
-AAAACwAEkxQAAAAHAASTDAAAAAsAAHfcAAAAAwAAd/T/////AAB4BAAAAAMAAZw4AAHAQAABnPgA
-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
-////H/+bdB//q7wf/51wH/+tsB//mVgf/53QH/+bPB//rjQAAP/9H/+rNOMAAgDi//8AIAtQYCAI
-6EAgC6oQIAAAAAAwAAAAYAAAIGAAANAAAAAgC6lQIAup4AAAEAAgAwjIH/+wMB//rDQf/4CwH/+s
-sP//8AAgC6rgIAtSoCALUyAgC1OQIAuqkCALqlAgC6qwH/+sTCALVCAABAAA4QAyAB//gOAf/4Eg
-H/+BYB//msz/gA////4AHwAAe2Af/OIACAAAAB//nKgf/5WoH/+quB//lRThAv4A4QO+AOEDPgDh
-A34A4QHiAOEBDgDhAJIA///w/x//qbAAAAkA4QEOBOEBDgjhAQ4M//AAAAACgAb/+///IAtcYCAL
-XMAf/4HgH/+cKB//mzAf/644EAAAAP/w//8gAwyAH/+ZsAAAfkzhAIoAAADwACALXTAgC12QIAtd
-8B//rggf/6woH/+qICALXjAgC16wIAuwwCALXmAf/51kIAtfMCALXvAf/5uwIAuvQCALX6AgC1/g
-IAuxsCALsRDf0AAAIAuxUB//rEAf/6wE/4AAAP//4AAgC2AgIAtgUCALrvAgAwyMIAdURB//rfgg
-C2CQH/+sRB//sswf/7MAH/+shAQAAAgSAAAAIAusYB//sbyBAAAAAAAwACALrJAgAwyIH/+xHB//
-s9gf/66wH/+zGEkAAAAgC6uwIAur8CALqwAgC6tgLgA2AAAPA/8DEQAAAxUAACAHUnAgC2DQH/+r
-YB//mlAf/6oMH/+djB//nsAgAMQgH//tMB//7Hwf/62sH//uNB//q0QCAIIQAgACEAAAIAACAAAQ
-ABoAAAD6xogAIAAA8AAAAB//rDzhAwYAIAdSxCAHU2wf/4HwIAthICALYPAgC2FQIAuukP//f/8A
-ADIAH/+bXB//nXQgC66wAAD4AAA8PDwf/7EwH/+WGB//mdQf/62cChQoUCAIDwQf/6w4IAdUAB//
-lZwgAw60H/+USP//x/8AAv/AH/+bBCALsHAgC7AQIAuyoB//m6wgC2HwIAuyQCALshAgC2GAIAuy
-cCALr6Af/5uoH/+boB//qbgf/6m0H/+CcB//qpAf/6rkH/+b1B//m9Af/4KQH/+q6CADCTAgAws4
-IAdUUB//grAf/6pwH/+qZB//qmgf/6psH/+qoB//qpwf/6qYH/+qlB//qogf/6p8H/+qgB//qoQf
-/4LgH/+p8B//mygAAEADH/+UtB//qaSH////H/+bjB//nGgAD//wIAtm4B//g3AgC2dAH/+DgB//
-rlQgC2eAH/+chCALZ9Af/5xYIAtoACALaDAf/4OQH/+byAAAJYAgC2hgIAtooB//mXAf/4OwH/+b
-cB//mgQf/5lsH/+DuP//AAAD5/wYIAto0B//g8Af/6sgIAMJhB//qxwP////IAMO4CALaTAgCBPk
-///rICAIE5T//+twIAgSVCAIE4z//+ywIAgRdCAIEkz//+2QH/+b7AP//+AABHIMAARyFAAEchwA
-BHAUAARwKAAEcCAABHAsAACFgD///+AABEAkAARATAAESiQABADgAAQABCALa9AgC2wAAAQCxAAE
-AsAgC7eAIAu3sAAEcGQgC7fgAARBwAAEQcQABEHIAARAeAAEQNwABEFAAARBRCALbNAgC20QIAtt
-QCALbDAgC2xwIAtsoAAEcFgAABAoAARBYCALbZAAAHd3AAAzMyALbtAgC23QIAtuUCALbpAgC24Q
-IAttYAAAICgABHQYAARKwAAEQMAABEDEAARB8AAEQfQABHQUIAu3QCALb/AgC2+wIAtvcCALbzAg
-C27wAAQCcAAACPAABAJ0AAQCfAAEApAAAL8oAARwXAAEdAAAAPAGAARL8AAEcigAAZsvAAFjHQAE
-ATAABADsAAQBCAAEdgAABAEEAAR2BAAA//gABAEAAAQA5AAEdggAAP/BAARyAAAAVVUABHIEAAQA
-+AAEANwABADYAARySAAEATgABAEYAARyTAAEAPQABHJQAAR0CAAEcggABEBIAARK3CALcDAgC3Bw
-IAtwsAAEQSwABEE8AARA4CALcPAABEEAIAtxIAAEcEgABHBgAARyIAAEdgwABHgEgBAAACALuCAg
-Aw9wgBIAAwAEAOiAEAADAAQAwAAATiAABADMAAQAxAAEAMgABAE0IAgG1CAICxQAAgAhAAQAgAAP
-/ykABABEIAtxUAAEAkQABAJMAAQCSAYGAAAABAGAAAAeeAABMLAABADQAAQA1AAEAPAABAD8AAII
-1QABBGoABAEMAAQBEAAAosIABAEUAAQBHAAEASQABAEoAAQBLAAEAUAABAFEAAQCUAAEASAABAJg
-AAQCZAAEAlQAAQAhdzWUAAAEQfwABEv8AACAIAAACAgABHAwIAgDwAAEYMAABGDEAACIAAAEQdQA
-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
-AjGw+swBIgAAGzD65gAgCAJzsPP/u2IAAGKwdKmvL8QA8/+pYgAAKzDKaWhhV2hiR8gxJzQAZF9U
-9FQAIAAQEDDRD8gxJzQAZF9C9FQAIAAQEDDRDwCOE/bmACAHADTgJzQAZFBBGPa5H/ZRqP/0VAAi
-ACB4sNEPAIsV+hIBIAAQYDBbme+LFPoSACAAEGAwW5nsiRP2lgAgBwA04Cc0AMhRJFQAZq7lG/ao
-GvZBq6qqItEPHfalHPY+/RIDLAAgazD/1gAiACBgsNEPAAAAbBAEizAmsAAnCgD4aUliAABK8GRg
-QQu5AvgaACAAEFAw/AoJICMQaDBtCChobBV8YRJ9YTb4jP8gAgJSsPYkACACAhCwsXereSaQAGhp
-UGSAY2RgSmP/0MBA9CQAIAICQnD4NgAgABAQMNEPLJAA+MkpYAAQKDCre/awACIAADrwbQgU9GAY
-YAICKXAmcAGxd/hpCWIAAEnwY//kq3urWcmCwND9JAAgAgJycP42ACIAABKw0Q/GKtEPAABsEAZb
-/v32prZiAAASsBT2bhn2P/z2bBABEFgw/fZsEAAQcDAf9msvxqUtxqQuxqcY9mkoxqYf9mgvxqke
-9mguxqgtxqsY9mYoxqotQoIf9mUe9mUPAgAP3QEO3QItRoIc9mMsRoYrRocoQqoPAgAIGEv/AgAG
-A/FOEBf2XShyM/b2XRaUADYg8vZcH/4QSDDz9hwf/xAoMBv2WRr2WQ8CACq2AC8ywBj2Vwj/AS82
-wC0y0C7qwP7dAQEVEHAwDt0CLTbQHPZRLDbRKjLbG/ZPC6oCKjbbGPZOKCY1LjLdL/rfD+4BLjbd
-KzLSHfZKHPZKDbsBDLsCKzbSKzLSGvXGKqDACbsB+zbSIjgBOqAsMtMe9kId9kMOzAENzAIsNtMl
-NvQlNvXA9C4y3g/uAi423iwywR32PP3MAQCAEGgwDcwCLDbBKjLCG/Y4C6oCKjbCLyItGfY2GPY2
-+vY2HgBAT/D89jUeCQBH8P8mLSAFEFgwW5ciGvYv/PYwEAYQWDBblx4a9iz89iwQBxBYMFuXGxr2
-KPz2KRAIEFgwW5cXGvYl/PYlEAkQWDBblxQa9iH89iIQChBYMFuXEBr2Hvz2HhALEFgwW5cNGvYc
-HPYeGPYc+CYOICAQWDAPAgBblwf69hcRQRBYMP0KACD/EGAwW5ko+vYSEUEQWDD9CgAg/xBgMFuZ
-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
-Dt1Q/2wAAAIQUDD8FgAiAABy8PzqRBAGEFgwW7Zf8/6Sb+oQEDCWERzqP/oWAiIAAHlw+xYALAAg
-V3D7CgYgAhBQMFu2VfP+am/0EBAwAAAAAAD6CgIgBhBYMPzqNRIAAGiwW7ZNY/ymAAD6CgIgBhBY
-MPzqMBIAAGiwW7ZHY/yOAABsEAYZ6sYa6sYokAQoFAQpkgApFgBb/LwV6sMa6lL8UXohQBBYMFuL
-Pxrqvw8CAA8CACqhf/IaACIBf+qQ+upJEUEQWDBbizP06fgcCAFQMCxUVCtC02azAC5SGy1SGh/q
-s67Y/wIACgGBx9DHfylSGP1GxCLfADZgKUbGLFIc9uooEoMANyApUh5kkniLX8Ax/rIVYAAQUDBt
-CAqxqgChBAA9GnvbAmP/7i1QwhnqnyhSESpWEguZLA2ILPlWFCH8AkIwKFYTLEbIiF8uUMKh7i7g
-AC1SEQLuEPhGzSwJAHdwKVISKZz1/UbOKQAEPmAtQtse6o8O3QH4Uh4oCQBucClG2yhGyo5eLVDD
-od0t0AApUhAB3RD+RssoCQBucC5SIS1SIA7YCPlGzCoBKEfQG+qBLlDDKlDCL1IR/FIQLgAgW7D+
-4IAqACBasCqggP/MCAoAIHKw++p4GgAgYrAoUMMvUhAuUhH5UMIgGBBgMAz/LAzuLAnuLAj/LAD/
-EfpmGy4JAHuwLkbHCqoR/UbFKgAgU3AtsnAM3SwK3RH6ZhgqACBqsCuycQy7LAq7EfpmGSoAIFqw
-KmYaGupg/SoAIAAQYDD+CgEgAhBYMPtmEyAAEHgwWlv/9qGxYgAAErAjZhPE8C9mIS1SJStSJB7q
-VBnp4Q17OCtWJCxSJSpSJKyq+5bbIf4CUrAoUictUiYqltwIfTgtViYvUicsUiavzP2W1yH+AmMw
-K1IpKFIoLJbYC3g4KFYoKlIpL1Ioqv/45vUh/gJ78CxSKC/m9i1SKStSKK27/JbfIf4CWvAqUisv
-UiorluAKfzgvViooUistUiqo3f/m9yH+AmtwK1IqLeb4LFIrKlIqrKr7luMh/gJSsChSLS5SLCqW
-5Ah+OC5WLC9SLS1SLK/d/pbhIf4Ca3AsUi8qUi4tluIMejgqVi4rUi8oUi6riPqW6SH+AkIwKJbq
-LkLwH+obD+4CLkbwLULCLVY3LELYLFY4K0LZK1Y5KkLbKlY6KULwKVY7KELsKFY80Q/AICdGxidG
-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
-UDD1FgAgYBBAMPgWASAyEFgwW6uyH+BkHOBwLfJM/vJLIAUQUDD/8gcgMhBYMFurq8Ag+t+9EUAQ
-WDBbgKYY4FoqhoL637gRQRBYMFuAotygHd+l+t+0EUEQWDD54GARABBwMPnWCCwJAHMwW4Ce+Ao/
-LAAQcDD8CgYgABBYMBrfQytG0ytG0itG1CtG2StG2CtG3itG4CtG5StG5CtG5itG6itG7CtG9ytG
-9itG/CtG/i5G8S5G8/5G+SABEEgwKUbiLEbnLEb9KEbw+EbyL/8QeDD/RtUgAxBoMC1G3P9G2yAA
-EGgw/Ub6IBsQaDD9RuggEBB4MC9G9Bje3pmtHOA6LEbr+EbaIBoQSDApRtYf39L+4DQQHhBQMCpG
-0P5G4SAREFAwKkbuL0bf/98vE/8QSDD5RvggDxBAMChG/y/ywhvgKitG7dEPAAAAAIga+Iz/IAEQ
-SDD4FgogAgIqMPWVOQH9zRog+goFIDIQWDD8EgkgABBoMFurWPP7f2AQEFAwbBAEFd8BKFIV8goA
-IAsANiDRDwAAAAAA+t9jEUEQWDBbgEwT4AcpMUf0ChAgABAQMPuXE3IAAFqwHd9KGuAMHOAHLNYI
-IqZ8+t9XEQAQYDD8vAIBQRBYMFuAQiQ29BzgBB3fnR/eoxvf/iI2+hjf/hnf/Sk26/g27SwAEFAw
-KjbxKjbzKjb5+zbhL/8QEDAiNtXyNtsgPxBwMC428C428i822v023yAREHgw/zbuIA8QaDD9Nv8g
-ABBwMC420y420i421C422S422C423i424C425S425C425i426i427C429y429i42/P42/iAGEBAw
-8jbnIC4QWDDyNv0gHhBQMPo20CAbEFAw+jboIBoQEDDyNtYgARAQMPI24iADEHAw/jbcI/8QcDD+
-NvggBBBQMFurCfJWFSAAEBAw0Q8AAABsEATz38wR/BBQMBTfGwoMPylC3wlZFCk2HChC4QhoFCg2
-HSRC4wRUFCQ2HhLevyIi3gICQPI0kCAAEBAw0Q8AbBAE9N+9EAAQEDAiRkUiRkQiRkMiRkIjQksj
-RXwjRX0jRX4jRX8DMxQjRYAjRYEjRYIjRYPRDwBsEAYb3k0Z368U37D1368QABAwMPkWACAQEGgw
-900DIBACETDzXAACAABQsNgw/N+oEgAASTAPAgDTD9MPbdog/IZRIGACQjArhZQphkH5hkIgYAJK
-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
+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
+PrgAAAAAAAAAAAAAAAAgAz4gIANAECAE2IAgBNZgIAM7ZCADPDwgAz0UIATUmCADOuQgAyi0IAgo
+LCAIKUggAzrcIAP15CADM1AgAzIQIAMw7CADONwAAAAAAAAAAAAAAAAgAzf8IAM2ICADLhQgA/aI
+IAMv1CADKaggAy9QIAMw5AAAAAAAAAAAAAABAgABAAAAAAAAAAAAAAEAAQIDBAUCMjIAAAAAAAAA
+AAAAAAAAAAIAAAAAAAAAAAAAAAAAAAADEAAAAAAAAAAAAAAAAAAAAAAAAf8BAAAAAAABAAAAAB/8
+4TAAAAAA4AAA4AEAAAAgCRjoAAAAASAJDxwAAAACIAkJ8AAAAAEgCQZgAAAAASAJAAAAAAAEIAjs
+PAAAAAEgCOswAAAAAQAAAAAAAAAAAAEAAQAAAAAAAAAAAAAAAAQAAAAIAIkGAAAAAAAAAAAEAAAB
+CACJFAAAAAAAAAAABAAAAiABDLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgA
+iQYAAAAAAAAAAAQAAAEIAIkUAAAAAAAAAAAEAAACIAEMvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAEAAAACACJBgAAAAAAAAAABAAAAQgAiRQAAAAAAAAAAAQAAAIgAQy8AAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAIkGAAAAAAAAAAAEAAABCACJFAAAAAAAAAAABAAA
+AiABDLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAADv8AAQAAAAAAAAoBAIEA
+CgEAAQAKAQABAAoBAAEADgMBAQAe/4GBAB4CgQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAABGwQDAwEbAgMDARsDAwMBGwIBAQEfBIGBASv/gYEBKgGBgQEpAYGBAR8DgQEBHwOBAQEs/4GB
+AT0CgQUBPP+FAAE8/4UAATkBBQUBPg8FBQEuBIGBARsCAQEADgKBAQEuAoGBAA4CAAEADgKBAQAO
+AgEBARoBgYEBDgIBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAMB
+AAAOAwEBAE8EAQEAXwQBAQA8BAEAAAAAAAAAbP8BAQBMBAEBAB4CAQEAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAABzAAAAfQAAAIcAAACRAAAAAB8AAAAAAAABAAAAAAAAAAIBAAAAAAAA
+BAIAAAAAAAAGFAAAAAAAAAcSAAAAAAAACAMAAAAAAAAKFQAAAAAAAA8TAAAAAAAAEAQAAAAAAAAg
+BQAAAAAAAEAGAAAAAAAAgAcAAAAAAADAFgAAAAAAAQAIAAAAAAACAAkAAAAAAAMAFwAAAAAABAAK
+AAAAAAAIAAsAAAAAAAwAGAAAAAAAEAAMAAAAAAAYABoAAAAAACAADQAAAAAAQAAOAAAAAACAAA8A
+AAAAAMAAGgAAAAAA4AAbAAAAAAEAABAAAAAAAYAAHAAAAAABwAAdAAAAAAHgAB4AAAAAAgAAEQAA
+AAAGIXoAAAAFAAAABAAAAAEAAABSAAAAEwAAABsAAAAWAAAAEAAAAAAAAAAAAAAAUgAAAFsACBsy
+AAAABgAAAAwAAAACAAAAZwAAAAAAAAAdAAAAFAAAABAAAAAAAAAAAAAAAFcAAABjAAmJaAAAAAcA
+AAACAAAAAgAAAP0AAAADAAAAHgAAABoAAAAQAAAAAwAAAAAAAABbAAAAaAAKIf8AAAAHAAAAAgAA
+AAIAAABnAAAAHAAAAB4AAAAeAAAAUAAAAAAAAAACAAAAXAAAAGwACrqVAAAACAAAAAoAAAADAAAA
+9QAAAAEAAAAeAAAAGgAAABAAAAABAAAAAAAAAF0AAABtAAsgTwAAAAgAAAAKAAAAAwAAAGoAAAAC
+AAAAHgAAABoAAAAQAAAAAgAAAAAAAABeAAAAbgALp/EAAAAIAAAACgAAAAMAAAApAAAAAgAAAB8A
+AAAcAAAAEAAAAAIAAAACAAAAXwAAAHEADDUAAAAACAAAAAoAAAADAAAAUgAAABMAAAAbAAAAGwAA
+AFAAAAAAAAAAAAAAAGEAAABzAAxC8wAAAAgAAAAKAAAAAwAAAPUAAAABAAAAGwAAABsAAAAQAAAA
+AQAAAAIAAABhAAAAcwAMtzYAAAAJAAAABgAAAAMAAAD9AAAAAwAAABwAAAAcAAAAEAAAAAMAAAAA
+AAAAZAAAAHAADRzvAAAACQAAAAYAAAADAAAAKQAAAAEAAAAcAAAAHAAAAFAAAAABAAAAAgAAAGQA
+AABxAA491QAAAAkAAAAGAAAAAwAAACoAAAAfAAAAHwAAAB8AAAAQAAAAAAAAAAIAAABmAAAAcgAO
+1b4AAAAKAAAACQAAAAQAAABqAAAAAgAAABwAAAAcAAAAEAAAAAIAAAAAAAAAZgAAAHcAD0JAAAAA
+CgAAAAkAAAAEAAAA/QAAAAIAAAAdAAAAHQAAAFAAAAACAAAAAgAAAGYAAAB3AA+8UgAAAAoAAAAJ
+AAAABAAAACkAAAABAAAAHQAAAB0AAABQAAAAAQAAAAIAAABrAAAAeAAQRgQAAAAKAAAACQAAAAQA
+AABqAAAAHwAAAB4AAAAeAAAABQAAAAIAAAACAAAAawAAAHkHADsAAgA4AAQDOwEAAAAAATYBbAGW
+APABIAFTAOEBMQFhALwA5AELAPUBIgFJAMYA6wEPAMIA6gETAJ0AvwDeAMsA7QENAKoAyQDkAKMA
+xADgAIEAogC9AK8AzADjAJQAsADGAIsAqAC/AAAAgQCdAJoAswDHAIEAmwCvAG4AjwClAAAAAAAA
+AIkAnwCxAG0AiACbAAAAYQByAAAAAAAAAHoAjwCfAAAAcgCHAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++wEmAWoA2QD/ATYA7gEuAYwAqwDTARMA1gD5ASoAuQDaAQoAtwDiATAAjACtAOEAugDZAQYAogC+
+AOcAlgC3AOoAZQCMALoApAC/AOYAjgCoAM0AegCYAMMAAAAAAJQAkQCqAM0AewCVALcAAAB6AKMA
+AAAAAAAAgACYALgAZACBAKMAAAAAAH0AAAAAAAAAbQCGAKUAAABmAI4AAAAAAAAAAAAAAAAAAAAA
+AAAAAAEAASkBVQDOAPMBFQDHAO4BFgChAMMA4ADNAO0BDACrAMoA4wCiAMEA3QB9AJ4AtwCtAMkA
+3wCTAK0AwQCGAKIAuQAAAAAAiwCXAK4AwAB9AJYAqQBMAIEAmQAAAAAAAACFAJoAqwBiAH8AkwAA
+AAAAAAAAAAAAAAB2AIkAmQAAAFYAeQAAAAAAAAAAAAAAAABmAHoAiQAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAN8BAwExAL8A3wEQALwA5AEsAI8ArwDiAL0A3AEHAKQAvwDnAJYAtgDmAFcAhgC0
+AKQAvwDkAI4ApgDKAHYAkwC8AAAAAAAAAI8ApwDIAHgAkQCyAAAAbQCZAAAAAAAAAHwAlACyAFoA
+egCYAAAAAAAAAAAAAAAAAGcAgACeAAAAAACBAAAAAAAAAAAAAAAAAAAAagCKAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAA2wEAARsAtwDXAPAAsADPAOgAkACuAMYAswDOAOQAmQCyAMYAjQCnALwA
+AAAAAI0AmQCvAMAAgACXAKkAAAB8AJQAAAAAAAAAhQCZAKgAWgB7AI8AAAAAAAAAAAAAAAAAdACH
+AJUAAAAAAAAAAAAAAAAAAAAAAAAAYQB1AIMAAAAAAAAAAAAAAAAAAAAAAAAAAABgAHEAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAADMAOsBGACyAM8A9gCpAMwBAACCAKEAygCtAMgA7QCYALEA1QCD
+AKAAxwAAAAAAlgCVAK0AzgCAAJgAuQAAAHUAnQAAAAAAAAB/AJYAtABVAH0AnwAAAAAAAAAAAAAA
+AABmAIAAnQAAAAAAfQAAAAAAAAAAAAAAAAAAAGIAhgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXwAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8P/w/8AP8P+AnbD/APpQ/gCZkPwACZD4AAAA8AAAAP
+/A/8D/gF/A/wD7QP4AW0D8AAtA+AAAAPAAAADAAAAA/AAAAOwAAAD4AAAA6AAAAPAAAADgAAAAwA
+AAABAAAAAAE4gAAAaCoAAE4gAAGGoAABhqAAAgjVAAII1QAAACgAAAAyAAEEagAAaCoAAEpnAAGG
+oAABhqAAAgjVAAII1QAAACgAAAAyAAFbAQAAaCoAAFAgAAII1QABhqAAAgjVAAK2cQAAACYAAAAy
+AAEpbgAAaCoAAE0pAAII1QABhqAAAgjVAAK2cQAAACYAAAAyAAEEQQAAaCoAAEpnAAII1QABhqAA
+AgjVAAK2cQAAACYAAAAyAAF0BgAAbIEAAFQBAAKLCgACCNUAAosKAAK2cQAAAB4AAAAtAAFFhQAA
+bIEAAFFhAAKLCgACCNUAAosKAAK2cQAAAB4AAAAtAAEhWgAAbIEAAE7qAAKLCgACCNUAAosKAAK2
+cQAAAB4AAAAtAAEEagAAbIEAAEyXAAKLCgACCNUAAosKAAK2cQAAAB4AAAAtAAGGoAAAb5sAAFbO
+AAKLCgACCNUAAosKAAMNQAAAAB4AAAAoAAFbOAAAb5sAAFR1AAKLCgACCNUAAosKAAMNQAAAAB4A
+AAAoAAE4gAAAb5sAAFI8AAKLCgACCNUAAosKAAMNQAAAAB4AAAAoAAEcGAAAb5wAAFAhAAKLCgAC
+CNYAAosKAAMNQAAAAB4AAAAoAAFsdAAAcuMAAFdjAAMNQAACiwoAAosKAAMNQAAAABsAAAAjAAFL
+UgAAcuMAAFVYAAMNQAACiwoAAosKAAMNQAAAABsAAAAjAAEvtgAAcuMAAFNlAAMNQAACiwoAAosK
+AAMNQAAAABsAAAAjAAEYWQAAcuMAAFGIAAMNQAACiwoAAosKAAMNQAAAABsAAAAjAAF6ugAAdl8A
+AFo+AAMNQAACiwoAAosKAAMNQAAAABkAAAAjAAFbKwAAdl8AAFhWAAMNQAACiwoAAosKAAMNQAAA
+ABkAAAAjAAFBXgAAdl8AAFaBAAMNQAACiwoAAosKAAMNQAAAABkAAAAjAAEpkwAAdmAAAFTBAAMN
+QQACiwsAAosLAAMNQQAAABkAAAAjAAERKgAAb5sAAE/dAAII1QACCNUAAosKAAMNQAAAAB4AAAAo
+AAEXBAAAbIEAAE4gAAKLCgACiwoAAosKAAMNQAAAABsAAAAjAAAAACtoI4MYag0GCyoAAAAAAAAA
+AAAyAAAD6AAAACgAAE4gAAAAAAAD0JAAmJaAAA9CQACYloAAABwgAAAASwA9CQAAA9CQAJiWgAEB
+AAADAwICBQUEBAcHBgYAAAAyAAAD6AAAAGQAAMNQAAAAAAAD0JAD0JAAAExLQAPQkAAAABwgAAAA
+SwA9CQAAD0JAI8NGAAMCAQAHBgUECwoJCA8ODQwAAAAyAAAD6AAAAAoAAAH0AAAAAAAAA+gAmJaA
+AA9CQACYloAAABwgAAAASwA9CQAAA9CQAJiWgAMCAQAHBgUECQkICAsLCgoAAAAAAAAAAAABABAA
+EQAeAA0AEgAHAB8ADgALABMAFQAbAAgAFwAgAA8AHQAMAAYACgAUABoAFgAcAAUACQAZAAQAGAAD
+AAIAAQB7AHUA+wD1AEUAbwB9AHcAXwBpAMUA7wCjAD8A/QD3ALsAOQDfAOkAzwCdAEcAcQAPAFkA
+JQC/ABMAYwB/AHkAbQBdAD0AuQCbAA0AYQBrAAsACQBRAB8AMQBTAMcA8QAhALUAjwDZAK0AMwCl
+AEEAVQCXAJMA4wApAMkA/wD5APMAwwDtAN0A5wAjAL0AOwC3AE8AHQCNANcAkQDhAOsA2wAbAIsA
+iQCHAK8A0QCfADUALQCxANMAFwCnAEkAcwBDAGcAoQA3AM0AVwARAFsAmQAHAC8AswCrAJUAJwDB
+AOUATQDVABkAhQArABUAZQDLAAUAqQBLAIMAAwCBAAAA+gD0AHwAdgDEAO4A/AD2AN4A6ABGAHAA
+JAC+AH4AeAA8ALgAYABqAFAAHgDGAPAAjgDYAKQAQACSAOIA/gD4AOwA3AC8ADoAHACMAOAA6gCK
+AIgA0ACeALAA0gBIAHIAoAA2ABAAWgAuALIAJgDAANQAGAAUAGQAqABKAIAAegB0AEQAbgBeAGgA
+ogA+ALoAOADOAJwADgBYABIAYgBsAFwAmgAMAAoACAAwAFIAIAC0AKwAMgBUAJYAKADIAPIAwgDm
+ACIAtgBOANYAkADaABoAhgCuADQALAAWAKYAQgBmAMwAVgCYAAYAqgCUAOQATACEACoAygAEAIIA
+AgABAAMAAgAEAAAAAAAAAAAAAQACABwAGwAWABUAHgAdABgAFwAMAAsAEAAPACAAHwAaABkAFAAT
+AAoACQAOAA0AEgARAAgABwAGAAUABAADAAEAAAACAAQAAAAAAAAAAAAAMAQAADAQAABZ3AAAWoAA
+AFqEAABaiAAAWowAAFqQAAGUMAAAECQAABAwAAAQPAAAENwAABEMAAB7LAAAezQAAeKMAAHmjAAB
+6owAAe6MAAHyjAAB9owAAfqMAAH+jAAAjcwAAI6AAAB+dAAAj9wAAZFYAAGScAAAj/wABBMcAAQT
+GAAEExAABJMcAASTGAAEkxAAAHfgAAB35AAAd/QAAHgEAAGcPAABEHQAARCEAACUCAAAmFwAAJYM
+AACWFAAAliAAAJYsAACWxAAA0CgAAJAIAAMI3AADSNwAA4jcAAPI3AADCOQAA0jkAAOI5AADyOQA
+AZBUAABgHAABoNgAAZCQAAB34AAAd+QAAHf0AAB4BAAAeNgAAHjgAAB49AAFAHgABQh4AAUTCAAB
+lAQAAePAAAHnwAAB68AAAe/AAAHzwAAB98AAAfvAAAH/wAABlAwAAAAAAAAAAAAAAAAAADAAv///
+QAAAMAi///9AAAGUEJ////8AAZQ0AAAAEAABlAif/+P/AAGUOAAAABAAABAo4f///wAAECzh////
+AAAQNAH///8AABA4Af///wAAEEAABAAAAAAREAD///8AABEUAP///wAAeygAff/iAAB7MD//7v8A
+AHs4AAAAAQAAe0A//+7/AAB8JAB9/+IAAeKIAAgAAAAB5ogACAAAAAHqiAAIAAAAAe6IAAgAAAAB
+8ogACAAAAAH2iAAIAAAAAfqIAAgAAAAB/ogACAAAAACNyP////AAAI3Q////8AAAjnwAAADwAACO
+hAAAAPAAAH5wf7//fwAAfnh/v/9/AAB+AALAAAAAAZFUAf///wABkZwB////AACP2AN///8AAI/4
+/////wAEExQAAAAHAAQTDAAAAAsABJMUAAAABwAEkwwAAAALAAB33AAAAAMAAHf0/////wAAeAQA
+AAADAAGcOAABwEAAAZz4AAHAQAAAkAQAAAA+AAEQeAD///8AARB8AP///wABEIgAAAAAAACUBAAA
+//8AAJQQAAD//wAAmFQAAAH/AACYWAAAAf8AAJYIAAAAAAAAlhwA////AACWJAD///8AAJYoAP//
+/wAAljAA////AADQIAAAAAcAANAkAAAABwADCNgAAAADAANI2AAAAAMAA4jYAAAAAwADyNgAAAAD
+AAMI5AAAAAMAA0jkAAAAAwADiOQAAAADAAPI5AAAAAMAAZBQAAAA7wABoNQAAAGDAAGQjAA4AAAA
+AZCYADgAAAAFAHQAAAAHAAUAcAAAAAUABQh0AAAABwAFCHAAAAAFAAUTBAAAAAEgAxCwIAjYHCAD
+ELQgCOeIIAMQwCAI5pggAxDMIAjmSCADEOAgCOWcIAMQ+CAI5DAgAxEIIAjjGCADERAgCOLwIAMR
+JCAI4sggAxE0IAjimCADEUAgCOF8IAMRSCAI4VQgAxFcIAjhICADEWggCN+8IAMRcCAI3xQgAxGA
+IAjeECADEYwgCN0AIAMRnCAI2/ggAxGsIAjazCADEcQgCNecIAMR3CAI11AgAxHwIAjWvCADEgQg
+CNaUIAMSGCAI1ZQgAxIcIAjUpCADEiggCNOkIAMSMCAI03wAAAAAAAAAACADEjwgCNM8IAMSQCAI
+0sAgAxJIIAjSiCADElAgCNJQIAMSXCAI0hggAxJgIAjR4CADEmggCNGoIAMSdCAI0XAgAxJ4IAjS
++CADEoAgCNE4IAMSiCAI0QAgAxKQIAjOICADEpggCNCwIAMSpCAI0KggAxKsIAjQcCADErQgCNA4
+IAMSvCAI0AAgAxLEIAjPyCADEIggCMvgIAMSzCAIy6ggAxLUIAjLcCADEtwgCMs4IAMS7CAIywAg
+AxL0IAjKyCADEvwgCMqQIAMTBCAIymggAxMQIAjKQCADExwgCMoQIAMTNCAIyeggAxNQIAjJwCAD
+E2AgCMmYIAMTcCAIyXAgAxOAIAjJSCADE5AgCMkgIAMToCAIyPggAxOwIAjI0CADE7wgCMioIAMT
+yCAIyIAgAxPUIAjIWAAAAAAAAAAAIAMT4CAIxyQgAxPkIAjFNCADE/AgCMRUIAMUBCAIxCAgAxQM
+IAjD7CADFBggCMO4IAMUHCAIw4QgAxQgIAjDUCADFCQgCMMgIAMRLCAIwiAgAxQ0IAjB+CADFDwg
+CMHQIAMQlCAI6oAgAxCcIAjptCADEIAgCOkEIAMQqCAI6GAgCwAAAABBjAAAQYgAAEGGAACAAAAA
+QYEAAKgZAACoGgAAwwAAAKgbAACoHAAAqBcAAP//AAAQBAAA5Z8AAB8RAADuCQAA//4AAOr/IAsA
+IAAA/wAAAKgYIAsAYAAAYA0AD0JAAADerSALAKAgCwDw4QBeAP7//v8BAAAAAQABACAwAAAgC3tA
+IAt7YAAAIEAAAYagIAt7kAAAQA0gC3vAIAt78AAAMNQgCwFQAABhqAAA/+kgC0iAH/+cuB//nMgf
+/5OwAIAAAP+fAAAgCAEAABAAAEAIAAACAAAA+MAAAAAAYCz/f///IAulgOEAcgAf/5xM4QQSAACL
+FEDhA/4AAAQASOEEAgAABAAhhhAAAAAEAECAAAAAgBQAA4AWAAOAEgAjgBGyA4AQAAUAKvEvAAGG
+nwAK8S8gC6XAAAQACCALSKAf/5uQIAdYgB//rfQgC6aA4AAAAOEAdgAgC6XwIAumMCALSNAf/56Q
+H/+cmOEBmgA/////AAGeDOEBngAAAZ50AAGerAABntgAAZ7wAAGfHB//npgAAf//AAGfTAABn5wA
+AZ+w4QB6ACALSfAgC0pAIAtKoAAAD/8gC0sAIAtLcCALS7AgC0vwIAtMMCALTHAgC0ywIAtM8CAL
+TTAgC01wH/+ctCADDrDhBJIAIAMOUP8A//8ADAAAgAAAH4AAAD8f/5yw/8D//x//rgQAAAgAACYM
+ACALTbAgC04QIAuoECALp6AgC6bAIAunACALp1DhAC4ABAAAAB//lZThAFYAAoBQAIAAAIAAAEAA
+//EAgAHwAACOAeCAAAAfACAIAAAgCBP0AAAU8OEBkgDhAA4AAAEAAAACAAAAfwBAAAMAAACCAIAA
+wQDA//8j/wAAyAAQIAEgH/+cBB//rjzhAH4A4QCOADwAAAD//7//UGjoR5IAAADwAPAA37//+yAA
+AAR/9///gABCAP/3/38ABgAA/wAAAABJJJIAAH4YEAEQAQAAfkAgASABFRUVFYQhhCEQEBAQ4QGO
+AAAA/n8EBAGAH/+qzB//lWzMzMzMiIiIiEREREThAM4A4QCOBOEAjgjhAI4M4P/+ACAIDaQAAAjA
+gAHEEcQRxBEA/wD/AEAAQP//P/8gC6jAIAuo8P8P///MiEQAIAuogAgICAggC6kg///gAUREAADM
+zIiI//D/AAACADMqKhUV/v///x//m3Qf/6u8H/+tsB//mVgf/51wH/+d0B//mzwf/640AAD//R//
+qzTjAAIA4v//ACALUGAgCOhgIAuqECAAAAAAMAAAAGAAACBgAADQAAAAIAupUCALqeAAABAAIAMI
+yB//sDAf/6w0H/+AsB//rLD///AAIAuq4CALUqAgC1MgIAtTkCALqpAgC6pQIAuqsB//rEwgC1Qg
+AAQAAOEAMgAf/4DgH/+BIB//gWAf/5rM/4AP///+AB8AAHtgH/ziAAgAAAAf/5yoH/+VqB//qrgf
+/5UU4QL+AOEDvgDhAz4A4QN+AOEB4gDhAQ4A4QCSAP//8P8f/6mwAAAJAOEBDgThAQ4I4QEODP/w
+AAAAAoAG//v//yALXGAgC1zAH/+B4B//nCgf/5swH/+uOBAAAAD/8P//IAMMgB//mbAAAH5M4QCK
+AAAA8AAgC10wIAtdkCALXfAf/64IH/+sKB//qiAgC14wIAtesCALsMAgC15gH/+dZCALXzAgC17w
+H/+bsCALr0AgC1+gIAtf4CALsbAgC7EQ39AAACALsVAf/6xAH/+sBP+AAAD//+AAIAtgICALYFAg
+C67wIAMMjCAHVFQf/634IAtgkB//rEQf/7LMH/+zAB//rIQEAAAIEgAAACALrGAf/7G8gQAAAAAA
+MAAgC6yQIAMMiB//sRwf/7PYH/+usB//sxhJAAAAIAursCALq/AgC6sAIAurYC4ANgAADwP/AxEA
+AAMVAAAgB1KAIAtg0B//q2Af/5pQH/+qDB//nYwf/57AIADEIB//7TAf/+x8H/+trB//7jQf/6tE
+AgCCEAIAAhAAACAAAgAAEAAaAAAA+saIACAAAPAAAAAf/6w84QMGACAHUtQgB1N8H/+B8CALYSAg
+C2DwIAthUCALrpD//3//AAAyAB//m1wf/510IAuusAAA+AAAPDw8H/+xMB//lhgf/5nUH/+tnAoU
+KFAgCA8EH/+sOCAHVBAf/5WcIAMOtB//lEj//8f/AAL/wB//mwQgC7BwIAuwECALsqAf/5usIAth
+8CALskAgC7IQIAthgCALsnAgC6+gH/+bqB//m6Af/6m4H/+ptB//gnAf/6qQH/+q5B//m+Af/5vc
+H/+b1B//m9Af/4KQH/+q6CADCTAgAws4IAdUYB//grAf/6pwH/+qZB//qmgf/6psH/+qoB//qpwf
+/6qYH/+qlB//qogf/6p8H/+qgB//qoQf/4LgH/+p8B//mygAAEADH/+UtB//qaSH////H/+cCB//
+m4wf/5xoAA//8CALZuAf/4NwIAtnQB//g4Af/65UIAtngB//nIQgC2fQH/+cWCALaAAgC2gwH/+D
+kB//m8gAACWAIAtoYCALaKAf/5lwH/+DsB//m3Af/5oEH/+ZbB//g7j//wAAA+f8GCALaNAf/4PA
+H/+rICADCYQf/6scD////yADDuAgC2kwIAgT5P//6yAgCBOU///rcCAIElQgCBOM///ssCAIEXQg
+CBJM///tkB//m+wD///gAARyDAAEchQABHIcAARwFAAEcCgABHAgAARwLAAAhYA////gAARAJAAE
+QEwABEokAAQA4AAEAAQgC2vQIAtsAAAEAsQABALAIAu3gCALt7AABHBkIAu34AAEQcAABEHEAARB
+yAAEQHgABEDcAARBQAAEQUQgC2zQIAttECALbUAgC2wwIAtscCALbKAABHBYAAAQKAAEQWAgC22Q
+AAB3dwAAMzMgC27QIAtt0CALblAgC26QIAtuECALbWAAACAoAAR0GAAESsAABEDAAARAxAAEQfAA
+BEH0AAR0FCALt0AgC2/wIAtvsCALb3AgC28wIAtu8AAEAnAAAAjwAAQCdAAEAnwABAKQAAC/KAAE
+cFwABHQAAADwBgAES/AABHIoAAGbLwABYx0ABAEwAAQA7AAEAQgABHYAAAQBBAAEdgQAAP/4AAQB
+AAAEAOQABHYIAAD/wQAEcgAAAFVVAARyBAAEAPgABADcAAQA2AAEckgABAE4AAQBGAAEckwABAD0
+AARyUAAEdAgABHIIAARASAAEStwgC3AwIAtwcCALcLAABEEsAARBPAAEQOAgC3DwAARBACALcSAA
+BHBIAARwYAAEciAABHYMAAR4BIAQAAAgC7ggIAMPcIASAAMABADogBAAAwAEAMAAAE4gAAQAzAAE
+AMQABADIAAQBNCAIBtQgCAsUAAIAIQAEAIAAD/8pAAQARCALcVAABAJEAAQCTAAEAkgGBgAAAAQB
+gAAAHngAATCwAAQA0AAEANQABADwAAQA/AACCNUAAQRqAAQBDAAEARAAAKLCAAQBFAAEARwABAEk
+AAQBKAAEASwABAFAAAQBRAAEAlAABAEgAAQCYAAEAmQABAJUAAEAIXc1lAAABEH8AARL/AAAgCAA
+AAgIAARwMCAIA8AABGDAAARgxAAAiAAABEHUAARL1AAEQdgABEvYAARB3AAES9wABHA4AARwACAL
+cYAABHAEAADAACALccAABGDIAACAJAAEQBwABEocAAAXLCALcgAgC3IwO5rKAAAEYOQABGDQIAty
+YAAEQAAABEAEAARADAAEQAggAwrUAARKBAAEcDQABHAIAARQAAAEVAAABGDMAAB/AAAEQdAABEvQ
+AARwUAAEUGgABFBAAARUaCAIB/AABFBQAARUUAAEUiQAAEBAAARSKAAEUiwABEAQAARIEAAEQBQA
+BEgUIAgIEAAEQeAABEvgIAgINAAEQegABEvoAARB5AAES+QABEHsAARL7AAEQBgABEoYAADu8AAE
+UGAABFRgAAARAAAAETAAABAwIAgD6CAIAzwgCAVIIAgEnCAIBqggCAX8AAQTBAAEEyQA////AIEC
+IOEB4kDhABIA/8AMAB//lEQf/5WwIAt1IAH///8D39JAAhYOwOEDRgAf/5p4AARUsAAA4+8ABFCw
+AARg4AAAwfMf/6yIH/+EEP/8f/8AAH7ogAAHAIAABQCAAAYAgAAEAIAAAQCAAAIAIAk/gCALdXAf
+/5SAIAlBACADCMAgC3WgAA///yAHVAgf/60wH/+sAB//ruAf/68AH/+Usx//rDAAVAAAIAwAAOEE
+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
+AA/dAQ7dAi1Gghz2XyxGhitGhyhCqg8CAAgYS/8CAAYD8U4QF/ZZKHI09vZZFpQANiDy9lgf/hBI
+MPP2GB//ECgwG/ZVGvZVDwIAKrYALzLAGPZTCP8BLzbALTLQLurA/t0BARUQcDAO3QItNtAc9k0s
+NtEqMtsb9ksLqgIqNtsY9kooJjUuMt0v+t8P7gEuNt0rMtId9kYc9kYNuwEMuwIrNtIrMtIa9cIq
+oMAJuwH7NtIiOAE6oCwy0x72Ph32Pw7MAQ3MAiw20yU29CU29cD0LjLeD+4CLjbeLDLBHfY4/cwB
+AIAQaDANzAIsNsEqMsIb9jQLqgIqNsIvIi0Z9jIY9jL69jIeAEBP8Pz2MR4JAEfw/yYtIAUQWDBb
+lyIa9iv89iwQBhBYMFuXHhr2KPz2KBAHEFgwW5cbGvYk/PYlEAgQWDBblxca9iH89iEQCRBYMFuX
+FBr2Hfz2HhAKEFgwW5cQGvYa/PYaEAsQWDBblw0a9hgc9hoY9hj4Jg4gIBBYMA8CAFuXB/r2ExFB
+EFgw/QoAIP8QYDBbmSj69g4RQRBYMP0KACD/EGAwW5kkGvYJ/PYLEOQQSDD5JgogIxBYMFuW+Br2
+BPz2BhAkEFgwW5b1GvYA/PYCECUQWDBblvEb9gGbLJsrmy0pcESZEC0y3C0WASwy2A8CAA8CAAxM
+U/wWAiTyADZg+RYAIAKMhmD5FgAiAteCYP8CAAIC54Zgxir09YQQAiEsoCkKzPIKgCAAEFAw8k4I
+AAAQKDAu4MD7QlEikAA3oPVcASQAIEkw+VLpbgAgETD2pAxiAAASsBT14i9C1Bn14Rj14Qn/Afj/
+AgAuEFAw/0bUIAcQWDBbcLwqYX3/AgAAAfPqkPsKAiCvEFAwW3Cn+gorIAEQWDBbcKT6CisgKRBY
+MFtwsfoKMiABEFgwW3Cf+goyICkQWDBbcKv6Ci8gARBYMFtwmfoKLyAsEFgwW3Cm+gomIAEQWDBb
+cJT6CiYgKRBYMFtwoPoKOiBHEFgwW3Cd+woBIKkQUDBbcIz7Ci0gqRBQMFtwmPoKNiADEFgwW3CG
++go2IC4QWDBbcJL6CjcgARBYMFtwgfoKNyA8EFgwW3CN+golIAIQWDBbcHv6CiUgAxBYMFtwh/oK
+OyACEFgwW3B2+go7IAYQWDBbcIL7CgEgsxBQMFtwcCthgSIKGA8CAP8CAAgBh9iQ+wpWILMQUDBb
+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
+sChQwy9SEC5SEflQwiAYEGAwDP8sDO4sCe4sCP8sAP8R+mYbLgkAe7AuRscKqhH9RsUqACBTcC2y
+cAzdLArdEfpmGCoAIGqwK7JxDLssCrsR+mYZKgAgWrAqZhoa6lz9KgAgABBgMP4KASACEFgw+2YT
+IAAQeDBaW/v2obFiAAASsCNmE8TwL2YhLVIlK1IkHupQGendDXs4K1YkLFIlKlIkrKr7ltsh/gJS
+sChSJy1SJiqW3Ah9OC1WJi9SJyxSJq/M/ZbXIf4CYzArUikoUigsltgLeDgoVigqUikvUiiq//jm
+9SH+AnvwLFIoL+b2LVIpK1Iorbv8lt8h/gJa8CpSKy9SKiuW4Ap/OC9WKihSKy1SKqjd/+b3If4C
+a3ArUiot5vgsUisqUiqsqvuW4yH+AlKwKFItLlIsKpbkCH44LlYsL1ItLVIsr93+luEh/gJrcCxS
+LypSLi2W4gx6OCpWLitSLyhSLquI+pbpIf4CQjAoluouQvAf6hcP7gIuRvAtQsItVjcsQtgsVjgr
+QtkrVjkqQtsqVjopQvApVjsoQuwoVjzRD8AgJ0bGJ0bIIkbNIkbOJ0bKIkbLIkbMImYbIkbHJ0bF
+J2YYJ2YZJ2YaY/61AAAAAAAA+umHEUEQWDBbinQCrAL66YMRQRBYMFuKdWP86CdGxmP9IR/o9S7w
+wcCECO4CLvTBY/ztwKH86fIQBhBYMFu1aMYq0Q/Aofzp7xAGEFgwW7VkxirRD8Ch/OnsEAYQWDBb
+tWDRD2wQBBvpCv0KASIAAHiw0w8qsnYPAgB/pxIssnD8zBAAABBwMPwvDAoAPhMQ/qcQcAIQcDAs
+snEMzBB/y3gM/wx9pygssnIMzBB/y3X8/wwAPgDusPoKASAAEFgw/Oj1EgAAaLBbtUXGKtEPAHun
+5C2yggzdEP/T23AGEHAwn0D+NgAgBhBwMP0sAAAFEFAw/OjpEAAQWDBbtTnAINEPAAAAAAAA8kYA
+IAAQeDCfMPP/1WIAAHiwnTCfQPP/yWABEHAwn0CeMPP/vWACEHAwAABsEAQmWkD6CoAiAABBMP36
+wCBAAliw8yYAIGACYLD8JgwgABBIMPwmDSIfASQw+SUUKgBAbvD1pToAgAJa8PsmCSBwAlCw+yYI
+KAUAGbD4JRUiAABZcFtmigNkOftcAAIAAFEwW3z9Cm4ULiUC0Q8AbBAEGumZAwsG8qKGIgAAaLAo
+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
-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
-OyAIEBgwI5YoGbY4ErZjHbeAHrdCIiKB9Ld+FAAQeDD1tz4UABAwMPOQwSAeALywAwJAAv05LeV+
-0Q8IOgIKB0D6lMEkBQA5sCRVftEPbBAEHLk3Grk3GLk0KsZ/+q1AIIgQWDD6hn8gABBgMFt6hR62
-Hh25MC3mMy3dAi3mNNEPAGwQBBq2zPus8CCiADygaCJo9JB+YAICEnD/IhNgARAgMGAANGlkBQWo
-CCeGAHJLKPo8AAIAAFkwW4CP+GESYAICITD5Yt1oACAusCeVAGP/26WrJ7QAY//T0Q8roncpooCj
-uwm7Efhhb2gAIF5waGJuaWTkpZyXwNEPGbbfqTkpkN1oQDb0kF9gAgIRMHJDn2P/xSyidymyhKPM
-+cwRAAICITD4YRtoACBmcGhiG2hkIP8CAAv/vZUQY/+cZZ9RY/+WpZgnhABj/+almielAGP/3qWb
-l7Bj/9elnCfEANEPpZ0n1QDRDwDRDwAAAAAAAAAAAAAAAAAAIAMQAAzAAAYgByacIAMQBAjAAAwg
-ByacIAMQCDzAABAgByXsIAMQDAbAADggBygAIAMQEAjAADwgByacIAMQFALAAEAgBygAIAMQGAjA
-AEQgByacIAMQHAhAAEwgBycsIAMQIAhAAFAgBycsIAMQJAhAAFQgBycsIAMQKAhAAFggBycsIAMQ
-LCBAAFwgBycsIAMQMCBAAGwgBycsIAMQNCBAAHwgBycsIAMQOCBAAIwgBycsIAMQPCBAAJwgBycs
-IAMQQCBAAKwgBycsIAMQRCBAALwgBycsIAMQSCBAAMwgBycsIAMQTAxAANwgByT8IAMQUAxAAOgg
-ByT8IAMQVAxAAPQgByT8IAMQWAxAAQAgByT8IAMQXAxAAQwgByT8IAMQYAxAARggByT8IAMQZAxA
-ASQgByT8IAMQaAxAATAgByT8IAMQbAhAATwgBycsIAMQcAhAAUAgBycsIAMQdAhAAUQgBycsIAMQ
-eBBAAUggBycsIAMQfBBAAVAgBycsYmNtODQ4NTZfbG9hZHNlcXVlbmNlOiBTdGFydGVkCgBiY204
-NDg1Nl9sb2Fkc2VxdWVuY2U6IFVwbG9hZCBpbWFnZSB0byBQSFkgb24tY2hpcCBtZW1vcnkKAAAA
-AAAAYmNtODQ4NTZfbG9hZHNlcXVlbmNlOiBkb25lIGxvYWRpbmcgaW1hZ2UgKGkgPSAldSkKAAAA
-AAAAAAAAAAAAAGJjbTg0ODU2X2xvYWRzZXF1ZW5jZTogRE9XTkxPQUQgRkFJTEVEIChsbyA9ICUj
-eCwgaGk9JSN4LCBjbnQ9JXUpCgAAAAAAAAAAAAAAAAAAYmNtODQ4NTZfbG9hZHNlcXVlbmNlOiBE
-b3dubG9hZCBjb21wbGV0ZWQgYWZ0ZXIgJXUgbG9vcHMKAAAAAAAAAGh3X2NsNDVfaW5pdFsldV0g
-YWNhcHMgJSN4CgAAAAAAYmNtODQ4NTZfaW5pdFsldV0KAAAAAAAAAAAAAAAAAABod19iY204NDg1
-Nl9sb3dwb3dlclsldV06IGVuYWJsZT0lZAoAAAAAAAAAAAAAAABod19iY204NDg1Nl9sb3dwb3dl
-clsldV0sIGZhaWxlZCB0byBzZXQgMzAuMHg0MDBBIGJpdCA3OyAzMC4weDQwMEUgYml0PTEgYWZ0
-ZXIgNW1zLCByZWc9JXgKAAAAAABod19iY201NDgyX2NmZ21kaVsldV0gc2V0dGluZyB0eXBlICV1
-CgAAAAAAAAAAAAByZW1vdmUgbXVsdGljYXN0IG1hYyBbJXg6JXg6JXg6JXg6JXg6JXhdIGZyb20g
-VENBTQoAAAAAAAAAAAAAAAAAaXB2Nl9qb2luX2dycDogaWQgJXUsIHJlZl9jbnQgJXUKAAAAAAAA
-AAAAAAAAAAAAZGhjcDZfdGltZXJfY2I6IHJlc2VuZGluZyBESENQNlNPTElDSVQgYWdhaW4KAAAA
-ZGhjcDZfdGltZXJfY2I6IHNlbmRpbmcgREhDUDZSRVFVRVNUCgAAAAAAAAAAAAAAZGhjcDZfdGlt
-ZXJfY2I6IHNlbmRpbmcgREhDUDZSRU5FVyByZXF1ZXN0CgAAAAAAZGhjcDZfdGltZXJfY2I6IHNl
-bmRpbmcgREhDUDZSRUJJTkQgcmVxdWVzdAoAAAAAZGhjcDZfdGltZXJfY2I6IERIQ1A2UkVQTFkg
-cmN2ZCwgc3RhdGUgJXUKAAAAAAAAZmFpbGVkIHRvIHJlbmV3L3JlYmluZCBkaGNwdjYgYWRkcmVz
-cwoAAAAAAAAAAAAAdHlwZSAleCwgeGlkICV4LCB0eXBlX3hpZCAleAoAAABpcHY2X211bHRpY2Fz
-dF9xdWVyeV90aW1lcl9jYiBub2RlX2lkICVkCgAAAAAAAABpcHY2X2dlbmVyYWxfcXVlcnlfdGlt
-ZXJfY2IKAAAAAGFkZCBtdWx0aWNhc3QgbWFjIFsleDoleDoleDoleDoleDoleF0gaW4gVENBTQoA
-AGNobmV0X2lwdjZfZGFkX2NiOiBoYW5kbGUgJXUsIGFkZHJfaWQgJXUsIGFkZHIgc3RhdGUgJXUK
-AAAAAAAAAABpcHY2IHByZWZlcnJlZCBhZGRyIFslMDR4ICUwNHggJTA0eCAlMDR4XQoAAAAAAABT
-dGFydGluZyBhZGRyIHZhbGlkaXR5IHRpbWVyIGZvciAldSBzZWNvbmRzCgAAAABWYWxpZGl0eSBl
-eHBpcmVkIGZvciBhZGRyX2lkICV1CgAAAAAAAAAAAAAAAAAAAABzZW5kaW5nIGlwdjYgZWNobyBy
-ZXBseQoAAAAAAAAAAGNobmV0X2lwdjZfcnNfb3V0cHV0OiBsMmRldl9mYyAweCV4CgAAAAAAAAAA
-AAAAAGNobmV0X2lwdjZfbnNfb3V0cHV0OiBsMmRldl9mYyAweCV4LCBmbG93Y19pZCAweCV4LCB2
-bGFuIGZsYWcgMHgleAoAAAAAAAAAAAAAAAAAY2huZXRfaXB2Nl9uYV9vdXRwdXQ6IGwyZGV2X2Zj
-IDB4JXgKAAAAAAAAAAAAAAAAY2huZXRfaXB2Nl9tbGR2Ml9yZXBvcnRfb3V0cHV0OiBsMmRldl9m
-YyAweCV4CgAAZ2F0aGVyX3Rhc2tzX3RvX3R4X2xpc3Q6IHRhc2sgaW4gdXNlIFsldV0KAAAAAAAA
-Z2F0aGVyX3Rhc2tzX3RvX3R4X2xpc3Q6IGlkeCBbJXVdLCB0YXNrIGZpZCBbMHgleF0sIHRhc2sg
-c3RhdGUgWzB4JXhdLCB0YXNrIGNvbm4gWzB4JXhdLCB0YXNrIGZmbGFncyBbMHgleF0sIGNvbm4g
-ZmlkIFsweCV4XSwgZGRwIFslZF0KAAAAAAAAAAAAZ2F0aGVyX3Rhc2tzX3RvX3R4X2xpc3Q6IHRh
-c2sgWzB4JXhdLCBzdGF0ZSBbMHgleF0gb24gY29ubiBbMHgleF0gbm90IHZhbGlkIHRvIGdhdGhl
-ciwgc2tpcHBpbmcKAAAAAAAAAAAAAAAAAAAAAGdhdGhlcl90YXNrc190b190eF9saXN0OiB0YXNr
-IFsweCV4XSwgc3RpbGwgcXVldWVkIG9uIHR4IHBlbmRpbmcgbGlzdC4gUmVtb3ZpbmcgaXQuCgAA
-AAAAAAAAAAAAAGdhdGhlcl90YXNrc190b190eF9saXN0OiBjb25uX2ZjLT5mbG93Y19mbGFncyBb
-MHgleF0sIGxpc3RfZW1wdHkgWzB4JXhdLCBhZGRfdGFza19jb3VudCBbMHgleF0KAHRvX3R4X2xp
-c3Q6IG5vIHRhc2sgdG8gY2xvc2UgZm9yIGNvbm4gWzB4JXhdLCBiYWlsaW5nIHRvIHJlY292ZXJ5
-IHN0YXRlIFsweCV4XQoAYXV0aGVudGljYXRlX3RhcmdldDogS0VZX0NIQVBfUkVTUCAtIFsweCV4
-JXgleCV4JXgleCV4JXhdCgAAAAAAAGF1dGhlbnRpY2F0ZV90YXJnZXQ6IEtFWV9DSEFQX1JFU1Ag
-LSBbMHgleCV4JXgleCV4JXgleCV4XQoAAAAAAABhdXRoZW50aWNhdGVfdGFyZ2V0OiBJbmNvcnJl
-Y3QgcGFzc3dvcmQKAAAAAAAAAABDSEFQX0M6IGRpZ2VzdCBleHBhbnNpb24gZXJyb3IKAENIQVBf
-TjogVGFyZ2V0IHVzZXJpZCBtaXNtYXRjaAoAQ0hBUF9SOiBkaWdlc3QgZXhwYW5zaW9uIGVycm9y
-CgBpU0NTSSBTZWMtcGFyYW1zIHJlY2VpdmVkaGF2ZSBlcnJvcnMhIQoAAAAAAAAAAABUYXJnZXQg
-bW92ZWQgdGVtcC4gY29ubiAleCwgc2VzcyAleAoAAAAAAAAAAAAAAABMb2dpbiBGYWlsZWQhIS4g
-Y29ubl9mYyBbMHgleF0sIHNlc3NfZmMgWzB4JXhdLCBzdGF0dXNfY2xhc3MgWzB4JXhdCgAAAAAA
-AAAAAAAAAFByb3RvY29sIEVycm9yIGNiaXQgJWQgdGJpdCAlZCBjc2cgJWQgbnNnICVkCgAAAHJl
-Y3Zfbm9waW46IGN0cmwgdGFzayBhbHJlYWR5IHBlbmRpbmcKAAAAAAAAAAAAAG9mbGRfcnhfZGF0
-YTogYWllZSwgaXNjc2kgY29ubiBbMHgleF0gZm9yIHNlc3MgWzB4JXhdLCB0eXBlIFsweCV4XSB0
-cmFuc2l0ZWQgaW4gdG9lIG1vZGUuIEtpY2tpbmcgcmVjb3ZlcnkgCgAAAABvZmxkX3J4X2RhdGE6
-IGNvbm4gdGlkIFsweCV4XSwgcnhfZGF0YS0+c2VxIFsweCV4XSwgcnhfZGF0YS0+bGVuIFsweCV4
-XSwgcnhfZGF0YS0+c3RhdHVzIFsweCV4XQoAAAAAAAAAAAAAAAAAAAAAb2ZsZF9yeF9kYXRhOiBj
-c2sgeyBpZCBbMHgleF0sIGNzb2NrX29mZnNldCBbMHgleF0sIGRsZW4gWzB4JXhdIH0KAAAAAAAA
-AAAAAAAAAABhY3RfZXN0OiB0Y2JfZmMgWzB4JXhdLCBmbG93Y19mb2lzY3NpX2Nvbm5fZmxhZ3Mg
-WzB4JXhdCgAAAAAAAAAAYWN0X2VzdGFiOiB0Y2JfZmMtPmZsb3djX2J1ZiBbMHgleF0sIHRjYl9m
-Yy0+Zmxvd2NfdHlwZSBbMHgleF0gdGNiX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIG5wYWdlcyBb
-MHgleF0sIGZsb3djX3RwX3NuZF9tYXggWzB4JXhdCgAAAAAAAAAAAAAAAAAAYWN0X2VzdGFiOiBh
-dGlkIFsweCV4XSwgdGlkIFsweCV4XSwgb3AgWzB4JXhdLCByY3ZfaXNuIFsweCV4XSwgc25kX2lz
-biBbMHgleF0sIGNzb2NrLT5mbG93Y19zdGF0ZSBbMHgleF0sIHRjcF9vcHQgWzB4JXhdLCB0Y2Jf
-ZmMtPmZsb3djX2lkIFsweCV4XSAKAAAAAAAAAAAAAAAAAGNza19mYy0+Zmxvd2NfY3NvY2tfY29v
-a2llIFsweCV4XSAKAAAAAAAAAAAAAAAAAG5ldF9sMmRldl9maW5kX2J5X2FkZHI2OiBsMmRldl9m
-Yy0+Zmxvd2NfaWQgWzB4JXhdLCBsMmRjLT5scG9ydCBbJXVdLCBsMmRfZmMtPmZsb3djX2lkIFsw
-eCV4XSwgYWRkciBbJTA0eCUwNHglMDR4JTA0eF0KAAAAAAAAAAAAY2huZXRfcXVldWVfeG1pdDog
-ZmMtPmZsb3djX2lkIFsweCV4XSwgYnVmX2xlbiBbMHgleF0sIGJ1ZmZlcmVkIFsweCV4XSwgZmlm
-by5udW1fYnl0ZXMgWyUweF0KAAAAbmV0aWZfZG9fZGhjcHY2OiB3ci0+cGFyYW0udmxhbmlkIFsl
-dV0sIGwyZGV2X2ZjLT5mbG93Y19uZXRfbDJkZXZfdmxhbmRldiBbMHgleF0KAAAAAAAAAAAAAAAA
-AAAAbmV0aWZfZG9fZGhjcHY2OiBpcHY2IG5vdCBlbmFibGVkCgAAAAAAAAAAAAAAAAAAZGhjcCBy
-ZXNwIHRvIGRyaXZlcgoAAAAAAAAAAAAAAABsM2luNl9kZXZfY29uZmlnOiB3ci0+cGFyYW0udmxh
-bmlkIFsldV0sIGwyZGV2X2ZjLT5mbG93Y19uZXRfbDJkZXZfdmxhbmRldiBbMHgleF0KAAAAAAAA
-AAAAAAAAAABsM2luNl9kZXZfY29uZmlnOiBpcHY2IG5vdCBlbmFibGVkCgAAAAAAAAAAAAAAAABu
-ZXRfbDNpbjZfZGV2X2NvbmZpZzogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgYWRkcmVzcyBh
-bHJlYWR5IHVzZWQgYnkgcG9ydCAlZCwgYWRkcl9pZCAlZAoAAABuZXRfbDNpbjZfZGV2X2NvbmZp
-ZzogIGFkZHIgWzB4JTA0eCUwNHglMDR4JTA0eF0sIHJlZl9jbnQgWzB4JXhdIGluIHVzZQoAAAAA
-AAAAAGwzaW40X2Rldl9jb25maWc6IHdyLT5wYXJhbS52bGFuaWQgWyV1XSwgbDJkZXZfZmMtPmZs
-b3djX25ldF9sMmRldl92bGFuZGV2IFsweCV4XQoAAAAAAAAAAAAAAAAAAG5ldF9sM2luNF9kZXZf
-Y29uZmlnOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBhZGRyZXNzIGFscmVhZHkgdXNlZCBi
-eSBwb3J0ICVkCgAAAAAAAAAAAAAAAAAAAG5ldF9sM2luNF9kZXZfY29uZmlnOiAgYWRkciBbMHgl
-eF0sIG1hc2sgWzB4JXhdLCBndyBbMHgleF0sIHJlZl9jbnQgWzB4JXhdIGluIHVzZQoAAAAAAAAA
-AAAAAAAAAGwyZGV2X2ZjIFsweCV4IF0gRmFpbGVkIHRvIHN0YXJ0IHRpbWVyIGZvciBpcHY0IGRh
-ZAoAAAAAAAAAAAAAAAB3cmhfY2huZXRfaWZjb25mOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhd
-LCBsMmRldl9mYy0+Zmxvd2NfdHlwZSBbJTB4XSwgaWZjb25mX3dyLT5zdWJvcCBbMHgleF0KAAAA
-AAAAAAAAAAAAAAAAd3JoX2NobmV0X2lmY29uZjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwg
-dW5rbm93biBzdWJvcCBbMHgleF0KAAAAAAAAAAAAAAAAAAB3cmhfY2huZXRfaWZjb25mOiBsMmRl
-dl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCByYyAlZAoAAAAAAAAAAAAAAAAAbmV0aWZfaXBfY29uZmxp
-Y3RfdGltZXJfY2I6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIGV4cGVjdGluZyB0aW1lciBo
-YW5kbGUgWyVkXSwgYnV0IGdvdCBoYW5kbGUgWyVkXSBleHBpcnkKAG5ldGlmX2lwX2NvbmZsaWN0
-X3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBpbmRldmN0eHQtPnN0YXRlIFsl
-ZF0sIGluZGV2Y3R4dC0+cmV0cnlfY250IFslZF0KAAAAAAAAAABuZXRpZl9pcF9jb25mbGljdF90
-aW1lcl9jYjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgaW5kZXZjdHh0IFsweCV4XSwgaW4g
-ZnJlZSBzdGF0ZQoAAAAAAAAAAABjbWRoX2NobmV0X2lmYWNlOiBmYyBbMHgleF0sIGZjLT5mbG93
-Y19pZCBbMHgleF0sIGZjLT5mbG93Y190eXBlIFsweCV4XSwgcCBbMHgleF0sIGxlbjE2IFsldV0s
-IGxvYyBbMHgleF0KAAAAAAAAY21kaF9jaG5ldF9pZmFjZTpsMmRldl9mYyBbMHgleF0sIGwyZGV2
-X2ZjLT5mbG93Y19pZCBbMHgleF0sIGwyZGV2LT5mbG93Y190eXBlIFsldV0sIGwyZGV2X2ZjLT5m
-bG93Y19uZXRfbDJkZXZfZmxhZ3MgWyUweF0KAAAAAABjbWRoX2NobmV0X2lmYWNlOiByMlswXSAl
-dSByMlsxXSAldQoAAAAAAAAAAAAAAABjbWRoX2NobmV0X2lmYWNlOiBsMmRldl9mYy0+Zmxvd2Nf
-bmV0X2wyZGV2X2ZsYWdzIGNoYW5nZWQgZnJvbSBbJTB4XSB0byBbJTB4XSwgcmMgWyVkXQoAAAAA
-AAAAAABjaG5ldF9sMmRldl91cF9tYl9jYjogcmMgWyVkXSwgcG9ydCBbJXVdLCBzdGF0ZSBbJXVd
-LCBjb29raWUgWzB4JXhdCgAAAAAAAAAAAAAAAGRoY3BfcHJvY2Vzc19jYjogbDJkZXZfZmMtPmZs
-b3djX2lkIFsweCV4XSwgZGhjdHh0LT5zdGF0ZSBbJTB4XSwgZGhjdHh0LT5ydHJ5X2NudCBbJXVd
-CgAAAAAAAAAAAGRoY3BfdGltZXJfY2I6IERIQ1BESVNDT1ZFUiBzZW50LCBidXQgbm8gcmVwbHkg
-ZnJvbSBhbnkgcG9zc2libGUgc2VydmVyIG9uIHRoZSBuZXR3b3JrLiBSZXRyeWluZyBhZ2FpbgoA
-AAAAAAAAAABkaGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBzZW5kaW5n
-IERIQ1BESVNDT1ZFUiBmb3IgZGhjdHh0IFsweCV4XSBvbiBwaWQgWyVkXQoAAABkaGNwX3RpbWVy
-X2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBESENQT0ZGRVIgcmVjZWl2ZWQgZm9yIGRo
-Y3R4dCBbJXhdIHBpZCBbJWRdCgAAAAAAAAAAAABkaGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxv
-d2NfaWQgWzB4JXhdLCAgREhDUEFDSyByZWNlaXZlZCBmb3IgZGhjdHh0IFsleF0sIHBpZCBbJWRd
-CgAAAAAAAAAAAABkaGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBkaGN0
-eHQtPmlwYWRkciBbMHgleF0KAAAAAAAAAAAAAAAAAAAAAGRoY3BfdGltZXJfY2I6IHN0YXJ0aW5n
-IHRpbWVyIGZvciBsZWFzZSBbJXVdIHNlY29uZHMKAAAAAAAAAAAAAABkaGNwX3RpbWVyX2NiOiBs
-ZWFzZSB0aW1lIG9mIFsldV0gc2Vjb25kcyBleHBpcmVkLCBzZW5kaW5nIHJlbmV3IHJlcXVlc3QK
-AAAAAAAAAGRoY3BfdGltZXJfY2I6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIG5vIHJlcGx5
-IGZyb20gZGhjcCBzZXJ2ZXIsIHRpbWluZyBvdXQKAAAAAAAAAAAAAAAAAAAAAGF1dGhfbmVnb19z
-ZWN1cml0eTogc2VuZF9mbGFnIFsweCV4XSwgYXV0aF9wb2xpY3kgWzB4JXhdCgAAAAAAAABhdXRo
-X25lZ29fc2VjdXJpdHk6IEtFWV9DSEFQX1JFU1AgLSBoYXNoWzB4JXgleCV4JXgleCV4JXgleF0K
-AAAAYXV0aF9uZWdvX3NlY3VyaXR5OiBLRVlfQ0hBUF9SRVNQIC0gaGFzaFsweCV4JXgleCV4JXgl
-eCV4JXhdCgAAAGF1dGhfbmVnb19zZWN1cml0eTogS0VZX0NIQVBfUkVTUCAtIGVycm9yIGVuY29k
-aW5nIHRvIGhleAoAAAAAAABhdXRoX25lZ29fc2VjdXJpdHk6IEtFWV9DSEFQX1JFU1AgLSBlbGVu
-IFsweCV4XQoAAAAAAAAAAAAAAAAAAAAAYXV0aF9uZWdvX3NlY3VyaXR5OiBLRVlfQ0hBUF9DSEFM
-IC0gZXJyb3IgZW5jb2RpbmcgdG8gaGV4CgAAAAAAAGF1dGhfbmVnb19zZWN1cml0eTogS0VZX0NI
-QVBfQ0hBTCAtIGVsZW4gWzB4JXhdCgAAAAAAAAAAAAAAAAAAAABsb2dvdXRfdGltZWRvdXQ6IGxv
-Z291dCByZXF1ZXN0IHRpbWVkb3V0LCBwb3NzaWJsZSBuZXR3b3JrIGlzc3Vlcy4gRm9yY2VmdWxs
-eSBicmVha2luZyBwYXRoIGZvciBzZXNzIFsweCV4XQoAAAAAcGluZ190YXJnZXQ6IHBpbmcgdGlt
-ZW91dCwga2lja2luZyByZWNvdmVyeSBmb3Igc2VzcyBbMHgleF0KAAAAAGNzb2NrX2ZhaWxlZDog
-Y3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCBzZXNz
-X2ZjLT5mbG93Y19pZCBbMHgleF0sIHNlc3NfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwgZXZ0IFsw
-eCV4XQoAAAAAAAAAAAAAAGNobmV0X2ZpbmRfaXA2X2wydF9lbnRyeTogZmluZCBwcmVmaXggbWF0
-Y2ggWyUwNHggJTA0eCAlMDR4ICUwNHhdCgAAAAAAAAAAAAAAAAAATm8gcm91dGVyIGNvbmZpZ3Vy
-ZWQsIGwyZGV2X2ZjLT5mbG93Y19pZCAweCV4CgAAClJvdXRlciBsaWZlICV1IGV4cGlyZWQuIGRl
-bGV0aW5nIHJvdXRlciBbJTA0eCAlMDR4ICUwNHggJTA0eF0KAFVzaW5nIHJvdXRlciBbJTA0eCAl
-MDR4ICUwNHggJTA0eF0gdG8gcmVhY2ggWyUwNHggJTA0eCAlMDR4ICUwNHhdCgAAAAAAAAAAAAAA
-AAAAbDJ0ZW50IFslMHhdLCBsMnRlbnQtPmlkeCBbJWRdCgByYyBbJWRdLCBjc2tfZmMgWzB4JXhd
-LCBjc2tfZmMtPmZsb3djX2lkIFsweCV4XQoAAAAAAAAAAAAAAAAAAAAAcmVjb3ZlcnlfdGltZW91
-dDogc2VzcyBpZCBbMHgleF0gc3RhdGUgWzB4JXhdLCByY291bnQgWyVkXSwgZmxhZ3MgWzB4JXhd
-CgAAAAAAAAByZWNvdmVyeV90aW1lb3V0OiBzZXNzIGlkIFsweCV4XSBpbiBsb2dvdXQsIGFib3J0
-IHRoZSBjb25uZWN0aW9uCgAAAAAAAAAAAAAAAAAAAHJlY292ZXJ5X3RpbWVvdXQ6IHNlc3NfZmMt
-PmZsb3djX2ZvaXNjc2lfc2Vzc19mbGFncyBbMHgleF0sIGNvbm5lY3Rpb24gcmVxdWVzdCBwZW5k
-aW5nLCBiYWlsaW5nIG91dAoAAAAAAAAAAAAAAABmb2lzY3NpOiBSZWNvdmVyeSB0aW1lZCBvdXQg
-YWZ0ZXIgWyV1XSByZXRyeSwgYmFpbGluZyBvdXQKAAAAAAAAVENQIGNvbm4gZXN0YWJsaXNobWVu
-dCBmYWlsZWQgJWQKAAAAAAAAAAAAAAAAAAAAZGlzY292ZXJ5X2RhdGE6IHNlc3MgeyBpZCBbMHgl
-eF0sIGZsYWdzIFsweCV4XSwgYnVmZmVyZWQgWyV1XS4gfQoAAAAAAAAAAAAAAAAAAABkaXNjb3Zl
-cnlfZGF0YTogc2VzcyB7IGlkIFsweCV4XSB9LCB1bHB0eGNoIFsldV0gbm8gY3JlZGl0cyBhdmFp
-bGFibGUsIHJlc2NoZWR1bGluZyByZXF1ZXN0LgoAAABJbnZhbGlkIG9wY29kZSAweCV4IGluIGN0
-cmwgcGF0aAoAAAAAAAAAAAAAAAAAAABERFAgZXJyb3IgWzB4JXhdLCBhYm9ydGluZyBjb25ubiBb
-MHgleF0KAAAAAAAAAAByeF9kYXRhX2RkcDogUmVzcG9uY2UgcmVjaWV2ZWQgZm9yIHRhc2sgWzB4
-JXhdIHdoaWxlIGludmFsaWQgdGFzayBvciBjb25uZWN0aW9uIHN0YXRlLiB0YXNrIHN0YXRlIFsw
-eCV4XSwgY29ubiBzdGF0ZSBbMHgleF0sIGNvbm4gZmxhZ3MgWzB4JXhdCgBpc2NzaV9oZHJfcng6
-IFJlc3BvbmNlIHJlY2lldmVkIGZvciB0YXNrIFsweCV4XSB3aGlsZSBpbnZhbGlkIHRhc2sgb3Ig
-Y29ubmVjdGlvbiBzdGF0ZS4gdGFzayBzdGF0ZSBbMHgleF0sIGNvbm4gc3RhdGUgWzB4JXhdLCBj
-b25uIGZsYWdzIFsweCV4XQoAAAAAAAAAAAAAAAAAAAAAaXNjc2lfaGRyX3J4OiBJbnZhbGlkIHRh
-c2sgc3RhdGUgMHgleCBmb3IgdGFzayAweCV4LCBpdHQgWzB4JXhdLCBvcGMgWzB4JXhdCgAAAABw
-cm9jZXNzX3RtZl9yZXNwb25zZTogYnVmZmVyZWQgWzB4JXhdLCBpc3Rhc2tfZmMtPmZsb3djX2J1
-Zi0+c2NoZWRfbm9kZS5uZXh0IFsweCV4XSwgaXN0YXNrX2ZjIFsweCV4XSwgaXN0YXNrX2ZjLT5m
-bG93Y19pZCBbMHgleF0KAAAAAAAAAAAAAAAAAABwcm9jZXNzX3RtZl9yZXNwb25zZTogd3Igb3Ag
-WzB4JXhdLCB0bWYgb3AgWzB4JXhdCgAAAAAAAAAAAAAAAAAAcmV0dXJuX3BlbmRpbmdfdGFzazog
-Y29va2llIFsweCUwOHhdLCBbMHglMDh4XQoAcmV0dXJuX3BlbmRpbmdfdGFzazogZGVsYXkgcHJv
-Y2Vzc2luZywgY29ubiBmbGFncyBbMHgleF0KAAAAAAAAAHJldHVybl9wZW5kaW5nX3Rhc2s6IERv
-bmUgc2VuZGluZyB0YXNrIGVycm9yIHRvIGhvc3QsIHVscHR4bGVuMTYgWyV1XQoAAAAAAAAAAAAA
-cmV0dXJuX3BlbmRpbmdfdGFzazogZGVxdWV1ZSB0YXNrIFsweCV4XSwgc3RhdGUgWzB4JXhdIGZy
-b20gdHhfbGlzdAoAAAAAAAAAAAAAAAByZXR1cm5fcGVuZGluZ190YXNrOiBhbGwgdGFza3MgcmV0
-dXJuZWQsIHJlY292ZXJ5IHN0YXRlIHRyYW5zIHRvIFsweCV4XQoAAAAAAAAAAGNsZWFyX2RkcF9t
-YXA6IGlzdGFza19mYyBbMHgleF0sIGlzdGFza19mYy0+Zmxvd2NfaWQgWzB4JXhdIGJ1ZmZlcmVk
-ICV1CgAAAAAAAAAAY2xlYXJfZGRwX21hcDogaXN0YXNrX2ZjLT5mbG93Y19mb2lzY3NpX3Rhc2tf
-bnBwb2QgJXUsIG5wcG9kICV1LCBwcGRhZGRyIFsweCV4XQoAAAAAAAAAAAAAAAAAAAAAY2xlYXJf
-ZGRwX21hcDogYWxsIHJldHVybmVkIHRhc2tzIGRkcCBjbGVhcmVkLCByZWNvdmVyeSBzdGF0ZSB0
-cmFucyB0byBbMHgleF0KAAB3cmhfZm9pc2NzaV9ub2RlOiBub2RlX3dyLT5mbG93aWRfbGVuMTYg
-MiBbJXhdCgB3cmhfZm9pc2NzaV9jaGFwOiBpZF9sZW4gWyV4XSwgc2VjX2xlbiBbJXhdCgAAAAB3
-cmhfZm9pc2NzaV9jaGFwOiB0Z3RfaWRfbGVuIFsleF0sIHRndF9zZWNfbGVuIFsleF0KAAAAAAAA
-AAAAAAAAc2Vzc2lvbl9ibG9jazogc2Vzc19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBzZXNzX2ZjLT5m
-bG93Y19zdGF0ZSBbMHgleF0sIGNvbm5fZmMtPmZsb3djX2lkIFsweCV4XSwgY29ubl9mYy0+Zmxv
-d2Nfc3RhdGUgWzB4JXhdLCBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19z
-dGF0ZSBbMHgleF0KAAAAAAAAAAAAAAAAAAAAc2Vzc2lvbl91bmJsb2NrOiBzZXNzX2ZjLT5mbG93
-Y19pZCBbMHgleF0sIHNlc3NfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwgY29ubl9mYy0+Zmxvd2Nf
-aWQgWzB4JXhdLCBjb25uX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQg
-WzB4JXhdLCBjc2tfZmMtPmZsb3djX3N0YXRlIFsweCV4XQoAAAAAAAAAAAAAAAAAc3RhcnRfbG9n
-b3V0OiBTZXNzLWlkIFsweCV4XSBhbHJlYWR5IGxvZ2dpbiBvdXQuCgAAAAAAAAAAAAAAAAAAAHBl
-ZXJfY29uOiBjc2tfZmMgPT4gZmxvd2lkIFsweCV4XSwgZmxvd2NfYnVmIFsweCV4XQoAAAAAAAAA
-AAAAAABhbGxvY19zZXNzOiBsb2dpbl9yZXRyeSBbJWRdLCByZWNvdl90aW1lb3V0IFslZF0KAAAA
-AAAAAAAAAAAAAAAAZm9pc2NzaV9jdHJsOiBzdWJvcCBbMHgleF0sIHNlc3NfdHlwZV90b19lcmwg
-WzB4JXhdLCBzZXNzX3R5cGUgWzB4JXhdCgAAAAAAAAAAAABmb2lzY3NpX2N0cmw6IHJlY2VpdmVk
-IGJsb2NrZWQgZnJvbSBkcml2ZXIsIHRyaWdnZXJpbmcgcmV0dXJuIHRhc2tzIG5vdy4KAAAAAAAA
-AHdhdGNoZG9nIGNtZCBoYW5kbGVyICh0aW1lICV1IGFjdGlvbiAldSkKAAAAAAAAAFdBVENIRE9H
-OiBkZXZpY2Ugc2h1dGRvd24KAAAAAAAAV0FUQ0hET0c6IHBvcnRbJXVdIHBhdXNlIHdhdGNoZG9n
-IHRpbWVvdXQKAAAAAAAAV0FUQ0hET0c6IGJ5cGFzcyB0aW1lb3V0CgAAAAAAAABXQVRDSERPRzog
-RkxSIC0gbm90IGltcGxlbWVudGVkIHlldAoAAAAAAAAAAAAAAABXQVRDSERPRzogdGVtcGVyYXR1
-cmUgb2YgJWRDIGV4Y2VlZHMgdGhyZXNob2xkIG9mICVkQwoAAAAAAAAAAAAAZmlsdGVyOiBwb3Jn
-cmFtbWluZyB0aWQgJXUgKGxlIHRjYW0gaW5kZXggJXUpLi4uCgAAAAAAAAAAAAAAAAAAAGZpbHRl
-cjogcmVxdWVzdGluZyBjb21wbGV0aW9uLi4uCgAAAAAAAAAAAAAAAAAAAGNobmV0X2lwdjZfbGlu
-a19jaGFuZ2Vfbm90aWZ5OiBsMmRldl9mYyBbMHgleF0sIHN0YXR1cyAldQoAAAAAAABsMmRldl9z
-ZW5kX3BvcnRfZXZlbnQ6IHdyIFsweCV4XSBwZW5kaW5nIG9uIHBvcnQgWyVkXSwgY3VycmVudCB0
-cnkgWyVkXQoAAAAAAAAAAEZDT0UgRnJlZTogc3RpbGwgeWllbGRlZCB3aGVuIGZyZWVpbmcuLi5m
-bG93Y19pZCAleCBmbG93Y19mbGFncyAleCAKAAAAAAAAAAAAAAAARkNPRSBCUCBXUiBFUlI6IFdS
-IHdpdGggY29va2llICV4JXggZXJyb3JlZCBiYWNrIAoAAAAAAAAAAAAAAAAAAHBvcnQgJWQgc2V0
-IHBmY19lbiA9IDB4JXgKAAAAAAAAcG9ydCAlZCBzZXQgcGZjX2VuID0gMHgleAoAAAAAAABldHNf
-c2V0X2NmZ19pZWVlWyV1XSB1bmtub3duIFRTQSBhbGcgZm9yIHByaW8gJXU6ICV1CgAAAAAAAAAA
-AAAARkNvRSBERFAgZmFpbGVkIDogb3hfaWQgMHgleCByeF9pZCAweCV4CgAAAAAAAAAARkNvRSBE
-RFAgZmFpbGVkIDogRGRwUmVwb3J0IDB4JXggRGRwVmFsaWQgMHgleAoARkMgeGNoZyBhbGxvYyBm
-YWlsZWQ6IGF2YWlsICVkCgBmY29lIG5vdGlmeSA6IFVwZGF0ZSBuZXcgRENCWCB2YWx1ZXMgVkkg
-c3RhdGUgMHgleCBwcmkgMHgleCBzY2hlZGNsIDB4JXggZGNieF9kb25lIDB4JXgKAAAAAAAAAABm
-Y29lIG5vdGlmeSA6IEZDRiBmbG93aWQgMHgleCwgdWxwY2ggMHgleCAKAAAAAABQUkxJIFJzcCB0
-aW1lZG91dCA6IGZsb3djX2lkIDB4JXggb3hfaWQgMHgleCByeF9pZCAweCV4IAoAAAAAAAAAY2Fu
-bm90IGFsbG9jYXRlIG9mZmxvYWRlZCBmaWx0ZXIgY29ubmVjdGlvbgoAAAAAY2Fubm90IGFsbG9j
-YXRlIG9mZmxvYWRlZCBmaWx0ZXIgSVB2NiBjb25uZWN0aW9uCgAAAAAAAAAAAAAAAAAAAGRpc3Bh
-dGNoX2RlZmVycmVkX2NsYXNzX2NsYXNzX3NoYXBpbmdbJXU6JXVdOiBsaXN0X2VtcHR5CgAAAAAA
-AABsb29wYmFjayBidWZmZXIgZ3JvdXBbJXVdIGlzIGRpc2FibGVkCgAAAAAAAAAAAABpbnZhbGlk
-IGJ1ZmZlciBncm91cFsldV0gY29uZmlndXJhdGlvbjogbXR1ICV1IGx3bSAldSBod20gJXUgZHdt
-ICV1CgAAAAAAAAAAAAAAAGZjICV1IHZmICV1IGdvdCBpdmY9MHgleCxyYW5nZTogJSN4LSUjeCAo
-JXUvJXUgdXNlZCkKAAAAAAAAAAAAAABWSSAldSBjYW5ub3QgZ2V0IFJTUyBzbGljZTogTm8gbW9y
-ZSBzbGljZXMgYXZhaWxhYmxlICh1c2VkICV1LyV1KQoAAAAAAAAAAAAAAAAAAHBmbiAldSB2Zm4g
-JXUgd2l0aCBwb3J0IG1hc2sgMHgleCBjYW5ub3QgYWNjZXNzIHBvcnQgJXUsIHJldCAlZAoAAAAA
-AAAAAAAAAAAAAAAAcGZuICV1IHZmbiAldSBjb3VsZCBub3QgYWxsb2NhdGUgdmlpZCwgcmV0ICVk
-CgAAcGZuICV1IHZmbiAldSBjb3VsZCBtYXAgdmlpZCAgMHgleCB0byBmbG93YywgcmV0ICVkCgAA
-AAAAAAAAAAAAAHBmbiAldSB2Zm4gJXUgY291bGQgbm90IGFsbG9jYXRlIHV3aXJlIGZ1bmMgJWQg
-bWFjIGFkZHIsIHJldCAlZAoAAAAAAAAAAAAAAAAAAAAAbWlpX2luaXRbJXVdOiBhY2FwcyAweCV4
-CgAAAAAAAABtaWlfZm9yY2Vfc3BlZWRbJXVdOiByY2FwcyAweCV4CgAAAAAAAAAAAAAAAAAAAABt
-aWlfcGRvd25bJXVdOiBwb3dlcmRvd24gZW4gJXUKAHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06IHVu
-a25vd24gYWN0aW9uIDB4JXgKAAAAAHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06IHVua25vd24gcmVh
-ZCBhY3Rpb24gMHgleAoAAAAAAAAAAAAAAAAAAABjcGxfZXJyX25vdGlmeTogdGlkICV1IGNwbCAw
-eCUwOHglMDh4CgAAAAAAAAAAAABjcGxfZXJyX25vdGlmeTogdGlkICV1IGNwbCAweCUwOHglMDh4
-IDB4JTA4eCUwOHgKAAAAAAAAAAAAAAAAAAAAY3BsX2Vycl9ub3RpZnk6IHRpZCAldSBsZW4gJXUK
-AABGQ09FIEZyZWU6IHN0aWxsIHlpZWxkZWQgd2hlbiBmcmVlaW5nLi4uZmxvd2NfaWQgJXggZmxv
-d2NfZmxhZ3MgJXggCgAAAAAAAAAAAAAAAHNjc2lfYWJvcnQ6IEVudGVyaW5nIEFib3J0X3Rhc2ss
-IGJ1ZmZlcmVkIFsldV0KAHNjc2lfYWJvcnQ6IHJjIFsweCV4XSByZWYgdGFzayBub3Qgb3V0c3Rh
-bmRpbmcKAHNjc2lfYWJvcnQ6IGlkYXRhLT5vcCBbMHgleF0sIGZsYWdzIFsweCV4XSwgZnVuYyBb
-MHgleF0sIGx1bl9pZHggWzB4JXhdCgAAAAAAAAAAc2NzaV9hYm9ydDogd3ItPmlxaWQgWzB4JXhd
-LCBpc3Rhc2tfZmMtPmZsb3djX3NnZV9pcWlkIFsweCV4XSwgaXN0YXNrX2ZjIHRhc2sgZmxhZ3Mg
-WzB4JXhdCgAAAAAAc2NzaV9hYm9ydDogY29ubiBbMHgleF0sIGNtZHNuIFsweCV4XSwgc2VudF9j
-bWRzbiBbMHgleF0sIG1heF9jbWRzbiBbMHgleF0sIGl0dCBbMHgleF0KAAAAAAAAAAAAYWJvcnQv
-Y2xvc2UgV1Igd2l0aCBjb29raWUgMHglbHggd2FzIGlzc3VlZCBvbiBzc24gMHgleCBpbiB3cm9u
-ZyBzdGF0ZSAweCV4CgAAAABhYm9ydCBXUiBvbiBzc24gMHgleCBkaWQgbm90IGZpbmQgV1Igd2l0
-aCBjb29raWUgMHgleCV4CgAAAAAAAAAAY2xvc2UgV1Igd2l0aCBjb29raWUgMHglbHggb24gc3Nu
-IDB4JXg7ZGlkIG5vdCBmaW5kIFdSIHdpdGggY29va2llIDB4JWx4CgAAAAAAAABhYm9ydCBXUiBv
-biBzc24gMHgleCB3YXMgaXNzdWVkIG9uIHhjaGcgMHgleCB3aXRoIHJ4X2lkIDB4JXggaW4gd3Jv
-bmcgc3RhdGUgMHgleAoAAAAAAAAAAAAAAAAAAABzY3NpX2x1cjogRW50ZXJpbmcgTFVSIGhhbmRs
-ZXIsIGJ1ZmZlcmVkIFsldV0KAABzY3NpX2x1cjogaWRhdGEtPm9wIFsweCV4XSwgZmxhZ3MgWzB4
-JXhdLCBmdW5jIFsweCV4XSwgbHVuX2lkeCBbMHgleF0KAAAAAAAAAAAAAHNjc2lfbHVyOiB3ci0+
-aXFpZCBbMHgleF0sIGlzdGFza19mYy0+Zmxvd2Nfc2dlX2lxaWQgWzB4JXhdLCBpc3Rhc2tfZmMg
-dGFzayBmbGFncyBbMHgleF0KAAAAAAAAAHNjc2lfbHVyOiBjb25uIFsweCV4XSwgY21kc24gWzB4
-JXhdLCBzZW50X2NtZHNuIFsweCV4XSwgbWF4X2NtZHNuIFsweCV4XSwgaXR0IFsweCV4XQoAAAAA
-AAAAAAAAAGRjYnhfY2VlX2ZlYV9zbVsldV0gRmVhdHVyZVsldV0gRkVBVFVSRV9MSU5LVVAKAGRj
-YnhfY2VlX2ZlYV9zbVsldV0gRmVhdHVyZVsldV0gU0VUX0xPQ0FMX1BBUkFNRVRFUlMKAAAAAAAA
-AAAAAABkY2J4X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVdIEZFQVRVUkVfTk9fQURWRVJUSVNF
-CgAAAAAAAAAAAAAAZGNieF9jZWVfZmVhX3NtWyV1XSBGZWF0dXJlWyV1XSBGRUFUVVJFX1BFRVJf
-Tk9UX0FEVkVSVElTRV9EQ0JYCgAAAAAAAAAAAAAAAAAAAABkY2J4X2NlZV9mZWFfc21bJXVdIEZl
-YXR1cmVbJXVdIEZFQVRVUkVfUEVFUl9OT1RfQURWRVJUSVNFX0ZFQVRVUkUKAAAAAAAAAAAAAAAA
-AGRjYnhfY2VlX2ZlYV9zbVsldV0gRmVhdHVyZVsldV0gRkVBVFVSRV9VUERBVEVfT1BFUl9WRVJT
-SU9OCgAAAABkY2J4X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVdIEZFQVRVUkVfUEVFUl9VUERB
-VEVfT1BFUl9WRVJTSU9OCgAAAAAAAAAAAAAAAAAAAGRjYnhfY2VlX2ZlYV9zbVsldV0gRmVhdHVy
-ZVsldV0gRkVBVFVSRV9HRVRfUEVFUl9DRkcKAAAAAAAAAAAAAABkY2J4X2NlZV9mZWFfc21bJXVd
-IEZlYXR1cmVbJXVdIEZFQVRVUkVfQ0ZHX05PVF9DT01QQVRJQkxFCgAAAAAAZGNieF9jZWVfZmVh
-X3NtWyV1XSBGZWF0dXJlWyV1XSBGRUFUVVJFX1VTRV9MT0NBTF9DRkcKAAAAAAAAAAAAAGRjYnhf
-Y2VlX2ZlYV9zbVsldV0gRmVhdHVyZVsldV0gRkVBVFVSRV9VU0VfUEVFUl9DRkcKAAAAAAAAAAAA
-AABkY2J4X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVdIEZFQVRVUkVfRkVBVFVSRV9ESVNBQkxF
-RAoAAAAAAAAAZGNieF9jZWVfZmVhX3NtWyV1XSBGZWF0dXJlWyV1XSBGRUFUVVJFX0VSUk9SX0NI
-QU5HRQoAAAAAAAAAAAAAAEZlYXR1cmUgJXUgc3luYydkPSV1IChlcnJvciAldSkKAAAAAAAAAAAA
-AAAAAAAAAGlwdjZfYWRkX3ByZWZpeF9pbl9saXN0OiBub2RlIGZvdW5kIDB4JXgKAAAAAAAAAGlw
-djZfYWRkX3ByZWZpeF9pbl9saXN0LCBub2RlIG5vdCBmb3VuZAoAAAAAAAAAAGNobmV0X2FycF91
-cGRhdGVfY2FjaGU6IGFycCBpcDQgZW50cnkgZm91bmQgCgAAAGNobmV0X2FycF91cGRhdGVfY2Fj
-aGU6IGFycCBpcDYgZW50cnkgZm91bmQgCgAAAGNobmV0X2FycF91cGRhdGVfY2FjaGU6IGJvdGgg
-aXA0IGFuZCBpcDYgYWRkciBjYW5ub3QgYmUgbnVsbAoAAABjaG5ldF9sMnRfdXBkYXRlOiBsMnRf
-dXBkYXRlIHJlcXVlc3Qgc2VudCBsMnRlbnQgWyUwOHhdLCBsMnRlbnQtPmlkeCBbJWRdLCBsMnRl
-bnQtPnZsYW4gWyVkXQoAAABjaG5ldF9pcHY2X3JhX2lucHV0OiBJbnZhbGlkIFJBCgAAAAAAAAAA
-AAAAAAAAAABpcHY2IFJBIHJjdmQKAAAAcm91dGVyIG5vdCBwcmVzZW50IGluIG91ciBsaXN0LiBh
-ZGRpbmcgaXQKAAAAAAAASW52YWxpZCBvcHRpb24gbGVuZ3RoICV1IGluIFNMTEEgb3B0aW9uCgAA
-AAAAAAAAR09UIFNMTEEgb3B0aW9uIGluIFJBLCBsZW4gJXUKAABJbnZhbGlkIG9wdGlvbiBsZW5n
-dGggJXUgaW4gcHJlZml4IG9wdGlvbgoAAAAAAABJbnZhbGlkIG9wdGlvbiBsZW5ndGggJXUgaW4g
-bXR1IG9wdGlvbgoAAAAAAAAAAABJbnZhbGlkIHBhY2tldCB3aXRoICV1IGV4dHJhIGJ5dGVzCgAA
-AAAAAAAAAAAAAABtbGQ2IHF1ZXJ5IHJjdmQKAAAAAAAAAAAAAAAAAAAAAGNobmV0X2lwdjZfbWxk
-Nl9xdWVyeV9pbnB1dDogSW52YWxpZCBNTEQgcXVlcnkKAFVuc3VwcG9ydGVkIHF1ZXJ5IHZlcnNp
-b24uIG9ubHkgbWxkdjIgcXVlcnkgc3VwcG9ydGVkCgAAAAAAAAAAAABxdWVyeSByZXNwb25zZSBk
-ZWxheSAldSAoaW4gMTBtcyB1bml0KSAKAAAAAAAAAABhbHJlYWR5IGEgZ2VuZXJhbCBxdWVyeSBw
-ZW5kaW5nIGluICV1ICgxMG1zKQoAAABEZWJ1ZyB0aGUgY29kZS4gZ3JwX25vZGUgbXVzdCBiZSBw
-cmVzZW50CgAAAAAAAABhbHJlYWR5IGEgbXVsdGljYXN0IHF1ZXJ5IHBlbmRpbmcgaW4gJXUgKDEw
-bXMpCgBpcHY2IGVjaG8gcmVxIHJjdmQKAAAAAAAAAAAAAAAAAERIQ1B2NiBwYWNrZXQgdHlwZSAl
-dSwgb3B0c2xlbiAldSByZWNlaXZlZAoAAAAAAEludmFsaWQgZGhjcCBzdGF0ZSAlZAoAAAAAAAAA
-AAAASWdub3JlIERIQ1B2NiBtc2cgeGlkICV4LCAgZGg2Y3R4dC0+eGlkICV4CgAAAAAARXJyb3Ig
-aW4gREhDUHY2IG9wdGlvbnMgcGFyc2luZy4gSWdub3JpbmcgbXNnLCBpICVkLCBvcHRzbGVuICVk
-CgAAAAAAAAAAAAAAAAAAAABESENQIGZhaWxlZCwgc3RhdHVzY29kZSAlZC4gSWdub3JpbmcgYWR2
-ZXJ0aXNlCgBpY21wNiBjaGVja3N1bSB2YWxpZGF0aW9uIGZhaWxlZCwgb3IgZXJyIHJjdmRpZ25v
-cmluZyBpY21wNiBtc2cgJXUsIGRsZW4gJXUKAAAAAG5ldGlmX3Byb2Nlc3NfZGhjcDogbDJkZXZf
-ZmMtPmZsb3djX2lkIFsweCV4XSwgcHJvY2Vzc2luZywgb3B0X2xlbiAldQoAAAAAAAAAAAAAY2hu
-ZXRfZGhjcF9yZWN2OiB2bGFuaWQgWyV1XSwgbDJkZXZfcGlkX2ZjLT5mbG93Y19uZXRfbDJkZXZf
-dmxhbmRldiBbMHgleF0sIGwyZGV2X2ZjIFsweCV4XQoAAAAAY2huZXRfZGhjcF9yZWN2OiBsMmRl
-dl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBkaGN0eHQtPnN0YXRlIFslZF0sIG1hbGFjaW91cyBkaGNw
-IHJlY3YgZm9yIG5vIHJlcXVlc3QKAAAAAAAAAAAAAAAAAGRoY3R4dC0+c3RhdGUgOiAlZAoAAAAA
-AAAAAAAAAAAAbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgQmFkIERIQ1AgY29va2llIHJlY2ll
-dmVkLCBhYm9ydGluZwoAAENvdWxkIG5vIGFsbG9jYXRlIHBjYiEhIEZyZWVpbmcgZmNmICEhIQoA
-AAAAAAAAAHZuX3BhcnNlIHVua25vd24gc3ViY29kZSAldQoAAAAAdm5fcGFyc2UgdW5rbm93biBk
-dHlwZSAldQoAAAAAAABpZ25vcmluZyBmaXAgcmVjdiBmb3IgcGNiIGZsb3c6JXggaW4gb2ZmbGlu
-ZSBzdGF0ZQoAAAAAAAAAAAAAAAAAZmlwX3ZuMnZuX3JlY3ZfZXJyIAoAAAAAAAAAAAAAAABDb3Vs
-ZCBub3QgYWxsb2NhdGUgZmxvd2MhISEhCgAAAENvdWxkIG5vdCBhbGxvY2F0ZSBTQ0IgZmxvd2Mh
-ISEhCgAAAAAAAAAAAAAAAAAAAENvdWxkIG5vdCBmaW5kIHJpZ2h0IHNjYiBmb3IgbG9nbwoAAAAA
-AAAAAAAAAAAAAGlnbm9yaW5nIGZpcCByZWN2IGZvciBmY2YgZmxvdzoleCBpbiBvZmZsaW5lIHN0
-YXRlCgAAAAAAAAAAAAAAAABDb3VsZCBub3QgZmluZCByaWdodCBzY2IgZm9yIGZsb2dpCgAAAAAA
-AAAAAAAAAABwb3J0IDB4JXgsIHN0YXRlIDB4JXgsIHJldHJ5IG5vdCBzdXBwb3J0ZWQKAAAAAABG
-bG9naSByZXNwIHJjdiB3aXRoIHVua25vd24geGNoZyBveF9pZCV4IHNpZCAlMnglMnglMnggZGlk
-ICUyeCUyeCUyeAoAAAAAAAAAAAAAAE5fUE9SVCAweCV4JXgleCByZWplY3RlZCBQTE9HSSB3aXRo
-IHJlYXNvbiBjb2RlICV4CgAAAAAAAAAAAAAAAABBQlRTIHdoaWxlIGF3YWl0aW5nIFBSTEkgUnNw
-OiBmbG93Y19pZCAweCV4IG94X2lkIDB4JXggcnhfaWQgMHgleCAKAAAAAAAAAAAAAAAAAEFCVFMg
-ZmFrZSBSc3A6IGxvYyAweCV4IG94X2lkIDB4JXggcnhfaWQgMHgleAoAAEZDIGZjYiBhbGxvYyBm
-YWlsZWQ6IGF2YWlsICVkCgAARkMgZmNiIGFsbG9jIHhpZDolZCBmbG93aWQgJWQKAABsbGRwX3J4
-X3BrdF9oYW5kbGVyWyV1XSBkcm9wIHByZS1pbml0IChjb3VudCA9ICV1KQoAAAAAAAAAAAAAAAAA
-JXgleCV4IFJlY2lldmVkIExPR08gZnJvbSAleCV4JXggCgAAAAAAAAAAAAAAAAAARmFpbGVkIHRv
-IHBvc3QgeGNoZyBlcnI6IHNzbmkgMHgleCBjb29raWUgMHglbHggcnZhbCAleCAKAAAAAAAAAHRj
-cF9yZWxlYXNlX3RpZDogdGlkIFsweCV4XSwgZmxvd2MgZmxhZ3MgWzB4JXhdLCBidWZmZXJlZCBb
-MHgleF0KAAAAAAAAAAAAAAAAAAAAdGNwX3JlbGVhc2VfdGlkOiBzaXplb2YodGNiX2ZjLT5mbG93
-Y19mb2lzY3NpX2Nvbm4pIFsldV0sIGJ5dGVzCgAAAAAAAAAAAAAAAAAAAABhY3Rfb3Blbl9ycGw6
-IGF0aWQgWzB4JXhdLCB0aWQgWzB4JXhdLCB0Y2JfZmMtPnsgaWQgWzB4JXhdLCBzdGF0ZSBbMHgl
-eF0sIHR5cGUgWzB4JXhdIH0sIGNwbF9vcCBbMHgleF0sIHN0YXR1cyBbMHgleF0KAAAAAAAAAAAA
-AGFjdF9vcGVuX3JwbDogY3NrX2ZjLT57IGlkIFsweCV4XSwgc3RhdGUgWzB4JXhdLCBjc29ja19m
-bGFncyBbMHgleF0gfSAKAAAAAAAAAAAAYWN0X29wZW5fcnBsOiByZWN2ZCBuZWcgYWR2aWNlIFsw
-eCV4XQoAAAAAAAAAAAAAc2VuZF9hYm9ydF9ycGw6IGNza19mYy0+Zmxvd2NfdHlwZSBbMHgleF0s
-IGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCB0aWQgWzB4JXhdLCB1bHB0eGNoIFsldV0sIGJ1ZmZl
-cmVkIFsldV0KAAAAAHdyaF9vZmxkX3RjcF9jbG9zZV9jb25fcmVwbHk6IHRjYl9mYy0+Zmxvd2Nf
-aWQgWzB4JXhdLCB0Y2JfZmMtPmZsb3djX3R5cGUgWzB4JXhdLCBsZW4xNiBbJXVdLCBsb2MgWyV1
-XQoAAAAAAAAAAAB3cmhfb2ZsZF90Y3BfY2xvc2VfY29uX3JlcGx5OiBycGwtPm9wX1RpZCBbMHgl
-eF0sIHJwbD5zdGF0dXMgWzB4JXhdLCBycGwtPnNuZF9ueHQgWzB4JXhdLCBycGwtPnJjdl9ueHQg
-WzB4JXhdCgAAdGNwX2Fib3J0X3JwbF9yc3M6IHRpZCBbMHgleF0sIHN0YXR1cyBbMHgleF0KAAAA
-dGNwX2Fib3J0X3JlcV9yc3M6IHRpZCBbMHgleF0sIHN0YXR1cyBbMHgleF0KAAAAb2ZsZF9hYm9y
-dF9yZXFfbmVnYWR2WyV1XTogd3IgMHglMDh4IGNwbF9hYm9ydF9yZXEgREVMSVZFUkVECgAAAGhv
-c3Rfd3JbJXVdOiB3ciAweCUwOHggY3BsX2Fib3J0X3JlcSBzdGF0dXMgMHgleAoAAAAAAAAAAAAA
-AAAAAABwa3RzY2hlZF9jbF9ybFsldToldV06IG1vZGUgfCB1bml0IHwgcmF0ZSAweCUwNnggbWlu
-ICV1IG1heCAldSBwa3RzaXplICV1CgAAAAAAAHBhcmFtX2NobmV0WzB4JXg6MHgleF06IGNobmV0
-IDB4JXggcmVhZCAldSBwZiAldSByZXQgJWQKAAAAAAAAAABwYXJhbV9kbWFxWzB4JXg6MHgleF06
-IGRtYXEgMHgleCByZWFkICV1IHBmICV1IHJldCAlZAoAAAAAAAAAAAAATUNbJXVdIGluaXRfc3Rh
-dGVfbWFjaGluZSAweCUwMngKAAAAAAAAAAAAAAAAAAAATUMgaW5pdGlhbGl6YXRpb24gbm90IGNv
-bXBsZXRpbmcsIE1DIGN1cnJlbnQgaW5pdCBzdGF0ZSBpcyAweCUwMngKAAAAAAAAAAAAAAAAAABN
-Q1sldV0gX2h3X21jX2luaXRfbWMKAAAAAAAAAAAAAF9od19tY19pbml0X21jX2ZwZ2FbJXVdOiBl
-cnJvciAlZAoAAAAAAAAAAAAAAAAAAHBoeTogZmFpbGVkIHRvIGFsbG9jYXRlZCBtZW1vcnkgZm9y
-IHBoeSBmdyBmaWxlLCByZXQgJWQKAAAAAAAAAABod19sZV9maWx0ZXJfY3R1cGxlOiB0dXBsZSAl
-dSBub3Qgc3BlY2lmaWVkIGJ1dCByZXF1aXJlZCBmb3IgbWFzayAweCV4CgAAAAAAAAAAAGxlIGNv
-bmZpZ3VyYXRpb246IGhhc2ggcmVnaW9uIHRvbyBsYXJnZSB0byBlbmFibGUgc2VydmVyIHNyYW0K
-AABsZSBjb25maWd1cmF0aW9uOiBjYW5ub3QgZW5hYmxlIHNlcnZlciBzcmFtIHdoZW4gaGFzaCBy
-ZWdpb24gaXMgZGlzYWJsZWQKAAAAAAAAAGh3X3RwX3RjcF9zZXR0aW5nc193OiB0aW1lcl9ycyAl
-dXVzIHRpbWVzdGFtcF9yZXMgJXV1cyBkZWxheWVkYWNrX3JlcyAldXVzCgAAAAAAaHdfdHBfdGNw
-X3NldHRpbmdzX3c6IGRhY2tfdGltZXIgJXV1cyBtc2wgJXV1cyByeHRfbWluLG1heCAldSwldXVz
-IHBlcnNfbWluLG1heCAldSwldXVzCgAAAAAAAAAAaHdfdHBfdGNwX3NldHRpbmdzX3c6IGtlZXBf
-aWRsZSxpbnR2bCAldSwldXMgbWF4cnR0ICV1dXMgaW5pdHNydHQgJXV1cyBmaW53YWl0Ml90aW1l
-ciAldXVzCgAAAAAAaHdfdHBfdGNwX3NldHRpbmdzX3c6IGNhcHBpbmcgZGFja190aW1lciBmcm9t
-ICV1IHRvICV1AAAAAAAAAAAAAGh3X3RwX3RjcF9zZXR0aW5nc193OiBjYXBwaW5nIG1zbCBmcm9t
-ICV1IHRvICV1AGh3X3RwX3RjcF9zZXR0aW5nc193OiBjYXBwaW5nIHJ4dF9taW4gZnJvbSAldSB0
-byAldQAAAAAAAAAAAAAAAABod190cF90Y3Bfc2V0dGluZ3NfdzogY2FwcGluZyByeHRfbWF4IGZy
-b20gJXUgdG8gJXUAAAAAAAAAAAAAAAAAaHdfdHBfdGNwX3NldHRpbmdzX3c6IGNhcHBpbmcgcGVy
-c19taW4gZnJvbSAldSB0byAldQAAAAAAAAAAAAAAAGh3X3RwX3RjcF9zZXR0aW5nc193OiBjYXBw
-aW5nIHBlcnNfbWF4IGZyb20gJXUgdG8gJXUAAAAAAAAAAAAAAABod190cF90Y3Bfc2V0dGluZ3Nf
-dzogY2FwcGluZyBrZWVwX2lkbGUgZnJvbSAldSB0byAldQAAAAAAAAAAAAAAaHdfdHBfdGNwX3Nl
-dHRpbmdzX3c6IGNhcHBpbmcga2VlcF9pbnR2bCBmcm9tICV1IHRvICV1AAAAAAAAAAAAAGh3X3Rw
-X3RjcF9zZXR0aW5nc193OiBjYXBwaW5nIGluaXRfc3J0dF9tYXhydHQgZnJvbSAldSB0byAldQAA
-AABod190cF90Y3Bfc2V0dGluZ3NfdzogY2FwcGluZyBpbml0X3NydHRfaW5pdHNydHQgZnJvbSAl
-dSB0byAldQAAaHdfdHBfdGNwX3NldHRpbmdzX3c6IGNhcHBpbmcgZmlud2FpdDJfdGltZXIgZnJv
-bSAldSB0byAldQAAAAAAAGxlIGNvbmZpZ3VyYXRpb246IG5lbnRyaWVzICV1IHJvdXRlICV1IGNs
-aXAgJXUgZmlsdGVyICV1IGFjdGl2ZSAldSBzZXJ2ZXIgJXUgaGFzaCAldQoAAAAAAAAAAAAAAGxl
-IGNvbmZpZ3VyYXRpb246IG5lbnRyaWVzICV1IHJvdXRlICV1IGNsaXAgJXUgZmlsdGVyICV1IHNl
-cnZlciAldSBhY3RpdmUgJXUgaGFzaCAldSBuc2VydmVyc3JhbSAldQoAAAAAAAAAAAAAAABod19z
-Z2VfcXVldWVfYmFzZV9tYXBbJXVdOiBleGNlZWRlZCBudW1iZXIgb2YgZWdyZXNzIHF1ZXVlcywg
-JXUKAAAAAAAAAAAAAAAAAAAAAGh3X3NnZV9xdWV1ZV9iYXNlX21hcFsldV06IGV4Y2VlZGVkIG51
-bWJlciBvZiBpbmdyZXNzIHF1ZXVlcyB3aXRoIGZyZWVsaXN0IGFuZCBpbnRlcnJ1cHQsICV1CgAA
-AGh3X3NnZV9xdWV1ZV9iYXNlX21hcFsldV06IGV4Y2VlZGVkIG51bWJlciBvZiBpbmdyZXNzIHF1
-ZXVlcywgJXUKAAAAAAAAAAAAAAAAAAAAc2t1OiBjdXN0b20gc2t1IDEwRyBkb2VzIG5vdCBzdXBw
-b3J0IDQwRyBwb3J0cwoAc2t1OiBjdXN0b20gc2t1IDQwR19TTyBkb2VzIG5vdCBzdXBwb3J0IGV4
-dG1lbQoAc2t1OiBjdXN0b20gc2t1IDEwR19TTyBkb2VzIG5vdCBzdXBwb3J0IDQwRyBwb3J0cygl
-dSkgb3IgZXh0bWVtKCV1KQoAAAAAAAAAAAAAAABza3U6IGN1c3RvbSBza3UgMHgleCA0MEcgcG9y
-dHMoJXUpIGV4dG1lbSgldSkKAABjZl9wYXJzZTogZmlsZSBtZW10eXBlIDB4JXggbWVtYWRkciAw
-eCV4IG1hcHBlZCBAICVwOgoAAAAAAAAAAAAAY29uZmlndXJlZCB3aXRoIGNhcHMgbmJtfGxpbmsg
-MHglMDh4IHN3aXRjaHxuaWMgMHglMDh4IHRvZXxyZG1hIDB4JTA4eCBpc2NzaXxmY29lIDB4JTA4
-eAoAAAAAAAAAbmV0IFZJIGFsbG9jYXRpb24gZmFpbGVkIGZvciBmY19pZCAldSB3aXRoIGVycm9y
-ICVkCgAAAAAAAAAAAAAAAG5ldCBWSSBtYWMgYWRkcmVzcyBwcm9ncmFtbWluZyBmYWlsZWQgZm9y
-IGZjX2lkICV1IHdpdGggZXJyb3IgJWQKAAAAAAAAAAAAAAAAAAAAbmV0IFZJIHJ4bW9kZSBwcm9n
-cmFtbWluZyBmYWlsZWQgZm9yIGZjX2lkICV1IHdpdGggZXJyb3IgJWQKAAAAAG5ldCBWSSByc3Mg
-aW5kaXJlY3Rpb24gdGFibGUgcHJvZ3JhbW1pbmcgZm9yIGZjX2lkICV1IGZhaWxlZCB3aXRoIGVy
-cm9yICVkCgAAAAAAbmV0IFZJIHJzcyBjb25maWcgY29tbWFuZCBmYWlsZWQgZm9yIGZjX2lkICV1
-IHdpdGggZXJyb3IgJWQKAAAAAG5ldCBWSSBjb21tYW5kIGZhaWxlZCBmb3IgZmNfaWQgJXUgd2l0
-aCBlcnJvciAlZAoAAAAAAAAAAAAAAAAAAABwcm9ncmFtbWVkIEhXIHRhZ20gWzB4JTA4eF0sIEhX
-IHBnc3ogZmFjdG9yIFsweCUwOHhdLCBGT2lTQ1NJIHRhZ20gWzB4JTA4eF0sIHJ0YWdtIFsweCUw
-OHhdLCBtYXhzel9iaXRzIFsldV0sIHN6X2JpdHMgWyV1XS4KAAAAAGJhc2UgWyAweCUwOHhdLCBs
-bGltaXQgWzB4JTA4eF0sIHVsaW1pdCBbMHglMDh4XSwgc2l6ZSBbJXVdLCBtYXhfdHhzeiBbJXVd
-LCBtYXhfcnhzeiBbJXVdLCBpb3NpemUgWyV1XQoAAAAAAAAAAABucHBvZHMgWyV1XSwgaWR4X21h
-c2sgWzB4JTA4eF0sIGlkeF9maXJzdCBbJXVdLCBpZHhfbGFzdCBbJXVdLCBzY3NpX3BsZF9zaXpl
-IFsldV0sIEFMSUdOKHNjc2lfcGxkX3NpemUsIDE2KSBbJXVdLCBwcGRfem9uZXMgWyV1XS4KAAAA
-AAAAAAAAAAAAAABmb2lzY3NpX2luaXQ6IGZvaXNjc2lfaW5pdF9kb25lIFsldV0sIGRldi5yZXMu
-Zm9pc2NzaV9udGFza3MgWyV1XSwgZGV2LnJlcy5mb2lzY3NpX25zZXNzIFsldV0sIGRldi5yZXMu
-bmNzb2NrIFsldV0sIGRldi5yZXMuZm9pc2NzaV9uaW5pdCBbJXVdLCByYyBbJWRdCgAAAAAAAAAA
-Y2hfY2xfcmF0ZVsldS8ldV06IGNhcHBlZCBjbGFzcyByYXRlIGZyb20gcmVxdWVzdGVkICV1IHRv
-IGNvbmZpZ3VyZWQgKGVmZmVjdGl2ZSkgY2hhbm5lbCByYXRlICV1CgAAAAAAAAAAAAAAAAAAAGNo
-X2NsX3JhdGVbJXUvJXVdOiBpbmNyZWFzZWQgZGVmaWNpdF9pbmNyIGZyb20gcmVxdWVzdGVkICV1
-IHRvIHJlcXVpcmVkIG1pbiBvZiAldTsgcmF0ZSAldSAoZWZmICV1KSBkZWZpY2l0X21heCAldQoA
-AAAAAAAAAAAAAAAAcGt0c2NoZWQgY2hhbm5lbCAldSBzZXRzIHNwZWVkIChmcm9tICV1KSB0byAl
-dSBrYnBzCgAAAAAAAAAAAAAAAG5ldF9sMmRldl9ub3RpZnk6IGwyZGV2X2ZjLT5mbG93Y19pZCBb
-MHgleF0sIHBvcnQgWyVkXSwgZXZlbnQgWzB4JXhdLCB1bHB0eGNoIFsldV0sIGNsYXNzIFsweCV4
-XSwgdnByaW8gWzB4JXhdLCB2aWQgWzB4JXhdLCB2aV9yZWFkeSBbJXVdCgAAAAAAAG5ldF9sMmRl
-dl9ub3RpZnk6IHBnaWQgWzB4JXhdLCBwcmlvIFsweCV4XSwgY2ggWzB4JXhdCgAAAAAAAAAAAABm
-Y29lIG5vdGlmeSA6IEZDb0UgTElOS1VQOiBwb3J0IDB4JXgsIGV2ZW50IDB4JXgKAAAAAAAAAAAA
-AAAAAAAAZmNvZSBub3RpZnkgOiBGQ29FIExJTktET1dOOiBwb3J0IDB4JXgsIGV2ZW50IDB4JXgK
-AAAAAAAAAAAAAAAAAGZjb2Ugbm90aWZ5IDogRENCWCA6IHBvcnQgMHgleCwgcHJpb3JpdHkgMHgl
-eCB1bHB0eGNoIDB4JXggY2xhc3MgMHgleAoAAAAAAAAAAAAAZGNieF90aW1lb3V0WyV1XQoAAAAA
-AAAAAAAAAAAAAABwb3J0X2NtZF9oYW5kbGVyOiB1bmtub3duIHUuZGNiLnR5cGUgMHgleAoAAAAA
-AABwb3J0WyV1XSBwdHlwZSAldSBsYW5lICV1OiByeGNmZyA9ICUjeAoAAAAAAAAAAABwb3J0WyV1
-XSBwdHlwZSAldSBsYW5lICV1OiB0eGNmZyA9ICUjeAoAAAAAAAAAAABwb3J0WyV1XSBsaW5rIGRv
-d24gKCV1KSAobHN0YXR1cyAlI3gpCgAAAAAAAAAAAABod19pMmNfdHJhbnNhY3Rpb246IG5kYXRh
-ICV1IGFkZHJfb3AgMHgleCBkYXRhWzBdIDB4JXggZGlmZiAldQoAaHdfaTJjX3RyYW5zYWN0aW9u
-OiBuZGF0YSAldSBhZGRyX29wIDB4JXggZGF0YVswXSAweCV4IGRpZmYgJXUgZHBvcyAldSBjb250
-ICV1IGZhaWxlZCB3aXRoIGVyciAlZAoAAAAAAAAAAAAAAAAAAGkyYyB0cmFuc2FjdGlvbiBmYWls
-ZWQgdG8gY29tcGxldGUKAAAAAAAAAAAAAAAAAGkyYyBlcnJvciBjYXVzZWQgYnkgbW9kdWxlIHVu
-cGx1ZwoAAAAAAAAAAAAAAAAAAHNlbmR0byBwZW5kaW5nOiB3cl9wZW5kICVwIGZvciBwb3J0ICV1
-LCB3YW50IHRvIHNlbmQgdG8gcG9ydCAldQoAAAAAAAAAAAAAAAAAAAAAcG9ydFsldV0gdXBkYXRl
-IChmbG93Y2lkICV1IHJjICV1KQoAAAAAAAAAAAAAAAAAcG9ydF9zZXRfbG9vcGJhY2sgcG9ydCAl
-I3ggY3VycmVudCAlI3ggbW9kZSAlI3gKAAAAAAAAAAAAAAAAAAAAAHBvcnRbJXVdIHNwZWVkIHVw
-ZGF0ZTogJSN4CgAAAAAAcG9ydFsldV0gYmVnaW5uaW5nIGRlYm91bmNlCgAAAABRU0ZQIG1vZHVs
-ZSB1bnBsdWcgLSByZWluaXRpYWxpemluZyByeF9sb3MgIHRvIDB4ZmYKAAAAAAAAAAAAAAAAZ3Bp
-b19xc2ZwX21vZHVsZV91cGRhdGU6IGNoYW5nZWQgcnhfbG9zIGZyb20gMHgleCB0byAweCV4CgAA
-AAAAAGdwaW9fcXNmcF9tb2R1bGVfdXBkYXRlOiBjaGFuZ2VkIHR4X2RpcyBmcm9tIDB4JXggdG8g
-MHgleAoAAAAAAABwb3J0X2xpbmtfc3RhdGVfaGFuZGxlclsldV0gcG93ZXJpbmcgZG93bgoAAAAA
-AABwb3J0X2xpbmtfc3RhdGVfaGFuZGxlclsldV0gcG93ZXJpbmcgdXAKAAAAAAAAAABwb3J0X2xp
-bmtfc3RhdGVfaGFuZGxlclsldV0gdW5rbm93biBzdGF0ZSAoc3RhdGUgPSAlI3gpCgAAAAAAAAAA
-cG9ydF9saW5rX3N0YXRlX2hhbmRsZXI6IFNvbWV0aGluZyB3ZW50IHRlcnJpYmx5IHdyb25nLiBy
-ZXQgPSAlZAoAAAAAAAAAAAAAAAAAAABod19zZ2VfbWFtZW1faW5pdDogZW5jb3VudGVyZWQgZXJy
-b3IgJWQKAAAAAAAAAABsZSBpbml0aWFsaXphdGlvbjogbmVudHJpZXMgJXUgcm91dGUgJXUgY2xp
-cCAldSBmaWx0ZXIgJXUgYWN0aXZlICV1IHNlcnZlciAldSBoYXNoICV1CgAAAAAAAAAAAABsZSBp
-bml0aWFsaXphdGlvbjogbmVudHJpZXMgJXUgcm91dGUgJXUgY2xpcCAldSBmaWx0ZXIgJXUgc2Vy
-dmVyICV1IGFjdGl2ZSAldSBoYXNoICV1IG5zZXJ2ZXJzcmFtICV1CgAAAAAAAAAAAAAAaHdfdHBf
-aW5pdDogdGNiIHJlZ2lvbiAoc3RhcnQgMHglMDhzIHNpemUgJXUpIG11c3QgYmUgaW4gZmlyc3Qg
-MjU2TUIgb2YgTUEgbWVtb3J5CgAAAAAAAAAAAAAAAAAAaHdfdHBfaW5pdDogcGdtbmd0IHJlZ2lv
-biAoc3RhcnQgMHglMDhzIHNpemUgJXUpIG11c3QgYmUgaW4gZmlyc3QgMjU2TUIgb2YgTUEgbWVt
-b3J5CgAAAAAAAAAAAAAAaHdfdHBfaW5pdDogVFAgcGdtbmd0IGluaXRpYWxpemF0aW9uIGRpZCBu
-b3QgY29tcGxldGUKAAAAAAAAAAAAAGJ1Zm1faW5pdDogbiAldSBidWZsbDY0aW50X3NpemUgMHgl
-eAoAAAAAAAAAAAAAAGJ1Zm1faW5pdDogbm90IGVub3VnaCBtZW1vcnkgdG8gYWxsb2NhdGUgaW50
-ZXJuYWwgYnVmbGw2NCBidWZmZXJzCgAAAAAAAAAAAAAAAAAAYnVmbV9pbml0OiBub3QgZW5vdWdo
-IG1lbW9yeSB0byBhbGxvY2F0ZSBidWZsbDY0IGJ1ZmZlcnMKAAAAAAAAAG1lbV9pbml0X2J1Zjog
-bm90IGVub3VnaCBtZW1vcnkgdG8gYWxsb2NhdGUgZmxvdyBidWZmZXJzCgAAAAAAAABtZW1faW5p
-dF9idWY6IG5vdCBlbm91Z2ggbWVtb3J5IHRvIGFsbG9jYXRlIHRjYl9jYWNoZSAob2ZmZXJlZCAl
-dSB0cnlpbmcgdG8gdXNlICV1IGF2YWlsYWJsZSAldSkKAAAAAAAAAAAAAAAAAAAAbXBhcnRpdGlv
-bl9vdGhlcnM6IHN0YXJ0IDB4JTA4eCBzaXplICV1ICh1bnVzZWQgJXUpCgAAAAAAAAAAAAAAAG1w
-YXJ0aXRpb25fb3RoZXJzOiBzdGFydCAweCUwOHggc2l6ZSAldSAodW51c2VkICV1KQoAAAAAAAAA
-AAAAAABtZW1faW5pdDogRURDIG92ZXJjb21taXR0ZWQgYnkgJWQgYnl0ZXMKAAAAAAAAAABtZW1f
-aW5pdDogbm90IGVub3VnaCBtZW1vcnkgdG8gYWxsb2NhdGUgZmxvdyB0YWJsZQoAAAAAAAAAAAAA
-AAAAY3hjbmljX2RldmljZV9pbml0OiBjeGNuaWMgWzB4JTB4XSwgY3hjbmljLT5maWx0ZXIgWyUw
-eF0KAAAAAAAAAHBvZmNvZSBpbml0IGRvbmUKAAAAAAAAAAAAAAAAAAAAUG9ydFsldV06IFVua25v
-d24gU0dNSUkgc3ViLXR5cGUgJSN4CgAAAAAAAAAAAAAAUG9ydFsldV06IFVua25vd24gQlRfWEZJ
-IHN1Yi10eXBlICUjeAoAAAAAAAAAAAAAcG9ydF9pbml0WyV1XTogcG9ydCB0eXBlIDB4JXggaXMg
-bm90IHN1cHBvcnRlZAoAbXBhcnRpdGlvbl9pbml0OiBtb3ZlZCBwbXJ4X3N0YXJ0IGZyb20gMHgl
-MDh4IHRvIDB4JTA4eCB0byBtYWtlIHJvb20gZm9yIExFIEhBU0ggYW5kL29yIFRQIFRDQnMKAAAA
-AAAAAAAAAAAAAAAAAG1wYXJ0aXRpb25faW5pdDogbW92ZWQgcG1yeF9zdGFydCBmcm9tIDB4JTA4
-eCB0byAweCUwOHggKEVEUkFNKQoAAAAAAAAAAAAAAAAAAAAARVEgcGZuICV1IHZmbiAldTogZGVz
-dHJveWluZyBlcWlkICV1IHdpdGggcGVuZGluZyBXUihzKSAobnVtX2J5dGVzICV1IGFuZCBmbGFn
-cyAweCUwOHgKAAAAAAAAAAAAbDJkZXZfZmMtPmZsb3djX2lkIFsldV0sIGwyZGMtPnBmbiBbJXVd
-LCBsMmRjLT52Zm4gWyV1XSwgbDJkYy0+bHBvcnQgWyV1XSwgbDJkZXZfZmMtPmZsb3dpZCBbJXVd
-IGwyZGMtPnR4X2NoIFsldV0sIGRldi52cGQucG9ydHZlYyBbJXhdCgAAAAAAAAAAcG9ydHZlYyBb
-JXVdCgAAAGwyZGV2X3ZpX2ZzbTogbWIgWzB4JXhdLCBkZWZlcnJlZCwgc3RhdGUgWzB4JXhdLCBw
-b3J0IFsweCV4XQoAAABsMmRldl92aV9mc206IHZpaWQgWzB4JXhdIHBvcnQgWzB4JXhdLCBtYWMt
-aWQgWyUwMng6JTAyeDolMDJ4OiUwMng6JTAyeDolMDJ4XS4gCgAAAAAAAAAAAAAAAAAAAABsMmRl
-dl92aV9mc206IHNnZV9lcWlkIFsweCV4XSwgc2dlX2lxaWQgWzB4JXhdLCBzZ2VfZXFjciBbMHgl
-eF0sIHJzc19zeiBbMHgleF0KAGwyZGV2X3ZpX2ZzbTogbDJkZXZfZmMtPmZsb3djX25ldF9sMmRl
-dl9tdHUgWyV1XSwgbWJfc2NyYXRjaCBbMHgleF0sIHBvcnQgWzB4JXhdCgAAAAAAAAAAAAAAAAAA
-AGwyZGV2X3ZpX2ZzbTogdmlpZCBbJWRdLCB2aV9mYy0+Zmxvd2NfdmlfZmxhZ3MgWzB4JXhdCgAA
-AAAAAAAAAABsMmRldl92aV9mc206IHBmbiBbMHgleF0sIHZmbiBbMHgleF0sIGwyZGV2X2ZjLT5m
-bG93Y19pZCBbMHgleF0sIGxwb3J0IFsweCV4XSwgdmlpZCBbMHgleF0sIGZsYWdzIFsweCV4XQoA
-AAAAAAAAbDJkZXZfdmlfZnNtOiBFcnJvciBmcmVlaW5nIFZJLCByYyBbMHgleF0KAAAAAAAAbDJk
-ZXZfdmlfZnNtOiBwaWQgWzB4JXhdLCB2aWlkIFsweCV4XSwgbWJfbG9jIFsweCV4XSwgbWJfb3Jp
-Z1sweCV4XSwgbDJkZXZfZmxhZ3MgWzB4JXhdLCByYyBbMHgleF0KAAAAAAAAAAAAAAAAAEFoIGhh
-Li4uZG91YmxlIGZyZWUgb3hfaWQgMHgleCwgcnhfaWQgMHgleAoAAAAAAEhvc3QgUFJMSSBSZXNw
-b25zZSB0aW1lZG91dDogb3hfaWQgMHgleCByeF9pZCAweCV4CgAAAAAAAAAAAAAAAABGQ09FIEZy
+ABBgMFtwdPevp2AAEHAwKRwQ/TwAAAsQeDDTD236FCrQAMmm+pQAIAICc7D93AEgAgJKcP4KCyAW
+Amjw91sKAAICG3Dy6AgAIAJQcPaEACAAEGAwW3Bg969XYAIQKDDSoNEPAAAAAPP/nG/qEFAwG81e
+iRGMECy0ffm1RCIAABKw0Q/GKtEPbBAI+iwAAD0QWDBbcavzrAABWAA2oBfNDvbMfRAAECAw9Qos
+IAAQYDD8FgUgABBQMPAAO2ALEEgwGcx1BB8UB/8KLfKu+goAL/8QcDD+mAMAAgIhMPjdAQALEEgw
++BIFLAkAbvD99q4mAH+RIGWA990QbZoco64r4AD1sRxyAAB6sPSwumACAlKw+9QAIAICa3D/Cgsg
+FgJw8NoQ8+wBICACWHDx/ggAABBoMP3kACAAEGAwW3AmCqIC9yBaYgAAcPABGQL/CgAgCxBAMG2K
+FCvgAMm2+5QAIAICe/D+7AEgAgJKcP8KCyAWAnDwseP7HBAiAABQcPkKACwAIA/w+dQAIAAQYDBb
+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
+lMEkBQA5sCRVftEPbBAEHLkyGrkyGLkvKsZ/+q1AIIgQWDD6hn8gABBgMFt6gR62Fh25Ky3mMy3d
+Ai3mNNEPAGwQBBq2w/us8CCiADygaCJo9JB+YAICEnD/IhNgARAgMGAANGlkBQWoCCeGAHJLKPo8
+AAIAAFkwW4CL+GESYAICITD5Yt1oACAusCeVAGP/26WrJ7QAY//T0Q8roncpooCjuwm7Efhhb2gA
+IF5waGJuaWTkpZyXwNEPGbbXqTkpkN1oQDb0kF9gAgIRMHJDn2P/xSyidymyhKPM+cwRAAICITD4
+YRtoACBmcGhiG2hkIP8CAAv/vZUQY/+cZZ9RY/+WpZgnhABj/+almielAGP/3qWbl7Bj/9elnCfE
+ANEPpZ0n1QDRDwDRDwAAAAAAAAAAAAAAAAAAIAMQAAzAAAYgByasIAMQBAjAAAwgByasIAMQCDzA
+ABAgByX8IAMQDAbAADggBygQIAMQEAjAADwgByasIAMQFALAAEAgBygQIAMQGAjAAEQgByasIAMQ
+HAhAAEwgByc8IAMQIAhAAFAgByc8IAMQJAhAAFQgByc8IAMQKAhAAFggByc8IAMQLCBAAFwgByc8
+IAMQMCBAAGwgByc8IAMQNCBAAHwgByc8IAMQOCBAAIwgByc8IAMQPCBAAJwgByc8IAMQQCBAAKwg
+Byc8IAMQRCBAALwgByc8IAMQSCBAAMwgByc8IAMQTAxAANwgByUMIAMQUAxAAOggByUMIAMQVAxA
+APQgByUMIAMQWAxAAQAgByUMIAMQXAxAAQwgByUMIAMQYAxAARggByUMIAMQZAxAASQgByUMIAMQ
+aAxAATAgByUMIAMQbAhAATwgByc8IAMQcAhAAUAgByc8IAMQdAhAAUQgByc8IAMQeBBAAUggByc8
+IAMQfBBAAVAgByc8YmNtODQ4NTZfbG9hZHNlcXVlbmNlOiBTdGFydGVkCgBiY204NDg1Nl9sb2Fk
+c2VxdWVuY2U6IFVwbG9hZCBpbWFnZSB0byBQSFkgb24tY2hpcCBtZW1vcnkKAAAAAAAAYmNtODQ4
+NTZfbG9hZHNlcXVlbmNlOiBkb25lIGxvYWRpbmcgaW1hZ2UgKGkgPSAldSkKAAAAAAAAAAAAAAAA
+AGJjbTg0ODU2X2xvYWRzZXF1ZW5jZTogRE9XTkxPQUQgRkFJTEVEIChsbyA9ICUjeCwgaGk9JSN4
+LCBjbnQ9JXUpCgAAAAAAAAAAAAAAAAAAYmNtODQ4NTZfbG9hZHNlcXVlbmNlOiBEb3dubG9hZCBj
+b21wbGV0ZWQgYWZ0ZXIgJXUgbG9vcHMKAAAAAAAAAGh3X2NsNDVfaW5pdFsldV0gYWNhcHMgJSN4
+CgAAAAAAYmNtODQ4NTZfaW5pdFsldV0KAAAAAAAAAAAAAAAAAABod19iY204NDg1Nl9sb3dwb3dl
+clsldV06IGVuYWJsZT0lZAoAAAAAAAAAAAAAAABod19iY204NDg1Nl9sb3dwb3dlclsldV0sIGZh
+aWxlZCB0byBzZXQgMzAuMHg0MDBBIGJpdCA3OyAzMC4weDQwMEUgYml0PTEgYWZ0ZXIgNW1zLCBy
+ZWc9JXgKAAAAAABod19iY201NDgyX2NmZ21kaVsldV0gc2V0dGluZyB0eXBlICV1CgAAAAAAAAAA
+AAByZW1vdmUgbXVsdGljYXN0IG1hYyBbJXg6JXg6JXg6JXg6JXg6JXhdIGZyb20gVENBTQoAAAAA
+AAAAAAAAAAAAaXB2Nl9qb2luX2dycDogaWQgJXUsIHJlZl9jbnQgJXUKAAAAAAAAAAAAAAAAAAAA
+ZGhjcDZfdGltZXJfY2I6IHJlc2VuZGluZyBESENQNlNPTElDSVQgYWdhaW4KAAAAZGhjcDZfdGlt
+ZXJfY2I6IHNlbmRpbmcgREhDUDZSRVFVRVNUCgAAAAAAAAAAAAAAZGhjcDZfdGltZXJfY2I6IHNl
+bmRpbmcgREhDUDZSRU5FVyByZXF1ZXN0CgAAAAAAZGhjcDZfdGltZXJfY2I6IHNlbmRpbmcgREhD
+UDZSRUJJTkQgcmVxdWVzdAoAAAAAZGhjcDZfdGltZXJfY2I6IERIQ1A2UkVQTFkgcmN2ZCwgc3Rh
+dGUgJXUKAAAAAAAAZmFpbGVkIHRvIHJlbmV3L3JlYmluZCBkaGNwdjYgYWRkcmVzcwoAAAAAAAAA
+AAAAdHlwZSAleCwgeGlkICV4LCB0eXBlX3hpZCAleAoAAABpcHY2X211bHRpY2FzdF9xdWVyeV90
+aW1lcl9jYiBub2RlX2lkICVkCgAAAAAAAABpcHY2X2dlbmVyYWxfcXVlcnlfdGltZXJfY2IKAAAA
+AGFkZCBtdWx0aWNhc3QgbWFjIFsleDoleDoleDoleDoleDoleF0gaW4gVENBTQoAAGNobmV0X2lw
+djZfZGFkX2NiOiBoYW5kbGUgJXUsIGFkZHJfaWQgJXUsIGFkZHIgc3RhdGUgJXUKAAAAAAAAAABp
+cHY2IHByZWZlcnJlZCBhZGRyIFslMDR4ICUwNHggJTA0eCAlMDR4XQoAAAAAAABTdGFydGluZyBh
+ZGRyIHZhbGlkaXR5IHRpbWVyIGZvciAldSBzZWNvbmRzCgAAAABWYWxpZGl0eSBleHBpcmVkIGZv
+ciBhZGRyX2lkICV1CgAAAAAAAAAAAAAAAAAAAABzZW5kaW5nIGlwdjYgZWNobyByZXBseQoAAAAA
+AAAAAGNobmV0X2lwdjZfcnNfb3V0cHV0OiBsMmRldl9mYyAweCV4CgAAAAAAAAAAAAAAAGNobmV0
+X2lwdjZfbnNfb3V0cHV0OiBsMmRldl9mYyAweCV4LCBmbG93Y19pZCAweCV4LCB2bGFuIGZsYWcg
+MHgleAoAAAAAAAAAAAAAAAAAY2huZXRfaXB2Nl9uYV9vdXRwdXQ6IGwyZGV2X2ZjIDB4JXgKAAAA
+AAAAAAAAAAAAY2huZXRfaXB2Nl9tbGR2Ml9yZXBvcnRfb3V0cHV0OiBsMmRldl9mYyAweCV4CgAA
+Z2F0aGVyX3Rhc2tzX3RvX3R4X2xpc3Q6IHRhc2sgaW4gdXNlIFsldV0KAAAAAAAAZ2F0aGVyX3Rh
+c2tzX3RvX3R4X2xpc3Q6IGlkeCBbJXVdLCB0YXNrIGZpZCBbMHgleF0sIHRhc2sgc3RhdGUgWzB4
+JXhdLCB0YXNrIGNvbm4gWzB4JXhdLCB0YXNrIGZmbGFncyBbMHgleF0sIGNvbm4gZmlkIFsweCV4
+XSwgZGRwIFslZF0KAAAAAAAAAAAAZ2F0aGVyX3Rhc2tzX3RvX3R4X2xpc3Q6IHRhc2sgWzB4JXhd
+LCBzdGF0ZSBbMHgleF0gb24gY29ubiBbMHgleF0gbm90IHZhbGlkIHRvIGdhdGhlciwgc2tpcHBp
+bmcKAAAAAAAAAAAAAAAAAAAAAGdhdGhlcl90YXNrc190b190eF9saXN0OiB0YXNrIFsweCV4XSwg
+c3RpbGwgcXVldWVkIG9uIHR4IHBlbmRpbmcgbGlzdC4gUmVtb3ZpbmcgaXQuCgAAAAAAAAAAAAAA
+AGdhdGhlcl90YXNrc190b190eF9saXN0OiBjb25uX2ZjLT5mbG93Y19mbGFncyBbMHgleF0sIGxp
+c3RfZW1wdHkgWzB4JXhdLCBhZGRfdGFza19jb3VudCBbMHgleF0KAHRvX3R4X2xpc3Q6IG5vIHRh
+c2sgdG8gY2xvc2UgZm9yIGNvbm4gWzB4JXhdLCBiYWlsaW5nIHRvIHJlY292ZXJ5IHN0YXRlIFsw
+eCV4XQoAYXV0aGVudGljYXRlX3RhcmdldDogS0VZX0NIQVBfUkVTUCAtIFsweCV4JXgleCV4JXgl
+eCV4JXhdCgAAAAAAAGF1dGhlbnRpY2F0ZV90YXJnZXQ6IEtFWV9DSEFQX1JFU1AgLSBbMHgleCV4
+JXgleCV4JXgleCV4XQoAAAAAAABhdXRoZW50aWNhdGVfdGFyZ2V0OiBJbmNvcnJlY3QgcGFzc3dv
+cmQKAAAAAAAAAABDSEFQX0M6IGRpZ2VzdCBleHBhbnNpb24gZXJyb3IKAENIQVBfTjogVGFyZ2V0
+IHVzZXJpZCBtaXNtYXRjaAoAQ0hBUF9SOiBkaWdlc3QgZXhwYW5zaW9uIGVycm9yCgBpU0NTSSBT
+ZWMtcGFyYW1zIHJlY2VpdmVkaGF2ZSBlcnJvcnMhIQoAAAAAAAAAAABUYXJnZXQgbW92ZWQgdGVt
+cC4gY29ubiAleCwgc2VzcyAleAoAAAAAAAAAAAAAAABMb2dpbiBGYWlsZWQhIS4gY29ubl9mYyBb
+MHgleF0sIHNlc3NfZmMgWzB4JXhdLCBzdGF0dXNfY2xhc3MgWzB4JXhdCgAAAAAAAAAAAAAAAFBy
+b3RvY29sIEVycm9yIGNiaXQgJWQgdGJpdCAlZCBjc2cgJWQgbnNnICVkCgAAAHJlY3Zfbm9waW46
+IGN0cmwgdGFzayBhbHJlYWR5IHBlbmRpbmcKAAAAAAAAAAAAAG9mbGRfcnhfZGF0YTogYWllZSwg
+aXNjc2kgY29ubiBbMHgleF0gZm9yIHNlc3MgWzB4JXhdLCB0eXBlIFsweCV4XSB0cmFuc2l0ZWQg
+aW4gdG9lIG1vZGUuIEtpY2tpbmcgcmVjb3ZlcnkgCgAAAABvZmxkX3J4X2RhdGE6IGNvbm4gdGlk
+IFsweCV4XSwgcnhfZGF0YS0+c2VxIFsweCV4XSwgcnhfZGF0YS0+bGVuIFsweCV4XSwgcnhfZGF0
+YS0+c3RhdHVzIFsweCV4XQoAAAAAAAAAAAAAAAAAAAAAb2ZsZF9yeF9kYXRhOiBjc2sgeyBpZCBb
+MHgleF0sIGNzb2NrX29mZnNldCBbMHgleF0sIGRsZW4gWzB4JXhdIH0KAAAAAAAAAAAAAAAAAABh
+Y3RfZXN0OiB0Y2JfZmMgWzB4JXhdLCBmbG93Y19mb2lzY3NpX2Nvbm5fZmxhZ3MgWzB4JXhdCgAA
+AAAAAAAAYWN0X2VzdGFiOiB0Y2JfZmMtPmZsb3djX2J1ZiBbMHgleF0sIHRjYl9mYy0+Zmxvd2Nf
+dHlwZSBbMHgleF0gdGNiX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIG5wYWdlcyBbMHgleF0sIGZs
+b3djX3RwX3NuZF9tYXggWzB4JXhdCgAAAAAAAAAAAAAAAAAAYWN0X2VzdGFiOiBhdGlkIFsweCV4
+XSwgdGlkIFsweCV4XSwgb3AgWzB4JXhdLCByY3ZfaXNuIFsweCV4XSwgc25kX2lzbiBbMHgleF0s
+IGNzb2NrLT5mbG93Y19zdGF0ZSBbMHgleF0sIHRjcF9vcHQgWzB4JXhdLCB0Y2JfZmMtPmZsb3dj
+X2lkIFsweCV4XSAKAAAAAAAAAAAAAAAAAGNza19mYy0+Zmxvd2NfY3NvY2tfY29va2llIFsweCV4
+XSAKAAAAAAAAAAAAAAAAAG5ldF9sMmRldl9maW5kX2J5X2FkZHI2OiBsMmRldl9mYy0+Zmxvd2Nf
+aWQgWzB4JXhdLCBsMmRjLT5scG9ydCBbJXVdLCBsMmRfZmMtPmZsb3djX2lkIFsweCV4XSwgYWRk
+ciBbJTA0eCUwNHglMDR4JTA0eF0KAAAAAAAAAAAAY2huZXRfcXVldWVfeG1pdDogZmMtPmZsb3dj
+X2lkIFsweCV4XSwgYnVmX2xlbiBbMHgleF0sIGJ1ZmZlcmVkIFsweCV4XSwgZmlmby5udW1fYnl0
+ZXMgWyUweF0KAAAAbmV0aWZfZG9fZGhjcHY2OiB3ci0+cGFyYW0udmxhbmlkIFsldV0sIGwyZGV2
+X2ZjLT5mbG93Y19uZXRfbDJkZXZfdmxhbmRldiBbMHgleF0KAAAAAAAAAAAAAAAAAAAAbmV0aWZf
+ZG9fZGhjcHY2OiBpcHY2IG5vdCBlbmFibGVkCgAAAAAAAAAAAAAAAAAAZGhjcCByZXNwIHRvIGRy
+aXZlcgoAAAAAAAAAAAAAAABsM2luNl9kZXZfY29uZmlnOiB3ci0+cGFyYW0udmxhbmlkIFsldV0s
+IGwyZGV2X2ZjLT5mbG93Y19uZXRfbDJkZXZfdmxhbmRldiBbMHgleF0KAAAAAAAAAAAAAAAAAABs
+M2luNl9kZXZfY29uZmlnOiBpcHY2IG5vdCBlbmFibGVkCgAAAAAAAAAAAAAAAABuZXRfbDNpbjZf
+ZGV2X2NvbmZpZzogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgYWRkcmVzcyBhbHJlYWR5IHVz
+ZWQgYnkgcG9ydCAlZCwgYWRkcl9pZCAlZAoAAABuZXRfbDNpbjZfZGV2X2NvbmZpZzogIGFkZHIg
+WzB4JTA0eCUwNHglMDR4JTA0eF0sIHJlZl9jbnQgWzB4JXhdIGluIHVzZQoAAAAAAAAAAGwzaW40
+X2Rldl9jb25maWc6IHdyLT5wYXJhbS52bGFuaWQgWyV1XSwgbDJkZXZfZmMtPmZsb3djX25ldF9s
+MmRldl92bGFuZGV2IFsweCV4XQoAAAAAAAAAAAAAAAAAAG5ldF9sM2luNF9kZXZfY29uZmlnOiBs
+MmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBhZGRyZXNzIGFscmVhZHkgdXNlZCBieSBwb3J0ICVk
+CgAAAAAAAAAAAAAAAAAAAG5ldF9sM2luNF9kZXZfY29uZmlnOiAgYWRkciBbMHgleF0sIG1hc2sg
+WzB4JXhdLCBndyBbMHgleF0sIHJlZl9jbnQgWzB4JXhdIGluIHVzZQoAAAAAAAAAAAAAAAAAAGwy
+ZGV2X2ZjIFsweCV4IF0gRmFpbGVkIHRvIHN0YXJ0IHRpbWVyIGZvciBpcHY0IGRhZAoAAAAAAAAA
+AAAAAAB3cmhfY2huZXRfaWZjb25mOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBsMmRldl9m
+Yy0+Zmxvd2NfdHlwZSBbJTB4XSwgaWZjb25mX3dyLT5zdWJvcCBbMHgleF0KAAAAAAAAAAAAAAAA
+AAAAd3JoX2NobmV0X2lmY29uZjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgdW5rbm93biBz
+dWJvcCBbMHgleF0KAAAAAAAAAAAAAAAAAAB3cmhfY2huZXRfaWZjb25mOiBsMmRldl9mYy0+Zmxv
+d2NfaWQgWzB4JXhdLCByYyAlZAoAAAAAAAAAAAAAAAAAbmV0aWZfaXBfY29uZmxpY3RfdGltZXJf
+Y2I6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIGV4cGVjdGluZyB0aW1lciBoYW5kbGUgWyVk
+XSwgYnV0IGdvdCBoYW5kbGUgWyVkXSBleHBpcnkKAG5ldGlmX2lwX2NvbmZsaWN0X3RpbWVyX2Ni
+OiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBpbmRldmN0eHQtPnN0YXRlIFslZF0sIGluZGV2
+Y3R4dC0+cmV0cnlfY250IFslZF0KAAAAAAAAAABuZXRpZl9pcF9jb25mbGljdF90aW1lcl9jYjog
+bDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgaW5kZXZjdHh0IFsweCV4XSwgaW4gZnJlZSBzdGF0
+ZQoAAAAAAAAAAABjbWRoX2NobmV0X2lmYWNlOiBmYyBbMHgleF0sIGZjLT5mbG93Y19pZCBbMHgl
+eF0sIGZjLT5mbG93Y190eXBlIFsweCV4XSwgcCBbMHgleF0sIGxlbjE2IFsldV0sIGxvYyBbMHgl
+eF0KAAAAAAAAY21kaF9jaG5ldF9pZmFjZTpsMmRldl9mYyBbMHgleF0sIGwyZGV2X2ZjLT5mbG93
+Y19pZCBbMHgleF0sIGwyZGV2LT5mbG93Y190eXBlIFsldV0sIGwyZGV2X2ZjLT5mbG93Y19uZXRf
+bDJkZXZfZmxhZ3MgWyUweF0KAAAAAABjbWRoX2NobmV0X2lmYWNlOiByMlswXSAldSByMlsxXSAl
+dQoAAAAAAAAAAAAAAABjbWRoX2NobmV0X2lmYWNlOiBsMmRldl9mYy0+Zmxvd2NfbmV0X2wyZGV2
+X2ZsYWdzIGNoYW5nZWQgZnJvbSBbJTB4XSB0byBbJTB4XSwgcmMgWyVkXQoAAAAAAAAAAABjaG5l
+dF9sMmRldl91cF9tYl9jYjogcmMgWyVkXSwgcG9ydCBbJXVdLCBzdGF0ZSBbJXVdLCBjb29raWUg
+WzB4JXhdCgAAAAAAAAAAAAAAAGRoY3BfcHJvY2Vzc19jYjogbDJkZXZfZmMtPmZsb3djX2lkIFsw
+eCV4XSwgZGhjdHh0LT5zdGF0ZSBbJTB4XSwgZGhjdHh0LT5ydHJ5X2NudCBbJXVdCgAAAAAAAAAA
+AGRoY3BfdGltZXJfY2I6IERIQ1BESVNDT1ZFUiBzZW50LCBidXQgbm8gcmVwbHkgZnJvbSBhbnkg
+cG9zc2libGUgc2VydmVyIG9uIHRoZSBuZXR3b3JrLiBSZXRyeWluZyBhZ2FpbgoAAAAAAAAAAABk
+aGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBzZW5kaW5nIERIQ1BESVND
+T1ZFUiBmb3IgZGhjdHh0IFsweCV4XSBvbiBwaWQgWyVkXQoAAABkaGNwX3RpbWVyX2NiOiBsMmRl
+dl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBESENQT0ZGRVIgcmVjZWl2ZWQgZm9yIGRoY3R4dCBbJXhd
+IHBpZCBbJWRdCgAAAAAAAAAAAABkaGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4
+JXhdLCAgREhDUEFDSyByZWNlaXZlZCBmb3IgZGhjdHh0IFsleF0sIHBpZCBbJWRdCgAAAAAAAAAA
+AABkaGNwX3RpbWVyX2NiOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBkaGN0eHQtPmlwYWRk
+ciBbMHgleF0KAAAAAAAAAAAAAAAAAAAAAGRoY3BfdGltZXJfY2I6IHN0YXJ0aW5nIHRpbWVyIGZv
+ciBsZWFzZSBbJXVdIHNlY29uZHMKAAAAAAAAAAAAAABkaGNwX3RpbWVyX2NiOiBsZWFzZSB0aW1l
+IG9mIFsldV0gc2Vjb25kcyBleHBpcmVkLCBzZW5kaW5nIHJlbmV3IHJlcXVlc3QKAAAAAAAAAGRo
+Y3BfdGltZXJfY2I6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIG5vIHJlcGx5IGZyb20gZGhj
+cCBzZXJ2ZXIsIHRpbWluZyBvdXQKAAAAAAAAAAAAAAAAAAAAAGF1dGhfbmVnb19zZWN1cml0eTog
+c2VuZF9mbGFnIFsweCV4XSwgYXV0aF9wb2xpY3kgWzB4JXhdCgAAAAAAAABhdXRoX25lZ29fc2Vj
+dXJpdHk6IEtFWV9DSEFQX1JFU1AgLSBoYXNoWzB4JXgleCV4JXgleCV4JXgleF0KAAAAYXV0aF9u
+ZWdvX3NlY3VyaXR5OiBLRVlfQ0hBUF9SRVNQIC0gaGFzaFsweCV4JXgleCV4JXgleCV4JXhdCgAA
+AGF1dGhfbmVnb19zZWN1cml0eTogS0VZX0NIQVBfUkVTUCAtIGVycm9yIGVuY29kaW5nIHRvIGhl
+eAoAAAAAAABhdXRoX25lZ29fc2VjdXJpdHk6IEtFWV9DSEFQX1JFU1AgLSBlbGVuIFsweCV4XQoA
+AAAAAAAAAAAAAAAAAAAAYXV0aF9uZWdvX3NlY3VyaXR5OiBLRVlfQ0hBUF9DSEFMIC0gZXJyb3Ig
+ZW5jb2RpbmcgdG8gaGV4CgAAAAAAAGF1dGhfbmVnb19zZWN1cml0eTogS0VZX0NIQVBfQ0hBTCAt
+IGVsZW4gWzB4JXhdCgAAAAAAAAAAAAAAAAAAAABsb2dvdXRfdGltZWRvdXQ6IGxvZ291dCByZXF1
+ZXN0IHRpbWVkb3V0LCBwb3NzaWJsZSBuZXR3b3JrIGlzc3Vlcy4gRm9yY2VmdWxseSBicmVha2lu
+ZyBwYXRoIGZvciBzZXNzIFsweCV4XQoAAAAAcGluZ190YXJnZXQ6IHBpbmcgdGltZW91dCwga2lj
+a2luZyByZWNvdmVyeSBmb3Igc2VzcyBbMHgleF0KAAAAAGNzb2NrX2ZhaWxlZDogY3NrX2ZjLT5m
+bG93Y19pZCBbMHgleF0sIGNza19mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCBzZXNzX2ZjLT5mbG93
+Y19pZCBbMHgleF0sIHNlc3NfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwgZXZ0IFsweCV4XQoAAAAA
+AAAAAAAAAGNobmV0X2ZpbmRfaXA2X2wydF9lbnRyeTogZmluZCBwcmVmaXggbWF0Y2ggWyUwNHgg
+JTA0eCAlMDR4ICUwNHhdCgAAAAAAAAAAAAAAAAAATm8gcm91dGVyIGNvbmZpZ3VyZWQsIGwyZGV2
+X2ZjLT5mbG93Y19pZCAweCV4CgAAClJvdXRlciBsaWZlICV1IGV4cGlyZWQuIGRlbGV0aW5nIHJv
+dXRlciBbJTA0eCAlMDR4ICUwNHggJTA0eF0KAFVzaW5nIHJvdXRlciBbJTA0eCAlMDR4ICUwNHgg
+JTA0eF0gdG8gcmVhY2ggWyUwNHggJTA0eCAlMDR4ICUwNHhdCgAAAAAAAAAAAAAAAAAAbDJ0ZW50
+IFslMHhdLCBsMnRlbnQtPmlkeCBbJWRdCgByYyBbJWRdLCBjc2tfZmMgWzB4JXhdLCBjc2tfZmMt
+PmZsb3djX2lkIFsweCV4XQoAAAAAAAAAAAAAAAAAAAAAcmVjb3ZlcnlfdGltZW91dDogc2VzcyBp
+ZCBbMHgleF0gc3RhdGUgWzB4JXhdLCByY291bnQgWyVkXSwgZmxhZ3MgWzB4JXhdCgAAAAAAAABy
+ZWNvdmVyeV90aW1lb3V0OiBzZXNzIGlkIFsweCV4XSBpbiBsb2dvdXQsIGFib3J0IHRoZSBjb25u
+ZWN0aW9uCgAAAAAAAAAAAAAAAAAAAHJlY292ZXJ5X3RpbWVvdXQ6IHNlc3NfZmMtPmZsb3djX2Zv
+aXNjc2lfc2Vzc19mbGFncyBbMHgleF0sIGNvbm5lY3Rpb24gcmVxdWVzdCBwZW5kaW5nLCBiYWls
+aW5nIG91dAoAAAAAAAAAAAAAAABmb2lzY3NpOiBSZWNvdmVyeSB0aW1lZCBvdXQgYWZ0ZXIgWyV1
+XSByZXRyeSwgYmFpbGluZyBvdXQKAAAAAAAAVENQIGNvbm4gZXN0YWJsaXNobWVudCBmYWlsZWQg
+JWQKAAAAAAAAAAAAAAAAAAAAZGlzY292ZXJ5X2RhdGE6IHNlc3MgeyBpZCBbMHgleF0sIGZsYWdz
+IFsweCV4XSwgYnVmZmVyZWQgWyV1XS4gfQoAAAAAAAAAAAAAAAAAAABkaXNjb3ZlcnlfZGF0YTog
+c2VzcyB7IGlkIFsweCV4XSB9LCB1bHB0eGNoIFsldV0gbm8gY3JlZGl0cyBhdmFpbGFibGUsIHJl
+c2NoZWR1bGluZyByZXF1ZXN0LgoAAABJbnZhbGlkIG9wY29kZSAweCV4IGluIGN0cmwgcGF0aAoA
+AAAAAAAAAAAAAAAAAABERFAgZXJyb3IgWzB4JXhdLCBhYm9ydGluZyBjb25ubiBbMHgleF0KAAAA
+AAAAAAByeF9kYXRhX2RkcDogUmVzcG9uY2UgcmVjaWV2ZWQgZm9yIHRhc2sgWzB4JXhdIHdoaWxl
+IGludmFsaWQgdGFzayBvciBjb25uZWN0aW9uIHN0YXRlLiB0YXNrIHN0YXRlIFsweCV4XSwgY29u
+biBzdGF0ZSBbMHgleF0sIGNvbm4gZmxhZ3MgWzB4JXhdCgBpc2NzaV9oZHJfcng6IFJlc3BvbmNl
+IHJlY2lldmVkIGZvciB0YXNrIFsweCV4XSB3aGlsZSBpbnZhbGlkIHRhc2sgb3IgY29ubmVjdGlv
+biBzdGF0ZS4gdGFzayBzdGF0ZSBbMHgleF0sIGNvbm4gc3RhdGUgWzB4JXhdLCBjb25uIGZsYWdz
+IFsweCV4XQoAAAAAAAAAAAAAAAAAAAAAaXNjc2lfaGRyX3J4OiBJbnZhbGlkIHRhc2sgc3RhdGUg
+MHgleCBmb3IgdGFzayAweCV4LCBpdHQgWzB4JXhdLCBvcGMgWzB4JXhdCgAAAABwcm9jZXNzX3Rt
+Zl9yZXNwb25zZTogYnVmZmVyZWQgWzB4JXhdLCBpc3Rhc2tfZmMtPmZsb3djX2J1Zi0+c2NoZWRf
+bm9kZS5uZXh0IFsweCV4XSwgaXN0YXNrX2ZjIFsweCV4XSwgaXN0YXNrX2ZjLT5mbG93Y19pZCBb
+MHgleF0KAAAAAAAAAAAAAAAAAABwcm9jZXNzX3RtZl9yZXNwb25zZTogd3Igb3AgWzB4JXhdLCB0
+bWYgb3AgWzB4JXhdCgAAAAAAAAAAAAAAAAAAcmV0dXJuX3BlbmRpbmdfdGFzazogY29va2llIFsw
+eCUwOHhdLCBbMHglMDh4XQoAcmV0dXJuX3BlbmRpbmdfdGFzazogZGVsYXkgcHJvY2Vzc2luZywg
+Y29ubiBmbGFncyBbMHgleF0KAAAAAAAAAHJldHVybl9wZW5kaW5nX3Rhc2s6IERvbmUgc2VuZGlu
+ZyB0YXNrIGVycm9yIHRvIGhvc3QsIHVscHR4bGVuMTYgWyV1XQoAAAAAAAAAAAAAcmV0dXJuX3Bl
+bmRpbmdfdGFzazogZGVxdWV1ZSB0YXNrIFsweCV4XSwgc3RhdGUgWzB4JXhdIGZyb20gdHhfbGlz
+dAoAAAAAAAAAAAAAAAByZXR1cm5fcGVuZGluZ190YXNrOiBhbGwgdGFza3MgcmV0dXJuZWQsIHJl
+Y292ZXJ5IHN0YXRlIHRyYW5zIHRvIFsweCV4XQoAAAAAAAAAAGNsZWFyX2RkcF9tYXA6IGlzdGFz
+a19mYyBbMHgleF0sIGlzdGFza19mYy0+Zmxvd2NfaWQgWzB4JXhdIGJ1ZmZlcmVkICV1CgAAAAAA
+AAAAY2xlYXJfZGRwX21hcDogaXN0YXNrX2ZjLT5mbG93Y19mb2lzY3NpX3Rhc2tfbnBwb2QgJXUs
+IG5wcG9kICV1LCBwcGRhZGRyIFsweCV4XQoAAAAAAAAAAAAAAAAAAAAAY2xlYXJfZGRwX21hcDog
+YWxsIHJldHVybmVkIHRhc2tzIGRkcCBjbGVhcmVkLCByZWNvdmVyeSBzdGF0ZSB0cmFucyB0byBb
+MHgleF0KAAB3cmhfZm9pc2NzaV9ub2RlOiBub2RlX3dyLT5mbG93aWRfbGVuMTYgMiBbJXhdCgB3
+cmhfZm9pc2NzaV9jaGFwOiBpZF9sZW4gWyV4XSwgc2VjX2xlbiBbJXhdCgAAAAB3cmhfZm9pc2Nz
+aV9jaGFwOiB0Z3RfaWRfbGVuIFsleF0sIHRndF9zZWNfbGVuIFsleF0KAAAAAAAAAAAAAAAAc2Vz
+c2lvbl9ibG9jazogc2Vzc19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBzZXNzX2ZjLT5mbG93Y19zdGF0
+ZSBbMHgleF0sIGNvbm5fZmMtPmZsb3djX2lkIFsweCV4XSwgY29ubl9mYy0+Zmxvd2Nfc3RhdGUg
+WzB4JXhdLCBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19zdGF0ZSBbMHgl
+eF0KAAAAAAAAAAAAAAAAAAAAc2Vzc2lvbl91bmJsb2NrOiBzZXNzX2ZjLT5mbG93Y19pZCBbMHgl
+eF0sIHNlc3NfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwgY29ubl9mYy0+Zmxvd2NfaWQgWzB4JXhd
+LCBjb25uX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCBj
+c2tfZmMtPmZsb3djX3N0YXRlIFsweCV4XQoAAAAAAAAAAAAAAAAAc3RhcnRfbG9nb3V0OiBTZXNz
+LWlkIFsweCV4XSBhbHJlYWR5IGxvZ2dpbiBvdXQuCgAAAAAAAAAAAAAAAAAAAHBlZXJfY29uOiBj
+c2tfZmMgPT4gZmxvd2lkIFsweCV4XSwgZmxvd2NfYnVmIFsweCV4XQoAAAAAAAAAAAAAAABhbGxv
+Y19zZXNzOiBsb2dpbl9yZXRyeSBbJWRdLCByZWNvdl90aW1lb3V0IFslZF0KAAAAAAAAAAAAAAAA
+AAAAZm9pc2NzaV9jdHJsOiBzdWJvcCBbMHgleF0sIHNlc3NfdHlwZV90b19lcmwgWzB4JXhdLCBz
+ZXNzX3R5cGUgWzB4JXhdCgAAAAAAAAAAAABmb2lzY3NpX2N0cmw6IHJlY2VpdmVkIGJsb2NrZWQg
+ZnJvbSBkcml2ZXIsIHRyaWdnZXJpbmcgcmV0dXJuIHRhc2tzIG5vdy4KAAAAAAAAAHdhdGNoZG9n
+IGNtZCBoYW5kbGVyICh0aW1lICV1IGFjdGlvbiAldSkKAAAAAAAAAFdBVENIRE9HOiBkZXZpY2Ug
+c2h1dGRvd24KAAAAAAAAV0FUQ0hET0c6IHBvcnRbJXVdIHBhdXNlIHdhdGNoZG9nIHRpbWVvdXQK
+AAAAAAAAV0FUQ0hET0c6IGJ5cGFzcyB0aW1lb3V0CgAAAAAAAABXQVRDSERPRzogRkxSIC0gbm90
+IGltcGxlbWVudGVkIHlldAoAAAAAAAAAAAAAAABXQVRDSERPRzogdGVtcGVyYXR1cmUgb2YgJWRD
+IGV4Y2VlZHMgdGhyZXNob2xkIG9mICVkQwoAAAAAAAAAAAAAZmlsdGVyOiBwb3JncmFtbWluZyB0
+aWQgJXUgKGxlIHRjYW0gaW5kZXggJXUpLi4uCgAAAAAAAAAAAAAAAAAAAGZpbHRlcjogcmVxdWVz
+dGluZyBjb21wbGV0aW9uLi4uCgAAAAAAAAAAAAAAAAAAAGNobmV0X2lwdjZfbGlua19jaGFuZ2Vf
+bm90aWZ5OiBsMmRldl9mYyBbMHgleF0sIHN0YXR1cyAldQoAAAAAAABsMmRldl9zZW5kX3BvcnRf
+ZXZlbnQ6IHdyIFsweCV4XSBwZW5kaW5nIG9uIHBvcnQgWyVkXSwgY3VycmVudCB0cnkgWyVkXQoA
+AAAAAAAAAEZDT0UgRnJlZTogc3RpbGwgeWllbGRlZCB3aGVuIGZyZWVpbmcuLi5mbG93Y19pZCAl
+eCBmbG93Y19mbGFncyAleCAKAAAAAAAAAAAAAAAARkNPRSBCUCBXUiBFUlI6IFdSIHdpdGggY29v
+a2llICV4JXggZXJyb3JlZCBiYWNrIAoAAAAAAAAAAAAAAAAAAHBvcnQgJWQgc2V0IHBmY19lbiA9
+IDB4JXgKAAAAAAAAcG9ydCAlZCBzZXQgcGZjX2VuID0gMHgleAoAAAAAAABldHNfc2V0X2NmZ19p
+ZWVlWyV1XSB1bmtub3duIFRTQSBhbGcgZm9yIHByaW8gJXU6ICV1CgAAAAAAAAAAAAAARkNvRSBE
+RFAgZmFpbGVkIDogb3hfaWQgMHgleCByeF9pZCAweCV4CgAAAAAAAAAARkNvRSBERFAgZmFpbGVk
+IDogRGRwUmVwb3J0IDB4JXggRGRwVmFsaWQgMHgleAoARkMgeGNoZyBhbGxvYyBmYWlsZWQ6IGF2
+YWlsICVkCgBmY29lIG5vdGlmeSA6IFVwZGF0ZSBuZXcgRENCWCB2YWx1ZXMgVkkgc3RhdGUgMHgl
+eCBwcmkgMHgleCBzY2hlZGNsIDB4JXggZGNieF9kb25lIDB4JXgKAAAAAAAAAABmY29lIG5vdGlm
+eSA6IEZDRiBmbG93aWQgMHgleCwgdWxwY2ggMHgleCAKAAAAAABQUkxJIFJzcCB0aW1lZG91dCA6
+IGZsb3djX2lkIDB4JXggb3hfaWQgMHgleCByeF9pZCAweCV4IAoAAAAAAAAAY2Fubm90IGFsbG9j
+YXRlIG9mZmxvYWRlZCBmaWx0ZXIgY29ubmVjdGlvbgoAAAAAY2Fubm90IGFsbG9jYXRlIG9mZmxv
+YWRlZCBmaWx0ZXIgSVB2NiBjb25uZWN0aW9uCgAAAAAAAAAAAAAAAAAAAGRpc3BhdGNoX2RlZmVy
+cmVkX2NsYXNzX2NsYXNzX3NoYXBpbmdbJXU6JXVdOiBsaXN0X2VtcHR5CgAAAAAAAABsb29wYmFj
+ayBidWZmZXIgZ3JvdXBbJXVdIGlzIGRpc2FibGVkCgAAAAAAAAAAAABpbnZhbGlkIGJ1ZmZlciBn
+cm91cFsldV0gY29uZmlndXJhdGlvbjogbXR1ICV1IGx3bSAldSBod20gJXUgZHdtICV1CgAAAAAA
+AAAAAAAAAGZjICV1IHZmICV1IGdvdCBpdmY9MHgleCxyYW5nZTogJSN4LSUjeCAoJXUvJXUgdXNl
+ZCkKAAAAAAAAAAAAAABWSSAldSBjYW5ub3QgZ2V0IFJTUyBzbGljZTogTm8gbW9yZSBzbGljZXMg
+YXZhaWxhYmxlICh1c2VkICV1LyV1KQoAAAAAAAAAAAAAAAAAAHBmbiAldSB2Zm4gJXUgd2l0aCBw
+b3J0IG1hc2sgMHgleCBjYW5ub3QgYWNjZXNzIHBvcnQgJXUsIHJldCAlZAoAAAAAAAAAAAAAAAAA
+AAAAcGZuICV1IHZmbiAldSBjb3VsZCBub3QgYWxsb2NhdGUgdmlpZCwgcmV0ICVkCgAAcGZuICV1
+IHZmbiAldSBjb3VsZCBtYXAgdmlpZCAgMHgleCB0byBmbG93YywgcmV0ICVkCgAAAAAAAAAAAAAA
+AHBmbiAldSB2Zm4gJXUgY291bGQgbm90IGFsbG9jYXRlIHV3aXJlIGZ1bmMgJWQgbWFjIGFkZHIs
+IHJldCAlZAoAAAAAAAAAAAAAAAAAAAAAbWlpX2luaXRbJXVdOiBhY2FwcyAweCV4CgAAAAAAAABt
+aWlfZm9yY2Vfc3BlZWRbJXVdOiByY2FwcyAweCV4CgAAAAAAAAAAAAAAAAAAAABtaWlfcGRvd25b
+JXVdOiBwb3dlcmRvd24gZW4gJXUKAHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06IHVua25vd24gYWN0
+aW9uIDB4JXgKAAAAAHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06IHVua25vd24gcmVhZCBhY3Rpb24g
+MHgleAoAAAAAAAAAAAAAAAAAAABjcGxfZXJyX25vdGlmeTogdGlkICV1IGNwbCAweCUwOHglMDh4
+CgAAAAAAAAAAAABjcGxfZXJyX25vdGlmeTogdGlkICV1IGNwbCAweCUwOHglMDh4IDB4JTA4eCUw
+OHgKAAAAAAAAAAAAAAAAAAAAY3BsX2Vycl9ub3RpZnk6IHRpZCAldSBsZW4gJXUKAABGQ09FIEZy
ZWU6IHN0aWxsIHlpZWxkZWQgd2hlbiBmcmVlaW5nLi4uZmxvd2NfaWQgJXggZmxvd2NfZmxhZ3Mg
-JXggCgAAAAAAAAAAAAAAAEZDIHhjaGcgZnJlZSB4aWQ6JWQgZmxvd2lkICVkCgAAcGZuICV1IHZm
-biAldSB2aWEgY29tbWFuZAoAAAAAAABjb25maWd1cmF0aW9uIGZpbGUgcGFyc2VyOiBwbCB0aW1l
-b3V0IHZhbHVlIGlzIHRvbyBsYXJnZSwgY2hhbmdpbmcgZnJvbSAldSB0byAldXVzZWNzCgAAAAAA
-AAAAAABQTF9QQ0lFX0xJTksuc3BlZWQgb2YgJXUgaXMgbm90IHN1cHBvcnRlZApmaWxlLCByZXQg
-RldfRUlPCgAAAAAAc2NoZWRfaW9xdHhfYnBfcHJpb3JpdHk6IGhhcyAldSBlbnRyaWVzIG9ubHks
-IHJlcXVpcmVzICV1IGVudHJpZXMKAAAAAAAAAAAAAAAAAAB0cF9iYWNrb2ZmOiBwYXJzZWQgJWQg
-aW5zdGVhZCBvZiAldSBlbnRyaWVzCgAAAAB0cF90aW1lcnZhbHM6IHBhcnNlZCAlZCBpbnN0ZWFk
-IG9mICV1IGVudHJpZXMKAAB0cF90aW1lcnJlczogcGFyc2VkICVkIGluc3RlYWQgb2YgJXUgZW50
-cmllcwoAAAB0cF9tdHVzIGhhcyAldSBlbnRyaWVzIG9ubHksIHJlcXVpcmVzICV1IGVudHJpZXMK
-AAAAAAAAAAAAAAAAAAAAdHBfbXR1c1sldV0gaXMgJXUgYnl0ZXMgd2hpY2ggaXMgbm90IHN1cHBv
-cnRlZAoAY29uZmlndXJhdGlvbiBmaWxlIHBhcnNlcjogc2dlIHRpbWVyIHZhbHVlWyVpXSBpcyB0
-b28gbGFyZ2UsIGNoYW5naW5nIGZyb20gJXUgdG8gJXV1c2VjcwoAAAAAAAAAZmlsdGVybWFzayAw
-eCV4IGlzIG5vdCBlcXVhbC9zdWJzZXQgdG8vb2YgZmlsdGVybW9kZQoAAAAAAAAAAAAAAGh3X2xl
-X2NsaXBfaGFuZGxlcjogcmVtb3ZlZCBwb3M9JXUgKD1pZHggJXUpCgAAAGh3X2xlX2NsaXBfaGFu
-ZGxlcjogYWRkaW5nIHRvIHBvcz0ldSAoPWlkeCAldSkKAG1vZHVsZVsldV06IHBvcnQgbW9kdWxl
-IGluc2VydGVkIGFuZCByZWFkeQoAAAAAAG1vZHVsZVsldV06IHBvcnQgbW9kdWxlIHJlbW92ZWQK
-AAAAAAAAAAAAAAAAAAAAAG1vZHVsZVsldV06IHVua25vd24gbW9kdWxlIGlkZW50aWZpZXIgMHgl
-MDJ4CgAAAG1vZHVsZVsldV06IGdwaW8gJXUgdHJhbnMgMTBHIDB4JTAyeCAxRyAweCUwMnggKGxl
-bmd0aCAldSkgY2FibGUgMHglMDJ4IChsZW5ndGggJXUpIG1vZHVsZV90eXBlIDB4JTAyeAoAAAAA
-AAAAAABtb2R1bGVbJXVdOiBncGlvICV1IHRyYW5zIDEwRyAweCUwMnggMUcgMHglMDJ4IChsZW5n
-dGggJXUpIGNhYmxlIDB4JTAyeCAobGVuZ3RoICV1KSBtb2R1bGVfdHlwZSAweCUwMngKAAAAAAAA
-AAAAY3JfbW9kdWxlX3J4X2xvc1sldV06IHJ4X2xvcyBjaGFuZ2VkIHRvICV1CgAAAAAATUM6IGV4
-cGVjdGVkIHN0YXRlIHRvIHN3aXRjaCB0byBDRkcuAAAAAAAAAAAAAAAATUM6IGV4cGVjdGVkIHN0
-YXRlIHRvIHN3aXRjaCB0byBBY2Nlc3MuAAAAAAAAAAAATUM6IGV4cGVjdGVkIHN0YXRlIHRvIHN3
-aXRjaCB0byBDRkcuAAAAAAAAAAAAAAAATUM6IGV4cGVjdGVkIHN0YXRlIHRvIHN3aXRjaCB0byBB
-Y2Nlc3MuAAAAAAAAAAAASUkuMS5ieCBkcDE4WyV1XSBxWyV1XSAlI3ggJSN4ICUjeCAlI3ggbWlu
-ICUjeCBtYXggJSN4CgAAAAAAAAAAAElJLjEuYy1kLiAlI3ggJSN4ICUjeCAlI3ggYWxsICAlI3gK
-AAAAAAAAAAAAAAAAAElJLjIuYiAoJSN4IC0gJSN4ICsgJSN4KSAlIDEyOCA9ICUjeAoAAAAAAAAA
-AAAAAElJLjMgaW5ld18xZSBhZnRlciBsaW1pdCBjb21wdXRlIGl0ZW1wXzFlICV4LCBpbmV3XzFl
-ICV4CgAAAAAAAABJSS4zLiBpdGVtcF8xZSAlI3ggaW5ld18xZSAlI3ggaW5ld18xZSAlZAoAAAAA
-AABJSS40LiBzZXRfMWUgJSN4CgAAAAAAAAAAAAAAAAAAAE1DOiBjYWxpYnJhdGlvbiBmYWlsZWQg
-Zm9yIGVycmF0YTI5IGRwMTggJXUKAAAAAElWLjEuIGRwMThbJXVdIHBoYXNlX3NlbCBiZWZvcmUg
-JSN4IGFmdGVyICUjeCwgZ2F0ZV9kZWxheSAlI3gKAABNQyBlcnJhdGEyOSBpc3N1ZTogZHAxOCAl
-dSBxdWFkICV1IGNhbm5vdCBiZSBkZWNyZWFzZWQKAAAAAAAAAAAATUMgZXJyYXRhMjkgaXNzdWU6
-IGRwMTggJXUgcXVhZCAldSBjYW5ub3QgYmUgZGVjcmVhc2VkCgAAAAAAAAAAAE1DIGVycmF0YTI5
-IGlzc3VlOiBkcDE4ICV1IHF1YWQgJXUgY2Fubm90IGJlIGRlY3JlYXNlZAoAAAAAAAAAAABNQyBl
-cnJhdGEyOSBpc3N1ZTogZHAxOCAldSBxdWFkICV1IGNhbm5vdCBiZSBkZWNyZWFzZWQKAAAAAAAA
-AAAAdGVtcDJfMWUrMHgxMCA9ICUjeAoAAAAAAAAAAAAAAABNQzogY2FsaWJyYXRpb24gZmFpbGVk
-IGZvciBlcnJhdGEyMSBpdGVyYXRpb24gJXUKAAAAAAAAAAAAAAAAAAAATUMgZXJyYXRhIDIxOiBk
-cDE4WyV1XSBwcjAgbjAyIGZhaWxlZCB0byBnZXQgYXZlcmFnZQoAAAAAAAAAAAAAAE1DIGVycmF0
-YSAyMTogZHAxOFsldV0gcHIwIG4xMyBmYWlsZWQgdG8gZ2V0IGF2ZXJhZ2UKAAAAAAAAAAAAAABN
-QyBlcnJhdGEgMjE6IGRwMThbJXVdIHByMSBuMDIgZmFpbGVkIHRvIGdldCBhdmVyYWdlCgAAAAAA
-AAAAAAAATUMgZXJyYXRhIDIxOiBkcDE4WyV1XSBwcjEgbjEzIGZhaWxlZCB0byBnZXQgYXZlcmFn
-ZQoAAAAAAAAAAAAAAE1DIGluaXRpYWxpemF0aW9uIGZhaWxlZDogREZJIGluaXQgbm90IGdvaW5n
-IHRvIDAKAAAAAAAAAAAAAAAAAABNQyBpbml0aWFsaXphdGlvbiBmYWlsZWQ6IERGSSBpbml0IG5v
-dCBjb21wbGV0aW5nCgAAAAAAAAAAAAAAAAAATUMgaW5pdGlhbGl6YXRpb24gZmFpbGVkOiBDYWxp
-YnJhdGlvbiBkaWRuJ3QgY29tcGxldGUuCgAAAAAAAAAAAERQMTggJXUsIGJ5dGVfbGFuZSAldSwg
-Yml0X3NlbGVjdCAldQoAAAAAAAAAAAAAAERQMTggJXUsIGJ5dGVfbGFuZSAldSwgYml0X3NlbGVj
-dCAldQoAAAAAAAAAAAAAAE1DIGZhaWxlZCB0byBnZXQgVVBDVEwgcG93ZXIgdXAgZG9uZQoAAAAA
-AAAAAAAAAE1DIGluaXRpYWxpemF0aW9uIGZhaWxlZDogRGlkbid0IGdldCBhbGwgRFAxOHMgbG9j
-a2VkCgAAAAAAAAAAAABNQyBpbml0aWFsaXphdGlvbiBmYWlsZWQ6IERpZG4ndCBnZXQgYm90aCBB
-RFJzIGxvY2tlZAoAAAAAAAAAAAAAQ3VycmVudCBTbGV3IHR4X3JvdyAlZDogdHhfY29sICVkLCB2
-YWwgJWQKAAAAAAAAQ3VycmVudCBTbGV3IGFkZHJfcm93ICVkOiBhZGRyX2NvbCAlZCwgdmFsICVk
-CgAATUMgaW5pdGlhbGl6YXRpb24gZmFpbGVkOiBTTEVXX0RPTkVfU1RBVFVTIG5ldmVyIHRvZ2ds
-ZWQAAAAAAAAAAGZscl9wZnZmX2ZzbVsldToldV06IHVua25vd24gc3RhdGUgJXUKAAAAAAAAAAAA
-AGh3IHBmIGJpdG1hcCAweCUwMnggdmZpZCBiaXRtYXAgMHglMDh4OjB4JTA4eDoweCUwOHg6MHgl
-MDh4CgAAAABhZnRlciB2ZmlkIGZpeHVwLCB2ZmlkIGJpdG1hcCAweCUwOHg6MHglMDh4OjB4JTA4
-eDoweCUwOHgKAAAAAAAATUNbJXVdOiBmYWlsZWQgdG8gc3dpdGNoIGNvbnRyb2xsZXIgdG8gQ0ZH
-IHN0YXRlCgAAAAAAAAAAAAAAAAAAAE1DWyV1XTogZmFpbGVkIHRvIHN3aXRjaCBjb250cm9sbGVy
-IHRvIElOSVRfTUVNIHN0YXRlCgAAAAAAAAAAAABNQ1sldV06IGZhaWxlZCB0byBzd2l0Y2ggY29u
-dHJvbGxlciB0byBDRkcgc3RhdGUKAAAAAAAAAAAAAAAAAAAATUNbJXVdOiBwZXJpb2RpYyBjYWxp
-YnJhdGlvbiBmYWlsZWQgd2l0aCBlcnJvciAldQoAAAAAAAAAAAAAAAAAAHRpbWVyIHF1ZXVlICV1
-IGxvc3QgYSB0aWNrISBuZXh0ICVwIGxhc3QgJXAgbnVtZSAldQoAAAAAAAAAAAAAAABmbHJfdGlt
-ZXJfc3RhcnQ6IGZsb3djX2lkICV1ICVwIGJ1ZiAlcAoAAAAAAAAAAABNQUM6IFBMTHMgZGlkbid0
-IGxvY2sKAAAAAAAAAAAAAHBjaWU6IHJlYWQgZnJvbSBzZXJjZmcgcGNpZV9pcF91cl9tYXhmdW5j
-IDB4JXggcGZiaXRtYXAgMHgleAoAAABwY2llOiBucGYgJXUgKHBmYml0bWFwIDB4JTAyeCkgbnZm
-ICV1IChwZiAwLi43IDB4JTA4eCUwOHgpIHZmc3RyaWRlICV1CgAAAAAAAAAAAGZhaWxlZCB0byBm
-aW5kIHRoZSAlYyVjIFZQRCBwYXJhbWV0ZXIKAAAAAAAAAAAAAGZhaWxlZCB0byBwYXJzZSB0aGUg
-JWMlYyBWUEQgcGFyYW1ldGVyCgAAAAAAAAAAAGZhaWxlZCB0byBzdWNjZXNzZnVsbHkgZmluZCBD
-aGVsc2lvIFZQRAoAAAAAAAAAAGxvZyBpbml0aWFsaXplZCBAIDB4JTA4eCBzaXplICV1ICgldSBl
-bnRyaWVzKSBmd3JldiAweCUwOHggcGNpZV9mdyAweCUwOHgKAAAAAAAAYm9vdHN0cmFwIGZpcm13
-YXJlIHRvb2sgJXUgbXNlY3MgdG8gcnVuCgAAAAAAAAAAUEkgZXJyb3IgZmxvd2lkX2xlbjE2IDB4
-JXgsIGFwcF90YWcgMHgleCwgcmVmX3RhZyAweCV4LCBwaXNjICUwNHggJTA0eCAlMDR4ICUwNHgK
-AAAAAAAAAAAAAAAAAAAAZmxvd2MgJXUgKFNHRSBlcWlkICV1KSAoRVRIQ1RSTCBxdWV1ZSkgZXhw
-ZXJpZW5jZWQgYSBQQ0kgRE1BIFJFQUQgd29yayByZXF1ZXN0IGVycm9yIChpbmJvdW5kIHF1ZXVl
-ICV1KQoAAAAAAAAAAGZsb3djICV1IChTR0UgZXFpZCAldSkgZXhwZXJpZW5jZWQgYW4gdW5leHBl
-Y3RlZCBQQ0kgRE1BIFJFQUQgd29yayByZXF1ZXN0IGVycm9yIChpbmJvdW5kIHF1ZXVlICV1KQoA
-AAAAAAAAAAAAAABmbG93YyAldSBleHBlcmllbmNlZCBhbiB1bmV4cGVjdGVkIFBDSSBETUEgUkVB
-RCBlcnJvciAoaW5ib3VuZCBxdWV1ZSAldSkKAAAAAAAAAGdhdGhlcl90YXNrc19mb3JfdG1mOiBp
-ZHggWzB4JXhdLCB0YXNrLWlkIFsweCV4XSwgY21kLWlkIFsweCV4XSwgYWN0aXZlIHRhc2tzIFsw
-eCV4XS4gY29ubi1pZCBbMHgleF0sIGNtZCBjb25uLWlkIFsweCV4XSwgdGFzayBjb25uLWlkIFsw
-eCV4XQoAAGdhdGhlcl90YXNrc19mb3JfdG1mOiBJbnZhbGlkIHR5cGUgWzB4JXhdLCBiYWlsaW5n
-IG91dC4KAAAAAAAAAABnYXRoZXJfdGFza3NfZm9yX3RtZjogdGFzayBpZCBbMHgleF0sIHN0YXRl
-IFsweCV4XSwgbGlkeCBbMHgleF0sIGNvb2tpZSBoaSBbMHglMDh4XSA6IGxvIFsweCUwOHhdCgAA
-AAAAAAAAAAAAAAAAZ2F0aGVyX3Rhc2tzX2Zvcl90bWY6IHJjIFsweCV4XSwgWzB4JXhdIHRhc2sg
-Z2F0aGVyZWQgZm9yIHRtZiB0eXBlIFsweCV4XSBwcm9jZXNzaW5nLgoAAAAAAAAAAAAAc2NzaV9k
-YXRhX291dDogY29ubl9mYyBbMHgleF0sIHN0YXRlIFsweCV4XSwgc2Vzc19mYyBbMHgleF0gaW4g
-cmVjb3ZlcnkuIFNraXBwaW5nIGlzdGFza19mYyBbMHgleF0gZnJvbSBUWC4KAAAAAHNlbmRfYWJv
-cnRfcmVxOiBjc2tfZmMtPmZsb3djX3R5cGUgWzB4JXhdLCBjc2tfZmMtPmZsb3djX2lkIFsweCV4
-XSwgdGlkIFsweCV4XSwgdWxwdHhjaCBbJXVdLCBidWZmZXJlZCBbJXVdCgAAAABodyByZWdpc3Rl
-ciBvcGVyYXRpb24gbm90IGNvbXBsZXRpbmcsIHJlZyAweCUwOHggbWFzayAweCUwOHggdmFsdWUg
-MHglMDh4IChyZWcgMHglMDh4KQoAAAAAAAAAAABNRElPIENMNDU6IGZhaWxlZCB0byBzZXQgdXAg
-TU1EIGFkZHIKAAAAAAAAAAAAAABNRElPOiBmYWlsZWQgdG8gcmVhZAoAAAAAAAAAAAAAAGh3X2Jj
-bTg0ODU2X2NoZWNrIGVudHJ5CgAAAAAAAAAAaHdfYmNtODQ4NTZfY2hlY2sgbG9vcCAldSAoY2hl
-Y2sgJSN4KQoAAAAAAAAAAAAAaHdfYmNtODQ4NTZfY2hlY2sgdXBfcnVubmluZyAobG9vcF9jbnQ9
-JXUpCgAAAAAAaHdfYmNtODQ4NTZfY2hlY2sgZmFpbGVkIChiYWQgQ1JDKQoAAAAAAAAAAAAAAAAA
-UEhZIGZpcm13YXJlIGxvYWQgc3VjY2Vzc2Z1bCEgKHdvdy4uLikKAAAAAAAAAAAATURJTyBDTDQ1
-OiBmYWlsZWQgdG8gc2V0IHVwIE1NRCBhZGRyCgAAAAAAAAAAAAAATURJTzogZmFpbGVkIHRvIHdy
-aXRlCgAAAAAAAAAAAABtaWlfYWR2X2ZjWyV1XTogcmNhcHMgMHgleAoAAAAAAG1paV9hZHZfc3Bl
-ZWRbJXVdOiByY2FwcyAweCV4CgAAbmV0aWZfc2V0X21hYzogbDJkZXZfZmMtPmZsb3djX25ldF9s
-MmRldl9tYnMgWzB4JXhdCgAAAAAAAAAAAAAAAHJlbW92aW5nIG1hYwoAAABub2RlLT5ncnAgWyUw
-NHggJTA0eCAlMDR4ICUwNHhdLCBub2RlX2lkICV1LCByZWZfY250ICV1CgAAAAAAAAAAREFEIGZv
-ciBhZGRyIFslMDR4ICUwNHggJTA0eCAlMDR4XQoAAAAAAAAAAAAAAAAAY3BsX3R4X3BrdDogdmxh
-bmlkIFsweCV4XQoAAAAAAABjcGxfdHhfcGt0OiB2bGFuaWQgWzB4JXhdCgAAAAAAAGZsb3djX2lk
-IFsldV0gbDJkZXZfZmMgWzB4JXhdIGFscmVhZHkgcmVjZWl2ZWQgUkEsIG5vdCBzZW5kaW5nIFJT
-CgAAAAAAAAAAAAAAAAAAZmxvd2NpZCBbJXVdIGwyZGV2X2ZjIFsweCV4XSBObyBJUHY2IHJvdXRl
-cgoAAAAAc2VuZF9jbG9zZV9yZXE6IGNza19mYy0+Zmxvd2NfdHlwZSBbMHgleF0sIGNza19mYy0+
-Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPnRjYl9zdGF0ZSBbMHgleF0KAAAAc2VuZF9jbG9zZV9y
-ZXE6IGNza19mYy0+Zmxvd2NfdHlwZSBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCB0
-aWQgWzB4JXhdLCB1bHB0eGNoIFsldV0sYnVmZmVyZWQgWyV1XQoAAAAAAG9mbGRfdGNwX2RvX2Fj
-dGl2ZV9jbG9zZTogY3NrX2ZjIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19m
-Yy0+dGNiX3N0YXRlIFsweCV4XQoAAAAAAG9mbGRfdGNwX2RvX2FjdGl2ZV9jbG9zZTogY3NrX2Zj
-IFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+dGNiX3N0YXRlIFsweCV4
-XQoAAAAAAG9mbGRfdGNwX2Rpc2Nvbm5lY3Q6IHRjYl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tf
-ZmMtPmZsb3djX2lkIFsweCV4XSwgY3NrLT50Y2Jfc3RhdGUgWzB4JXhdCgAAAGRlY29kZV9iYXNl
-NjRfc3RyaW5nOiBkbGVuIFslZF0KAAAAAAAAAAAAAAAAAAAAAGRlY29kZV9oZXhfc3RyaW5nOiBk
-bGVuIFslZF0KAAAAZm9pc2NzaV92YWxpZGF0ZV9sb2dpbl9zdGFnZTogLSAxCgAAAAAAAAAAAAAA
-AAAAYXN5bmNfcGR1OiBsb2dvdXQgcmVxdWVzdGVkIGJsb2NraW5nIHNlc3Npb24KAAAAYXN5bmNf
-cGR1OiBzZXNzL2Nvbm4gZHJvcCByZXF1ZXN0ZWQgYmxvY2tpbmcgc2Vzc2lvbgoAAAAAAAAAAAAA
-AGNwbF90eF9wa3Q6IHZsYW5pZCBbMHgleF0KAAAAAAAAcmVpbml0IGxpbmstbG9jYWwgYWRkcmVz
-cwoAAAAAAABuZXRfbDJkZXZfZmluZF9ieV9hZGRyOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhd
-LCBsMmRjLT5scG9ydCBbJXVdLCBsMmRfZmMtPmZsb3djX2lkIFsweCV4XSwgbDJkYy0+aW40X2Rl
-di5pbl9hZGRyLmFkZHIgWzB4JXhdLCBhZGRyIFsweCV4XQoAAABuZXRfbDJkZXZfbXR1X2NvbmZp
-ZzogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgbXR1ICV1CgAAAAAAAAAAbmV0aWZfZG9fZGhj
-cDogd3ItPnBhcmFtLnZsYW5pZCBbJXVdLCBsMmRldl9mYy0+Zmxvd2NfbmV0X2wyZGV2X3ZsYW5k
-ZXYgWzB4JXhdCgBjcGxfdHhfcGt0OiB2bGFuaWQgWzB4JXhdCgAAAAAAAGVuY29kZSBoZXggc3Ry
-aW5nOiBkbGVuIFslZF0KAAAAY2huZXRfZmluZF9sMnRfZW50cnk6IGRhZGRyIFslMDh4XSwgWzB4
-JTA4eF0sIGxvY2FsIG5ldHdvcmsgWyVkXQoAAAAAAAAAAAAAAAAAAABsMnRlbnQgWyUweF0sIGwy
-dGVudC0+aWR4IFslZF0KAHRjcF9zZW5kX2FvcGVuX3JlcTogY3NrX2ZjLT5mbG93Y19pZCBbMHgl
-eF0sIGNza19mYy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCBidWZmZXJlZCBbJXVdLCByZXNfY250IFsw
-eCV4XSwgaXFfaWR4IFsweCV4XQoAAAAAAAAAAAAAdGNwX3NlbmRfYW9wZW5fcmVxOiBjc2tfZmMt
-PmZsb3djX2lkIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIG5vIHZhbGlkIGwy
-dF9lbnR5LiBEZWxheWluZyBhbm90aGVyIHJldHJ5IGZvciAxIHNlY29uZHMuCgAAAAAAAAAAAAAA
-AAAAYW9wZW5fcmVxOiBod19sZV9maWx0ZXJfY3R1cGxlIGZhaWxlZAoAAAAAAAAAAAAAb2ZsZF90
-Y3Bfc2VuZF9hb3Blbl9yZXE6IGNwbF9yZXEtPkZpbHRlcl9oaSBbMHglMHhdLCBjcGxfcmVxLT5G
-aWx0ZXJfbG9fRkNvRU1hc2sgWzB4JTB4XSwgY3R1cGxlc1swXSBbMHgleF0sIGN0dXBsZXNbMV0g
-WzB4JXhdCgBjb25uZWN0aW9uIG92ZXIgaXB2NiwgbDJkZXYgZmxvd2NfaWQgMHgleAoAAAAAAABj
-c29ja19hbGxvYzogdHhfY2ggWzB4JXhdLCBscG9ydCBbMHgleF0sIGNvb2tpZSBbJTA4eF0KAAAA
-AAAAAAAAY3NvY2tfYWxsb2M6IGF2YWlsYWJsZSBbJXVdLCBuY3NvY2sgWyV1XSwgcG9zOmF0aWQg
-WzB4JXhdLCBjc2tfZmMgWzB4JXhdLCBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgc3BvcnQgWyV1
-XQoAAFdBVENIRE9HOiBObyB0ZW1wZXJhdHVyZSBzZW5zb3IgYXZhaWxhYmxlLgoAAAAAAHdhdGNo
-ZG9nIGNtZCByZWZyZXNoIChhY3Rpb24gJXUpCgAAAAAAAAAAAAAAAAAAAFdBVENIRE9HOiBBY3Rp
-dmF0aW5nCgAAAAAAAAAAAAAAV0FUQ0hET0cgLSBFbmFibGUgYWN0aW9uICV1IHRpbWUgJXUKAAAA
-AAAAAAAAAAAAV0FUQ0hET0cgLSBEaXNhYmxlIGFjdGlvbiAldQoAAABXQVRDSERPRzogRGUtYWN0
-aXZhdGluZwoAAAAAAAAAAHBvcnRbJXVdIHNldCBQQVVTRSBQQVJBTVM6IHBwcGVuICV1IHR4cGUg
-JSN4IHJ4cGUgJSN4CgAAAAAAAAAAAABtcHNfbGlua191cFsldV0gYWNhcHMgJSN4ICg4MDIuMyAl
-I3gpICsgbHBhY2FwcyAlI3ggPT4gJSN4CgAAAAAAaXB2Nl9oYW5kbGVfbGlua19kb3duIGZsb3dj
-X2lkIDB4JXgKAAAAAAAAAAAAAAAAaXB2Nl9oYW5kbGVfbGlua191cCBmbG93Y19pZCAweCV4CgAA
-AAAAAAAAAAAAAAAAZm9pc2NzaSBjb25uX2ZjIFsweCV4XSwgZmxvd2Nfc2NoZWRjbCBbMHgleF0s
-IGluZ19jaCBbMHgleF0sIGVncl9jaCBbMHgleF0KAAAAAABsMmRldl9ub3RpZnkgd2l0aCB1bmtu
-b3duIGZsYWcgWzB4JXhdCgAAAAAAAAAAAABGQ29FIEZDQiBsaW5rZG93bjogaW9fcmVxIDB4JXgl
-eCBpcWlkIDB4JXggZmxvd2lkIDB4JXggb3AgMHgleAoAY2FuY2VsIGZjYjoleCBzY2I6JXggc3Rh
-dGU6JXgKAABSREVWIG1zZyBmbG93YzoleCBzdGF0ZSAweCV4IGV2ZW50IDB4JXgKAAAAAAAAAAB2
-bjJ2bjogcG9ydCAweCV4IGRpZDoweCV4JXgleCBVUAoAAAAAAAAAAAAAAAAAAAB2bjJ2bjogcG9y
-dCAweCV4IGRpZDoweCV4JXgleCBET1dOCgAAAAAAAAAAAAAAAABmY19zZW5kX2FsbG9jX2NwbDog
-ZmFpbGVkIHRvIHNldHVwIGZpbHRlciBjdHVwbGUKAAAAAAAAAAAAAAAAAAAAZmNvZV9jb21wdXRl
-X2N0dXBsZSAweCV4OiV4CgAAAABjb21wdXRlX2N0dXBsZSgpOiBmYWlsZWQgdG8gc2V0dXAgZmls
-dGVyIGN0dXBsZQoAAAAAAAAAAAAAAAAAAAAAZmNvZV9jb21wdXRlX2N0dXBsZSB2bGFuICV4IHZp
-aWQgJXggcG9ydCAleCBtcHNfaWR4ICV4CgAAAAAAAAAAAEFwcGx5IEFQUDogcG9ydCAlZCBwcmlv
-ciAlZCBzZWxlY3QgJWQgcHJvdG9jb2xJRCAweCUwNHgKAAAAAAAAAABjaF9jbF9yYXRlWyV1LyV1
-XTogY2FwcGVkIGRlZmljaXRfaW5jciBmcm9tIHJlcXVpcmVkICV1IHRvICV1OyByYXRlICV1IChl
-ZmYgJXUpIGRlZmljaXRfbWF4ICV1CgBmY19zZW5kX2FsbG9jX2NwbDogZmFpbGVkIHRvIHNldHVw
-IGZpbHRlciBjdHVwbGUKAAAAAAAAAAAAAAAAAAAAZmNvZV9jb21wdXRlX2N0dXBsZSAweCV4OiV4
-CgAAAABjb21wdXRlX2N0dXBsZSgpOiBmYWlsZWQgdG8gc2V0dXAgZmlsdGVyIGN0dXBsZQoAAAAA
-AAAAAAAAAAAAAAAARkNvRSBGQ0YgdGltZXI6IGZsb3djIHN0YXRlIDB4JXgsIHBvcnQgMHgleCAs
-ZmNmIDB4JXgsIGZsb3djX2lkIDB4JXgKAAAAAAAAAAAAAAByaV93cl9pbml0WyV1XTogbXNzICV1
-IGlzIG5vdCA4LWJ5dGUgYWxpZ25lZAoAAABjb3JlX3Byb2dyYW1fdGNiOiB0aWQgJSN4IHRfc3Rh
-dGUgJSN4IHJjdl9hZHYgMHglMDh4IHJjdl9zY2FsZSAlI3ggdHhfbWF4ICUjeCByY3Zfbnh0ICUj
-eCBhdGlkICUjeAoAAAAAAAAAAAAAAAAACW9wdDAgJSN4JXggb3B0MiAlI3ggaXB2NiAlI3ggZmxh
-Z3NfdGltZXIgMHglMDh4CgAAAAAAAAAAAAAAAAAAAG9mbGRfY29ubmVjdGlvbl93cjogY29ubmVj
-dGlvbiB3aXRoIDUtdHVwbGUgbHAgMHglMDR4IGZwIDB4JTA0eCBsaXAgMHglMDh4JTA4eCBwaXAg
-MHglMDh4JTA4eCBmaWx0ZXIgMHglMDh4IGV4aXN0cyBAIExFIGluZGV4ICV1CgAAAAAAAAAAAAAA
-AAAAAG9mbGRfY29ubmVjdGlvbl93cjogY29ubmVjdGlvbiB3aXRoIDUtdHVwbGUgbHAgMHglMDR4
-IGZwIDB4JTA0eCBsaXAgMHglMDh4IHBpcCAweCUwOHggZmlsdGVyIDB4JTA4eCBleGlzdHMgQCBM
-RSBpbmRleCAldQoAAAAAAAAAb2ZsZF9jb25uZWN0aW9uX3dyOiBjb25uZWN0aW9uIHdpdGggNS10
-dXBsZSBscCAweCUwNHggZnAgMHglMDR4IGxpcCAweCUwOHglMDh4IHBpcCAweCUwOHglMDh4IGZp
-bHRlciAweCUwOHgKAAAAAG9mbGRfY29ubmVjdGlvbl93cjogY29ubmVjdGlvbiB3aXRoIDUtdHVw
-bGUgbHAgMHglMDR4IGZwIDB4JTA0eCBsaXAgMHglMDh4IHBpcCAweCUwOHggZmlsdGVyIDB4JTA4
-eAoAAAAAAAAAAAAAAABJUUZMSU5UIHBmbiAldSB2Zm4gJXU6IGlxZXNpemUgJXUgdG9vIHNtYWxs
-CgAAAABJUUZMSU5UIHBmbiAldSB2Zm4gJXU6IGlxaWQgJXUgdG9vIGxhcmdlIChtYXggJXUpCgAA
-AAAAAAAAAAAAAAAASVFGTElOVCBwZm4gJXUgdmZuICV1OiBpcWlkICV1IG5vdCBhbGxvY2F0ZWQK
-AAAASVFGTElOVCBwZm4gJXUgdmZuICV1OiBmbDBpZCAldSB0b28gbGFyZ2UgKG1heCAldSkKAAAA
-AAAAAAAAAAAAAElRRkxJTlQgcGZuICV1IHZmbiAldTogZmwwaWQgJXUgbm90IGFsbG9jYXRlZAoA
-AElRRkxJTlQgcGZuICV1IHZmbiAldTogZmwxaWQgJXUgdG9vIGxhcmdlIChtYXggJXUpCgAAAAAA
-AAAAAAAAAABJUUZMSU5UIHBmbiAldSB2Zm4gJXU6IGZsMWlkICV1IG5vdCBhbGxvY2F0ZWQKAABJ
-UUZMSU5UIHBmbiAldSB2Zm4gJXU6IGZsMWlkICV1IGlzIHZhbGlkIGJ1dCBub3QgZmwwaWQgJXUK
-AAAAAAAASVFGTElOVCBwZm4gJXUgdmZuICV1OiBmbDFpZCAldSBpcyB2YWxpZCBidXQgaGVhZGVy
-IHNwbGl0IGZlYXR1cmUgaXMgbm90IGVuYWJsZWQKAAAAAAAAAAAAAAAAAAAAaHdfdWxwdHhfd29y
-a2Fyb3VuZF9wcjE2OTQ5X2VuYWJsZWRfcGY6IHBmICV1IGVuYWJsZWQgJXUKAAAAAAAAAGh3X3Vs
-cHR4X3dvcmthcm91bmRfcHIxNjk0OV9lbmFibGVkX3ZmaWQ6IHZmaWQgJXUgZW5hYmxlZCAldQoA
-AABFUSBwZm4gJXUgdmZuICV1OiBjcmVhdGluZyBFVEggZXFpZCAldSB3aXRoIHBlbmRpbmcgV1Io
-cykgKG51bV9ieXRlcyAldSBhbmQgZmxhZ3MgMHglMDh4CgAAAAAAAABFUSBwZm4gJXUgdmZuICV1
-OiBjcmVhdGluZyBDVFJMIGVxaWQgJXUgd2l0aCBwZW5kaW5nIFdSKHMpIChudW1fYnl0ZXMgJXUg
-YW5kIGZsYWdzIDB4JTA4eAoAAAAAAABFUSBwZm4gJXUgdmZuICV1OiBlcWlkICV1IHRvbyBsYXJn
-ZSAobWF4ICV1KQoAAABFUSBwZm4gJXUgdmZuICV1OiBlcWlkICV1IG5vdCBhbGxvY2F0ZWQKAAAA
-AAAAAABwb3J0X2JsaW5rX2xlZF9yZXN0b3JlCgAAAAAAAAAAAHBvcnRfYmxpbms6IGJsaW5rZHVy
-PTB4JXggYmxpbmtfcmVmY250CgAAAAAAAAAAAHBvcnRfYmxpbms6IAlibGlua19yZWZjbnQ9MHgl
-eAoAcG9ydF9ibGluazogCWJsaW5rX3JlZmNudD0weCV4CgBtaWlfYW5yZXN0YXJ0WyV1XTogYWNh
-cHMgMHgleAoAAHBvcnRfY21kX2hhbmRsZXI6IHVua25vd24gdS5kY2IudHlwZSAweCV4CgAAAAAA
-AHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06IGwxY2ZnLCBpbnZhbGlkIHJlcXVlc3QsIHBjYXBzIDB4
-JXggYWNhcHMgMHgleCByY2FwcyAweCV4CgAAAAAAAAAAAAAAAAAAAHBvcnRbJXU6MHglMDJ4OjB4
-JTAyeF06IGwxY2ZnLCBwY2FwcyAlI3ggYWNhcHMgJSN4IHJjYXBzICUjeCBtY2FwcyAlI3gKAAAA
-AAAAAAAAcG9ydFsldToweCUwMng6MHglMDJ4XTogbDFjZmcsIG1kaSBpc3N1ZSBwY2FwcyAweCV4
-IGFjYXBzIDB4JXggcmNhcHMgMHgleAoAAAAAAABwb3J0WyV1OjB4JTAyeDoweCUwMnhdOiBsMWNm
-ZywgY2Fubm90IGZvcmNlIG5vL211bHRpcGxlIHNwZWVkKHMpLCBwY2FwcyAweCV4IGFjYXBzIDB4
-JXggcmNhcHMgMHgleAoAAAAAAAAAAAAAAAAAZXRoX2Zsb3djX2hhbmRsZXJbMHgleF06IGZsYWdz
-IDB4JTA4eCBudW1fYnl0ZXMgJXUgc2NoZWRjbCAweCV4IC0+IDB4JXgKAAAAAAAAAABzY3NpX2Nt
-ZDogcmVjZWl2ZWQgVE1GIG9wIFsweCV4XSBmdW5jIFsweCV4XSBvbiBjb25uIFsweCV4XSB0aHJv
-dWdoIGNvbW1hbmQgcGF0aC4KAAAAAAAAAAAAAAAAAABzY3NpX2NtZDogY29ubl9mYyBbMHgleF0s
-IHN0YXRlIFsweCV4XSwgc2Vzc19mYyBbMHgleF0gaW4gcmVjb3ZlcnkuIFNraXBwaW5nIGlzdGFz
-a19mYyBbMHgleF0gZnJvbSBUWC4KAAAAAAAAAAAAc2NzaV9jbWQ6IGlTQ1NJIGNvbW1hbmQgc2Vx
-dWVuY2Ugd2luZG93IGNsb3NlZC4gY29ubiBbMHgleF0sIG9wIFsweCV4XSwgIGNtZHNuIFsweCV4
-XSwgc2VudF9jbWRzbiBbMHgleF0sIG1heF9jbWRzbiBbMHgleF0sIGl0dCBbMHgleF0KAAAAAAAA
-AAAAc2NzaV9yZWFkOiBjb25uX2ZjIFsweCV4XSwgc3RhdGUgWzB4JXhdLCBzZXNzX2ZjIFsweCV4
-XSBpbiByZWNvdmVyeS4gU2tpcHBpbmcgaXN0YXNrX2ZjIFsweCV4XSBmcm9tIFRYLgoAAAAAAAAA
-AHNjc2lfcmVhZDogaVNDU0kgY29tbWFuZCBzZXF1ZW5jZSB3aW5kb3cgY2xvc2VkLiBjb25uIFsw
-eCV4XSwgY21kc24gWzB4JXhdLCBzZW50X2NtZHNuIFsweCV4XSwgbWF4X2NtZHNuIFsweCV4XQoA
-AAAAAAAAAAAAAAAAAAAAc2NzaV93cml0ZTogY29ubl9mYyBbMHgleF0sIHN0YXRlIFsweCV4XSwg
-c2Vzc19mYyBbMHgleF0gaW4gcmVjb3ZlcnkuIFNraXBwaW5nIGlzdGFza19mYyBbMHgleF0gZnJv
-bSBUWC4KAAAAAAAAAHNjc2lfd3JpdGU6IGlTQ1NJIGNvbW1hbmQgc2VxdWVuY2Ugd2luZG93IGNs
-b3NlZC4gY29ubiBbMHgleF0sIGNtZHNuIFsweCV4XSwgc2VudF9jbWRzbiBbMHgleF0sIG1heF9j
-bWRzbiBbMHgleF0sIGl0dCBbMHgleF0KAAAAZGNieF9jb250cm9sX3NtWyV1XSBDT05UUk9MX0xJ
-TktVUAoAAAAAAAAAAAAAAAAAZGNieF9jb250cm9sX3NtWyV1XSBDT05UUk9MX1VQREFURV9EQ0JY
-X1RMVgoAAAAAZGNieF9jb250cm9sX3NtWyV1XSBDT05UUk9MX1BFRVJfTk9UX0FEVkVSVElTRV9E
-Q0JYCgAAAAAAAAAAAAAAAGRjYnhfY29udHJvbF9zbVsldV0gQ09OVFJPTF9VUERBVEVfT1BFUl9W
-RVJTSU9OCgAAAAAAAAAAAAAAAAAAAABkY2J4X2NvbnRyb2xfc21bJXVdIENPTlRST0xfUFJPQ0VT
-U19QRUVSX1RMVgoAAABkY2J4X2NvbnRyb2xfc21bJXVdIENPTlRST0xfQUNLX1BFRVIKAAAAAAAA
-AAAAAABkY2J4X2llZWVfdmFsaWRhdGVbJXVdIGVycm9yIChvdWkgJSN4IHN1YnR5cGUgJSN4IGxl
-biAlI3gpCgAAAAAAZGNieF9jZWVfdmFsaWRhdGVbJXVdIGVycm9yCgAAAABjaG5ldF9sMnRfdXBk
-YXRlOiBsMmRldl9mYyBbMHgleF0sIGwyZGV2X2ZjLT5mbG93Y19pZCBbJXVdIGwyZGV2X2ZjLT5m
-bG93Y19mbGFncyBbMHgleF0sIGludGYgWzB4JXhdCgAAAAAAAAAAAAAAY2huZXRfbDJ0X3VwZGF0
-ZTogbDJkZXZfZmMtPmZsb3djX2lkIFsldV0gYWxyZWFkeSBzY2hlZHVsZWQKAAAAAGNobmV0X2wy
-dF91cGRhdGU6IGluIGRlbGF5ZWRfcHJvY2Vzc2luZywgbDJ0ZW50IFslMDh4XQoAAAAAAAAAAABE
-SENQdjYgUkVQTFkgcmVjZWl2ZWQgc3RhdGUgJXUKAGRoY3AgcmVwbHkgcmVjZWl2ZWQgaW4gd3Jv
-bmcgc3RhdGUgJWQKAAAAAAAAAAAAAHVua25vd24gc2VydmVyaWQuIElnbm9yaW5nIGRoY3AgcmVw
-bHkKAAAAAAAAAAAAAHJlY2VpdmVkIHJlcGx5IHdpdGggZGlmZmVyZW50IGFkZHJlc3MuIGlnbm9y
-aW5nIGRoY3AgcmVwbHkKAAAAAABESENQdjYgQURWRVJUSVNFIHJlY2VpdmVkCgAAAAAAAGRoY3Ag
-YWR2ZXJ0aXNlIHJlY2VpdmVkIGluIHdyb25nIHN0YXRlICVkCgAAAAAAAGlnbm9yaW5nIHJjdmQg
-YWR2ZXJ0aXNlIHByZWZlcmVuY2UgJXUKAAAAAAAAAAAAAHByZWZpeCBub2RlIDB4JXgsIHZhbGlk
-X2xpZmV0aW1lICV1LCBjdXJyZW50X3RpbWUgJXUgZXhwaXJlZCwgZGVsZXRpbmcgaXQKAAAAAAAA
-RGVsZXRlZCBwcmVmaXg6IDB4WyUwNHggJTA0eCAlMDR4ICUwNHhdCgAAAAAAAAAAU3RhcnQgREhD
-UHY2IHRvIGdldCB0aGUgaXAgYWRkcmVzcwoAAAAAAAAAAAAAAAAATm8gZGhjcCwgZGhjcCBzdGF0
-ZSAlZCwgYWRkciBzdGF0ZSAlZAoAAAAAAAAAAAAAcGluZyByZXEgcGF5bG9hZCB0b28gbGFyZ2Ug
-JXUuIElnbm9yaW5nIHJlcS4KAAAAUlIgcmN2ZAoAAAAAAAAAAGNobmV0X2lwdjZfcmRfaW5wdXQ6
-IEludmFsaWQgUmVkaXJlY3QKAAAAAAAAAAAAAGNobmV0X2lwdjZfbmFfaW5wdXQ6IEludmFsaWQg
-TkEKAAAAAAAAAAAAAAAAAAAAAGlwdjYgTkEgcmN2ZAoAAABjaG5ldF9pcHY2X25hX2lucHV0OiBE
-dXBsaWNhdGUgYWRkcmVzcyBkZXRlY3RlZCEKAAAAAAAAAAAAAAAAAAAATkEgaW4gcmVwb25zZSBv
-ZiBOUwoAAAAAAAAAAAAAAABjaG5ldF9pcHY2X25zX2lucHV0OiBJbnZhbGlkIE5TCgAAAAAAAAAA
-AAAAAAAAAABjaG5ldF9pcHY2X25zX2lucHV0OiBJbnZhbGlkIE5TIGlwdjZoLT5wbGVuICV1CgBp
-cHY2IE5TIHJjdmQKAAAAY2huZXRfaXB2Nl9uc19pbnB1dDogRHVwbGljYXRlIGFkZHJlc3MgZGV0
-ZWN0ZWQKAAAAAAAAAAAAAAAAAAAAAGNobmV0X2lwdjZfbnNfaW5wdXQ6IHNvbWVib2R5IHRyeWlu
-ZyB0byB1c2Ugb3VyIGFkZHJlc3MKAAAAAAAAAABjaG5ldF9pcHY2X25zX2lucHV0OiByZXEgZm9y
-IGFkZHIgcmVzb2x1dGlvbgoAAABIb3AgYnkgSG9wIG9wdGlvbgoAAAAAAAAAAAAAAAAAAHByb2Nl
-c3NfZGhjcF9vcHRzOiByb290IHBhdGggbGVuIFslZF0gYnl0ZXMKAAAAAG5ldGlmX3Byb2Nlc3Nf
-ZGhjcF9vcHRzOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBNU0dfVFlQRSBbJWRdLCBkaGN0
-eHQtPnN0YXRlIFslZF0KAAAAAAAAAAAAAGljbXBfcmVjdjogbDJkZXZfZmMtPmZsb3djX2lkIFsw
-eCV4XSwgcGlkIFsweCV4XSwgaWNtcCB0eXBlIFsweCV4XQoAAAAAAAAAAAAAAAAAQUJUUyBBQ0Mg
-YXdhaXRpbmcgUFJMSSBSc3A6IGZsb3djX2lkIDB4JXggb3hfaWQgMHgleCByeF9pZCAweCV4IGlx
-aWQgMHgleAoAAAAAAABwb3J0IDB4JXgsIHN0YXRlIDB4JXgsIGNvbW1hbmQgZmFpbGVkIHJldHJp
-ZXMgMHgleAoAAAAAAAAAAAAAAAAAYXJwX3JlY3Y6IGlwaWQgWzB4JXhdLCBpbl9hZGRyLmFkZHIg
-WzB4JXhdLCBzaXAgWzB4JXhdLCByaXAgWzB4JXhdLCBhcnBfb3AgWzB4JXhdCgAAAAAAAAAAAAAA
-AAAAY2huZXRfYXJwX3JlY3Y6IGlwIGNvbmZsaWN0IGRldGVjdGVkCgAAAAAAAAAAAAAAY2huZXRf
-YXJwX3JlY3Y6IHBpZCBbJXVdLCB2bGFuIFsweCV4XSwgYXJwIG9wIFsweCV4XSwgc2lwIFsweCV4
-XSwgcmlwIFsweCV4XQoAAABjaG5ldF9pcHY2X3JlY3Y6IHZsYW4gZXh0cmFjdGVkLCB2bGFuaWQg
-WyV1XSwgbDJkZXZfZmMtPmZsb3djX25ldF9sMmRldl92bGFuZGV2IFsweCV4XQoAAAAAAAAAAABJ
-bnZhbGlkIGRhdGEgbGVuZ3RoIGRsZW4gJXUsIHBhY2tldCBpbmRpY2F0ZXMgJXUgYnl0ZXMKAAAA
-AAAAAAAAVW5rbm93biBJUHY2IG54dCBwcm90b2NvbCAldQoAAABJbnZhbGlkIGRpZDp4JTJ4JTJ4
-JTJ4IHJjdmQgb24gcG9ydDolZC5Ecm9waW5nIGZyYW1lCgAAAAAAAAAAAAAAcmN0OngleCBzaWQ6
-eCUyeCUyeCUyeCByY3ZkIG9uIGZsb3djOiVkLkRyb3BpbmcgZnJhbWUKAAAAAAAAAAAAAGNzb2Nr
-X2ZyZWU6IHNpemVvZihjc2tfZmMtPnUuY3NvY2spIFsldV0sIGJ5dGVzCgAAAAAAAAAAAAAAAAAA
-AABHb3QgQ09OTl9FWElTVCBmb3IgeGlkOjB4JXgsIHRhZzoweCV4LCByZXRyeWluZy4KAAAAAAAA
-AAAAAAAAAAAAY3NvY2tfcGVlcl9jbG9zZTogY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIHRjYl9m
-Yy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwgdGNiX2ZjLT5m
-bG93Y19zdGF0ZSBbMHgleF0KAAAAAABjc29ja19wZWVyX2Nsb3NlOiBjc2tfZmMtPmZsb3djX2lk
-IFsweCV4XSwgY3NrX2ZjLT5mbG93Y19zdGF0ZSAgWzB4JXhdCgAAAAAAAAAAAHRjcF9jbHNfYWJy
-dF9ycGw6IHRjYiB0aWQgWzB4JTA2eF0sIGZsb3djX3R5cGUgWzB4JXhdLCBjcGxvcCBbMHgleF0g
-CgAAAAAAAAAAAAAAY2hfcmF0ZVsldV06IGNhcHBlZCB0aWNrIGZyb20gcmVxdWlyZWQgJXUgdG8g
-c3VwcG9ydGVkICV1OyByYXRlICV1IChlZmYgJXUpIGRlZmljaXRfaW5jciAldSB0aWNrICV1CgAA
-AAAAAAAAAAAAAHBrdHNjaGVkX2NoX3JsWyV1XTogY2hhbm5lbCBybCBub3QgYXZhaWxhYmxlIGlu
-IGNvbmp1bmN0aW9uIHdpdGggZmxvdyBzaGFwaW5nCgAAcGt0c2NoZWRfY2hfcmxbJXVdOiByYXRl
-ICV1IG1heCAldQoAAAAAAAAAAAAAAAAAcGt0c2NoZWRfY2xfd3JyWyV1OiV1XTogd2VpZ2h0ICV1
-CgAAAAAAAAAAAAAAAAAAZXFfcGFyYW1zWzB4JXg6MHgleF06IGRtYXEgMHgleCByZWFkICV1IHBm
-ICV1IGVxaWRfYXBpICV1IHJldCAlZAoAAAAAAAAAAAAAAAAAAABNQyBDTEsgc2V0dGluZyBmYWls
-ZWQ6IFBMTF9NX0xPQ0sgbmV2ZXIgdG9nZ2xlZAoAAAAAAAAAAAAAAAAAAAAAd2FpdF9mb3JfY2Fs
-aWJfZG9uZTogcmV0ICVkIGluICV1IGF0dGVtcHRzCgAAAAAAaHdfbWFfYWRkcl90b19tZW1fdHlw
-ZV9vZmY6IE1BIGFkZHJlc3MgMHglMDh4IGlzIG5vdCBtYXBwZWQKAAAAAGh3X21hX2FkZHJfdG9f
-bWVtX3R5cGVfb2ZmOiBNQSBhZGRyZXNzIDB4JTA4eCBtYXBzIHRvIHR5cGUgJXUgb2Zmc2V0IDB4
-JXgKAAAAAAAAbWVtX21hbGxvY190ZW1wOiBmYWlsZWQgdG8gYWxsb2NhdGUgJXUgYnl0ZXMsIHJl
-dHVybmluZyBOVUxMCgAAAG1lbV9tYWxsb2M6IGZhaWxlZCB0byBhbGxvY2F0ZSAldSBieXRlcywg
-cmV0dXJuaW5nIE5VTEwKAAAAAAAAAABsZSBjb25maWd1cmF0aW9uOiBoYXNoIG1vZGUgcmVxdWly
-ZXMgYXQgbGVhc3QgMTYgZW50cmllcywgbmhhc2ggJXUKAAAAAAAAAAAAAAAAAGxlIGNvbmZpZ3Vy
-YXRpb246IGhhc2ggbW9kZSByZXF1aXJlcyBhdCBlbnRyaWVzIHRvIGJlIGEgcG93ZXIgb2YgMiwg
-bmhhc2ggJXUKAAAAbGUgY29uZmlndXJhdGlvbjogcmVxdWVzdGVkICV1IHRjYW0gZW50cmllcyBi
-dXQgb25seSAldSBhdmFpbGFibGUgKG5yb3V0ZSAldSBuY2xpcCAldSBuZmlsdGVyICV1IG5zZXJ2
-ZXIgJXUKAAAAAGxlIGNvbmZpZ3VyYXRpb246IHRjYW0gcmVnaW9ucyBtdXN0IGhhdmUgbXVsdGlw
-bGUgb2YgMzIgZW50cmllcywgbnJvdXRlICV1IG5jbGlwICV1IG5maWx0ZXIgJXUgbnNlcnZlciAl
-dQoAAAAAAABod190cF90Y3BfdHVuaW5nczogdHVuaW5nIGZvciBjbHVzdGVyIGVudmlyb25tZW50
-CgAAAAAAAAAAAAAAAAAAaHdfdHBfdGNwX3R1bmluZ3M6IHR1bmluZyBmb3IgTEFOIGVudmlyb25t
-ZW50CgAAaHdfdHBfdGNwX3R1bmluZ3M6IHR1bmluZyBmb3IgV0FOIGVudmlyb25tZW50CgAAaHdf
-dHBfdGNwX3R1bmluZ3M6IG1hbnVhbCB0dW5pbmcKAAAAAAAAAAAAAAAAAAAAX2h3X2NpbV9mbGFz
-aF9tZW1jcHk6IG1lbWNweVggc3RhcnQKAAAAAAAAAAAAAAAAX2h3X2NpbV9mbGFzaF9tZW1jcHk6
-IGRzdCAweCUwOCBvZmZzZXQgMHglMDh4IHNpemUgJXUsIHdpZHRoIG9mICV1IGlzIG5vdCBzdXBw
-b3J0ZWQKAAAAAAAAAAAAAAAAX2h3X2NpbV9mbGFzaF9tZW1jcHk6IG1lbWNweVggZW5kCgAAAAAA
-AAAAAAAAAAAAY29uZmlndXJhdGlvbiBmaWxlIHBhcnNlciBlbmNvdW50ZXJlZCBlcnJvciBAIGxp
-bmUgJXU6CgAAAAAAAAAAAEhPU1QgUEFHRV9TSVpFIFsweCUwbHhdIHRvbyBzbWFsbCwgbWluIFsw
-eCUwbHhdIHJlcXVpcmVkCgAAAAAAAABwYWdlIHNpemUgWyVsdV0gbWlzbWF0Y2gKAAAAAAAAAFBB
-R0Ugc2l6ZSAlbHUgdW5zdXBwb3J0ZWQsIGRkcCBkaXNhYmxlZAoAAAAAAAAAAEhvc3QgcGFnZV9z
-aXplICVsdSwgZGRwX2lkeCAldQoARkNvRSBERFAgaW5pdDogZmNvZSBsbGltaXQgMHgleCwgZmNv
-ZSB1bGltaXQgMHgleCBnYmwgbGxpbWl0IDB4JXggZ2JsIHVsaW1pdCAweCV4IHBjYnN6ICV4CgAA
-AAAARkNvRSBERFAgaW5pdDogZmNvZSBwcG9kIG9mZiAweCV4LCBmY29lIHN0IHBwb2QgYWRkciAw
-eCV4IGZjb2UgbnVtIHBwb2RzIDB4JXgKAABmY29lIHhjaGcgbWdyIGluaXQ6IE51bWJlciBvZiBE
-RFAgZXhjaGFuZ2VzIGZvciBGQ29FIGlzICV4CgAAAAAAZmNvZSB4Y2hnIG1nciBpbml0OiBOdW1i
-ZXIgb2YgdHVubmVsIGV4Y2hzIGZvciBGQ29FIGlzICV4CgAAAAAAAGZjb2VfbDJ0X2luaXQ6IE5v
-IHVscHR4IGNyZWRpdCBjaDpbJXVdCgAAAAAAAAAAAGZjb2VfbDJ0X2luaXQ6IGNoOlsldV0gbDJ0
-X2lkeCBbJXVdCgAAAAAAAAAAAAAAAG5vIGwydCBlbnRyaWVzIGNvbmZpZ3VyZWQ7IGZvcmNpbmcg
-JXUgZW50cmllcywgc3RhcnRpbmcgYXQgJXUKAABkY2J4IHVwZGF0ZVsldV0gc2VudCB0byBkcml2
-ZXIgKHR5cGUgJSN4IHN1YnR5cGUgJSN4IGZsb3djaWQgJXUpCgAAAAAAAAAAAAAAAAAAAGRjYnhf
-cnVuX3ZlcnNpb25fc21bJXVdIERDQlhfVkVSX1NUQVRFX1JVTl9JRUVFCgAAAAAAAAAAAAAAAAAA
-AABkY2J4X3J1bl92ZXJzaW9uX3NtWyV1XSBEQ0JYX1ZFUl9TVEFURV9SVU5fQ0VFCgBkY2J4X3J1
-bl92ZXJzaW9uX3NtWyV1XSBEQ0JYX1ZFUl9TVEFURV9SVU5fTk9ORQoAAAAAAAAAAAAAAAAAAAAA
-TUFDIGZhaWxlZCB0byByZXN5bmMgdHgKAAAAAAAAAABwb3J0WyV1XSBsaW5rIHVwICgldSkgKHNw
-ZWVkICUjeCBhY2FwcyAlI3ggbHBjYXBzICUjeCkKAAAAAAAAAAAAcG9ydF9oc3Nfc2lnZGV0WyV1
-XTogaHNzX3NpZ2RldCBjaGFuZ2VkIHRvIDB4JXgKAAAAAAAAAAAAAAAAAAAAAHBvcnRbJXVdIGlu
-aXRpYWxpemluZyBLUgoAAAAAAAAAZGlzYWJsaW5nIHR4ICUjeCByeCAlI3gKAAAAAAAAAABDYWxj
-dWxhdGlvbiBvdXQgb2YgYm91bmRzIGZ1cmluZyBpbml0OiAlI3ggJSN4ICUjeAoAAAAAAAAAAAAA
-AAAAX2h3X3RwX3BnbW5ndDogdHhfcGFnZV9tYXggJXUgcnhfcGFnZV9tYXggJXUgcHN0cnVjdHMg
-JXUgc2l6ZSAldQoAAAAAAAAAAAAAAAAAAABtcGFydGl0aW9uX290aGVyc190b3RhbDogZGRwICV1
-IGRkcF9pc2NzaSAldSBzdGFnICV1IHBibCAldSBycSAldSBycXVkcCAldSAtPiAldQoAAAAAAAAA
-AAAAAAAAAABfbXBhcnRpdGlvbl9iYW5rc19tY1g6IG5iYW5rc19wbXR4ICV1ICgldU1CKSBuYmFu
-a3NfcG1yeCAldSAoJXVNQikgbmJhbmtzX290aGVycyAldSAoJXVNQikgbmJhbmtzX2Z3ICV1ICgl
-dU1CKQoAX21wYXJ0aXRpb25fYmFua3NfbWMxOiBuYmFua3NfcG10eCAldSAoJXVNQikgbmJhbmtz
-X290aGVycyAldSAoJXVNQikgbmJhbmtzX2Z3ICV1ICgldU1CKQoAAAAAAAAAX21wYXJ0aXRpb25f
-YmFua3NfbWMwOiBuYmFua3NfcG1yeCAldSAoJXVNQikgbmJhbmtzX290aGVycyAldSAoJXVNQikK
-AAAAAAAAAAAAAABtZW1fbWFsbG9jX2ludGVybmFsOiBmYWlsZWQgdG8gYWxsb2NhdGUgJXUgYnl0
-ZXMsIHJldHVybmluZyBOVUxMCgAAAAAAAAAAAAAAAAAAAGh3X2VkY19iaXN0WyV1XTogYmlzdF9j
-bWRbMHglMDh4XSBhZGRyIDB4JXggbGVuIDB4JXgKAAAAAAAAAAAAAABod19lZGNfYmlzdFsldV06
-IGRvbmUsIGVuY291bnRlcmVkICV1IGVycm9ycyBvbiBmaXJzdCBhbmQgJXUgZXJyb3JzIG9uIHNl
-Y29uZCBhdHRlbXB0ICgldWdicHMpCgBtZW1faW5pdF9jYWNoZXM6IGNhY2hlX3NpemUgJXUgZmxv
-d2NfYnVmX3RjYl9jYWNoZV9zaXplICV1IGJ1ZmxsNjRfY2FjaGVfc2l6ZSAldQoAAAAAAAAAAAAA
-AAAAAABtcGFydGl0aW9uX3BtdHg6IG0gMHglMDh4IHNpemUgJXUKAAAAAAAAAAAAAAAAAABtcGFy
-dGl0aW9uX3Btcng6IG0gMHglMDh4IHNpemUgJXUKAAAAAAAAAAAAAAAAAABtcGFydGl0aW9uX2Vk
-YyAobm8gZXh0bWVtKTogbSAweCUwOHggc2l6ZSAldQoAAABtcGFydGl0aW9uX2VkY19lc3RpbWF0
-ZTogaHcgbW9kdWxlcyByZXF1aXJlICVkIGJ5dGVzIGluIEVEQwoAAAAAVGVtcGVyYXR1cmUvVm9s
-dGFnZSBTZW5zb3I6IENvcmUgY2xvY2sgJWQgPiA1MDA7IHVzaW5nIDUwMCB0byBzdGF5IGluIGNv
-bXBsaWFuY2Ugd2l0aCBoYXJkd2FyZS4KAAAAAAAAAAAAAAAAAAAAAGNobmV0X2J5ZTpsMmRldl9m
-Yy0+Zmxvd2NfaWQgWzB4JXhdLCBsMmRldl9mYy0+Zmxvd2NfcGNpZV9wZm4gWzB4JXhdLCBsMmRl
-dl9mYy0+Zmxvd2NfcGNpZV92Zm4gWzB4JXhdLCBwb3J0IFsweCV4XQoAAAAAAAAAAAAAAAAAY2hu
-ZXRfYnllOnZsYW5kZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgdmxhbmRldl9mYy0+Zmxvd2NfcGNp
-ZV9wZm4gWzB4JXhdLCB2bGFuZGV2X2ZjLT5mbG93Y19wY2llX3ZmbiBbMHgleF0sIHBvcnQgWzB4
-JXhdCgAAAAAAAABod19tYWNfYWVjX2NvbXBsZXRlWyV1XSBvbiBsYW5lcyAlI3ggKHNpZ2RldCAl
-I3gpCgAAAAAAAAAAAAAAAAAAYWVjX2ZzbVsldV0gOiBzdGF0ZSBTVEFSVCAoc2lnZGV0ICUjeCkK
-AAAAAAAAAAAAYWVjX2ZzbVsldV0gOiB0cmFuc2l0aW9uaW5nIHRvIFRSQUlOSU5HCgAAAAAAAAAA
-YWVjX2ZzbVsldV0gOiBUUkFJTklOR19DT01QTEVURQoAAAAAAAAAAAAAAAAAAAAAYWVjX2ZzbVsl
-dV0gOiBET05FCgAAAAAAAAAAAAAAAABhZWNfZnNtWyV1XSA6IHRpbWVkIG91dCB0cmFpbmluZwoA
-AAAAAAAAAAAAAAAAAABiZWFuX2ZzbVsldV0gOiBzdGF0ZSBTVEFSVCAoY291bnQgPSAldSkKAAAA
-AAAAAABiZWFuX2ZzbVsldV0gOiBlbnRlcmluZyBzdGF0ZSBXQUlUX1NJR0RFVAoAAAAAAABiZWFu
-X2ZzbVsldV0gOiBlbnRlcmluZyBzdGF0ZSBOWFBfSEFORExFCgAAAAAAAABiZWFuX2ZzbVsldV0g
-OiBlbnRlcmluZyBzdGF0ZSBXQUlUX0NPTVBMRVRFCgAAAABiZWFuX2ZzbVsldV0gOiBzdGF0ZSBE
-T05FCgAAAAAAAGJlYW5fZnNtWyV1XSA6IHN0YXRlIFJFU1RBUlQKAAAAYmVhbl9mc21bJXVdIFRJ
-TUVPVVQ7IHN0YXRlICV1IGV0aF9zdGF0dXMgJSN4IGJlYW5fc3RhdHVzICUjeCBoc3Mgc2lnZGV0
-ICUjeCByZXRyeV9jbnQgJXUKAAAAAAAAcG9ydCAldSBuZWdvdGlhdGVkIHVuc3VwcG9ydGVkIHNw
-ZWVkICUjeAoAAAAAAAAAYmVhbi9hZWMgY29tcGxldGUgKHJldHJ5OiAldSkKAABwb3J0WyV1XSBy
-ZXNldHRpbmcgS1IKAAAAAAAAAAAAAFJhbmdlIGNhbGM6IEF2ZXJhZ2VkICUjeCBidXQgaWdub3Jl
-ZCB2YWx1ZSAlI3ggKGl0ZXJhdGlvbiAldSkKAABNQyBjYWxpYnJhdGlvbiBmYWlsZWQ6IERGSSBp
-bml0IG5vdCBnb2luZyB0byAwCgBNQyBjYWxpYnJhdGlvbiBmYWlsZWQ6IERGSSBpbml0IG5vdCBj
-b21wbGV0aW5nCgBNQyBjYWxpYnJhdGlvbiBmYWlsZWQ6IENhbGlicmF0aW9uIGRpZG4ndCBjb21w
-bGV0ZS4KAAAAAAAAAAAAAAAATUMgY29tbWFuZCBmYWlsZWQgdG8gY29tcGxldGUob3Bjb2RlICUj
-eCBjYWRkciAlI3ggYmFkZHIgJSN4IGRlbGF5ICVkKQoAAAAAAAAAAABwZm5fYml0bWFwIDB4JXgK
-AAAAAAAAAAAAAAAAAAAAAGJhZCBtYWlsYm94IGNtZDogcGZuIDB4JXggdmZuIDB4JXg7IG9wY29k
-ZSAweCV4ID4gTEFTVEMyRSAweCV4CgBtYWlsYm94IGNtZCBub3QgeWV0IHN1cHBvcnRlZDogcGZu
-IDB4JXggdmZuIDB4JXg7IG9wY29kZSAweCV4CgAAYmFkIG1haWxib3ggY21kOiBwZm4gMHgleCB2
-Zm4gMHgleDsgb3Bjb2RlIDB4JXggaXMgdmFsaWQgcG9zdCBkZXZpY2UgaW5pdCBvbmx5CgBiYWQg
-bWFpbGJveCBjbWQ6IHBmbiAweCV4IHZmbiAweCV4OyBvcGNvZGUgMHglMDJ4IHJhbWFzayAweCV4
-IGNtZCByYW1hc2sgMHgleAoAAGJhZCBtYWlsYm94IGNtZDogcGZuIDB4JXggdmZuIDB4JXg7IG9w
-Y29kZSAweCUwMnggbGVuMTYgMHgleCB2ZXJzdXMgZXhwZWN0ZWQgbGVuMTYgMHgleAoAAAAAAAAA
-AGluc3VmZmljaWVudCBjYXBzIHRvIHByb2Nlc3MgbWFpbGJveCBjbWQ6IHBmbiAweCV4IHZmbiAw
-eCV4OyByX2NhcHMgMHgleCB3eF9jYXBzIDB4JXggcmVxdWlyZWQgcl9jYXBzIDB4JXggd19jYXBz
-IDB4JXgKAAAAAAAAAAAAaW5zdWZmaWNpZW50IGNhcHMgdG8gcHJvY2VzcyBtYWlsYm94IGNtZDog
-cGZuIDB4JXggdmZuIDB4JXg7IHJfY2FwcyAweCV4IHd4X2NhcHMgMHgleCByZXF1aXJlZCByX2Nh
-cHMgMHgleCB3X2NhcHMgMHgleAoAAAAAAAAAAABod19wb3dlcl9wcmVwOiBWREQ9Tk9ORSBidXQg
-VkNTPSVkCgAAAAAAAAAAAAAAAABod19wb3dlcl9wcmVwOiB1bnN1cHBvcnRlZCBleHRlcm5hbCBh
-ZGp1c3RhYmxlIHBvd2VyIHJlZ3VsYXRvcnMgVkREPSVkLCBWQ1M9JWQKAGh3X3Bvd2VyX3ByZXA6
-IHVuc3VwcG9ydGVkIFZERD0lZAoAAAAAAAAAAAAAAAAAAGh3X3Bvd2VyX3ByZXA6IHVuc3VwcG9y
-dGVkIFZDUz0lZAoAAAAAAAAAAAAAAAAAAGh3X3Bvd2VyX3ByZXA6IGkyYyB3cml0ZSBlcnJvciwg
-VkREPSVkLHJldD0lZAoAAGh3X3Bvd2VyX3ByZXA6IHVuc3VwcG9ydGVkIFZERD0lZAoAAAAAAAAA
-AAAAAAAAAGh3X3Bvd2VyX3ByZXA6IGkyYyB3cml0ZSBlcnJvciwgVkNTPSVkLHJldD0lZAoAAGh3
-X3Bvd2VyX3ByZXA6IHVuc3VwcG9ydGVkIFZDUz0lZAoAAAAAAAAAAAAAAAAAAFZQRCByZWdpb24g
-aXMgdG9vIHNtYWxsIChTRVJDRkdfU1JfUEZOVlBEU0laRSAweCV4KQoAAAAAAAAAAAAAAABjZjog
-ZmFpbGVkIHRvIGFsbG9jYXRlZCBtZW1vcnkgZm9yIGNvbmZpZ3VyYXRpb24gZmlsZSwgcmV0ICVk
-CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+JXggCgAAAAAAAAAAAAAAAHNjc2lfYWJvcnQ6IEVudGVyaW5nIEFib3J0X3Rhc2ssIGJ1ZmZlcmVk
+IFsldV0KAHNjc2lfYWJvcnQ6IHJjIFsweCV4XSByZWYgdGFzayBub3Qgb3V0c3RhbmRpbmcKAHNj
+c2lfYWJvcnQ6IGlkYXRhLT5vcCBbMHgleF0sIGZsYWdzIFsweCV4XSwgZnVuYyBbMHgleF0sIGx1
+bl9pZHggWzB4JXhdCgAAAAAAAAAAc2NzaV9hYm9ydDogd3ItPmlxaWQgWzB4JXhdLCBpc3Rhc2tf
+ZmMtPmZsb3djX3NnZV9pcWlkIFsweCV4XSwgaXN0YXNrX2ZjIHRhc2sgZmxhZ3MgWzB4JXhdCgAA
+AAAAc2NzaV9hYm9ydDogY29ubiBbMHgleF0sIGNtZHNuIFsweCV4XSwgc2VudF9jbWRzbiBbMHgl
+eF0sIG1heF9jbWRzbiBbMHgleF0sIGl0dCBbMHgleF0KAAAAAAAAAAAAYWJvcnQvY2xvc2UgV1Ig
+d2l0aCBjb29raWUgMHglbHggd2FzIGlzc3VlZCBvbiBzc24gMHgleCBpbiB3cm9uZyBzdGF0ZSAw
+eCV4CgAAAABhYm9ydCBXUiBvbiBzc24gMHgleCBkaWQgbm90IGZpbmQgV1Igd2l0aCBjb29raWUg
+MHgleCV4CgAAAAAAAAAAY2xvc2UgV1Igd2l0aCBjb29raWUgMHglbHggb24gc3NuIDB4JXg7ZGlk
+IG5vdCBmaW5kIFdSIHdpdGggY29va2llIDB4JWx4CgAAAAAAAABhYm9ydCBXUiBvbiBzc24gMHgl
+eCB3YXMgaXNzdWVkIG9uIHhjaGcgMHgleCB3aXRoIHJ4X2lkIDB4JXggaW4gd3Jvbmcgc3RhdGUg
+MHgleAoAAAAAAAAAAAAAAAAAAABzY3NpX2x1cjogRW50ZXJpbmcgTFVSIGhhbmRsZXIsIGJ1ZmZl
+cmVkIFsldV0KAABzY3NpX2x1cjogaWRhdGEtPm9wIFsweCV4XSwgZmxhZ3MgWzB4JXhdLCBmdW5j
+IFsweCV4XSwgbHVuX2lkeCBbMHgleF0KAAAAAAAAAAAAAHNjc2lfbHVyOiB3ci0+aXFpZCBbMHgl
+eF0sIGlzdGFza19mYy0+Zmxvd2Nfc2dlX2lxaWQgWzB4JXhdLCBpc3Rhc2tfZmMgdGFzayBmbGFn
+cyBbMHgleF0KAAAAAAAAAHNjc2lfbHVyOiBjb25uIFsweCV4XSwgY21kc24gWzB4JXhdLCBzZW50
+X2NtZHNuIFsweCV4XSwgbWF4X2NtZHNuIFsweCV4XSwgaXR0IFsweCV4XQoAAAAAAAAAAAAAAGRj
+YnhfY2VlX2ZlYV9zbVsldV0gRmVhdHVyZVsldV0gRkVBVFVSRV9MSU5LVVAKAGRjYnhfY2VlX2Zl
+YV9zbVsldV0gRmVhdHVyZVsldV0gU0VUX0xPQ0FMX1BBUkFNRVRFUlMKAAAAAAAAAAAAAABkY2J4
+X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVdIEZFQVRVUkVfTk9fQURWRVJUSVNFCgAAAAAAAAAA
+AAAAZGNieF9jZWVfZmVhX3NtWyV1XSBGZWF0dXJlWyV1XSBGRUFUVVJFX1BFRVJfTk9UX0FEVkVS
+VElTRV9EQ0JYCgAAAAAAAAAAAAAAAAAAAABkY2J4X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVd
+IEZFQVRVUkVfUEVFUl9OT1RfQURWRVJUSVNFX0ZFQVRVUkUKAAAAAAAAAAAAAAAAAGRjYnhfY2Vl
+X2ZlYV9zbVsldV0gRmVhdHVyZVsldV0gRkVBVFVSRV9VUERBVEVfT1BFUl9WRVJTSU9OCgAAAABk
+Y2J4X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVdIEZFQVRVUkVfUEVFUl9VUERBVEVfT1BFUl9W
+RVJTSU9OCgAAAAAAAAAAAAAAAAAAAGRjYnhfY2VlX2ZlYV9zbVsldV0gRmVhdHVyZVsldV0gRkVB
+VFVSRV9HRVRfUEVFUl9DRkcKAAAAAAAAAAAAAABkY2J4X2NlZV9mZWFfc21bJXVdIEZlYXR1cmVb
+JXVdIEZFQVRVUkVfQ0ZHX05PVF9DT01QQVRJQkxFCgAAAAAAZGNieF9jZWVfZmVhX3NtWyV1XSBG
+ZWF0dXJlWyV1XSBGRUFUVVJFX1VTRV9MT0NBTF9DRkcKAAAAAAAAAAAAAGRjYnhfY2VlX2ZlYV9z
+bVsldV0gRmVhdHVyZVsldV0gRkVBVFVSRV9VU0VfUEVFUl9DRkcKAAAAAAAAAAAAAABkY2J4X2Nl
+ZV9mZWFfc21bJXVdIEZlYXR1cmVbJXVdIEZFQVRVUkVfRkVBVFVSRV9ESVNBQkxFRAoAAAAAAAAA
+ZGNieF9jZWVfZmVhX3NtWyV1XSBGZWF0dXJlWyV1XSBGRUFUVVJFX0VSUk9SX0NIQU5HRQoAAAAA
+AAAAAAAAAEZlYXR1cmUgJXUgc3luYydkPSV1IChlcnJvciAldSkKAAAAAAAAAAAAAAAAAAAAAGlw
+djZfYWRkX3ByZWZpeF9pbl9saXN0OiBub2RlIGZvdW5kIDB4JXgKAAAAAAAAAGlwdjZfYWRkX3By
+ZWZpeF9pbl9saXN0LCBub2RlIG5vdCBmb3VuZAoAAAAAAAAAAGNobmV0X2FycF91cGRhdGVfY2Fj
+aGU6IGFycCBpcDQgZW50cnkgZm91bmQgCgAAAGNobmV0X2FycF91cGRhdGVfY2FjaGU6IGFycCBp
+cDYgZW50cnkgZm91bmQgCgAAAGNobmV0X2FycF91cGRhdGVfY2FjaGU6IGJvdGggaXA0IGFuZCBp
+cDYgYWRkciBjYW5ub3QgYmUgbnVsbAoAAABjaG5ldF9sMnRfdXBkYXRlOiBsMnRfdXBkYXRlIHJl
+cXVlc3Qgc2VudCBsMnRlbnQgWyUwOHhdLCBsMnRlbnQtPmlkeCBbJWRdLCBsMnRlbnQtPnZsYW4g
+WyVkXQoAAABjaG5ldF9pcHY2X3JhX2lucHV0OiBJbnZhbGlkIFJBCgAAAAAAAAAAAAAAAAAAAABp
+cHY2IFJBIHJjdmQKAAAAcm91dGVyIG5vdCBwcmVzZW50IGluIG91ciBsaXN0LiBhZGRpbmcgaXQK
+AAAAAAAASW52YWxpZCBvcHRpb24gbGVuZ3RoICV1IGluIFNMTEEgb3B0aW9uCgAAAAAAAAAAR09U
+IFNMTEEgb3B0aW9uIGluIFJBLCBsZW4gJXUKAABJbnZhbGlkIG9wdGlvbiBsZW5ndGggJXUgaW4g
+cHJlZml4IG9wdGlvbgoAAAAAAABJbnZhbGlkIG9wdGlvbiBsZW5ndGggJXUgaW4gbXR1IG9wdGlv
+bgoAAAAAAAAAAABJbnZhbGlkIHBhY2tldCB3aXRoICV1IGV4dHJhIGJ5dGVzCgAAAAAAAAAAAAAA
+AABtbGQ2IHF1ZXJ5IHJjdmQKAAAAAAAAAAAAAAAAAAAAAGNobmV0X2lwdjZfbWxkNl9xdWVyeV9p
+bnB1dDogSW52YWxpZCBNTEQgcXVlcnkKAFVuc3VwcG9ydGVkIHF1ZXJ5IHZlcnNpb24uIG9ubHkg
+bWxkdjIgcXVlcnkgc3VwcG9ydGVkCgAAAAAAAAAAAABxdWVyeSByZXNwb25zZSBkZWxheSAldSAo
+aW4gMTBtcyB1bml0KSAKAAAAAAAAAABhbHJlYWR5IGEgZ2VuZXJhbCBxdWVyeSBwZW5kaW5nIGlu
+ICV1ICgxMG1zKQoAAABEZWJ1ZyB0aGUgY29kZS4gZ3JwX25vZGUgbXVzdCBiZSBwcmVzZW50CgAA
+AAAAAABhbHJlYWR5IGEgbXVsdGljYXN0IHF1ZXJ5IHBlbmRpbmcgaW4gJXUgKDEwbXMpCgBpcHY2
+IGVjaG8gcmVxIHJjdmQKAAAAAAAAAAAAAAAAAERIQ1B2NiBwYWNrZXQgdHlwZSAldSwgb3B0c2xl
+biAldSByZWNlaXZlZAoAAAAAAEludmFsaWQgZGhjcCBzdGF0ZSAlZAoAAAAAAAAAAAAASWdub3Jl
+IERIQ1B2NiBtc2cgeGlkICV4LCAgZGg2Y3R4dC0+eGlkICV4CgAAAAAARXJyb3IgaW4gREhDUHY2
+IG9wdGlvbnMgcGFyc2luZy4gSWdub3JpbmcgbXNnLCBpICVkLCBvcHRzbGVuICVkCgAAAAAAAAAA
+AAAAAAAAAABESENQIGZhaWxlZCwgc3RhdHVzY29kZSAlZC4gSWdub3JpbmcgYWR2ZXJ0aXNlCgBp
+Y21wNiBjaGVja3N1bSB2YWxpZGF0aW9uIGZhaWxlZCwgb3IgZXJyIHJjdmRpZ25vcmluZyBpY21w
+NiBtc2cgJXUsIGRsZW4gJXUKAAAAAG5ldGlmX3Byb2Nlc3NfZGhjcDogbDJkZXZfZmMtPmZsb3dj
+X2lkIFsweCV4XSwgcHJvY2Vzc2luZywgb3B0X2xlbiAldQoAAAAAAAAAAAAAY2huZXRfZGhjcF9y
+ZWN2OiB2bGFuaWQgWyV1XSwgbDJkZXZfcGlkX2ZjLT5mbG93Y19uZXRfbDJkZXZfdmxhbmRldiBb
+MHgleF0sIGwyZGV2X2ZjIFsweCV4XQoAAAAAY2huZXRfZGhjcF9yZWN2OiBsMmRldl9mYy0+Zmxv
+d2NfaWQgWzB4JXhdLCBkaGN0eHQtPnN0YXRlIFslZF0sIG1hbGFjaW91cyBkaGNwIHJlY3YgZm9y
+IG5vIHJlcXVlc3QKAAAAAAAAAAAAAAAAAGRoY3R4dC0+c3RhdGUgOiAlZAoAAAAAAAAAAAAAAAAA
+bDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgQmFkIERIQ1AgY29va2llIHJlY2lldmVkLCBhYm9y
+dGluZwoAAENvdWxkIG5vIGFsbG9jYXRlIHBjYiEhIEZyZWVpbmcgZmNmICEhIQoAAAAAAAAAAHZu
+X3BhcnNlIHVua25vd24gc3ViY29kZSAldQoAAAAAdm5fcGFyc2UgdW5rbm93biBkdHlwZSAldQoA
+AAAAAABpZ25vcmluZyBmaXAgcmVjdiBmb3IgcGNiIGZsb3c6JXggaW4gb2ZmbGluZSBzdGF0ZQoA
+AAAAAAAAAAAAAAAAZmlwX3ZuMnZuX3JlY3ZfZXJyIAoAAAAAAAAAAAAAAABDb3VsZCBub3QgYWxs
+b2NhdGUgZmxvd2MhISEhCgAAAENvdWxkIG5vdCBhbGxvY2F0ZSBTQ0IgZmxvd2MhISEhCgAAAAAA
+AAAAAAAAAAAAAENvdWxkIG5vdCBmaW5kIHJpZ2h0IHNjYiBmb3IgbG9nbwoAAAAAAAAAAAAAAAAA
+AGlnbm9yaW5nIGZpcCByZWN2IGZvciBmY2YgZmxvdzoleCBpbiBvZmZsaW5lIHN0YXRlCgAAAAAA
+AAAAAAAAAABDb3VsZCBub3QgZmluZCByaWdodCBzY2IgZm9yIGZsb2dpCgAAAAAAAAAAAAAAAABw
+b3J0IDB4JXgsIHN0YXRlIDB4JXgsIHJldHJ5IG5vdCBzdXBwb3J0ZWQKAAAAAABGbG9naSByZXNw
+IHJjdiB3aXRoIHVua25vd24geGNoZyBveF9pZCV4IHNpZCAlMnglMnglMnggZGlkICUyeCUyeCUy
+eAoAAAAAAAAAAAAAAE5fUE9SVCAweCV4JXgleCByZWplY3RlZCBQTE9HSSB3aXRoIHJlYXNvbiBj
+b2RlICV4CgAAAAAAAAAAAAAAAABBQlRTIHdoaWxlIGF3YWl0aW5nIFBSTEkgUnNwOiBmbG93Y19p
+ZCAweCV4IG94X2lkIDB4JXggcnhfaWQgMHgleCAKAAAAAAAAAAAAAAAAAEFCVFMgZmFrZSBSc3A6
+IGxvYyAweCV4IG94X2lkIDB4JXggcnhfaWQgMHgleAoAAEZDIGZjYiBhbGxvYyBmYWlsZWQ6IGF2
+YWlsICVkCgAARkMgZmNiIGFsbG9jIHhpZDolZCBmbG93aWQgJWQKAABsbGRwX3J4X3BrdF9oYW5k
+bGVyWyV1XSBkcm9wIHByZS1pbml0IChjb3VudCA9ICV1KQoAAAAAAAAAAAAAAAAAJXgleCV4IFJl
+Y2lldmVkIExPR08gZnJvbSAleCV4JXggCgAAAAAAAAAAAAAAAAAARmFpbGVkIHRvIHBvc3QgeGNo
+ZyBlcnI6IHNzbmkgMHgleCBjb29raWUgMHglbHggcnZhbCAleCAKAAAAAAAAAHRjcF9yZWxlYXNl
+X3RpZDogdGlkIFsweCV4XSwgZmxvd2MgZmxhZ3MgWzB4JXhdLCBidWZmZXJlZCBbMHgleF0KAAAA
+AAAAAAAAAAAAAAAAdGNwX3JlbGVhc2VfdGlkOiBzaXplb2YodGNiX2ZjLT5mbG93Y19mb2lzY3Np
+X2Nvbm4pIFsldV0sIGJ5dGVzCgAAAAAAAAAAAAAAAAAAAABhY3Rfb3Blbl9ycGw6IGF0aWQgWzB4
+JXhdLCB0aWQgWzB4JXhdLCB0Y2JfZmMtPnsgaWQgWzB4JXhdLCBzdGF0ZSBbMHgleF0sIHR5cGUg
+WzB4JXhdIH0sIGNwbF9vcCBbMHgleF0sIHN0YXR1cyBbMHgleF0KAAAAAAAAAAAAAGFjdF9vcGVu
+X3JwbDogY3NrX2ZjLT57IGlkIFsweCV4XSwgc3RhdGUgWzB4JXhdLCBjc29ja19mbGFncyBbMHgl
+eF0gfSAKAAAAAAAAAAAAYWN0X29wZW5fcnBsOiByZWN2ZCBuZWcgYWR2aWNlIFsweCV4XQoAAAAA
+AAAAAAAAc2VuZF9hYm9ydF9ycGw6IGNza19mYy0+Zmxvd2NfdHlwZSBbMHgleF0sIGNza19mYy0+
+Zmxvd2NfaWQgWzB4JXhdLCB0aWQgWzB4JXhdLCB1bHB0eGNoIFsldV0sIGJ1ZmZlcmVkIFsldV0K
+AAAAAHdyaF9vZmxkX3RjcF9jbG9zZV9jb25fcmVwbHk6IHRjYl9mYy0+Zmxvd2NfaWQgWzB4JXhd
+LCB0Y2JfZmMtPmZsb3djX3R5cGUgWzB4JXhdLCBsZW4xNiBbJXVdLCBsb2MgWyV1XQoAAAAAAAAA
+AAB3cmhfb2ZsZF90Y3BfY2xvc2VfY29uX3JlcGx5OiBycGwtPm9wX1RpZCBbMHgleF0sIHJwbD5z
+dGF0dXMgWzB4JXhdLCBycGwtPnNuZF9ueHQgWzB4JXhdLCBycGwtPnJjdl9ueHQgWzB4JXhdCgAA
+dGNwX2Fib3J0X3JwbF9yc3M6IHRpZCBbMHgleF0sIHN0YXR1cyBbMHgleF0KAAAAdGNwX2Fib3J0
+X3JlcV9yc3M6IHRpZCBbMHgleF0sIHN0YXR1cyBbMHgleF0KAAAAb2ZsZF9hYm9ydF9yZXFfbmVn
+YWR2WyV1XTogd3IgMHglMDh4IGNwbF9hYm9ydF9yZXEgREVMSVZFUkVECgAAAGhvc3Rfd3JbJXVd
+OiB3ciAweCUwOHggY3BsX2Fib3J0X3JlcSBzdGF0dXMgMHgleAoAAAAAAAAAAAAAAAAAAABwa3Rz
+Y2hlZF9jbF9ybFsldToldV06IG1vZGUgfCB1bml0IHwgcmF0ZSAweCUwNnggbWluICV1IG1heCAl
+dSBwa3RzaXplICV1CgAAAAAAAHBhcmFtX2NobmV0WzB4JXg6MHgleF06IGNobmV0IDB4JXggcmVh
+ZCAldSBwZiAldSByZXQgJWQKAAAAAAAAAABwYXJhbV9kbWFxWzB4JXg6MHgleF06IGRtYXEgMHgl
+eCByZWFkICV1IHBmICV1IHJldCAlZAoAAAAAAAAAAAAATUNbJXVdIGluaXRfc3RhdGVfbWFjaGlu
+ZSAweCUwMngKAAAAAAAAAAAAAAAAAAAATUMgaW5pdGlhbGl6YXRpb24gbm90IGNvbXBsZXRpbmcs
+IE1DIGN1cnJlbnQgaW5pdCBzdGF0ZSBpcyAweCUwMngKAAAAAAAAAAAAAAAAAABNQ1sldV0gX2h3
+X21jX2luaXRfbWMKAAAAAAAAAAAAAF9od19tY19pbml0X21jX2ZwZ2FbJXVdOiBlcnJvciAlZAoA
+AAAAAAAAAAAAAAAAAHBoeTogZmFpbGVkIHRvIGFsbG9jYXRlZCBtZW1vcnkgZm9yIHBoeSBmdyBm
+aWxlLCByZXQgJWQKAAAAAAAAAABod19sZV9maWx0ZXJfY3R1cGxlOiB0dXBsZSAldSBub3Qgc3Bl
+Y2lmaWVkIGJ1dCByZXF1aXJlZCBmb3IgbWFzayAweCV4CgAAAAAAAAAAAGxlIGNvbmZpZ3VyYXRp
+b246IGhhc2ggcmVnaW9uIHRvbyBsYXJnZSB0byBlbmFibGUgc2VydmVyIHNyYW0KAABsZSBjb25m
+aWd1cmF0aW9uOiBjYW5ub3QgZW5hYmxlIHNlcnZlciBzcmFtIHdoZW4gaGFzaCByZWdpb24gaXMg
+ZGlzYWJsZWQKAAAAAAAAAGh3X3RwX3RjcF9zZXR0aW5nc193OiB0aW1lcl9ycyAldXVzIHRpbWVz
+dGFtcF9yZXMgJXV1cyBkZWxheWVkYWNrX3JlcyAldXVzCgAAAAAAaHdfdHBfdGNwX3NldHRpbmdz
+X3c6IGRhY2tfdGltZXIgJXV1cyBtc2wgJXV1cyByeHRfbWluLG1heCAldSwldXVzIHBlcnNfbWlu
+LG1heCAldSwldXVzCgAAAAAAAAAAaHdfdHBfdGNwX3NldHRpbmdzX3c6IGtlZXBfaWRsZSxpbnR2
+bCAldSwldXMgbWF4cnR0ICV1dXMgaW5pdHNydHQgJXV1cyBmaW53YWl0Ml90aW1lciAldXVzCgAA
+AAAAaHdfdHBfdGNwX3NldHRpbmdzX3c6IGNhcHBpbmcgZGFja190aW1lciBmcm9tICV1IHRvICV1
+AAAAAAAAAAAAAGh3X3RwX3RjcF9zZXR0aW5nc193OiBjYXBwaW5nIG1zbCBmcm9tICV1IHRvICV1
+AGh3X3RwX3RjcF9zZXR0aW5nc193OiBjYXBwaW5nIHJ4dF9taW4gZnJvbSAldSB0byAldQAAAAAA
+AAAAAAAAAABod190cF90Y3Bfc2V0dGluZ3NfdzogY2FwcGluZyByeHRfbWF4IGZyb20gJXUgdG8g
+JXUAAAAAAAAAAAAAAAAAaHdfdHBfdGNwX3NldHRpbmdzX3c6IGNhcHBpbmcgcGVyc19taW4gZnJv
+bSAldSB0byAldQAAAAAAAAAAAAAAAGh3X3RwX3RjcF9zZXR0aW5nc193OiBjYXBwaW5nIHBlcnNf
+bWF4IGZyb20gJXUgdG8gJXUAAAAAAAAAAAAAAABod190cF90Y3Bfc2V0dGluZ3NfdzogY2FwcGlu
+ZyBrZWVwX2lkbGUgZnJvbSAldSB0byAldQAAAAAAAAAAAAAAaHdfdHBfdGNwX3NldHRpbmdzX3c6
+IGNhcHBpbmcga2VlcF9pbnR2bCBmcm9tICV1IHRvICV1AAAAAAAAAAAAAGh3X3RwX3RjcF9zZXR0
+aW5nc193OiBjYXBwaW5nIGluaXRfc3J0dF9tYXhydHQgZnJvbSAldSB0byAldQAAAABod190cF90
+Y3Bfc2V0dGluZ3NfdzogY2FwcGluZyBpbml0X3NydHRfaW5pdHNydHQgZnJvbSAldSB0byAldQAA
+aHdfdHBfdGNwX3NldHRpbmdzX3c6IGNhcHBpbmcgZmlud2FpdDJfdGltZXIgZnJvbSAldSB0byAl
+dQAAAAAAAGxlIGNvbmZpZ3VyYXRpb246IG5lbnRyaWVzICV1IHJvdXRlICV1IGNsaXAgJXUgZmls
+dGVyICV1IGFjdGl2ZSAldSBzZXJ2ZXIgJXUgaGFzaCAldQoAAAAAAAAAAAAAAGxlIGNvbmZpZ3Vy
+YXRpb246IG5lbnRyaWVzICV1IHJvdXRlICV1IGNsaXAgJXUgZmlsdGVyICV1IHNlcnZlciAldSBh
+Y3RpdmUgJXUgaGFzaCAldSBuc2VydmVyc3JhbSAldQoAAAAAAAAAAAAAAABod19zZ2VfcXVldWVf
+YmFzZV9tYXBbJXVdOiBleGNlZWRlZCBudW1iZXIgb2YgZWdyZXNzIHF1ZXVlcywgJXUKAAAAAAAA
+AAAAAAAAAAAAAGh3X3NnZV9xdWV1ZV9iYXNlX21hcFsldV06IGV4Y2VlZGVkIG51bWJlciBvZiBp
+bmdyZXNzIHF1ZXVlcyB3aXRoIGZyZWVsaXN0IGFuZCBpbnRlcnJ1cHQsICV1CgAAAGh3X3NnZV9x
+dWV1ZV9iYXNlX21hcFsldV06IGV4Y2VlZGVkIG51bWJlciBvZiBpbmdyZXNzIHF1ZXVlcywgJXUK
+AAAAAAAAAAAAAAAAAAAAc2t1OiBjdXN0b20gc2t1IDEwRyBkb2VzIG5vdCBzdXBwb3J0IDQwRyBw
+b3J0cwoAc2t1OiBjdXN0b20gc2t1IDQwR19TTyBkb2VzIG5vdCBzdXBwb3J0IGV4dG1lbQoAc2t1
+OiBjdXN0b20gc2t1IDEwR19TTyBkb2VzIG5vdCBzdXBwb3J0IDQwRyBwb3J0cygldSkgb3IgZXh0
+bWVtKCV1KQoAAAAAAAAAAAAAAABza3U6IGN1c3RvbSBza3UgMHgleCA0MEcgcG9ydHMoJXUpIGV4
+dG1lbSgldSkKAABjZl9wYXJzZTogZmlsZSBtZW10eXBlIDB4JXggbWVtYWRkciAweCV4IG1hcHBl
+ZCBAICVwOgoAAAAAAAAAAAAAY29uZmlndXJlZCB3aXRoIGNhcHMgbmJtfGxpbmsgMHglMDh4IHN3
+aXRjaHxuaWMgMHglMDh4IHRvZXxyZG1hIDB4JTA4eCBpc2NzaXxmY29lIDB4JTA4eAoAAAAAAAAA
+bmV0IFZJIGFsbG9jYXRpb24gZmFpbGVkIGZvciBmY19pZCAldSB3aXRoIGVycm9yICVkCgAAAAAA
+AAAAAAAAAG5ldCBWSSBtYWMgYWRkcmVzcyBwcm9ncmFtbWluZyBmYWlsZWQgZm9yIGZjX2lkICV1
+IHdpdGggZXJyb3IgJWQKAAAAAAAAAAAAAAAAAAAAbmV0IFZJIHJ4bW9kZSBwcm9ncmFtbWluZyBm
+YWlsZWQgZm9yIGZjX2lkICV1IHdpdGggZXJyb3IgJWQKAAAAAG5ldCBWSSByc3MgaW5kaXJlY3Rp
+b24gdGFibGUgcHJvZ3JhbW1pbmcgZm9yIGZjX2lkICV1IGZhaWxlZCB3aXRoIGVycm9yICVkCgAA
+AAAAbmV0IFZJIHJzcyBjb25maWcgY29tbWFuZCBmYWlsZWQgZm9yIGZjX2lkICV1IHdpdGggZXJy
+b3IgJWQKAAAAAG5ldCBWSSBjb21tYW5kIGZhaWxlZCBmb3IgZmNfaWQgJXUgd2l0aCBlcnJvciAl
+ZAoAAAAAAAAAAAAAAAAAAABwcm9ncmFtbWVkIEhXIHRhZ20gWzB4JTA4eF0sIEhXIHBnc3ogZmFj
+dG9yIFsweCUwOHhdLCBGT2lTQ1NJIHRhZ20gWzB4JTA4eF0sIHJ0YWdtIFsweCUwOHhdLCBtYXhz
+el9iaXRzIFsldV0sIHN6X2JpdHMgWyV1XS4KAAAAAGJhc2UgWyAweCUwOHhdLCBsbGltaXQgWzB4
+JTA4eF0sIHVsaW1pdCBbMHglMDh4XSwgc2l6ZSBbJXVdLCBtYXhfdHhzeiBbJXVdLCBtYXhfcnhz
+eiBbJXVdLCBpb3NpemUgWyV1XQoAAAAAAAAAAABucHBvZHMgWyV1XSwgaWR4X21hc2sgWzB4JTA4
+eF0sIGlkeF9maXJzdCBbJXVdLCBpZHhfbGFzdCBbJXVdLCBzY3NpX3BsZF9zaXplIFsldV0sIEFM
+SUdOKHNjc2lfcGxkX3NpemUsIDE2KSBbJXVdLCBwcGRfem9uZXMgWyV1XS4KAAAAAAAAAAAAAAAA
+AABmb2lzY3NpX2luaXQ6IGZvaXNjc2lfaW5pdF9kb25lIFsldV0sIGRldi5yZXMuZm9pc2NzaV9u
+dGFza3MgWyV1XSwgZGV2LnJlcy5mb2lzY3NpX25zZXNzIFsldV0sIGRldi5yZXMubmNzb2NrIFsl
+dV0sIGRldi5yZXMuZm9pc2NzaV9uaW5pdCBbJXVdLCByYyBbJWRdCgAAAAAAAAAAY2hfY2xfcmF0
+ZVsldS8ldV06IGNhcHBlZCBjbGFzcyByYXRlIGZyb20gcmVxdWVzdGVkICV1IHRvIGNvbmZpZ3Vy
+ZWQgKGVmZmVjdGl2ZSkgY2hhbm5lbCByYXRlICV1CgAAAAAAAAAAAAAAAAAAAGNoX2NsX3JhdGVb
+JXUvJXVdOiBpbmNyZWFzZWQgZGVmaWNpdF9pbmNyIGZyb20gcmVxdWVzdGVkICV1IHRvIHJlcXVp
+cmVkIG1pbiBvZiAldTsgcmF0ZSAldSAoZWZmICV1KSBkZWZpY2l0X21heCAldQoAAAAAAAAAAAAA
+AAAAcGt0c2NoZWQgY2hhbm5lbCAldSBzZXRzIHNwZWVkIChmcm9tICV1KSB0byAldSBrYnBzCgAA
+AAAAAAAAAAAAAG5ldF9sMmRldl9ub3RpZnk6IGwyZGV2X2ZjLT5mbG93Y19pZCBbMHgleF0sIHBv
+cnQgWyVkXSwgZXZlbnQgWzB4JXhdLCB1bHB0eGNoIFsldV0sIGNsYXNzIFsweCV4XSwgdnByaW8g
+WzB4JXhdLCB2aWQgWzB4JXhdLCB2aV9yZWFkeSBbJXVdCgAAAAAAAG5ldF9sMmRldl9ub3RpZnk6
+IHBnaWQgWzB4JXhdLCBwcmlvIFsweCV4XSwgY2ggWzB4JXhdCgAAAAAAAAAAAABmY29lIG5vdGlm
+eSA6IEZDb0UgTElOS1VQOiBwb3J0IDB4JXgsIGV2ZW50IDB4JXgKAAAAAAAAAAAAAAAAAAAAZmNv
+ZSBub3RpZnkgOiBGQ29FIExJTktET1dOOiBwb3J0IDB4JXgsIGV2ZW50IDB4JXgKAAAAAAAAAAAA
+AAAAAGZjb2Ugbm90aWZ5IDogRENCWCA6IHBvcnQgMHgleCwgcHJpb3JpdHkgMHgleCB1bHB0eGNo
+IDB4JXggY2xhc3MgMHgleAoAAAAAAAAAAAAAZGNieF90aW1lb3V0WyV1XQoAAAAAAAAAAAAAAAAA
+AABwb3J0X2NtZF9oYW5kbGVyOiB1bmtub3duIHUuZGNiLnR5cGUgMHgleAoAAAAAAABwb3J0WyV1
+XSBwdHlwZSAldSBsYW5lICV1OiByeGNmZyA9ICUjeAoAAAAAAAAAAABwb3J0WyV1XSBwdHlwZSAl
+dSBsYW5lICV1OiB0eGNmZyA9ICUjeAoAAAAAAAAAAABwb3J0WyV1XSBsaW5rIGRvd24gKCV1KSAo
+bHN0YXR1cyAlI3gpCgAAAAAAAAAAAABod19pMmNfdHJhbnNhY3Rpb246IG5kYXRhICV1IGFkZHJf
+b3AgMHgleCBkYXRhWzBdIDB4JXggZGlmZiAldQoAaHdfaTJjX3RyYW5zYWN0aW9uOiBuZGF0YSAl
+dSBhZGRyX29wIDB4JXggZGF0YVswXSAweCV4IGRpZmYgJXUgZHBvcyAldSBjb250ICV1IGZhaWxl
+ZCB3aXRoIGVyciAlZAoAAAAAAAAAAAAAAAAAAGkyYyB0cmFuc2FjdGlvbiBmYWlsZWQgdG8gY29t
+cGxldGUKAAAAAAAAAAAAAAAAAGkyYyBlcnJvciBjYXVzZWQgYnkgbW9kdWxlIHVucGx1ZwoAAAAA
+AAAAAAAAAAAAAHNlbmR0byBwZW5kaW5nOiB3cl9wZW5kICVwIGZvciBwb3J0ICV1LCB3YW50IHRv
+IHNlbmQgdG8gcG9ydCAldQoAAAAAAAAAAAAAAAAAAAAAcG9ydFsldV0gdXBkYXRlIChmbG93Y2lk
+ICV1IHJjICV1KQoAAAAAAAAAAAAAAAAAcG9ydF9zZXRfbG9vcGJhY2sgcG9ydCAlI3ggY3VycmVu
+dCAlI3ggbW9kZSAlI3gKAAAAAAAAAAAAAAAAAAAAAHBvcnRbJXVdIHNwZWVkIHVwZGF0ZTogJSN4
+CgAAAAAAcG9ydFsldV0gYmVnaW5uaW5nIGRlYm91bmNlCgAAAABRU0ZQIG1vZHVsZSB1bnBsdWcg
+LSByZWluaXRpYWxpemluZyByeF9sb3MgIHRvIDB4ZmYKAAAAAAAAAAAAAAAAZ3Bpb19xc2ZwX21v
+ZHVsZV91cGRhdGU6IGNoYW5nZWQgcnhfbG9zIGZyb20gMHgleCB0byAweCV4CgAAAAAAAGdwaW9f
+cXNmcF9tb2R1bGVfdXBkYXRlOiBjaGFuZ2VkIHR4X2RpcyBmcm9tIDB4JXggdG8gMHgleAoAAAAA
+AABwb3J0X2xpbmtfc3RhdGVfaGFuZGxlclsldV0gcG93ZXJpbmcgZG93bgoAAAAAAABwb3J0X2xp
+bmtfc3RhdGVfaGFuZGxlclsldV0gcG93ZXJpbmcgdXAKAAAAAAAAAABwb3J0X2xpbmtfc3RhdGVf
+aGFuZGxlclsldV0gdW5rbm93biBzdGF0ZSAoc3RhdGUgPSAlI3gpCgAAAAAAAAAAcG9ydF9saW5r
+X3N0YXRlX2hhbmRsZXI6IFNvbWV0aGluZyB3ZW50IHRlcnJpYmx5IHdyb25nLiByZXQgPSAlZAoA
+AAAAAAAAAAAAAAAAAABod19zZ2VfbWFtZW1faW5pdDogZW5jb3VudGVyZWQgZXJyb3IgJWQKAAAA
+AAAAAABsZSBpbml0aWFsaXphdGlvbjogbmVudHJpZXMgJXUgcm91dGUgJXUgY2xpcCAldSBmaWx0
+ZXIgJXUgYWN0aXZlICV1IHNlcnZlciAldSBoYXNoICV1CgAAAAAAAAAAAABsZSBpbml0aWFsaXph
+dGlvbjogbmVudHJpZXMgJXUgcm91dGUgJXUgY2xpcCAldSBmaWx0ZXIgJXUgc2VydmVyICV1IGFj
+dGl2ZSAldSBoYXNoICV1IG5zZXJ2ZXJzcmFtICV1CgAAAAAAAAAAAAAAaHdfdHBfaW5pdDogdGNi
+IHJlZ2lvbiAoc3RhcnQgMHglMDhzIHNpemUgJXUpIG11c3QgYmUgaW4gZmlyc3QgMjU2TUIgb2Yg
+TUEgbWVtb3J5CgAAAAAAAAAAAAAAAAAAaHdfdHBfaW5pdDogcGdtbmd0IHJlZ2lvbiAoc3RhcnQg
+MHglMDhzIHNpemUgJXUpIG11c3QgYmUgaW4gZmlyc3QgMjU2TUIgb2YgTUEgbWVtb3J5CgAAAAAA
+AAAAAAAAaHdfdHBfaW5pdDogVFAgcGdtbmd0IGluaXRpYWxpemF0aW9uIGRpZCBub3QgY29tcGxl
+dGUKAAAAAAAAAAAAAGJ1Zm1faW5pdDogbiAldSBidWZsbDY0aW50X3NpemUgMHgleAoAAAAAAAAA
+AAAAAGJ1Zm1faW5pdDogbm90IGVub3VnaCBtZW1vcnkgdG8gYWxsb2NhdGUgaW50ZXJuYWwgYnVm
+bGw2NCBidWZmZXJzCgAAAAAAAAAAAAAAAAAAYnVmbV9pbml0OiBub3QgZW5vdWdoIG1lbW9yeSB0
+byBhbGxvY2F0ZSBidWZsbDY0IGJ1ZmZlcnMKAAAAAAAAAG1lbV9pbml0X2J1Zjogbm90IGVub3Vn
+aCBtZW1vcnkgdG8gYWxsb2NhdGUgZmxvdyBidWZmZXJzCgAAAAAAAABtZW1faW5pdF9idWY6IG5v
+dCBlbm91Z2ggbWVtb3J5IHRvIGFsbG9jYXRlIHRjYl9jYWNoZSAob2ZmZXJlZCAldSB0cnlpbmcg
+dG8gdXNlICV1IGF2YWlsYWJsZSAldSkKAAAAAAAAAAAAAAAAAAAAbXBhcnRpdGlvbl9vdGhlcnM6
+IHN0YXJ0IDB4JTA4eCBzaXplICV1ICh1bnVzZWQgJXUpCgAAAAAAAAAAAAAAAG1wYXJ0aXRpb25f
+b3RoZXJzOiBzdGFydCAweCUwOHggc2l6ZSAldSAodW51c2VkICV1KQoAAAAAAAAAAAAAAABtZW1f
+aW5pdDogRURDIG92ZXJjb21taXR0ZWQgYnkgJWQgYnl0ZXMKAAAAAAAAAABtZW1faW5pdDogbm90
+IGVub3VnaCBtZW1vcnkgdG8gYWxsb2NhdGUgZmxvdyB0YWJsZQoAAAAAAAAAAAAAAAAAY3hjbmlj
+X2RldmljZV9pbml0OiBjeGNuaWMgWzB4JTB4XSwgY3hjbmljLT5maWx0ZXIgWyUweF0KAAAAAAAA
+AHBvZmNvZSBpbml0IGRvbmUKAAAAAAAAAAAAAAAAAAAAUG9ydFsldV06IFVua25vd24gU0dNSUkg
+c3ViLXR5cGUgJSN4CgAAAAAAAAAAAAAAUG9ydFsldV06IFVua25vd24gQlRfWEZJIHN1Yi10eXBl
+ICUjeAoAAAAAAAAAAAAAcG9ydF9pbml0WyV1XTogcG9ydCB0eXBlIDB4JXggaXMgbm90IHN1cHBv
+cnRlZAoAbXBhcnRpdGlvbl9pbml0OiBtb3ZlZCBwbXJ4X3N0YXJ0IGZyb20gMHglMDh4IHRvIDB4
+JTA4eCB0byBtYWtlIHJvb20gZm9yIExFIEhBU0ggYW5kL29yIFRQIFRDQnMKAAAAAAAAAAAAAAAA
+AAAAAG1wYXJ0aXRpb25faW5pdDogbW92ZWQgcG1yeF9zdGFydCBmcm9tIDB4JTA4eCB0byAweCUw
+OHggKEVEUkFNKQoAAAAAAAAAAAAAAAAAAAAARVEgcGZuICV1IHZmbiAldTogZGVzdHJveWluZyBl
+cWlkICV1IHdpdGggcGVuZGluZyBXUihzKSAobnVtX2J5dGVzICV1IGFuZCBmbGFncyAweCUwOHgK
+AAAAAAAAAAAAbDJkZXZfZmMtPmZsb3djX2lkIFsldV0sIGwyZGMtPnBmbiBbJXVdLCBsMmRjLT52
+Zm4gWyV1XSwgbDJkYy0+bHBvcnQgWyV1XSwgbDJkZXZfZmMtPmZsb3dpZCBbJXVdIGwyZGMtPnR4
+X2NoIFsldV0sIGRldi52cGQucG9ydHZlYyBbJXhdCgAAAAAAAAAAcG9ydHZlYyBbJXVdCgAAAGwy
+ZGV2X3ZpX2ZzbTogbWIgWzB4JXhdLCBkZWZlcnJlZCwgc3RhdGUgWzB4JXhdLCBwb3J0IFsweCV4
+XQoAAABsMmRldl92aV9mc206IHZpaWQgWzB4JXhdIHBvcnQgWzB4JXhdLCBtYWMtaWQgWyUwMng6
+JTAyeDolMDJ4OiUwMng6JTAyeDolMDJ4XS4gCgAAAAAAAAAAAAAAAAAAAABsMmRldl92aV9mc206
+IHNnZV9lcWlkIFsweCV4XSwgc2dlX2lxaWQgWzB4JXhdLCBzZ2VfZXFjciBbMHgleF0sIHJzc19z
+eiBbMHgleF0KAGwyZGV2X3ZpX2ZzbTogbDJkZXZfZmMtPmZsb3djX25ldF9sMmRldl9tdHUgWyV1
+XSwgbWJfc2NyYXRjaCBbMHgleF0sIHBvcnQgWzB4JXhdCgAAAAAAAAAAAAAAAAAAAGwyZGV2X3Zp
+X2ZzbTogdmlpZCBbJWRdLCB2aV9mYy0+Zmxvd2NfdmlfZmxhZ3MgWzB4JXhdCgAAAAAAAAAAAABs
+MmRldl92aV9mc206IHBmbiBbMHgleF0sIHZmbiBbMHgleF0sIGwyZGV2X2ZjLT5mbG93Y19pZCBb
+MHgleF0sIGxwb3J0IFsweCV4XSwgdmlpZCBbMHgleF0sIGZsYWdzIFsweCV4XQoAAAAAAAAAbDJk
+ZXZfdmlfZnNtOiBFcnJvciBmcmVlaW5nIFZJLCByYyBbMHgleF0KAAAAAAAAbDJkZXZfdmlfZnNt
+OiBwaWQgWzB4JXhdLCB2aWlkIFsweCV4XSwgbWJfbG9jIFsweCV4XSwgbWJfb3JpZ1sweCV4XSwg
+bDJkZXZfZmxhZ3MgWzB4JXhdLCByYyBbMHgleF0KAAAAAAAAAAAAAAAAAEFoIGhhLi4uZG91Ymxl
+IGZyZWUgb3hfaWQgMHgleCwgcnhfaWQgMHgleAoAAAAAAEhvc3QgUFJMSSBSZXNwb25zZSB0aW1l
+ZG91dDogb3hfaWQgMHgleCByeF9pZCAweCV4CgAAAAAAAAAAAAAAAABGQ09FIEZyZWU6IHN0aWxs
+IHlpZWxkZWQgd2hlbiBmcmVlaW5nLi4uZmxvd2NfaWQgJXggZmxvd2NfZmxhZ3MgJXggCgAAAAAA
+AAAAAAAAAEZDIHhjaGcgZnJlZSB4aWQ6JWQgZmxvd2lkICVkCgAAcGZuICV1IHZmbiAldSB2aWEg
+Y29tbWFuZAoAAAAAAABjb25maWd1cmF0aW9uIGZpbGUgcGFyc2VyOiBwbCB0aW1lb3V0IHZhbHVl
+IGlzIHRvbyBsYXJnZSwgY2hhbmdpbmcgZnJvbSAldSB0byAldXVzZWNzCgAAAAAAAAAAAABQTF9Q
+Q0lFX0xJTksuc3BlZWQgb2YgJXUgaXMgbm90IHN1cHBvcnRlZApmaWxlLCByZXQgRldfRUlPCgAA
+AAAAc2NoZWRfaW9xdHhfYnBfcHJpb3JpdHk6IGhhcyAldSBlbnRyaWVzIG9ubHksIHJlcXVpcmVz
+ICV1IGVudHJpZXMKAAAAAAAAAAAAAAAAAAB0cF9iYWNrb2ZmOiBwYXJzZWQgJWQgaW5zdGVhZCBv
+ZiAldSBlbnRyaWVzCgAAAAB0cF90aW1lcnZhbHM6IHBhcnNlZCAlZCBpbnN0ZWFkIG9mICV1IGVu
+dHJpZXMKAAB0cF90aW1lcnJlczogcGFyc2VkICVkIGluc3RlYWQgb2YgJXUgZW50cmllcwoAAAB0
+cF9tdHVzIGhhcyAldSBlbnRyaWVzIG9ubHksIHJlcXVpcmVzICV1IGVudHJpZXMKAAAAAAAAAAAA
+AAAAAAAAdHBfbXR1c1sldV0gaXMgJXUgYnl0ZXMgd2hpY2ggaXMgbm90IHN1cHBvcnRlZAoAY29u
+ZmlndXJhdGlvbiBmaWxlIHBhcnNlcjogc2dlIHRpbWVyIHZhbHVlWyVpXSBpcyB0b28gbGFyZ2Us
+IGNoYW5naW5nIGZyb20gJXUgdG8gJXV1c2VjcwoAAAAAAAAAZmlsdGVybWFzayAweCV4IGlzIG5v
+dCBlcXVhbC9zdWJzZXQgdG8vb2YgZmlsdGVybW9kZQoAAAAAAAAAAAAAAGh3X2xlX2NsaXBfaGFu
+ZGxlcjogcmVtb3ZlZCBwb3M9JXUgKD1pZHggJXUpCgAAAGh3X2xlX2NsaXBfaGFuZGxlcjogYWRk
+aW5nIHRvIHBvcz0ldSAoPWlkeCAldSkKAG1vZHVsZVsldV06IHBvcnQgbW9kdWxlIGluc2VydGVk
+IGFuZCByZWFkeQoAAAAAAG1vZHVsZVsldV06IHBvcnQgbW9kdWxlIHJlbW92ZWQKAAAAAAAAAAAA
+AAAAAAAAAG1vZHVsZVsldV06IHVua25vd24gbW9kdWxlIGlkZW50aWZpZXIgMHglMDJ4CgAAAG1v
+ZHVsZVsldV06IGdwaW8gJXUgdHJhbnMgMTBHIDB4JTAyeCAxRyAweCUwMnggKGxlbmd0aCAldSkg
+Y2FibGUgMHglMDJ4IChsZW5ndGggJXUpIG1vZHVsZV90eXBlIDB4JTAyeAoAAAAAAAAAAABtb2R1
+bGVbJXVdOiBncGlvICV1IHRyYW5zIDEwRyAweCUwMnggMUcgMHglMDJ4IChsZW5ndGggJXUpIGNh
+YmxlIDB4JTAyeCAobGVuZ3RoICV1KSBtb2R1bGVfdHlwZSAweCUwMngKAAAAAAAAAAAAY3JfbW9k
+dWxlX3J4X2xvc1sldV06IHJ4X2xvcyBjaGFuZ2VkIHRvICV1CgAAAAAATUM6IGV4cGVjdGVkIHN0
+YXRlIHRvIHN3aXRjaCB0byBDRkcuAAAAAAAAAAAAAAAATUM6IGV4cGVjdGVkIHN0YXRlIHRvIHN3
+aXRjaCB0byBBY2Nlc3MuAAAAAAAAAAAATUM6IGV4cGVjdGVkIHN0YXRlIHRvIHN3aXRjaCB0byBD
+RkcuAAAAAAAAAAAAAAAATUM6IGV4cGVjdGVkIHN0YXRlIHRvIHN3aXRjaCB0byBBY2Nlc3MuAAAA
+AAAAAAAASUkuMS5ieCBkcDE4WyV1XSBxWyV1XSAlI3ggJSN4ICUjeCAlI3ggbWluICUjeCBtYXgg
+JSN4CgAAAAAAAAAAAElJLjEuYy1kLiAlI3ggJSN4ICUjeCAlI3ggYWxsICAlI3gKAAAAAAAAAAAA
+AAAAAElJLjIuYiAoJSN4IC0gJSN4ICsgJSN4KSAlIDEyOCA9ICUjeAoAAAAAAAAAAAAAAElJLjMg
+aW5ld18xZSBhZnRlciBsaW1pdCBjb21wdXRlIGl0ZW1wXzFlICV4LCBpbmV3XzFlICV4CgAAAAAA
+AABJSS4zLiBpdGVtcF8xZSAlI3ggaW5ld18xZSAlI3ggaW5ld18xZSAlZAoAAAAAAABJSS40LiBz
+ZXRfMWUgJSN4CgAAAAAAAAAAAAAAAAAAAE1DOiBjYWxpYnJhdGlvbiBmYWlsZWQgZm9yIGVycmF0
+YTI5IGRwMTggJXUKAAAAAElWLjEuIGRwMThbJXVdIHBoYXNlX3NlbCBiZWZvcmUgJSN4IGFmdGVy
+ICUjeCwgZ2F0ZV9kZWxheSAlI3gKAABNQyBlcnJhdGEyOSBpc3N1ZTogZHAxOCAldSBxdWFkICV1
+IGNhbm5vdCBiZSBkZWNyZWFzZWQKAAAAAAAAAAAATUMgZXJyYXRhMjkgaXNzdWU6IGRwMTggJXUg
+cXVhZCAldSBjYW5ub3QgYmUgZGVjcmVhc2VkCgAAAAAAAAAAAE1DIGVycmF0YTI5IGlzc3VlOiBk
+cDE4ICV1IHF1YWQgJXUgY2Fubm90IGJlIGRlY3JlYXNlZAoAAAAAAAAAAABNQyBlcnJhdGEyOSBp
+c3N1ZTogZHAxOCAldSBxdWFkICV1IGNhbm5vdCBiZSBkZWNyZWFzZWQKAAAAAAAAAAAAdGVtcDJf
+MWUrMHgxMCA9ICUjeAoAAAAAAAAAAAAAAABNQzogY2FsaWJyYXRpb24gZmFpbGVkIGZvciBlcnJh
+dGEyMSBpdGVyYXRpb24gJXUKAAAAAAAAAAAAAAAAAAAATUMgZXJyYXRhIDIxOiBkcDE4WyV1XSBw
+cjAgbjAyIGZhaWxlZCB0byBnZXQgYXZlcmFnZQoAAAAAAAAAAAAAAE1DIGVycmF0YSAyMTogZHAx
+OFsldV0gcHIwIG4xMyBmYWlsZWQgdG8gZ2V0IGF2ZXJhZ2UKAAAAAAAAAAAAAABNQyBlcnJhdGEg
+MjE6IGRwMThbJXVdIHByMSBuMDIgZmFpbGVkIHRvIGdldCBhdmVyYWdlCgAAAAAAAAAAAAAATUMg
+ZXJyYXRhIDIxOiBkcDE4WyV1XSBwcjEgbjEzIGZhaWxlZCB0byBnZXQgYXZlcmFnZQoAAAAAAAAA
+AAAAAE1DIGluaXRpYWxpemF0aW9uIGZhaWxlZDogREZJIGluaXQgbm90IGdvaW5nIHRvIDAKAAAA
+AAAAAAAAAAAAAABNQyBpbml0aWFsaXphdGlvbiBmYWlsZWQ6IERGSSBpbml0IG5vdCBjb21wbGV0
+aW5nCgAAAAAAAAAAAAAAAAAATUMgaW5pdGlhbGl6YXRpb24gZmFpbGVkOiBDYWxpYnJhdGlvbiBk
+aWRuJ3QgY29tcGxldGUuCgAAAAAAAAAAAERQMTggJXUsIGJ5dGVfbGFuZSAldSwgYml0X3NlbGVj
+dCAldQoAAAAAAAAAAAAAAERQMTggJXUsIGJ5dGVfbGFuZSAldSwgYml0X3NlbGVjdCAldQoAAAAA
+AAAAAAAAAE1DIGZhaWxlZCB0byBnZXQgVVBDVEwgcG93ZXIgdXAgZG9uZQoAAAAAAAAAAAAAAE1D
+IGluaXRpYWxpemF0aW9uIGZhaWxlZDogRGlkbid0IGdldCBhbGwgRFAxOHMgbG9ja2VkCgAAAAAA
+AAAAAABNQyBpbml0aWFsaXphdGlvbiBmYWlsZWQ6IERpZG4ndCBnZXQgYm90aCBBRFJzIGxvY2tl
+ZAoAAAAAAAAAAAAAQ3VycmVudCBTbGV3IHR4X3JvdyAlZDogdHhfY29sICVkLCB2YWwgJWQKAAAA
+AAAAQ3VycmVudCBTbGV3IGFkZHJfcm93ICVkOiBhZGRyX2NvbCAlZCwgdmFsICVkCgAATUMgaW5p
+dGlhbGl6YXRpb24gZmFpbGVkOiBTTEVXX0RPTkVfU1RBVFVTIG5ldmVyIHRvZ2dsZWQAAAAAAAAA
+AGZscl9wZnZmX2ZzbVsldToldV06IHVua25vd24gc3RhdGUgJXUKAAAAAAAAAAAAAGh3IHBmIGJp
+dG1hcCAweCUwMnggdmZpZCBiaXRtYXAgMHglMDh4OjB4JTA4eDoweCUwOHg6MHglMDh4CgAAAABh
+ZnRlciB2ZmlkIGZpeHVwLCB2ZmlkIGJpdG1hcCAweCUwOHg6MHglMDh4OjB4JTA4eDoweCUwOHgK
+AAAAAAAATUNbJXVdOiBmYWlsZWQgdG8gc3dpdGNoIGNvbnRyb2xsZXIgdG8gQ0ZHIHN0YXRlCgAA
+AAAAAAAAAAAAAAAAAE1DWyV1XTogZmFpbGVkIHRvIHN3aXRjaCBjb250cm9sbGVyIHRvIElOSVRf
+TUVNIHN0YXRlCgAAAAAAAAAAAABNQ1sldV06IGZhaWxlZCB0byBzd2l0Y2ggY29udHJvbGxlciB0
+byBDRkcgc3RhdGUKAAAAAAAAAAAAAAAAAAAATUNbJXVdOiBwZXJpb2RpYyBjYWxpYnJhdGlvbiBm
+YWlsZWQgd2l0aCBlcnJvciAldQoAAAAAAAAAAAAAAAAAAHRpbWVyIHF1ZXVlICV1IGxvc3QgYSB0
+aWNrISBuZXh0ICVwIGxhc3QgJXAgbnVtZSAldQoAAAAAAAAAAAAAAABmbHJfdGltZXJfc3RhcnQ6
+IGZsb3djX2lkICV1ICVwIGJ1ZiAlcAoAAAAAAAAAAABNQUM6IFBMTHMgZGlkbid0IGxvY2sKAAAA
+AAAAAAAAAHBjaWU6IHJlYWQgZnJvbSBzZXJjZmcgcGNpZV9pcF91cl9tYXhmdW5jIDB4JXggcGZi
+aXRtYXAgMHgleAoAAABwY2llOiBucGYgJXUgKHBmYml0bWFwIDB4JTAyeCkgbnZmICV1IChwZiAw
+Li43IDB4JTA4eCUwOHgpIHZmc3RyaWRlICV1CgAAAAAAAAAAAGZhaWxlZCB0byBmaW5kIHRoZSAl
+YyVjIFZQRCBwYXJhbWV0ZXIKAAAAAAAAAAAAAGZhaWxlZCB0byBwYXJzZSB0aGUgJWMlYyBWUEQg
+cGFyYW1ldGVyCgAAAAAAAAAAAGZhaWxlZCB0byBzdWNjZXNzZnVsbHkgZmluZCBDaGVsc2lvIFZQ
+RAoAAAAAAAAAAGxvZyBpbml0aWFsaXplZCBAIDB4JTA4eCBzaXplICV1ICgldSBlbnRyaWVzKSBm
+d3JldiAweCUwOHggcGNpZV9mdyAweCUwOHgKAAAAAAAAYm9vdHN0cmFwIGZpcm13YXJlIHRvb2sg
+JXUgbXNlY3MgdG8gcnVuCgAAAAAAAAAAUEkgZXJyb3IgZmxvd2lkX2xlbjE2IDB4JXgsIGFwcF90
+YWcgMHgleCwgcmVmX3RhZyAweCV4LCBwaXNjICUwNHggJTA0eCAlMDR4ICUwNHgKAAAAAAAAAAAA
+AAAAAAAAZmxvd2MgJXUgKFNHRSBlcWlkICV1KSAoRVRIQ1RSTCBxdWV1ZSkgZXhwZXJpZW5jZWQg
+YSBQQ0kgRE1BIFJFQUQgd29yayByZXF1ZXN0IGVycm9yIChpbmJvdW5kIHF1ZXVlICV1KQoAAAAA
+AAAAAGZsb3djICV1IChTR0UgZXFpZCAldSkgZXhwZXJpZW5jZWQgYW4gdW5leHBlY3RlZCBQQ0kg
+RE1BIFJFQUQgd29yayByZXF1ZXN0IGVycm9yIChpbmJvdW5kIHF1ZXVlICV1KQoAAAAAAAAAAAAA
+AABmbG93YyAldSBleHBlcmllbmNlZCBhbiB1bmV4cGVjdGVkIFBDSSBETUEgUkVBRCBlcnJvciAo
+aW5ib3VuZCBxdWV1ZSAldSkKAAAAAAAAAGdhdGhlcl90YXNrc19mb3JfdG1mOiBpZHggWzB4JXhd
+LCB0YXNrLWlkIFsweCV4XSwgY21kLWlkIFsweCV4XSwgYWN0aXZlIHRhc2tzIFsweCV4XS4gY29u
+bi1pZCBbMHgleF0sIGNtZCBjb25uLWlkIFsweCV4XSwgdGFzayBjb25uLWlkIFsweCV4XQoAAGdh
+dGhlcl90YXNrc19mb3JfdG1mOiBJbnZhbGlkIHR5cGUgWzB4JXhdLCBiYWlsaW5nIG91dC4KAAAA
+AAAAAABnYXRoZXJfdGFza3NfZm9yX3RtZjogdGFzayBpZCBbMHgleF0sIHN0YXRlIFsweCV4XSwg
+bGlkeCBbMHgleF0sIGNvb2tpZSBoaSBbMHglMDh4XSA6IGxvIFsweCUwOHhdCgAAAAAAAAAAAAAA
+AAAAZ2F0aGVyX3Rhc2tzX2Zvcl90bWY6IHJjIFsweCV4XSwgWzB4JXhdIHRhc2sgZ2F0aGVyZWQg
+Zm9yIHRtZiB0eXBlIFsweCV4XSBwcm9jZXNzaW5nLgoAAAAAAAAAAAAAc2NzaV9kYXRhX291dDog
+Y29ubl9mYyBbMHgleF0sIHN0YXRlIFsweCV4XSwgc2Vzc19mYyBbMHgleF0gaW4gcmVjb3Zlcnku
+IFNraXBwaW5nIGlzdGFza19mYyBbMHgleF0gZnJvbSBUWC4KAAAAAHNlbmRfYWJvcnRfcmVxOiBj
+c2tfZmMtPmZsb3djX3R5cGUgWzB4JXhdLCBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgdGlkIFsw
+eCV4XSwgdWxwdHhjaCBbJXVdLCBidWZmZXJlZCBbJXVdCgAAAABodyByZWdpc3RlciBvcGVyYXRp
+b24gbm90IGNvbXBsZXRpbmcsIHJlZyAweCUwOHggbWFzayAweCUwOHggdmFsdWUgMHglMDh4IChy
+ZWcgMHglMDh4KQoAAAAAAAAAAABNRElPIENMNDU6IGZhaWxlZCB0byBzZXQgdXAgTU1EIGFkZHIK
+AAAAAAAAAAAAAABNRElPOiBmYWlsZWQgdG8gcmVhZAoAAAAAAAAAAAAAAGh3X2JjbTg0ODU2X2No
+ZWNrIGVudHJ5CgAAAAAAAAAAaHdfYmNtODQ4NTZfY2hlY2sgbG9vcCAldSAoY2hlY2sgJSN4KQoA
+AAAAAAAAAAAAaHdfYmNtODQ4NTZfY2hlY2sgdXBfcnVubmluZyAobG9vcF9jbnQ9JXUpCgAAAAAA
+aHdfYmNtODQ4NTZfY2hlY2sgZmFpbGVkIChiYWQgQ1JDKQoAAAAAAAAAAAAAAAAAUEhZIGZpcm13
+YXJlIGxvYWQgc3VjY2Vzc2Z1bCEgKHdvdy4uLikKAAAAAAAAAAAATURJTyBDTDQ1OiBmYWlsZWQg
+dG8gc2V0IHVwIE1NRCBhZGRyCgAAAAAAAAAAAAAATURJTzogZmFpbGVkIHRvIHdyaXRlCgAAAAAA
+AAAAAABtaWlfYWR2X2ZjWyV1XTogcmNhcHMgMHgleAoAAAAAAG1paV9hZHZfc3BlZWRbJXVdOiBy
+Y2FwcyAweCV4CgAAbmV0aWZfc2V0X21hYzogbDJkZXZfZmMtPmZsb3djX25ldF9sMmRldl9tYnMg
+WzB4JXhdCgAAAAAAAAAAAAAAAHJlbW92aW5nIG1hYwoAAABub2RlLT5ncnAgWyUwNHggJTA0eCAl
+MDR4ICUwNHhdLCBub2RlX2lkICV1LCByZWZfY250ICV1CgAAAAAAAAAAREFEIGZvciBhZGRyIFsl
+MDR4ICUwNHggJTA0eCAlMDR4XQoAAAAAAAAAAAAAAAAAY3BsX3R4X3BrdDogdmxhbmlkIFsweCV4
+XQoAAAAAAABjcGxfdHhfcGt0OiB2bGFuaWQgWzB4JXhdCgAAAAAAAGZsb3djX2lkIFsldV0gbDJk
+ZXZfZmMgWzB4JXhdIGFscmVhZHkgcmVjZWl2ZWQgUkEsIG5vdCBzZW5kaW5nIFJTCgAAAAAAAAAA
+AAAAAAAAZmxvd2NpZCBbJXVdIGwyZGV2X2ZjIFsweCV4XSBObyBJUHY2IHJvdXRlcgoAAAAAc2Vu
+ZF9jbG9zZV9yZXE6IGNza19mYy0+Zmxvd2NfdHlwZSBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQg
+WzB4JXhdLCBjc2tfZmMtPnRjYl9zdGF0ZSBbMHgleF0KAAAAc2VuZF9jbG9zZV9yZXE6IGNza19m
+Yy0+Zmxvd2NfdHlwZSBbMHgleF0sIGNza19mYy0+Zmxvd2NfaWQgWzB4JXhdLCB0aWQgWzB4JXhd
+LCB1bHB0eGNoIFsldV0sYnVmZmVyZWQgWyV1XQoAAAAAAG9mbGRfdGNwX2RvX2FjdGl2ZV9jbG9z
+ZTogY3NrX2ZjIFsweCV4XSwgY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+dGNiX3N0
+YXRlIFsweCV4XQoAAAAAAG9mbGRfdGNwX2RvX2FjdGl2ZV9jbG9zZTogY3NrX2ZjIFsweCV4XSwg
+Y3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19mYy0+dGNiX3N0YXRlIFsweCV4XQoAAAAAAG9m
+bGRfdGNwX2Rpc2Nvbm5lY3Q6IHRjYl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBjc2tfZmMtPmZsb3dj
+X2lkIFsweCV4XSwgY3NrLT50Y2Jfc3RhdGUgWzB4JXhdCgAAAGRlY29kZV9iYXNlNjRfc3RyaW5n
+OiBkbGVuIFslZF0KAAAAAAAAAAAAAAAAAAAAAGRlY29kZV9oZXhfc3RyaW5nOiBkbGVuIFslZF0K
+AAAAZm9pc2NzaV92YWxpZGF0ZV9sb2dpbl9zdGFnZTogLSAxCgAAAAAAAAAAAAAAAAAAYXN5bmNf
+cGR1OiBsb2dvdXQgcmVxdWVzdGVkIGJsb2NraW5nIHNlc3Npb24KAAAAYXN5bmNfcGR1OiBzZXNz
+L2Nvbm4gZHJvcCByZXF1ZXN0ZWQgYmxvY2tpbmcgc2Vzc2lvbgoAAAAAAAAAAAAAAGNwbF90eF9w
+a3Q6IHZsYW5pZCBbMHgleF0KAAAAAAAAcmVpbml0IGxpbmstbG9jYWwgYWRkcmVzcwoAAAAAAABu
+ZXRfbDJkZXZfZmluZF9ieV9hZGRyOiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBsMmRjLT5s
+cG9ydCBbJXVdLCBsMmRfZmMtPmZsb3djX2lkIFsweCV4XSwgbDJkYy0+aW40X2Rldi5pbl9hZGRy
+LmFkZHIgWzB4JXhdLCBhZGRyIFsweCV4XQoAAABuZXRfbDJkZXZfbXR1X2NvbmZpZzogbDJkZXZf
+ZmMtPmZsb3djX2lkIFsweCV4XSwgbXR1ICV1CgAAAAAAAAAAbmV0aWZfZG9fZGhjcDogd3ItPnBh
+cmFtLnZsYW5pZCBbJXVdLCBsMmRldl9mYy0+Zmxvd2NfbmV0X2wyZGV2X3ZsYW5kZXYgWzB4JXhd
+CgBjcGxfdHhfcGt0OiB2bGFuaWQgWzB4JXhdCgAAAAAAAGVuY29kZSBoZXggc3RyaW5nOiBkbGVu
+IFslZF0KAAAAY2huZXRfZmluZF9sMnRfZW50cnk6IGRhZGRyIFslMDh4XSwgWzB4JTA4eF0sIGxv
+Y2FsIG5ldHdvcmsgWyVkXQoAAAAAAAAAAAAAAAAAAABsMnRlbnQgWyUweF0sIGwydGVudC0+aWR4
+IFslZF0KAHRjcF9zZW5kX2FvcGVuX3JlcTogY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIGNza19m
+Yy0+Zmxvd2Nfc3RhdGUgWzB4JXhdLCBidWZmZXJlZCBbJXVdLCByZXNfY250IFsweCV4XSwgaXFf
+aWR4IFsweCV4XQoAAAAAAAAAAAAAdGNwX3NlbmRfYW9wZW5fcmVxOiBjc2tfZmMtPmZsb3djX2lk
+IFsweCV4XSwgY3NrX2ZjLT5mbG93Y19zdGF0ZSBbMHgleF0sIG5vIHZhbGlkIGwydF9lbnR5LiBE
+ZWxheWluZyBhbm90aGVyIHJldHJ5IGZvciAxIHNlY29uZHMuCgAAAAAAAAAAAAAAAAAAYW9wZW5f
+cmVxOiBod19sZV9maWx0ZXJfY3R1cGxlIGZhaWxlZAoAAAAAAAAAAAAAb2ZsZF90Y3Bfc2VuZF9h
+b3Blbl9yZXE6IGNwbF9yZXEtPkZpbHRlcl9oaSBbMHglMHhdLCBjcGxfcmVxLT5GaWx0ZXJfbG9f
+RkNvRU1hc2sgWzB4JTB4XSwgY3R1cGxlc1swXSBbMHgleF0sIGN0dXBsZXNbMV0gWzB4JXhdCgBj
+b25uZWN0aW9uIG92ZXIgaXB2NiwgbDJkZXYgZmxvd2NfaWQgMHgleAoAAAAAAABjc29ja19hbGxv
+YzogdHhfY2ggWzB4JXhdLCBscG9ydCBbMHgleF0sIGNvb2tpZSBbJTA4eF0KAAAAAAAAAAAAY3Nv
+Y2tfYWxsb2M6IGF2YWlsYWJsZSBbJXVdLCBuY3NvY2sgWyV1XSwgcG9zOmF0aWQgWzB4JXhdLCBj
+c2tfZmMgWzB4JXhdLCBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwgc3BvcnQgWyV1XQoAAFdBVENI
+RE9HOiBObyB0ZW1wZXJhdHVyZSBzZW5zb3IgYXZhaWxhYmxlLgoAAAAAAHdhdGNoZG9nIGNtZCBy
+ZWZyZXNoIChhY3Rpb24gJXUpCgAAAAAAAAAAAAAAAAAAAFdBVENIRE9HOiBBY3RpdmF0aW5nCgAA
+AAAAAAAAAAAAV0FUQ0hET0cgLSBFbmFibGUgYWN0aW9uICV1IHRpbWUgJXUKAAAAAAAAAAAAAAAA
+V0FUQ0hET0cgLSBEaXNhYmxlIGFjdGlvbiAldQoAAABXQVRDSERPRzogRGUtYWN0aXZhdGluZwoA
+AAAAAAAAAHBvcnRbJXVdIHNldCBQQVVTRSBQQVJBTVM6IHBwcGVuICV1IHR4cGUgJSN4IHJ4cGUg
+JSN4CgAAAAAAAAAAAABtcHNfbGlua191cFsldV0gYWNhcHMgJSN4ICg4MDIuMyAlI3gpICsgbHBh
+Y2FwcyAlI3ggPT4gJSN4CgAAAAAAaXB2Nl9oYW5kbGVfbGlua19kb3duIGZsb3djX2lkIDB4JXgK
+AAAAAAAAAAAAAAAAaXB2Nl9oYW5kbGVfbGlua191cCBmbG93Y19pZCAweCV4CgAAAAAAAAAAAAAA
+AAAAZm9pc2NzaSBjb25uX2ZjIFsweCV4XSwgZmxvd2Nfc2NoZWRjbCBbMHgleF0sIGluZ19jaCBb
+MHgleF0sIGVncl9jaCBbMHgleF0KAAAAAABsMmRldl9ub3RpZnkgd2l0aCB1bmtub3duIGZsYWcg
+WzB4JXhdCgAAAAAAAAAAAABGQ29FIEZDQiBsaW5rZG93bjogaW9fcmVxIDB4JXgleCBpcWlkIDB4
+JXggZmxvd2lkIDB4JXggb3AgMHgleAoAY2FuY2VsIGZjYjoleCBzY2I6JXggc3RhdGU6JXgKAABS
+REVWIG1zZyBmbG93YzoleCBzdGF0ZSAweCV4IGV2ZW50IDB4JXgKAAAAAAAAAAB2bjJ2bjogcG9y
+dCAweCV4IGRpZDoweCV4JXgleCBVUAoAAAAAAAAAAAAAAAAAAAB2bjJ2bjogcG9ydCAweCV4IGRp
+ZDoweCV4JXgleCBET1dOCgAAAAAAAAAAAAAAAABmY19zZW5kX2FsbG9jX2NwbDogZmFpbGVkIHRv
+IHNldHVwIGZpbHRlciBjdHVwbGUKAAAAAAAAAAAAAAAAAAAAZmNvZV9jb21wdXRlX2N0dXBsZSAw
+eCV4OiV4CgAAAABjb21wdXRlX2N0dXBsZSgpOiBmYWlsZWQgdG8gc2V0dXAgZmlsdGVyIGN0dXBs
+ZQoAAAAAAAAAAAAAAAAAAAAAZmNvZV9jb21wdXRlX2N0dXBsZSB2bGFuICV4IHZpaWQgJXggcG9y
+dCAleCBtcHNfaWR4ICV4CgAAAAAAAAAAAEFwcGx5IEFQUDogcG9ydCAlZCBwcmlvciAlZCBzZWxl
+Y3QgJWQgcHJvdG9jb2xJRCAweCUwNHgKAAAAAAAAAABjaF9jbF9yYXRlWyV1LyV1XTogY2FwcGVk
+IGRlZmljaXRfaW5jciBmcm9tIHJlcXVpcmVkICV1IHRvICV1OyByYXRlICV1IChlZmYgJXUpIGRl
+ZmljaXRfbWF4ICV1CgBmY19zZW5kX2FsbG9jX2NwbDogZmFpbGVkIHRvIHNldHVwIGZpbHRlciBj
+dHVwbGUKAAAAAAAAAAAAAAAAAAAAZmNvZV9jb21wdXRlX2N0dXBsZSAweCV4OiV4CgAAAABjb21w
+dXRlX2N0dXBsZSgpOiBmYWlsZWQgdG8gc2V0dXAgZmlsdGVyIGN0dXBsZQoAAAAAAAAAAAAAAAAA
+AAAARkNvRSBGQ0YgdGltZXI6IGZsb3djIHN0YXRlIDB4JXgsIHBvcnQgMHgleCAsZmNmIDB4JXgs
+IGZsb3djX2lkIDB4JXgKAAAAAAAAAAAAAAByaV93cl9pbml0WyV1XTogbXNzICV1IGlzIG5vdCA4
+LWJ5dGUgYWxpZ25lZAoAAABjb3JlX3Byb2dyYW1fdGNiOiB0aWQgJSN4IHRfc3RhdGUgJSN4IHJj
+dl9hZHYgMHglMDh4IHJjdl9zY2FsZSAlI3ggdHhfbWF4ICUjeCByY3Zfbnh0ICUjeCBhdGlkICUj
+eAoAAAAAAAAAAAAAAAAACW9wdDAgJSN4JXggb3B0MiAlI3ggaXB2NiAlI3ggZmxhZ3NfdGltZXIg
+MHglMDh4CgAAAAAAAAAAAAAAAAAAAG9mbGRfY29ubmVjdGlvbl93cjogY29ubmVjdGlvbiB3aXRo
+IDUtdHVwbGUgbHAgMHglMDR4IGZwIDB4JTA0eCBsaXAgMHglMDh4JTA4eCBwaXAgMHglMDh4JTA4
+eCBmaWx0ZXIgMHglMDh4IGV4aXN0cyBAIExFIGluZGV4ICV1CgAAAAAAAAAAAAAAAAAAAG9mbGRf
+Y29ubmVjdGlvbl93cjogY29ubmVjdGlvbiB3aXRoIDUtdHVwbGUgbHAgMHglMDR4IGZwIDB4JTA0
+eCBsaXAgMHglMDh4IHBpcCAweCUwOHggZmlsdGVyIDB4JTA4eCBleGlzdHMgQCBMRSBpbmRleCAl
+dQoAAAAAAAAAb2ZsZF9jb25uZWN0aW9uX3dyOiBjb25uZWN0aW9uIHdpdGggNS10dXBsZSBscCAw
+eCUwNHggZnAgMHglMDR4IGxpcCAweCUwOHglMDh4IHBpcCAweCUwOHglMDh4IGZpbHRlciAweCUw
+OHgKAAAAAG9mbGRfY29ubmVjdGlvbl93cjogY29ubmVjdGlvbiB3aXRoIDUtdHVwbGUgbHAgMHgl
+MDR4IGZwIDB4JTA0eCBsaXAgMHglMDh4IHBpcCAweCUwOHggZmlsdGVyIDB4JTA4eAoAAAAAAAAA
+AAAAAABJUUZMSU5UIHBmbiAldSB2Zm4gJXU6IGlxZXNpemUgJXUgdG9vIHNtYWxsCgAAAABJUUZM
+SU5UIHBmbiAldSB2Zm4gJXU6IGlxaWQgJXUgdG9vIGxhcmdlIChtYXggJXUpCgAAAAAAAAAAAAAA
+AAAASVFGTElOVCBwZm4gJXUgdmZuICV1OiBpcWlkICV1IG5vdCBhbGxvY2F0ZWQKAAAASVFGTElO
+VCBwZm4gJXUgdmZuICV1OiBmbDBpZCAldSB0b28gbGFyZ2UgKG1heCAldSkKAAAAAAAAAAAAAAAA
+AElRRkxJTlQgcGZuICV1IHZmbiAldTogZmwwaWQgJXUgbm90IGFsbG9jYXRlZAoAAElRRkxJTlQg
+cGZuICV1IHZmbiAldTogZmwxaWQgJXUgdG9vIGxhcmdlIChtYXggJXUpCgAAAAAAAAAAAAAAAABJ
+UUZMSU5UIHBmbiAldSB2Zm4gJXU6IGZsMWlkICV1IG5vdCBhbGxvY2F0ZWQKAABJUUZMSU5UIHBm
+biAldSB2Zm4gJXU6IGZsMWlkICV1IGlzIHZhbGlkIGJ1dCBub3QgZmwwaWQgJXUKAAAAAAAASVFG
+TElOVCBwZm4gJXUgdmZuICV1OiBmbDFpZCAldSBpcyB2YWxpZCBidXQgaGVhZGVyIHNwbGl0IGZl
+YXR1cmUgaXMgbm90IGVuYWJsZWQKAAAAAAAAAAAAAAAAAAAAaHdfdWxwdHhfd29ya2Fyb3VuZF9w
+cjE2OTQ5X2VuYWJsZWRfcGY6IHBmICV1IGVuYWJsZWQgJXUKAAAAAAAAAGh3X3VscHR4X3dvcmth
+cm91bmRfcHIxNjk0OV9lbmFibGVkX3ZmaWQ6IHZmaWQgJXUgZW5hYmxlZCAldQoAAABFUSBwZm4g
+JXUgdmZuICV1OiBjcmVhdGluZyBFVEggZXFpZCAldSB3aXRoIHBlbmRpbmcgV1IocykgKG51bV9i
+eXRlcyAldSBhbmQgZmxhZ3MgMHglMDh4CgAAAAAAAABFUSBwZm4gJXUgdmZuICV1OiBjcmVhdGlu
+ZyBDVFJMIGVxaWQgJXUgd2l0aCBwZW5kaW5nIFdSKHMpIChudW1fYnl0ZXMgJXUgYW5kIGZsYWdz
+IDB4JTA4eAoAAAAAAABFUSBwZm4gJXUgdmZuICV1OiBlcWlkICV1IHRvbyBsYXJnZSAobWF4ICV1
+KQoAAABFUSBwZm4gJXUgdmZuICV1OiBlcWlkICV1IG5vdCBhbGxvY2F0ZWQKAAAAAAAAAABwb3J0
+X2JsaW5rX2xlZF9yZXN0b3JlCgAAAAAAAAAAAHBvcnRfYmxpbms6IGJsaW5rZHVyPTB4JXggYmxp
+bmtfcmVmY250CgAAAAAAAAAAAHBvcnRfYmxpbms6IAlibGlua19yZWZjbnQ9MHgleAoAcG9ydF9i
+bGluazogCWJsaW5rX3JlZmNudD0weCV4CgBtaWlfYW5yZXN0YXJ0WyV1XTogYWNhcHMgMHgleAoA
+AHBvcnRfY21kX2hhbmRsZXI6IHVua25vd24gdS5kY2IudHlwZSAweCV4CgAAAAAAAHBvcnRbJXU6
+MHglMDJ4OjB4JTAyeF06IGwxY2ZnLCBpbnZhbGlkIHJlcXVlc3QsIHBjYXBzIDB4JXggYWNhcHMg
+MHgleCByY2FwcyAweCV4CgAAAAAAAAAAAAAAAAAAAHBvcnRbJXU6MHglMDJ4OjB4JTAyeF06IGwx
+Y2ZnLCBwY2FwcyAlI3ggYWNhcHMgJSN4IHJjYXBzICUjeCBtY2FwcyAlI3gKAAAAAAAAAAAAcG9y
+dFsldToweCUwMng6MHglMDJ4XTogbDFjZmcsIG1kaSBpc3N1ZSBwY2FwcyAweCV4IGFjYXBzIDB4
+JXggcmNhcHMgMHgleAoAAAAAAABwb3J0WyV1OjB4JTAyeDoweCUwMnhdOiBsMWNmZywgY2Fubm90
+IGZvcmNlIG5vL211bHRpcGxlIHNwZWVkKHMpLCBwY2FwcyAweCV4IGFjYXBzIDB4JXggcmNhcHMg
+MHgleAoAAAAAAAAAAAAAAAAAZXRoX2Zsb3djX2hhbmRsZXJbMHgleF06IGZsYWdzIDB4JTA4eCBu
+dW1fYnl0ZXMgJXUgc2NoZWRjbCAweCV4IC0+IDB4JXgKAAAAAAAAAABzY3NpX2NtZDogcmVjZWl2
+ZWQgVE1GIG9wIFsweCV4XSBmdW5jIFsweCV4XSBvbiBjb25uIFsweCV4XSB0aHJvdWdoIGNvbW1h
+bmQgcGF0aC4KAAAAAAAAAAAAAAAAAABzY3NpX2NtZDogY29ubl9mYyBbMHgleF0sIHN0YXRlIFsw
+eCV4XSwgc2Vzc19mYyBbMHgleF0gaW4gcmVjb3ZlcnkuIFNraXBwaW5nIGlzdGFza19mYyBbMHgl
+eF0gZnJvbSBUWC4KAAAAAAAAAAAAc2NzaV9jbWQ6IGlTQ1NJIGNvbW1hbmQgc2VxdWVuY2Ugd2lu
+ZG93IGNsb3NlZC4gY29ubiBbMHgleF0sIG9wIFsweCV4XSwgIGNtZHNuIFsweCV4XSwgc2VudF9j
+bWRzbiBbMHgleF0sIG1heF9jbWRzbiBbMHgleF0sIGl0dCBbMHgleF0KAAAAAAAAAAAAc2NzaV9y
+ZWFkOiBjb25uX2ZjIFsweCV4XSwgc3RhdGUgWzB4JXhdLCBzZXNzX2ZjIFsweCV4XSBpbiByZWNv
+dmVyeS4gU2tpcHBpbmcgaXN0YXNrX2ZjIFsweCV4XSBmcm9tIFRYLgoAAAAAAAAAAHNjc2lfcmVh
+ZDogaVNDU0kgY29tbWFuZCBzZXF1ZW5jZSB3aW5kb3cgY2xvc2VkLiBjb25uIFsweCV4XSwgY21k
+c24gWzB4JXhdLCBzZW50X2NtZHNuIFsweCV4XSwgbWF4X2NtZHNuIFsweCV4XQoAAAAAAAAAAAAA
+AAAAAAAAc2NzaV93cml0ZTogY29ubl9mYyBbMHgleF0sIHN0YXRlIFsweCV4XSwgc2Vzc19mYyBb
+MHgleF0gaW4gcmVjb3ZlcnkuIFNraXBwaW5nIGlzdGFza19mYyBbMHgleF0gZnJvbSBUWC4KAAAA
+AAAAAHNjc2lfd3JpdGU6IGlTQ1NJIGNvbW1hbmQgc2VxdWVuY2Ugd2luZG93IGNsb3NlZC4gY29u
+biBbMHgleF0sIGNtZHNuIFsweCV4XSwgc2VudF9jbWRzbiBbMHgleF0sIG1heF9jbWRzbiBbMHgl
+eF0sIGl0dCBbMHgleF0KAAAAZGNieF9jb250cm9sX3NtWyV1XSBDT05UUk9MX0xJTktVUAoAAAAA
+AAAAAAAAAAAAZGNieF9jb250cm9sX3NtWyV1XSBDT05UUk9MX1VQREFURV9EQ0JYX1RMVgoAAAAA
+ZGNieF9jb250cm9sX3NtWyV1XSBDT05UUk9MX1BFRVJfTk9UX0FEVkVSVElTRV9EQ0JYCgAAAAAA
+AAAAAAAAAGRjYnhfY29udHJvbF9zbVsldV0gQ09OVFJPTF9VUERBVEVfT1BFUl9WRVJTSU9OCgAA
+AAAAAAAAAAAAAAAAAABkY2J4X2NvbnRyb2xfc21bJXVdIENPTlRST0xfUFJPQ0VTU19QRUVSX1RM
+VgoAAABkY2J4X2NvbnRyb2xfc21bJXVdIENPTlRST0xfQUNLX1BFRVIKAAAAAAAAAAAAAABkY2J4
+X2llZWVfdmFsaWRhdGVbJXVdIGVycm9yIChvdWkgJSN4IHN1YnR5cGUgJSN4IGxlbiAlI3gpCgAA
+AAAAZGNieF9jZWVfdmFsaWRhdGVbJXVdIGVycm9yCgAAAABjaG5ldF9sMnRfdXBkYXRlOiBsMmRl
+dl9mYyBbMHgleF0sIGwyZGV2X2ZjLT5mbG93Y19pZCBbJXVdIGwyZGV2X2ZjLT5mbG93Y19mbGFn
+cyBbMHgleF0sIGludGYgWzB4JXhdCgAAAAAAAAAAAAAAY2huZXRfbDJ0X3VwZGF0ZTogbDJkZXZf
+ZmMtPmZsb3djX2lkIFsldV0gYWxyZWFkeSBzY2hlZHVsZWQKAAAAAGNobmV0X2wydF91cGRhdGU6
+IGluIGRlbGF5ZWRfcHJvY2Vzc2luZywgbDJ0ZW50IFslMDh4XQoAAAAAAAAAAABESENQdjYgUkVQ
+TFkgcmVjZWl2ZWQgc3RhdGUgJXUKAGRoY3AgcmVwbHkgcmVjZWl2ZWQgaW4gd3Jvbmcgc3RhdGUg
+JWQKAAAAAAAAAAAAAHVua25vd24gc2VydmVyaWQuIElnbm9yaW5nIGRoY3AgcmVwbHkKAAAAAAAA
+AAAAAHJlY2VpdmVkIHJlcGx5IHdpdGggZGlmZmVyZW50IGFkZHJlc3MuIGlnbm9yaW5nIGRoY3Ag
+cmVwbHkKAAAAAABESENQdjYgQURWRVJUSVNFIHJlY2VpdmVkCgAAAAAAAGRoY3AgYWR2ZXJ0aXNl
+IHJlY2VpdmVkIGluIHdyb25nIHN0YXRlICVkCgAAAAAAAGlnbm9yaW5nIHJjdmQgYWR2ZXJ0aXNl
+IHByZWZlcmVuY2UgJXUKAAAAAAAAAAAAAHByZWZpeCBub2RlIDB4JXgsIHZhbGlkX2xpZmV0aW1l
+ICV1LCBjdXJyZW50X3RpbWUgJXUgZXhwaXJlZCwgZGVsZXRpbmcgaXQKAAAAAAAARGVsZXRlZCBw
+cmVmaXg6IDB4WyUwNHggJTA0eCAlMDR4ICUwNHhdCgAAAAAAAAAAU3RhcnQgREhDUHY2IHRvIGdl
+dCB0aGUgaXAgYWRkcmVzcwoAAAAAAAAAAAAAAAAATm8gZGhjcCwgZGhjcCBzdGF0ZSAlZCwgYWRk
+ciBzdGF0ZSAlZAoAAAAAAAAAAAAAcGluZyByZXEgcGF5bG9hZCB0b28gbGFyZ2UgJXUuIElnbm9y
+aW5nIHJlcS4KAAAAUlIgcmN2ZAoAAAAAAAAAAGNobmV0X2lwdjZfcmRfaW5wdXQ6IEludmFsaWQg
+UmVkaXJlY3QKAAAAAAAAAAAAAGNobmV0X2lwdjZfbmFfaW5wdXQ6IEludmFsaWQgTkEKAAAAAAAA
+AAAAAAAAAAAAAGlwdjYgTkEgcmN2ZAoAAABjaG5ldF9pcHY2X25hX2lucHV0OiBEdXBsaWNhdGUg
+YWRkcmVzcyBkZXRlY3RlZCEKAAAAAAAAAAAAAAAAAAAATkEgaW4gcmVwb25zZSBvZiBOUwoAAAAA
+AAAAAAAAAABjaG5ldF9pcHY2X25zX2lucHV0OiBJbnZhbGlkIE5TCgAAAAAAAAAAAAAAAAAAAABj
+aG5ldF9pcHY2X25zX2lucHV0OiBJbnZhbGlkIE5TIGlwdjZoLT5wbGVuICV1CgBpcHY2IE5TIHJj
+dmQKAAAAY2huZXRfaXB2Nl9uc19pbnB1dDogRHVwbGljYXRlIGFkZHJlc3MgZGV0ZWN0ZWQKAAAA
+AAAAAAAAAAAAAAAAAGNobmV0X2lwdjZfbnNfaW5wdXQ6IHNvbWVib2R5IHRyeWluZyB0byB1c2Ug
+b3VyIGFkZHJlc3MKAAAAAAAAAABjaG5ldF9pcHY2X25zX2lucHV0OiByZXEgZm9yIGFkZHIgcmVz
+b2x1dGlvbgoAAABIb3AgYnkgSG9wIG9wdGlvbgoAAAAAAAAAAAAAAAAAAHByb2Nlc3NfZGhjcF9v
+cHRzOiByb290IHBhdGggbGVuIFslZF0gYnl0ZXMKAAAAAG5ldGlmX3Byb2Nlc3NfZGhjcF9vcHRz
+OiBsMmRldl9mYy0+Zmxvd2NfaWQgWzB4JXhdLCBNU0dfVFlQRSBbJWRdLCBkaGN0eHQtPnN0YXRl
+IFslZF0KAAAAAAAAAAAAAGljbXBfcmVjdjogbDJkZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgcGlk
+IFsweCV4XSwgaWNtcCB0eXBlIFsweCV4XQoAAAAAAAAAAAAAAAAAQUJUUyBBQ0MgYXdhaXRpbmcg
+UFJMSSBSc3A6IGZsb3djX2lkIDB4JXggb3hfaWQgMHgleCByeF9pZCAweCV4IGlxaWQgMHgleAoA
+AAAAAABwb3J0IDB4JXgsIHN0YXRlIDB4JXgsIGNvbW1hbmQgZmFpbGVkIHJldHJpZXMgMHgleAoA
+AAAAAAAAAAAAAAAAYXJwX3JlY3Y6IGlwaWQgWzB4JXhdLCBpbl9hZGRyLmFkZHIgWzB4JXhdLCBz
+aXAgWzB4JXhdLCByaXAgWzB4JXhdLCBhcnBfb3AgWzB4JXhdCgAAAAAAAAAAAAAAAAAAY2huZXRf
+YXJwX3JlY3Y6IGlwIGNvbmZsaWN0IGRldGVjdGVkCgAAAAAAAAAAAAAAY2huZXRfYXJwX3JlY3Y6
+IHBpZCBbJXVdLCB2bGFuIFsweCV4XSwgYXJwIG9wIFsweCV4XSwgc2lwIFsweCV4XSwgcmlwIFsw
+eCV4XQoAAABjaG5ldF9pcHY2X3JlY3Y6IHZsYW4gZXh0cmFjdGVkLCB2bGFuaWQgWyV1XSwgbDJk
+ZXZfZmMtPmZsb3djX25ldF9sMmRldl92bGFuZGV2IFsweCV4XQoAAAAAAAAAAABJbnZhbGlkIGRh
+dGEgbGVuZ3RoIGRsZW4gJXUsIHBhY2tldCBpbmRpY2F0ZXMgJXUgYnl0ZXMKAAAAAAAAAAAAVW5r
+bm93biBJUHY2IG54dCBwcm90b2NvbCAldQoAAABJbnZhbGlkIGRpZDp4JTJ4JTJ4JTJ4IHJjdmQg
+b24gcG9ydDolZC5Ecm9waW5nIGZyYW1lCgAAAAAAAAAAAAAAcmN0OngleCBzaWQ6eCUyeCUyeCUy
+eCByY3ZkIG9uIGZsb3djOiVkLkRyb3BpbmcgZnJhbWUKAAAAAAAAAAAAAGNzb2NrX2ZyZWU6IHNp
+emVvZihjc2tfZmMtPnUuY3NvY2spIFsldV0sIGJ5dGVzCgAAAAAAAAAAAAAAAAAAAABHb3QgQ09O
+Tl9FWElTVCBmb3IgeGlkOjB4JXgsIHRhZzoweCV4LCByZXRyeWluZy4KAAAAAAAAAAAAAAAAAAAA
+Y3NvY2tfcGVlcl9jbG9zZTogY3NrX2ZjLT5mbG93Y19pZCBbMHgleF0sIHRjYl9mYy0+Zmxvd2Nf
+aWQgWzB4JXhdLCBjc2tfZmMtPmZsb3djX3N0YXRlIFsweCV4XSwgdGNiX2ZjLT5mbG93Y19zdGF0
+ZSBbMHgleF0KAAAAAABjc29ja19wZWVyX2Nsb3NlOiBjc2tfZmMtPmZsb3djX2lkIFsweCV4XSwg
+Y3NrX2ZjLT5mbG93Y19zdGF0ZSAgWzB4JXhdCgAAAAAAAAAAAHRjcF9jbHNfYWJydF9ycGw6IHRj
+YiB0aWQgWzB4JTA2eF0sIGZsb3djX3R5cGUgWzB4JXhdLCBjcGxvcCBbMHgleF0gCgAAAAAAAAAA
+AAAAY2hfcmF0ZVsldV06IGNhcHBlZCB0aWNrIGZyb20gcmVxdWlyZWQgJXUgdG8gc3VwcG9ydGVk
+ICV1OyByYXRlICV1IChlZmYgJXUpIGRlZmljaXRfaW5jciAldSB0aWNrICV1CgAAAAAAAAAAAAAA
+AHBrdHNjaGVkX2NoX3JsWyV1XTogY2hhbm5lbCBybCBub3QgYXZhaWxhYmxlIGluIGNvbmp1bmN0
+aW9uIHdpdGggZmxvdyBzaGFwaW5nCgAAcGt0c2NoZWRfY2hfcmxbJXVdOiByYXRlICV1IG1heCAl
+dQoAAAAAAAAAAAAAAAAAcGt0c2NoZWRfY2xfd3JyWyV1OiV1XTogd2VpZ2h0ICV1CgAAAAAAAAAA
+AAAAAAAAZXFfcGFyYW1zWzB4JXg6MHgleF06IGRtYXEgMHgleCByZWFkICV1IHBmICV1IGVxaWRf
+YXBpICV1IHJldCAlZAoAAAAAAAAAAAAAAAAAAABNQyBDTEsgc2V0dGluZyBmYWlsZWQ6IFBMTF9N
+X0xPQ0sgbmV2ZXIgdG9nZ2xlZAoAAAAAAAAAAAAAAAAAAAAAd2FpdF9mb3JfY2FsaWJfZG9uZTog
+cmV0ICVkIGluICV1IGF0dGVtcHRzCgAAAAAAaHdfbWFfYWRkcl90b19tZW1fdHlwZV9vZmY6IE1B
+IGFkZHJlc3MgMHglMDh4IGlzIG5vdCBtYXBwZWQKAAAAAGh3X21hX2FkZHJfdG9fbWVtX3R5cGVf
+b2ZmOiBNQSBhZGRyZXNzIDB4JTA4eCBtYXBzIHRvIHR5cGUgJXUgb2Zmc2V0IDB4JXgKAAAAAAAA
+bWVtX21hbGxvY190ZW1wOiBmYWlsZWQgdG8gYWxsb2NhdGUgJXUgYnl0ZXMsIHJldHVybmluZyBO
+VUxMCgAAAG1lbV9tYWxsb2M6IGZhaWxlZCB0byBhbGxvY2F0ZSAldSBieXRlcywgcmV0dXJuaW5n
+IE5VTEwKAAAAAAAAAABsZSBjb25maWd1cmF0aW9uOiBoYXNoIG1vZGUgcmVxdWlyZXMgYXQgbGVh
+c3QgMTYgZW50cmllcywgbmhhc2ggJXUKAAAAAAAAAAAAAAAAAGxlIGNvbmZpZ3VyYXRpb246IGhh
+c2ggbW9kZSByZXF1aXJlcyBhdCBlbnRyaWVzIHRvIGJlIGEgcG93ZXIgb2YgMiwgbmhhc2ggJXUK
+AAAAbGUgY29uZmlndXJhdGlvbjogcmVxdWVzdGVkICV1IHRjYW0gZW50cmllcyBidXQgb25seSAl
+dSBhdmFpbGFibGUgKG5yb3V0ZSAldSBuY2xpcCAldSBuZmlsdGVyICV1IG5zZXJ2ZXIgJXUKAAAA
+AGxlIGNvbmZpZ3VyYXRpb246IHRjYW0gcmVnaW9ucyBtdXN0IGhhdmUgbXVsdGlwbGUgb2YgMzIg
+ZW50cmllcywgbnJvdXRlICV1IG5jbGlwICV1IG5maWx0ZXIgJXUgbnNlcnZlciAldQoAAAAAAABo
+d190cF90Y3BfdHVuaW5nczogdHVuaW5nIGZvciBjbHVzdGVyIGVudmlyb25tZW50CgAAAAAAAAAA
+AAAAAAAAaHdfdHBfdGNwX3R1bmluZ3M6IHR1bmluZyBmb3IgTEFOIGVudmlyb25tZW50CgAAaHdf
+dHBfdGNwX3R1bmluZ3M6IHR1bmluZyBmb3IgV0FOIGVudmlyb25tZW50CgAAaHdfdHBfdGNwX3R1
+bmluZ3M6IG1hbnVhbCB0dW5pbmcKAAAAAAAAAAAAAAAAAAAAX2h3X2NpbV9mbGFzaF9tZW1jcHk6
+IG1lbWNweVggc3RhcnQKAAAAAAAAAAAAAAAAX2h3X2NpbV9mbGFzaF9tZW1jcHk6IGRzdCAweCUw
+OCBvZmZzZXQgMHglMDh4IHNpemUgJXUsIHdpZHRoIG9mICV1IGlzIG5vdCBzdXBwb3J0ZWQKAAAA
+AAAAAAAAAAAAX2h3X2NpbV9mbGFzaF9tZW1jcHk6IG1lbWNweVggZW5kCgAAAAAAAAAAAAAAAAAA
+Y29uZmlndXJhdGlvbiBmaWxlIHBhcnNlciBlbmNvdW50ZXJlZCBlcnJvciBAIGxpbmUgJXU6CgAA
+AAAAAAAAAEhPU1QgUEFHRV9TSVpFIFsweCUwbHhdIHRvbyBzbWFsbCwgbWluIFsweCUwbHhdIHJl
+cXVpcmVkCgAAAAAAAABwYWdlIHNpemUgWyVsdV0gbWlzbWF0Y2gKAAAAAAAAAFBBR0Ugc2l6ZSAl
+bHUgdW5zdXBwb3J0ZWQsIGRkcCBkaXNhYmxlZAoAAAAAAAAAAEhvc3QgcGFnZV9zaXplICVsdSwg
+ZGRwX2lkeCAldQoARkNvRSBERFAgaW5pdDogZmNvZSBsbGltaXQgMHgleCwgZmNvZSB1bGltaXQg
+MHgleCBnYmwgbGxpbWl0IDB4JXggZ2JsIHVsaW1pdCAweCV4IHBjYnN6ICV4CgAAAAAARkNvRSBE
+RFAgaW5pdDogZmNvZSBwcG9kIG9mZiAweCV4LCBmY29lIHN0IHBwb2QgYWRkciAweCV4IGZjb2Ug
+bnVtIHBwb2RzIDB4JXgKAABmY29lIHhjaGcgbWdyIGluaXQ6IE51bWJlciBvZiBERFAgZXhjaGFu
+Z2VzIGZvciBGQ29FIGlzICV4CgAAAAAAZmNvZSB4Y2hnIG1nciBpbml0OiBOdW1iZXIgb2YgdHVu
+bmVsIGV4Y2hzIGZvciBGQ29FIGlzICV4CgAAAAAAAGZjb2VfbDJ0X2luaXQ6IE5vIHVscHR4IGNy
+ZWRpdCBjaDpbJXVdCgAAAAAAAAAAAGZjb2VfbDJ0X2luaXQ6IGNoOlsldV0gbDJ0X2lkeCBbJXVd
+CgAAAAAAAAAAAAAAAG5vIGwydCBlbnRyaWVzIGNvbmZpZ3VyZWQ7IGZvcmNpbmcgJXUgZW50cmll
+cywgc3RhcnRpbmcgYXQgJXUKAABkY2J4IHVwZGF0ZVsldV0gc2VudCB0byBkcml2ZXIgKHR5cGUg
+JSN4IHN1YnR5cGUgJSN4IGZsb3djaWQgJXUpCgAAAAAAAAAAAAAAAAAAAGRjYnhfcnVuX3ZlcnNp
+b25fc21bJXVdIERDQlhfVkVSX1NUQVRFX1JVTl9JRUVFCgAAAAAAAAAAAAAAAAAAAABkY2J4X3J1
+bl92ZXJzaW9uX3NtWyV1XSBEQ0JYX1ZFUl9TVEFURV9SVU5fQ0VFCgBkY2J4X3J1bl92ZXJzaW9u
+X3NtWyV1XSBEQ0JYX1ZFUl9TVEFURV9SVU5fTk9ORQoAAAAAAAAAAAAAAAAAAAAATUFDIGZhaWxl
+ZCB0byByZXN5bmMgdHgKAAAAAAAAAABwb3J0WyV1XSBsaW5rIHVwICgldSkgKHNwZWVkICUjeCBh
+Y2FwcyAlI3ggbHBjYXBzICUjeCkKAAAAAAAAAAAAcG9ydF9oc3Nfc2lnZGV0WyV1XTogaHNzX3Np
+Z2RldCBjaGFuZ2VkIHRvIDB4JXgKAAAAAAAAAAAAAAAAAAAAAHBvcnRbJXVdIGluaXRpYWxpemlu
+ZyBLUgoAAAAAAAAAZGlzYWJsaW5nIHR4ICUjeCByeCAlI3gKAAAAAAAAAABDYWxjdWxhdGlvbiBv
+dXQgb2YgYm91bmRzIGZ1cmluZyBpbml0OiAlI3ggJSN4ICUjeAoAAAAAAAAAAAAAAAAAX2h3X3Rw
+X3BnbW5ndDogdHhfcGFnZV9tYXggJXUgcnhfcGFnZV9tYXggJXUgcHN0cnVjdHMgJXUgc2l6ZSAl
+dQoAAAAAAAAAAAAAAAAAAABtcGFydGl0aW9uX290aGVyc190b3RhbDogZGRwICV1IGRkcF9pc2Nz
+aSAldSBzdGFnICV1IHBibCAldSBycSAldSBycXVkcCAldSAtPiAldQoAAAAAAAAAAAAAAAAAAABf
+bXBhcnRpdGlvbl9iYW5rc19tY1g6IG5iYW5rc19wbXR4ICV1ICgldU1CKSBuYmFua3NfcG1yeCAl
+dSAoJXVNQikgbmJhbmtzX290aGVycyAldSAoJXVNQikgbmJhbmtzX2Z3ICV1ICgldU1CKQoAX21w
+YXJ0aXRpb25fYmFua3NfbWMxOiBuYmFua3NfcG10eCAldSAoJXVNQikgbmJhbmtzX290aGVycyAl
+dSAoJXVNQikgbmJhbmtzX2Z3ICV1ICgldU1CKQoAAAAAAAAAX21wYXJ0aXRpb25fYmFua3NfbWMw
+OiBuYmFua3NfcG1yeCAldSAoJXVNQikgbmJhbmtzX290aGVycyAldSAoJXVNQikKAAAAAAAAAAAA
+AABtZW1fbWFsbG9jX2ludGVybmFsOiBmYWlsZWQgdG8gYWxsb2NhdGUgJXUgYnl0ZXMsIHJldHVy
+bmluZyBOVUxMCgAAAAAAAAAAAAAAAAAAAGh3X2VkY19iaXN0WyV1XTogYmlzdF9jbWRbMHglMDh4
+XSBhZGRyIDB4JXggbGVuIDB4JXgKAAAAAAAAAAAAAABod19lZGNfYmlzdFsldV06IGRvbmUsIGVu
+Y291bnRlcmVkICV1IGVycm9ycyBvbiBmaXJzdCBhbmQgJXUgZXJyb3JzIG9uIHNlY29uZCBhdHRl
+bXB0ICgldWdicHMpCgBtZW1faW5pdF9jYWNoZXM6IGNhY2hlX3NpemUgJXUgZmxvd2NfYnVmX3Rj
+Yl9jYWNoZV9zaXplICV1IGJ1ZmxsNjRfY2FjaGVfc2l6ZSAldQoAAAAAAAAAAAAAAAAAAABtcGFy
+dGl0aW9uX3BtdHg6IG0gMHglMDh4IHNpemUgJXUKAAAAAAAAAAAAAAAAAABtcGFydGl0aW9uX3Bt
+cng6IG0gMHglMDh4IHNpemUgJXUKAAAAAAAAAAAAAAAAAABtcGFydGl0aW9uX2VkYyAobm8gZXh0
+bWVtKTogbSAweCUwOHggc2l6ZSAldQoAAABtcGFydGl0aW9uX2VkY19lc3RpbWF0ZTogaHcgbW9k
+dWxlcyByZXF1aXJlICVkIGJ5dGVzIGluIEVEQwoAAAAAVGVtcGVyYXR1cmUvVm9sdGFnZSBTZW5z
+b3I6IENvcmUgY2xvY2sgJWQgPiA1MDA7IHVzaW5nIDUwMCB0byBzdGF5IGluIGNvbXBsaWFuY2Ug
+d2l0aCBoYXJkd2FyZS4KAAAAAAAAAAAAAAAAAAAAAGNobmV0X2J5ZTpsMmRldl9mYy0+Zmxvd2Nf
+aWQgWzB4JXhdLCBsMmRldl9mYy0+Zmxvd2NfcGNpZV9wZm4gWzB4JXhdLCBsMmRldl9mYy0+Zmxv
+d2NfcGNpZV92Zm4gWzB4JXhdLCBwb3J0IFsweCV4XQoAAAAAAAAAAAAAAAAAY2huZXRfYnllOnZs
+YW5kZXZfZmMtPmZsb3djX2lkIFsweCV4XSwgdmxhbmRldl9mYy0+Zmxvd2NfcGNpZV9wZm4gWzB4
+JXhdLCB2bGFuZGV2X2ZjLT5mbG93Y19wY2llX3ZmbiBbMHgleF0sIHBvcnQgWzB4JXhdCgAAAAAA
+AABod19tYWNfYWVjX2NvbXBsZXRlWyV1XSBvbiBsYW5lcyAlI3ggKHNpZ2RldCAlI3gpCgAAAAAA
+AAAAAAAAAAAAYWVjX2ZzbVsldV0gOiBzdGF0ZSBTVEFSVCAoc2lnZGV0ICUjeCkKAAAAAAAAAAAA
+YWVjX2ZzbVsldV0gOiB0cmFuc2l0aW9uaW5nIHRvIFRSQUlOSU5HCgAAAAAAAAAAYWVjX2ZzbVsl
+dV0gOiBUUkFJTklOR19DT01QTEVURQoAAAAAAAAAAAAAAAAAAAAAYWVjX2ZzbVsldV0gOiBET05F
+CgAAAAAAAAAAAAAAAABhZWNfZnNtWyV1XSA6IHRpbWVkIG91dCB0cmFpbmluZwoAAAAAAAAAAAAA
+AAAAAABiZWFuX2ZzbVsldV0gOiBzdGF0ZSBTVEFSVCAoY291bnQgPSAldSkKAAAAAAAAAABiZWFu
+X2ZzbVsldV0gOiBlbnRlcmluZyBzdGF0ZSBXQUlUX1NJR0RFVAoAAAAAAABiZWFuX2ZzbVsldV0g
+OiBlbnRlcmluZyBzdGF0ZSBOWFBfSEFORExFCgAAAAAAAABiZWFuX2ZzbVsldV0gOiBlbnRlcmlu
+ZyBzdGF0ZSBXQUlUX0NPTVBMRVRFCgAAAABiZWFuX2ZzbVsldV0gOiBzdGF0ZSBET05FCgAAAAAA
+AGJlYW5fZnNtWyV1XSA6IHN0YXRlIFJFU1RBUlQKAAAAYmVhbl9mc21bJXVdIFRJTUVPVVQ7IHN0
+YXRlICV1IGV0aF9zdGF0dXMgJSN4IGJlYW5fc3RhdHVzICUjeCBoc3Mgc2lnZGV0ICUjeCByZXRy
+eV9jbnQgJXUKAAAAAAAAcG9ydCAldSBuZWdvdGlhdGVkIHVuc3VwcG9ydGVkIHNwZWVkICUjeAoA
+AAAAAAAAYmVhbi9hZWMgY29tcGxldGUgKHJldHJ5OiAldSkKAABwb3J0WyV1XSByZXNldHRpbmcg
+S1IKAAAAAAAAAAAAAFJhbmdlIGNhbGM6IEF2ZXJhZ2VkICUjeCBidXQgaWdub3JlZCB2YWx1ZSAl
+I3ggKGl0ZXJhdGlvbiAldSkKAABNQyBjYWxpYnJhdGlvbiBmYWlsZWQ6IERGSSBpbml0IG5vdCBn
+b2luZyB0byAwCgBNQyBjYWxpYnJhdGlvbiBmYWlsZWQ6IERGSSBpbml0IG5vdCBjb21wbGV0aW5n
+CgBNQyBjYWxpYnJhdGlvbiBmYWlsZWQ6IENhbGlicmF0aW9uIGRpZG4ndCBjb21wbGV0ZS4KAAAA
+AAAAAAAAAAAATUMgY29tbWFuZCBmYWlsZWQgdG8gY29tcGxldGUob3Bjb2RlICUjeCBjYWRkciAl
+I3ggYmFkZHIgJSN4IGRlbGF5ICVkKQoAAAAAAAAAAABwZm5fYml0bWFwIDB4JXgKAAAAAAAAAAAA
+AAAAAAAAAGJhZCBtYWlsYm94IGNtZDogcGZuIDB4JXggdmZuIDB4JXg7IG9wY29kZSAweCV4ID4g
+TEFTVEMyRSAweCV4CgBtYWlsYm94IGNtZCBub3QgeWV0IHN1cHBvcnRlZDogcGZuIDB4JXggdmZu
+IDB4JXg7IG9wY29kZSAweCV4CgAAYmFkIG1haWxib3ggY21kOiBwZm4gMHgleCB2Zm4gMHgleDsg
+b3Bjb2RlIDB4JXggaXMgdmFsaWQgcG9zdCBkZXZpY2UgaW5pdCBvbmx5CgBiYWQgbWFpbGJveCBj
+bWQ6IHBmbiAweCV4IHZmbiAweCV4OyBvcGNvZGUgMHglMDJ4IHJhbWFzayAweCV4IGNtZCByYW1h
+c2sgMHgleAoAAGJhZCBtYWlsYm94IGNtZDogcGZuIDB4JXggdmZuIDB4JXg7IG9wY29kZSAweCUw
+MnggbGVuMTYgMHgleCB2ZXJzdXMgZXhwZWN0ZWQgbGVuMTYgMHgleAoAAAAAAAAAAGluc3VmZmlj
+aWVudCBjYXBzIHRvIHByb2Nlc3MgbWFpbGJveCBjbWQ6IHBmbiAweCV4IHZmbiAweCV4OyByX2Nh
+cHMgMHgleCB3eF9jYXBzIDB4JXggcmVxdWlyZWQgcl9jYXBzIDB4JXggd19jYXBzIDB4JXgKAAAA
+AAAAAAAAaW5zdWZmaWNpZW50IGNhcHMgdG8gcHJvY2VzcyBtYWlsYm94IGNtZDogcGZuIDB4JXgg
+dmZuIDB4JXg7IHJfY2FwcyAweCV4IHd4X2NhcHMgMHgleCByZXF1aXJlZCByX2NhcHMgMHgleCB3
+X2NhcHMgMHgleAoAAAAAAAAAAABod19wb3dlcl9wcmVwOiBWREQ9Tk9ORSBidXQgVkNTPSVkCgAA
+AAAAAAAAAAAAAABod19wb3dlcl9wcmVwOiB1bnN1cHBvcnRlZCBleHRlcm5hbCBhZGp1c3RhYmxl
+IHBvd2VyIHJlZ3VsYXRvcnMgVkREPSVkLCBWQ1M9JWQKAGh3X3Bvd2VyX3ByZXA6IHVuc3VwcG9y
+dGVkIFZERD0lZAoAAAAAAAAAAAAAAAAAAGh3X3Bvd2VyX3ByZXA6IHVuc3VwcG9ydGVkIFZDUz0l
+ZAoAAAAAAAAAAAAAAAAAAGh3X3Bvd2VyX3ByZXA6IGkyYyB3cml0ZSBlcnJvciwgVkREPSVkLHJl
+dD0lZAoAAGh3X3Bvd2VyX3ByZXA6IHVuc3VwcG9ydGVkIFZERD0lZAoAAAAAAAAAAAAAAAAAAGh3
+X3Bvd2VyX3ByZXA6IGkyYyB3cml0ZSBlcnJvciwgVkNTPSVkLHJldD0lZAoAAGh3X3Bvd2VyX3By
+ZXA6IHVuc3VwcG9ydGVkIFZDUz0lZAoAAAAAAAAAAAAAAAAAAFZQRCByZWdpb24gaXMgdG9vIHNt
+YWxsIChTRVJDRkdfU1JfUEZOVlBEU0laRSAweCV4KQoAAAAAAAAAAAAAAABjZjogZmFpbGVkIHRv
+IGFsbG9jYXRlZCBtZW1vcnkgZm9yIGNvbmZpZ3VyYXRpb24gZmlsZSwgcmV0ICVkCgAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 8c96715..442643e 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -585,9 +585,7 @@ t4_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
-#ifdef INVARIANTS
- sc->debug_flags = DF_DUMP_MBOX;
-#endif
+ TUNABLE_INT_FETCH("hw.cxgbe.debug_flags", &sc->debug_flags);
pci_enable_busmaster(dev);
if (pci_find_cap(dev, PCIY_EXPRESS, &i) == 0) {
diff --git a/sys/dev/cxgbe/tom/t4_connect.c b/sys/dev/cxgbe/tom/t4_connect.c
index 425c563..fae7979 100644
--- a/sys/dev/cxgbe/tom/t4_connect.c
+++ b/sys/dev/cxgbe/tom/t4_connect.c
@@ -189,12 +189,12 @@ act_open_failure_cleanup(struct adapter *sc, u_int atid, u_int status)
toep->tid = -1;
if (status != EAGAIN)
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
toe_connect_failed(tod, inp, status);
final_cpl_received(toep); /* unlocks inp */
if (status != EAGAIN)
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
}
static int
diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c
index 147802d..eb972d0 100644
--- a/sys/dev/cxgbe/tom/t4_cpl_io.c
+++ b/sys/dev/cxgbe/tom/t4_cpl_io.c
@@ -1085,7 +1085,7 @@ do_peer_close(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
KASSERT(toep->tid == tid, ("%s: toep tid mismatch", __func__));
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
tp = intotcpcb(inp);
@@ -1127,7 +1127,7 @@ do_peer_close(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
case TCPS_FIN_WAIT_2:
tcp_twstart(tp);
INP_UNLOCK_ASSERT(inp); /* safe, we have a ref on the inp */
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
INP_WLOCK(inp);
final_cpl_received(toep);
@@ -1139,7 +1139,7 @@ do_peer_close(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
}
done:
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (0);
}
@@ -1166,7 +1166,7 @@ do_close_con_rpl(struct sge_iq *iq, const struct rss_header *rss,
KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__));
KASSERT(toep->tid == tid, ("%s: toep tid mismatch", __func__));
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
tp = intotcpcb(inp);
@@ -1184,7 +1184,7 @@ do_close_con_rpl(struct sge_iq *iq, const struct rss_header *rss,
tcp_twstart(tp);
release:
INP_UNLOCK_ASSERT(inp); /* safe, we have a ref on the inp */
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
INP_WLOCK(inp);
final_cpl_received(toep); /* no more CPLs expected */
@@ -1208,7 +1208,7 @@ release:
}
done:
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (0);
}
@@ -1367,7 +1367,7 @@ do_abort_req(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
}
inp = toep->inp;
- INP_INFO_WLOCK(&V_tcbinfo); /* for tcp_close */
+ INP_INFO_RLOCK(&V_tcbinfo); /* for tcp_close */
INP_WLOCK(inp);
tp = intotcpcb(inp);
@@ -1401,7 +1401,7 @@ do_abort_req(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
final_cpl_received(toep);
done:
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
send_abort_rpl(sc, ofld_txq, tid, CPL_ABORT_NO_RST);
return (0);
}
@@ -1515,12 +1515,12 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m)
SOCKBUF_UNLOCK(sb);
INP_WUNLOCK(inp);
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
tp = tcp_drop(tp, ECONNRESET);
if (tp)
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (0);
}
diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c
index fc5f935..127abe0 100644
--- a/sys/dev/cxgbe/tom/t4_listen.c
+++ b/sys/dev/cxgbe/tom/t4_listen.c
@@ -930,7 +930,7 @@ t4_offload_socket(struct toedev *tod, void *arg, struct socket *so)
struct cpl_pass_establish *cpl = mtod(synqe->syn, void *);
struct toepcb *toep = *(struct toepcb **)(cpl + 1);
- INP_INFO_LOCK_ASSERT(&V_tcbinfo); /* prevents bad race with accept() */
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo); /* prevents bad race with accept() */
INP_WLOCK_ASSERT(inp);
KASSERT(synqe->flags & TPF_SYNQE,
("%s: %p not a synq_entry?", __func__, arg));
@@ -1259,15 +1259,15 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
REJECT_PASS_ACCEPT();
rpl = wrtod(wr);
- INP_INFO_WLOCK(&V_tcbinfo); /* for 4-tuple check */
+ INP_INFO_RLOCK(&V_tcbinfo); /* for 4-tuple check */
/* Don't offload if the 4-tuple is already in use */
if (toe_4tuple_check(&inc, &th, ifp) != 0) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
free(wr, M_CXGBE);
REJECT_PASS_ACCEPT();
}
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
inp = lctx->inp; /* listening socket, not owned by TOE */
INP_WLOCK(inp);
@@ -1441,7 +1441,7 @@ do_pass_establish(struct sge_iq *iq, const struct rss_header *rss,
unsigned int tid = GET_TID(cpl);
struct synq_entry *synqe = lookup_tid(sc, tid);
struct listen_ctx *lctx = synqe->lctx;
- struct inpcb *inp = lctx->inp;
+ struct inpcb *inp = lctx->inp, *new_inp;
struct socket *so;
struct tcphdr th;
struct tcpopt to;
@@ -1459,7 +1459,7 @@ do_pass_establish(struct sge_iq *iq, const struct rss_header *rss,
KASSERT(synqe->flags & TPF_SYNQE,
("%s: tid %u (ctx %p) not a synqe", __func__, tid, synqe));
- INP_INFO_WLOCK(&V_tcbinfo); /* for syncache_expand */
+ INP_INFO_RLOCK(&V_tcbinfo); /* for syncache_expand */
INP_WLOCK(inp);
CTR6(KTR_CXGBE,
@@ -1475,7 +1475,7 @@ do_pass_establish(struct sge_iq *iq, const struct rss_header *rss,
}
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (0);
}
@@ -1500,7 +1500,7 @@ reset:
*/
send_reset_synqe(TOEDEV(ifp), synqe);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (0);
}
toep->tid = tid;
@@ -1534,6 +1534,10 @@ reset:
goto reset;
}
+ /* New connection inpcb is already locked by syncache_expand(). */
+ new_inp = sotoinpcb(so);
+ INP_WLOCK_ASSERT(new_inp);
+
/*
* This is for the unlikely case where the syncache entry that we added
* has been evicted from the syncache, but the syncache_expand above
@@ -1544,20 +1548,18 @@ reset:
* this somewhat defeats the purpose of having a tod_offload_socket :-(
*/
if (__predict_false(!(synqe->flags & TPF_SYNQE_EXPANDED))) {
- struct inpcb *new_inp = sotoinpcb(so);
-
- INP_WLOCK(new_inp);
tcp_timer_activate(intotcpcb(new_inp), TT_KEEP, 0);
t4_offload_socket(TOEDEV(ifp), synqe, so);
- INP_WUNLOCK(new_inp);
}
+ INP_WUNLOCK(new_inp);
+
/* Done with the synqe */
TAILQ_REMOVE(&lctx->synq, synqe, link);
inp = release_lctx(sc, lctx);
if (inp != NULL)
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
release_synqe(synqe);
return (0);
diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c
index a980fba..d0a2488 100644
--- a/sys/dev/cxgbe/tom/t4_tom.c
+++ b/sys/dev/cxgbe/tom/t4_tom.c
@@ -36,9 +36,11 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
+#include <sys/lock.h>
#include <sys/module.h>
#include <sys/protosw.h>
#include <sys/domain.h>
+#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/taskqueue.h>
@@ -762,6 +764,7 @@ t4_clip_task(void *arg, int count)
static void
update_clip_table(struct adapter *sc, struct tom_data *td)
{
+ struct rm_priotracker in6_ifa_tracker;
struct in6_ifaddr *ia;
struct in6_addr *lip, tlip;
struct clip_head stale;
@@ -770,7 +773,7 @@ update_clip_table(struct adapter *sc, struct tom_data *td)
ASSERT_SYNCHRONIZED_OP(sc);
- IN6_IFADDR_RLOCK();
+ IN6_IFADDR_RLOCK(&in6_ifa_tracker);
mtx_lock(&td->clip_table_lock);
if (gen == td->clip_gen)
@@ -862,7 +865,7 @@ next:
td->clip_gen = gen;
done:
mtx_unlock(&td->clip_table_lock);
- IN6_IFADDR_RUNLOCK();
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
}
static void
diff --git a/sys/dev/drm2/i915/i915_drv.h b/sys/dev/drm2/i915/i915_drv.h
index 0a79d3b..fd1aa14 100644
--- a/sys/dev/drm2/i915/i915_drv.h
+++ b/sys/dev/drm2/i915/i915_drv.h
@@ -1151,8 +1151,6 @@ void i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
void i915_destroy_error_state(struct drm_device *dev);
/* i915_gem.c */
-int i915_gem_create(struct drm_file *file, struct drm_device *dev, uint64_t size,
- uint32_t *handle_p);
int i915_gem_init_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int i915_gem_create_ioctl(struct drm_device *dev, void *data,
@@ -1243,7 +1241,6 @@ int i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj);
int i915_gem_flush_ring(struct intel_ring_buffer *ring,
uint32_t invalidate_domains, uint32_t flush_domains);
void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
-int i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj);
int i915_gem_object_sync(struct drm_i915_gem_object *obj,
struct intel_ring_buffer *to);
int i915_gem_object_put_fence(struct drm_i915_gem_object *obj);
diff --git a/sys/dev/drm2/i915/i915_gem.c b/sys/dev/drm2/i915/i915_gem.c
index 356ccc5..1b45917 100644
--- a/sys/dev/drm2/i915/i915_gem.c
+++ b/sys/dev/drm2/i915/i915_gem.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <dev/drm2/i915/i915_drv.h>
#include <dev/drm2/i915/intel_drv.h>
#include <dev/drm2/i915/intel_ringbuffer.h>
+
#include <sys/resourcevar.h>
#include <sys/sched.h>
#include <sys/sf_buf.h>
@@ -69,38 +70,40 @@ __FBSDID("$FreeBSD$");
#include <machine/md_var.h>
-static void i915_gem_object_flush_cpu_write_domain(
- struct drm_i915_gem_object *obj);
-static uint32_t i915_gem_get_gtt_size(struct drm_device *dev, uint32_t size,
- int tiling_mode);
-static uint32_t i915_gem_get_gtt_alignment(struct drm_device *dev,
- uint32_t size, int tiling_mode);
-static int i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
- unsigned alignment, bool map_and_fenceable);
-static int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
- int flags);
-static void i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj);
-static void i915_gem_object_put_pages_range(struct drm_i915_gem_object *obj,
- off_t start, off_t end);
+#define __user
+#define __force
+#define __iomem
+#define __must_check
+#define to_user_ptr(x) ((void *)(uintptr_t)(x))
+#define offset_in_page(x) ((x) & PAGE_MASK)
+#define page_to_phys(x) VM_PAGE_TO_PHYS(x)
+
+static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj);
+static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj);
+static __must_check int i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
+ unsigned alignment,
+ bool map_and_fenceable);
+static int i915_gem_phys_pwrite(struct drm_device *dev,
+ struct drm_i915_gem_object *obj,
+ struct drm_i915_gem_pwrite *args,
+ struct drm_file *file);
+
+static void i915_gem_write_fence(struct drm_device *dev, int reg,
+ struct drm_i915_gem_object *obj);
+static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
+ struct drm_i915_fence_reg *fence,
+ bool enable);
+
+static void i915_gem_lowmem(void *arg);
+static void i915_gem_object_truncate(struct drm_i915_gem_object *obj);
+
static int i915_gem_object_get_pages_range(struct drm_i915_gem_object *obj,
off_t start, off_t end);
-static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj);
-static void i915_gem_object_truncate(struct drm_i915_gem_object *obj);
-static int i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj);
-static bool i915_gem_object_is_inactive(struct drm_i915_gem_object *obj);
-static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj);
+static void i915_gem_object_put_pages_range(struct drm_i915_gem_object *obj,
+ off_t start, off_t end);
+
static vm_page_t i915_gem_wire_page(vm_object_t object, vm_pindex_t pindex,
bool *fresh);
-static void i915_gem_process_flushing_list(struct intel_ring_buffer *ring,
- uint32_t flush_domains);
-static void i915_gem_reset_fences(struct drm_device *dev);
-static void i915_gem_retire_task_handler(void *arg, int pending);
-static void i915_gem_lowmem(void *arg);
-static void i915_gem_write_fence(struct drm_device *dev, int reg,
- struct drm_i915_gem_object *obj);
-static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
- bool interruptible);
-static int i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno);
MALLOC_DEFINE(DRM_I915_GEM, "i915gem", "Allocations from i915 gem");
long i915_gem_wired_pages_cnt;
@@ -131,18 +134,17 @@ static inline void i915_gem_object_fence_lost(struct drm_i915_gem_object *obj)
obj->fence_reg = I915_FENCE_REG_NONE;
}
-static void
-i915_gem_info_add_obj(struct drm_i915_private *dev_priv, size_t size)
+/* some bookkeeping */
+static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv,
+ size_t size)
{
-
dev_priv->mm.object_count++;
dev_priv->mm.object_memory += size;
}
-static void
-i915_gem_info_remove_obj(struct drm_i915_private *dev_priv, size_t size)
+static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv,
+ size_t size)
{
-
dev_priv->mm.object_count--;
dev_priv->mm.object_memory -= size;
}
@@ -150,10 +152,9 @@ i915_gem_info_remove_obj(struct drm_i915_private *dev_priv, size_t size)
static int
i915_gem_wait_for_error(struct drm_device *dev)
{
- struct drm_i915_private *dev_priv;
+ struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
- dev_priv = dev->dev_private;
if (!atomic_load_acq_int(&dev_priv->mm.wedged))
return (0);
@@ -171,150 +172,61 @@ i915_gem_wait_for_error(struct drm_device *dev)
mtx_unlock(&dev_priv->error_completion_lock);
if (atomic_load_acq_int(&dev_priv->mm.wedged)) {
+ /* GPU is hung, bump the completion count to account for
+ * the token we just consumed so that we never hit zero and
+ * end up waiting upon a subsequent completion event that
+ * will never happen.
+ */
mtx_lock(&dev_priv->error_completion_lock);
dev_priv->error_completion++;
mtx_unlock(&dev_priv->error_completion_lock);
}
- return (0);
+ return 0;
}
-int
-i915_mutex_lock_interruptible(struct drm_device *dev)
+int i915_mutex_lock_interruptible(struct drm_device *dev)
{
- struct drm_i915_private *dev_priv;
int ret;
- dev_priv = dev->dev_private;
ret = i915_gem_wait_for_error(dev);
- if (ret != 0)
- return (ret);
+ if (ret)
+ return ret;
/*
* interruptible shall it be. might indeed be if dev_lock is
* changed to sx
*/
- ret = sx_xlock_sig(&dev->dev_struct_lock);
- if (ret != 0)
- return (-ret);
-
- return (0);
-}
-
-
-void
-i915_gem_free_object(struct drm_gem_object *gem_obj)
-{
- struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
- struct drm_device *dev;
- drm_i915_private_t *dev_priv;
-
- dev = obj->base.dev;
- dev_priv = dev->dev_private;
-
- CTR1(KTR_DRM, "object_destroy_tail %p", obj);
-
- if (obj->phys_obj)
- i915_gem_detach_phys_object(dev, obj);
-
- obj->pin_count = 0;
- if (i915_gem_object_unbind(obj) == -ERESTARTSYS) {
- bool was_interruptible;
-
- was_interruptible = dev_priv->mm.interruptible;
- dev_priv->mm.interruptible = false;
-
- if (i915_gem_object_unbind(obj))
- printf("i915_gem_free_object: unbind\n");
-
- dev_priv->mm.interruptible = was_interruptible;
- }
-
- drm_gem_free_mmap_offset(&obj->base);
- drm_gem_object_release(&obj->base);
- i915_gem_info_remove_obj(dev_priv, obj->base.size);
-
- free(obj->bit_17, DRM_I915_GEM);
- free(obj, DRM_I915_GEM);
-}
-
-static void
-init_ring_lists(struct intel_ring_buffer *ring)
-{
+ ret = -sx_xlock_sig(&dev->dev_struct_lock);
+ if (ret)
+ return ret;
- INIT_LIST_HEAD(&ring->active_list);
- INIT_LIST_HEAD(&ring->request_list);
- INIT_LIST_HEAD(&ring->gpu_write_list);
+ return 0;
}
-void
-i915_gem_load(struct drm_device *dev)
+static bool
+i915_gem_object_is_inactive(struct drm_i915_gem_object *obj)
{
- drm_i915_private_t *dev_priv;
- int i;
-
- dev_priv = dev->dev_private;
- INIT_LIST_HEAD(&dev_priv->mm.active_list);
- INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
- INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
- INIT_LIST_HEAD(&dev_priv->mm.fence_list);
- INIT_LIST_HEAD(&dev_priv->mm.gtt_list);
- for (i = 0; i < I915_NUM_RINGS; i++)
- init_ring_lists(&dev_priv->rings[i]);
- for (i = 0; i < I915_MAX_NUM_FENCES; i++)
- INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
- TIMEOUT_TASK_INIT(dev_priv->tq, &dev_priv->mm.retire_task, 0,
- i915_gem_retire_task_handler, dev_priv);
- dev_priv->error_completion = 0;
-
- /* On GEN3 we really need to make sure the ARB C3 LP bit is set */
- if (IS_GEN3(dev)) {
- I915_WRITE(MI_ARB_STATE,
- _MASKED_BIT_ENABLE(MI_ARB_C3_LP_WRITE_ENABLE));
- }
-
- dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
-
- /* Old X drivers will take 0-2 for front, back, depth buffers */
- if (!drm_core_check_feature(dev, DRIVER_MODESET))
- dev_priv->fence_reg_start = 3;
-
- if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) ||
- IS_G33(dev))
- dev_priv->num_fence_regs = 16;
- else
- dev_priv->num_fence_regs = 8;
-
- /* Initialize fence registers to zero */
- i915_gem_reset_fences(dev);
-
- i915_gem_detect_bit_6_swizzle(dev);
- dev_priv->mm.interruptible = true;
-
- dev_priv->mm.i915_lowmem = EVENTHANDLER_REGISTER(vm_lowmem,
- i915_gem_lowmem, dev, EVENTHANDLER_PRI_ANY);
+ return !obj->active;
}
int
i915_gem_init_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
+ struct drm_file *file)
{
- struct drm_i915_gem_init *args;
- drm_i915_private_t *dev_priv;
- int error;
+ struct drm_i915_gem_init *args = data;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int ret;
if (drm_core_check_feature(dev, DRIVER_MODESET))
return -ENODEV;
- dev_priv = dev->dev_private;
- args = data;
-
if (args->gtt_start >= args->gtt_end ||
(args->gtt_end | args->gtt_start) & (PAGE_SIZE - 1))
- return (-EINVAL);
+ return -EINVAL;
if (mtx_initialized(&dev_priv->mm.gtt_space.unused_lock))
- return (-EBUSY);
+ return -EBUSY;
/* GEM with user mode setting was never supported on ilk and later. */
if (INTEL_INFO(dev)->gen >= 5)
@@ -325,254 +237,22 @@ i915_gem_init_ioctl(struct drm_device *dev, void *data,
* against.
*/
DRM_LOCK(dev);
- error = i915_gem_init_global_gtt(dev, args->gtt_start,
- args->gtt_end, args->gtt_end);
- DRM_UNLOCK(dev);
- return (error);
-}
-
-int
-i915_gem_idle(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv;
- int ret;
-
- DRM_LOCK(dev);
-
- dev_priv = dev->dev_private;
- if (dev_priv->mm.suspended) {
- DRM_UNLOCK(dev);
- return (0);
- }
-
- ret = i915_gpu_idle(dev);
- if (ret != 0) {
- DRM_UNLOCK(dev);
- return (ret);
- }
- i915_gem_retire_requests(dev);
-
- /* Under UMS, be paranoid and evict. */
- if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
- ret = i915_gem_evict_everything(dev, false);
- if (ret != 0) {
- DRM_UNLOCK(dev);
- return ret;
- }
- }
-
- i915_gem_reset_fences(dev);
-
- /* Hack! Don't let anybody do execbuf while we don't control the chip.
- * We need to replace this with a semaphore, or something.
- * And not confound mm.suspended!
- */
- dev_priv->mm.suspended = 1;
- callout_stop(&dev_priv->hangcheck_timer);
-
- i915_kernel_lost_context(dev);
- i915_gem_cleanup_ringbuffer(dev);
-
+ ret = i915_gem_init_global_gtt(dev, args->gtt_start,
+ args->gtt_end, args->gtt_end);
DRM_UNLOCK(dev);
- /* Cancel the retire work handler, which should be idle now. */
- taskqueue_cancel_timeout(dev_priv->tq, &dev_priv->mm.retire_task, NULL);
- return (ret);
-}
-
-void
-i915_gem_init_swizzling(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv;
-
- dev_priv = dev->dev_private;
-
- if (INTEL_INFO(dev)->gen < 5 ||
- dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_NONE)
- return;
-
- I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) |
- DISP_TILE_SURFACE_SWIZZLING);
-
- if (IS_GEN5(dev))
- return;
-
-
- I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_SWZCTL);
- if (IS_GEN6(dev))
- I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB));
- else
- I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB));
-}
-
-void i915_gem_init_ppgtt(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv;
- struct i915_hw_ppgtt *ppgtt;
- uint32_t pd_offset, pd_entry;
- vm_paddr_t pt_addr;
- struct intel_ring_buffer *ring;
- u_int first_pd_entry_in_global_pt, i;
-
- dev_priv = dev->dev_private;
- ppgtt = dev_priv->mm.aliasing_ppgtt;
- if (ppgtt == NULL)
- return;
-
- first_pd_entry_in_global_pt = 512 * 1024 - I915_PPGTT_PD_ENTRIES;
- for (i = 0; i < ppgtt->num_pd_entries; i++) {
- pt_addr = VM_PAGE_TO_PHYS(ppgtt->pt_pages[i]);
- pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
- pd_entry |= GEN6_PDE_VALID;
- intel_gtt_write(first_pd_entry_in_global_pt + i, pd_entry);
- }
- intel_gtt_read_pte(first_pd_entry_in_global_pt);
-
- pd_offset = ppgtt->pd_offset;
- pd_offset /= 64; /* in cachelines, */
- pd_offset <<= 16;
-
- if (INTEL_INFO(dev)->gen == 6) {
- uint32_t ecochk, gab_ctl, ecobits;
-
- ecobits = I915_READ(GAC_ECO_BITS);
- I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
-
- gab_ctl = I915_READ(GAB_CTL);
- I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT);
-
- ecochk = I915_READ(GAM_ECOCHK);
- I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT |
- ECOCHK_PPGTT_CACHE64B);
- I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
- } else if (INTEL_INFO(dev)->gen >= 7) {
- I915_WRITE(GAM_ECOCHK, ECOCHK_PPGTT_CACHE64B);
- /* GFX_MODE is per-ring on gen7+ */
- }
-
- for_each_ring(ring, dev_priv, i) {
- if (INTEL_INFO(dev)->gen >= 7)
- I915_WRITE(RING_MODE_GEN7(ring),
- _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
-
- I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
- I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset);
- }
-}
-
-int
-i915_gem_init_hw(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv;
- int ret;
-
- dev_priv = dev->dev_private;
-
- i915_gem_init_swizzling(dev);
-
- ret = intel_init_render_ring_buffer(dev);
- if (ret != 0)
- return (ret);
-
- if (HAS_BSD(dev)) {
- ret = intel_init_bsd_ring_buffer(dev);
- if (ret != 0)
- goto cleanup_render_ring;
- }
-
- if (HAS_BLT(dev)) {
- ret = intel_init_blt_ring_buffer(dev);
- if (ret != 0)
- goto cleanup_bsd_ring;
- }
-
- dev_priv->next_seqno = 1;
- i915_gem_context_init(dev);
- i915_gem_init_ppgtt(dev);
- return (0);
-
-cleanup_bsd_ring:
- intel_cleanup_ring_buffer(&dev_priv->rings[VCS]);
-cleanup_render_ring:
- intel_cleanup_ring_buffer(&dev_priv->rings[RCS]);
- return (ret);
-}
-
-static bool
-intel_enable_ppgtt(struct drm_device *dev)
-{
- if (i915_enable_ppgtt >= 0)
- return i915_enable_ppgtt;
-
- /* Disable ppgtt on SNB if VT-d is on. */
- if (INTEL_INFO(dev)->gen == 6 && intel_iommu_enabled)
- return false;
-
- return true;
-}
-
-int i915_gem_init(struct drm_device *dev)
-{
- struct drm_i915_private *dev_priv = dev->dev_private;
- unsigned long gtt_size, mappable_size;
- int ret;
-
- gtt_size = dev_priv->mm.gtt.gtt_total_entries << PAGE_SHIFT;
- mappable_size = dev_priv->mm.gtt.gtt_mappable_entries << PAGE_SHIFT;
-
- DRM_LOCK(dev);
- if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
- /* PPGTT pdes are stolen from global gtt ptes, so shrink the
- * aperture accordingly when using aliasing ppgtt. */
- gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
-
- i915_gem_init_global_gtt(dev, 0, mappable_size, gtt_size);
-
- ret = i915_gem_init_aliasing_ppgtt(dev);
- if (ret) {
- DRM_UNLOCK(dev);
- return ret;
- }
- } else {
- /* Let GEM Manage all of the aperture.
- *
- * However, leave one page at the end still bound to the scratch
- * page. There are a number of places where the hardware
- * apparently prefetches past the end of the object, and we've
- * seen multiple hangs with the GPU head pointer stuck in a
- * batchbuffer bound at the last page of the aperture. One page
- * should be enough to keep any prefetching inside of the
- * aperture.
- */
- i915_gem_init_global_gtt(dev, 0, mappable_size,
- gtt_size);
- }
-
- ret = i915_gem_init_hw(dev);
- DRM_UNLOCK(dev);
- if (ret != 0) {
- i915_gem_cleanup_aliasing_ppgtt(dev);
- return (ret);
- }
-
- /* Allow hardware batchbuffers unless told otherwise, but not for KMS. */
- if (!drm_core_check_feature(dev, DRIVER_MODESET))
- dev_priv->dri1.allow_batchbuffer = 1;
- return 0;
+ return ret;
}
int
i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
+ struct drm_file *file)
{
- struct drm_i915_private *dev_priv;
- struct drm_i915_gem_get_aperture *args;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_gem_get_aperture *args = data;
struct drm_i915_gem_object *obj;
size_t pinned;
- dev_priv = dev->dev_private;
- args = data;
-
pinned = 0;
DRM_LOCK(dev);
list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list)
@@ -583,418 +263,84 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
args->aper_size = dev_priv->mm.gtt_total;
args->aper_available_size = args->aper_size - pinned;
- return (0);
-}
-
-int
-i915_gem_object_pin(struct drm_i915_gem_object *obj, uint32_t alignment,
- bool map_and_fenceable)
-{
- int ret;
-
- if (obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)
- return (-EBUSY);
-
- if (obj->gtt_space != NULL) {
- if ((alignment && obj->gtt_offset & (alignment - 1)) ||
- (map_and_fenceable && !obj->map_and_fenceable)) {
- DRM_DEBUG("bo is already pinned with incorrect alignment:"
- " offset=%x, req.alignment=%x, req.map_and_fenceable=%d,"
- " obj->map_and_fenceable=%d\n",
- obj->gtt_offset, alignment,
- map_and_fenceable,
- obj->map_and_fenceable);
- ret = i915_gem_object_unbind(obj);
- if (ret != 0)
- return (ret);
- }
- }
-
- if (obj->gtt_space == NULL) {
- ret = i915_gem_object_bind_to_gtt(obj, alignment,
- map_and_fenceable);
- if (ret)
- return (ret);
- }
-
- if (!obj->has_global_gtt_mapping && map_and_fenceable)
- i915_gem_gtt_bind_object(obj, obj->cache_level);
-
- obj->pin_count++;
- obj->pin_mappable |= map_and_fenceable;
-
return 0;
}
-void
-i915_gem_object_unpin(struct drm_i915_gem_object *obj)
-{
-
- KASSERT(obj->pin_count != 0, ("zero pin count"));
- KASSERT(obj->gtt_space != NULL, ("No gtt mapping"));
-
- if (--obj->pin_count == 0)
- obj->pin_mappable = false;
-}
-
-int
-i915_gem_pin_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
- struct drm_i915_gem_pin *args;
- struct drm_i915_gem_object *obj;
- struct drm_gem_object *gobj;
- int ret;
-
- args = data;
-
- ret = i915_mutex_lock_interruptible(dev);
- if (ret != 0)
- return ret;
-
- gobj = drm_gem_object_lookup(dev, file, args->handle);
- if (gobj == NULL) {
- ret = -ENOENT;
- goto unlock;
- }
- obj = to_intel_bo(gobj);
-
- if (obj->madv != I915_MADV_WILLNEED) {
- DRM_ERROR("Attempting to pin a purgeable buffer\n");
- ret = -EINVAL;
- goto out;
- }
-
- if (obj->pin_filp != NULL && obj->pin_filp != file) {
- DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
- args->handle);
- ret = -EINVAL;
- goto out;
- }
-
- obj->user_pin_count++;
- obj->pin_filp = file;
- if (obj->user_pin_count == 1) {
- ret = i915_gem_object_pin(obj, args->alignment, true);
- if (ret != 0)
- goto out;
- }
-
- /* XXX - flush the CPU caches for pinned objects
- * as the X server doesn't manage domains yet
- */
- i915_gem_object_flush_cpu_write_domain(obj);
- args->offset = obj->gtt_offset;
-out:
- drm_gem_object_unreference(&obj->base);
-unlock:
- DRM_UNLOCK(dev);
- return (ret);
-}
-
-int
-i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
- struct drm_i915_gem_pin *args;
- struct drm_i915_gem_object *obj;
- int ret;
-
- args = data;
- ret = i915_mutex_lock_interruptible(dev);
- if (ret != 0)
- return (ret);
-
- obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
- if (&obj->base == NULL) {
- ret = -ENOENT;
- goto unlock;
- }
-
- if (obj->pin_filp != file) {
- DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n",
- args->handle);
- ret = -EINVAL;
- goto out;
- }
- obj->user_pin_count--;
- if (obj->user_pin_count == 0) {
- obj->pin_filp = NULL;
- i915_gem_object_unpin(obj);
- }
-
-out:
- drm_gem_object_unreference(&obj->base);
-unlock:
- DRM_UNLOCK(dev);
- return (ret);
-}
-
-int
-i915_gem_busy_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
- struct drm_i915_gem_busy *args;
- struct drm_i915_gem_object *obj;
- int ret;
-
- args = data;
-
- ret = i915_mutex_lock_interruptible(dev);
- if (ret != 0)
- return ret;
-
- obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
- if (&obj->base == NULL) {
- ret = -ENOENT;
- goto unlock;
- }
-
- args->busy = obj->active;
- if (args->busy) {
- if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
- ret = i915_gem_flush_ring(obj->ring,
- 0, obj->base.write_domain);
- } else {
- ret = i915_gem_check_olr(obj->ring,
- obj->last_rendering_seqno);
- }
-
- i915_gem_retire_requests_ring(obj->ring);
- args->busy = obj->active;
- }
-
- drm_gem_object_unreference(&obj->base);
-unlock:
- DRM_UNLOCK(dev);
- return (ret);
-}
-
static int
-i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
-{
- struct drm_i915_private *dev_priv;
- struct drm_i915_file_private *file_priv;
- unsigned long recent_enough;
- struct drm_i915_gem_request *request;
- struct intel_ring_buffer *ring;
- u32 seqno;
- int ret;
-
- dev_priv = dev->dev_private;
- if (atomic_load_acq_int(&dev_priv->mm.wedged))
- return (-EIO);
-
- file_priv = file->driver_priv;
- recent_enough = ticks - (20 * hz / 1000);
- ring = NULL;
- seqno = 0;
-
- mtx_lock(&file_priv->mm.lck);
- list_for_each_entry(request, &file_priv->mm.request_list, client_list) {
- if (time_after_eq(request->emitted_jiffies, recent_enough))
- break;
- ring = request->ring;
- seqno = request->seqno;
- }
- mtx_unlock(&file_priv->mm.lck);
- if (seqno == 0)
- return (0);
-
- ret = __wait_seqno(ring, seqno, true);
- if (ret == 0)
- taskqueue_enqueue_timeout(dev_priv->tq,
- &dev_priv->mm.retire_task, 0);
-
- return (ret);
-}
-
-int
-i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
-
- return (i915_gem_ring_throttle(dev, file_priv));
-}
-
-int
-i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- struct drm_i915_gem_madvise *args;
- struct drm_i915_gem_object *obj;
- int ret;
-
- args = data;
- switch (args->madv) {
- case I915_MADV_DONTNEED:
- case I915_MADV_WILLNEED:
- break;
- default:
- return (-EINVAL);
- }
-
- ret = i915_mutex_lock_interruptible(dev);
- if (ret != 0)
- return (ret);
-
- obj = to_intel_bo(drm_gem_object_lookup(dev, file_priv, args->handle));
- if (&obj->base == NULL) {
- ret = -ENOENT;
- goto unlock;
- }
-
- if (obj->pin_count != 0) {
- ret = -EINVAL;
- goto out;
- }
-
- if (obj->madv != I915_MADV_PURGED_INTERNAL)
- obj->madv = args->madv;
- if (i915_gem_object_is_purgeable(obj) && obj->gtt_space == NULL)
- i915_gem_object_truncate(obj);
- args->retained = obj->madv != I915_MADV_PURGED_INTERNAL;
-
-out:
- drm_gem_object_unreference(&obj->base);
-unlock:
- DRM_UNLOCK(dev);
- return (ret);
-}
-
-void
-i915_gem_cleanup_ringbuffer(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv;
- struct intel_ring_buffer *ring;
- int i;
-
- dev_priv = dev->dev_private;
- for_each_ring(ring, dev_priv, i)
- intel_cleanup_ring_buffer(ring);
-}
-
-int
-i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
- drm_i915_private_t *dev_priv;
- int ret;
-
- if (drm_core_check_feature(dev, DRIVER_MODESET))
- return (0);
- dev_priv = dev->dev_private;
- if (atomic_load_acq_int(&dev_priv->mm.wedged) != 0) {
- DRM_ERROR("Reenabling wedged hardware, good luck\n");
- atomic_store_rel_int(&dev_priv->mm.wedged, 0);
- }
-
- DRM_LOCK(dev);
- dev_priv->mm.suspended = 0;
-
- ret = i915_gem_init_hw(dev);
- if (ret != 0) {
- DRM_UNLOCK(dev);
- return (ret);
- }
-
- KASSERT(list_empty(&dev_priv->mm.active_list), ("active list"));
- KASSERT(list_empty(&dev_priv->mm.flushing_list), ("flushing list"));
- KASSERT(list_empty(&dev_priv->mm.inactive_list), ("inactive list"));
- DRM_UNLOCK(dev);
-
- ret = drm_irq_install(dev);
- if (ret)
- goto cleanup_ringbuffer;
-
- return (0);
-
-cleanup_ringbuffer:
- DRM_LOCK(dev);
- i915_gem_cleanup_ringbuffer(dev);
- dev_priv->mm.suspended = 1;
- DRM_UNLOCK(dev);
-
- return (ret);
-}
-
-int
-i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file_priv)
-{
-
- if (drm_core_check_feature(dev, DRIVER_MODESET))
- return 0;
-
- drm_irq_uninstall(dev);
- return (i915_gem_idle(dev));
-}
-
-int
-i915_gem_create(struct drm_file *file, struct drm_device *dev, uint64_t size,
- uint32_t *handle_p)
+i915_gem_create(struct drm_file *file,
+ struct drm_device *dev,
+ uint64_t size,
+ uint32_t *handle_p)
{
struct drm_i915_gem_object *obj;
- uint32_t handle;
int ret;
+ u32 handle;
size = roundup(size, PAGE_SIZE);
if (size == 0)
- return (-EINVAL);
+ return -EINVAL;
+ /* Allocate the new object */
obj = i915_gem_alloc_object(dev, size);
if (obj == NULL)
- return (-ENOMEM);
+ return -ENOMEM;
ret = drm_gem_handle_create(file, &obj->base, &handle);
- if (ret != 0) {
+ if (ret) {
drm_gem_object_release(&obj->base);
i915_gem_info_remove_obj(dev->dev_private, obj->base.size);
free(obj, DRM_I915_GEM);
- return (ret);
+ return ret;
}
/* drop reference from allocate - handle holds it now */
drm_gem_object_unreference(&obj->base);
CTR2(KTR_DRM, "object_create %p %x", obj, size);
+
*handle_p = handle;
- return (0);
+ return 0;
}
int
-i915_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
- struct drm_mode_create_dumb *args)
+i915_gem_dumb_create(struct drm_file *file,
+ struct drm_device *dev,
+ struct drm_mode_create_dumb *args)
{
-
/* have to work out size/pitch and return them */
args->pitch = roundup2(args->width * ((args->bpp + 7) / 8), 64);
args->size = args->pitch * args->height;
- return (i915_gem_create(file, dev, args->size, &args->handle));
+ return i915_gem_create(file, dev,
+ args->size, &args->handle);
}
-int
-i915_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
- uint32_t handle)
+int i915_gem_dumb_destroy(struct drm_file *file,
+ struct drm_device *dev,
+ uint32_t handle)
{
-
- return (drm_gem_handle_delete(file, handle));
+ return drm_gem_handle_delete(file, handle);
}
+/**
+ * Creates a new mm object and returns a handle to it.
+ */
int
i915_gem_create_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
+ struct drm_file *file)
{
struct drm_i915_gem_create *args = data;
- return (i915_gem_create(file, dev, args->size, &args->handle));
+ return i915_gem_create(file, dev,
+ args->size, &args->handle);
+}
+
+static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
+{
+ drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
+
+ return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
+ obj->tiling_mode != I915_TILING_NONE;
}
-#define __user
-#define __force
-#define __iomem
-#define to_user_ptr(x) ((void *)(uintptr_t)(x))
-#define offset_in_page(x) ((x) & PAGE_MASK)
-#define page_to_phys(x) VM_PAGE_TO_PHYS(x)
static inline int
__copy_to_user_inatomic(void __user *to, const void *from, unsigned n)
{
@@ -1120,33 +466,6 @@ __copy_from_user_swizzled(char *gpu_vaddr, int gpu_offset,
return 0;
}
-static int
-i915_gem_phys_pwrite(struct drm_device *dev,
- struct drm_i915_gem_object *obj,
- struct drm_i915_gem_pwrite *args,
- struct drm_file *file_priv)
-{
- void *vaddr = (char *)obj->phys_obj->handle->vaddr + args->offset;
- char __user *user_data = to_user_ptr(args->data_ptr);
-
- if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) {
- unsigned long unwritten;
-
- /* The physical object once assigned is fixed for the lifetime
- * of the obj, so we can safely drop the lock and continue
- * to access vaddr.
- */
- DRM_UNLOCK(dev);
- unwritten = copy_from_user(vaddr, user_data, args->size);
- DRM_LOCK(dev);
- if (unwritten)
- return -EFAULT;
- }
-
- i915_gem_chipset_flush(dev);
- return 0;
-}
-
/* Per-page copy function for the shmem pread fastpath.
* Flushes invalid cachelines before reading the target if
* needs_clflush is set. */
@@ -1411,7 +730,7 @@ fast_user_write(struct drm_device *dev,
vaddr_atomic = pmap_mapdev_attr(dev->agp->base + page_base,
length, PAT_WRITE_COMBINING);
/* We can use the cpu mem copy function because this is X86. */
- vaddr = (char *)vaddr_atomic + page_offset;
+ vaddr = (char __force*)vaddr_atomic + page_offset;
unwritten = __copy_from_user_inatomic_nocache(vaddr,
user_data, length);
pmap_unmapdev((vm_offset_t)vaddr_atomic, length);
@@ -1435,7 +754,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
ret = i915_gem_object_pin(obj, 0, true);
/* XXXKIB ret = i915_gem_obj_ggtt_pin(obj, 0, true, true); */
- if (ret != 0)
+ if (ret)
goto out;
ret = i915_gem_object_set_to_gtt_domain(obj, true);
@@ -1678,7 +997,7 @@ out:
if (!needs_clflush_after &&
obj->base.write_domain != I915_GEM_DOMAIN_CPU) {
i915_gem_clflush_object(obj);
- i915_gem_chipset_flush(dev);
+ i915_gem_chipset_flush(dev);
}
}
@@ -1775,35 +1094,159 @@ unlock:
DRM_UNLOCK(dev);
return ret;
}
-#undef __user
-#undef __force
-#undef __iomem
-#undef to_user_ptr
-#undef offset_in_page
-#undef page_to_phys
+
+static int
+i915_gem_check_wedge(struct drm_i915_private *dev_priv)
+{
+ DRM_LOCK_ASSERT(dev_priv->dev);
+
+ if (atomic_load_acq_int(&dev_priv->mm.wedged) != 0) {
+ bool recovery_complete;
+
+ /* Give the error handler a chance to run. */
+ mtx_lock(&dev_priv->error_completion_lock);
+ recovery_complete = (&dev_priv->error_completion) > 0;
+ mtx_unlock(&dev_priv->error_completion_lock);
+
+ return (recovery_complete ? -EIO : -EAGAIN);
+ }
+
+ return 0;
+}
+
+/*
+ * Compare seqno against outstanding lazy request. Emit a request if they are
+ * equal.
+ */
+static int
+i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
+{
+ int ret;
+
+ DRM_LOCK_ASSERT(ring->dev);
+
+ ret = 0;
+ if (seqno == ring->outstanding_lazy_request) {
+ struct drm_i915_gem_request *request;
+
+ request = malloc(sizeof(*request), DRM_I915_GEM,
+ M_WAITOK | M_ZERO);
+
+ ret = i915_add_request(ring, NULL, request);
+ if (ret != 0) {
+ free(request, DRM_I915_GEM);
+ return ret;
+ }
+
+ MPASS(seqno == request->seqno);
+ }
+ return ret;
+}
+
+static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
+ bool interruptible)
+{
+ drm_i915_private_t *dev_priv = ring->dev->dev_private;
+ int ret = 0, flags;
+
+ if (i915_seqno_passed(ring->get_seqno(ring), seqno))
+ return 0;
+
+ CTR2(KTR_DRM, "request_wait_begin %s %d", ring->name, seqno);
+
+ mtx_lock(&dev_priv->irq_lock);
+ if (!ring->irq_get(ring)) {
+ mtx_unlock(&dev_priv->irq_lock);
+ return -ENODEV;
+ }
+
+ flags = interruptible ? PCATCH : 0;
+ while (!i915_seqno_passed(ring->get_seqno(ring), seqno)
+ && !atomic_load_acq_int(&dev_priv->mm.wedged) &&
+ ret == 0) {
+ ret = -msleep(ring, &dev_priv->irq_lock, flags, "915gwr", 0);
+ if (ret == -ERESTART)
+ ret = -ERESTARTSYS;
+ }
+ ring->irq_put(ring);
+ mtx_unlock(&dev_priv->irq_lock);
+
+ CTR3(KTR_DRM, "request_wait_end %s %d %d", ring->name, seqno, ret);
+
+ return ret;
+}
+
+/**
+ * Waits for a sequence number to be signaled, and cleans up the
+ * request and object lists appropriately for that event.
+ */
+int
+i915_wait_request(struct intel_ring_buffer *ring, uint32_t seqno)
+{
+ struct drm_device *dev = ring->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int ret;
+
+ KASSERT(seqno != 0, ("Zero seqno"));
+
+ ret = i915_gem_check_wedge(dev_priv);
+ if (ret)
+ return ret;
+
+ ret = i915_gem_check_olr(ring, seqno);
+ if (ret)
+ return ret;
+
+ ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible);
+ if (atomic_load_acq_int(&dev_priv->mm.wedged))
+ ret = -EAGAIN;
+
+ return ret;
+}
+
+/**
+ * Ensures that all rendering to the object has completed and the object is
+ * safe to unbind from the GTT or access from the CPU.
+ */
+static __must_check int
+i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj)
+{
+ int ret;
+
+ KASSERT((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0,
+ ("In GPU write domain"));
+
+ CTR5(KTR_DRM, "object_wait_rendering %p %s %x %d %d", obj,
+ obj->ring != NULL ? obj->ring->name : "none", obj->gtt_offset,
+ obj->active, obj->last_rendering_seqno);
+ if (obj->active) {
+ ret = i915_wait_request(obj->ring, obj->last_rendering_seqno);
+ if (ret != 0)
+ return (ret);
+ i915_gem_retire_requests_ring(obj->ring);
+ }
+
+ return 0;
+}
int
i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
+ struct drm_file *file)
{
- struct drm_i915_gem_set_domain *args;
+ struct drm_i915_gem_set_domain *args = data;
struct drm_i915_gem_object *obj;
- uint32_t read_domains;
- uint32_t write_domain;
+ uint32_t read_domains = args->read_domains;
+ uint32_t write_domain = args->write_domain;
int ret;
- args = data;
- read_domains = args->read_domains;
- write_domain = args->write_domain;
-
if ((write_domain & I915_GEM_GPU_DOMAINS) != 0 ||
(read_domains & I915_GEM_GPU_DOMAINS) != 0 ||
(write_domain != 0 && read_domains != write_domain))
- return (-EINVAL);
+ return -EINVAL;
ret = i915_mutex_lock_interruptible(dev);
- if (ret != 0)
- return (ret);
+ if (ret)
+ return ret;
obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
if (&obj->base == NULL) {
@@ -1811,50 +1254,68 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
goto unlock;
}
- if ((read_domains & I915_GEM_DOMAIN_GTT) != 0) {
+ if (read_domains & I915_GEM_DOMAIN_GTT) {
ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0);
+
+ /* Silently promote "you're not bound, there was nothing to do"
+ * to success, since the client was just asking us to
+ * make sure everything was done.
+ */
if (ret == -EINVAL)
ret = 0;
- } else
+ } else {
ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0);
+ }
drm_gem_object_unreference(&obj->base);
unlock:
DRM_UNLOCK(dev);
- return (ret);
+ return ret;
}
+/**
+ * Called when user space has done writes to this buffer
+ */
int
i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
+ struct drm_file *file)
{
- struct drm_i915_gem_sw_finish *args;
+ struct drm_i915_gem_sw_finish *args = data;
struct drm_i915_gem_object *obj;
- int ret;
-
- args = data;
+ int ret = 0;
ret = i915_mutex_lock_interruptible(dev);
- if (ret != 0)
- return (ret);
+ if (ret)
+ return ret;
+
obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
if (&obj->base == NULL) {
ret = -ENOENT;
goto unlock;
}
- if (obj->pin_count != 0)
+
+ /* Pinned buffers may be scanout, so flush the cache */
+ if (obj->pin_count)
i915_gem_object_flush_cpu_write_domain(obj);
+
drm_gem_object_unreference(&obj->base);
unlock:
DRM_UNLOCK(dev);
- return (ret);
+ return ret;
}
+/**
+ * Maps the contents of an object, returning the address it is mapped
+ * into.
+ *
+ * While the mapping holds a reference on the contents of the object, it doesn't
+ * imply a ref on the object itself.
+ */
int
i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
+ struct drm_file *file)
{
- struct drm_i915_gem_mmap *args;
+ struct drm_i915_gem_mmap *args = data;
struct drm_gem_object *obj;
struct proc *p;
vm_map_t map;
@@ -1862,11 +1323,10 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
vm_size_t size;
int error, rv;
- args = data;
-
obj = drm_gem_object_lookup(dev, file, args->handle);
if (obj == NULL)
- return (-ENOENT);
+ return -ENOENT;
+
error = 0;
if (args->size == 0)
goto out;
@@ -1906,6 +1366,23 @@ i915_gem_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot,
return (0);
}
+/**
+ * i915_gem_fault - fault a page into the GTT
+ * vma: VMA in question
+ * vmf: fault info
+ *
+ * The fault handler is set up by drm_gem_mmap() when a object is GTT mapped
+ * from userspace. The fault handler takes care of binding the object to
+ * the GTT (if needed), allocating and programming a fence register (again,
+ * only if needed based on whether the old reg is still valid or the object
+ * is tiled) and inserting a new PTE into the faulting process.
+ *
+ * Note that the faulting process may involve evicting existing objects
+ * from the GTT and/or fence registers to make room. So performance may
+ * suffer if the GTT working set is large or there are few fence registers
+ * left.
+ */
+
int i915_intr_pf;
static int
@@ -1916,7 +1393,7 @@ i915_gem_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot,
struct drm_i915_gem_object *obj;
struct drm_device *dev;
drm_i915_private_t *dev_priv;
- vm_page_t m, oldm;
+ vm_page_t page, oldpage;
int cause, ret;
bool write;
@@ -1943,17 +1420,17 @@ i915_gem_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot,
* progress.
*/
if (*mres != NULL) {
- oldm = *mres;
- vm_page_lock(oldm);
- vm_page_remove(oldm);
- vm_page_unlock(oldm);
+ oldpage = *mres;
+ vm_page_lock(oldpage);
+ vm_page_remove(oldpage);
+ vm_page_unlock(oldpage);
*mres = NULL;
} else
- oldm = NULL;
+ oldpage = NULL;
VM_OBJECT_WUNLOCK(vm_obj);
retry:
cause = ret = 0;
- m = NULL;
+ page = NULL;
if (i915_intr_pf) {
ret = i915_mutex_lock_interruptible(dev);
@@ -1970,13 +1447,13 @@ retry:
* mapping for the page. Recheck.
*/
VM_OBJECT_WLOCK(vm_obj);
- m = vm_page_lookup(vm_obj, OFF_TO_IDX(offset));
- if (m != NULL) {
- if (vm_page_busied(m)) {
+ page = vm_page_lookup(vm_obj, OFF_TO_IDX(offset));
+ if (page != NULL) {
+ if (vm_page_busied(page)) {
DRM_UNLOCK(dev);
- vm_page_lock(m);
+ vm_page_lock(page);
VM_OBJECT_WUNLOCK(vm_obj);
- vm_page_busy_sleep(m, "915pee");
+ vm_page_busy_sleep(page, "915pee");
goto retry;
}
goto have_page;
@@ -2019,45 +1496,45 @@ retry:
obj->fault_mappable = true;
VM_OBJECT_WLOCK(vm_obj);
- m = PHYS_TO_VM_PAGE(dev->agp->base + obj->gtt_offset + offset);
- KASSERT((m->flags & PG_FICTITIOUS) != 0,
+ page = PHYS_TO_VM_PAGE(dev->agp->base + obj->gtt_offset + offset);
+ KASSERT((page->flags & PG_FICTITIOUS) != 0,
("physical address %#jx not fictitious",
(uintmax_t)(dev->agp->base + obj->gtt_offset + offset)));
- if (m == NULL) {
+ if (page == NULL) {
VM_OBJECT_WUNLOCK(vm_obj);
cause = 60;
ret = -EFAULT;
goto unlock;
}
- KASSERT((m->flags & PG_FICTITIOUS) != 0,
- ("not fictitious %p", m));
- KASSERT(m->wire_count == 1, ("wire_count not 1 %p", m));
+ KASSERT((page->flags & PG_FICTITIOUS) != 0,
+ ("not fictitious %p", page));
+ KASSERT(page->wire_count == 1, ("wire_count not 1 %p", page));
- if (vm_page_busied(m)) {
+ if (vm_page_busied(page)) {
DRM_UNLOCK(dev);
- vm_page_lock(m);
+ vm_page_lock(page);
VM_OBJECT_WUNLOCK(vm_obj);
- vm_page_busy_sleep(m, "915pbs");
+ vm_page_busy_sleep(page, "915pbs");
goto retry;
}
- if (vm_page_insert(m, vm_obj, OFF_TO_IDX(offset))) {
+ if (vm_page_insert(page, vm_obj, OFF_TO_IDX(offset))) {
DRM_UNLOCK(dev);
VM_OBJECT_WUNLOCK(vm_obj);
VM_WAIT;
goto retry;
}
- m->valid = VM_PAGE_BITS_ALL;
+ page->valid = VM_PAGE_BITS_ALL;
have_page:
- *mres = m;
- vm_page_xbusy(m);
+ *mres = page;
+ vm_page_xbusy(page);
CTR4(KTR_DRM, "fault %p %jx %x phys %x", gem_obj, offset, prot,
- m->phys_addr);
+ page->phys_addr);
DRM_UNLOCK(dev);
- if (oldm != NULL) {
- vm_page_lock(oldm);
- vm_page_free(oldm);
- vm_page_unlock(oldm);
+ if (oldpage != NULL) {
+ vm_page_lock(oldpage);
+ vm_page_free(oldpage);
+ vm_page_unlock(oldpage);
}
vm_object_pip_wakeup(vm_obj);
return (VM_PAGER_OK);
@@ -2099,416 +1576,51 @@ struct cdev_pager_ops i915_gem_pager_ops = {
.cdev_pg_dtor = i915_gem_pager_dtor
};
-int
-i915_gem_mmap_gtt(struct drm_file *file, struct drm_device *dev,
- uint32_t handle, uint64_t *offset)
-{
- struct drm_i915_private *dev_priv;
- struct drm_i915_gem_object *obj;
- int ret;
-
- dev_priv = dev->dev_private;
-
- ret = i915_mutex_lock_interruptible(dev);
- if (ret != 0)
- return (ret);
-
- obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
- if (&obj->base == NULL) {
- ret = -ENOENT;
- goto unlock;
- }
-
- if (obj->base.size > dev_priv->mm.gtt_mappable_end) {
- ret = -E2BIG;
- goto out;
- }
-
- if (obj->madv != I915_MADV_WILLNEED) {
- DRM_ERROR("Attempting to mmap a purgeable buffer\n");
- ret = -EINVAL;
- goto out;
- }
-
- ret = drm_gem_create_mmap_offset(&obj->base);
- if (ret != 0)
- goto out;
-
- *offset = DRM_GEM_MAPPING_OFF(obj->base.map_list.key) |
- DRM_GEM_MAPPING_KEY;
-out:
- drm_gem_object_unreference(&obj->base);
-unlock:
- DRM_UNLOCK(dev);
- return (ret);
-}
-
-int
-i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
- struct drm_file *file)
-{
- struct drm_i915_private *dev_priv;
- struct drm_i915_gem_mmap_gtt *args;
-
- dev_priv = dev->dev_private;
- args = data;
-
- return (i915_gem_mmap_gtt(file, dev, args->handle, &args->offset));
-}
-
-struct drm_i915_gem_object *
-i915_gem_alloc_object(struct drm_device *dev, size_t size)
-{
- struct drm_i915_private *dev_priv;
- struct drm_i915_gem_object *obj;
-
- dev_priv = dev->dev_private;
-
- obj = malloc(sizeof(*obj), DRM_I915_GEM, M_WAITOK | M_ZERO);
-
- if (drm_gem_object_init(dev, &obj->base, size) != 0) {
- free(obj, DRM_I915_GEM);
- return (NULL);
- }
-
- obj->base.write_domain = I915_GEM_DOMAIN_CPU;
- obj->base.read_domains = I915_GEM_DOMAIN_CPU;
-
- if (HAS_LLC(dev))
- obj->cache_level = I915_CACHE_LLC;
- else
- obj->cache_level = I915_CACHE_NONE;
- obj->base.driver_private = NULL;
- obj->fence_reg = I915_FENCE_REG_NONE;
- INIT_LIST_HEAD(&obj->mm_list);
- INIT_LIST_HEAD(&obj->gtt_list);
- INIT_LIST_HEAD(&obj->ring_list);
- INIT_LIST_HEAD(&obj->exec_list);
- INIT_LIST_HEAD(&obj->gpu_write_list);
- obj->madv = I915_MADV_WILLNEED;
- /* Avoid an unnecessary call to unbind on the first bind. */
- obj->map_and_fenceable = true;
-
- i915_gem_info_add_obj(dev_priv, size);
-
- return (obj);
-}
-
+/**
+ * i915_gem_release_mmap - remove physical page mappings
+ * @obj: obj in question
+ *
+ * Preserve the reservation of the mmapping with the DRM core code, but
+ * relinquish ownership of the pages back to the system.
+ *
+ * It is vital that we remove the page mapping if we have mapped a tiled
+ * object through the GTT and then lose the fence register due to
+ * resource pressure. Similarly if the object has been moved out of the
+ * aperture, than pages mapped into userspace must be revoked. Removing the
+ * mapping will then trigger a page fault on the next user access, allowing
+ * fixup by i915_gem_fault().
+ */
void
-i915_gem_clflush_object(struct drm_i915_gem_object *obj)
-{
-
- /* If we don't have a page list set up, then we're not pinned
- * to GPU, and we can ignore the cache flush because it'll happen
- * again at bind time.
- */
- if (obj->pages == NULL)
- return;
-
- /* If the GPU is snooping the contents of the CPU cache,
- * we do not need to manually clear the CPU cache lines. However,
- * the caches are only snooped when the render cache is
- * flushed/invalidated. As we always have to emit invalidations
- * and flushes when moving into and out of the RENDER domain, correct
- * snooping behaviour occurs naturally as the result of our domain
- * tracking.
- */
- if (obj->cache_level != I915_CACHE_NONE)
- return;
-
- CTR1(KTR_DRM, "object_clflush %p", obj);
- drm_clflush_pages(obj->pages, obj->base.size / PAGE_SIZE);
-}
-
-static void
-i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj)
-{
- uint32_t old_write_domain;
-
- if (obj->base.write_domain != I915_GEM_DOMAIN_CPU)
- return;
-
- i915_gem_clflush_object(obj);
- intel_gtt_chipset_flush();
- old_write_domain = obj->base.write_domain;
- obj->base.write_domain = 0;
-
- CTR3(KTR_DRM, "object_change_domain flush_cpu_write %p %x %x", obj,
- obj->base.read_domains, old_write_domain);
-}
-
-static int
-i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj)
-{
-
- if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0)
- return (0);
- return (i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain));
-}
-
-static void
-i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj)
+i915_gem_release_mmap(struct drm_i915_gem_object *obj)
{
- uint32_t old_write_domain;
+ vm_object_t devobj;
+ vm_page_t page;
+ int i, page_count;
- if (obj->base.write_domain != I915_GEM_DOMAIN_GTT)
+ if (!obj->fault_mappable)
return;
- wmb();
-
- old_write_domain = obj->base.write_domain;
- obj->base.write_domain = 0;
-
- CTR3(KTR_DRM, "object_change_domain flush gtt_write %p %x %x", obj,
- obj->base.read_domains, old_write_domain);
-}
-
-int
-i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
-{
- drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
- uint32_t old_write_domain, old_read_domains;
- int ret;
-
- if (obj->gtt_space == NULL)
- return (-EINVAL);
-
- if (obj->base.write_domain == I915_GEM_DOMAIN_GTT)
- return 0;
-
- ret = i915_gem_object_flush_gpu_write_domain(obj);
- if (ret != 0)
- return (ret);
-
- if (obj->pending_gpu_write || write) {
- ret = i915_gem_object_wait_rendering(obj);
- if (ret != 0)
- return (ret);
- }
-
- i915_gem_object_flush_cpu_write_domain(obj);
-
- old_write_domain = obj->base.write_domain;
- old_read_domains = obj->base.read_domains;
-
- KASSERT((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) == 0,
- ("In GTT write domain"));
- obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
- if (write) {
- obj->base.read_domains = I915_GEM_DOMAIN_GTT;
- obj->base.write_domain = I915_GEM_DOMAIN_GTT;
- obj->dirty = 1;
- }
-
- /* And bump the LRU for this access */
- if (i915_gem_object_is_inactive(obj))
- list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
-
- CTR3(KTR_DRM, "object_change_domain set_to_gtt %p %x %x", obj,
- old_read_domains, old_write_domain);
- return (0);
-}
-
-int
-i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
- enum i915_cache_level cache_level)
-{
- struct drm_device *dev;
- drm_i915_private_t *dev_priv;
- int ret;
-
- if (obj->cache_level == cache_level)
- return 0;
-
- if (obj->pin_count) {
- DRM_DEBUG("can not change the cache level of pinned objects\n");
- return (-EBUSY);
- }
-
- dev = obj->base.dev;
- dev_priv = dev->dev_private;
- if (obj->gtt_space) {
- ret = i915_gem_object_finish_gpu(obj);
- if (ret != 0)
- return (ret);
-
- i915_gem_object_finish_gtt(obj);
+ CTR3(KTR_DRM, "release_mmap %p %x %x", obj, obj->gtt_offset,
+ OFF_TO_IDX(obj->base.size));
+ devobj = cdev_pager_lookup(obj);
+ if (devobj != NULL) {
+ page_count = OFF_TO_IDX(obj->base.size);
- /* Before SandyBridge, you could not use tiling or fence
- * registers with snooped memory, so relinquish any fences
- * currently pointing to our region in the aperture.
- */
- if (INTEL_INFO(obj->base.dev)->gen < 6) {
- ret = i915_gem_object_put_fence(obj);
- if (ret != 0)
- return (ret);
+ VM_OBJECT_WLOCK(devobj);
+retry:
+ for (i = 0; i < page_count; i++) {
+ page = vm_page_lookup(devobj, i);
+ if (page == NULL)
+ continue;
+ if (vm_page_sleep_if_busy(page, "915unm"))
+ goto retry;
+ cdev_pager_free_page(devobj, page);
}
-
- if (obj->has_global_gtt_mapping)
- i915_gem_gtt_bind_object(obj, cache_level);
- if (obj->has_aliasing_ppgtt_mapping)
- i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
- obj, cache_level);
- }
-
- if (cache_level == I915_CACHE_NONE) {
- u32 old_read_domains, old_write_domain;
-
- /* If we're coming from LLC cached, then we haven't
- * actually been tracking whether the data is in the
- * CPU cache or not, since we only allow one bit set
- * in obj->write_domain and have been skipping the clflushes.
- * Just set it to the CPU cache for now.
- */
- KASSERT((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) == 0,
- ("obj %p in CPU write domain", obj));
- KASSERT((obj->base.read_domains & ~I915_GEM_DOMAIN_CPU) == 0,
- ("obj %p in CPU read domain", obj));
-
- old_read_domains = obj->base.read_domains;
- old_write_domain = obj->base.write_domain;
-
- obj->base.read_domains = I915_GEM_DOMAIN_CPU;
- obj->base.write_domain = I915_GEM_DOMAIN_CPU;
-
- CTR3(KTR_DRM, "object_change_domain set_cache_level %p %x %x",
- obj, old_read_domains, old_write_domain);
- }
-
- obj->cache_level = cache_level;
- return (0);
-}
-
-static bool is_pin_display(struct drm_i915_gem_object *obj)
-{
- /* There are 3 sources that pin objects:
- * 1. The display engine (scanouts, sprites, cursors);
- * 2. Reservations for execbuffer;
- * 3. The user.
- *
- * We can ignore reservations as we hold the struct_mutex and
- * are only called outside of the reservation path. The user
- * can only increment pin_count once, and so if after
- * subtracting the potential reference by the user, any pin_count
- * remains, it must be due to another use by the display engine.
- */
- return obj->pin_count - !!obj->user_pin_count;
-}
-
-int
-i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
- u32 alignment, struct intel_ring_buffer *pipelined)
-{
- u32 old_read_domains, old_write_domain;
- int ret;
-
- ret = i915_gem_object_flush_gpu_write_domain(obj);
- if (ret != 0)
- return (ret);
-
- if (pipelined != obj->ring) {
- ret = i915_gem_object_sync(obj, pipelined);
- if (ret)
- return (ret);
- }
-
- obj->pin_display = true;
- ret = i915_gem_object_set_cache_level(obj, I915_CACHE_NONE);
- if (ret != 0)
- goto err_unpin_display;
-
- ret = i915_gem_object_pin(obj, alignment, true);
- if (ret != 0)
- goto err_unpin_display;
-
- i915_gem_object_flush_cpu_write_domain(obj);
-
- old_write_domain = obj->base.write_domain;
- old_read_domains = obj->base.read_domains;
-
- KASSERT((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) == 0,
- ("obj %p in GTT write domain", obj));
- obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
-
- CTR3(KTR_DRM, "object_change_domain pin_to_display_plan %p %x %x",
- obj, old_read_domains, obj->base.write_domain);
- return (0);
-
-err_unpin_display:
- obj->pin_display = is_pin_display(obj);
- return ret;
-}
-
-void
-i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj)
-{
- i915_gem_object_unpin(obj);
- obj->pin_display = is_pin_display(obj);
-}
-
-int
-i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj)
-{
- int ret;
-
- if ((obj->base.read_domains & I915_GEM_GPU_DOMAINS) == 0)
- return (0);
-
- if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
- ret = i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain);
- if (ret != 0)
- return (ret);
- }
-
- ret = i915_gem_object_wait_rendering(obj);
- if (ret != 0)
- return (ret);
-
- obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
-
- return (0);
-}
-
-int
-i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
-{
- uint32_t old_write_domain, old_read_domains;
- int ret;
-
- if (obj->base.write_domain == I915_GEM_DOMAIN_CPU)
- return 0;
-
- ret = i915_gem_object_flush_gpu_write_domain(obj);
- if (ret != 0)
- return (ret);
-
- if (write || obj->pending_gpu_write) {
- ret = i915_gem_object_wait_rendering(obj);
- if (ret != 0)
- return (ret);
- }
-
- i915_gem_object_flush_gtt_write_domain(obj);
-
- old_write_domain = obj->base.write_domain;
- old_read_domains = obj->base.read_domains;
-
- if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0) {
- i915_gem_clflush_object(obj);
- obj->base.read_domains |= I915_GEM_DOMAIN_CPU;
- }
-
- KASSERT((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) == 0,
- ("In cpu write domain"));
-
- if (write) {
- obj->base.read_domains = I915_GEM_DOMAIN_CPU;
- obj->base.write_domain = I915_GEM_DOMAIN_CPU;
+ VM_OBJECT_WUNLOCK(devobj);
+ vm_object_deallocate(devobj);
}
- CTR3(KTR_DRM, "object_change_domain set_to_cpu %p %x %x", obj,
- old_read_domains, old_write_domain);
- return (0);
+ obj->fault_mappable = false;
}
static uint32_t
@@ -2518,7 +1630,7 @@ i915_gem_get_gtt_size(struct drm_device *dev, uint32_t size, int tiling_mode)
if (INTEL_INFO(dev)->gen >= 4 ||
tiling_mode == I915_TILING_NONE)
- return (size);
+ return size;
/* Previous chips need a power-of-two fence region when tiling */
if (INTEL_INFO(dev)->gen == 3)
@@ -2529,7 +1641,7 @@ i915_gem_get_gtt_size(struct drm_device *dev, uint32_t size, int tiling_mode)
while (gtt_size < size)
gtt_size <<= 1;
- return (gtt_size);
+ return gtt_size;
}
/**
@@ -2540,382 +1652,165 @@ i915_gem_get_gtt_size(struct drm_device *dev, uint32_t size, int tiling_mode)
* potential fence register mapping.
*/
static uint32_t
-i915_gem_get_gtt_alignment(struct drm_device *dev, uint32_t size,
- int tiling_mode)
+i915_gem_get_gtt_alignment(struct drm_device *dev,
+ uint32_t size,
+ int tiling_mode)
{
-
/*
* Minimum alignment is 4k (GTT page size), but might be greater
* if a fence register is needed for the object.
*/
if (INTEL_INFO(dev)->gen >= 4 ||
tiling_mode == I915_TILING_NONE)
- return (4096);
+ return 4096;
/*
* Previous chips need to be aligned to the size of the smallest
* fence register that can contain the object.
*/
- return (i915_gem_get_gtt_size(dev, size, tiling_mode));
+ return i915_gem_get_gtt_size(dev, size, tiling_mode);
}
+/**
+ * i915_gem_get_unfenced_gtt_alignment - return required GTT alignment for an
+ * unfenced object
+ * @dev: the device
+ * @size: size of the object
+ * @tiling_mode: tiling mode of the object
+ *
+ * Return the required GTT alignment for an object, only taking into account
+ * unfenced tiled surface requirements.
+ */
uint32_t
-i915_gem_get_unfenced_gtt_alignment(struct drm_device *dev, uint32_t size,
- int tiling_mode)
+i915_gem_get_unfenced_gtt_alignment(struct drm_device *dev,
+ uint32_t size,
+ int tiling_mode)
{
-
if (tiling_mode == I915_TILING_NONE)
- return (4096);
+ return 4096;
/*
* Minimum alignment is 4k (GTT page size) for sane hw.
*/
if (INTEL_INFO(dev)->gen >= 4 || IS_G33(dev))
- return (4096);
+ return 4096;
- /*
- * Previous hardware however needs to be aligned to a power-of-two
+ /* Previous hardware however needs to be aligned to a power-of-two
* tile height. The simplest method for determining this is to reuse
* the power-of-tile object size.
- */
- return (i915_gem_get_gtt_size(dev, size, tiling_mode));
-}
-
-static int
-i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
- unsigned alignment, bool map_and_fenceable)
-{
- struct drm_device *dev;
- struct drm_i915_private *dev_priv;
- struct drm_mm_node *free_space;
- uint32_t size, fence_size, fence_alignment, unfenced_alignment;
- bool mappable, fenceable;
- int ret;
-
- dev = obj->base.dev;
- dev_priv = dev->dev_private;
-
- if (obj->madv != I915_MADV_WILLNEED) {
- DRM_ERROR("Attempting to bind a purgeable object\n");
- return (-EINVAL);
- }
-
- fence_size = i915_gem_get_gtt_size(dev, obj->base.size,
- obj->tiling_mode);
- fence_alignment = i915_gem_get_gtt_alignment(dev, obj->base.size,
- obj->tiling_mode);
- unfenced_alignment = i915_gem_get_unfenced_gtt_alignment(dev,
- obj->base.size, obj->tiling_mode);
- if (alignment == 0)
- alignment = map_and_fenceable ? fence_alignment :
- unfenced_alignment;
- if (map_and_fenceable && (alignment & (fence_alignment - 1)) != 0) {
- DRM_ERROR("Invalid object alignment requested %u\n", alignment);
- return (-EINVAL);
- }
-
- size = map_and_fenceable ? fence_size : obj->base.size;
-
- /* If the object is bigger than the entire aperture, reject it early
- * before evicting everything in a vain attempt to find space.
*/
- if (obj->base.size > (map_and_fenceable ?
- dev_priv->mm.gtt_mappable_end : dev_priv->mm.gtt_total)) {
- DRM_ERROR(
-"Attempting to bind an object larger than the aperture\n");
- return (-E2BIG);
- }
-
- search_free:
- if (map_and_fenceable)
- free_space = drm_mm_search_free_in_range(
- &dev_priv->mm.gtt_space, size, alignment, 0,
- dev_priv->mm.gtt_mappable_end, 0);
- else
- free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
- size, alignment, 0);
- if (free_space != NULL) {
- if (map_and_fenceable)
- obj->gtt_space = drm_mm_get_block_range_generic(
- free_space, size, alignment, 0, 0,
- dev_priv->mm.gtt_mappable_end, 1);
- else
- obj->gtt_space = drm_mm_get_block_generic(free_space,
- size, alignment, 0, 1);
- }
- if (obj->gtt_space == NULL) {
- ret = i915_gem_evict_something(dev, size, alignment,
- map_and_fenceable);
- if (ret != 0)
- return (ret);
- goto search_free;
- }
- ret = i915_gem_object_get_pages_gtt(obj, 0);
- if (ret != 0) {
- drm_mm_put_block(obj->gtt_space);
- obj->gtt_space = NULL;
- /*
- * i915_gem_object_get_pages_gtt() cannot return
- * ENOMEM, since we use vm_page_grab().
- */
- return (ret);
- }
-
- ret = i915_gem_gtt_prepare_object(obj);
- if (ret != 0) {
- i915_gem_object_put_pages_gtt(obj);
- drm_mm_put_block(obj->gtt_space);
- obj->gtt_space = NULL;
- if (i915_gem_evict_everything(dev, false))
- return (ret);
- goto search_free;
- }
-
- if (!dev_priv->mm.aliasing_ppgtt)
- i915_gem_gtt_bind_object(obj, obj->cache_level);
-
- list_add_tail(&obj->gtt_list, &dev_priv->mm.gtt_list);
- list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
-
- KASSERT((obj->base.read_domains & I915_GEM_GPU_DOMAINS) == 0,
- ("Object in gpu read domain"));
- KASSERT((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0,
- ("Object in gpu write domain"));
-
- obj->gtt_offset = obj->gtt_space->start;
-
- fenceable =
- obj->gtt_space->size == fence_size &&
- (obj->gtt_space->start & (fence_alignment - 1)) == 0;
-
- mappable =
- obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end;
- obj->map_and_fenceable = mappable && fenceable;
-
- CTR4(KTR_DRM, "object_bind %p %x %x %d", obj, obj->gtt_offset,
- obj->base.size, map_and_fenceable);
- return (0);
+ return i915_gem_get_gtt_size(dev, size, tiling_mode);
}
int
-i915_gem_object_sync(struct drm_i915_gem_object *obj,
- struct intel_ring_buffer *to)
+i915_gem_mmap_gtt(struct drm_file *file,
+ struct drm_device *dev,
+ uint32_t handle,
+ uint64_t *offset)
{
- struct intel_ring_buffer *from = obj->ring;
- u32 seqno;
- int ret, idx;
-
- if (from == NULL || to == from)
- return 0;
-
- if (to == NULL || !i915_semaphore_is_enabled(obj->base.dev))
- return i915_gem_object_wait_rendering(obj);
-
- idx = intel_ring_sync_index(from, to);
-
- seqno = obj->last_rendering_seqno;
- if (seqno <= from->sync_seqno[idx])
- return 0;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_gem_object *obj;
+ int ret;
- if (seqno == from->outstanding_lazy_request) {
- struct drm_i915_gem_request *request;
+ ret = i915_mutex_lock_interruptible(dev);
+ if (ret)
+ return ret;
- request = malloc(sizeof(*request), DRM_I915_GEM,
- M_WAITOK | M_ZERO);
- ret = i915_add_request(from, NULL, request);
- if (ret) {
- free(request, DRM_I915_GEM);
- return ret;
- }
- seqno = request->seqno;
+ obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
+ if (&obj->base == NULL) {
+ ret = -ENOENT;
+ goto unlock;
}
-
- ret = to->sync_to(to, from, seqno);
- if (!ret)
- from->sync_seqno[idx] = seqno;
-
- return ret;
-}
-
-static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj)
-{
- u32 old_write_domain, old_read_domains;
-
- /* Act a barrier for all accesses through the GTT */
- mb();
-
- /* Force a pagefault for domain tracking on next user access */
- i915_gem_release_mmap(obj);
-
- if ((obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0)
- return;
-
- old_read_domains = obj->base.read_domains;
- old_write_domain = obj->base.write_domain;
-
- obj->base.read_domains &= ~I915_GEM_DOMAIN_GTT;
- obj->base.write_domain &= ~I915_GEM_DOMAIN_GTT;
-
- CTR3(KTR_DRM, "object_change_domain finish gtt %p %x %x",
- obj, old_read_domains, old_write_domain);
-}
-
-int
-i915_gem_object_unbind(struct drm_i915_gem_object *obj)
-{
- drm_i915_private_t *dev_priv;
- int ret;
-
- dev_priv = obj->base.dev->dev_private;
- ret = 0;
- if (obj->gtt_space == NULL)
- return (0);
- if (obj->pin_count != 0) {
- DRM_ERROR("Attempting to unbind pinned buffer\n");
- return (-EINVAL);
+ if (obj->base.size > dev_priv->mm.gtt_mappable_end) {
+ ret = -E2BIG;
+ goto out;
}
- ret = i915_gem_object_finish_gpu(obj);
- if (ret == -ERESTARTSYS || ret == -EINTR)
- return (ret);
-
- i915_gem_object_finish_gtt(obj);
-
- if (ret == 0)
- ret = i915_gem_object_set_to_cpu_domain(obj, 1);
- if (ret == -ERESTARTSYS || ret == -EINTR)
- return (ret);
- if (ret != 0) {
- i915_gem_clflush_object(obj);
- obj->base.read_domains = obj->base.write_domain =
- I915_GEM_DOMAIN_CPU;
+ if (obj->madv != I915_MADV_WILLNEED) {
+ DRM_ERROR("Attempting to mmap a purgeable buffer\n");
+ ret = -EINVAL;
+ goto out;
}
- ret = i915_gem_object_put_fence(obj);
+ ret = drm_gem_create_mmap_offset(&obj->base);
if (ret)
- return (ret);
-
- if (obj->has_global_gtt_mapping)
- i915_gem_gtt_unbind_object(obj);
- if (obj->has_aliasing_ppgtt_mapping) {
- i915_ppgtt_unbind_object(dev_priv->mm.aliasing_ppgtt, obj);
- obj->has_aliasing_ppgtt_mapping = 0;
- }
- i915_gem_gtt_finish_object(obj);
-
- i915_gem_object_put_pages_gtt(obj);
-
- list_del_init(&obj->gtt_list);
- list_del_init(&obj->mm_list);
- obj->map_and_fenceable = true;
-
- drm_mm_put_block(obj->gtt_space);
- obj->gtt_space = NULL;
- obj->gtt_offset = 0;
+ goto out;
- if (i915_gem_object_is_purgeable(obj))
- i915_gem_object_truncate(obj);
- CTR1(KTR_DRM, "object_unbind %p", obj);
+ *offset = DRM_GEM_MAPPING_OFF(obj->base.map_list.key) |
+ DRM_GEM_MAPPING_KEY;
- return (ret);
+out:
+ drm_gem_object_unreference(&obj->base);
+unlock:
+ DRM_UNLOCK(dev);
+ return ret;
}
-static void
-i915_gem_object_put_pages_range_locked(struct drm_i915_gem_object *obj,
- vm_pindex_t si, vm_pindex_t ei)
+/**
+ * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
+ * @dev: DRM device
+ * @data: GTT mapping ioctl data
+ * @file: GEM object info
+ *
+ * Simply returns the fake offset to userspace so it can mmap it.
+ * The mmap call will end up in drm_gem_mmap(), which will set things
+ * up so we can get faults in the handler above.
+ *
+ * The fault handler will take care of binding the object into the GTT
+ * (since it may have been evicted to make room for something), allocating
+ * a fence register, and mapping the appropriate aperture address into
+ * userspace.
+ */
+int
+i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
{
- vm_object_t vm_obj;
- vm_page_t m;
- vm_pindex_t i;
+ struct drm_i915_gem_mmap_gtt *args = data;
- vm_obj = obj->base.vm_obj;
- VM_OBJECT_ASSERT_LOCKED(vm_obj);
- for (i = si, m = vm_page_lookup(vm_obj, i); i < ei;
- m = vm_page_next(m), i++) {
- KASSERT(m->pindex == i, ("pindex %jx %jx",
- (uintmax_t)m->pindex, (uintmax_t)i));
- vm_page_lock(m);
- vm_page_unwire(m, PQ_INACTIVE);
- if (m->wire_count == 0)
- atomic_add_long(&i915_gem_wired_pages_cnt, -1);
- vm_page_unlock(m);
- }
+ return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset);
}
+/* Immediately discard the backing storage */
static void
-i915_gem_object_put_pages_range(struct drm_i915_gem_object *obj,
- off_t start, off_t end)
+i915_gem_object_truncate(struct drm_i915_gem_object *obj)
{
vm_object_t vm_obj;
vm_obj = obj->base.vm_obj;
VM_OBJECT_WLOCK(vm_obj);
- i915_gem_object_put_pages_range_locked(obj,
- OFF_TO_IDX(trunc_page(start)), OFF_TO_IDX(round_page(end)));
+ vm_object_page_remove(vm_obj, 0, 0, false);
VM_OBJECT_WUNLOCK(vm_obj);
+ drm_gem_free_mmap_offset(&obj->base);
+ obj->madv = I915_MADV_PURGED_INTERNAL;
}
-static int
-i915_gem_object_get_pages_range(struct drm_i915_gem_object *obj,
- off_t start, off_t end)
+static inline int
+i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj)
{
- vm_object_t vm_obj;
- vm_page_t m;
- vm_pindex_t si, ei, i;
- bool need_swizzle, fresh;
-
- need_swizzle = i915_gem_object_needs_bit17_swizzle(obj) != 0;
- vm_obj = obj->base.vm_obj;
- si = OFF_TO_IDX(trunc_page(start));
- ei = OFF_TO_IDX(round_page(end));
- VM_OBJECT_WLOCK(vm_obj);
- for (i = si; i < ei; i++) {
- m = i915_gem_wire_page(vm_obj, i, &fresh);
- if (m == NULL)
- goto failed;
- if (need_swizzle && fresh)
- i915_gem_object_do_bit_17_swizzle_page(obj, m);
- }
- VM_OBJECT_WUNLOCK(vm_obj);
- return (0);
-failed:
- i915_gem_object_put_pages_range_locked(obj, si, i);
- VM_OBJECT_WUNLOCK(vm_obj);
- return (-EIO);
+ return obj->madv == I915_MADV_DONTNEED;
}
-static int
-i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
- int flags)
+static void
+i915_gem_object_put_pages_range_locked(struct drm_i915_gem_object *obj,
+ vm_pindex_t si, vm_pindex_t ei)
{
- struct drm_device *dev;
vm_object_t vm_obj;
- vm_page_t m;
- vm_pindex_t i, page_count;
- int res;
+ vm_page_t page;
+ vm_pindex_t i;
- dev = obj->base.dev;
- KASSERT(obj->pages == NULL, ("Obj already has pages"));
- page_count = OFF_TO_IDX(obj->base.size);
- obj->pages = malloc(page_count * sizeof(vm_page_t), DRM_I915_GEM,
- M_WAITOK);
- res = i915_gem_object_get_pages_range(obj, 0, obj->base.size);
- if (res != 0) {
- free(obj->pages, DRM_I915_GEM);
- obj->pages = NULL;
- return (res);
- }
vm_obj = obj->base.vm_obj;
- VM_OBJECT_WLOCK(vm_obj);
- for (i = 0, m = vm_page_lookup(vm_obj, 0); i < page_count;
- i++, m = vm_page_next(m)) {
- KASSERT(m->pindex == i, ("pindex %jx %jx",
- (uintmax_t)m->pindex, (uintmax_t)i));
- obj->pages[i] = m;
+ VM_OBJECT_ASSERT_LOCKED(vm_obj);
+ for (i = si, page = vm_page_lookup(vm_obj, i); i < ei;
+ page = vm_page_next(page), i++) {
+ KASSERT(page->pindex == i, ("pindex %jx %jx",
+ (uintmax_t)page->pindex, (uintmax_t)i));
+ vm_page_lock(page);
+ vm_page_unwire(page, PQ_INACTIVE);
+ if (page->wire_count == 0)
+ atomic_add_long(&i915_gem_wired_pages_cnt, -1);
+ vm_page_unlock(page);
}
- VM_OBJECT_WUNLOCK(vm_obj);
- return (0);
}
#define GEM_PARANOID_CHECK_GTT 0
@@ -2946,9 +1841,22 @@ i915_gem_assert_pages_not_mapped(struct drm_device *dev, vm_page_t *ma,
#endif
static void
+i915_gem_object_put_pages_range(struct drm_i915_gem_object *obj,
+ off_t start, off_t end)
+{
+ vm_object_t vm_obj;
+
+ vm_obj = obj->base.vm_obj;
+ VM_OBJECT_WLOCK(vm_obj);
+ i915_gem_object_put_pages_range_locked(obj,
+ OFF_TO_IDX(trunc_page(start)), OFF_TO_IDX(round_page(end)));
+ VM_OBJECT_WUNLOCK(vm_obj);
+}
+
+static void
i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
{
- vm_page_t m;
+ vm_page_t page;
int page_count, i;
KASSERT(obj->madv != I915_MADV_PURGED_INTERNAL, ("Purged object"));
@@ -2963,14 +1871,14 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
i915_gem_assert_pages_not_mapped(obj->base.dev, obj->pages, page_count);
#endif
for (i = 0; i < page_count; i++) {
- m = obj->pages[i];
+ page = obj->pages[i];
if (obj->dirty)
- vm_page_dirty(m);
+ vm_page_dirty(page);
if (obj->madv == I915_MADV_WILLNEED)
- vm_page_reference(m);
- vm_page_lock(m);
+ vm_page_reference(page);
+ vm_page_lock(page);
vm_page_unwire(obj->pages[i], PQ_ACTIVE);
- vm_page_unlock(m);
+ vm_page_unlock(page);
atomic_add_long(&i915_gem_wired_pages_cnt, -1);
}
VM_OBJECT_WUNLOCK(obj->base.vm_obj);
@@ -2979,69 +1887,139 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj)
obj->pages = NULL;
}
-void
-i915_gem_release_mmap(struct drm_i915_gem_object *obj)
+static int
+i915_gpu_is_active(struct drm_device *dev)
{
- vm_object_t devobj;
- vm_page_t m;
- int i, page_count;
+ drm_i915_private_t *dev_priv = dev->dev_private;
- if (!obj->fault_mappable)
+ return (!list_empty(&dev_priv->mm.flushing_list) ||
+ !list_empty(&dev_priv->mm.active_list));
+}
+
+static void
+i915_gem_lowmem(void *arg)
+{
+ struct drm_device *dev;
+ struct drm_i915_private *dev_priv;
+ struct drm_i915_gem_object *obj, *next;
+ int cnt, cnt_fail, cnt_total;
+
+ dev = arg;
+ dev_priv = dev->dev_private;
+
+ if (!sx_try_xlock(&dev->dev_struct_lock))
return;
- CTR3(KTR_DRM, "release_mmap %p %x %x", obj, obj->gtt_offset,
- OFF_TO_IDX(obj->base.size));
- devobj = cdev_pager_lookup(obj);
- if (devobj != NULL) {
- page_count = OFF_TO_IDX(obj->base.size);
+ CTR0(KTR_DRM, "gem_lowmem");
- VM_OBJECT_WLOCK(devobj);
-retry:
- for (i = 0; i < page_count; i++) {
- m = vm_page_lookup(devobj, i);
- if (m == NULL)
- continue;
- if (vm_page_sleep_if_busy(m, "915unm"))
- goto retry;
- cdev_pager_free_page(devobj, m);
- }
- VM_OBJECT_WUNLOCK(devobj);
- vm_object_deallocate(devobj);
+rescan:
+ /* first scan for clean buffers */
+ i915_gem_retire_requests(dev);
+
+ cnt_total = cnt_fail = cnt = 0;
+
+ list_for_each_entry_safe(obj, next, &dev_priv->mm.inactive_list,
+ mm_list) {
+ if (i915_gem_object_is_purgeable(obj)) {
+ if (i915_gem_object_unbind(obj) != 0)
+ cnt_total++;
+ } else
+ cnt_total++;
}
- obj->fault_mappable = false;
+ /* second pass, evict/count anything still on the inactive list */
+ list_for_each_entry_safe(obj, next, &dev_priv->mm.inactive_list,
+ mm_list) {
+ if (i915_gem_object_unbind(obj) == 0)
+ cnt++;
+ else
+ cnt_fail++;
+ }
+
+ if (cnt_fail > cnt_total / 100 && i915_gpu_is_active(dev)) {
+ /*
+ * We are desperate for pages, so as a last resort, wait
+ * for the GPU to finish and discard whatever we can.
+ * This has a dramatic impact to reduce the number of
+ * OOM-killer events whilst running the GPU aggressively.
+ */
+ if (i915_gpu_idle(dev) == 0)
+ goto rescan;
+ }
+ DRM_UNLOCK(dev);
}
-int
-i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj)
+static int
+i915_gem_object_get_pages_range(struct drm_i915_gem_object *obj,
+ off_t start, off_t end)
{
- int ret;
+ vm_object_t vm_obj;
+ vm_page_t page;
+ vm_pindex_t si, ei, i;
+ bool need_swizzle, fresh;
- KASSERT((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0,
- ("In GPU write domain"));
+ need_swizzle = i915_gem_object_needs_bit17_swizzle(obj) != 0;
+ vm_obj = obj->base.vm_obj;
+ si = OFF_TO_IDX(trunc_page(start));
+ ei = OFF_TO_IDX(round_page(end));
+ VM_OBJECT_WLOCK(vm_obj);
+ for (i = si; i < ei; i++) {
+ page = i915_gem_wire_page(vm_obj, i, &fresh);
+ if (page == NULL)
+ goto failed;
+ if (need_swizzle && fresh)
+ i915_gem_object_do_bit_17_swizzle_page(obj, page);
+ }
+ VM_OBJECT_WUNLOCK(vm_obj);
+ return (0);
+failed:
+ i915_gem_object_put_pages_range_locked(obj, si, i);
+ VM_OBJECT_WUNLOCK(vm_obj);
+ return (-EIO);
+}
- CTR5(KTR_DRM, "object_wait_rendering %p %s %x %d %d", obj,
- obj->ring != NULL ? obj->ring->name : "none", obj->gtt_offset,
- obj->active, obj->last_rendering_seqno);
- if (obj->active) {
- ret = i915_wait_request(obj->ring, obj->last_rendering_seqno);
- if (ret != 0)
- return (ret);
- i915_gem_retire_requests_ring(obj->ring);
+static int
+i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
+ int flags)
+{
+ vm_object_t vm_obj;
+ vm_page_t page;
+ vm_pindex_t i, page_count;
+ int res;
+
+ KASSERT(obj->pages == NULL, ("Obj already has pages"));
+
+ page_count = OFF_TO_IDX(obj->base.size);
+ obj->pages = malloc(page_count * sizeof(vm_page_t), DRM_I915_GEM,
+ M_WAITOK);
+ res = i915_gem_object_get_pages_range(obj, 0, obj->base.size);
+ if (res != 0) {
+ free(obj->pages, DRM_I915_GEM);
+ obj->pages = NULL;
+ return (res);
}
+ vm_obj = obj->base.vm_obj;
+ VM_OBJECT_WLOCK(vm_obj);
+ for (i = 0, page = vm_page_lookup(vm_obj, 0); i < page_count;
+ i++, page = vm_page_next(page)) {
+ KASSERT(page->pindex == i, ("pindex %jx %jx",
+ (uintmax_t)page->pindex, (uintmax_t)i));
+ obj->pages[i] = page;
+ }
+ VM_OBJECT_WUNLOCK(vm_obj);
return (0);
}
void
i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
- struct intel_ring_buffer *ring, uint32_t seqno)
+ struct intel_ring_buffer *ring, uint32_t seqno)
{
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_fence_reg *reg;
- obj->ring = ring;
KASSERT(ring != NULL, ("NULL ring"));
+ obj->ring = ring;
/* Add a reference if we're newly entering the active list. */
if (!obj->active) {
@@ -3112,262 +2090,6 @@ i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
#endif
}
-static void
-i915_gem_object_truncate(struct drm_i915_gem_object *obj)
-{
- vm_object_t vm_obj;
-
- vm_obj = obj->base.vm_obj;
- VM_OBJECT_WLOCK(vm_obj);
- vm_object_page_remove(vm_obj, 0, 0, false);
- VM_OBJECT_WUNLOCK(vm_obj);
- drm_gem_free_mmap_offset(&obj->base);
- obj->madv = I915_MADV_PURGED_INTERNAL;
-}
-
-static inline int
-i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj)
-{
-
- return (obj->madv == I915_MADV_DONTNEED);
-}
-
-static void
-i915_gem_process_flushing_list(struct intel_ring_buffer *ring,
- uint32_t flush_domains)
-{
- struct drm_i915_gem_object *obj, *next;
- uint32_t old_write_domain;
-
- list_for_each_entry_safe(obj, next, &ring->gpu_write_list,
- gpu_write_list) {
- if (obj->base.write_domain & flush_domains) {
- old_write_domain = obj->base.write_domain;
- obj->base.write_domain = 0;
- list_del_init(&obj->gpu_write_list);
- i915_gem_object_move_to_active(obj, ring,
- i915_gem_next_request_seqno(ring));
-
- CTR3(KTR_DRM, "object_change_domain process_flush %p %x %x",
- obj, obj->base.read_domains, old_write_domain);
- }
- }
-}
-
-static int
-i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
-{
- drm_i915_private_t *dev_priv;
-
- dev_priv = obj->base.dev->dev_private;
- return (dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
- obj->tiling_mode != I915_TILING_NONE);
-}
-
-static vm_page_t
-i915_gem_wire_page(vm_object_t object, vm_pindex_t pindex, bool *fresh)
-{
- vm_page_t m;
- int rv;
-
- VM_OBJECT_ASSERT_WLOCKED(object);
- m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL);
- if (m->valid != VM_PAGE_BITS_ALL) {
- if (vm_pager_has_page(object, pindex, NULL, NULL)) {
- rv = vm_pager_get_pages(object, &m, 1, 0);
- if (rv != VM_PAGER_OK) {
- vm_page_lock(m);
- vm_page_free(m);
- vm_page_unlock(m);
- return (NULL);
- }
- if (fresh != NULL)
- *fresh = true;
- } else {
- pmap_zero_page(m);
- m->valid = VM_PAGE_BITS_ALL;
- m->dirty = 0;
- if (fresh != NULL)
- *fresh = false;
- }
- } else if (fresh != NULL) {
- *fresh = false;
- }
- vm_page_lock(m);
- vm_page_wire(m);
- vm_page_unlock(m);
- vm_page_xunbusy(m);
- atomic_add_long(&i915_gem_wired_pages_cnt, 1);
- return (m);
-}
-
-int
-i915_gem_flush_ring(struct intel_ring_buffer *ring, uint32_t invalidate_domains,
- uint32_t flush_domains)
-{
- int ret;
-
- if (((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) == 0)
- return 0;
-
- CTR3(KTR_DRM, "ring_flush %s %x %x", ring->name, invalidate_domains,
- flush_domains);
- ret = ring->flush(ring, invalidate_domains, flush_domains);
- if (ret)
- return ret;
-
- if (flush_domains & I915_GEM_GPU_DOMAINS)
- i915_gem_process_flushing_list(ring, flush_domains);
- return 0;
-}
-
-static int
-i915_ring_idle(struct intel_ring_buffer *ring)
-{
- int ret;
-
- if (list_empty(&ring->gpu_write_list) && list_empty(&ring->active_list))
- return 0;
-
- if (!list_empty(&ring->gpu_write_list)) {
- ret = i915_gem_flush_ring(ring, I915_GEM_GPU_DOMAINS,
- I915_GEM_GPU_DOMAINS);
- if (ret != 0)
- return ret;
- }
-
- return (i915_wait_request(ring, i915_gem_next_request_seqno(ring)));
-}
-
-int
-i915_gpu_idle(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv = dev->dev_private;
- struct intel_ring_buffer *ring;
- int ret, i;
-
- /* Flush everything onto the inactive list. */
- for_each_ring(ring, dev_priv, i) {
- ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID);
- if (ret)
- return ret;
-
- ret = i915_ring_idle(ring);
- if (ret)
- return ret;
-
- /* Is the device fubar? */
- if (!list_empty(&ring->gpu_write_list))
- return -EBUSY;
- }
-
- return 0;
-}
-
-static int
-i915_gem_check_wedge(struct drm_i915_private *dev_priv)
-{
- DRM_LOCK_ASSERT(dev_priv->dev);
-
- if (atomic_load_acq_int(&dev_priv->mm.wedged) != 0) {
- bool recovery_complete;
- /* Give the error handler a chance to run. */
- mtx_lock(&dev_priv->error_completion_lock);
- recovery_complete = (&dev_priv->error_completion) > 0;
- mtx_unlock(&dev_priv->error_completion_lock);
- return (recovery_complete ? -EIO : -EAGAIN);
- }
-
- return 0;
-}
-
-/*
- * Compare seqno against outstanding lazy request. Emit a request if they are
- * equal.
- */
-static int
-i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
-{
- int ret = 0;
-
- DRM_LOCK_ASSERT(ring->dev);
-
- if (seqno == ring->outstanding_lazy_request) {
- struct drm_i915_gem_request *request;
-
- request = malloc(sizeof(*request), DRM_I915_GEM,
- M_WAITOK | M_ZERO);
-
- ret = i915_add_request(ring, NULL, request);
- if (ret != 0) {
- free(request, DRM_I915_GEM);
- return (ret);
- }
-
- MPASS(seqno == request->seqno);
- }
- return ret;
-}
-
-static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
- bool interruptible)
-{
- drm_i915_private_t *dev_priv = ring->dev->dev_private;
- int ret = 0, flags;
-
- if (i915_seqno_passed(ring->get_seqno(ring), seqno))
- return 0;
-
- CTR2(KTR_DRM, "request_wait_begin %s %d", ring->name, seqno);
-
- mtx_lock(&dev_priv->irq_lock);
- if (!ring->irq_get(ring)) {
- mtx_unlock(&dev_priv->irq_lock);
- return (-ENODEV);
- }
-
- flags = interruptible ? PCATCH : 0;
- while (!i915_seqno_passed(ring->get_seqno(ring), seqno)
- && !atomic_load_acq_int(&dev_priv->mm.wedged) &&
- ret == 0) {
- ret = -msleep(ring, &dev_priv->irq_lock, flags, "915gwr", 0);
- if (ret == -ERESTART)
- ret = -ERESTARTSYS;
- }
- ring->irq_put(ring);
- mtx_unlock(&dev_priv->irq_lock);
-
- CTR3(KTR_DRM, "request_wait_end %s %d %d", ring->name, seqno, ret);
-
- return ret;
-}
-
-int
-i915_wait_request(struct intel_ring_buffer *ring, uint32_t seqno)
-{
- drm_i915_private_t *dev_priv;
- int ret;
-
- KASSERT(seqno != 0, ("Zero seqno"));
-
- dev_priv = ring->dev->dev_private;
- ret = 0;
-
- ret = i915_gem_check_wedge(dev_priv);
- if (ret)
- return ret;
-
- ret = i915_gem_check_olr(ring, seqno);
- if (ret)
- return ret;
-
- ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible);
- if (atomic_load_acq_int(&dev_priv->mm.wedged))
- ret = -EAGAIN;
-
- return (ret);
-}
-
static u32
i915_gem_get_seqno(struct drm_device *dev)
{
@@ -3391,10 +2113,11 @@ i915_gem_next_request_seqno(struct intel_ring_buffer *ring)
}
int
-i915_add_request(struct intel_ring_buffer *ring, struct drm_file *file,
- struct drm_i915_gem_request *request)
+i915_add_request(struct intel_ring_buffer *ring,
+ struct drm_file *file,
+ struct drm_i915_gem_request *request)
{
- drm_i915_private_t *dev_priv;
+ drm_i915_private_t *dev_priv = ring->dev->dev_private;
struct drm_i915_file_private *file_priv;
uint32_t seqno;
u32 request_ring_position;
@@ -3403,7 +2126,6 @@ i915_add_request(struct intel_ring_buffer *ring, struct drm_file *file,
KASSERT(request != NULL, ("NULL request in add"));
DRM_LOCK_ASSERT(ring->dev);
- dev_priv = ring->dev->dev_private;
seqno = i915_gem_next_request_seqno(ring);
request_ring_position = intel_ring_get_tail(ring);
@@ -3421,13 +2143,13 @@ i915_add_request(struct intel_ring_buffer *ring, struct drm_file *file,
was_empty = list_empty(&ring->request_list);
list_add_tail(&request->list, &ring->request_list);
- if (file != NULL) {
+ if (file) {
file_priv = file->driver_priv;
mtx_lock(&file_priv->mm.lck);
request->file_priv = file_priv;
list_add_tail(&request->client_list,
- &file_priv->mm.request_list);
+ &file_priv->mm.request_list);
mtx_unlock(&file_priv->mm.lck);
}
@@ -3442,7 +2164,8 @@ i915_add_request(struct intel_ring_buffer *ring, struct drm_file *file,
taskqueue_enqueue_timeout(dev_priv->tq,
&dev_priv->mm.retire_task, hz);
}
- return (0);
+
+ return 0;
}
static inline void
@@ -3456,41 +2179,16 @@ i915_gem_request_remove_from_client(struct drm_i915_gem_request *request)
DRM_LOCK_ASSERT(request->ring->dev);
mtx_lock(&file_priv->mm.lck);
- if (request->file_priv != NULL) {
- list_del(&request->client_list);
- request->file_priv = NULL;
- }
- mtx_unlock(&file_priv->mm.lck);
-}
-
-void
-i915_gem_release(struct drm_device *dev, struct drm_file *file)
-{
- struct drm_i915_file_private *file_priv;
- struct drm_i915_gem_request *request;
-
- file_priv = file->driver_priv;
-
- /* Clean up our request list when the client is going away, so that
- * later retire_requests won't dereference our soon-to-be-gone
- * file_priv.
- */
- mtx_lock(&file_priv->mm.lck);
- while (!list_empty(&file_priv->mm.request_list)) {
- request = list_first_entry(&file_priv->mm.request_list,
- struct drm_i915_gem_request,
- client_list);
+ if (request->file_priv) {
list_del(&request->client_list);
request->file_priv = NULL;
}
mtx_unlock(&file_priv->mm.lck);
}
-static void
-i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
- struct intel_ring_buffer *ring)
+static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
+ struct intel_ring_buffer *ring)
{
-
if (ring->dev != NULL)
DRM_LOCK_ASSERT(ring->dev);
@@ -3498,7 +2196,8 @@ i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
struct drm_i915_gem_request *request;
request = list_first_entry(&ring->request_list,
- struct drm_i915_gem_request, list);
+ struct drm_i915_gem_request,
+ list);
list_del(&request->list);
i915_gem_request_remove_from_client(request);
@@ -3509,7 +2208,8 @@ i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
struct drm_i915_gem_object *obj;
obj = list_first_entry(&ring->active_list,
- struct drm_i915_gem_object, ring_list);
+ struct drm_i915_gem_object,
+ ring_list);
obj->base.write_domain = 0;
list_del_init(&obj->gpu_write_list);
@@ -3517,8 +2217,7 @@ i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
}
}
-static void
-i915_gem_reset_fences(struct drm_device *dev)
+static void i915_gem_reset_fences(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int i;
@@ -3539,8 +2238,7 @@ i915_gem_reset_fences(struct drm_device *dev)
INIT_LIST_HEAD(&dev_priv->mm.fence_list);
}
-void
-i915_gem_reset(struct drm_device *dev)
+void i915_gem_reset(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj;
@@ -3653,6 +2351,270 @@ i915_gem_retire_requests(struct drm_device *dev)
i915_gem_retire_requests_ring(ring);
}
+static void
+i915_gem_process_flushing_list(struct intel_ring_buffer *ring,
+ uint32_t flush_domains)
+{
+ struct drm_i915_gem_object *obj, *next;
+ uint32_t old_write_domain;
+
+ list_for_each_entry_safe(obj, next, &ring->gpu_write_list,
+ gpu_write_list) {
+ if (obj->base.write_domain & flush_domains) {
+ old_write_domain = obj->base.write_domain;
+ obj->base.write_domain = 0;
+ list_del_init(&obj->gpu_write_list);
+ i915_gem_object_move_to_active(obj, ring,
+ i915_gem_next_request_seqno(ring));
+
+ CTR3(KTR_DRM, "object_change_domain process_flush %p %x %x",
+ obj, obj->base.read_domains, old_write_domain);
+ }
+ }
+}
+
+int
+i915_gem_flush_ring(struct intel_ring_buffer *ring, uint32_t invalidate_domains,
+ uint32_t flush_domains)
+{
+ int ret;
+
+ if (((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) == 0)
+ return 0;
+
+ CTR3(KTR_DRM, "ring_flush %s %x %x", ring->name, invalidate_domains,
+ flush_domains);
+ ret = ring->flush(ring, invalidate_domains, flush_domains);
+ if (ret)
+ return ret;
+
+ if (flush_domains & I915_GEM_GPU_DOMAINS)
+ i915_gem_process_flushing_list(ring, flush_domains);
+ return 0;
+}
+
+static void
+i915_gem_retire_task_handler(void *arg, int pending)
+{
+ drm_i915_private_t *dev_priv;
+ struct drm_device *dev;
+ struct intel_ring_buffer *ring;
+ bool idle;
+ int i;
+
+ dev_priv = arg;
+ dev = dev_priv->dev;
+
+ /* Come back later if the device is busy... */
+ if (!sx_try_xlock(&dev->dev_struct_lock)) {
+ taskqueue_enqueue_timeout(dev_priv->tq,
+ &dev_priv->mm.retire_task, hz);
+ return;
+ }
+
+ CTR0(KTR_DRM, "retire_task");
+
+ i915_gem_retire_requests(dev);
+
+ /* Send a periodic flush down the ring so we don't hold onto GEM
+ * objects indefinitely.
+ */
+ idle = true;
+ for_each_ring(ring, dev_priv, i) {
+ struct intel_ring_buffer *ring = &dev_priv->rings[i];
+
+ if (!list_empty(&ring->gpu_write_list)) {
+ struct drm_i915_gem_request *request;
+ int ret;
+
+ ret = i915_gem_flush_ring(ring,
+ 0, I915_GEM_GPU_DOMAINS);
+ request = malloc(sizeof(*request), DRM_I915_GEM,
+ M_WAITOK | M_ZERO);
+ if (ret || request == NULL ||
+ i915_add_request(ring, NULL, request))
+ free(request, DRM_I915_GEM);
+ }
+
+ idle &= list_empty(&ring->request_list);
+ }
+
+ if (!dev_priv->mm.suspended && !idle)
+ taskqueue_enqueue_timeout(dev_priv->tq,
+ &dev_priv->mm.retire_task, hz);
+
+ DRM_UNLOCK(dev);
+}
+
+int
+i915_gem_object_sync(struct drm_i915_gem_object *obj,
+ struct intel_ring_buffer *to)
+{
+ struct intel_ring_buffer *from = obj->ring;
+ u32 seqno;
+ int ret, idx;
+
+ if (from == NULL || to == from)
+ return 0;
+
+ if (to == NULL || !i915_semaphore_is_enabled(obj->base.dev))
+ return i915_gem_object_wait_rendering(obj);
+
+ idx = intel_ring_sync_index(from, to);
+
+ seqno = obj->last_rendering_seqno;
+ if (seqno <= from->sync_seqno[idx])
+ return 0;
+
+ if (seqno == from->outstanding_lazy_request) {
+ struct drm_i915_gem_request *request;
+
+ request = malloc(sizeof(*request), DRM_I915_GEM,
+ M_WAITOK | M_ZERO);
+ ret = i915_add_request(from, NULL, request);
+ if (ret) {
+ free(request, DRM_I915_GEM);
+ return ret;
+ }
+ seqno = request->seqno;
+ }
+
+
+ ret = to->sync_to(to, from, seqno);
+ if (!ret)
+ from->sync_seqno[idx] = seqno;
+
+ return ret;
+}
+
+static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj)
+{
+ u32 old_write_domain, old_read_domains;
+
+ /* Act a barrier for all accesses through the GTT */
+ mb();
+
+ /* Force a pagefault for domain tracking on next user access */
+ i915_gem_release_mmap(obj);
+
+ if ((obj->base.read_domains & I915_GEM_DOMAIN_GTT) == 0)
+ return;
+
+ old_read_domains = obj->base.read_domains;
+ old_write_domain = obj->base.write_domain;
+
+ obj->base.read_domains &= ~I915_GEM_DOMAIN_GTT;
+ obj->base.write_domain &= ~I915_GEM_DOMAIN_GTT;
+
+ CTR3(KTR_DRM, "object_change_domain finish gtt %p %x %x",
+ obj, old_read_domains, old_write_domain);
+}
+
+/**
+ * Unbinds an object from the GTT aperture.
+ */
+int
+i915_gem_object_unbind(struct drm_i915_gem_object *obj)
+{
+ drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
+ int ret = 0;
+
+ if (obj->gtt_space == NULL)
+ return 0;
+
+ if (obj->pin_count) {
+ DRM_ERROR("Attempting to unbind pinned buffer\n");
+ return -EINVAL;
+ }
+
+ ret = i915_gem_object_finish_gpu(obj);
+ if (ret == -ERESTARTSYS || ret == -EINTR)
+ return ret;
+
+ i915_gem_object_finish_gtt(obj);
+
+ if (ret == 0)
+ ret = i915_gem_object_set_to_cpu_domain(obj, 1);
+ if (ret == -ERESTARTSYS || ret == -EINTR)
+ return ret;
+ if (ret != 0) {
+ i915_gem_clflush_object(obj);
+ obj->base.read_domains = obj->base.write_domain =
+ I915_GEM_DOMAIN_CPU;
+ }
+
+ /* release the fence reg _after_ flushing */
+ ret = i915_gem_object_put_fence(obj);
+ if (ret)
+ return ret;
+
+ if (obj->has_global_gtt_mapping)
+ i915_gem_gtt_unbind_object(obj);
+ if (obj->has_aliasing_ppgtt_mapping) {
+ i915_ppgtt_unbind_object(dev_priv->mm.aliasing_ppgtt, obj);
+ obj->has_aliasing_ppgtt_mapping = 0;
+ }
+ i915_gem_gtt_finish_object(obj);
+
+ i915_gem_object_put_pages_gtt(obj);
+
+ list_del_init(&obj->gtt_list);
+ list_del_init(&obj->mm_list);
+ obj->map_and_fenceable = true;
+
+ drm_mm_put_block(obj->gtt_space);
+ obj->gtt_space = NULL;
+ obj->gtt_offset = 0;
+
+ if (i915_gem_object_is_purgeable(obj))
+ i915_gem_object_truncate(obj);
+ CTR1(KTR_DRM, "object_unbind %p", obj);
+
+ return ret;
+}
+
+static int
+i915_ring_idle(struct intel_ring_buffer *ring)
+{
+ int ret;
+
+ if (list_empty(&ring->gpu_write_list) && list_empty(&ring->active_list))
+ return 0;
+
+ if (!list_empty(&ring->gpu_write_list)) {
+ ret = i915_gem_flush_ring(ring, I915_GEM_GPU_DOMAINS,
+ I915_GEM_GPU_DOMAINS);
+ if (ret != 0)
+ return ret;
+ }
+
+ return (i915_wait_request(ring, i915_gem_next_request_seqno(ring)));
+}
+
+int i915_gpu_idle(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct intel_ring_buffer *ring;
+ int ret, i;
+
+ /* Flush everything onto the inactive list. */
+ for_each_ring(ring, dev_priv, i) {
+ ret = i915_switch_context(ring, NULL, DEFAULT_CONTEXT_ID);
+ if (ret)
+ return ret;
+
+ ret = i915_ring_idle(ring);
+ if (ret)
+ return ret;
+
+ /* Is the device fubar? */
+ if (!list_empty(&ring->gpu_write_list))
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
static void sandybridge_write_fence_reg(struct drm_device *dev, int reg,
struct drm_i915_gem_object *obj)
{
@@ -3803,13 +2765,14 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
struct drm_i915_fence_reg *fence,
bool enable)
{
- struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
- int reg = fence_number(dev_priv, fence);
+ struct drm_device *dev = obj->base.dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int fence_reg = fence_number(dev_priv, fence);
- i915_gem_write_fence(obj->base.dev, reg, enable ? obj : NULL);
+ i915_gem_write_fence(dev, fence_reg, enable ? obj : NULL);
if (enable) {
- obj->fence_reg = reg;
+ obj->fence_reg = fence_reg;
fence->obj = obj;
list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list);
} else {
@@ -3906,6 +2869,20 @@ i915_find_fence_reg(struct drm_device *dev)
return NULL;
}
+/**
+ * i915_gem_object_get_fence - set up fencing for an object
+ * @obj: object to map through a fence reg
+ *
+ * When mapping objects through the GTT, userspace wants to be able to write
+ * to them without having to worry about swizzling if the object is tiled.
+ * This function walks the fence regs looking for a free one for @obj,
+ * stealing one if it can't find any.
+ *
+ * It then sets up the reg based on the object's properties: address, pitch
+ * and tiling format.
+ *
+ * For an untiled surface, this removes any existing fence.
+ */
int
i915_gem_object_get_fence(struct drm_i915_gem_object *obj)
{
@@ -3924,8 +2901,7 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj)
return ret;
}
- ret = 0;
-
+ /* Just update our place in the LRU if our fence is getting reused. */
if (obj->fence_reg != I915_FENCE_REG_NONE) {
reg = &dev_priv->fence_regs[obj->fence_reg];
if (!obj->fence_dirty) {
@@ -3956,72 +2932,1097 @@ i915_gem_object_get_fence(struct drm_i915_gem_object *obj)
return 0;
}
-int
-i915_gem_init_object(struct drm_gem_object *obj)
+/**
+ * Finds free space in the GTT aperture and binds the object there.
+ */
+static int
+i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
+ unsigned alignment,
+ bool map_and_fenceable)
{
+ struct drm_device *dev = obj->base.dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_mm_node *free_space;
+ u32 size, fence_size, fence_alignment, unfenced_alignment;
+ bool mappable, fenceable;
+ int ret;
- printf("i915_gem_init_object called\n");
- return (0);
+ if (obj->madv != I915_MADV_WILLNEED) {
+ DRM_ERROR("Attempting to bind a purgeable object\n");
+ return -EINVAL;
+ }
+
+ fence_size = i915_gem_get_gtt_size(dev,
+ obj->base.size,
+ obj->tiling_mode);
+ fence_alignment = i915_gem_get_gtt_alignment(dev,
+ obj->base.size,
+ obj->tiling_mode);
+ unfenced_alignment =
+ i915_gem_get_unfenced_gtt_alignment(dev,
+ obj->base.size,
+ obj->tiling_mode);
+
+ if (alignment == 0)
+ alignment = map_and_fenceable ? fence_alignment :
+ unfenced_alignment;
+ if (map_and_fenceable && alignment & (fence_alignment - 1)) {
+ DRM_ERROR("Invalid object alignment requested %u\n", alignment);
+ return -EINVAL;
+ }
+
+ size = map_and_fenceable ? fence_size : obj->base.size;
+
+ /* If the object is bigger than the entire aperture, reject it early
+ * before evicting everything in a vain attempt to find space.
+ */
+ if (obj->base.size >
+ (map_and_fenceable ? dev_priv->mm.gtt_mappable_end : dev_priv->mm.gtt_total)) {
+ DRM_ERROR("Attempting to bind an object larger than the aperture\n");
+ return -E2BIG;
+ }
+
+ search_free:
+ if (map_and_fenceable)
+ free_space = drm_mm_search_free_in_range(
+ &dev_priv->mm.gtt_space, size, alignment, 0,
+ dev_priv->mm.gtt_mappable_end, 0);
+ else
+ free_space = drm_mm_search_free(&dev_priv->mm.gtt_space,
+ size, alignment, 0);
+ if (free_space != NULL) {
+ if (map_and_fenceable)
+ obj->gtt_space = drm_mm_get_block_range_generic(
+ free_space, size, alignment, 0, 0,
+ dev_priv->mm.gtt_mappable_end, 1);
+ else
+ obj->gtt_space = drm_mm_get_block_generic(free_space,
+ size, alignment, 0, 1);
+ }
+ if (obj->gtt_space == NULL) {
+ ret = i915_gem_evict_something(dev, size, alignment,
+ map_and_fenceable);
+ if (ret != 0)
+ return ret;
+ goto search_free;
+ }
+ ret = i915_gem_object_get_pages_gtt(obj, 0);
+ if (ret) {
+ drm_mm_put_block(obj->gtt_space);
+ obj->gtt_space = NULL;
+ /*
+ * i915_gem_object_get_pages_gtt() cannot return
+ * ENOMEM, since we use vm_page_grab().
+ */
+ return ret;
+ }
+
+ ret = i915_gem_gtt_prepare_object(obj);
+ if (ret) {
+ i915_gem_object_put_pages_gtt(obj);
+ drm_mm_put_block(obj->gtt_space);
+ obj->gtt_space = NULL;
+ if (i915_gem_evict_everything(dev, false))
+ return ret;
+ goto search_free;
+ }
+
+ if (!dev_priv->mm.aliasing_ppgtt)
+ i915_gem_gtt_bind_object(obj, obj->cache_level);
+
+ list_add_tail(&obj->gtt_list, &dev_priv->mm.gtt_list);
+ list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
+
+ KASSERT((obj->base.read_domains & I915_GEM_GPU_DOMAINS) == 0,
+ ("Object in gpu read domain"));
+ KASSERT((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0,
+ ("Object in gpu write domain"));
+
+ obj->gtt_offset = obj->gtt_space->start;
+
+ fenceable =
+ obj->gtt_space->size == fence_size &&
+ (obj->gtt_space->start & (fence_alignment - 1)) == 0;
+
+ mappable =
+ obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end;
+
+ obj->map_and_fenceable = mappable && fenceable;
+
+ CTR4(KTR_DRM, "object_bind %p %x %x %d", obj, obj->gtt_offset,
+ obj->base.size, map_and_fenceable);
+ return 0;
}
-static bool
-i915_gem_object_is_inactive(struct drm_i915_gem_object *obj)
+void
+i915_gem_clflush_object(struct drm_i915_gem_object *obj)
{
+ /* If we don't have a page list set up, then we're not pinned
+ * to GPU, and we can ignore the cache flush because it'll happen
+ * again at bind time.
+ */
+ if (obj->pages == NULL)
+ return;
- return !obj->active;
+ /* If the GPU is snooping the contents of the CPU cache,
+ * we do not need to manually clear the CPU cache lines. However,
+ * the caches are only snooped when the render cache is
+ * flushed/invalidated. As we always have to emit invalidations
+ * and flushes when moving into and out of the RENDER domain, correct
+ * snooping behaviour occurs naturally as the result of our domain
+ * tracking.
+ */
+ if (obj->cache_level != I915_CACHE_NONE)
+ return;
+
+ CTR1(KTR_DRM, "object_clflush %p", obj);
+
+ drm_clflush_pages(obj->pages, obj->base.size / PAGE_SIZE);
}
+/** Flushes the GTT write domain for the object if it's dirty. */
static void
-i915_gem_retire_task_handler(void *arg, int pending)
+i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj)
{
- drm_i915_private_t *dev_priv;
- struct drm_device *dev;
- struct intel_ring_buffer *ring;
- bool idle;
- int i;
+ uint32_t old_write_domain;
- dev_priv = arg;
- dev = dev_priv->dev;
+ if (obj->base.write_domain != I915_GEM_DOMAIN_GTT)
+ return;
- /* Come back later if the device is busy... */
- if (!sx_try_xlock(&dev->dev_struct_lock)) {
- taskqueue_enqueue_timeout(dev_priv->tq,
- &dev_priv->mm.retire_task, hz);
+ /* No actual flushing is required for the GTT write domain. Writes
+ * to it immediately go to main memory as far as we know, so there's
+ * no chipset flush. It also doesn't land in render cache.
+ *
+ * However, we do have to enforce the order so that all writes through
+ * the GTT land before any writes to the device, such as updates to
+ * the GATT itself.
+ */
+ wmb();
+
+ old_write_domain = obj->base.write_domain;
+ obj->base.write_domain = 0;
+
+ CTR3(KTR_DRM, "object_change_domain flush gtt_write %p %x %x", obj,
+ obj->base.read_domains, old_write_domain);
+}
+
+/** Flushes the CPU write domain for the object if it's dirty. */
+static void
+i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj)
+{
+ uint32_t old_write_domain;
+
+ if (obj->base.write_domain != I915_GEM_DOMAIN_CPU)
return;
+
+ i915_gem_clflush_object(obj);
+ intel_gtt_chipset_flush();
+ old_write_domain = obj->base.write_domain;
+ obj->base.write_domain = 0;
+
+ CTR3(KTR_DRM, "object_change_domain flush_cpu_write %p %x %x", obj,
+ obj->base.read_domains, old_write_domain);
+}
+
+static int
+i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj)
+{
+
+ if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0)
+ return (0);
+ return (i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain));
+}
+
+/**
+ * Moves a single object to the GTT read, and possibly write domain.
+ *
+ * This function returns when the move is complete, including waiting on
+ * flushes to occur.
+ */
+int
+i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
+{
+ drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
+ uint32_t old_write_domain, old_read_domains;
+ int ret;
+
+ /* Not valid to be called on unbound objects. */
+ if (obj->gtt_space == NULL)
+ return -EINVAL;
+
+ if (obj->base.write_domain == I915_GEM_DOMAIN_GTT)
+ return 0;
+
+ ret = i915_gem_object_flush_gpu_write_domain(obj);
+ if (ret)
+ return (ret);
+
+ if (obj->pending_gpu_write || write) {
+ ret = i915_gem_object_wait_rendering(obj);
+ if (ret)
+ return (ret);
}
- CTR0(KTR_DRM, "retire_task");
+ i915_gem_object_flush_cpu_write_domain(obj);
- i915_gem_retire_requests(dev);
+ old_write_domain = obj->base.write_domain;
+ old_read_domains = obj->base.read_domains;
- /* Send a periodic flush down the ring so we don't hold onto GEM
- * objects indefinitely.
+ /* It should now be out of any other write domains, and we can update
+ * the domain values for our changes.
*/
- idle = true;
- for_each_ring(ring, dev_priv, i) {
- struct intel_ring_buffer *ring = &dev_priv->rings[i];
+ KASSERT((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) == 0,
+ ("In GTT write domain"));
+ obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
+ if (write) {
+ obj->base.read_domains = I915_GEM_DOMAIN_GTT;
+ obj->base.write_domain = I915_GEM_DOMAIN_GTT;
+ obj->dirty = 1;
+ }
- if (!list_empty(&ring->gpu_write_list)) {
- struct drm_i915_gem_request *request;
- int ret;
+ CTR3(KTR_DRM, "object_change_domain set_to_gtt %p %x %x", obj,
+ old_read_domains, old_write_domain);
- ret = i915_gem_flush_ring(ring,
- 0, I915_GEM_GPU_DOMAINS);
- request = malloc(sizeof(*request), DRM_I915_GEM,
- M_WAITOK | M_ZERO);
- if (ret || request == NULL ||
- i915_add_request(ring, NULL, request))
- free(request, DRM_I915_GEM);
+ /* And bump the LRU for this access */
+ if (i915_gem_object_is_inactive(obj))
+ list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
+
+ return 0;
+}
+
+int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
+ enum i915_cache_level cache_level)
+{
+ struct drm_device *dev = obj->base.dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int ret;
+
+ if (obj->cache_level == cache_level)
+ return 0;
+
+ if (obj->pin_count) {
+ DRM_DEBUG("can not change the cache level of pinned objects\n");
+ return -EBUSY;
+ }
+
+ if (obj->gtt_space) {
+ ret = i915_gem_object_finish_gpu(obj);
+ if (ret)
+ return ret;
+
+ i915_gem_object_finish_gtt(obj);
+
+ /* Before SandyBridge, you could not use tiling or fence
+ * registers with snooped memory, so relinquish any fences
+ * currently pointing to our region in the aperture.
+ */
+ if (INTEL_INFO(obj->base.dev)->gen < 6) {
+ ret = i915_gem_object_put_fence(obj);
+ if (ret)
+ return ret;
}
- idle &= list_empty(&ring->request_list);
+ if (obj->has_global_gtt_mapping)
+ i915_gem_gtt_bind_object(obj, cache_level);
+ if (obj->has_aliasing_ppgtt_mapping)
+ i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
+ obj, cache_level);
}
- if (!dev_priv->mm.suspended && !idle)
+ if (cache_level == I915_CACHE_NONE) {
+ u32 old_read_domains, old_write_domain;
+
+ /* If we're coming from LLC cached, then we haven't
+ * actually been tracking whether the data is in the
+ * CPU cache or not, since we only allow one bit set
+ * in obj->write_domain and have been skipping the clflushes.
+ * Just set it to the CPU cache for now.
+ */
+ KASSERT((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) == 0,
+ ("obj %p in CPU write domain", obj));
+ KASSERT((obj->base.read_domains & ~I915_GEM_DOMAIN_CPU) == 0,
+ ("obj %p in CPU read domain", obj));
+
+ old_read_domains = obj->base.read_domains;
+ old_write_domain = obj->base.write_domain;
+
+ obj->base.read_domains = I915_GEM_DOMAIN_CPU;
+ obj->base.write_domain = I915_GEM_DOMAIN_CPU;
+
+ CTR3(KTR_DRM, "object_change_domain set_cache_level %p %x %x",
+ obj, old_read_domains, old_write_domain);
+ }
+
+ obj->cache_level = cache_level;
+ return 0;
+}
+
+static bool is_pin_display(struct drm_i915_gem_object *obj)
+{
+ /* There are 3 sources that pin objects:
+ * 1. The display engine (scanouts, sprites, cursors);
+ * 2. Reservations for execbuffer;
+ * 3. The user.
+ *
+ * We can ignore reservations as we hold the struct_mutex and
+ * are only called outside of the reservation path. The user
+ * can only increment pin_count once, and so if after
+ * subtracting the potential reference by the user, any pin_count
+ * remains, it must be due to another use by the display engine.
+ */
+ return obj->pin_count - !!obj->user_pin_count;
+}
+
+int
+i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
+ u32 alignment,
+ struct intel_ring_buffer *pipelined)
+{
+ u32 old_read_domains, old_write_domain;
+ int ret;
+
+ ret = i915_gem_object_flush_gpu_write_domain(obj);
+ if (ret)
+ return ret;
+
+ if (pipelined != obj->ring) {
+ ret = i915_gem_object_sync(obj, pipelined);
+ if (ret)
+ return ret;
+ }
+
+ /* Mark the pin_display early so that we account for the
+ * display coherency whilst setting up the cache domains.
+ */
+ obj->pin_display = true;
+
+ /* The display engine is not coherent with the LLC cache on gen6. As
+ * a result, we make sure that the pinning that is about to occur is
+ * done with uncached PTEs. This is lowest common denominator for all
+ * chipsets.
+ *
+ * However for gen6+, we could do better by using the GFDT bit instead
+ * of uncaching, which would allow us to flush all the LLC-cached data
+ * with that bit in the PTE to main memory with just one PIPE_CONTROL.
+ */
+ ret = i915_gem_object_set_cache_level(obj, I915_CACHE_NONE);
+ if (ret)
+ goto err_unpin_display;
+
+ /* As the user may map the buffer once pinned in the display plane
+ * (e.g. libkms for the bootup splash), we have to ensure that we
+ * always use map_and_fenceable for all scanout buffers.
+ */
+ ret = i915_gem_object_pin(obj, alignment, true);
+ if (ret)
+ goto err_unpin_display;
+
+ i915_gem_object_flush_cpu_write_domain(obj);
+
+ old_write_domain = obj->base.write_domain;
+ old_read_domains = obj->base.read_domains;
+
+ KASSERT((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) == 0,
+ ("obj %p in GTT write domain", obj));
+ obj->base.read_domains |= I915_GEM_DOMAIN_GTT;
+
+ CTR3(KTR_DRM, "object_change_domain pin_to_display_plan %p %x %x",
+ obj, old_read_domains, obj->base.write_domain);
+
+ return 0;
+
+err_unpin_display:
+ obj->pin_display = is_pin_display(obj);
+ return ret;
+}
+
+void
+i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj)
+{
+ i915_gem_object_unpin(obj);
+ obj->pin_display = is_pin_display(obj);
+}
+
+int
+i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj)
+{
+ int ret;
+
+ if ((obj->base.read_domains & I915_GEM_GPU_DOMAINS) == 0)
+ return 0;
+
+ if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
+ ret = i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain);
+ if (ret)
+ return ret;
+ }
+
+ ret = i915_gem_object_wait_rendering(obj);
+ if (ret)
+ return ret;
+
+ /* Ensure that we invalidate the GPU's caches and TLBs. */
+ obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS;
+ return 0;
+}
+
+int
+i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)
+{
+ uint32_t old_write_domain, old_read_domains;
+ int ret;
+
+ if (obj->base.write_domain == I915_GEM_DOMAIN_CPU)
+ return 0;
+
+ ret = i915_gem_object_flush_gpu_write_domain(obj);
+ if (ret)
+ return ret;
+
+ if (write || obj->pending_gpu_write) {
+ ret = i915_gem_object_wait_rendering(obj);
+ if (ret)
+ return ret;
+ }
+
+ i915_gem_object_flush_gtt_write_domain(obj);
+
+ old_write_domain = obj->base.write_domain;
+ old_read_domains = obj->base.read_domains;
+
+ /* Flush the CPU cache if it's still invalid. */
+ if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0) {
+ i915_gem_clflush_object(obj);
+
+ obj->base.read_domains |= I915_GEM_DOMAIN_CPU;
+ }
+
+ /* It should now be out of any other write domains, and we can update
+ * the domain values for our changes.
+ */
+ KASSERT((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) == 0,
+ ("In cpu write domain"));
+
+ /* If we're writing through the CPU, then the GPU read domains will
+ * need to be invalidated at next use.
+ */
+ if (write) {
+ obj->base.read_domains = I915_GEM_DOMAIN_CPU;
+ obj->base.write_domain = I915_GEM_DOMAIN_CPU;
+ }
+
+ CTR3(KTR_DRM, "object_change_domain set_to_cpu %p %x %x", obj,
+ old_read_domains, old_write_domain);
+
+ return 0;
+}
+
+/* Throttle our rendering by waiting until the ring has completed our requests
+ * emitted over 20 msec ago.
+ *
+ * Note that if we were to use the current jiffies each time around the loop,
+ * we wouldn't escape the function with any frames outstanding if the time to
+ * render a frame was over 20ms.
+ *
+ * This should get us reasonable parallelism between CPU and GPU but also
+ * relatively low latency when blocking on a particular request to finish.
+ */
+static int
+i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ struct drm_i915_file_private *file_priv = file->driver_priv;
+ unsigned long recent_enough = ticks - (20 * hz / 1000);
+ struct drm_i915_gem_request *request;
+ struct intel_ring_buffer *ring = NULL;
+ u32 seqno = 0;
+ int ret;
+
+ if (atomic_load_acq_int(&dev_priv->mm.wedged))
+ return -EIO;
+
+ mtx_lock(&file_priv->mm.lck);
+ list_for_each_entry(request, &file_priv->mm.request_list, client_list) {
+ if (time_after_eq(request->emitted_jiffies, recent_enough))
+ break;
+ ring = request->ring;
+ seqno = request->seqno;
+ }
+ mtx_unlock(&file_priv->mm.lck);
+ if (seqno == 0)
+ return 0;
+
+ ret = __wait_seqno(ring, seqno, true);
+ if (ret == 0)
taskqueue_enqueue_timeout(dev_priv->tq,
- &dev_priv->mm.retire_task, hz);
+ &dev_priv->mm.retire_task, 0);
+
+ return ret;
+}
+
+int
+i915_gem_object_pin(struct drm_i915_gem_object *obj,
+ uint32_t alignment,
+ bool map_and_fenceable)
+{
+ int ret;
+
+ if (obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)
+ return -EBUSY;
+
+ if (obj->gtt_space != NULL) {
+ if ((alignment && obj->gtt_offset & (alignment - 1)) ||
+ (map_and_fenceable && !obj->map_and_fenceable)) {
+ DRM_DEBUG("bo is already pinned with incorrect alignment:"
+ " offset=%x, req.alignment=%x, req.map_and_fenceable=%d,"
+ " obj->map_and_fenceable=%d\n",
+ obj->gtt_offset, alignment,
+ map_and_fenceable,
+ obj->map_and_fenceable);
+ ret = i915_gem_object_unbind(obj);
+ if (ret)
+ return ret;
+ }
+ }
+
+ if (obj->gtt_space == NULL) {
+ ret = i915_gem_object_bind_to_gtt(obj, alignment,
+ map_and_fenceable);
+ if (ret)
+ return ret;
+ }
+
+ if (!obj->has_global_gtt_mapping && map_and_fenceable)
+ i915_gem_gtt_bind_object(obj, obj->cache_level);
+
+ obj->pin_count++;
+ obj->pin_mappable |= map_and_fenceable;
+ return 0;
+}
+
+void
+i915_gem_object_unpin(struct drm_i915_gem_object *obj)
+{
+
+ KASSERT(obj->pin_count != 0, ("zero pin count"));
+ KASSERT(obj->gtt_space != NULL, ("No gtt mapping"));
+
+ if (--obj->pin_count == 0)
+ obj->pin_mappable = false;
+}
+
+int
+i915_gem_pin_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_i915_gem_pin *args = data;
+ struct drm_i915_gem_object *obj;
+ struct drm_gem_object *gobj;
+ int ret;
+
+ ret = i915_mutex_lock_interruptible(dev);
+ if (ret)
+ return ret;
+
+ gobj = drm_gem_object_lookup(dev, file, args->handle);
+ if (gobj == NULL) {
+ ret = -ENOENT;
+ goto unlock;
+ }
+ obj = to_intel_bo(gobj);
+
+ if (obj->madv != I915_MADV_WILLNEED) {
+ DRM_ERROR("Attempting to pin a purgeable buffer\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (obj->pin_filp != NULL && obj->pin_filp != file) {
+ DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
+ args->handle);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ obj->user_pin_count++;
+ obj->pin_filp = file;
+ if (obj->user_pin_count == 1) {
+ ret = i915_gem_object_pin(obj, args->alignment, true);
+ if (ret)
+ goto out;
+ }
+
+ /* XXX - flush the CPU caches for pinned objects
+ * as the X server doesn't manage domains yet
+ */
+ i915_gem_object_flush_cpu_write_domain(obj);
+ args->offset = obj->gtt_offset;
+out:
+ drm_gem_object_unreference(&obj->base);
+unlock:
+ DRM_UNLOCK(dev);
+ return ret;
+}
+
+int
+i915_gem_unpin_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_i915_gem_pin *args = data;
+ struct drm_i915_gem_object *obj;
+ int ret;
+
+ ret = i915_mutex_lock_interruptible(dev);
+ if (ret)
+ return ret;
+
+ obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+ if (&obj->base == NULL) {
+ ret = -ENOENT;
+ goto unlock;
+ }
+
+ if (obj->pin_filp != file) {
+ DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n",
+ args->handle);
+ ret = -EINVAL;
+ goto out;
+ }
+ obj->user_pin_count--;
+ if (obj->user_pin_count == 0) {
+ obj->pin_filp = NULL;
+ i915_gem_object_unpin(obj);
+ }
+
+out:
+ drm_gem_object_unreference(&obj->base);
+unlock:
+ DRM_UNLOCK(dev);
+ return ret;
+}
+
+int
+i915_gem_busy_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file)
+{
+ struct drm_i915_gem_busy *args = data;
+ struct drm_i915_gem_object *obj;
+ int ret;
+
+ ret = i915_mutex_lock_interruptible(dev);
+ if (ret)
+ return ret;
+
+ obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
+ if (&obj->base == NULL) {
+ ret = -ENOENT;
+ goto unlock;
+ }
+
+ args->busy = obj->active;
+ if (args->busy) {
+ if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
+ ret = i915_gem_flush_ring(obj->ring,
+ 0, obj->base.write_domain);
+ } else {
+ ret = i915_gem_check_olr(obj->ring,
+ obj->last_rendering_seqno);
+ }
+
+ i915_gem_retire_requests_ring(obj->ring);
+ args->busy = obj->active;
+ }
+
+ drm_gem_object_unreference(&obj->base);
+unlock:
+ DRM_UNLOCK(dev);
+ return ret;
+}
+
+int
+i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+
+ return i915_gem_ring_throttle(dev, file_priv);
+}
+
+int
+i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_i915_gem_madvise *args = data;
+ struct drm_i915_gem_object *obj;
+ int ret;
+
+ switch (args->madv) {
+ case I915_MADV_DONTNEED:
+ case I915_MADV_WILLNEED:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = i915_mutex_lock_interruptible(dev);
+ if (ret)
+ return ret;
+
+ obj = to_intel_bo(drm_gem_object_lookup(dev, file_priv, args->handle));
+ if (&obj->base == NULL) {
+ ret = -ENOENT;
+ goto unlock;
+ }
+
+ if (obj->pin_count) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (obj->madv != I915_MADV_PURGED_INTERNAL)
+ obj->madv = args->madv;
+
+ /* if the object is no longer attached, discard its backing storage */
+ if (i915_gem_object_is_purgeable(obj) && obj->gtt_space == NULL)
+ i915_gem_object_truncate(obj);
+
+ args->retained = obj->madv != I915_MADV_PURGED_INTERNAL;
+
+out:
+ drm_gem_object_unreference(&obj->base);
+unlock:
DRM_UNLOCK(dev);
+ return ret;
+}
+
+struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
+ size_t size)
+{
+ struct drm_i915_private *dev_priv;
+ struct drm_i915_gem_object *obj;
+
+ dev_priv = dev->dev_private;
+
+ obj = malloc(sizeof(*obj), DRM_I915_GEM, M_WAITOK | M_ZERO);
+
+ if (drm_gem_object_init(dev, &obj->base, size) != 0) {
+ free(obj, DRM_I915_GEM);
+ return NULL;
+ }
+
+ obj->base.write_domain = I915_GEM_DOMAIN_CPU;
+ obj->base.read_domains = I915_GEM_DOMAIN_CPU;
+
+ if (HAS_LLC(dev)) {
+ /* On some devices, we can have the GPU use the LLC (the CPU
+ * cache) for about a 10% performance improvement
+ * compared to uncached. Graphics requests other than
+ * display scanout are coherent with the CPU in
+ * accessing this cache. This means in this mode we
+ * don't need to clflush on the CPU side, and on the
+ * GPU side we only need to flush internal caches to
+ * get data visible to the CPU.
+ *
+ * However, we maintain the display planes as UC, and so
+ * need to rebind when first used as such.
+ */
+ obj->cache_level = I915_CACHE_LLC;
+ } else
+ obj->cache_level = I915_CACHE_NONE;
+ obj->base.driver_private = NULL;
+ obj->fence_reg = I915_FENCE_REG_NONE;
+ INIT_LIST_HEAD(&obj->mm_list);
+ INIT_LIST_HEAD(&obj->gtt_list);
+ INIT_LIST_HEAD(&obj->ring_list);
+ INIT_LIST_HEAD(&obj->exec_list);
+ INIT_LIST_HEAD(&obj->gpu_write_list);
+ obj->madv = I915_MADV_WILLNEED;
+ /* Avoid an unnecessary call to unbind on the first bind. */
+ obj->map_and_fenceable = true;
+
+ i915_gem_info_add_obj(dev_priv, size);
+
+ return obj;
+}
+
+int i915_gem_init_object(struct drm_gem_object *obj)
+{
+ printf("i915_gem_init_object called\n");
+
+ return 0;
+}
+
+void i915_gem_free_object(struct drm_gem_object *gem_obj)
+{
+ struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
+ struct drm_device *dev = obj->base.dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ CTR1(KTR_DRM, "object_destroy_tail %p", obj);
+
+ if (obj->phys_obj)
+ i915_gem_detach_phys_object(dev, obj);
+
+ obj->pin_count = 0;
+ if (i915_gem_object_unbind(obj) == -ERESTARTSYS) {
+ bool was_interruptible;
+
+ was_interruptible = dev_priv->mm.interruptible;
+ dev_priv->mm.interruptible = false;
+
+ if (i915_gem_object_unbind(obj))
+ printf("i915_gem_free_object: unbind\n");
+
+ dev_priv->mm.interruptible = was_interruptible;
+ }
+
+ drm_gem_free_mmap_offset(&obj->base);
+ drm_gem_object_release(&obj->base);
+ i915_gem_info_remove_obj(dev_priv, obj->base.size);
+
+ free(obj->bit_17, DRM_I915_GEM);
+ free(obj, DRM_I915_GEM);
+}
+
+int
+i915_gem_idle(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int ret;
+
+ DRM_LOCK(dev);
+
+ if (dev_priv->mm.suspended) {
+ DRM_UNLOCK(dev);
+ return 0;
+ }
+
+ ret = i915_gpu_idle(dev);
+ if (ret) {
+ DRM_UNLOCK(dev);
+ return ret;
+ }
+ i915_gem_retire_requests(dev);
+
+ /* Under UMS, be paranoid and evict. */
+ if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
+ ret = i915_gem_evict_everything(dev, false);
+ if (ret) {
+ DRM_UNLOCK(dev);
+ return ret;
+ }
+ }
+
+ i915_gem_reset_fences(dev);
+
+ /* Hack! Don't let anybody do execbuf while we don't control the chip.
+ * We need to replace this with a semaphore, or something.
+ * And not confound mm.suspended!
+ */
+ dev_priv->mm.suspended = 1;
+ callout_stop(&dev_priv->hangcheck_timer);
+
+ i915_kernel_lost_context(dev);
+ i915_gem_cleanup_ringbuffer(dev);
+
+ DRM_UNLOCK(dev);
+
+ /* Cancel the retire work handler, which should be idle now. */
+ taskqueue_cancel_timeout(dev_priv->tq, &dev_priv->mm.retire_task, NULL);
+
+ return ret;
+}
+
+void i915_gem_init_swizzling(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ if (INTEL_INFO(dev)->gen < 5 ||
+ dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_NONE)
+ return;
+
+ I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) |
+ DISP_TILE_SURFACE_SWIZZLING);
+
+ if (IS_GEN5(dev))
+ return;
+
+ I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_SWZCTL);
+ if (IS_GEN6(dev))
+ I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB));
+ else
+ I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB));
+}
+
+int
+i915_gem_init_hw(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int ret;
+
+ i915_gem_init_swizzling(dev);
+
+ ret = intel_init_render_ring_buffer(dev);
+ if (ret)
+ return ret;
+
+ if (HAS_BSD(dev)) {
+ ret = intel_init_bsd_ring_buffer(dev);
+ if (ret)
+ goto cleanup_render_ring;
+ }
+
+ if (HAS_BLT(dev)) {
+ ret = intel_init_blt_ring_buffer(dev);
+ if (ret)
+ goto cleanup_bsd_ring;
+ }
+
+ dev_priv->next_seqno = 1;
+
+ /*
+ * XXX: There was some w/a described somewhere suggesting loading
+ * contexts before PPGTT.
+ */
+ i915_gem_context_init(dev);
+ i915_gem_init_ppgtt(dev);
+
+ return 0;
+
+cleanup_bsd_ring:
+ intel_cleanup_ring_buffer(&dev_priv->rings[VCS]);
+cleanup_render_ring:
+ intel_cleanup_ring_buffer(&dev_priv->rings[RCS]);
+ return ret;
+}
+
+static bool
+intel_enable_ppgtt(struct drm_device *dev)
+{
+ if (i915_enable_ppgtt >= 0)
+ return i915_enable_ppgtt;
+
+ /* Disable ppgtt on SNB if VT-d is on. */
+ if (INTEL_INFO(dev)->gen == 6 && intel_iommu_enabled)
+ return false;
+
+ return true;
+}
+
+int i915_gem_init(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ unsigned long gtt_size, mappable_size;
+ int ret;
+
+ gtt_size = dev_priv->mm.gtt.gtt_total_entries << PAGE_SHIFT;
+ mappable_size = dev_priv->mm.gtt.gtt_mappable_entries << PAGE_SHIFT;
+
+ DRM_LOCK(dev);
+ if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
+ /* PPGTT pdes are stolen from global gtt ptes, so shrink the
+ * aperture accordingly when using aliasing ppgtt. */
+ gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
+
+ i915_gem_init_global_gtt(dev, 0, mappable_size, gtt_size);
+
+ ret = i915_gem_init_aliasing_ppgtt(dev);
+ if (ret) {
+ DRM_UNLOCK(dev);
+ return ret;
+ }
+ } else {
+ /* Let GEM Manage all of the aperture.
+ *
+ * However, leave one page at the end still bound to the scratch
+ * page. There are a number of places where the hardware
+ * apparently prefetches past the end of the object, and we've
+ * seen multiple hangs with the GPU head pointer stuck in a
+ * batchbuffer bound at the last page of the aperture. One page
+ * should be enough to keep any prefetching inside of the
+ * aperture.
+ */
+ i915_gem_init_global_gtt(dev, 0, mappable_size,
+ gtt_size);
+ }
+
+ ret = i915_gem_init_hw(dev);
+ DRM_UNLOCK(dev);
+ if (ret) {
+ i915_gem_cleanup_aliasing_ppgtt(dev);
+ return ret;
+ }
+
+ /* Allow hardware batchbuffers unless told otherwise, but not for KMS. */
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ dev_priv->dri1.allow_batchbuffer = 1;
+ return 0;
+}
+
+void
+i915_gem_cleanup_ringbuffer(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct intel_ring_buffer *ring;
+ int i;
+
+ for_each_ring(ring, dev_priv, i)
+ intel_cleanup_ring_buffer(ring);
+}
+
+int
+i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ int ret;
+
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
+
+ if (atomic_load_acq_int(&dev_priv->mm.wedged) != 0) {
+ DRM_ERROR("Reenabling wedged hardware, good luck\n");
+ atomic_store_rel_int(&dev_priv->mm.wedged, 0);
+ }
+
+ DRM_LOCK(dev);
+ dev_priv->mm.suspended = 0;
+
+ ret = i915_gem_init_hw(dev);
+ if (ret != 0) {
+ DRM_UNLOCK(dev);
+ return ret;
+ }
+
+ KASSERT(list_empty(&dev_priv->mm.active_list), ("active list"));
+ KASSERT(list_empty(&dev_priv->mm.flushing_list), ("flushing list"));
+ KASSERT(list_empty(&dev_priv->mm.inactive_list), ("inactive list"));
+ DRM_UNLOCK(dev);
+
+ ret = drm_irq_install(dev);
+ if (ret)
+ goto cleanup_ringbuffer;
+
+ return 0;
+
+cleanup_ringbuffer:
+ DRM_LOCK(dev);
+ i915_gem_cleanup_ringbuffer(dev);
+ dev_priv->mm.suspended = 1;
+ DRM_UNLOCK(dev);
+
+ return ret;
+}
+
+int
+i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ return 0;
+
+ drm_irq_uninstall(dev);
+ return i915_gem_idle(dev);
}
void
@@ -4033,64 +4034,123 @@ i915_gem_lastclose(struct drm_device *dev)
return;
ret = i915_gem_idle(dev);
- if (ret != 0)
+ if (ret)
DRM_ERROR("failed to idle hardware: %d\n", ret);
}
-static int
-i915_gem_init_phys_object(struct drm_device *dev, int id, int size, int align)
+static void
+init_ring_lists(struct intel_ring_buffer *ring)
{
- drm_i915_private_t *dev_priv;
+ INIT_LIST_HEAD(&ring->active_list);
+ INIT_LIST_HEAD(&ring->request_list);
+ INIT_LIST_HEAD(&ring->gpu_write_list);
+}
+
+void
+i915_gem_load(struct drm_device *dev)
+{
+ int i;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+
+ INIT_LIST_HEAD(&dev_priv->mm.active_list);
+ INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
+ INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
+ INIT_LIST_HEAD(&dev_priv->mm.fence_list);
+ INIT_LIST_HEAD(&dev_priv->mm.gtt_list);
+ for (i = 0; i < I915_NUM_RINGS; i++)
+ init_ring_lists(&dev_priv->rings[i]);
+ for (i = 0; i < I915_MAX_NUM_FENCES; i++)
+ INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
+ TIMEOUT_TASK_INIT(dev_priv->tq, &dev_priv->mm.retire_task, 0,
+ i915_gem_retire_task_handler, dev_priv);
+ dev_priv->error_completion = 0;
+
+ /* On GEN3 we really need to make sure the ARB C3 LP bit is set */
+ if (IS_GEN3(dev)) {
+ I915_WRITE(MI_ARB_STATE,
+ _MASKED_BIT_ENABLE(MI_ARB_C3_LP_WRITE_ENABLE));
+ }
+
+ dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
+
+ /* Old X drivers will take 0-2 for front, back, depth buffers */
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ dev_priv->fence_reg_start = 3;
+
+ if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
+ dev_priv->num_fence_regs = 16;
+ else
+ dev_priv->num_fence_regs = 8;
+
+ /* Initialize fence registers to zero */
+ i915_gem_reset_fences(dev);
+
+ i915_gem_detect_bit_6_swizzle(dev);
+ dev_priv->mm.interruptible = true;
+
+ dev_priv->mm.i915_lowmem = EVENTHANDLER_REGISTER(vm_lowmem,
+ i915_gem_lowmem, dev, EVENTHANDLER_PRI_ANY);
+}
+
+void
+i915_gem_unload(struct drm_device *dev)
+{
+ struct drm_i915_private *dev_priv;
+
+ dev_priv = dev->dev_private;
+ EVENTHANDLER_DEREGISTER(vm_lowmem, dev_priv->mm.i915_lowmem);
+}
+
+static int i915_gem_init_phys_object(struct drm_device *dev,
+ int id, int size, int align)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_phys_object *phys_obj;
int ret;
- dev_priv = dev->dev_private;
- if (dev_priv->mm.phys_objs[id - 1] != NULL || size == 0)
- return (0);
+ if (dev_priv->mm.phys_objs[id - 1] || !size)
+ return 0;
- phys_obj = malloc(sizeof(struct drm_i915_gem_phys_object), DRM_I915_GEM,
- M_WAITOK | M_ZERO);
+ phys_obj = malloc(sizeof(struct drm_i915_gem_phys_object),
+ DRM_I915_GEM, M_WAITOK | M_ZERO);
phys_obj->id = id;
phys_obj->handle = drm_pci_alloc(dev, size, align, BUS_SPACE_MAXADDR);
- if (phys_obj->handle == NULL) {
+ if (!phys_obj->handle) {
ret = -ENOMEM;
- goto free_obj;
+ goto kfree_obj;
}
pmap_change_attr((vm_offset_t)phys_obj->handle->vaddr,
size / PAGE_SIZE, PAT_WRITE_COMBINING);
dev_priv->mm.phys_objs[id - 1] = phys_obj;
- return (0);
-
-free_obj:
+ return 0;
+kfree_obj:
free(phys_obj, DRM_I915_GEM);
- return (ret);
+ return ret;
}
-static void
-i915_gem_free_phys_object(struct drm_device *dev, int id)
+static void i915_gem_free_phys_object(struct drm_device *dev, int id)
{
- drm_i915_private_t *dev_priv;
+ drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_i915_gem_phys_object *phys_obj;
- dev_priv = dev->dev_private;
- if (dev_priv->mm.phys_objs[id - 1] == NULL)
+ if (!dev_priv->mm.phys_objs[id - 1])
return;
phys_obj = dev_priv->mm.phys_objs[id - 1];
- if (phys_obj->cur_obj != NULL)
+ if (phys_obj->cur_obj) {
i915_gem_detach_phys_object(dev, phys_obj->cur_obj);
+ }
drm_pci_free(dev, phys_obj->handle);
free(phys_obj, DRM_I915_GEM);
dev_priv->mm.phys_objs[id - 1] = NULL;
}
-void
-i915_gem_free_all_phys_object(struct drm_device *dev)
+void i915_gem_free_all_phys_object(struct drm_device *dev)
{
int i;
@@ -4098,41 +4158,40 @@ i915_gem_free_all_phys_object(struct drm_device *dev)
i915_gem_free_phys_object(dev, i);
}
-void
-i915_gem_detach_phys_object(struct drm_device *dev,
- struct drm_i915_gem_object *obj)
+void i915_gem_detach_phys_object(struct drm_device *dev,
+ struct drm_i915_gem_object *obj)
{
- vm_page_t m;
+ vm_page_t page;
struct sf_buf *sf;
char *vaddr, *dst;
int i, page_count;
- if (obj->phys_obj == NULL)
+ if (!obj->phys_obj)
return;
vaddr = obj->phys_obj->handle->vaddr;
page_count = obj->base.size / PAGE_SIZE;
VM_OBJECT_WLOCK(obj->base.vm_obj);
for (i = 0; i < page_count; i++) {
- m = i915_gem_wire_page(obj->base.vm_obj, i, NULL);
- if (m == NULL)
+ page = i915_gem_wire_page(obj->base.vm_obj, i, NULL);
+ if (page == NULL)
continue; /* XXX */
VM_OBJECT_WUNLOCK(obj->base.vm_obj);
- sf = sf_buf_alloc(m, 0);
+ sf = sf_buf_alloc(page, 0);
if (sf != NULL) {
dst = (char *)sf_buf_kva(sf);
memcpy(dst, vaddr + IDX_TO_OFF(i), PAGE_SIZE);
sf_buf_free(sf);
}
- drm_clflush_pages(&m, 1);
+ drm_clflush_pages(&page, 1);
VM_OBJECT_WLOCK(obj->base.vm_obj);
- vm_page_reference(m);
- vm_page_lock(m);
- vm_page_dirty(m);
- vm_page_unwire(m, PQ_INACTIVE);
- vm_page_unlock(m);
+ vm_page_reference(page);
+ vm_page_lock(page);
+ vm_page_dirty(page);
+ vm_page_unwire(page, PQ_INACTIVE);
+ vm_page_unlock(page);
atomic_add_long(&i915_gem_wired_pages_cnt, -1);
}
VM_OBJECT_WUNLOCK(obj->base.vm_obj);
@@ -4144,30 +4203,35 @@ i915_gem_detach_phys_object(struct drm_device *dev,
int
i915_gem_attach_phys_object(struct drm_device *dev,
- struct drm_i915_gem_object *obj, int id, int align)
+ struct drm_i915_gem_object *obj,
+ int id,
+ int align)
{
- drm_i915_private_t *dev_priv;
- vm_page_t m;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ vm_page_t page;
struct sf_buf *sf;
char *dst, *src;
- int i, page_count, ret;
+ int ret = 0;
+ int page_count;
+ int i;
if (id > I915_MAX_PHYS_OBJECT)
- return (-EINVAL);
+ return -EINVAL;
- if (obj->phys_obj != NULL) {
+ if (obj->phys_obj) {
if (obj->phys_obj->id == id)
- return (0);
+ return 0;
i915_gem_detach_phys_object(dev, obj);
}
- dev_priv = dev->dev_private;
- if (dev_priv->mm.phys_objs[id - 1] == NULL) {
- ret = i915_gem_init_phys_object(dev, id, obj->base.size, align);
- if (ret != 0) {
+ /* create a new object */
+ if (!dev_priv->mm.phys_objs[id - 1]) {
+ ret = i915_gem_init_phys_object(dev, id,
+ obj->base.size, align);
+ if (ret) {
DRM_ERROR("failed to init phys object %d size: %zu\n",
id, obj->base.size);
- return (ret);
+ return ret;
}
}
@@ -4178,15 +4242,14 @@ i915_gem_attach_phys_object(struct drm_device *dev,
page_count = obj->base.size / PAGE_SIZE;
VM_OBJECT_WLOCK(obj->base.vm_obj);
- ret = 0;
for (i = 0; i < page_count; i++) {
- m = i915_gem_wire_page(obj->base.vm_obj, i, NULL);
- if (m == NULL) {
+ page = i915_gem_wire_page(obj->base.vm_obj, i, NULL);
+ if (page == NULL) {
ret = -EIO;
break;
}
VM_OBJECT_WUNLOCK(obj->base.vm_obj);
- sf = sf_buf_alloc(m, 0);
+ sf = sf_buf_alloc(page, 0);
src = (char *)sf_buf_kva(sf);
dst = (char *)obj->phys_obj->handle->vaddr + IDX_TO_OFF(i);
memcpy(dst, src, PAGE_SIZE);
@@ -4194,85 +4257,106 @@ i915_gem_attach_phys_object(struct drm_device *dev,
VM_OBJECT_WLOCK(obj->base.vm_obj);
- vm_page_reference(m);
- vm_page_lock(m);
- vm_page_unwire(m, PQ_INACTIVE);
- vm_page_unlock(m);
+ vm_page_reference(page);
+ vm_page_lock(page);
+ vm_page_unwire(page, PQ_INACTIVE);
+ vm_page_unlock(page);
atomic_add_long(&i915_gem_wired_pages_cnt, -1);
}
VM_OBJECT_WUNLOCK(obj->base.vm_obj);
- return (ret);
+ return ret;
}
static int
-i915_gpu_is_active(struct drm_device *dev)
-{
- drm_i915_private_t *dev_priv;
-
- dev_priv = dev->dev_private;
- return (!list_empty(&dev_priv->mm.flushing_list) ||
- !list_empty(&dev_priv->mm.active_list));
-}
-
-static void
-i915_gem_lowmem(void *arg)
+i915_gem_phys_pwrite(struct drm_device *dev,
+ struct drm_i915_gem_object *obj,
+ struct drm_i915_gem_pwrite *args,
+ struct drm_file *file_priv)
{
- struct drm_device *dev;
- struct drm_i915_private *dev_priv;
- struct drm_i915_gem_object *obj, *next;
- int cnt, cnt_fail, cnt_total;
-
- dev = arg;
- dev_priv = dev->dev_private;
-
- if (!sx_try_xlock(&dev->dev_struct_lock))
- return;
+ void *vaddr = (char *)obj->phys_obj->handle->vaddr + args->offset;
+ char __user *user_data = to_user_ptr(args->data_ptr);
- CTR0(KTR_DRM, "gem_lowmem");
+ if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) {
+ unsigned long unwritten;
-rescan:
- /* first scan for clean buffers */
- i915_gem_retire_requests(dev);
+ /* The physical object once assigned is fixed for the lifetime
+ * of the obj, so we can safely drop the lock and continue
+ * to access vaddr.
+ */
+ DRM_UNLOCK(dev);
+ unwritten = copy_from_user(vaddr, user_data, args->size);
+ DRM_LOCK(dev);
+ if (unwritten)
+ return -EFAULT;
+ }
- cnt_total = cnt_fail = cnt = 0;
+ i915_gem_chipset_flush(dev);
+ return 0;
+}
- list_for_each_entry_safe(obj, next, &dev_priv->mm.inactive_list,
- mm_list) {
- if (i915_gem_object_is_purgeable(obj)) {
- if (i915_gem_object_unbind(obj) != 0)
- cnt_total++;
- } else
- cnt_total++;
- }
+void i915_gem_release(struct drm_device *dev, struct drm_file *file)
+{
+ struct drm_i915_file_private *file_priv = file->driver_priv;
- /* second pass, evict/count anything still on the inactive list */
- list_for_each_entry_safe(obj, next, &dev_priv->mm.inactive_list,
- mm_list) {
- if (i915_gem_object_unbind(obj) == 0)
- cnt++;
- else
- cnt_fail++;
- }
+ /* Clean up our request list when the client is going away, so that
+ * later retire_requests won't dereference our soon-to-be-gone
+ * file_priv.
+ */
+ mtx_lock(&file_priv->mm.lck);
+ while (!list_empty(&file_priv->mm.request_list)) {
+ struct drm_i915_gem_request *request;
- if (cnt_fail > cnt_total / 100 && i915_gpu_is_active(dev)) {
- /*
- * We are desperate for pages, so as a last resort, wait
- * for the GPU to finish and discard whatever we can.
- * This has a dramatic impact to reduce the number of
- * OOM-killer events whilst running the GPU aggressively.
- */
- if (i915_gpu_idle(dev) == 0)
- goto rescan;
+ request = list_first_entry(&file_priv->mm.request_list,
+ struct drm_i915_gem_request,
+ client_list);
+ list_del(&request->client_list);
+ request->file_priv = NULL;
}
- DRM_UNLOCK(dev);
+ mtx_unlock(&file_priv->mm.lck);
}
-void
-i915_gem_unload(struct drm_device *dev)
+static vm_page_t
+i915_gem_wire_page(vm_object_t object, vm_pindex_t pindex, bool *fresh)
{
- struct drm_i915_private *dev_priv;
+ vm_page_t page;
+ int rv;
- dev_priv = dev->dev_private;
- EVENTHANDLER_DEREGISTER(vm_lowmem, dev_priv->mm.i915_lowmem);
+ VM_OBJECT_ASSERT_WLOCKED(object);
+ page = vm_page_grab(object, pindex, VM_ALLOC_NORMAL);
+ if (page->valid != VM_PAGE_BITS_ALL) {
+ if (vm_pager_has_page(object, pindex, NULL, NULL)) {
+ rv = vm_pager_get_pages(object, &page, 1, 0);
+ if (rv != VM_PAGER_OK) {
+ vm_page_lock(page);
+ vm_page_free(page);
+ vm_page_unlock(page);
+ return (NULL);
+ }
+ if (fresh != NULL)
+ *fresh = true;
+ } else {
+ pmap_zero_page(page);
+ page->valid = VM_PAGE_BITS_ALL;
+ page->dirty = 0;
+ if (fresh != NULL)
+ *fresh = false;
+ }
+ } else if (fresh != NULL) {
+ *fresh = false;
+ }
+ vm_page_lock(page);
+ vm_page_wire(page);
+ vm_page_unlock(page);
+ vm_page_xunbusy(page);
+ atomic_add_long(&i915_gem_wired_pages_cnt, 1);
+ return (page);
}
+
+#undef __user
+#undef __force
+#undef __iomem
+#undef __must_check
+#undef to_user_ptr
+#undef offset_in_page
+#undef page_to_phys
diff --git a/sys/dev/drm2/i915/i915_gem_gtt.c b/sys/dev/drm2/i915/i915_gem_gtt.c
index 89c8060..117c07c 100644
--- a/sys/dev/drm2/i915/i915_gem_gtt.c
+++ b/sys/dev/drm2/i915/i915_gem_gtt.c
@@ -189,6 +189,61 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,
obj->base.size >> PAGE_SHIFT);
}
+void i915_gem_init_ppgtt(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv;
+ struct i915_hw_ppgtt *ppgtt;
+ uint32_t pd_offset, pd_entry;
+ vm_paddr_t pt_addr;
+ struct intel_ring_buffer *ring;
+ u_int first_pd_entry_in_global_pt, i;
+
+ dev_priv = dev->dev_private;
+ ppgtt = dev_priv->mm.aliasing_ppgtt;
+ if (ppgtt == NULL)
+ return;
+
+ first_pd_entry_in_global_pt = 512 * 1024 - I915_PPGTT_PD_ENTRIES;
+ for (i = 0; i < ppgtt->num_pd_entries; i++) {
+ pt_addr = VM_PAGE_TO_PHYS(ppgtt->pt_pages[i]);
+ pd_entry = GEN6_PDE_ADDR_ENCODE(pt_addr);
+ pd_entry |= GEN6_PDE_VALID;
+ intel_gtt_write(first_pd_entry_in_global_pt + i, pd_entry);
+ }
+ intel_gtt_read_pte(first_pd_entry_in_global_pt);
+
+ pd_offset = ppgtt->pd_offset;
+ pd_offset /= 64; /* in cachelines, */
+ pd_offset <<= 16;
+
+ if (INTEL_INFO(dev)->gen == 6) {
+ uint32_t ecochk, gab_ctl, ecobits;
+
+ ecobits = I915_READ(GAC_ECO_BITS);
+ I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B);
+
+ gab_ctl = I915_READ(GAB_CTL);
+ I915_WRITE(GAB_CTL, gab_ctl | GAB_CTL_CONT_AFTER_PAGEFAULT);
+
+ ecochk = I915_READ(GAM_ECOCHK);
+ I915_WRITE(GAM_ECOCHK, ecochk | ECOCHK_SNB_BIT |
+ ECOCHK_PPGTT_CACHE64B);
+ I915_WRITE(GFX_MODE, _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
+ } else if (INTEL_INFO(dev)->gen >= 7) {
+ I915_WRITE(GAM_ECOCHK, ECOCHK_PPGTT_CACHE64B);
+ /* GFX_MODE is per-ring on gen7+ */
+ }
+
+ for_each_ring(ring, dev_priv, i) {
+ if (INTEL_INFO(dev)->gen >= 7)
+ I915_WRITE(RING_MODE_GEN7(ring),
+ _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE));
+
+ I915_WRITE(RING_PP_DIR_DCLV(ring), PP_DIR_DCLV_2G);
+ I915_WRITE(RING_PP_DIR_BASE(ring), pd_offset);
+ }
+}
+
void
i915_gem_cleanup_aliasing_ppgtt(struct drm_device *dev)
{
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 528ad14..830325b 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -2029,9 +2029,6 @@ retry:
/* Try it again, but only once */
remap = 0;
goto retry;
- } else if (error == ENOMEM) {
- adapter->no_tx_dma_setup++;
- return (error);
} else if (error != 0) {
adapter->no_tx_dma_setup++;
m_freem(*m_headp);
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 384a46b..9eacc78 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -1908,9 +1908,6 @@ retry:
goto retry;
} else
return (error);
- case ENOMEM:
- txr->no_tx_dma_setup++;
- return (error);
default:
txr->no_tx_dma_setup++;
m_freem(*m_headp);
diff --git a/sys/dev/gpio/gpiobacklight.c b/sys/dev/gpio/gpiobacklight.c
new file mode 100644
index 0000000..3ff74f1
--- /dev/null
+++ b/sys/dev/gpio/gpiobacklight.c
@@ -0,0 +1,211 @@
+/*-
+ * Copyright (c) 2015 Oleksandr Tymoshenko <gonzo@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.
+ * 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 "opt_platform.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/sysctl.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+
+#include <dev/gpio/gpiobusvar.h>
+
+#include "gpiobus_if.h"
+
+/*
+ * Only one pin for led
+ */
+#define GPIOBL_PIN 0
+
+#define GPIOBL_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define GPIOBL_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define GPIOBL_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), \
+ "gpiobacklight", MTX_DEF)
+#define GPIOBL_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+
+struct gpiobacklight_softc
+{
+ device_t sc_dev;
+ device_t sc_busdev;
+ struct mtx sc_mtx;
+
+ struct sysctl_oid *sc_oid;
+ int sc_brightness;
+};
+
+static int gpiobacklight_sysctl(SYSCTL_HANDLER_ARGS);
+static void gpiobacklight_update_brightness(struct gpiobacklight_softc *);
+static int gpiobacklight_probe(device_t);
+static int gpiobacklight_attach(device_t);
+static int gpiobacklight_detach(device_t);
+
+static void
+gpiobacklight_update_brightness(struct gpiobacklight_softc *sc)
+{
+ int error;
+
+ GPIOBL_LOCK(sc);
+ error = GPIOBUS_ACQUIRE_BUS(sc->sc_busdev, sc->sc_dev,
+ GPIOBUS_DONTWAIT);
+ if (error != 0) {
+ GPIOBL_UNLOCK(sc);
+ return;
+ }
+ error = GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev,
+ GPIOBL_PIN, GPIO_PIN_OUTPUT);
+ if (error == 0)
+ GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev, GPIOBL_PIN,
+ sc->sc_brightness ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
+ GPIOBUS_RELEASE_BUS(sc->sc_busdev, sc->sc_dev);
+ GPIOBL_UNLOCK(sc);
+}
+
+static int
+gpiobacklight_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct gpiobacklight_softc *sc;
+ int error;
+ int brightness;
+
+ sc = (struct gpiobacklight_softc*)arg1;
+ brightness = sc->sc_brightness;
+ error = sysctl_handle_int(oidp, &brightness, 0, req);
+
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ if (brightness <= 0)
+ sc->sc_brightness = 0;
+ else
+ sc->sc_brightness = 1;
+
+ gpiobacklight_update_brightness(sc);
+
+ return (error);
+}
+
+static void
+gpiobacklight_identify(driver_t *driver, device_t bus)
+{
+ phandle_t node, root;
+
+ root = OF_finddevice("/");
+ if (root == 0)
+ return;
+ for (node = OF_child(root); node != 0; node = OF_peer(node)) {
+ if (!fdt_is_compatible_strict(node, "gpio-backlight"))
+ continue;
+ ofw_gpiobus_add_fdt_child(bus, driver->name, node);
+ }
+}
+
+static int
+gpiobacklight_probe(device_t dev)
+{
+
+ if (!ofw_bus_is_compatible(dev, "gpio-backlight"))
+ return (ENXIO);
+
+ device_set_desc(dev, "GPIO backlight");
+
+ return (0);
+}
+
+static int
+gpiobacklight_attach(device_t dev)
+{
+ struct gpiobacklight_softc *sc;
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *tree;
+ phandle_t node;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ sc->sc_busdev = device_get_parent(dev);
+
+ if ((node = ofw_bus_get_node(dev)) == -1)
+ return (ENXIO);
+
+ GPIOBL_LOCK_INIT(sc);
+ if (OF_hasprop(node, "default-on"))
+ sc->sc_brightness = 1;
+ else
+ sc->sc_brightness = 0;
+
+ /* Init backlight interface */
+ ctx = device_get_sysctl_ctx(sc->sc_dev);
+ tree = device_get_sysctl_tree(sc->sc_dev);
+ sc->sc_oid = SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+ "brightness", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
+ gpiobacklight_sysctl, "I", "backlight brightness");
+
+ gpiobacklight_update_brightness(sc);
+
+ return (0);
+}
+
+static int
+gpiobacklight_detach(device_t dev)
+{
+ struct gpiobacklight_softc *sc;
+
+ sc = device_get_softc(dev);
+ GPIOBL_LOCK_DESTROY(sc);
+ return (0);
+}
+
+static devclass_t gpiobacklight_devclass;
+
+static device_method_t gpiobacklight_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, gpiobacklight_identify),
+ DEVMETHOD(device_probe, gpiobacklight_probe),
+ DEVMETHOD(device_attach, gpiobacklight_attach),
+ DEVMETHOD(device_detach, gpiobacklight_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t gpiobacklight_driver = {
+ "gpiobacklight",
+ gpiobacklight_methods,
+ sizeof(struct gpiobacklight_softc),
+};
+
+DRIVER_MODULE(gpiobacklight, gpiobus, gpiobacklight_driver, gpiobacklight_devclass, 0, 0);
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c
index 9c57aed..c30f31c 100644
--- a/sys/dev/if_ndis/if_ndis.c
+++ b/sys/dev/if_ndis/if_ndis.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/kthread.h>
+#include <sys/limits.h>
#include <net/if.h>
#include <net/if_var.h>
@@ -166,7 +167,6 @@ static void ndis_starttask (device_object *, void *);
static void ndis_resettask (device_object *, void *);
static void ndis_inputtask (device_object *, void *);
static int ndis_ioctl (struct ifnet *, u_long, caddr_t);
-static int ndis_ioctl_80211 (struct ifnet *, u_long, caddr_t);
static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state,
int);
static int ndis_nettype_chan (uint32_t);
@@ -197,10 +197,15 @@ static int ndis_add_key (struct ieee80211vap *,
const struct ieee80211_key *, const u_int8_t []);
static int ndis_del_key (struct ieee80211vap *,
const struct ieee80211_key *);
-
static void ndis_setmulti (struct ndis_softc *);
static void ndis_map_sclist (void *, bus_dma_segment_t *,
int, bus_size_t, int);
+static int ndis_ifattach(struct ndis_softc *);
+
+static int ndis_80211attach(struct ndis_softc *);
+static int ndis_80211ioctl(struct ieee80211com *, u_long , void *);
+static int ndis_80211transmit(struct ieee80211com *, struct mbuf *);
+static void ndis_80211parent(struct ieee80211com *);
static int ndisdrv_loaded = 0;
@@ -536,16 +541,12 @@ ndis_nettype_mode(uint32_t type)
* setup and ethernet/BPF attach.
*/
int
-ndis_attach(dev)
- device_t dev;
+ndis_attach(device_t dev)
{
- u_char eaddr[ETHER_ADDR_LEN];
struct ndis_softc *sc;
driver_object *pdrv;
device_object *pdo;
- struct ifnet *ifp = NULL;
- int error = 0, len, mode;
- uint8_t bands = 0;
+ int error = 0, len;
int i;
sc = device_get_softc(dev);
@@ -559,6 +560,7 @@ ndis_attach(dev)
InitializeListHead(&sc->ndisusb_tasklist);
InitializeListHead(&sc->ndisusb_xferdonelist);
callout_init(&sc->ndis_stat_callout, 1);
+ mbufq_init(&sc->ndis_rxqueue, INT_MAX); /* XXXGL: sane maximum */
if (sc->ndis_iftype == PCMCIABus) {
error = ndis_alloc_amem(sc);
@@ -635,15 +637,8 @@ ndis_attach(dev)
}
/*
- * Get station address from the driver.
- */
- len = sizeof(eaddr);
- ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len);
-
- /*
* Figure out how big to make the TX buffer pool.
*/
-
len = sizeof(sc->ndis_maxpkts);
if (ndis_get_info(sc, OID_GEN_MAXIMUM_SEND_PACKETS,
&sc->ndis_maxpkts, &len)) {
@@ -696,95 +691,89 @@ ndis_attach(dev)
*/
for (i = 0; i < sc->ndis_oidcnt; i++)
if (sc->ndis_oids[i] == OID_802_11_CONFIGURATION) {
- sc->ndis_80211++;
+ sc->ndis_80211 = 1;
break;
}
if (sc->ndis_80211)
- ifp = if_alloc(IFT_IEEE80211);
+ error = ndis_80211attach(sc);
else
- ifp = if_alloc(IFT_ETHER);
- if (ifp == NULL) {
- error = ENOSPC;
- goto fail;
+ error = ndis_ifattach(sc);
+
+fail:
+ if (error) {
+ ndis_detach(dev);
+ return (error);
}
- sc->ifp = ifp;
- ifp->if_softc = sc;
- /* Check for task offload support. */
- ndis_probe_offload(sc);
+ if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
+ return (error);
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = ndis_ioctl;
- ifp->if_start = ndis_start;
- ifp->if_init = ndis_init;
- ifp->if_baudrate = 10000000;
- IFQ_SET_MAXLEN(&ifp->if_snd, 50);
- ifp->if_snd.ifq_drv_maxlen = 25;
- IFQ_SET_READY(&ifp->if_snd);
- ifp->if_capenable = ifp->if_capabilities;
- ifp->if_hwassist = sc->ndis_hwassist;
+ DPRINTF(("attach done.\n"));
+ /* We're done talking to the NIC for now; halt it. */
+ ndis_halt_nic(sc);
+ DPRINTF(("halting done.\n"));
- /* Do media setup */
- if (sc->ndis_80211) {
- struct ieee80211com *ic = ifp->if_l2com;
- ndis_80211_rates_ex rates;
- struct ndis_80211_nettype_list *ntl;
- uint32_t arg;
- int r;
-
- callout_init(&sc->ndis_scan_callout, 1);
-
- ifp->if_ioctl = ndis_ioctl_80211;
- ic->ic_ifp = ifp;
- ic->ic_softc = sc;
- ic->ic_name = device_get_nameunit(dev);
- ic->ic_opmode = IEEE80211_M_STA;
- ic->ic_phytype = IEEE80211_T_DS;
- ic->ic_caps = IEEE80211_C_8023ENCAP |
- IEEE80211_C_STA | IEEE80211_C_IBSS;
- setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
- len = 0;
- r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
- NULL, &len);
- if (r != ENOSPC)
- goto nonettypes;
- ntl = malloc(len, M_DEVBUF, M_NOWAIT|M_ZERO);
- r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
- ntl, &len);
- if (r != 0) {
- free(ntl, M_DEVBUF);
- goto nonettypes;
- }
+ return (error);
+}
- for (i = 0; i < ntl->ntl_items; i++) {
- mode = ndis_nettype_mode(ntl->ntl_type[i]);
- if (mode) {
- setbit(ic->ic_modecaps, mode);
- setbit(&bands, mode);
- } else
- device_printf(dev, "Unknown nettype %d\n",
- ntl->ntl_type[i]);
- }
+static int
+ndis_80211attach(struct ndis_softc *sc)
+{
+ struct ieee80211com *ic = &sc->ndis_ic;
+ ndis_80211_rates_ex rates;
+ struct ndis_80211_nettype_list *ntl;
+ uint32_t arg;
+ int mode, i, r, len;
+ uint8_t bands = 0;
+
+ callout_init(&sc->ndis_scan_callout, 1);
+
+ ic->ic_softc = sc;
+ ic->ic_ioctl = ndis_80211ioctl;
+ ic->ic_name = device_get_nameunit(sc->ndis_dev);
+ ic->ic_opmode = IEEE80211_M_STA;
+ ic->ic_phytype = IEEE80211_T_DS;
+ ic->ic_caps = IEEE80211_C_8023ENCAP |
+ IEEE80211_C_STA | IEEE80211_C_IBSS;
+ setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
+ len = 0;
+ r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, NULL, &len);
+ if (r != ENOSPC)
+ goto nonettypes;
+ ntl = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO);
+ r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED, ntl, &len);
+ if (r != 0) {
free(ntl, M_DEVBUF);
+ goto nonettypes;
+ }
+
+ for (i = 0; i < ntl->ntl_items; i++) {
+ mode = ndis_nettype_mode(ntl->ntl_type[i]);
+ if (mode) {
+ setbit(ic->ic_modecaps, mode);
+ setbit(&bands, mode);
+ } else
+ device_printf(sc->ndis_dev, "Unknown nettype %d\n",
+ ntl->ntl_type[i]);
+ }
+ free(ntl, M_DEVBUF);
nonettypes:
- /* Default to 11b channels if the card did not supply any */
- if (bands == 0) {
- setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
- setbit(&bands, IEEE80211_MODE_11B);
- }
- len = sizeof(rates);
- bzero((char *)&rates, len);
- r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES,
- (void *)rates, &len);
- if (r)
- device_printf(dev, "get rates failed: 0x%x\n", r);
- /*
- * Since the supported rates only up to 8 can be supported,
- * if this is not 802.11b we're just going to be faking it
- * all up to heck.
- */
+ /* Default to 11b channels if the card did not supply any */
+ if (bands == 0) {
+ setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
+ setbit(&bands, IEEE80211_MODE_11B);
+ }
+ len = sizeof(rates);
+ bzero((char *)&rates, len);
+ r = ndis_get_info(sc, OID_802_11_SUPPORTED_RATES, (void *)rates, &len);
+ if (r != 0)
+ device_printf(sc->ndis_dev, "get rates failed: 0x%x\n", r);
+ /*
+ * Since the supported rates only up to 8 can be supported,
+ * if this is not 802.11b we're just going to be faking it
+ * all up to heck.
+ */
#define TESTSETRATE(x, y) \
do { \
@@ -804,174 +793,198 @@ nonettypes:
#define INCRATE(x) \
ic->ic_sup_rates[x].rs_nrates++
- ic->ic_curmode = IEEE80211_MODE_AUTO;
- if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
- ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
- if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
- ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
- if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
- ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
- for (i = 0; i < len; i++) {
- switch (rates[i] & IEEE80211_RATE_VAL) {
- case 2:
- case 4:
- case 11:
- case 10:
- case 22:
- if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
- /* Lazy-init 802.11b. */
- setbit(ic->ic_modecaps,
- IEEE80211_MODE_11B);
- ic->ic_sup_rates[IEEE80211_MODE_11B].
- rs_nrates = 0;
- }
- SETRATE(IEEE80211_MODE_11B, rates[i]);
- INCRATE(IEEE80211_MODE_11B);
- break;
- default:
- if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
- SETRATE(IEEE80211_MODE_11A, rates[i]);
- INCRATE(IEEE80211_MODE_11A);
- }
- if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
- SETRATE(IEEE80211_MODE_11G, rates[i]);
- INCRATE(IEEE80211_MODE_11G);
- }
- break;
+ ic->ic_curmode = IEEE80211_MODE_AUTO;
+ if (isset(ic->ic_modecaps, IEEE80211_MODE_11A))
+ ic->ic_sup_rates[IEEE80211_MODE_11A].rs_nrates = 0;
+ if (isset(ic->ic_modecaps, IEEE80211_MODE_11B))
+ ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = 0;
+ if (isset(ic->ic_modecaps, IEEE80211_MODE_11G))
+ ic->ic_sup_rates[IEEE80211_MODE_11G].rs_nrates = 0;
+ for (i = 0; i < len; i++) {
+ switch (rates[i] & IEEE80211_RATE_VAL) {
+ case 2:
+ case 4:
+ case 11:
+ case 10:
+ case 22:
+ if (isclr(ic->ic_modecaps, IEEE80211_MODE_11B)) {
+ /* Lazy-init 802.11b. */
+ setbit(ic->ic_modecaps, IEEE80211_MODE_11B);
+ ic->ic_sup_rates[IEEE80211_MODE_11B].
+ rs_nrates = 0;
}
+ SETRATE(IEEE80211_MODE_11B, rates[i]);
+ INCRATE(IEEE80211_MODE_11B);
+ break;
+ default:
+ if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
+ SETRATE(IEEE80211_MODE_11A, rates[i]);
+ INCRATE(IEEE80211_MODE_11A);
+ }
+ if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
+ SETRATE(IEEE80211_MODE_11G, rates[i]);
+ INCRATE(IEEE80211_MODE_11G);
+ }
+ break;
}
+ }
+
+ /*
+ * If the hardware supports 802.11g, it most
+ * likely supports 802.11b and all of the
+ * 802.11b and 802.11g speeds, so maybe we can
+ * just cheat here. Just how in the heck do
+ * we detect turbo modes, though?
+ */
+ if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
+ TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|2);
+ TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|4);
+ TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|11);
+ TESTSETRATE(IEEE80211_MODE_11B, IEEE80211_RATE_BASIC|22);
+ }
+ if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
+ TESTSETRATE(IEEE80211_MODE_11G, 48);
+ TESTSETRATE(IEEE80211_MODE_11G, 72);
+ TESTSETRATE(IEEE80211_MODE_11G, 96);
+ TESTSETRATE(IEEE80211_MODE_11G, 108);
+ }
+ if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
+ TESTSETRATE(IEEE80211_MODE_11A, 48);
+ TESTSETRATE(IEEE80211_MODE_11A, 72);
+ TESTSETRATE(IEEE80211_MODE_11A, 96);
+ TESTSETRATE(IEEE80211_MODE_11A, 108);
+ }
- /*
- * If the hardware supports 802.11g, it most
- * likely supports 802.11b and all of the
- * 802.11b and 802.11g speeds, so maybe we can
- * just cheat here. Just how in the heck do
- * we detect turbo modes, though?
- */
- if (isset(ic->ic_modecaps, IEEE80211_MODE_11B)) {
- TESTSETRATE(IEEE80211_MODE_11B,
- IEEE80211_RATE_BASIC|2);
- TESTSETRATE(IEEE80211_MODE_11B,
- IEEE80211_RATE_BASIC|4);
- TESTSETRATE(IEEE80211_MODE_11B,
- IEEE80211_RATE_BASIC|11);
- TESTSETRATE(IEEE80211_MODE_11B,
- IEEE80211_RATE_BASIC|22);
- }
- if (isset(ic->ic_modecaps, IEEE80211_MODE_11G)) {
- TESTSETRATE(IEEE80211_MODE_11G, 48);
- TESTSETRATE(IEEE80211_MODE_11G, 72);
- TESTSETRATE(IEEE80211_MODE_11G, 96);
- TESTSETRATE(IEEE80211_MODE_11G, 108);
- }
- if (isset(ic->ic_modecaps, IEEE80211_MODE_11A)) {
- TESTSETRATE(IEEE80211_MODE_11A, 48);
- TESTSETRATE(IEEE80211_MODE_11A, 72);
- TESTSETRATE(IEEE80211_MODE_11A, 96);
- TESTSETRATE(IEEE80211_MODE_11A, 108);
- }
#undef SETRATE
#undef INCRATE
- ieee80211_init_channels(ic, NULL, &bands);
+#undef TESTSETRATE
- /*
- * To test for WPA support, we need to see if we can
- * set AUTHENTICATION_MODE to WPA and read it back
- * successfully.
- */
- i = sizeof(arg);
- arg = NDIS_80211_AUTHMODE_WPA;
- r = ndis_set_info(sc,
- OID_802_11_AUTHENTICATION_MODE, &arg, &i);
- if (r == 0) {
- r = ndis_get_info(sc,
- OID_802_11_AUTHENTICATION_MODE, &arg, &i);
- if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
- ic->ic_caps |= IEEE80211_C_WPA;
- }
+ ieee80211_init_channels(ic, NULL, &bands);
- /*
- * To test for supported ciphers, we set each
- * available encryption type in descending order.
- * If ENC3 works, then we have WEP, TKIP and AES.
- * If only ENC2 works, then we have WEP and TKIP.
- * If only ENC1 works, then we have just WEP.
- */
- i = sizeof(arg);
- arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
- r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
- if (r == 0) {
- ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
- | IEEE80211_CRYPTO_TKIP
- | IEEE80211_CRYPTO_AES_CCM;
- goto got_crypto;
- }
- arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
- r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
- if (r == 0) {
- ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
- | IEEE80211_CRYPTO_TKIP;
- goto got_crypto;
- }
- arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
- r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
- if (r == 0)
- ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
+ /*
+ * To test for WPA support, we need to see if we can
+ * set AUTHENTICATION_MODE to WPA and read it back
+ * successfully.
+ */
+ i = sizeof(arg);
+ arg = NDIS_80211_AUTHMODE_WPA;
+ r = ndis_set_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
+ if (r == 0) {
+ r = ndis_get_info(sc, OID_802_11_AUTHENTICATION_MODE, &arg, &i);
+ if (r == 0 && arg == NDIS_80211_AUTHMODE_WPA)
+ ic->ic_caps |= IEEE80211_C_WPA;
+ }
+
+ /*
+ * To test for supported ciphers, we set each
+ * available encryption type in descending order.
+ * If ENC3 works, then we have WEP, TKIP and AES.
+ * If only ENC2 works, then we have WEP and TKIP.
+ * If only ENC1 works, then we have just WEP.
+ */
+ i = sizeof(arg);
+ arg = NDIS_80211_WEPSTAT_ENC3ENABLED;
+ r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
+ if (r == 0) {
+ ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
+ | IEEE80211_CRYPTO_TKIP
+ | IEEE80211_CRYPTO_AES_CCM;
+ goto got_crypto;
+ }
+ arg = NDIS_80211_WEPSTAT_ENC2ENABLED;
+ r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
+ if (r == 0) {
+ ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP
+ | IEEE80211_CRYPTO_TKIP;
+ goto got_crypto;
+ }
+ arg = NDIS_80211_WEPSTAT_ENC1ENABLED;
+ r = ndis_set_info(sc, OID_802_11_ENCRYPTION_STATUS, &arg, &i);
+ if (r == 0)
+ ic->ic_cryptocaps |= IEEE80211_CRYPTO_WEP;
got_crypto:
- i = sizeof(arg);
- r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
- if (r == 0)
- ic->ic_caps |= IEEE80211_C_PMGT;
-
- r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
- if (r == 0)
- ic->ic_caps |= IEEE80211_C_TXPMGT;
-
- ieee80211_ifattach(ic, eaddr);
- ic->ic_raw_xmit = ndis_raw_xmit;
- ic->ic_scan_start = ndis_scan_start;
- ic->ic_scan_end = ndis_scan_end;
- ic->ic_set_channel = ndis_set_channel;
- ic->ic_scan_curchan = ndis_scan_curchan;
- ic->ic_scan_mindwell = ndis_scan_mindwell;
- ic->ic_bsschan = IEEE80211_CHAN_ANYC;
- //ic->ic_bss->ni_chan = ic->ic_bsschan;
- ic->ic_vap_create = ndis_vap_create;
- ic->ic_vap_delete = ndis_vap_delete;
- ic->ic_update_mcast = ndis_update_mcast;
- ic->ic_update_promisc = ndis_update_promisc;
-
- if (bootverbose)
- ieee80211_announce(ic);
+ i = sizeof(arg);
+ r = ndis_get_info(sc, OID_802_11_POWER_MODE, &arg, &i);
+ if (r == 0)
+ ic->ic_caps |= IEEE80211_C_PMGT;
- } else {
- ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
- ndis_ifmedia_sts);
- ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
- ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
- ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
- ifmedia_add(&sc->ifmedia,
- IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
- ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
- ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
- ether_ifattach(ifp, eaddr);
- }
+ r = ndis_get_info(sc, OID_802_11_TX_POWER_LEVEL, &arg, &i);
+ if (r == 0)
+ ic->ic_caps |= IEEE80211_C_TXPMGT;
-fail:
- if (error) {
- ndis_detach(dev);
- return (error);
- }
+ /*
+ * Get station address from the driver.
+ */
+ len = sizeof(ic->ic_macaddr);
+ ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len);
+
+ ieee80211_ifattach(ic);
+ ic->ic_raw_xmit = ndis_raw_xmit;
+ ic->ic_scan_start = ndis_scan_start;
+ ic->ic_scan_end = ndis_scan_end;
+ ic->ic_set_channel = ndis_set_channel;
+ ic->ic_scan_curchan = ndis_scan_curchan;
+ ic->ic_scan_mindwell = ndis_scan_mindwell;
+ ic->ic_bsschan = IEEE80211_CHAN_ANYC;
+ ic->ic_vap_create = ndis_vap_create;
+ ic->ic_vap_delete = ndis_vap_delete;
+ ic->ic_update_mcast = ndis_update_mcast;
+ ic->ic_update_promisc = ndis_update_promisc;
+ ic->ic_transmit = ndis_80211transmit;
+ ic->ic_parent = ndis_80211parent;
+
+ if (bootverbose)
+ ieee80211_announce(ic);
- if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0)
- return (error);
+ return (0);
+}
- DPRINTF(("attach done.\n"));
- /* We're done talking to the NIC for now; halt it. */
- ndis_halt_nic(sc);
- DPRINTF(("halting done.\n"));
+static int
+ndis_ifattach(struct ndis_softc *sc)
+{
+ struct ifnet *ifp;
+ u_char eaddr[ETHER_ADDR_LEN];
+ int len;
- return (error);
+ ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL)
+ return (ENOSPC);
+ sc->ifp = ifp;
+ ifp->if_softc = sc;
+
+ /* Check for task offload support. */
+ ndis_probe_offload(sc);
+
+ /*
+ * Get station address from the driver.
+ */
+ len = sizeof(eaddr);
+ ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, eaddr, &len);
+
+ if_initname(ifp, device_get_name(sc->ndis_dev),
+ device_get_unit(sc->ndis_dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_ioctl = ndis_ioctl;
+ ifp->if_start = ndis_start;
+ ifp->if_init = ndis_init;
+ ifp->if_baudrate = 10000000;
+ IFQ_SET_MAXLEN(&ifp->if_snd, 50);
+ ifp->if_snd.ifq_drv_maxlen = 25;
+ IFQ_SET_READY(&ifp->if_snd);
+ ifp->if_capenable = ifp->if_capabilities;
+ ifp->if_hwassist = sc->ndis_hwassist;
+
+ ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
+ ndis_ifmedia_sts);
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
+ ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
+ ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
+ ether_ifattach(ifp, eaddr);
+
+ return (0);
}
static struct ieee80211vap *
@@ -985,18 +998,16 @@ ndis_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
- nvp = (struct ndis_vap *) malloc(sizeof(struct ndis_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (nvp == NULL)
- return NULL;
+ nvp = malloc(sizeof(struct ndis_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &nvp->vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override with driver methods */
nvp->newstate = vap->iv_newstate;
vap->iv_newstate = ndis_newstate;
/* complete setup */
- ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status);
+ ieee80211_vap_attach(vap, ieee80211_media_change, ndis_media_status,
+ mac);
ic->ic_opmode = opmode;
/* install key handing routines */
vap->iv_key_set = ndis_add_key;
@@ -1009,8 +1020,7 @@ ndis_vap_delete(struct ieee80211vap *vap)
{
struct ndis_vap *nvp = NDIS_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct ndis_softc *sc = ifp->if_softc;
+ struct ndis_softc *sc = ic->ic_softc;
ndis_stop(sc);
callout_drain(&sc->ndis_scan_callout);
@@ -1026,28 +1036,27 @@ ndis_vap_delete(struct ieee80211vap *vap)
* allocated.
*/
int
-ndis_detach(dev)
- device_t dev;
+ndis_detach(device_t dev)
{
- struct ndis_softc *sc;
struct ifnet *ifp;
+ struct ndis_softc *sc;
driver_object *drv;
sc = device_get_softc(dev);
NDIS_LOCK(sc);
- ifp = sc->ifp;
+ if (!sc->ndis_80211)
+ ifp = sc->ifp;
+ else
+ ifp = NULL;
if (ifp != NULL)
ifp->if_flags &= ~IFF_UP;
-
if (device_is_attached(dev)) {
NDIS_UNLOCK(sc);
ndis_stop(sc);
- if (ifp != NULL) {
- if (sc->ndis_80211)
- ieee80211_ifdetach(ifp->if_l2com);
- else
- ether_ifdetach(ifp);
- }
+ if (sc->ndis_80211)
+ ieee80211_ifdetach(&sc->ndis_ic);
+ else if (ifp != NULL)
+ ether_ifdetach(ifp);
} else
NDIS_UNLOCK(sc);
@@ -1302,11 +1311,11 @@ ndis_rxeof_xfr(dpc, adapter, sysarg1, sysarg2)
IoFreeMdl(p->np_private.npp_head);
NdisFreePacket(p);
KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
- _IF_ENQUEUE(&sc->ndis_rxqueue, m);
+ mbufq_enqueue(&sc->ndis_rxqueue, m);
KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
IoQueueWorkItem(sc->ndis_inputitem,
(io_workitem_func)ndis_inputtask_wrap,
- WORKQUEUE_CRITICAL, ifp);
+ WORKQUEUE_CRITICAL, sc);
}
if (status == NDIS_STATUS_FAILURE)
@@ -1350,11 +1359,11 @@ ndis_rxeof_xfr_done(adapter, packet, status, len)
m->m_len = m->m_pkthdr.len;
m->m_pkthdr.rcvif = ifp;
KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
- _IF_ENQUEUE(&sc->ndis_rxqueue, m);
+ mbufq_enqueue(&sc->ndis_rxqueue, m);
KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
IoQueueWorkItem(sc->ndis_inputitem,
(io_workitem_func)ndis_inputtask_wrap,
- WORKQUEUE_CRITICAL, ifp);
+ WORKQUEUE_CRITICAL, sc);
}
/*
* A frame has been uploaded: pass the resulting mbuf chain up to
@@ -1399,7 +1408,7 @@ ndis_rxeof(adapter, packets, pktcnt)
* before we're completely ready to handle them. If we detect this,
* we need to return them to the miniport and ignore them.
*/
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!sc->ndis_running) {
for (i = 0; i < pktcnt; i++) {
p = packets[i];
if (p->np_oob.npo_status == NDIS_STATUS_SUCCESS) {
@@ -1473,11 +1482,11 @@ ndis_rxeof(adapter, packets, pktcnt)
}
KeAcquireSpinLockAtDpcLevel(&sc->ndis_rxlock);
- _IF_ENQUEUE(&sc->ndis_rxqueue, m0);
+ mbufq_enqueue(&sc->ndis_rxqueue, m0);
KeReleaseSpinLockFromDpcLevel(&sc->ndis_rxlock);
IoQueueWorkItem(sc->ndis_inputitem,
(io_workitem_func)ndis_inputtask_wrap,
- WORKQUEUE_CRITICAL, ifp);
+ WORKQUEUE_CRITICAL, sc);
}
}
}
@@ -1489,34 +1498,29 @@ ndis_rxeof(adapter, packets, pktcnt)
* 'dispatch level' per-cpu sleep lock).
*/
static void
-ndis_inputtask(dobj, arg)
- device_object *dobj;
- void *arg;
+ndis_inputtask(device_object *dobj, void *arg)
{
ndis_miniport_block *block;
- struct ifnet *ifp;
- struct ndis_softc *sc;
+ struct ndis_softc *sc = arg;
struct mbuf *m;
- struct ieee80211com *ic;
- struct ieee80211vap *vap;
uint8_t irql;
- ifp = arg;
- sc = ifp->if_softc;
- ic = ifp->if_l2com;
- vap = TAILQ_FIRST(&ic->ic_vaps);
block = dobj->do_devext;
KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
- while(1) {
- _IF_DEQUEUE(&sc->ndis_rxqueue, m);
- if (m == NULL)
- break;
+ while ((m = mbufq_dequeue(&sc->ndis_rxqueue)) != NULL) {
KeReleaseSpinLock(&sc->ndis_rxlock, irql);
- if ((sc->ndis_80211 != 0) && (vap != NULL))
- vap->iv_deliver_data(vap, vap->iv_bss, m);
- else
+ if ((sc->ndis_80211 != 0)) {
+ struct ieee80211com *ic = &sc->ndis_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+
+ if (vap != NULL)
+ vap->iv_deliver_data(vap, vap->iv_bss, m);
+ } else {
+ struct ifnet *ifp = sc->ifp;
+
(*ifp->if_input)(ifp, m);
+ }
KeAcquireSpinLock(&sc->ndis_rxlock, &irql);
}
KeReleaseSpinLock(&sc->ndis_rxlock, irql);
@@ -1676,20 +1680,12 @@ ndis_tick(xsc)
}
static void
-ndis_ticktask(d, xsc)
- device_object *d;
- void *xsc;
+ndis_ticktask(device_object *d, void *xsc)
{
- struct ndis_softc *sc;
- struct ieee80211com *ic;
- struct ieee80211vap *vap;
+ struct ndis_softc *sc = xsc;
ndis_checkforhang_handler hangfunc;
uint8_t rval;
- sc = xsc;
- ic = sc->ifp->if_l2com;
- vap = TAILQ_FIRST(&ic->ic_vaps);
-
NDIS_LOCK(sc);
if (!NDIS_INITIALIZED(sc)) {
NDIS_UNLOCK(sc);
@@ -1712,12 +1708,18 @@ ndis_ticktask(d, xsc)
if (sc->ndis_link == 0 &&
sc->ndis_sts == NDIS_STATUS_MEDIA_CONNECT) {
sc->ndis_link = 1;
- if ((sc->ndis_80211 != 0) && (vap != NULL)) {
- NDIS_UNLOCK(sc);
- ndis_getstate_80211(sc);
- ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
- NDIS_LOCK(sc);
- if_link_state_change(vap->iv_ifp, LINK_STATE_UP);
+ if (sc->ndis_80211 != 0) {
+ struct ieee80211com *ic = &sc->ndis_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+
+ if (vap != NULL) {
+ NDIS_UNLOCK(sc);
+ ndis_getstate_80211(sc);
+ ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
+ NDIS_LOCK(sc);
+ if_link_state_change(vap->iv_ifp,
+ LINK_STATE_UP);
+ }
} else
if_link_state_change(sc->ifp, LINK_STATE_UP);
}
@@ -1725,11 +1727,17 @@ ndis_ticktask(d, xsc)
if (sc->ndis_link == 1 &&
sc->ndis_sts == NDIS_STATUS_MEDIA_DISCONNECT) {
sc->ndis_link = 0;
- if ((sc->ndis_80211 != 0) && (vap != NULL)) {
- NDIS_UNLOCK(sc);
- ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
- NDIS_LOCK(sc);
- if_link_state_change(vap->iv_ifp, LINK_STATE_DOWN);
+ if (sc->ndis_80211 != 0) {
+ struct ieee80211com *ic = &sc->ndis_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+
+ if (vap != NULL) {
+ NDIS_UNLOCK(sc);
+ ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
+ NDIS_LOCK(sc);
+ if_link_state_change(vap->iv_ifp,
+ LINK_STATE_DOWN);
+ }
} else
if_link_state_change(sc->ifp, LINK_STATE_DOWN);
}
@@ -1939,13 +1947,103 @@ ndis_start(ifp)
return;
}
+static int
+ndis_80211transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct ndis_softc *sc = ic->ic_softc;
+ ndis_packet **p0 = NULL, *p = NULL;
+ int status;
+
+ NDIS_LOCK(sc);
+ if (!sc->ndis_link || !sc->ndis_running) {
+ NDIS_UNLOCK(sc);
+ return (ENXIO);
+ }
+
+ if (sc->ndis_txpending == 0) {
+ NDIS_UNLOCK(sc);
+ return (ENOBUFS);
+ }
+
+ p0 = &sc->ndis_txarray[sc->ndis_txidx];
+
+ NdisAllocatePacket(&status,
+ &sc->ndis_txarray[sc->ndis_txidx], sc->ndis_txpool);
+
+ if (status != NDIS_STATUS_SUCCESS) {
+ NDIS_UNLOCK(sc);
+ return (ENOBUFS);
+ }
+
+ if (ndis_mtop(m, &sc->ndis_txarray[sc->ndis_txidx])) {
+ NDIS_UNLOCK(sc);
+ return (ENOBUFS);
+ }
+
+ /*
+ * Save pointer to original mbuf
+ * so we can free it later.
+ */
+
+ p = sc->ndis_txarray[sc->ndis_txidx];
+ p->np_txidx = sc->ndis_txidx;
+ p->np_m0 = m;
+ p->np_oob.npo_status = NDIS_STATUS_PENDING;
+
+ /*
+ * Do scatter/gather processing, if driver requested it.
+ */
+ if (sc->ndis_sc) {
+ bus_dmamap_load_mbuf(sc->ndis_ttag,
+ sc->ndis_tmaps[sc->ndis_txidx], m,
+ ndis_map_sclist, &p->np_sclist, BUS_DMA_NOWAIT);
+ bus_dmamap_sync(sc->ndis_ttag,
+ sc->ndis_tmaps[sc->ndis_txidx],
+ BUS_DMASYNC_PREREAD);
+ p->np_ext.npe_info[ndis_sclist_info] = &p->np_sclist;
+ }
+
+ NDIS_INC(sc);
+ sc->ndis_txpending--;
+
+ /*
+ * Set a timeout in case the chip goes out to lunch.
+ */
+ sc->ndis_tx_timer = 5;
+ NDIS_UNLOCK(sc);
+
+ /*
+ * According to NDIS documentation, if a driver exports
+ * a MiniportSendPackets() routine, we prefer that over
+ * a MiniportSend() routine (which sends just a single
+ * packet).
+ */
+ if (sc->ndis_chars->nmc_sendmulti_func != NULL)
+ ndis_send_packets(sc, p0, 1);
+ else
+ ndis_send_packet(sc, p);
+
+ return (0);
+}
+
static void
-ndis_init(xsc)
- void *xsc;
+ndis_80211parent(struct ieee80211com *ic)
+{
+ struct ndis_softc *sc = ic->ic_softc;
+
+ /*NDIS_LOCK(sc);*/
+ if (ic->ic_nrunning > 0) {
+ if (!sc->ndis_running)
+ ndis_init(sc);
+ } else if (sc->ndis_running)
+ ndis_stop(sc);
+ /*NDIS_UNLOCK(sc);*/
+}
+
+static void
+ndis_init(void *xsc)
{
struct ndis_softc *sc = xsc;
- struct ifnet *ifp = sc->ifp;
- struct ieee80211com *ic = ifp->if_l2com;
int i, len, error;
/*
@@ -1971,17 +2069,21 @@ ndis_init(xsc)
}
}
- /* Init our MAC address */
-
/* Program the packet filter */
+ sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED |
+ NDIS_PACKET_TYPE_BROADCAST;
- sc->ndis_filter = NDIS_PACKET_TYPE_DIRECTED;
+ if (sc->ndis_80211) {
+ struct ieee80211com *ic = &sc->ndis_ic;
- if (ifp->if_flags & IFF_BROADCAST)
- sc->ndis_filter |= NDIS_PACKET_TYPE_BROADCAST;
+ if (ic->ic_promisc > 0)
+ sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
+ } else {
+ struct ifnet *ifp = sc->ifp;
- if (ifp->if_flags & IFF_PROMISC)
- sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
+ if (ifp->if_flags & IFF_PROMISC)
+ sc->ndis_filter |= NDIS_PACKET_TYPE_PROMISCUOUS;
+ }
len = sizeof(sc->ndis_filter);
@@ -1994,7 +2096,10 @@ ndis_init(xsc)
/*
* Set lookahead.
*/
- i = ifp->if_mtu;
+ if (sc->ndis_80211)
+ i = ETHERMTU;
+ else
+ i = sc->ifp->if_mtu;
len = sizeof(i);
ndis_set_info(sc, OID_GEN_CURRENT_LOOKAHEAD, &i, &len);
@@ -2012,10 +2117,12 @@ ndis_init(xsc)
sc->ndis_txpending = sc->ndis_maxpkts;
sc->ndis_link = 0;
- if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
+ if (!sc->ndis_80211) {
+ if_link_state_change(sc->ifp, LINK_STATE_UNKNOWN);
+ sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ }
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
sc->ndis_tx_timer = 0;
/*
@@ -2029,11 +2136,12 @@ ndis_init(xsc)
sc->ndis_hang_timer = sc->ndis_block->nmb_checkforhangsecs;
callout_reset(&sc->ndis_stat_callout, hz, ndis_tick, sc);
+ sc->ndis_running = 1;
NDIS_UNLOCK(sc);
/* XXX force handling */
if (sc->ndis_80211)
- ieee80211_start_all(ic); /* start all vap's */
+ ieee80211_start_all(&sc->ndis_ic); /* start all vap's */
}
/*
@@ -2101,16 +2209,12 @@ ndis_ifmedia_sts(ifp, ifmr)
}
static int
-ndis_set_cipher(sc, cipher)
- struct ndis_softc *sc;
- int cipher;
+ndis_set_cipher(struct ndis_softc *sc, int cipher)
{
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->ndis_ic;
int rval = 0, len;
uint32_t arg, save;
- ic = sc->ifp->if_l2com;
-
len = sizeof(arg);
if (cipher == WPA_CSE_WEP40 || cipher == WPA_CSE_WEP104) {
@@ -2239,7 +2343,7 @@ static void
ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
{
struct ieee80211vap *vap = ifp->if_softc;
- struct ndis_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct ndis_softc *sc = vap->iv_ic->ic_softc;
uint32_t txrate;
int len;
@@ -2253,20 +2357,14 @@ ndis_media_status(struct ifnet *ifp, struct ifmediareq *imr)
}
static void
-ndis_setstate_80211(sc)
- struct ndis_softc *sc;
+ndis_setstate_80211(struct ndis_softc *sc)
{
- struct ieee80211com *ic;
- struct ieee80211vap *vap;
+ struct ieee80211com *ic = &sc->ndis_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
ndis_80211_macaddr bssid;
ndis_80211_config config;
int rval = 0, len;
uint32_t arg;
- struct ifnet *ifp;
-
- ifp = sc->ifp;
- ic = ifp->if_l2com;
- vap = TAILQ_FIRST(&ic->ic_vaps);
if (!NDIS_INITIALIZED(sc)) {
DPRINTF(("%s: NDIS not initialized\n", __func__));
@@ -2371,7 +2469,7 @@ ndis_setstate_80211(sc)
/* Set the BSSID to our value so the driver doesn't associate */
len = IEEE80211_ADDR_LEN;
- bcopy(IF_LLADDR(ifp), bssid, len);
+ bcopy(vap->iv_myaddr, bssid, len);
DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
if (rval)
@@ -2380,22 +2478,14 @@ ndis_setstate_80211(sc)
}
static void
-ndis_auth_and_assoc(sc, vap)
- struct ndis_softc *sc;
- struct ieee80211vap *vap;
+ndis_auth_and_assoc(struct ndis_softc *sc, struct ieee80211vap *vap)
{
- struct ieee80211com *ic;
- struct ieee80211_node *ni;
+ struct ieee80211_node *ni = vap->iv_bss;
ndis_80211_ssid ssid;
ndis_80211_macaddr bssid;
ndis_80211_wep wep;
int i, rval = 0, len, error;
uint32_t arg;
- struct ifnet *ifp;
-
- ifp = sc->ifp;
- ic = ifp->if_l2com;
- ni = vap->iv_bss;
if (!NDIS_INITIALIZED(sc)) {
DPRINTF(("%s: NDIS not initialized\n", __func__));
@@ -2562,7 +2652,7 @@ ndis_auth_and_assoc(sc, vap)
vap->iv_opmode != IEEE80211_M_IBSS)
bcopy(ni->ni_bssid, bssid, len);
else
- bcopy(ifp->if_broadcastaddr, bssid, len);
+ bcopy(ieee80211broadcastaddr, bssid, len);
DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
@@ -2627,12 +2717,9 @@ ndis_get_bssid_list(sc, bl)
}
static int
-ndis_get_assoc(sc, assoc)
- struct ndis_softc *sc;
- ndis_wlan_bssid_ex **assoc;
+ndis_get_assoc(struct ndis_softc *sc, ndis_wlan_bssid_ex **assoc)
{
- struct ifnet *ifp = sc->ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->ndis_ic;
struct ieee80211vap *vap;
struct ieee80211_node *ni;
ndis_80211_bssid_list_ex *bl;
@@ -2679,22 +2766,15 @@ ndis_get_assoc(sc, assoc)
}
static void
-ndis_getstate_80211(sc)
- struct ndis_softc *sc;
+ndis_getstate_80211(struct ndis_softc *sc)
{
- struct ieee80211com *ic;
- struct ieee80211vap *vap;
- struct ieee80211_node *ni;
+ struct ieee80211com *ic = &sc->ndis_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct ieee80211_node *ni = vap->iv_bss;
ndis_wlan_bssid_ex *bs;
int rval, len, i = 0;
int chanflag;
uint32_t arg;
- struct ifnet *ifp;
-
- ifp = sc->ifp;
- ic = ifp->if_l2com;
- vap = TAILQ_FIRST(&ic->ic_vaps);
- ni = vap->iv_bss;
if (!NDIS_INITIALIZED(sc))
return;
@@ -2813,7 +2893,7 @@ ndis_ioctl(ifp, command, data)
switch (command) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
+ if (sc->ndis_running &&
ifp->if_flags & IFF_PROMISC &&
!(sc->ndis_if_flags & IFF_PROMISC)) {
sc->ndis_filter |=
@@ -2822,7 +2902,7 @@ ndis_ioctl(ifp, command, data)
error = ndis_set_info(sc,
OID_GEN_CURRENT_PACKET_FILTER,
&sc->ndis_filter, &i);
- } else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
+ } else if (sc->ndis_running &&
!(ifp->if_flags & IFF_PROMISC) &&
sc->ndis_if_flags & IFF_PROMISC) {
sc->ndis_filter &=
@@ -2834,7 +2914,7 @@ ndis_ioctl(ifp, command, data)
} else
ndis_init(sc);
} else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->ndis_running)
ndis_stop(sc);
}
sc->ndis_if_flags = ifp->if_flags;
@@ -2868,101 +2948,48 @@ ndis_ioctl(ifp, command, data)
}
static int
-ndis_ioctl_80211(ifp, command, data)
- struct ifnet *ifp;
- u_long command;
- caddr_t data;
+ndis_80211ioctl(struct ieee80211com *ic, u_long cmd, void *data)
{
- struct ndis_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- struct ndis_oid_data oid;
- struct ndis_evt evt;
- void *oidbuf;
- int error = 0;
+ struct ndis_softc *sc = ic->ic_softc;
+ struct ifreq *ifr = data;
+ struct ndis_oid_data oid;
+ struct ndis_evt evt;
+ void *oidbuf = NULL;
+ int error = 0;
+
+ if ((error = priv_check(curthread, PRIV_DRIVER)) != 0)
+ return (error);
- switch (command) {
- case SIOCSIFFLAGS:
- /*NDIS_LOCK(sc);*/
- if (ifp->if_flags & IFF_UP) {
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
- ndis_init(sc);
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ndis_stop(sc);
- }
- sc->ndis_if_flags = ifp->if_flags;
- error = 0;
- /*NDIS_UNLOCK(sc);*/
- break;
+ switch (cmd) {
case SIOCGDRVSPEC:
- if ((error = priv_check(curthread, PRIV_DRIVER)))
- break;
- error = copyin(ifr->ifr_data, &oid, sizeof(oid));
+ case SIOCSDRVSPEC:
+ error = copyin(ifr->ifr_data, &oid, sizeof(oid));
if (error)
break;
- oidbuf = malloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
- if (oidbuf == NULL) {
- error = ENOMEM;
- break;
- }
- error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
- if (error) {
- free(oidbuf, M_TEMP);
- break;
- }
- error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
- if (error) {
- free(oidbuf, M_TEMP);
- break;
- }
- error = copyout(&oid, ifr->ifr_data, sizeof(oid));
- if (error) {
- free(oidbuf, M_TEMP);
- break;
- }
- error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
+ oidbuf = malloc(oid.len, M_TEMP, M_WAITOK | M_ZERO);
+ error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
+ }
+
+ if (error) {
free(oidbuf, M_TEMP);
+ return (error);
+ }
+
+ switch (cmd) {
+ case SIOCGDRVSPEC:
+ error = ndis_get_info(sc, oid.oid, oidbuf, &oid.len);
break;
case SIOCSDRVSPEC:
- if ((error = priv_check(curthread, PRIV_DRIVER)))
- break;
- error = copyin(ifr->ifr_data, &oid, sizeof(oid));
- if (error)
- break;
- oidbuf = malloc(oid.len, M_TEMP, M_NOWAIT|M_ZERO);
- if (oidbuf == NULL) {
- error = ENOMEM;
- break;
- }
- error = copyin(ifr->ifr_data + sizeof(oid), oidbuf, oid.len);
- if (error) {
- free(oidbuf, M_TEMP);
- break;
- }
error = ndis_set_info(sc, oid.oid, oidbuf, &oid.len);
- if (error) {
- free(oidbuf, M_TEMP);
- break;
- }
- error = copyout(&oid, ifr->ifr_data, sizeof(oid));
- if (error) {
- free(oidbuf, M_TEMP);
- break;
- }
- error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
- free(oidbuf, M_TEMP);
break;
case SIOCGPRIVATE_0:
- if ((error = priv_check(curthread, PRIV_DRIVER)))
- break;
NDIS_LOCK(sc);
if (sc->ndis_evt[sc->ndis_evtcidx].ne_sts == 0) {
error = ENOENT;
NDIS_UNLOCK(sc);
break;
}
- error = copyin(ifr->ifr_data, &evt, sizeof(evt));
+ error = copyin(ifr->ifr_data, &evt, sizeof(evt));
if (error) {
NDIS_UNLOCK(sc);
break;
@@ -2994,30 +3021,32 @@ ndis_ioctl_80211(ifp, command, data)
NDIS_EVTINC(sc->ndis_evtcidx);
NDIS_UNLOCK(sc);
break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, command);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, command, data);
- break;
default:
- error = EINVAL;
+ error = ENOTTY;
break;
}
+
+ switch (cmd) {
+ case SIOCGDRVSPEC:
+ case SIOCSDRVSPEC:
+ error = copyout(&oid, ifr->ifr_data, sizeof(oid));
+ if (error)
+ break;
+ error = copyout(oidbuf, ifr->ifr_data + sizeof(oid), oid.len);
+ }
+
+ free(oidbuf, M_TEMP);
+
return (error);
}
int
-ndis_del_key(vap, key)
- struct ieee80211vap *vap;
- const struct ieee80211_key *key;
+ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
{
- struct ndis_softc *sc;
+ struct ndis_softc *sc = vap->iv_ic->ic_softc;
ndis_80211_key rkey;
int len, error = 0;
- sc = vap->iv_ic->ic_ifp->if_softc;
-
bzero((char *)&rkey, sizeof(rkey));
len = sizeof(rkey);
@@ -3041,19 +3070,13 @@ ndis_del_key(vap, key)
* set after initial authentication with the AP.
*/
static int
-ndis_add_key(vap, key, mac)
- struct ieee80211vap *vap;
- const struct ieee80211_key *key;
- const uint8_t mac[IEEE80211_ADDR_LEN];
+ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key,
+ const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct ndis_softc *sc;
- struct ifnet *ifp;
+ struct ndis_softc *sc = vap->iv_ic->ic_softc;
ndis_80211_key rkey;
int len, error = 0;
- ifp = vap->iv_ic->ic_ifp;
- sc = ifp->if_softc;
-
switch (key->wk_cipher->ic_cipher) {
case IEEE80211_CIPHER_TKIP:
@@ -3077,7 +3100,7 @@ ndis_add_key(vap, key, mac)
rkey.nk_keyidx |= 1 << 31;
if (key->wk_flags & IEEE80211_KEY_GROUP) {
- bcopy(ifp->if_broadcastaddr,
+ bcopy(ieee80211broadcastaddr,
rkey.nk_bssid, IEEE80211_ADDR_LEN);
} else {
bcopy(vap->iv_bss->ni_bssid,
@@ -3138,19 +3161,18 @@ ndis_resettask(d, arg)
* RX and TX lists.
*/
static void
-ndis_stop(sc)
- struct ndis_softc *sc;
+ndis_stop(struct ndis_softc *sc)
{
- struct ifnet *ifp;
int i;
- ifp = sc->ifp;
callout_drain(&sc->ndis_stat_callout);
NDIS_LOCK(sc);
sc->ndis_tx_timer = 0;
sc->ndis_link = 0;
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ if (!sc->ndis_80211)
+ sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->ndis_running = 0;
NDIS_UNLOCK(sc);
if (sc->ndis_iftype != PNPBus ||
@@ -3192,8 +3214,7 @@ ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ndis_vap *nvp = NDIS_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct ndis_softc *sc = ifp->if_softc;
+ struct ndis_softc *sc = ic->ic_softc;
enum ieee80211_state ostate;
DPRINTF(("%s: %s -> %s\n", __func__,
@@ -3239,8 +3260,8 @@ ndis_scan(void *arg)
static void
ndis_scan_results(struct ndis_softc *sc)
{
- struct ieee80211com *ic;
- struct ieee80211vap *vap;
+ struct ieee80211com *ic = &sc->ndis_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
ndis_80211_bssid_list_ex *bl;
ndis_wlan_bssid_ex *wb;
struct ieee80211_scanparams sp;
@@ -3252,8 +3273,6 @@ ndis_scan_results(struct ndis_softc *sc)
uint8_t rates[2+IEEE80211_RATE_MAXSIZE];
uint8_t *frm, *efrm;
- ic = sc->ifp->if_l2com;
- vap = TAILQ_FIRST(&ic->ic_vaps);
saved_chan = ic->ic_curchan;
noise = -96;
@@ -3329,8 +3348,7 @@ done:
static void
ndis_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ndis_softc *sc = ifp->if_softc;
+ struct ndis_softc *sc = ic->ic_softc;
struct ieee80211vap *vap;
struct ieee80211_scan_state *ss;
ndis_80211_ssid ssid;
@@ -3391,7 +3409,7 @@ ndis_scan_mindwell(struct ieee80211_scan_state *ss)
static void
ndis_scan_end(struct ieee80211com *ic)
{
- struct ndis_softc *sc = ic->ic_ifp->if_softc;
+ struct ndis_softc *sc = ic->ic_softc;
ndis_scan_results(sc);
}
diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h
index f98db0a..e3b1a39 100644
--- a/sys/dev/if_ndis/if_ndisvar.h
+++ b/sys/dev/if_ndis/if_ndisvar.h
@@ -152,8 +152,22 @@ struct ndisusb_task {
};
struct ndis_softc {
- struct ifnet *ifp;
- struct ifmedia ifmedia; /* media info */
+ u_int ndis_80211:1,
+ ndis_link:1,
+ ndis_running:1;
+ union {
+ struct { /* Ethernet */
+ struct ifnet *ifp;
+ struct ifmedia ifmedia;
+ int ndis_if_flags;
+ };
+ struct { /* Wireless */
+ struct ieee80211com ndis_ic;
+ struct callout ndis_scan_callout;
+ int (*ndis_newstate)(struct ieee80211com *,
+ enum ieee80211_state, int);
+ };
+ };
u_long ndis_hwassist;
uint32_t ndis_v4tx;
uint32_t ndis_v4rx;
@@ -180,7 +194,6 @@ struct ndis_softc {
ndis_miniport_block *ndis_block;
ndis_miniport_characteristics *ndis_chars;
interface_type ndis_type;
- struct callout ndis_scan_callout;
struct callout ndis_stat_callout;
int ndis_maxpkts;
ndis_oid *ndis_oids;
@@ -192,13 +205,9 @@ struct ndis_softc {
int ndis_sc;
ndis_cfg *ndis_regvals;
struct nch ndis_cfglist_head;
- int ndis_80211;
- int ndis_link;
uint32_t ndis_sts;
uint32_t ndis_filter;
- int ndis_if_flags;
int ndis_skip;
-
int ndis_devidx;
interface_type ndis_iftype;
driver_object *ndis_dobj;
@@ -217,11 +226,9 @@ struct ndis_softc {
struct ndis_evt ndis_evt[NDIS_EVENTS];
int ndis_evtpidx;
int ndis_evtcidx;
- struct ifqueue ndis_rxqueue;
+ struct mbufq ndis_rxqueue;
kspin_lock ndis_rxlock;
- int (*ndis_newstate)(struct ieee80211com *,
- enum ieee80211_state, int);
int ndis_tx_timer;
int ndis_hang_timer;
diff --git a/sys/dev/ipw/if_ipw.c b/sys/dev/ipw/if_ipw.c
index d3eb85e..1ffd24c 100644
--- a/sys/dev/ipw/if_ipw.c
+++ b/sys/dev/ipw/if_ipw.c
@@ -127,14 +127,14 @@ static void ipw_intr(void *);
static void ipw_dma_map_addr(void *, bus_dma_segment_t *, int, int);
static const char * ipw_cmdname(int);
static int ipw_cmd(struct ipw_softc *, uint32_t, void *, uint32_t);
-static int ipw_tx_start(struct ifnet *, struct mbuf *,
+static int ipw_tx_start(struct ipw_softc *, struct mbuf *,
struct ieee80211_node *);
static int ipw_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
-static void ipw_start(struct ifnet *);
-static void ipw_start_locked(struct ifnet *);
+static int ipw_transmit(struct ieee80211com *, struct mbuf *);
+static void ipw_start(struct ipw_softc *);
static void ipw_watchdog(void *);
-static int ipw_ioctl(struct ifnet *, u_long, caddr_t);
+static void ipw_parent(struct ieee80211com *);
static void ipw_stop_master(struct ipw_softc *);
static int ipw_enable(struct ipw_softc *);
static int ipw_disable(struct ipw_softc *);
@@ -220,18 +220,16 @@ static int
ipw_attach(device_t dev)
{
struct ipw_softc *sc = device_get_softc(dev);
- struct ifnet *ifp;
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *c;
uint16_t val;
int error, i;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
-
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
TASK_INIT(&sc->sc_init_task, 0, ipw_init_task, sc);
callout_init_mtx(&sc->sc_wdtimer, &sc->sc_mtx, 0);
@@ -268,24 +266,6 @@ ipw_attach(device_t dev)
goto fail2;
}
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(dev, "can not if_alloc()\n");
- goto fail3;
- }
- ic = ifp->if_l2com;
-
- ifp->if_softc = sc;
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = ipw_init;
- ifp->if_ioctl = ipw_ioctl;
- ifp->if_start = ipw_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_opmode = IEEE80211_M_STA;
@@ -303,14 +283,14 @@ ipw_attach(device_t dev)
/* read MAC address from EEPROM */
val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 0);
- macaddr[0] = val >> 8;
- macaddr[1] = val & 0xff;
+ ic->ic_macaddr[0] = val >> 8;
+ ic->ic_macaddr[1] = val & 0xff;
val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 1);
- macaddr[2] = val >> 8;
- macaddr[3] = val & 0xff;
+ ic->ic_macaddr[2] = val >> 8;
+ ic->ic_macaddr[3] = val & 0xff;
val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 2);
- macaddr[4] = val >> 8;
- macaddr[5] = val & 0xff;
+ ic->ic_macaddr[4] = val >> 8;
+ ic->ic_macaddr[5] = val & 0xff;
/* set supported .11b channels (read from EEPROM) */
if ((val = ipw_read_prom_word(sc, IPW_EEPROM_CHANNEL_LIST)) == 0)
@@ -329,16 +309,17 @@ ipw_attach(device_t dev)
if (!(ipw_read_prom_word(sc, IPW_EEPROM_RADIO) & 8))
sc->flags |= IPW_FLAG_HAS_RADIO_SWITCH;
- ieee80211_ifattach(ic, macaddr);
+ ieee80211_ifattach(ic);
ic->ic_scan_start = ipw_scan_start;
ic->ic_scan_end = ipw_scan_end;
ic->ic_set_channel = ipw_set_channel;
ic->ic_scan_curchan = ipw_scan_curchan;
ic->ic_scan_mindwell = ipw_scan_mindwell;
ic->ic_raw_xmit = ipw_raw_xmit;
-
ic->ic_vap_create = ipw_vap_create;
ic->ic_vap_delete = ipw_vap_delete;
+ ic->ic_transmit = ipw_transmit;
+ ic->ic_parent = ipw_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -366,15 +347,13 @@ ipw_attach(device_t dev)
NULL, ipw_intr, sc, &sc->sc_ih);
if (error != 0) {
device_printf(dev, "could not set up interrupt\n");
- goto fail4;
+ goto fail3;
}
if (bootverbose)
ieee80211_announce(ic);
return 0;
-fail4:
- if_free(ifp);
fail3:
ipw_release(sc);
fail2:
@@ -391,8 +370,7 @@ static int
ipw_detach(device_t dev)
{
struct ipw_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
bus_teardown_intr(dev, sc->irq, sc->sc_ih);
@@ -402,6 +380,7 @@ ipw_detach(device_t dev)
ieee80211_ifdetach(ic);
callout_drain(&sc->sc_wdtimer);
+ mbufq_drain(&sc->sc_snd);
ipw_release(sc);
@@ -410,8 +389,6 @@ ipw_detach(device_t dev)
bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(sc->mem),
sc->mem);
- if_free(ifp);
-
if (sc->sc_firmware != NULL) {
firmware_put(sc->sc_firmware, FIRMWARE_UNLOAD);
sc->sc_firmware = NULL;
@@ -428,8 +405,7 @@ ipw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ipw_softc *sc = ifp->if_softc;
+ struct ipw_softc *sc = ic->ic_softc;
struct ipw_vap *ivp;
struct ieee80211vap *vap;
const struct firmware *fp;
@@ -487,19 +463,17 @@ ipw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
return NULL;
}
- ivp = (struct ipw_vap *) malloc(sizeof(struct ipw_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (ivp == NULL)
- return NULL;
+ ivp = malloc(sizeof(struct ipw_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &ivp->vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override with driver methods */
ivp->newstate = vap->iv_newstate;
vap->iv_newstate = ipw_newstate;
/* complete setup */
- ieee80211_vap_attach(vap, ieee80211_media_change, ipw_media_status);
+ ieee80211_vap_attach(vap, ieee80211_media_change, ipw_media_status,
+ mac);
ic->ic_opmode = opmode;
return vap;
}
@@ -827,7 +801,7 @@ static int
ipw_suspend(device_t dev)
{
struct ipw_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
ieee80211_suspend_all(ic);
return 0;
@@ -837,7 +811,7 @@ static int
ipw_resume(device_t dev)
{
struct ipw_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
pci_write_config(dev, 0x41, 0, 1);
@@ -866,7 +840,7 @@ ipw_media_status(struct ifnet *ifp, struct ifmediareq *imr)
{
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
- struct ipw_softc *sc = ic->ic_ifp->if_softc;
+ struct ipw_softc *sc = ic->ic_softc;
/* read current transmission rate from adapter */
vap->iv_bss->ni_txrate = ipw_cvtrate(
@@ -879,8 +853,7 @@ ipw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ipw_vap *ivp = IPW_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct ipw_softc *sc = ifp->if_softc;
+ struct ipw_softc *sc = ic->ic_softc;
enum ieee80211_state ostate;
DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__,
@@ -1015,8 +988,7 @@ static void
ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
{
#define IEEESTATE(vap) ieee80211_state_name[vap->iv_state]
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t state;
@@ -1118,8 +1090,7 @@ ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
static void
ipw_setcurchan(struct ipw_softc *sc, struct ieee80211_channel *chan)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
ic->ic_curchan = chan;
ieee80211_radiotap_chan_change(ic);
@@ -1132,8 +1103,7 @@ ipw_setcurchan(struct ipw_softc *sc, struct ieee80211_channel *chan)
static void
ipw_fix_channel(struct ipw_softc *sc, struct mbuf *m)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *c;
struct ieee80211_frame *wh;
uint8_t subtype;
@@ -1178,8 +1148,7 @@ static void
ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
struct ipw_soft_bd *sbd, struct ipw_soft_buf *sbuf)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *mnew, *m;
struct ieee80211_node *ni;
bus_addr_t physaddr;
@@ -1201,7 +1170,7 @@ ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
*/
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (mnew == NULL) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return;
}
@@ -1222,7 +1191,7 @@ ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
panic("%s: could not load old rx mbuf",
device_get_name(sc->sc_dev));
}
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return;
}
@@ -1233,9 +1202,6 @@ ipw_rx_data_intr(struct ipw_softc *sc, struct ipw_status *status,
m = sbuf->m;
sbuf->m = mnew;
sbd->bd->physaddr = htole32(physaddr);
-
- /* finalize mbuf */
- m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = le32toh(status->len);
rssi = status->rssi + IPW_RSSI_TO_DBM;
@@ -1364,7 +1330,6 @@ ipw_release_sbd(struct ipw_softc *sc, struct ipw_soft_bd *sbd)
static void
ipw_tx_intr(struct ipw_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
struct ipw_soft_bd *sbd;
uint32_t r, i;
@@ -1375,10 +1340,6 @@ ipw_tx_intr(struct ipw_softc *sc)
for (i = (sc->txold + 1) % IPW_NTBD; i != r; i = (i + 1) % IPW_NTBD) {
sbd = &sc->stbd_list[i];
-
- if (sbd->type == IPW_SBD_TYPE_DATA)
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
-
ipw_release_sbd(sc, sbd);
sc->txfree++;
}
@@ -1386,15 +1347,13 @@ ipw_tx_intr(struct ipw_softc *sc)
/* remember what the firmware has processed */
sc->txold = (r == 0) ? IPW_NTBD - 1 : r - 1;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ipw_start_locked(ifp);
+ ipw_start(sc);
}
static void
ipw_fatal_error_intr(struct ipw_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
device_printf(sc->sc_dev, "firmware error\n");
@@ -1579,10 +1538,9 @@ ipw_cmd(struct ipw_softc *sc, uint32_t type, void *data, uint32_t len)
}
static int
-ipw_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni)
+ipw_tx_start(struct ipw_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
- struct ipw_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_frame *wh;
struct ipw_soft_bd *sbd;
@@ -1736,38 +1694,42 @@ ipw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
}
-static void
-ipw_start(struct ifnet *ifp)
+static int
+ipw_transmit(struct ieee80211com *ic, struct mbuf *m)
{
- struct ipw_softc *sc = ifp->if_softc;
+ struct ipw_softc *sc = ic->ic_softc;
+ int error;
IPW_LOCK(sc);
- ipw_start_locked(ifp);
+ if ((sc->flags & IPW_FLAG_RUNNING) == 0) {
+ IPW_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ IPW_UNLOCK(sc);
+ return (error);
+ }
+ ipw_start(sc);
IPW_UNLOCK(sc);
+ return (0);
}
static void
-ipw_start_locked(struct ifnet *ifp)
+ipw_start(struct ipw_softc *sc)
{
- struct ipw_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
IPW_LOCK_ASSERT(sc);
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
- if (sc->txfree < 1 + IPW_MAX_NSEG) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
+ while (sc->txfree < 1 + IPW_MAX_NSEG &&
+ (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- if (ipw_tx_start(ifp, m, ni) != 0) {
+ if (ipw_tx_start(sc, m, ni) != 0) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
break;
}
/* start watchdog timer */
@@ -1779,15 +1741,14 @@ static void
ipw_watchdog(void *arg)
{
struct ipw_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
IPW_LOCK_ASSERT(sc);
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
- if_printf(ifp, "device timeout\n");
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ device_printf(sc->sc_dev, "device timeout\n");
+ counter_u64_add(ic->ic_oerrors, 1);
taskqueue_enqueue(taskqueue_swi, &sc->sc_init_task);
}
}
@@ -1803,45 +1764,27 @@ ipw_watchdog(void *arg)
}
}
}
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->flags & IPW_FLAG_RUNNING)
callout_reset(&sc->sc_wdtimer, hz, ipw_watchdog, sc);
}
-static int
-ipw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+ipw_parent(struct ieee80211com *ic)
{
- struct ipw_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ struct ipw_softc *sc = ic->ic_softc;
+ int startall = 0;
- switch (cmd) {
- case SIOCSIFFLAGS:
- IPW_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- ipw_init_locked(sc);
- startall = 1;
- }
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ipw_stop_locked(sc);
+ IPW_LOCK(sc);
+ if (ic->ic_nrunning > 0) {
+ if (!(sc->flags & IPW_FLAG_RUNNING)) {
+ ipw_init_locked(sc);
+ startall = 1;
}
- IPW_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
- }
- return error;
+ } else if (sc->flags & IPW_FLAG_RUNNING)
+ ipw_stop_locked(sc);
+ IPW_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
static void
@@ -2057,8 +2000,7 @@ ipw_load_firmware(struct ipw_softc *sc, const char *fw, int size)
static int
ipw_setwepkeys(struct ipw_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ipw_wep_key wepkey;
struct ieee80211_key *wk;
@@ -2201,8 +2143,7 @@ done:
static int
ipw_setchannel(struct ipw_softc *sc, struct ieee80211_channel *chan)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t data;
int error;
@@ -2217,8 +2158,7 @@ ipw_setchannel(struct ipw_softc *sc, struct ieee80211_channel *chan)
static void
ipw_assoc(struct ieee80211com *ic, struct ieee80211vap *vap)
{
- struct ifnet *ifp = vap->iv_ic->ic_ifp;
- struct ipw_softc *sc = ifp->if_softc;
+ struct ipw_softc *sc = ic->ic_softc;
struct ieee80211_node *ni = vap->iv_bss;
struct ipw_security security;
uint32_t data;
@@ -2309,9 +2249,8 @@ done:
static void
ipw_disassoc(struct ieee80211com *ic, struct ieee80211vap *vap)
{
- struct ifnet *ifp = vap->iv_ic->ic_ifp;
struct ieee80211_node *ni = vap->iv_bss;
- struct ipw_softc *sc = ifp->if_softc;
+ struct ipw_softc *sc = ic->ic_softc;
IPW_LOCK(sc);
DPRINTF(("Disassociate from %6D\n", ni->ni_bssid, ":"));
@@ -2345,22 +2284,20 @@ static void
ipw_init(void *priv)
{
struct ipw_softc *sc = priv;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
IPW_LOCK(sc);
ipw_init_locked(sc);
IPW_UNLOCK(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->flags & IPW_FLAG_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
static void
ipw_init_locked(struct ipw_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
const struct firmware *fp;
const struct ipw_firmware_hdr *hdr;
@@ -2444,22 +2381,19 @@ ipw_init_locked(struct ipw_softc *sc)
}
callout_reset(&sc->sc_wdtimer, hz, ipw_watchdog, sc);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
-
- sc->flags &=~ IPW_FLAG_INIT_LOCKED;
+ sc->flags |= IPW_FLAG_RUNNING;
+ sc->flags &= ~IPW_FLAG_INIT_LOCKED;
return;
fail:
ipw_stop_locked(sc);
- sc->flags &=~ IPW_FLAG_INIT_LOCKED;
+ sc->flags &= ~IPW_FLAG_INIT_LOCKED;
}
static int
ipw_config(struct ipw_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ipw_configuration config;
uint32_t data;
int error;
@@ -2504,7 +2438,7 @@ ipw_config(struct ipw_softc *sc)
IPW_CFG_PREAMBLE_AUTO | IPW_CFG_802_1x_ENABLE);
if (ic->ic_opmode == IEEE80211_M_IBSS)
config.flags |= htole32(IPW_CFG_IBSS_AUTO_START);
- if (ifp->if_flags & IFF_PROMISC)
+ if (ic->ic_promisc > 0)
config.flags |= htole32(IPW_CFG_PROMISCUOUS);
config.bss_chan = htole32(0x3fff); /* channels 1-14 */
config.ibss_chan = htole32(0x7ff); /* channels 1-11 */
@@ -2562,7 +2496,6 @@ ipw_stop(void *priv)
static void
ipw_stop_locked(struct ipw_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
int i;
IPW_LOCK_ASSERT(sc);
@@ -2579,7 +2512,7 @@ ipw_stop_locked(struct ipw_softc *sc)
ipw_release_sbd(sc, &sc->stbd_list[i]);
sc->sc_tx_timer = 0;
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->flags &= ~IPW_FLAG_RUNNING;
}
static int
@@ -2677,8 +2610,7 @@ ipw_write_mem_1(struct ipw_softc *sc, bus_size_t offset, const uint8_t *datap,
static void
ipw_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ipw_softc *sc = ifp->if_softc;
+ struct ipw_softc *sc = ic->ic_softc;
IPW_LOCK(sc);
ipw_scan(sc);
@@ -2688,8 +2620,7 @@ ipw_scan_start(struct ieee80211com *ic)
static void
ipw_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ipw_softc *sc = ifp->if_softc;
+ struct ipw_softc *sc = ic->ic_softc;
IPW_LOCK(sc);
if (ic->ic_opmode == IEEE80211_M_MONITOR) {
@@ -2715,8 +2646,7 @@ ipw_scan_mindwell(struct ieee80211_scan_state *ss)
static void
ipw_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ipw_softc *sc = ifp->if_softc;
+ struct ipw_softc *sc = ic->ic_softc;
IPW_LOCK(sc);
sc->flags &= ~IPW_FLAG_SCANNING;
diff --git a/sys/dev/ipw/if_ipwvar.h b/sys/dev/ipw/if_ipwvar.h
index cca050f..aa3ba5b 100644
--- a/sys/dev/ipw/if_ipwvar.h
+++ b/sys/dev/ipw/if_ipwvar.h
@@ -87,7 +87,8 @@ struct ipw_vap {
#define IPW_VAP(vap) ((struct ipw_vap *)(vap))
struct ipw_softc {
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
device_t sc_dev;
struct mtx sc_mtx;
@@ -104,6 +105,7 @@ struct ipw_softc {
#define IPW_FLAG_BUSY 0x0040
#define IPW_FLAG_ASSOCIATING 0x0080
#define IPW_FLAG_ASSOCIATED 0x0100
+#define IPW_FLAG_RUNNING 0x0200
struct resource *irq;
struct resource *mem;
diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c
index 5188ac8..10430f6 100644
--- a/sys/dev/iscsi/iscsi.c
+++ b/sys/dev/iscsi/iscsi.c
@@ -2322,11 +2322,23 @@ iscsi_shutdown(struct iscsi_softc *sc)
{
struct iscsi_session *is;
- ISCSI_DEBUG("removing all sessions due to shutdown");
+ /*
+ * Trying to reconnect during system shutdown would lead to hang.
+ */
+ fail_on_disconnection = 1;
+ /*
+ * If we have any sessions waiting for reconnection, request
+ * maintenance thread to fail them immediately instead of waiting
+ * for reconnect timeout.
+ */
sx_slock(&sc->sc_lock);
- TAILQ_FOREACH(is, &sc->sc_sessions, is_next)
- iscsi_session_terminate(is);
+ TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
+ ISCSI_SESSION_LOCK(is);
+ if (is->is_waiting_for_iscsid)
+ iscsi_session_reconnect(is);
+ ISCSI_SESSION_UNLOCK(is);
+ }
sx_sunlock(&sc->sc_lock);
}
@@ -2352,12 +2364,7 @@ iscsi_load(void)
}
sc->sc_cdev->si_drv1 = sc;
- /*
- * Note that this needs to get run before dashutdown(). Otherwise,
- * when rebooting with iSCSI session with outstanding requests,
- * but disconnected, dashutdown() will hang on cam_periph_runccb().
- */
- sc->sc_shutdown_eh = EVENTHANDLER_REGISTER(shutdown_post_sync,
+ sc->sc_shutdown_eh = EVENTHANDLER_REGISTER(shutdown_pre_sync,
iscsi_shutdown, sc, SHUTDOWN_PRI_FIRST);
return (0);
@@ -2375,7 +2382,7 @@ iscsi_unload(void)
}
if (sc->sc_shutdown_eh != NULL)
- EVENTHANDLER_DEREGISTER(shutdown_post_sync, sc->sc_shutdown_eh);
+ EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->sc_shutdown_eh);
sx_slock(&sc->sc_lock);
TAILQ_FOREACH_SAFE(is, &sc->sc_sessions, is_next, tmp)
diff --git a/sys/dev/iwi/if_iwi.c b/sys/dev/iwi/if_iwi.c
index fecbe89..73631ea 100644
--- a/sys/dev/iwi/if_iwi.c
+++ b/sys/dev/iwi/if_iwi.c
@@ -166,14 +166,15 @@ static void iwi_tx_intr(struct iwi_softc *, struct iwi_tx_ring *);
static void iwi_intr(void *);
static int iwi_cmd(struct iwi_softc *, uint8_t, void *, uint8_t);
static void iwi_write_ibssnode(struct iwi_softc *, const u_int8_t [], int);
-static int iwi_tx_start(struct ifnet *, struct mbuf *,
+static int iwi_tx_start(struct iwi_softc *, struct mbuf *,
struct ieee80211_node *, int);
static int iwi_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
-static void iwi_start_locked(struct ifnet *);
-static void iwi_start(struct ifnet *);
+static void iwi_start(struct iwi_softc *);
+static int iwi_transmit(struct ieee80211com *, struct mbuf *);
static void iwi_watchdog(void *);
-static int iwi_ioctl(struct ifnet *, u_long, caddr_t);
+static int iwi_ioctl(struct ieee80211com *, u_long, void *);
+static void iwi_parent(struct ieee80211com *);
static void iwi_stop_master(struct iwi_softc *);
static int iwi_reset(struct iwi_softc *);
static int iwi_load_ucode(struct iwi_softc *, const struct iwi_fw *);
@@ -269,23 +270,15 @@ static int
iwi_attach(device_t dev)
{
struct iwi_softc *sc = device_get_softc(dev);
- struct ifnet *ifp;
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t val;
int i, error;
uint8_t bands;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(dev, "can not if_alloc()\n");
- return ENXIO;
- }
- ic = ifp->if_l2com;
-
IWI_LOCK_INIT(sc);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
sc->sc_unr = new_unrhdr(1, IWI_MAX_IBSSNODE-1, &sc->sc_mtx);
@@ -353,17 +346,6 @@ iwi_attach(device_t dev)
iwi_wme_init(sc);
- ifp->if_softc = sc;
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = iwi_init;
- ifp->if_ioctl = iwi_ioctl;
- ifp->if_start = iwi_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_opmode = IEEE80211_M_STA;
@@ -385,14 +367,14 @@ iwi_attach(device_t dev)
/* read MAC address from EEPROM */
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0);
- macaddr[0] = val & 0xff;
- macaddr[1] = val >> 8;
+ ic->ic_macaddr[0] = val & 0xff;
+ ic->ic_macaddr[1] = val >> 8;
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 1);
- macaddr[2] = val & 0xff;
- macaddr[3] = val >> 8;
+ ic->ic_macaddr[2] = val & 0xff;
+ ic->ic_macaddr[3] = val >> 8;
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 2);
- macaddr[4] = val & 0xff;
- macaddr[5] = val >> 8;
+ ic->ic_macaddr[4] = val & 0xff;
+ ic->ic_macaddr[5] = val >> 8;
bands = 0;
setbit(&bands, IEEE80211_MODE_11B);
@@ -401,7 +383,7 @@ iwi_attach(device_t dev)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, macaddr);
+ ieee80211_ifattach(ic);
/* override default methods */
ic->ic_node_alloc = iwi_node_alloc;
sc->sc_node_free = ic->ic_node_free;
@@ -416,6 +398,9 @@ iwi_attach(device_t dev)
ic->ic_vap_create = iwi_vap_create;
ic->ic_vap_delete = iwi_vap_delete;
+ ic->ic_ioctl = iwi_ioctl;
+ ic->ic_transmit = iwi_transmit;
+ ic->ic_parent = iwi_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -450,8 +435,7 @@ static int
iwi_detach(device_t dev)
{
struct iwi_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
bus_teardown_intr(dev, sc->irq, sc->sc_ih);
@@ -482,11 +466,10 @@ iwi_detach(device_t dev)
sc->mem);
delete_unrhdr(sc->sc_unr);
+ mbufq_drain(&sc->sc_snd);
IWI_LOCK_DESTROY(sc);
- if_free(ifp);
-
return 0;
}
@@ -496,8 +479,7 @@ iwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = ic->ic_ifp;
- struct iwi_softc *sc = ifp->if_softc;
+ struct iwi_softc *sc = ic->ic_softc;
struct iwi_vap *ivp;
struct ieee80211vap *vap;
int i;
@@ -519,12 +501,9 @@ iwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (iwi_init_fw_dma(sc, i))
return NULL;
- ivp = (struct iwi_vap *) malloc(sizeof(struct iwi_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (ivp == NULL)
- return NULL;
+ ivp = malloc(sizeof(struct iwi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &ivp->iwi_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override the default, the setting comes from the linux driver */
vap->iv_bmissthreshold = 24;
/* override with driver methods */
@@ -532,7 +511,8 @@ iwi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
vap->iv_newstate = iwi_newstate;
/* complete setup */
- ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status);
+ ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status,
+ mac);
ic->ic_opmode = opmode;
return vap;
}
@@ -859,7 +839,7 @@ static int
iwi_suspend(device_t dev)
{
struct iwi_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
ieee80211_suspend_all(ic);
return 0;
@@ -869,7 +849,7 @@ static int
iwi_resume(device_t dev)
{
struct iwi_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
pci_write_config(dev, 0x41, 0, 1);
@@ -895,7 +875,7 @@ static void
iwi_node_free(struct ieee80211_node *ni)
{
struct ieee80211com *ic = ni->ni_ic;
- struct iwi_softc *sc = ic->ic_ifp->if_softc;
+ struct iwi_softc *sc = ic->ic_softc;
struct iwi_node *in = (struct iwi_node *)ni;
if (in->in_station != -1) {
@@ -939,7 +919,7 @@ iwi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
{
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
- struct iwi_softc *sc = ic->ic_ifp->if_softc;
+ struct iwi_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
/* read current transmission rate from adapter */
@@ -955,8 +935,7 @@ iwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct iwi_vap *ivp = IWI_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct iwi_softc *sc = ifp->if_softc;
+ struct iwi_softc *sc = ic->ic_softc;
IWI_LOCK_DECL;
DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__,
@@ -1061,7 +1040,7 @@ iwi_wme_init(struct iwi_softc *sc)
static int
iwi_wme_setparams(struct iwi_softc *sc)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
const struct wmeParams *wmep;
int ac;
@@ -1095,7 +1074,7 @@ iwi_update_wme(void *arg, int npending)
static int
iwi_wme_update(struct ieee80211com *ic)
{
- struct iwi_softc *sc = ic->ic_ifp->if_softc;
+ struct iwi_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
/*
@@ -1189,8 +1168,7 @@ iwi_read_prom_word(struct iwi_softc *sc, uint8_t addr)
static void
iwi_setcurchan(struct iwi_softc *sc, int chan)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
sc->curchan = chan;
ieee80211_radiotap_chan_change(ic);
@@ -1200,8 +1178,7 @@ static void
iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
struct iwi_frame *frame)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *mnew, *m;
struct ieee80211_node *ni;
int type, error, framelen;
@@ -1237,7 +1214,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
*/
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (mnew == NULL) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return;
}
@@ -1258,7 +1235,7 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
panic("%s: could not load old rx mbuf",
device_get_name(sc->sc_dev));
}
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return;
}
@@ -1271,7 +1248,6 @@ iwi_frame_intr(struct iwi_softc *sc, struct iwi_rx_data *data, int i,
CSR_WRITE_4(sc, data->reg, data->physaddr);
/* finalize mbuf */
- m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = sizeof (struct iwi_hdr) +
sizeof (struct iwi_frame) + framelen;
@@ -1410,8 +1386,7 @@ iwi_notif_link_quality(struct iwi_softc *sc, struct iwi_notif *notif)
static void
iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct iwi_notif_scan_channel *chan;
struct iwi_notif_scan_complete *scan;
@@ -1632,47 +1607,33 @@ iwi_rx_intr(struct iwi_softc *sc)
static void
iwi_tx_intr(struct iwi_softc *sc, struct iwi_tx_ring *txq)
{
- struct ifnet *ifp = sc->sc_ifp;
struct iwi_tx_data *data;
uint32_t hw;
hw = CSR_READ_4(sc, txq->csr_ridx);
- for (; txq->next != hw;) {
+ while (txq->next != hw) {
data = &txq->data[txq->next];
-
+ DPRINTFN(15, ("tx done idx=%u\n", txq->next));
bus_dmamap_sync(txq->data_dmat, data->map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(txq->data_dmat, data->map);
- if (data->m->m_flags & M_TXCB)
- ieee80211_process_callback(data->ni, data->m, 0/*XXX*/);
- m_freem(data->m);
- data->m = NULL;
- ieee80211_free_node(data->ni);
+ ieee80211_tx_complete(data->ni, data->m, 0);
data->ni = NULL;
-
- DPRINTFN(15, ("tx done idx=%u\n", txq->next));
-
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
-
+ data->m = NULL;
txq->queued--;
txq->next = (txq->next + 1) % IWI_TX_RING_COUNT;
}
-
sc->sc_tx_timer = 0;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
if (sc->sc_softled)
iwi_led_event(sc, IWI_LED_TX);
-
- iwi_start_locked(ifp);
+ iwi_start(sc);
}
static void
iwi_fatal_error_intr(struct iwi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
device_printf(sc->sc_dev, "firmware error\n");
@@ -1688,10 +1649,8 @@ iwi_fatal_error_intr(struct iwi_softc *sc)
static void
iwi_radio_off_intr(struct iwi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- ieee80211_runtask(ic, &sc->sc_radiofftask);
+ ieee80211_runtask(&sc->sc_ic, &sc->sc_radiofftask);
}
static void
@@ -1806,10 +1765,9 @@ iwi_write_ibssnode(struct iwi_softc *sc,
}
static int
-iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni,
+iwi_tx_start(struct iwi_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
int ac)
{
- struct iwi_softc *sc = ifp->if_softc;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
struct iwi_node *in = (struct iwi_node *)ni;
@@ -1852,9 +1810,10 @@ iwi_tx_start(struct ifnet *ifp, struct mbuf *m0, struct ieee80211_node *ni,
in->in_station = alloc_unr(sc->sc_unr);
if (in->in_station == -1) {
/* h/w table is full */
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
m_freem(m0);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return 0;
}
iwi_write_ibssnode(sc,
@@ -1980,141 +1939,139 @@ iwi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
}
+static int
+iwi_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct iwi_softc *sc = ic->ic_softc;
+ int error;
+ IWI_LOCK_DECL;
+
+ IWI_LOCK(sc);
+ if (!sc->sc_running) {
+ IWI_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ IWI_UNLOCK(sc);
+ return (error);
+ }
+ iwi_start(sc);
+ IWI_UNLOCK(sc);
+ return (0);
+}
+
static void
-iwi_start_locked(struct ifnet *ifp)
+iwi_start(struct iwi_softc *sc)
{
- struct iwi_softc *sc = ifp->if_softc;
struct mbuf *m;
struct ieee80211_node *ni;
int ac;
IWI_LOCK_ASSERT(sc);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return;
-
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ac = M_WME_GETAC(m);
if (sc->txq[ac].queued > IWI_TX_RING_COUNT - 8) {
/* there is no place left in this ring; tail drop */
/* XXX tail drop */
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ mbufq_prepend(&sc->sc_snd, m);
break;
}
-
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- if (iwi_tx_start(ifp, m, ni, ac) != 0) {
+ if (iwi_tx_start(sc, m, ni, ac) != 0) {
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
break;
}
-
sc->sc_tx_timer = 5;
}
}
static void
-iwi_start(struct ifnet *ifp)
-{
- struct iwi_softc *sc = ifp->if_softc;
- IWI_LOCK_DECL;
-
- IWI_LOCK(sc);
- iwi_start_locked(ifp);
- IWI_UNLOCK(sc);
-}
-
-static void
iwi_watchdog(void *arg)
{
struct iwi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
IWI_LOCK_ASSERT(sc);
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
- if_printf(ifp, "device timeout\n");
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ device_printf(sc->sc_dev, "device timeout\n");
+ counter_u64_add(ic->ic_oerrors, 1);
ieee80211_runtask(ic, &sc->sc_restarttask);
}
}
if (sc->sc_state_timer > 0) {
if (--sc->sc_state_timer == 0) {
- if_printf(ifp, "firmware stuck in state %d, resetting\n",
+ device_printf(sc->sc_dev,
+ "firmware stuck in state %d, resetting\n",
sc->fw_state);
- if (sc->fw_state == IWI_FW_SCANNING) {
- struct ieee80211com *ic = ifp->if_l2com;
+ if (sc->fw_state == IWI_FW_SCANNING)
ieee80211_cancel_scan(TAILQ_FIRST(&ic->ic_vaps));
- }
ieee80211_runtask(ic, &sc->sc_restarttask);
sc->sc_state_timer = 3;
}
}
if (sc->sc_busy_timer > 0) {
if (--sc->sc_busy_timer == 0) {
- if_printf(ifp, "firmware command timeout, resetting\n");
+ device_printf(sc->sc_dev,
+ "firmware command timeout, resetting\n");
ieee80211_runtask(ic, &sc->sc_restarttask);
}
}
callout_reset(&sc->sc_wdtimer, hz, iwi_watchdog, sc);
}
+static void
+iwi_parent(struct ieee80211com *ic)
+{
+ struct iwi_softc *sc = ic->ic_softc;
+ int startall = 0;
+ IWI_LOCK_DECL;
+
+ IWI_LOCK(sc);
+ if (ic->ic_nrunning > 0) {
+ if (!sc->sc_running) {
+ iwi_init_locked(sc);
+ startall = 1;
+ }
+ } else if (sc->sc_running)
+ iwi_stop_locked(sc);
+ IWI_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
+}
+
static int
-iwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+iwi_ioctl(struct ieee80211com *ic, u_long cmd, void *data)
{
- struct iwi_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ struct ifreq *ifr = data;
+ struct iwi_softc *sc = ic->ic_softc;
+ int error;
IWI_LOCK_DECL;
+ IWI_LOCK(sc);
switch (cmd) {
- case SIOCSIFFLAGS:
- IWI_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- iwi_init_locked(sc);
- startall = 1;
- }
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- iwi_stop_locked(sc);
- }
- IWI_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
case SIOCGIWISTATS:
- IWI_LOCK(sc);
/* XXX validate permissions/memory/etc? */
error = copyout(&sc->sc_linkqual, ifr->ifr_data,
sizeof(struct iwi_notif_link_quality));
- IWI_UNLOCK(sc);
break;
case SIOCZIWISTATS:
- IWI_LOCK(sc);
memset(&sc->sc_linkqual, 0,
sizeof(struct iwi_notif_link_quality));
- IWI_UNLOCK(sc);
error = 0;
break;
default:
- error = EINVAL;
+ error = ENOTTY;
break;
}
- return error;
+ IWI_UNLOCK(sc);
+
+ return (error);
}
static void
@@ -2593,8 +2550,7 @@ iwi_setwepkeys(struct iwi_softc *sc, struct ieee80211vap *vap)
static int
iwi_config(struct iwi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct iwi_configuration config;
struct iwi_rateset rs;
struct iwi_txpower power;
@@ -2603,8 +2559,8 @@ iwi_config(struct iwi_softc *sc)
IWI_LOCK_ASSERT(sc);
- DPRINTF(("Setting MAC address to %6D\n", IF_LLADDR(ifp), ":"));
- error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp),
+ DPRINTF(("Setting MAC address to %6D\n", ic->ic_macaddr, ":"));
+ error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, ic->ic_macaddr,
IEEE80211_ADDR_LEN);
if (error != 0)
return error;
@@ -2724,7 +2680,7 @@ iwi_monitor_scan(void *arg, int npending)
static int
iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int allchan)
{
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *chan;
struct ieee80211_scan_state *ss;
struct iwi_scan_ext scan;
@@ -2741,7 +2697,6 @@ iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int allchan)
}
IWI_STATE_BEGIN(sc, IWI_FW_SCANNING);
- ic = sc->sc_ifp->if_l2com;
ss = ic->ic_scan;
memset(&scan, 0, sizeof scan);
@@ -3128,7 +3083,6 @@ error:
static void
iwi_init_locked(struct iwi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
struct iwi_rx_data *data;
int i;
@@ -3202,8 +3156,7 @@ iwi_init_locked(struct iwi_softc *sc)
}
callout_reset(&sc->sc_wdtimer, hz, iwi_watchdog, sc);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_running = 1;
return;
fail:
IWI_STATE_END(sc, IWI_FW_LOADING);
@@ -3215,15 +3168,14 @@ static void
iwi_init(void *priv)
{
struct iwi_softc *sc = priv;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
IWI_LOCK_DECL;
IWI_LOCK(sc);
iwi_init_locked(sc);
IWI_UNLOCK(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->sc_running)
ieee80211_start_all(ic);
}
@@ -3231,11 +3183,10 @@ static void
iwi_stop_locked(void *priv)
{
struct iwi_softc *sc = priv;
- struct ifnet *ifp = sc->sc_ifp;
IWI_LOCK_ASSERT(sc);
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_running = 0;
if (sc->sc_softled) {
callout_stop(&sc->sc_ledtimer);
@@ -3296,7 +3247,7 @@ static void
iwi_radio_on(void *arg, int pending)
{
struct iwi_softc *sc = arg;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
device_printf(sc->sc_dev, "radio turned on\n");
@@ -3317,10 +3268,7 @@ iwi_rfkill_poll(void *arg)
* it is enabled so we must poll for the latter.
*/
if (!iwi_getrfkill(sc)) {
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
-
- ieee80211_runtask(ic, &sc->sc_radiontask);
+ ieee80211_runtask(&sc->sc_ic, &sc->sc_radiontask);
return;
}
callout_reset(&sc->sc_rftimer, 2*hz, iwi_rfkill_poll, sc);
@@ -3330,7 +3278,7 @@ static void
iwi_radio_off(void *arg, int pending)
{
struct iwi_softc *sc = arg;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
IWI_LOCK_DECL;
device_printf(sc->sc_dev, "radio turned off\n");
@@ -3594,8 +3542,8 @@ iwi_scan_start(struct ieee80211com *ic)
static void
iwi_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct iwi_softc *sc = ifp->if_softc;
+ struct iwi_softc *sc = ic->ic_softc;
+
if (sc->fw_state == IWI_FW_IDLE)
iwi_setcurchan(sc, ic->ic_curchan->ic_ieee);
}
@@ -3604,8 +3552,7 @@ static void
iwi_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
{
struct ieee80211vap *vap = ss->ss_vap;
- struct ifnet *ifp = vap->iv_ic->ic_ifp;
- struct iwi_softc *sc = ifp->if_softc;
+ struct iwi_softc *sc = vap->iv_ic->ic_softc;
IWI_LOCK_DECL;
IWI_LOCK(sc);
@@ -3623,8 +3570,7 @@ iwi_scan_mindwell(struct ieee80211_scan_state *ss)
static void
iwi_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct iwi_softc *sc = ifp->if_softc;
+ struct iwi_softc *sc = ic->ic_softc;
IWI_LOCK_DECL;
IWI_LOCK(sc);
diff --git a/sys/dev/iwi/if_iwivar.h b/sys/dev/iwi/if_iwivar.h
index b38bbd9..47848e1 100644
--- a/sys/dev/iwi/if_iwivar.h
+++ b/sys/dev/iwi/if_iwivar.h
@@ -125,11 +125,13 @@ struct iwi_vap {
#define IWI_VAP(vap) ((struct iwi_vap *)(vap))
struct iwi_softc {
- struct ifnet *sc_ifp;
- void (*sc_node_free)(struct ieee80211_node *);
+ struct mtx sc_mtx;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
device_t sc_dev;
- struct mtx sc_mtx;
+ void (*sc_node_free)(struct ieee80211_node *);
+
uint8_t sc_mcast[IEEE80211_ADDR_LEN];
struct unrhdr *sc_unr;
@@ -193,7 +195,8 @@ struct iwi_softc {
struct task sc_wmetask; /* set wme parameters */
struct task sc_monitortask;
- unsigned int sc_softled : 1, /* enable LED gpio status */
+ unsigned int sc_running : 1, /* initialized */
+ sc_softled : 1, /* enable LED gpio status */
sc_ledstate: 1, /* LED on/off state */
sc_blinking: 1; /* LED blink operation active */
u_int sc_nictype; /* NIC type from EEPROM */
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index 3cd5d7b..cfed420 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -235,10 +235,11 @@ static int iwn_tx_data_raw(struct iwn_softc *, struct mbuf *,
static void iwn_xmit_task(void *arg0, int pending);
static int iwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
-static void iwn_start(struct ifnet *);
-static void iwn_start_locked(struct ifnet *);
+static int iwn_transmit(struct ieee80211com *, struct mbuf *);
+static void iwn_start_locked(struct iwn_softc *);
static void iwn_watchdog(void *);
-static int iwn_ioctl(struct ifnet *, u_long, caddr_t);
+static int iwn_ioctl(struct ieee80211com *, u_long , void *);
+static void iwn_parent(struct ieee80211com *);
static int iwn_cmd(struct iwn_softc *, int, const void *, int, int);
static int iwn4965_add_node(struct iwn_softc *, struct iwn_node_info *,
int);
@@ -336,7 +337,7 @@ static void iwn_radio_on(void *, int);
static void iwn_radio_off(void *, int);
static void iwn_panicked(void *, int);
static void iwn_init_locked(struct iwn_softc *);
-static void iwn_init(void *);
+static void iwn_init(struct iwn_softc *);
static void iwn_stop_locked(struct iwn_softc *);
static void iwn_stop(struct iwn_softc *);
static void iwn_scan_start(struct ieee80211com *);
@@ -406,9 +407,7 @@ iwn_attach(device_t dev)
{
struct iwn_softc *sc = (struct iwn_softc *)device_get_softc(dev);
struct ieee80211com *ic;
- struct ifnet *ifp;
int i, error, rid;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
@@ -464,6 +463,7 @@ iwn_attach(device_t dev)
}
IWN_LOCK_INIT(sc);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
/* Read hardware revision and attach. */
sc->hw_type = (IWN_READ(sc, IWN_HW_REV) >> IWN_HW_REV_TYPE_SHIFT)
@@ -549,14 +549,7 @@ iwn_attach(device_t dev)
/* Clear pending interrupts. */
IWN_WRITE(sc, IWN_INT, 0xffffffff);
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(dev, "can not allocate ifnet structure\n");
- goto fail;
- }
-
- ic = ifp->if_l2com;
- ic->ic_ifp = ifp;
+ ic = &sc->sc_ic;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -581,7 +574,7 @@ iwn_attach(device_t dev)
;
/* Read MAC address, channels, etc from EEPROM. */
- if ((error = iwn_read_eeprom(sc, macaddr)) != 0) {
+ if ((error = iwn_read_eeprom(sc, ic->ic_macaddr)) != 0) {
device_printf(dev, "could not read EEPROM, error %d\n",
error);
goto fail;
@@ -599,7 +592,7 @@ iwn_attach(device_t dev)
if (bootverbose) {
device_printf(dev, "MIMO %dT%dR, %.4s, address %6D\n",
sc->ntxchains, sc->nrxchains, sc->eeprom_domain,
- macaddr, ":");
+ ic->ic_macaddr, ":");
}
if (sc->sc_flags & IWN_FLAG_HAS_11N) {
@@ -640,19 +633,12 @@ iwn_attach(device_t dev)
;
}
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_softc = sc;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = iwn_init;
- ifp->if_ioctl = iwn_ioctl;
- ifp->if_start = iwn_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ieee80211_ifattach(ic, macaddr);
+ ieee80211_ifattach(ic);
ic->ic_vap_create = iwn_vap_create;
+ ic->ic_ioctl = iwn_ioctl;
+ ic->ic_parent = iwn_parent;
ic->ic_vap_delete = iwn_vap_delete;
+ ic->ic_transmit = iwn_transmit;
ic->ic_raw_xmit = iwn_raw_xmit;
ic->ic_node_alloc = iwn_node_alloc;
sc->sc_ampdu_rx_start = ic->ic_ampdu_rx_start;
@@ -1293,10 +1279,9 @@ iwn5000_attach(struct iwn_softc *sc, uint16_t pid)
static void
iwn_radiotap_attach(struct iwn_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
- ieee80211_radiotap_attach(ic,
+ ieee80211_radiotap_attach(&sc->sc_ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
IWN_TX_RADIOTAP_PRESENT,
&sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
@@ -1326,21 +1311,14 @@ iwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
struct iwn_softc *sc = ic->ic_softc;
struct iwn_vap *ivp;
struct ieee80211vap *vap;
- uint8_t mac1[IEEE80211_ADDR_LEN];
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
- IEEE80211_ADDR_COPY(mac1, mac);
-
- ivp = (struct iwn_vap *) malloc(sizeof(struct iwn_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (ivp == NULL)
- return NULL;
+ ivp = malloc(sizeof(struct iwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &ivp->iv_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac1);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
ivp->ctx = IWN_RXON_BSS_CTX;
- IEEE80211_ADDR_COPY(ivp->macaddr, mac1);
vap->iv_bmissthreshold = 10; /* override default */
/* Override with driver methods. */
ivp->iv_newstate = vap->iv_newstate;
@@ -1349,7 +1327,8 @@ iwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
/* Complete setup. */
- ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status);
+ ieee80211_vap_attach(vap, iwn_media_change, ieee80211_media_status,
+ mac);
ic->ic_opmode = opmode;
return vap;
}
@@ -1390,24 +1369,19 @@ static int
iwn_detach(device_t dev)
{
struct iwn_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic;
int qid;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
- if (ifp != NULL) {
- ic = ifp->if_l2com;
-
+ if (sc->sc_ic.ic_softc != NULL) {
/* Free the mbuf queue and node references */
IWN_LOCK(sc);
iwn_xmit_queue_drain(sc);
IWN_UNLOCK(sc);
- ieee80211_draintask(ic, &sc->sc_reinit_task);
- ieee80211_draintask(ic, &sc->sc_radioon_task);
- ieee80211_draintask(ic, &sc->sc_radiooff_task);
-
+ ieee80211_draintask(&sc->sc_ic, &sc->sc_reinit_task);
+ ieee80211_draintask(&sc->sc_ic, &sc->sc_radioon_task);
+ ieee80211_draintask(&sc->sc_ic, &sc->sc_radiooff_task);
iwn_stop(sc);
taskqueue_drain_all(sc->sc_tq);
@@ -1415,9 +1389,11 @@ iwn_detach(device_t dev)
callout_drain(&sc->watchdog_to);
callout_drain(&sc->calib_to);
- ieee80211_ifdetach(ic);
+ ieee80211_ifdetach(&sc->sc_ic);
}
+ mbufq_drain(&sc->sc_snd);
+
/* Uninstall interrupt handler. */
if (sc->irq != NULL) {
bus_teardown_intr(dev, sc->irq, sc->sc_ih);
@@ -1440,9 +1416,6 @@ iwn_detach(device_t dev)
bus_release_resource(dev, SYS_RES_MEMORY,
rman_get_rid(sc->mem), sc->mem);
- if (ifp != NULL)
- if_free(ifp);
-
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n", __func__);
IWN_LOCK_DESTROY(sc);
return 0;
@@ -1461,9 +1434,8 @@ static int
iwn_suspend(device_t dev)
{
struct iwn_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
- ieee80211_suspend_all(ic);
+ ieee80211_suspend_all(&sc->sc_ic);
return 0;
}
@@ -1471,12 +1443,11 @@ static int
iwn_resume(device_t dev)
{
struct iwn_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
/* Clear device-specific "PCI retry timeout" register (41h). */
pci_write_config(dev, 0x41, 0, 1);
- ieee80211_resume_all(ic);
+ ieee80211_resume_all(&sc->sc_ic);
return 0;
}
@@ -2385,8 +2356,7 @@ iwn_eeprom_channel_flags(struct iwn_eeprom_chan *channel)
static void
iwn_read_eeprom_band(struct iwn_softc *sc, int n)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
const struct iwn_chan_band *band = &iwn_bands[n];
struct ieee80211_channel *c;
@@ -2445,8 +2415,7 @@ iwn_read_eeprom_band(struct iwn_softc *sc, int n)
static void
iwn_read_eeprom_ht40(struct iwn_softc *sc, int n)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct iwn_eeprom_chan *channels = sc->eeprom_channels[n];
const struct iwn_chan_band *band = &iwn_bands[n];
struct ieee80211_channel *c, *cent, *extc;
@@ -2514,8 +2483,7 @@ iwn_read_eeprom_ht40(struct iwn_softc *sc, int n)
static void
iwn_read_eeprom_channels(struct iwn_softc *sc, int n, uint32_t addr)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
iwn_read_prom_data(sc, addr, &sc->eeprom_channels[n],
iwn_bands[n].nchan * sizeof (struct iwn_eeprom_chan));
@@ -2583,8 +2551,7 @@ static void
iwn_read_eeprom_enhinfo(struct iwn_softc *sc)
{
struct iwn_eeprom_enhinfo enhinfo[35];
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *c;
uint16_t val, base;
int8_t maxpwr;
@@ -2967,8 +2934,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
struct iwn_rx_data *data)
{
struct iwn_ops *ops = &sc->ops;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct iwn_rx_ring *ring = &sc->rxq;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
@@ -3015,14 +2981,14 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
if ((flags & IWN_RX_NOERROR) != IWN_RX_NOERROR) {
DPRINTF(sc, IWN_DEBUG_RECV, "%s: RX flags error %x\n",
__func__, flags);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return;
}
/* Discard frames that are too short. */
if (len < sizeof (struct ieee80211_frame_ack)) {
DPRINTF(sc, IWN_DEBUG_RECV, "%s: frame too short: %d\n",
__func__, len);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return;
}
@@ -3030,7 +2996,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
if (m1 == NULL) {
DPRINTF(sc, IWN_DEBUG_ANY, "%s: no mbuf to restock ring\n",
__func__);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return;
}
bus_dmamap_unload(ring->data_dmat, data->map);
@@ -3053,7 +3019,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
ring->desc[ring->cur] = htole32(paddr >> 8);
bus_dmamap_sync(ring->data_dmat, ring->desc_dma.map,
BUS_DMASYNC_PREWRITE);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return;
}
@@ -3065,7 +3031,6 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
BUS_DMASYNC_PREWRITE);
/* Finalize mbuf. */
- m->m_pkthdr.rcvif = ifp;
m->m_data = head;
m->m_pkthdr.len = m->m_len = len;
@@ -3159,7 +3124,6 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
struct iwn_rx_data *data)
{
struct iwn_ops *ops = &sc->ops;
- struct ifnet *ifp = sc->sc_ifp;
struct iwn_node *wn;
struct ieee80211_node *ni;
struct iwn_compressed_ba *ba = (struct iwn_compressed_ba *)(desc + 1);
@@ -3240,12 +3204,10 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap;
for (i = 0; bitmap; i++) {
if ((bitmap & 1) == 0) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
tx_err ++;
ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
} else {
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
tx_ok ++;
ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
@@ -3391,8 +3353,7 @@ iwn_rx_statistics(struct iwn_softc *sc, struct iwn_rx_desc *desc,
struct iwn_rx_data *data)
{
struct iwn_ops *ops = &sc->ops;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct iwn_calib_state *calib = &sc->calib;
struct iwn_stats *stats = (struct iwn_stats *)(desc + 1);
@@ -3565,7 +3526,6 @@ static void
iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt,
uint8_t status)
{
- struct ifnet *ifp = sc->sc_ifp;
struct iwn_tx_ring *ring = &sc->txq[desc->qid & 0xf];
struct iwn_tx_data *data = &ring->data[desc->idx];
struct mbuf *m;
@@ -3586,15 +3546,12 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt,
/*
* Update rate control statistics for the node.
*/
- if (status & IWN_TX_FAIL) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if (status & IWN_TX_FAIL)
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
- } else {
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ else
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
- }
/*
* Channels marked for "radar" require traffic to be received
@@ -3620,11 +3577,8 @@ iwn_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc, int ackfailcnt,
sc->sc_tx_timer = 0;
if (--ring->queued < IWN_TX_RING_LOMARK) {
sc->qfullmsk &= ~(1 << ring->qid);
- if (sc->qfullmsk == 0 &&
- (ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- iwn_start_locked(ifp);
- }
+ if (sc->qfullmsk == 0)
+ iwn_start_locked(sc);
}
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
@@ -3669,7 +3623,6 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
int ackfailcnt, void *stat)
{
struct iwn_ops *ops = &sc->ops;
- struct ifnet *ifp = sc->sc_ifp;
struct iwn_tx_ring *ring = &sc->txq[qid];
struct iwn_tx_data *data;
struct mbuf *m;
@@ -3808,11 +3761,8 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
sc->sc_tx_timer = 0;
if (ring->queued < IWN_TX_RING_LOMARK) {
sc->qfullmsk &= ~(1 << ring->qid);
- if (sc->qfullmsk == 0 &&
- (ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- iwn_start_locked(ifp);
- }
+ if (sc->qfullmsk == 0)
+ iwn_start_locked(sc);
}
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
@@ -3826,8 +3776,7 @@ static void
iwn_notif_intr(struct iwn_softc *sc)
{
struct iwn_ops *ops = &sc->ops;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint16_t hw;
@@ -4021,8 +3970,7 @@ iwn_wakeup_intr(struct iwn_softc *sc)
static void
iwn_rftoggle_intr(struct iwn_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp = IWN_READ(sc, IWN_GP_CNTRL);
IWN_LOCK_ASSERT(sc);
@@ -4101,7 +4049,6 @@ static void
iwn_intr(void *arg)
{
struct iwn_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
uint32_t r1, r2, tmp;
IWN_LOCK(sc);
@@ -4194,7 +4141,7 @@ iwn_intr(void *arg)
done:
/* Re-enable interrupts. */
- if (ifp->if_flags & IFF_UP)
+ if (sc->sc_flags & IWN_FLAG_RUNNING)
IWN_WRITE(sc, IWN_INT_MASK, sc->int_mask);
IWN_UNLOCK(sc);
@@ -4678,9 +4625,7 @@ iwn_tx_data_raw(struct iwn_softc *sc, struct mbuf *m,
struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
{
struct iwn_ops *ops = &sc->ops;
-// struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap = ni->ni_vap;
-// struct ieee80211com *ic = ifp->if_l2com;
struct iwn_tx_cmd *cmd;
struct iwn_cmd_data *tx;
struct ieee80211_frame *wh;
@@ -4875,7 +4820,6 @@ static void
iwn_xmit_task(void *arg0, int pending)
{
struct iwn_softc *sc = arg0;
- struct ifnet *ifp = sc->sc_ifp;
struct ieee80211_node *ni;
struct mbuf *m;
int error;
@@ -4907,8 +4851,9 @@ iwn_xmit_task(void *arg0, int pending)
error = iwn_tx_data(sc, m, ni);
if (error != 0) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
}
@@ -4921,13 +4866,12 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct iwn_softc *sc = ifp->if_softc;
+ struct iwn_softc *sc = ic->ic_softc;
int error = 0;
DPRINTF(sc, IWN_DEBUG_XMIT | IWN_DEBUG_TRACE, "->%s begin\n", __func__);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ if ((sc->sc_flags & IWN_FLAG_RUNNING) == 0) {
ieee80211_free_node(ni);
m_freem(m);
return ENETDOWN;
@@ -4942,8 +4886,9 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
if (sc->sc_beacon_wait) {
if (iwn_xmit_queue_enqueue(sc, m) != 0) {
m_freem(m);
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
IWN_UNLOCK(sc);
return (ENOBUFS);
}
@@ -4968,7 +4913,6 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
if (error != 0) {
/* NB: m is reclaimed on tx failure */
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
} else
sc->sc_tx_timer = 5;
@@ -4979,20 +4923,32 @@ iwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return error;
}
-static void
-iwn_start(struct ifnet *ifp)
+static int
+iwn_transmit(struct ieee80211com *ic, struct mbuf *m)
{
- struct iwn_softc *sc = ifp->if_softc;
+ struct iwn_softc *sc;
+ int error;
+
+ sc = ic->ic_softc;
IWN_LOCK(sc);
- iwn_start_locked(ifp);
+ if ((sc->sc_flags & IWN_FLAG_RUNNING) == 0) {
+ IWN_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ IWN_UNLOCK(sc);
+ return (error);
+ }
+ iwn_start_locked(sc);
IWN_UNLOCK(sc);
+ return (0);
}
static void
-iwn_start_locked(struct ifnet *ifp)
+iwn_start_locked(struct iwn_softc *sc)
{
- struct iwn_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
@@ -5007,27 +4963,16 @@ iwn_start_locked(struct ifnet *ifp)
}
DPRINTF(sc, IWN_DEBUG_XMIT, "%s: called\n", __func__);
-
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
- (ifp->if_drv_flags & IFF_DRV_OACTIVE))
- return;
-
- for (;;) {
- if (sc->qfullmsk != 0) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
+ while (sc->qfullmsk == 0 &&
+ (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (iwn_tx_data(sc, m, ni) != 0) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
} else
sc->sc_tx_timer = 5;
}
-
DPRINTF(sc, IWN_DEBUG_XMIT, "%s: done\n", __func__);
}
@@ -5035,12 +4980,11 @@ static void
iwn_watchdog(void *arg)
{
struct iwn_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
IWN_LOCK_ASSERT(sc);
- KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
+ KASSERT(sc->sc_flags & IWN_FLAG_RUNNING, ("not running"));
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
@@ -5055,41 +4999,13 @@ iwn_watchdog(void *arg)
}
static int
-iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+iwn_ioctl(struct ieee80211com *ic, u_long cmd, void *data)
{
- struct iwn_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
- struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0, stop = 0;
-
+ struct ifreq *ifr = data;
+ struct iwn_softc *sc = ic->ic_softc;
+ int error = 0;
+
switch (cmd) {
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- case SIOCSIFFLAGS:
- IWN_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- iwn_init_locked(sc);
- if (IWN_READ(sc, IWN_GP_CNTRL) & IWN_GP_CNTRL_RFKILL)
- startall = 1;
- else
- stop = 1;
- }
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- iwn_stop_locked(sc);
- }
- IWN_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- else if (vap != NULL && stop)
- ieee80211_stop(vap);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
case SIOCGIWNSTATS:
IWN_LOCK(sc);
/* XXX validate permissions/memory/etc? */
@@ -5103,10 +5019,35 @@ iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
IWN_UNLOCK(sc);
break;
default:
- error = EINVAL;
+ error = ENOTTY;
break;
}
- return error;
+ return (error);
+}
+
+static void
+iwn_parent(struct ieee80211com *ic)
+{
+ struct iwn_softc *sc = ic->ic_softc;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ int startall = 0, stop = 0;
+
+ IWN_LOCK(sc);
+ if (ic->ic_nrunning > 0) {
+ if (!(sc->sc_flags & IWN_FLAG_RUNNING)) {
+ iwn_init_locked(sc);
+ if (IWN_READ(sc, IWN_GP_CNTRL) & IWN_GP_CNTRL_RFKILL)
+ startall = 1;
+ else
+ stop = 1;
+ }
+ } else if (sc->sc_flags & IWN_FLAG_RUNNING)
+ iwn_stop_locked(sc);
+ IWN_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
+ else if (vap != NULL && stop)
+ ieee80211_stop(vap);
}
/*
@@ -5340,8 +5281,7 @@ static int
iwn_add_broadcast_node(struct iwn_softc *sc, int async)
{
struct iwn_ops *ops = &sc->ops;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct iwn_node_info node;
struct iwn_cmd_link_quality linkq;
uint8_t txant;
@@ -5352,7 +5292,7 @@ iwn_add_broadcast_node(struct iwn_softc *sc, int async)
sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
memset(&node, 0, sizeof node);
- IEEE80211_ADDR_COPY(node.macaddr, ifp->if_broadcastaddr);
+ IEEE80211_ADDR_COPY(node.macaddr, ieee80211broadcastaddr);
node.id = sc->broadcast_id;
DPRINTF(sc, IWN_DEBUG_RESET, "%s: adding broadcast node\n", __func__);
if ((error = ops->add_node(sc, &node, async)) != 0)
@@ -5501,8 +5441,7 @@ iwn_set_timing(struct iwn_softc *sc, struct ieee80211_node *ni)
static void
iwn4965_power_calibration(struct iwn_softc *sc, int temp)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
@@ -5872,8 +5811,7 @@ iwn_collect_noise(struct iwn_softc *sc,
{
struct iwn_ops *ops = &sc->ops;
struct iwn_calib_state *calib = &sc->calib;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t val;
int i;
@@ -6506,9 +6444,8 @@ iwn5000_runtime_calib(struct iwn_softc *sc)
static uint32_t
iwn_get_rxon_ht_flags(struct iwn_softc *sc, struct ieee80211_channel *c)
{
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t htflags = 0;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
if (! IEEE80211_IS_CHAN_HT(c))
return (0);
@@ -6535,8 +6472,9 @@ static int
iwn_config(struct iwn_softc *sc)
{
struct iwn_ops *ops = &sc->ops;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ const uint8_t *macaddr;
uint32_t txmask;
uint16_t rxchain;
int error;
@@ -6618,8 +6556,9 @@ iwn_config(struct iwn_softc *sc)
/* Set mode, channel, RX filter and enable RX. */
sc->rxon = &sc->rx_on[IWN_RXON_BSS_CTX];
memset(sc->rxon, 0, sizeof (struct iwn_rxon));
- IEEE80211_ADDR_COPY(sc->rxon->myaddr, IF_LLADDR(ifp));
- IEEE80211_ADDR_COPY(sc->rxon->wlap, IF_LLADDR(ifp));
+ macaddr = vap ? vap->iv_myaddr : ic->ic_macaddr;
+ IEEE80211_ADDR_COPY(sc->rxon->myaddr, macaddr);
+ IEEE80211_ADDR_COPY(sc->rxon->wlap, macaddr);
sc->rxon->chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
sc->rxon->flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF);
if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan))
@@ -6732,7 +6671,7 @@ iwn_get_active_dwell_time(struct iwn_softc *sc,
static uint16_t
iwn_limit_dwell(struct iwn_softc *sc, uint16_t dwell_time)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = NULL;
int bintval = 0;
@@ -6780,8 +6719,7 @@ static int
iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap,
struct ieee80211_scan_state *ss, struct ieee80211_channel *c)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni = vap->iv_bss;
struct iwn_scan_hdr *hdr;
struct iwn_cmd_data *tx;
@@ -6919,9 +6857,9 @@ iwn_scan(struct iwn_softc *sc, struct ieee80211vap *vap,
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
IEEE80211_FC0_SUBTYPE_PROBE_REQ;
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
- IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
- IEEE80211_ADDR_COPY(wh->i_addr2, IF_LLADDR(ifp));
- IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr);
+ IEEE80211_ADDR_COPY(wh->i_addr1, vap->iv_ifp->if_broadcastaddr);
+ IEEE80211_ADDR_COPY(wh->i_addr2, IF_LLADDR(vap->iv_ifp));
+ IEEE80211_ADDR_COPY(wh->i_addr3, vap->iv_ifp->if_broadcastaddr);
*(uint16_t *)&wh->i_dur[0] = 0; /* filled by HW */
*(uint16_t *)&wh->i_seq[0] = 0; /* filled by HW */
@@ -7040,8 +6978,7 @@ static int
iwn_auth(struct iwn_softc *sc, struct ieee80211vap *vap)
{
struct iwn_ops *ops = &sc->ops;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni = vap->iv_bss;
int error;
@@ -7113,8 +7050,7 @@ static int
iwn_run(struct iwn_softc *sc, struct ieee80211vap *vap)
{
struct iwn_ops *ops = &sc->ops;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni = vap->iv_bss;
struct iwn_node_info node;
int error;
@@ -8685,8 +8621,7 @@ static void
iwn_radio_on(void *arg0, int pending)
{
struct iwn_softc *sc = arg0;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
@@ -8701,8 +8636,7 @@ static void
iwn_radio_off(void *arg0, int pending)
{
struct iwn_softc *sc = arg0;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
@@ -8722,8 +8656,7 @@ static void
iwn_panicked(void *arg0, int pending)
{
struct iwn_softc *sc = arg0;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
int error;
@@ -8751,7 +8684,7 @@ iwn_panicked(void *arg0, int pending)
}
/* Only run start once the NIC is in a useful state, like associated */
- iwn_start_locked(sc->sc_ifp);
+ iwn_start_locked(sc);
IWN_UNLOCK(sc);
}
@@ -8759,13 +8692,14 @@ iwn_panicked(void *arg0, int pending)
static void
iwn_init_locked(struct iwn_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
int error;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
IWN_LOCK_ASSERT(sc);
+ sc->sc_flags |= IWN_FLAG_RUNNING;
+
if ((error = iwn_hw_prepare(sc)) != 0) {
device_printf(sc->sc_dev, "%s: hardware not ready, error %d\n",
__func__, error);
@@ -8813,38 +8747,33 @@ iwn_init_locked(struct iwn_softc *sc)
goto fail;
}
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
-
callout_reset(&sc->watchdog_to, hz, iwn_watchdog, sc);
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end\n",__func__);
return;
-fail: iwn_stop_locked(sc);
+fail:
+ sc->sc_flags &= ~IWN_FLAG_RUNNING;
+ iwn_stop_locked(sc);
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s: end in error\n",__func__);
}
static void
-iwn_init(void *arg)
+iwn_init(struct iwn_softc *sc)
{
- struct iwn_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
IWN_LOCK(sc);
iwn_init_locked(sc);
IWN_UNLOCK(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ieee80211_start_all(ic);
+ if (sc->sc_flags & IWN_FLAG_RUNNING)
+ ieee80211_start_all(&sc->sc_ic);
}
static void
iwn_stop_locked(struct iwn_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
IWN_LOCK_ASSERT(sc);
@@ -8852,7 +8781,7 @@ iwn_stop_locked(struct iwn_softc *sc)
sc->sc_tx_timer = 0;
callout_stop(&sc->watchdog_to);
callout_stop(&sc->calib_to);
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_flags &= ~IWN_FLAG_RUNNING;
/* Power OFF hardware. */
iwn_hw_stop(sc);
@@ -8872,8 +8801,7 @@ iwn_stop(struct iwn_softc *sc)
static void
iwn_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct iwn_softc *sc = ifp->if_softc;
+ struct iwn_softc *sc = ic->ic_softc;
IWN_LOCK(sc);
/* make the link LED blink while we're scanning */
@@ -8887,8 +8815,7 @@ iwn_scan_start(struct ieee80211com *ic)
static void
iwn_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct iwn_softc *sc = ifp->if_softc;
+ struct iwn_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
IWN_LOCK(sc);
@@ -8906,8 +8833,7 @@ static void
iwn_set_channel(struct ieee80211com *ic)
{
const struct ieee80211_channel *c = ic->ic_curchan;
- struct ifnet *ifp = ic->ic_ifp;
- struct iwn_softc *sc = ifp->if_softc;
+ struct iwn_softc *sc = ic->ic_softc;
int error;
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
@@ -8964,8 +8890,7 @@ static void
iwn_hw_reset(void *arg0, int pending)
{
struct iwn_softc *sc = arg0;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
DPRINTF(sc, IWN_DEBUG_TRACE, "->Doing %s\n", __func__);
diff --git a/sys/dev/iwn/if_iwnvar.h b/sys/dev/iwn/if_iwnvar.h
index 9366fc2..ed275bf 100644
--- a/sys/dev/iwn/if_iwnvar.h
+++ b/sys/dev/iwn/if_iwnvar.h
@@ -228,18 +228,16 @@ struct iwn_vap {
enum ieee80211_state, int);
int ctx;
int beacon_int;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
};
#define IWN_VAP(_vap) ((struct iwn_vap *)(_vap))
struct iwn_softc {
device_t sc_dev;
-
- struct ifnet *sc_ifp;
int sc_debug;
-
struct mtx sc_mtx;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
u_int sc_flags;
#define IWN_FLAG_HAS_OTPROM (1 << 1)
@@ -251,6 +249,7 @@ struct iwn_softc {
#define IWN_FLAG_ADV_BTCOEX (1 << 8)
#define IWN_FLAG_PAN_SUPPORT (1 << 9)
#define IWN_FLAG_BTCOEX (1 << 10)
+#define IWN_FLAG_RUNNING (1 << 11)
uint8_t hw_type;
/* subdevice_id used to adjust configuration */
@@ -320,7 +319,6 @@ struct iwn_softc {
struct iwn_calib_state calib;
int last_calib_ticks;
struct callout watchdog_to;
- struct callout ct_kill_exit_to;
struct iwn_fw_info fw;
struct iwn_calib_info calibcmd[IWN5000_PHY_CALIB_MAX_RESULT];
uint32_t errptr;
diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
index 3787db3..7742eea 100644
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -828,9 +828,9 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
struct ifreq *ifr = (struct ifreq *) data;
#if defined(INET) || defined(INET6)
struct ifaddr *ifa = (struct ifaddr *)data;
- bool avoid_reset = FALSE;
#endif
int error = 0;
+ bool avoid_reset = FALSE;
switch (command) {
@@ -843,7 +843,6 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
if (ifa->ifa_addr->sa_family == AF_INET6)
avoid_reset = TRUE;
#endif
-#if defined(INET) || defined(INET6)
/*
** Calling init results in link renegotiation,
** so we avoid doing it when possible.
@@ -852,11 +851,12 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
ifp->if_flags |= IFF_UP;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
ixgbe_init(adapter);
+#if defined(INET)
if (!(ifp->if_flags & IFF_NOARP))
arp_ifinit(ifp, ifa);
+#endif
} else
error = ether_ioctl(ifp, command, data);
-#endif
break;
case SIOCSIFMTU:
IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
diff --git a/sys/dev/malo/if_malo.c b/sys/dev/malo/if_malo.c
index 7418379..2790fdc 100644
--- a/sys/dev/malo/if_malo.c
+++ b/sys/dev/malo/if_malo.c
@@ -102,13 +102,9 @@ enum {
(IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_BEACON))
#define IFF_DUMPPKTS_RECV(sc, wh) \
(((sc->malo_debug & MALO_DEBUG_RECV) && \
- ((sc->malo_debug & MALO_DEBUG_RECV_ALL) || !IS_BEACON(wh))) || \
- (sc->malo_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == \
- (IFF_DEBUG|IFF_LINK2))
+ ((sc->malo_debug & MALO_DEBUG_RECV_ALL) || !IS_BEACON(wh))))
#define IFF_DUMPPKTS_XMIT(sc) \
- ((sc->malo_debug & MALO_DEBUG_XMIT) || \
- (sc->malo_ifp->if_flags & (IFF_DEBUG | IFF_LINK2)) == \
- (IFF_DEBUG | IFF_LINK2))
+ (sc->malo_debug & MALO_DEBUG_XMIT)
#define DPRINTF(sc, m, fmt, ...) do { \
if (sc->malo_debug & (m)) \
printf(fmt, __VA_ARGS__); \
@@ -130,9 +126,10 @@ static int malo_dma_setup(struct malo_softc *);
static int malo_setup_hwdma(struct malo_softc *);
static void malo_txq_init(struct malo_softc *, struct malo_txq *, int);
static void malo_tx_cleanupq(struct malo_softc *, struct malo_txq *);
-static void malo_start(struct ifnet *);
+static void malo_parent(struct ieee80211com *);
+static int malo_transmit(struct ieee80211com *, struct mbuf *);
+static void malo_start(struct malo_softc *);
static void malo_watchdog(void *);
-static int malo_ioctl(struct ifnet *, u_long, caddr_t);
static void malo_updateslot(struct ieee80211com *);
static int malo_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static void malo_scan_start(struct ieee80211com *);
@@ -143,7 +140,7 @@ static int malo_raw_xmit(struct ieee80211_node *, struct mbuf *,
static void malo_sysctlattach(struct malo_softc *);
static void malo_announce(struct malo_softc *);
static void malo_dma_cleanup(struct malo_softc *);
-static void malo_stop_locked(struct ifnet *, int);
+static void malo_stop(struct malo_softc *);
static int malo_chan_set(struct malo_softc *, struct ieee80211_channel *);
static int malo_mode_init(struct malo_softc *);
static void malo_tx_proc(void *, int);
@@ -173,30 +170,19 @@ malo_bar0_write4(struct malo_softc *sc, bus_size_t off, uint32_t val)
int
malo_attach(uint16_t devid, struct malo_softc *sc)
{
- int error;
- struct ieee80211com *ic;
- struct ifnet *ifp;
+ struct ieee80211com *ic = &sc->malo_ic;
struct malo_hal *mh;
+ int error;
uint8_t bands;
- ifp = sc->malo_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->malo_dev, "can not if_alloc()\n");
- return ENOSPC;
- }
- ic = ifp->if_l2com;
-
MALO_LOCK_INIT(sc);
callout_init_mtx(&sc->malo_watchdog_timer, &sc->malo_mtx, 0);
-
- /* set these up early for if_printf use */
- if_initname(ifp, device_get_name(sc->malo_dev),
- device_get_unit(sc->malo_dev));
+ mbufq_init(&sc->malo_snd, ifqmaxlen);
mh = malo_hal_attach(sc->malo_dev, devid,
sc->malo_io1h, sc->malo_io1t, sc->malo_dmat);
if (mh == NULL) {
- if_printf(ifp, "unable to attach HAL\n");
+ device_printf(sc->malo_dev, "unable to attach HAL\n");
error = EIO;
goto bad;
}
@@ -209,13 +195,13 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
*/
error = malo_hal_fwload(mh, "malo8335-h", "malo8335-m");
if (error != 0) {
- if_printf(ifp, "unable to setup firmware\n");
+ device_printf(sc->malo_dev, "unable to setup firmware\n");
goto bad1;
}
/* XXX gethwspecs() extracts correct informations? not maybe! */
error = malo_hal_gethwspecs(mh, &sc->malo_hwspecs);
if (error != 0) {
- if_printf(ifp, "unable to fetch h/w specs\n");
+ device_printf(sc->malo_dev, "unable to fetch h/w specs\n");
goto bad1;
}
@@ -251,7 +237,8 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
*/
error = malo_dma_setup(sc);
if (error != 0) {
- if_printf(ifp, "failed to setup descriptors: %d\n", error);
+ device_printf(sc->malo_dev,
+ "failed to setup descriptors: %d\n", error);
goto bad1;
}
error = malo_setup_hwdma(sc); /* push to firmware */
@@ -261,21 +248,11 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
sc->malo_tq = taskqueue_create_fast("malo_taskq", M_NOWAIT,
taskqueue_thread_enqueue, &sc->malo_tq);
taskqueue_start_threads(&sc->malo_tq, 1, PI_NET,
- "%s taskq", ifp->if_xname);
+ "%s taskq", device_get_nameunit(sc->malo_dev));
TASK_INIT(&sc->malo_rxtask, 0, malo_rx_proc, sc);
TASK_INIT(&sc->malo_txtask, 0, malo_tx_proc, sc);
- ifp->if_softc = sc;
- ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
- ifp->if_start = malo_start;
- ifp->if_ioctl = malo_ioctl;
- ifp->if_init = malo_init;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(sc->malo_dev);
/* XXX not right but it's not used anywhere important */
@@ -290,6 +267,7 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
| IEEE80211_C_TXPMGT /* capable of txpow mgt */
| IEEE80211_C_WPA /* capable of WPA1+WPA2 */
;
+ IEEE80211_ADDR_COPY(ic->ic_macaddr, sc->malo_hwspecs.macaddr);
/*
* Transmit requires space in the packet for a special format transmit
@@ -301,16 +279,17 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
sizeof(struct ieee80211_frame);
/* call MI attach routine. */
- ieee80211_ifattach(ic, sc->malo_hwspecs.macaddr);
+ ieee80211_ifattach(ic);
/* override default methods */
ic->ic_vap_create = malo_vap_create;
ic->ic_vap_delete = malo_vap_delete;
ic->ic_raw_xmit = malo_raw_xmit;
ic->ic_updateslot = malo_updateslot;
-
ic->ic_scan_start = malo_scan_start;
ic->ic_scan_end = malo_scan_end;
ic->ic_set_channel = malo_set_channel;
+ ic->ic_parent = malo_parent;
+ ic->ic_transmit = malo_transmit;
sc->malo_invalid = 0; /* ready to go, enable int handling */
@@ -335,7 +314,6 @@ bad2:
bad1:
malo_hal_detach(mh);
bad:
- if_free(ifp);
sc->malo_invalid = 1;
return error;
@@ -347,12 +325,12 @@ malo_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = ic->ic_ifp;
+ struct malo_softc *sc = ic->ic_softc;
struct malo_vap *mvp;
struct ieee80211vap *vap;
if (!TAILQ_EMPTY(&ic->ic_vaps)) {
- if_printf(ifp, "multiple vaps not supported\n");
+ device_printf(sc->malo_dev, "multiple vaps not supported\n");
return NULL;
}
switch (opmode) {
@@ -363,18 +341,13 @@ malo_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_MONITOR:
break;
default:
- if_printf(ifp, "%s mode not supported\n",
+ device_printf(sc->malo_dev, "%s mode not supported\n",
ieee80211_opmode_name[opmode]);
return NULL; /* unsupported */
}
- mvp = (struct malo_vap *) malloc(sizeof(struct malo_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (mvp == NULL) {
- if_printf(ifp, "cannot allocate vap state block\n");
- return NULL;
- }
+ mvp = malloc(sizeof(struct malo_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &mvp->malo_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override state transition machine */
mvp->malo_newstate = vap->iv_newstate;
@@ -382,7 +355,7 @@ malo_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap,
- ieee80211_media_change, ieee80211_media_status);
+ ieee80211_media_change, ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return vap;
}
@@ -461,7 +434,6 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
int nbuf, size_t bufsize, int ndesc, size_t descsize)
{
int error;
- struct ifnet *ifp = sc->malo_ifp;
uint8_t *ds;
DPRINTF(sc, MALO_DEBUG_RESET,
@@ -488,7 +460,8 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
NULL, /* lockarg */
&dd->dd_dmat);
if (error != 0) {
- if_printf(ifp, "cannot allocate %s DMA tag\n", dd->dd_name);
+ device_printf(sc->malo_dev, "cannot allocate %s DMA tag\n",
+ dd->dd_name);
return error;
}
@@ -496,7 +469,8 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
error = bus_dmamem_alloc(dd->dd_dmat, (void**) &dd->dd_desc,
BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dd->dd_dmamap);
if (error != 0) {
- if_printf(ifp, "unable to alloc memory for %u %s descriptors, "
+ device_printf(sc->malo_dev,
+ "unable to alloc memory for %u %s descriptors, "
"error %u\n", nbuf * ndesc, dd->dd_name, error);
goto fail1;
}
@@ -505,7 +479,8 @@ malo_desc_setup(struct malo_softc *sc, const char *name,
dd->dd_desc, dd->dd_desc_len,
malo_load_cb, &dd->dd_desc_paddr, BUS_DMA_NOWAIT);
if (error != 0) {
- if_printf(ifp, "unable to map %s descriptors, error %u\n",
+ device_printf(sc->malo_dev,
+ "unable to map %s descriptors, error %u\n",
dd->dd_name, error);
goto fail2;
}
@@ -532,7 +507,6 @@ fail1:
static int
malo_rxdma_setup(struct malo_softc *sc)
{
- struct ifnet *ifp = sc->malo_ifp;
int error, bsize, i;
struct malo_rxbuf *bf;
struct malo_rxdesc *ds;
@@ -549,7 +523,8 @@ malo_rxdma_setup(struct malo_softc *sc)
bsize = malo_rxbuf * sizeof(struct malo_rxbuf);
bf = malloc(bsize, M_MALODEV, M_NOWAIT | M_ZERO);
if (bf == NULL) {
- if_printf(ifp, "malloc of %u rx buffers failed\n", bsize);
+ device_printf(sc->malo_dev,
+ "malloc of %u rx buffers failed\n", bsize);
return error;
}
sc->malo_rxdma.dd_bufptr = bf;
@@ -562,8 +537,9 @@ malo_rxdma_setup(struct malo_softc *sc)
error = bus_dmamap_create(sc->malo_dmat, BUS_DMA_NOWAIT,
&bf->bf_dmamap);
if (error != 0) {
- if_printf(ifp, "%s: unable to dmamap for rx buffer, "
- "error %d\n", __func__, error);
+ device_printf(sc->malo_dev,
+ "%s: unable to dmamap for rx buffer, error %d\n",
+ __func__, error);
return error;
}
/* NB: tail is intentional to preserve descriptor order */
@@ -575,7 +551,6 @@ malo_rxdma_setup(struct malo_softc *sc)
static int
malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq)
{
- struct ifnet *ifp = sc->malo_ifp;
int error, bsize, i;
struct malo_txbuf *bf;
struct malo_txdesc *ds;
@@ -590,7 +565,7 @@ malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq)
bsize = malo_txbuf * sizeof(struct malo_txbuf);
bf = malloc(bsize, M_MALODEV, M_NOWAIT | M_ZERO);
if (bf == NULL) {
- if_printf(ifp, "malloc of %u tx buffers failed\n",
+ device_printf(sc->malo_dev, "malloc of %u tx buffers failed\n",
malo_txbuf);
return ENOMEM;
}
@@ -605,7 +580,8 @@ malo_txdma_setup(struct malo_softc *sc, struct malo_txq *txq)
error = bus_dmamap_create(sc->malo_dmat, BUS_DMA_NOWAIT,
&bf->bf_dmamap);
if (error != 0) {
- if_printf(ifp, "unable to create dmamap for tx "
+ device_printf(sc->malo_dev,
+ "unable to create dmamap for tx "
"buffer %u, error %u\n", i, error);
return error;
}
@@ -1004,33 +980,19 @@ malo_tx_processq(struct malo_softc *sc, struct malo_txq *txq)
if (status & MALO_TXD_STATUS_FAILED_AGING)
sc->malo_stats.mst_tx_aging++;
}
- /*
- * Do any tx complete callback. Note this must
- * be done before releasing the node reference.
- * XXX no way to figure out if frame was ACK'd
- */
- if (bf->bf_m->m_flags & M_TXCB) {
- /* XXX strip fw len in case header inspected */
- m_adj(bf->bf_m, sizeof(uint16_t));
- ieee80211_process_callback(ni, bf->bf_m,
- (status & MALO_TXD_STATUS_OK) == 0);
- }
- /*
- * Reclaim reference to node.
- *
- * NB: the node may be reclaimed here if, for example
- * this is a DEAUTH message that was sent and the
- * node was timed out due to inactivity.
- */
- ieee80211_free_node(ni);
- }
+ /* XXX strip fw len in case header inspected */
+ m_adj(bf->bf_m, sizeof(uint16_t));
+ ieee80211_tx_complete(ni, bf->bf_m,
+ (status & MALO_TXD_STATUS_OK) == 0);
+ } else
+ m_freem(bf->bf_m);
+
ds->status = htole32(MALO_TXD_STATUS_IDLE);
ds->pktlen = htole32(0);
bus_dmamap_sync(sc->malo_dmat, bf->bf_dmamap,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->malo_dmat, bf->bf_dmamap);
- m_freem(bf->bf_m);
bf->bf_m = NULL;
bf->bf_node = NULL;
@@ -1049,23 +1011,23 @@ static void
malo_tx_proc(void *arg, int npending)
{
struct malo_softc *sc = arg;
- struct ifnet *ifp = sc->malo_ifp;
int i, nreaped;
/*
* Process each active queue.
*/
nreaped = 0;
+ MALO_LOCK(sc);
for (i = 0; i < MALO_NUM_TX_QUEUES; i++) {
if (!STAILQ_EMPTY(&sc->malo_txq[i].active))
nreaped += malo_tx_processq(sc, &sc->malo_txq[i]);
}
if (nreaped != 0) {
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
sc->malo_timer = 0;
- malo_start(ifp);
+ malo_start(sc);
}
+ MALO_UNLOCK(sc);
}
static int
@@ -1079,8 +1041,7 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni,
int error, ismcast, iswep;
int copyhdrlen, hdrlen, pktlen;
struct ieee80211_frame *wh;
- struct ifnet *ifp = sc->malo_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->malo_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct malo_txdesc *ds;
struct malo_txrec *tr;
@@ -1225,7 +1186,7 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni,
ds->txpriority = txq->qnum;
break;
default:
- if_printf(ifp, "bogus frame type 0x%x (%s)\n",
+ device_printf(sc->malo_dev, "bogus frame type 0x%x (%s)\n",
wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
/* XXX statistic */
m_freem(m0);
@@ -1246,37 +1207,52 @@ malo_tx_start(struct malo_softc *sc, struct ieee80211_node *ni,
STAILQ_INSERT_TAIL(&txq->active, bf, bf_list);
MALO_TXDESC_SYNC(txq, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
sc->malo_timer = 5;
MALO_TXQ_UNLOCK(txq);
return 0;
#undef IEEE80211_DIR_DSTODS
}
+static int
+malo_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct malo_softc *sc = ic->ic_softc;
+ int error;
+
+ MALO_LOCK(sc);
+ if (!sc->malo_running) {
+ MALO_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->malo_snd, m);
+ if (error) {
+ MALO_UNLOCK(sc);
+ return (error);
+ }
+ malo_start(sc);
+ MALO_UNLOCK(sc);
+ return (0);
+}
+
static void
-malo_start(struct ifnet *ifp)
+malo_start(struct malo_softc *sc)
{
- struct malo_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct malo_txq *txq = &sc->malo_txq[0];
struct malo_txbuf *bf = NULL;
struct mbuf *m;
int nqueued = 0;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->malo_invalid)
+ MALO_LOCK_ASSERT(sc);
+
+ if (!sc->malo_running || sc->malo_invalid)
return;
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
+ while ((m = mbufq_dequeue(&sc->malo_snd)) != NULL) {
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
bf = malo_getbuf(sc, txq);
if (bf == NULL) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
-
- /* XXX blocks other traffic */
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ mbufq_prepend(&sc->malo_snd, m);
sc->malo_stats.mst_tx_qstop++;
break;
}
@@ -1284,7 +1260,8 @@ malo_start(struct ifnet *ifp)
* Pass the frame to the h/w for transmission.
*/
if (malo_tx_start(sc, ni, bf, m)) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
if (bf != NULL) {
bf->bf_m = NULL;
bf->bf_node = NULL;
@@ -1328,21 +1305,18 @@ malo_start(struct ifnet *ifp)
static void
malo_watchdog(void *arg)
{
- struct malo_softc *sc;
- struct ifnet *ifp;
+ struct malo_softc *sc = arg;
- sc = arg;
callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc);
if (sc->malo_timer == 0 || --sc->malo_timer > 0)
return;
- ifp = sc->malo_ifp;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && !sc->malo_invalid) {
- if_printf(ifp, "watchdog timeout\n");
+ if (sc->malo_running && !sc->malo_invalid) {
+ device_printf(sc->malo_dev, "watchdog timeout\n");
/* XXX no way to reset h/w. now */
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->malo_ic.ic_oerrors, 1);
sc->malo_stats.mst_watchdog++;
}
}
@@ -1351,8 +1325,7 @@ static int
malo_hal_reset(struct malo_softc *sc)
{
static int first = 0;
- struct ifnet *ifp = sc->malo_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->malo_ic;
struct malo_hal *mh = sc->malo_mh;
if (first == 0) {
@@ -1392,7 +1365,7 @@ malo_getrxmbuf(struct malo_softc *sc, struct malo_rxbuf *bf)
mtod(m, caddr_t), MJUMPAGESIZE,
malo_load_cb, &paddr, BUS_DMA_NOWAIT);
if (error != 0) {
- if_printf(sc->malo_ifp,
+ device_printf(sc->malo_dev,
"%s: bus_dmamap_load failed, error %d\n", __func__, error);
m_freem(m);
return NULL;
@@ -1483,26 +1456,23 @@ malo_startrecv(struct malo_softc *sc)
static void
malo_init_locked(struct malo_softc *sc)
{
- struct ifnet *ifp = sc->malo_ifp;
struct malo_hal *mh = sc->malo_mh;
int error;
- DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags 0x%x\n",
- __func__, ifp->if_flags);
-
MALO_LOCK_ASSERT(sc);
/*
* Stop anything previously setup. This is safe whether this is
* the first time through or not.
*/
- malo_stop_locked(ifp, 0);
+ malo_stop(sc);
/*
* Push state to the firmware.
*/
if (!malo_hal_reset(sc)) {
- if_printf(ifp, "%s: unable to reset hardware\n", __func__);
+ device_printf(sc->malo_dev,
+ "%s: unable to reset hardware\n", __func__);
return;
}
@@ -1511,7 +1481,8 @@ malo_init_locked(struct malo_softc *sc)
*/
error = malo_startrecv(sc);
if (error != 0) {
- if_printf(ifp, "%s: unable to start recv logic, error %d\n",
+ device_printf(sc->malo_dev,
+ "%s: unable to start recv logic, error %d\n",
__func__, error);
return;
}
@@ -1528,7 +1499,7 @@ malo_init_locked(struct malo_softc *sc)
| MALO_A2HRIC_BIT_RADAR_DETECT
| MALO_A2HRIC_BIT_CHAN_SWITCH;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->malo_running = 1;
malo_hal_intrset(mh, sc->malo_imask);
callout_reset(&sc->malo_watchdog_timer, hz, malo_watchdog, sc);
}
@@ -1537,18 +1508,13 @@ static void
malo_init(void *arg)
{
struct malo_softc *sc = (struct malo_softc *) arg;
- struct ifnet *ifp = sc->malo_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->malo_ic;
- DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags 0x%x\n",
- __func__, ifp->if_flags);
-
MALO_LOCK(sc);
malo_init_locked(sc);
-
MALO_UNLOCK(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->malo_running)
ieee80211_start_all(ic); /* start all vap's */
}
@@ -1558,9 +1524,8 @@ malo_init(void *arg)
static void
malo_setmcastfilter(struct malo_softc *sc)
{
- struct ifnet *ifp = sc->malo_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifmultiaddr *ifma;
+ struct ieee80211com *ic = &sc->malo_ic;
+ struct ieee80211vap *vap;
uint8_t macs[IEEE80211_ADDR_LEN * MALO_HAL_MCAST_MAX];
uint8_t *mp;
int nmc;
@@ -1568,26 +1533,32 @@ malo_setmcastfilter(struct malo_softc *sc)
mp = macs;
nmc = 0;
- if (ic->ic_opmode == IEEE80211_M_MONITOR ||
- (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)))
+ if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 ||
+ ic->ic_promisc > 0)
goto all;
-
- if_maddr_rlock(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (nmc == MALO_HAL_MCAST_MAX) {
- ifp->if_flags |= IFF_ALLMULTI;
- if_maddr_runlock(ifp);
- goto all;
- }
- IEEE80211_ADDR_COPY(mp,
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+
+ ifp = vap->iv_ifp;
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+
+ if (nmc == MALO_HAL_MCAST_MAX) {
+ ifp->if_flags |= IFF_ALLMULTI;
+ if_maddr_runlock(ifp);
+ goto all;
+ }
+ IEEE80211_ADDR_COPY(mp,
+ LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
- mp += IEEE80211_ADDR_LEN, nmc++;
+ mp += IEEE80211_ADDR_LEN, nmc++;
+ }
+ if_maddr_runlock(ifp);
}
- if_maddr_runlock(ifp);
malo_hal_setmcast(sc->malo_mh, nmc, macs);
@@ -1602,8 +1573,7 @@ all:
static int
malo_mode_init(struct malo_softc *sc)
{
- struct ifnet *ifp = sc->malo_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->malo_ic;
struct malo_hal *mh = sc->malo_mh;
/*
@@ -1612,7 +1582,7 @@ malo_mode_init(struct malo_softc *sc)
* identify internal requests (from the bridge)
* versus external requests such as for tcpdump.
*/
- malo_hal_setpromisc(mh, (ifp->if_flags & IFF_PROMISC) &&
+ malo_hal_setpromisc(mh, ic->ic_promisc > 0 &&
ic->ic_opmode != IEEE80211_M_HOSTAP);
malo_setmcastfilter(sc);
@@ -1641,8 +1611,7 @@ malo_tx_draintxq(struct malo_softc *sc, struct malo_txq *txq)
MALO_TXQ_UNLOCK(txq);
#ifdef MALO_DEBUG
if (sc->malo_debug & MALO_DEBUG_RESET) {
- struct ifnet *ifp = sc->malo_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->malo_ic;
const struct malo_txrec *tr =
mtod(bf->bf_m, const struct malo_txrec *);
malo_printtxbuf(bf, txq->qnum, ix);
@@ -1670,18 +1639,17 @@ malo_tx_draintxq(struct malo_softc *sc, struct malo_txq *txq)
}
static void
-malo_stop_locked(struct ifnet *ifp, int disable)
+malo_stop(struct malo_softc *sc)
{
- struct malo_softc *sc = ifp->if_softc;
struct malo_hal *mh = sc->malo_mh;
int i;
- DPRINTF(sc, MALO_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n",
- __func__, sc->malo_invalid, ifp->if_flags);
+ DPRINTF(sc, MALO_DEBUG_ANY, "%s: invalid %u running %u\n",
+ __func__, sc->malo_invalid, sc->malo_running);
MALO_LOCK_ASSERT(sc);
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ if (!sc->malo_running)
return;
/*
@@ -1693,10 +1661,10 @@ malo_stop_locked(struct ifnet *ifp, int disable)
* Note that some of this work is not possible if the hardware
* is gone (invalid).
*/
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ sc->malo_running = 0;
callout_stop(&sc->malo_watchdog_timer);
sc->malo_timer = 0;
- /* diable interrupt. */
+ /* disable interrupt. */
malo_hal_intrset(mh, 0);
/* turn off the radio. */
malo_hal_setradio(mh, 0, MHP_AUTO_PREAMBLE);
@@ -1706,57 +1674,38 @@ malo_stop_locked(struct ifnet *ifp, int disable)
malo_tx_draintxq(sc, &sc->malo_txq[i]);
}
-static int
-malo_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+malo_parent(struct ieee80211com *ic)
{
-#define MALO_IS_RUNNING(ifp) \
- ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
- struct malo_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ struct malo_softc *sc = ic->ic_softc;
+ int startall = 0;
MALO_LOCK(sc);
- switch (cmd) {
- case SIOCSIFFLAGS:
- if (MALO_IS_RUNNING(ifp)) {
- /*
- * To avoid rescanning another access point,
- * do not call malo_init() here. Instead,
- * only reflect promisc mode settings.
- */
- malo_mode_init(sc);
- } else if (ifp->if_flags & IFF_UP) {
- /*
- * Beware of being called during attach/detach
- * to reset promiscuous mode. In that case we
- * will still be marked UP but not RUNNING.
- * However trying to re-init the interface
- * is the wrong thing to do as we've already
- * torn down much of our state. There's
- * probably a better way to deal with this.
- */
- if (!sc->malo_invalid) {
- malo_init_locked(sc);
- startall = 1;
- }
- } else
- malo_stop_locked(ifp, 1);
- break;
- case SIOCGIFMEDIA:
- case SIOCSIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- default:
- error = ether_ioctl(ifp, cmd, data);
- break;
- }
+ if (ic->ic_nrunning > 0) {
+ /*
+ * Beware of being called during attach/detach
+ * to reset promiscuous mode. In that case we
+ * will still be marked UP but not RUNNING.
+ * However trying to re-init the interface
+ * is the wrong thing to do as we've already
+ * torn down much of our state. There's
+ * probably a better way to deal with this.
+ */
+ if (!sc->malo_running && !sc->malo_invalid) {
+ malo_init(sc);
+ startall = 1;
+ }
+ /*
+ * To avoid rescanning another access point,
+ * do not call malo_init() here. Instead,
+ * only reflect promisc mode settings.
+ */
+ malo_mode_init(sc);
+ } else if (sc->malo_running)
+ malo_stop(sc);
MALO_UNLOCK(sc);
-
if (startall)
ieee80211_start_all(ic);
- return error;
-#undef MALO_IS_RUNNING
}
/*
@@ -1773,7 +1722,7 @@ malo_updateslot(struct ieee80211com *ic)
int error;
/* NB: can be called early; suppress needless cmds */
- if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ if (!sc->malo_running)
return;
DPRINTF(sc, MALO_DEBUG_RESET,
@@ -1795,7 +1744,7 @@ static int
malo_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
- struct malo_softc *sc = ic->ic_ifp->if_softc;
+ struct malo_softc *sc = ic->ic_softc;
struct malo_hal *mh = sc->malo_mh;
int error;
@@ -1839,12 +1788,11 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct malo_softc *sc = ifp->if_softc;
+ struct malo_softc *sc = ic->ic_softc;
struct malo_txbuf *bf;
struct malo_txq *txq;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->malo_invalid) {
+ if (!sc->malo_running || sc->malo_invalid) {
ieee80211_free_node(ni);
m_freem(m);
return ENETDOWN;
@@ -1859,8 +1807,6 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
txq = &sc->malo_txq[0];
bf = malo_getbuf(sc, txq);
if (bf == NULL) {
- /* XXX blocks other traffic */
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
ieee80211_free_node(ni);
m_freem(m);
return ENOBUFS;
@@ -1870,7 +1816,6 @@ malo_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
* Pass the frame to the h/w for transmission.
*/
if (malo_tx_start(sc, ni, bf, m) != 0) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
bf->bf_m = NULL;
bf->bf_node = NULL;
MALO_TXQ_LOCK(txq);
@@ -1915,9 +1860,9 @@ malo_sysctlattach(struct malo_softc *sc)
static void
malo_announce(struct malo_softc *sc)
{
- struct ifnet *ifp = sc->malo_ifp;
- if_printf(ifp, "versions [hw %d fw %d.%d.%d.%d] (regioncode %d)\n",
+ device_printf(sc->malo_dev,
+ "versions [hw %d fw %d.%d.%d.%d] (regioncode %d)\n",
sc->malo_hwspecs.hwversion,
(sc->malo_hwspecs.fw_releasenum >> 24) & 0xff,
(sc->malo_hwspecs.fw_releasenum >> 16) & 0xff,
@@ -1926,9 +1871,11 @@ malo_announce(struct malo_softc *sc)
sc->malo_hwspecs.regioncode);
if (bootverbose || malo_rxbuf != MALO_RXBUF)
- if_printf(ifp, "using %u rx buffers\n", malo_rxbuf);
+ device_printf(sc->malo_dev,
+ "using %u rx buffers\n", malo_rxbuf);
if (bootverbose || malo_txbuf != MALO_TXBUF)
- if_printf(ifp, "using %u tx buffers\n", malo_txbuf);
+ device_printf(sc->malo_dev,
+ "using %u tx buffers\n", malo_txbuf);
}
/*
@@ -1989,8 +1936,7 @@ malo_chan_set(struct malo_softc *sc, struct ieee80211_channel *chan)
static void
malo_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct malo_softc *sc = ifp->if_softc;
+ struct malo_softc *sc = ic->ic_softc;
DPRINTF(sc, MALO_DEBUG_STATE, "%s\n", __func__);
}
@@ -1998,8 +1944,7 @@ malo_scan_start(struct ieee80211com *ic)
static void
malo_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct malo_softc *sc = ifp->if_softc;
+ struct malo_softc *sc = ic->ic_softc;
DPRINTF(sc, MALO_DEBUG_STATE, "%s\n", __func__);
}
@@ -2007,8 +1952,7 @@ malo_scan_end(struct ieee80211com *ic)
static void
malo_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct malo_softc *sc = ifp->if_softc;
+ struct malo_softc *sc = ic->ic_softc;
(void) malo_chan_set(sc, ic->ic_curchan);
}
@@ -2020,8 +1964,7 @@ malo_rx_proc(void *arg, int npending)
((((const struct ieee80211_frame *)wh)->i_fc[1] & \
IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
struct malo_softc *sc = arg;
- struct ifnet *ifp = sc->malo_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->malo_ic;
struct malo_rxbuf *bf;
struct malo_rxdesc *ds;
struct mbuf *m, *mnew;
@@ -2078,7 +2021,7 @@ malo_rx_proc(void *arg, int npending)
#endif
status = ds->status;
if (status & MALO_RXD_STATUS_DECRYPT_ERR_MASK) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto rx_next;
}
/*
@@ -2117,7 +2060,7 @@ malo_rx_proc(void *arg, int npending)
/* XXX don't need mbuf, just dma buffer */
mnew = malo_getrxmbuf(sc, bf);
if (mnew == NULL) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto rx_next;
}
/*
@@ -2128,7 +2071,6 @@ malo_rx_proc(void *arg, int npending)
bf->bf_m = mnew;
m->m_data += off - hdrlen;
m->m_pkthdr.len = m->m_len = pktlen;
- m->m_pkthdr.rcvif = ifp;
/*
* Piece 802.11 header together.
@@ -2158,8 +2100,6 @@ malo_rx_proc(void *arg, int npending)
len, ds->rate, rssi);
}
#endif
- if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
-
/* dispatch */
ni = ieee80211_find_rxnode(ic,
(struct ieee80211_frame_min *)wh);
@@ -2177,22 +2117,11 @@ rx_next:
malo_bar0_write4(sc, sc->malo_hwspecs.rxdesc_read, readptr);
sc->malo_rxnext = bf;
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
- !IFQ_IS_EMPTY(&ifp->if_snd))
- malo_start(ifp);
+ if (mbufq_first(&sc->malo_snd) != NULL)
+ malo_start(sc);
#undef IEEE80211_DIR_DSTODS
}
-static void
-malo_stop(struct ifnet *ifp, int disable)
-{
- struct malo_softc *sc = ifp->if_softc;
-
- MALO_LOCK(sc);
- malo_stop_locked(ifp, disable);
- MALO_UNLOCK(sc);
-}
-
/*
* Reclaim all tx queue resources.
*/
@@ -2208,13 +2137,9 @@ malo_tx_cleanup(struct malo_softc *sc)
int
malo_detach(struct malo_softc *sc)
{
- struct ifnet *ifp = sc->malo_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->malo_ic;
- DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n",
- __func__, ifp->if_flags);
-
- malo_stop(ifp, 1);
+ malo_stop(sc);
if (sc->malo_tq != NULL) {
taskqueue_drain(sc->malo_tq, &sc->malo_rxtask);
@@ -2240,8 +2165,7 @@ malo_detach(struct malo_softc *sc)
malo_dma_cleanup(sc);
malo_tx_cleanup(sc);
malo_hal_detach(sc->malo_mh);
- if_free(ifp);
-
+ mbufq_drain(&sc->malo_snd);
MALO_LOCK_DESTROY(sc);
return 0;
@@ -2250,28 +2174,21 @@ malo_detach(struct malo_softc *sc)
void
malo_shutdown(struct malo_softc *sc)
{
- malo_stop(sc->malo_ifp, 1);
+
+ malo_stop(sc);
}
void
malo_suspend(struct malo_softc *sc)
{
- struct ifnet *ifp = sc->malo_ifp;
- DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n",
- __func__, ifp->if_flags);
-
- malo_stop(ifp, 1);
+ malo_stop(sc);
}
void
malo_resume(struct malo_softc *sc)
{
- struct ifnet *ifp = sc->malo_ifp;
-
- DPRINTF(sc, MALO_DEBUG_ANY, "%s: if_flags %x\n",
- __func__, ifp->if_flags);
- if (ifp->if_flags & IFF_UP)
+ if (sc->malo_ic.ic_nrunning > 0)
malo_init(sc);
}
diff --git a/sys/dev/malo/if_malo.h b/sys/dev/malo/if_malo.h
index bac290c..681e750 100644
--- a/sys/dev/malo/if_malo.h
+++ b/sys/dev/malo/if_malo.h
@@ -520,8 +520,9 @@ struct malo_vap {
#define MALO_VAP(vap) ((struct malo_vap *)(vap))
struct malo_softc {
+ struct ieee80211com malo_ic;
+ struct mbufq malo_snd;
device_t malo_dev;
- struct ifnet *malo_ifp; /* interface common */
struct mtx malo_mtx; /* master lock (recursive) */
struct taskqueue *malo_tq; /* private task queue */
@@ -531,9 +532,10 @@ struct malo_softc {
bus_space_handle_t malo_io1h; /* BAR 1 */
bus_space_tag_t malo_io1t;
- unsigned int malo_invalid : 1,/* disable hardware accesses */
- malo_recvsetup : 1, /* recv setup */
- malo_fixedrate: 1; /* use fixed tx rate */
+ unsigned int malo_invalid: 1,/* disable hardware accesses */
+ malo_recvsetup: 1, /* recv setup */
+ malo_fixedrate: 1, /* use fixed tx rate */
+ malo_running: 1;
struct malo_hal *malo_mh; /* h/w access layer */
struct malo_hal_hwspec malo_hwspecs; /* h/w capabilities */
diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c
index 32914a3..373b709 100644
--- a/sys/dev/mii/brgphy.c
+++ b/sys/dev/mii/brgphy.c
@@ -131,6 +131,7 @@ static const struct mii_phydesc brgphys[] = {
MII_PHY_DESC(BROADCOM, BCM5752),
MII_PHY_DESC(BROADCOM, BCM5780),
MII_PHY_DESC(BROADCOM, BCM5708C),
+ MII_PHY_DESC(BROADCOM, BCM5466),
MII_PHY_DESC(BROADCOM2, BCM5482),
MII_PHY_DESC(BROADCOM2, BCM5708S),
MII_PHY_DESC(BROADCOM2, BCM5709C),
diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs
index 2d3a5be..04452f2 100644
--- a/sys/dev/mii/miidevs
+++ b/sys/dev/mii/miidevs
@@ -170,6 +170,7 @@ model BROADCOM BCM54K2 0x002e BCM54K2 1000BASE-T media interface
model BROADCOM BCM5714 0x0034 BCM5714 1000BASE-T media interface
model BROADCOM BCM5780 0x0035 BCM5780 1000BASE-T media interface
model BROADCOM BCM5708C 0x0036 BCM5708C 1000BASE-T media interface
+model BROADCOM BCM5466 0x003b BCM5466 1000BASE-T media interface
model BROADCOM2 BCM5325 0x0003 BCM5325 10/100 5-port PHY switch
model BROADCOM2 BCM5906 0x0004 BCM5906 10/100baseTX media interface
model BROADCOM2 BCM5481 0x000a BCM5481 1000BASE-T media interface
diff --git a/sys/dev/mmc/host/dwmmc.c b/sys/dev/mmc/host/dwmmc.c
index 81e3083..162cd94 100644
--- a/sys/dev/mmc/host/dwmmc.c
+++ b/sys/dev/mmc/host/dwmmc.c
@@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus_subr.h>
#include <machine/bus.h>
-#include <machine/fdt.h>
#include <machine/cpu.h>
#include <machine/intr.h>
@@ -1209,4 +1208,5 @@ static driver_t dwmmc_driver = {
static devclass_t dwmmc_devclass;
DRIVER_MODULE(dwmmc, simplebus, dwmmc_driver, dwmmc_devclass, 0, 0);
+DRIVER_MODULE(dwmmc, ofwbus, dwmmc_driver, dwmmc_devclass, 0, 0);
diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c
index 0997500..be80e46 100644
--- a/sys/dev/mwl/if_mwl.c
+++ b/sys/dev/mwl/if_mwl.c
@@ -91,17 +91,17 @@ static struct ieee80211vap *mwl_vap_create(struct ieee80211com *,
static void mwl_vap_delete(struct ieee80211vap *);
static int mwl_setupdma(struct mwl_softc *);
static int mwl_hal_reset(struct mwl_softc *sc);
-static int mwl_init_locked(struct mwl_softc *);
-static void mwl_init(void *);
-static void mwl_stop_locked(struct ifnet *, int);
+static int mwl_init(struct mwl_softc *);
+static void mwl_parent(struct ieee80211com *);
static int mwl_reset(struct ieee80211vap *, u_long);
-static void mwl_stop(struct ifnet *, int);
-static void mwl_start(struct ifnet *);
+static void mwl_stop(struct mwl_softc *);
+static void mwl_start(struct mwl_softc *);
+static int mwl_transmit(struct ieee80211com *, struct mbuf *);
static int mwl_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int mwl_media_change(struct ifnet *);
static void mwl_watchdog(void *);
-static int mwl_ioctl(struct ifnet *, u_long, caddr_t);
+static int mwl_ioctl(struct ieee80211com *, u_long, void *);
static void mwl_radar_proc(void *, int);
static void mwl_chanswitch_proc(void *, int);
static void mwl_bawatchdog_proc(void *, int);
@@ -229,12 +229,11 @@ enum {
((wh->i_fc[0] & (IEEE80211_FC0_TYPE_MASK|IEEE80211_FC0_SUBTYPE_MASK)) == \
(IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_BEACON))
#define IFF_DUMPPKTS_RECV(sc, wh) \
- (((sc->sc_debug & MWL_DEBUG_RECV) && \
- ((sc->sc_debug & MWL_DEBUG_RECV_ALL) || !IS_BEACON(wh))) || \
- (sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
+ ((sc->sc_debug & MWL_DEBUG_RECV) && \
+ ((sc->sc_debug & MWL_DEBUG_RECV_ALL) || !IS_BEACON(wh)))
#define IFF_DUMPPKTS_XMIT(sc) \
- ((sc->sc_debug & MWL_DEBUG_XMIT) || \
- (sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
+ (sc->sc_debug & MWL_DEBUG_XMIT)
+
#define DPRINTF(sc, m, fmt, ...) do { \
if (sc->sc_debug & (m)) \
printf(fmt, __VA_ARGS__); \
@@ -246,16 +245,10 @@ enum {
static void mwl_printrxbuf(const struct mwl_rxbuf *bf, u_int ix);
static void mwl_printtxbuf(const struct mwl_txbuf *bf, u_int qnum, u_int ix);
#else
-#define IFF_DUMPPKTS_RECV(sc, wh) \
- ((sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
-#define IFF_DUMPPKTS_XMIT(sc) \
- ((sc->sc_ifp->if_flags & (IFF_DEBUG|IFF_LINK2)) == (IFF_DEBUG|IFF_LINK2))
-#define DPRINTF(sc, m, fmt, ...) do { \
- (void) sc; \
-} while (0)
-#define KEYPRINTF(sc, k, mac) do { \
- (void) sc; \
-} while (0)
+#define IFF_DUMPPKTS_RECV(sc, wh) 0
+#define IFF_DUMPPKTS_XMIT(sc) 0
+#define DPRINTF(sc, m, fmt, ...) do { (void )sc; } while (0)
+#define KEYPRINTF(sc, k, mac) do { (void )sc; } while (0)
#endif
static MALLOC_DEFINE(M_MWLDEV, "mwldev", "mwl driver dma buffers");
@@ -293,34 +286,22 @@ WR4(struct mwl_softc *sc, bus_size_t off, uint32_t val)
int
mwl_attach(uint16_t devid, struct mwl_softc *sc)
{
- struct ifnet *ifp;
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
struct mwl_hal *mh;
int error = 0;
DPRINTF(sc, MWL_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "cannot if_alloc()\n");
- return ENOSPC;
- }
- ic = ifp->if_l2com;
-
/*
* Setup the RX free list lock early, so it can be consistently
* removed.
*/
MWL_RXFREE_INIT(sc);
- /* set these up early for if_printf use */
- if_initname(ifp, device_get_name(sc->sc_dev),
- device_get_unit(sc->sc_dev));
-
mh = mwl_hal_attach(sc->sc_dev, devid,
sc->sc_io1h, sc->sc_io1t, sc->sc_dmat);
if (mh == NULL) {
- if_printf(ifp, "unable to attach HAL\n");
+ device_printf(sc->sc_dev, "unable to attach HAL\n");
error = EIO;
goto bad;
}
@@ -331,12 +312,12 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc)
* needed so setting up the wrong mode isn't a big deal.
*/
if (mwl_hal_fwload(mh, NULL) != 0) {
- if_printf(ifp, "unable to setup builtin firmware\n");
+ device_printf(sc->sc_dev, "unable to setup builtin firmware\n");
error = EIO;
goto bad1;
}
if (mwl_hal_gethwspecs(mh, &sc->sc_hwspecs) != 0) {
- if_printf(ifp, "unable to fetch h/w specs\n");
+ device_printf(sc->sc_dev, "unable to fetch h/w specs\n");
error = EIO;
goto bad1;
}
@@ -356,7 +337,8 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc)
*/
error = mwl_dma_setup(sc);
if (error != 0) {
- if_printf(ifp, "failed to setup descriptors: %d\n", error);
+ device_printf(sc->sc_dev, "failed to setup descriptors: %d\n",
+ error);
goto bad1;
}
error = mwl_setupdma(sc); /* push to firmware */
@@ -365,11 +347,12 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc)
callout_init(&sc->sc_timer, 1);
callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
sc->sc_tq = taskqueue_create("mwl_taskq", M_NOWAIT,
taskqueue_thread_enqueue, &sc->sc_tq);
taskqueue_start_threads(&sc->sc_tq, 1, PI_NET,
- "%s taskq", ifp->if_xname);
+ "%s taskq", device_get_nameunit(sc->sc_dev));
TASK_INIT(&sc->sc_rxtask, 0, mwl_rx_proc, sc);
TASK_INIT(&sc->sc_radartask, 0, mwl_radar_proc, sc);
@@ -378,8 +361,9 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc)
/* NB: insure BK queue is the lowest priority h/w queue */
if (!mwl_tx_setup(sc, WME_AC_BK, MWL_WME_AC_BK)) {
- if_printf(ifp, "unable to setup xmit queue for %s traffic!\n",
- ieee80211_wme_acnames[WME_AC_BK]);
+ device_printf(sc->sc_dev,
+ "unable to setup xmit queue for %s traffic!\n",
+ ieee80211_wme_acnames[WME_AC_BK]);
error = EIO;
goto bad2;
}
@@ -403,16 +387,6 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc)
}
TASK_INIT(&sc->sc_txtask, 0, mwl_tx_proc, sc);
- ifp->if_softc = sc;
- ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
- ifp->if_start = mwl_start;
- ifp->if_ioctl = mwl_ioctl;
- ifp->if_init = mwl_init;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(sc->sc_dev);
/* XXX not right but it's not used anywhere important */
@@ -480,8 +454,10 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc)
ic->ic_headroom = sizeof(struct mwltxrec) -
sizeof(struct ieee80211_frame);
+ IEEE80211_ADDR_COPY(ic->ic_macaddr, sc->sc_hwspecs.macAddr);
+
/* call MI attach routine. */
- ieee80211_ifattach(ic, sc->sc_hwspecs.macAddr);
+ ieee80211_ifattach(ic);
ic->ic_setregdomain = mwl_setregdomain;
ic->ic_getradiocaps = mwl_getradiocaps;
/* override default methods */
@@ -491,6 +467,9 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc)
ic->ic_update_mcast = mwl_update_mcast;
ic->ic_update_promisc = mwl_update_promisc;
ic->ic_wme.wme_update = mwl_wme_update;
+ ic->ic_transmit = mwl_transmit;
+ ic->ic_ioctl = mwl_ioctl;
+ ic->ic_parent = mwl_parent;
ic->ic_node_alloc = mwl_node_alloc;
sc->sc_node_cleanup = ic->ic_node_cleanup;
@@ -537,7 +516,6 @@ bad1:
mwl_hal_detach(mh);
bad:
MWL_RXFREE_DESTROY(sc);
- if_free(ifp);
sc->sc_invalid = 1;
return error;
}
@@ -545,13 +523,11 @@ bad:
int
mwl_detach(struct mwl_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
-
- DPRINTF(sc, MWL_DEBUG_ANY, "%s: if_flags %x\n",
- __func__, ifp->if_flags);
+ struct ieee80211com *ic = &sc->sc_ic;
- mwl_stop(ifp, 1);
+ MWL_LOCK(sc);
+ mwl_stop(sc);
+ MWL_UNLOCK(sc);
/*
* NB: the order of these is important:
* o call the 802.11 layer before detaching the hal to
@@ -570,7 +546,7 @@ mwl_detach(struct mwl_softc *sc)
MWL_RXFREE_DESTROY(sc);
mwl_tx_cleanup(sc);
mwl_hal_detach(sc->sc_mh);
- if_free(ifp);
+ mbufq_drain(&sc->sc_snd);
return 0;
}
@@ -601,7 +577,7 @@ assign_address(struct mwl_softc *sc, uint8_t mac[IEEE80211_ADDR_LEN], int clone)
}
static void
-reclaim_address(struct mwl_softc *sc, uint8_t mac[IEEE80211_ADDR_LEN])
+reclaim_address(struct mwl_softc *sc, const uint8_t mac[IEEE80211_ADDR_LEN])
{
int i = mac[0] >> 2;
if (i != 0 || --sc->sc_nbssid0 == 0)
@@ -614,8 +590,7 @@ mwl_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac0[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = ic->ic_ifp;
- struct mwl_softc *sc = ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
struct mwl_hal *mh = sc->sc_mh;
struct ieee80211vap *vap, *apvap;
struct mwl_hal_vap *hvap;
@@ -661,17 +636,7 @@ mwl_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
return NULL;
}
- mvp = (struct mwl_vap *) malloc(sizeof(struct mwl_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (mvp == NULL) {
- if (hvap != NULL) {
- mwl_hal_delvap(hvap);
- if ((flags & IEEE80211_CLONE_MACADDR) == 0)
- reclaim_address(sc, mac);
- }
- /* XXX msg */
- return NULL;
- }
+ mvp = malloc(sizeof(struct mwl_vap), M_80211_VAP, M_WAITOK | M_ZERO);
mvp->mv_hvap = hvap;
if (opmode == IEEE80211_M_WDS) {
/*
@@ -686,9 +651,7 @@ mwl_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
KASSERT(mvp->mv_ap_hvap != NULL, ("no ap vap"));
}
vap = &mvp->mv_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
- if (hvap != NULL)
- IEEE80211_ADDR_COPY(vap->iv_myaddr, mac);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override with driver methods */
mvp->mv_newstate = vap->iv_newstate;
vap->iv_newstate = mwl_newstate;
@@ -713,7 +676,8 @@ mwl_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_4;
/* complete setup */
- ieee80211_vap_attach(vap, mwl_media_change, ieee80211_media_status);
+ ieee80211_vap_attach(vap, mwl_media_change, ieee80211_media_status,
+ mac);
switch (vap->iv_opmode) {
case IEEE80211_M_HOSTAP:
@@ -752,14 +716,13 @@ static void
mwl_vap_delete(struct ieee80211vap *vap)
{
struct mwl_vap *mvp = MWL_VAP(vap);
- struct ifnet *parent = vap->iv_ic->ic_ifp;
- struct mwl_softc *sc = parent->if_softc;
+ struct mwl_softc *sc = vap->iv_ic->ic_softc;
struct mwl_hal *mh = sc->sc_mh;
struct mwl_hal_vap *hvap = mvp->mv_hvap;
enum ieee80211_opmode opmode = vap->iv_opmode;
/* XXX disallow ap vap delete if WDS still present */
- if (parent->if_drv_flags & IFF_DRV_RUNNING) {
+ if (sc->sc_running) {
/* quiesce h/w while we remove the vap */
mwl_hal_intrset(mh, 0); /* disable interrupts */
}
@@ -786,31 +749,31 @@ mwl_vap_delete(struct ieee80211vap *vap)
}
mwl_cleartxq(sc, vap);
free(mvp, M_80211_VAP);
- if (parent->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->sc_running)
mwl_hal_intrset(mh, sc->sc_imask);
}
void
mwl_suspend(struct mwl_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- DPRINTF(sc, MWL_DEBUG_ANY, "%s: if_flags %x\n",
- __func__, ifp->if_flags);
-
- mwl_stop(ifp, 1);
+ MWL_LOCK(sc);
+ mwl_stop(sc);
+ MWL_UNLOCK(sc);
}
void
mwl_resume(struct mwl_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
+ int error = EDOOFUS;
- DPRINTF(sc, MWL_DEBUG_ANY, "%s: if_flags %x\n",
- __func__, ifp->if_flags);
+ MWL_LOCK(sc);
+ if (sc->sc_ic.ic_nrunning > 0)
+ error = mwl_init(sc);
+ MWL_UNLOCK(sc);
- if (ifp->if_flags & IFF_UP)
- mwl_init(sc);
+ if (error == 0)
+ ieee80211_start_all(&sc->sc_ic); /* start all vap's */
}
void
@@ -818,7 +781,9 @@ mwl_shutdown(void *arg)
{
struct mwl_softc *sc = arg;
- mwl_stop(sc->sc_ifp, 1);
+ MWL_LOCK(sc);
+ mwl_stop(sc);
+ MWL_UNLOCK(sc);
}
/*
@@ -884,8 +849,7 @@ static void
mwl_radar_proc(void *arg, int pending)
{
struct mwl_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
DPRINTF(sc, MWL_DEBUG_ANY, "%s: radar detected, pending %u\n",
__func__, pending);
@@ -902,8 +866,7 @@ static void
mwl_chanswitch_proc(void *arg, int pending)
{
struct mwl_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
DPRINTF(sc, MWL_DEBUG_ANY, "%s: channel switch notice, pending %u\n",
__func__, pending);
@@ -1031,8 +994,7 @@ mwl_setupdma(struct mwl_softc *sc)
static int
mwl_setcurchanrates(struct mwl_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
const struct ieee80211_rateset *rs;
MWL_HAL_TXRATE rates;
@@ -1145,8 +1107,7 @@ mwl_map2regioncode(const struct ieee80211_regdomain *rd)
static int
mwl_hal_reset(struct mwl_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct mwl_hal *mh = sc->sc_mh;
mwl_hal_setantenna(mh, WL_ANTENNATYPE_RX, sc->sc_rxantenna);
@@ -1168,28 +1129,24 @@ mwl_hal_reset(struct mwl_softc *sc)
}
static int
-mwl_init_locked(struct mwl_softc *sc)
+mwl_init(struct mwl_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
struct mwl_hal *mh = sc->sc_mh;
int error = 0;
- DPRINTF(sc, MWL_DEBUG_ANY, "%s: if_flags 0x%x\n",
- __func__, ifp->if_flags);
-
MWL_LOCK_ASSERT(sc);
/*
* Stop anything previously setup. This is safe
* whether this is the first time through or not.
*/
- mwl_stop_locked(ifp, 0);
+ mwl_stop(sc);
/*
* Push vap-independent state to the firmware.
*/
if (!mwl_hal_reset(sc)) {
- if_printf(ifp, "unable to reset hardware\n");
+ device_printf(sc->sc_dev, "unable to reset hardware\n");
return EIO;
}
@@ -1198,7 +1155,7 @@ mwl_init_locked(struct mwl_softc *sc)
*/
error = mwl_startrecv(sc);
if (error != 0) {
- if_printf(ifp, "unable to start recv logic\n");
+ device_printf(sc->sc_dev, "unable to start recv logic\n");
return error;
}
@@ -1221,7 +1178,7 @@ mwl_init_locked(struct mwl_softc *sc)
| MACREQ_A2HRIC_BIT_TX_ACK
;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_running = 1;
mwl_hal_intrset(mh, sc->sc_imask);
callout_reset(&sc->sc_watchdog, hz, mwl_watchdog, sc);
@@ -1229,54 +1186,21 @@ mwl_init_locked(struct mwl_softc *sc)
}
static void
-mwl_init(void *arg)
+mwl_stop(struct mwl_softc *sc)
{
- struct mwl_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- int error = 0;
-
- DPRINTF(sc, MWL_DEBUG_ANY, "%s: if_flags 0x%x\n",
- __func__, ifp->if_flags);
-
- MWL_LOCK(sc);
- error = mwl_init_locked(sc);
- MWL_UNLOCK(sc);
-
- if (error == 0)
- ieee80211_start_all(ic); /* start all vap's */
-}
-
-static void
-mwl_stop_locked(struct ifnet *ifp, int disable)
-{
- struct mwl_softc *sc = ifp->if_softc;
-
- DPRINTF(sc, MWL_DEBUG_ANY, "%s: invalid %u if_flags 0x%x\n",
- __func__, sc->sc_invalid, ifp->if_flags);
MWL_LOCK_ASSERT(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if (sc->sc_running) {
/*
* Shutdown the hardware and driver.
*/
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ sc->sc_running = 0;
callout_stop(&sc->sc_watchdog);
sc->sc_tx_timer = 0;
mwl_draintxq(sc);
}
}
-static void
-mwl_stop(struct ifnet *ifp, int disable)
-{
- struct mwl_softc *sc = ifp->if_softc;
-
- MWL_LOCK(sc);
- mwl_stop_locked(ifp, disable);
- MWL_UNLOCK(sc);
-}
-
static int
mwl_reset_vap(struct ieee80211vap *vap, int state)
{
@@ -1319,8 +1243,7 @@ mwl_reset(struct ieee80211vap *vap, u_long cmd)
if (hvap != NULL) { /* WDS, MONITOR, etc. */
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct mwl_softc *sc = ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
struct mwl_hal *mh = sc->sc_mh;
/* XXX handle DWDS sta vap change */
@@ -1386,24 +1309,41 @@ mwl_puttxbuf_tail(struct mwl_txq *txq, struct mwl_txbuf *bf)
MWL_TXQ_UNLOCK(txq);
}
+static int
+mwl_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct mwl_softc *sc = ic->ic_softc;
+ int error;
+
+ MWL_LOCK(sc);
+ if (!sc->sc_running) {
+ MWL_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ MWL_UNLOCK(sc);
+ return (error);
+ }
+ mwl_start(sc);
+ MWL_UNLOCK(sc);
+ return (0);
+}
+
static void
-mwl_start(struct ifnet *ifp)
+mwl_start(struct mwl_softc *sc)
{
- struct mwl_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mwl_txbuf *bf;
struct mbuf *m;
struct mwl_txq *txq = NULL; /* XXX silence gcc */
int nqueued;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid)
+ MWL_LOCK_ASSERT(sc);
+ if (!sc->sc_running || sc->sc_invalid)
return;
nqueued = 0;
- for (;;) {
- bf = NULL;
- IFQ_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
/*
* Grab the node for the destination.
*/
@@ -1421,8 +1361,6 @@ mwl_start(struct ifnet *ifp)
ieee80211_free_node(ni);
#ifdef MWL_TX_NODROP
sc->sc_stats.mst_tx_qstop++;
- /* XXX blocks other traffic */
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
#else
DPRINTF(sc, MWL_DEBUG_XMIT,
@@ -1436,7 +1374,8 @@ mwl_start(struct ifnet *ifp)
* Pass the frame to the h/w for transmission.
*/
if (mwl_tx_start(sc, ni, bf, m)) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
mwl_puttxbuf_head(txq, bf);
ieee80211_free_node(ni);
continue;
@@ -1474,12 +1413,11 @@ mwl_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct mwl_softc *sc = ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
struct mwl_txbuf *bf;
struct mwl_txq *txq;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid) {
+ if (!sc->sc_running || sc->sc_invalid) {
ieee80211_free_node(ni);
m_freem(m);
return ENETDOWN;
@@ -1496,8 +1434,6 @@ mwl_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
bf = mwl_gettxbuf(sc, txq);
if (bf == NULL) {
sc->sc_stats.mst_tx_qstop++;
- /* XXX blocks other traffic */
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
ieee80211_free_node(ni);
m_freem(m);
return ENOBUFS;
@@ -1506,7 +1442,6 @@ mwl_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
* Pass the frame to the h/w for transmission.
*/
if (mwl_tx_start(sc, ni, bf, m)) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
mwl_puttxbuf_head(txq, bf);
ieee80211_free_node(ni);
@@ -1581,7 +1516,7 @@ static int
mwl_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
{
- struct mwl_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = vap->iv_ic->ic_softc;
if (k->wk_keyix != IEEE80211_KEYIX_NONE ||
(k->wk_flags & IEEE80211_KEY_GROUP)) {
@@ -1609,7 +1544,7 @@ mwl_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
static int
mwl_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
{
- struct mwl_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = vap->iv_ic->ic_softc;
struct mwl_hal_vap *hvap = MWL_VAP(vap)->mv_hvap;
MWL_HAL_KEYVAL hk;
const uint8_t bcastaddr[IEEE80211_ADDR_LEN] =
@@ -1676,7 +1611,7 @@ mwl_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
#define IEEE80211_IS_STATICKEY(k) \
(((k)->wk_flags & (GRPXMIT|IEEE80211_KEY_RECV)) == \
(GRPXMIT|IEEE80211_KEY_RECV))
- struct mwl_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = vap->iv_ic->ic_softc;
struct mwl_hal_vap *hvap = MWL_VAP(vap)->mv_hvap;
const struct ieee80211_cipher *cip = k->wk_cipher;
const uint8_t *macaddr;
@@ -1791,7 +1726,6 @@ mwl_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
static void
mwl_setmcastfilter(struct mwl_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
#if 0
struct ether_multi *enm;
struct ether_multistep estep;
@@ -1815,17 +1749,13 @@ mwl_setmcastfilter(struct mwl_softc *sc)
}
ifp->if_flags &= ~IFF_ALLMULTI;
mwl_hal_setmcast(sc->sc_mh, nmc, macs);
-#else
- /* XXX no mcast filter support; we get everything */
- ifp->if_flags |= IFF_ALLMULTI;
#endif
}
static int
mwl_mode_init(struct mwl_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct mwl_hal *mh = sc->sc_mh;
/*
@@ -1834,7 +1764,7 @@ mwl_mode_init(struct mwl_softc *sc)
* identify internal requests (from the bridge)
* versus external requests such as for tcpdump.
*/
- mwl_hal_setpromisc(mh, (ifp->if_flags & IFF_PROMISC) &&
+ mwl_hal_setpromisc(mh, ic->ic_promisc > 0 &&
ic->ic_opmode != IEEE80211_M_HOSTAP);
mwl_setmcastfilter(sc);
@@ -1864,8 +1794,7 @@ mwl_update_promisc(struct ieee80211com *ic)
{
struct mwl_softc *sc = ic->ic_softc;
- mwl_hal_setpromisc(sc->sc_mh,
- (ic->ic_ifp->if_flags & IFF_PROMISC) != 0);
+ mwl_hal_setpromisc(sc->sc_mh, ic->ic_promisc > 0);
}
/*
@@ -1882,7 +1811,7 @@ mwl_updateslot(struct ieee80211com *ic)
int prot;
/* NB: can be called early; suppress needless cmds */
- if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ if (!sc->sc_running)
return;
/*
@@ -2004,7 +1933,6 @@ mwl_desc_setup(struct mwl_softc *sc, const char *name,
struct mwl_descdma *dd,
int nbuf, size_t bufsize, int ndesc, size_t descsize)
{
- struct ifnet *ifp = sc->sc_ifp;
uint8_t *ds;
int error;
@@ -2032,7 +1960,7 @@ mwl_desc_setup(struct mwl_softc *sc, const char *name,
NULL, /* lockarg */
&dd->dd_dmat);
if (error != 0) {
- if_printf(ifp, "cannot allocate %s DMA tag\n", dd->dd_name);
+ device_printf(sc->sc_dev, "cannot allocate %s DMA tag\n", dd->dd_name);
return error;
}
@@ -2041,7 +1969,7 @@ mwl_desc_setup(struct mwl_softc *sc, const char *name,
BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
&dd->dd_dmamap);
if (error != 0) {
- if_printf(ifp, "unable to alloc memory for %u %s descriptors, "
+ device_printf(sc->sc_dev, "unable to alloc memory for %u %s descriptors, "
"error %u\n", nbuf * ndesc, dd->dd_name, error);
goto fail1;
}
@@ -2051,7 +1979,7 @@ mwl_desc_setup(struct mwl_softc *sc, const char *name,
mwl_load_cb, &dd->dd_desc_paddr,
BUS_DMA_NOWAIT);
if (error != 0) {
- if_printf(ifp, "unable to map %s descriptors, error %u\n",
+ device_printf(sc->sc_dev, "unable to map %s descriptors, error %u\n",
dd->dd_name, error);
goto fail2;
}
@@ -2109,7 +2037,6 @@ mwl_txq_reset(struct mwl_softc *sc, struct mwl_txq *txq)
static int
mwl_txdma_setup(struct mwl_softc *sc, struct mwl_txq *txq)
{
- struct ifnet *ifp = sc->sc_ifp;
int error, bsize, i;
struct mwl_txbuf *bf;
struct mwl_txdesc *ds;
@@ -2124,7 +2051,7 @@ mwl_txdma_setup(struct mwl_softc *sc, struct mwl_txq *txq)
bsize = mwl_txbuf * sizeof(struct mwl_txbuf);
bf = malloc(bsize, M_MWLDEV, M_NOWAIT | M_ZERO);
if (bf == NULL) {
- if_printf(ifp, "malloc of %u tx buffers failed\n",
+ device_printf(sc->sc_dev, "malloc of %u tx buffers failed\n",
mwl_txbuf);
return ENOMEM;
}
@@ -2137,7 +2064,7 @@ mwl_txdma_setup(struct mwl_softc *sc, struct mwl_txq *txq)
error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT,
&bf->bf_dmamap);
if (error != 0) {
- if_printf(ifp, "unable to create dmamap for tx "
+ device_printf(sc->sc_dev, "unable to create dmamap for tx "
"buffer %u, error %u\n", i, error);
return error;
}
@@ -2172,7 +2099,6 @@ mwl_txdma_cleanup(struct mwl_softc *sc, struct mwl_txq *txq)
static int
mwl_rxdma_setup(struct mwl_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
int error, jumbosize, bsize, i;
struct mwl_rxbuf *bf;
struct mwl_jumbo *rbuf;
@@ -2196,7 +2122,7 @@ mwl_rxdma_setup(struct mwl_softc *sc)
* us while frames are processed.
*/
if (mwl_rxbuf < 2*mwl_rxdesc) {
- if_printf(ifp,
+ device_printf(sc->sc_dev,
"too few rx dma buffers (%d); increasing to %d\n",
mwl_rxbuf, 2*mwl_rxdesc);
mwl_rxbuf = 2*mwl_rxdesc;
@@ -2217,7 +2143,7 @@ mwl_rxdma_setup(struct mwl_softc *sc)
NULL, /* lockarg */
&sc->sc_rxdmat);
if (error != 0) {
- if_printf(ifp, "could not create rx DMA tag\n");
+ device_printf(sc->sc_dev, "could not create rx DMA tag\n");
return error;
}
@@ -2225,7 +2151,7 @@ mwl_rxdma_setup(struct mwl_softc *sc)
BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
&sc->sc_rxmap);
if (error != 0) {
- if_printf(ifp, "could not alloc %ju bytes of rx DMA memory\n",
+ device_printf(sc->sc_dev, "could not alloc %ju bytes of rx DMA memory\n",
(uintmax_t) sc->sc_rxmemsize);
return error;
}
@@ -2235,7 +2161,7 @@ mwl_rxdma_setup(struct mwl_softc *sc)
mwl_load_cb, &sc->sc_rxmem_paddr,
BUS_DMA_NOWAIT);
if (error != 0) {
- if_printf(ifp, "could not load rx DMA map\n");
+ device_printf(sc->sc_dev, "could not load rx DMA map\n");
return error;
}
@@ -2245,7 +2171,7 @@ mwl_rxdma_setup(struct mwl_softc *sc)
bsize = mwl_rxdesc * sizeof(struct mwl_rxbuf);
bf = malloc(bsize, M_MWLDEV, M_NOWAIT | M_ZERO);
if (bf == NULL) {
- if_printf(ifp, "malloc of %u rx buffers failed\n", bsize);
+ device_printf(sc->sc_dev, "malloc of %u rx buffers failed\n", bsize);
return error;
}
sc->sc_rxdma.dd_bufptr = bf;
@@ -2329,7 +2255,7 @@ static struct ieee80211_node *
mwl_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ieee80211com *ic = vap->iv_ic;
- struct mwl_softc *sc = ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
const size_t space = sizeof(struct mwl_node);
struct mwl_node *mn;
@@ -2346,7 +2272,7 @@ static void
mwl_node_cleanup(struct ieee80211_node *ni)
{
struct ieee80211com *ic = ni->ni_ic;
- struct mwl_softc *sc = ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
struct mwl_node *mn = MWL_NODE(ni);
DPRINTF(sc, MWL_DEBUG_NODE, "%s: ni %p ic %p staid %d\n",
@@ -2441,7 +2367,7 @@ static void
mwl_node_drain(struct ieee80211_node *ni)
{
struct ieee80211com *ic = ni->ni_ic;
- struct mwl_softc *sc = ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
struct mwl_node *mn = MWL_NODE(ni);
DPRINTF(sc, MWL_DEBUG_NODE, "%s: ni %p vap %p staid %d\n",
@@ -2696,8 +2622,7 @@ mwl_rx_proc(void *arg, int npending)
#define IEEE80211_DIR_DSTODS(wh) \
((((const struct ieee80211_frame *)wh)->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
struct mwl_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct mwl_rxbuf *bf;
struct mwl_rxdesc *ds;
struct mbuf *m;
@@ -2744,7 +2669,7 @@ mwl_rx_proc(void *arg, int npending)
#endif
status = ds->Status;
if (status & EAGLE_RXD_STATUS_DECRYPT_ERR_MASK) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
sc->sc_stats.mst_rx_crypto++;
/*
* NB: Check EAGLE_RXD_STATUS_GENERAL_DECRYPT_ERR
@@ -2840,7 +2765,6 @@ mwl_rx_proc(void *arg, int npending)
data, sc, 0, EXT_NET_DRV);
m->m_data += off - hdrlen;
m->m_pkthdr.len = m->m_len = pktlen;
- m->m_pkthdr.rcvif = ifp;
/* NB: dma buffer assumed read-only */
/*
@@ -2890,8 +2814,6 @@ mwl_rx_proc(void *arg, int npending)
ieee80211_dump_pkt(ic, mtod(m, caddr_t),
len, ds->Rate, rssi);
}
- if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
-
/* dispatch */
ni = ieee80211_find_rxnode(ic,
(const struct ieee80211_frame_min *) wh);
@@ -2918,11 +2840,10 @@ rx_next:
rx_stop:
sc->sc_rxnext = bf;
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
- !IFQ_IS_EMPTY(&ifp->if_snd)) {
+ if (mbufq_first(&sc->sc_snd) != NULL) {
/* NB: kick fw; the tx thread may have been preempted */
mwl_hal_txstart(sc->sc_mh, 0);
- mwl_start(ifp);
+ mwl_start(sc);
}
#undef IEEE80211_DIR_DSTODS
}
@@ -2987,8 +2908,7 @@ static int
mwl_txq_update(struct mwl_softc *sc, int ac)
{
#define MWL_EXPONENT_TO_VALUE(v) ((1<<v)-1)
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct mwl_txq *txq = sc->sc_ac2q[ac];
struct wmeParams *wmep = &ic->ic_wme.wme_chanParams.cap_wmeParams[ac];
struct mwl_hal *mh = sc->sc_mh;
@@ -3016,7 +2936,7 @@ mwl_txq_update(struct mwl_softc *sc, int ac)
static int
mwl_wme_update(struct ieee80211com *ic)
{
- struct mwl_softc *sc = ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
return !mwl_txq_update(sc, WME_AC_BE) ||
!mwl_txq_update(sc, WME_AC_BK) ||
@@ -3173,8 +3093,7 @@ mwl_tx_start(struct mwl_softc *sc, struct ieee80211_node *ni, struct mwl_txbuf *
{
#define IEEE80211_DIR_DSTODS(wh) \
((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS)
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
int error, iswep, ismcast;
int hdrlen, copyhdrlen, pktlen;
@@ -3391,7 +3310,7 @@ mwl_tx_start(struct mwl_softc *sc, struct ieee80211_node *ni, struct mwl_txbuf *
ds->TxPriority = txq->qnum;
break;
default:
- if_printf(ifp, "bogus frame type 0x%x (%s)\n",
+ device_printf(sc->sc_dev, "bogus frame type 0x%x (%s)\n",
wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
sc->sc_stats.mst_tx_badframetype++;
m_freem(m0);
@@ -3408,7 +3327,6 @@ mwl_tx_start(struct mwl_softc *sc, struct ieee80211_node *ni, struct mwl_txbuf *
STAILQ_INSERT_TAIL(&txq->active, bf, bf_list);
MWL_TXDESC_SYNC(txq, ds, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
sc->sc_tx_timer = 5;
MWL_TXQ_UNLOCK(txq);
@@ -3434,8 +3352,7 @@ mwl_tx_processq(struct mwl_softc *sc, struct mwl_txq *txq)
{
#define EAGLE_TXD_STATUS_MCAST \
(EAGLE_TXD_STATUS_MULTICAST_TX | EAGLE_TXD_STATUS_BROADCAST_TX)
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct mwl_txbuf *bf;
struct mwl_txdesc *ds;
struct ieee80211_node *ni;
@@ -3497,32 +3414,18 @@ mwl_tx_processq(struct mwl_softc *sc, struct mwl_txq *txq)
if (bf->bf_m->m_flags & M_FF)
sc->sc_stats.mst_ff_txerr++;
}
- /*
- * Do any tx complete callback. Note this must
- * be done before releasing the node reference.
- * XXX no way to figure out if frame was ACK'd
- */
- if (bf->bf_m->m_flags & M_TXCB) {
+ if (bf->bf_m->m_flags & M_TXCB)
/* XXX strip fw len in case header inspected */
m_adj(bf->bf_m, sizeof(uint16_t));
- ieee80211_process_callback(ni, bf->bf_m,
- (status & EAGLE_TXD_STATUS_OK) == 0);
- }
- /*
- * Reclaim reference to node.
- *
- * NB: the node may be reclaimed here if, for example
- * this is a DEAUTH message that was sent and the
- * node was timed out due to inactivity.
- */
- ieee80211_free_node(ni);
- }
+ ieee80211_tx_complete(ni, bf->bf_m,
+ (status & EAGLE_TXD_STATUS_OK) == 0);
+ } else
+ m_freem(bf->bf_m);
ds->Status = htole32(EAGLE_TXD_STATUS_IDLE);
bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
- m_freem(bf->bf_m);
mwl_puttxbuf_tail(txq, bf);
}
@@ -3538,7 +3441,6 @@ static void
mwl_tx_proc(void *arg, int npending)
{
struct mwl_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
int nreaped;
/*
@@ -3555,12 +3457,11 @@ mwl_tx_proc(void *arg, int npending)
nreaped += mwl_tx_processq(sc, &sc->sc_txq[3]);
if (nreaped != 0) {
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
sc->sc_tx_timer = 0;
- if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
+ if (mbufq_first(&sc->sc_snd) != NULL) {
/* NB: kick fw; the tx thread may have been preempted */
mwl_hal_txstart(sc->sc_mh, 0);
- mwl_start(ifp);
+ mwl_start(sc);
}
}
}
@@ -3587,8 +3488,7 @@ mwl_tx_draintxq(struct mwl_softc *sc, struct mwl_txq *txq)
MWL_TXQ_UNLOCK(txq);
#ifdef MWL_DEBUG
if (sc->sc_debug & MWL_DEBUG_RESET) {
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
const struct mwltxrec *tr =
mtod(bf->bf_m, const struct mwltxrec *);
mwl_printtxbuf(bf, txq->qnum, ix);
@@ -3616,12 +3516,10 @@ mwl_tx_draintxq(struct mwl_softc *sc, struct mwl_txq *txq)
static void
mwl_draintxq(struct mwl_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
int i;
for (i = 0; i < MWL_NUM_TX_QUEUES; i++)
mwl_tx_draintxq(sc, &sc->sc_txq[i]);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
sc->sc_tx_timer = 0;
}
@@ -3671,7 +3569,7 @@ static int
mwl_recv_action(struct ieee80211_node *ni, const struct ieee80211_frame *wh,
const uint8_t *frm, const uint8_t *efrm)
{
- struct mwl_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = ni->ni_ic->ic_softc;
const struct ieee80211_action *ia;
ia = (const struct ieee80211_action *) frm;
@@ -3692,7 +3590,7 @@ static int
mwl_addba_request(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
int dialogtoken, int baparamset, int batimeout)
{
- struct mwl_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = ni->ni_ic->ic_softc;
struct ieee80211vap *vap = ni->ni_vap;
struct mwl_node *mn = MWL_NODE(ni);
struct mwl_bastate *bas;
@@ -3764,7 +3662,7 @@ static int
mwl_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
int code, int baparamset, int batimeout)
{
- struct mwl_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = ni->ni_ic->ic_softc;
struct mwl_bastate *bas;
bas = tap->txa_private;
@@ -3830,7 +3728,7 @@ mwl_addba_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
static void
mwl_addba_stop(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
{
- struct mwl_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = ni->ni_ic->ic_softc;
struct mwl_bastate *bas;
bas = tap->txa_private;
@@ -3923,8 +3821,7 @@ static int
mwl_chan_set(struct mwl_softc *sc, struct ieee80211_channel *chan)
{
struct mwl_hal *mh = sc->sc_mh;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
MWL_HAL_CHANNEL hchan;
int maxtxpow;
@@ -3980,8 +3877,7 @@ mwl_chan_set(struct mwl_softc *sc, struct ieee80211_channel *chan)
static void
mwl_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct mwl_softc *sc = ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
DPRINTF(sc, MWL_DEBUG_STATE, "%s\n", __func__);
}
@@ -3989,8 +3885,7 @@ mwl_scan_start(struct ieee80211com *ic)
static void
mwl_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct mwl_softc *sc = ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
DPRINTF(sc, MWL_DEBUG_STATE, "%s\n", __func__);
}
@@ -3998,8 +3893,7 @@ mwl_scan_end(struct ieee80211com *ic)
static void
mwl_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct mwl_softc *sc = ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
(void) mwl_chan_set(sc, ic->ic_curchan);
}
@@ -4014,7 +3908,7 @@ static void
mwl_startcsa(struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
- struct mwl_softc *sc = ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
MWL_HAL_CHANNEL hchan;
if (sc->sc_csapending)
@@ -4215,8 +4109,7 @@ mwl_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
struct mwl_hal_vap *hvap = mvp->mv_hvap;
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_node *ni = NULL;
- struct ifnet *ifp = ic->ic_ifp;
- struct mwl_softc *sc = ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
struct mwl_hal *mh = sc->sc_mh;
enum ieee80211_state ostate = vap->iv_state;
int error;
@@ -4398,7 +4291,7 @@ static void
mwl_newassoc(struct ieee80211_node *ni, int isnew)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct mwl_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = vap->iv_ic->ic_softc;
struct mwl_node *mn = MWL_NODE(ni);
MWL_HAL_PEERINFO pi;
uint16_t aid;
@@ -4454,7 +4347,7 @@ static int
mwl_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd,
int nchan, struct ieee80211_channel chans[])
{
- struct mwl_softc *sc = ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
struct mwl_hal *mh = sc->sc_mh;
const MWL_HAL_CHANNELINFO *ci;
int i;
@@ -4472,7 +4365,7 @@ mwl_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd,
IEEE80211_IS_CHAN_HT40(c) ?
MWL_CH_40_MHz_WIDTH : MWL_CH_20_MHz_WIDTH, &ci);
} else {
- if_printf(ic->ic_ifp,
+ device_printf(sc->sc_dev,
"%s: channel %u freq %u/0x%x not 2.4/5GHz\n",
__func__, c->ic_ieee, c->ic_freq, c->ic_flags);
return EINVAL;
@@ -4498,7 +4391,7 @@ mwl_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd,
goto next;
}
}
- if_printf(ic->ic_ifp,
+ device_printf(sc->sc_dev,
"%s: no cal data for channel %u ext %u freq %u/0x%x\n",
__func__, c->ic_ieee, c->ic_extieee,
c->ic_freq, c->ic_flags);
@@ -4654,7 +4547,7 @@ static void
mwl_getradiocaps(struct ieee80211com *ic,
int maxchans, int *nchans, struct ieee80211_channel chans[])
{
- struct mwl_softc *sc = ic->ic_ifp->if_softc;
+ struct mwl_softc *sc = ic->ic_softc;
getchannels(sc, maxchans, nchans, chans);
}
@@ -4662,8 +4555,7 @@ mwl_getradiocaps(struct ieee80211com *ic,
static int
mwl_getchannels(struct mwl_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
/*
* Use the channel info from the hal to craft the
@@ -4768,25 +4660,24 @@ mwl_txq_dump(struct mwl_txq *txq)
static void
mwl_watchdog(void *arg)
{
- struct mwl_softc *sc;
- struct ifnet *ifp;
+ struct mwl_softc *sc = arg;
- sc = arg;
callout_reset(&sc->sc_watchdog, hz, mwl_watchdog, sc);
if (sc->sc_tx_timer == 0 || --sc->sc_tx_timer > 0)
return;
- ifp = sc->sc_ifp;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && !sc->sc_invalid) {
+ if (sc->sc_running && !sc->sc_invalid) {
if (mwl_hal_setkeepalive(sc->sc_mh))
- if_printf(ifp, "transmit timeout (firmware hung?)\n");
+ device_printf(sc->sc_dev,
+ "transmit timeout (firmware hung?)\n");
else
- if_printf(ifp, "transmit timeout\n");
+ device_printf(sc->sc_dev,
+ "transmit timeout\n");
#if 0
- mwl_reset(ifp);
+ mwl_reset(sc);
mwl_txq_dump(&sc->sc_txq[0]);/*XXX*/
#endif
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
sc->sc_stats.mst_watchdog++;
}
}
@@ -4885,28 +4776,22 @@ mwl_ioctl_reset(struct mwl_softc *sc, struct mwl_diag *md)
}
#endif /* MWL_DIAGAPI */
-static int
-mwl_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+mwl_parent(struct ieee80211com *ic)
{
-#define IS_RUNNING(ifp) \
- ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
- struct mwl_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *)data;
- int error = 0, startall;
+ struct mwl_softc *sc = ic->ic_softc;
+ int startall = 0;
- switch (cmd) {
- case SIOCSIFFLAGS:
- MWL_LOCK(sc);
- startall = 0;
- if (IS_RUNNING(ifp)) {
+ MWL_LOCK(sc);
+ if (ic->ic_nrunning > 0) {
+ if (sc->sc_running) {
/*
* To avoid rescanning another access point,
* do not call mwl_init() here. Instead,
* only reflect promisc mode settings.
*/
mwl_mode_init(sc);
- } else if (ifp->if_flags & IFF_UP) {
+ } else {
/*
* Beware of being called during attach/detach
* to reset promiscuous mode. In that case we
@@ -4917,30 +4802,42 @@ mwl_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
* probably a better way to deal with this.
*/
if (!sc->sc_invalid) {
- mwl_init_locked(sc); /* XXX lose error */
+ mwl_init(sc); /* XXX lose error */
startall = 1;
}
- } else
- mwl_stop_locked(ifp, 1);
- MWL_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
+ }
+ } else
+ mwl_stop(sc);
+ MWL_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
+}
+
+static int
+mwl_ioctl(struct ieee80211com *ic, u_long cmd, void *data)
+{
+ struct mwl_softc *sc = ic->ic_softc;
+ struct ifreq *ifr = data;
+ int error = 0;
+
+ switch (cmd) {
case SIOCGMVSTATS:
mwl_hal_gethwstats(sc->sc_mh, &sc->sc_stats.hw_stats);
+#if 0
/* NB: embed these numbers to get a consistent view */
sc->sc_stats.mst_tx_packets =
ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS);
sc->sc_stats.mst_rx_packets =
ifp->if_get_counter(ifp, IFCOUNTER_IPACKETS);
+#endif
/*
* NB: Drop the softc lock in case of a page fault;
* we'll accept any potential inconsisentcy in the
* statistics. The alternative is to copy the data
* to a local structure.
*/
- return copyout(&sc->sc_stats,
- ifr->ifr_data, sizeof (sc->sc_stats));
+ return (copyout(&sc->sc_stats,
+ ifr->ifr_data, sizeof (sc->sc_stats)));
#ifdef MWL_DIAGAPI
case SIOCGMVDIAG:
/* XXX check privs */
@@ -4952,18 +4849,11 @@ mwl_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
MWL_UNLOCK(sc);
break;
#endif /* MWL_DIAGAPI */
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
default:
- error = EINVAL;
+ error = ENOTTY;
break;
}
- return error;
-#undef IS_RUNNING
+ return (error);
}
#ifdef MWL_DEBUG
@@ -5003,9 +4893,8 @@ mwl_sysctlattach(struct mwl_softc *sc)
static void
mwl_announce(struct mwl_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- if_printf(ifp, "Rev A%d hardware, v%d.%d.%d.%d firmware (regioncode %d)\n",
+ device_printf(sc->sc_dev, "Rev A%d hardware, v%d.%d.%d.%d firmware (regioncode %d)\n",
sc->sc_hwspecs.hwVersion,
(sc->sc_hwspecs.fwReleaseNumber>>24) & 0xff,
(sc->sc_hwspecs.fwReleaseNumber>>16) & 0xff,
@@ -5018,20 +4907,20 @@ mwl_announce(struct mwl_softc *sc)
int i;
for (i = 0; i <= WME_AC_VO; i++) {
struct mwl_txq *txq = sc->sc_ac2q[i];
- if_printf(ifp, "Use hw queue %u for %s traffic\n",
+ device_printf(sc->sc_dev, "Use hw queue %u for %s traffic\n",
txq->qnum, ieee80211_wme_acnames[i]);
}
}
if (bootverbose || mwl_rxdesc != MWL_RXDESC)
- if_printf(ifp, "using %u rx descriptors\n", mwl_rxdesc);
+ device_printf(sc->sc_dev, "using %u rx descriptors\n", mwl_rxdesc);
if (bootverbose || mwl_rxbuf != MWL_RXBUF)
- if_printf(ifp, "using %u rx buffers\n", mwl_rxbuf);
+ device_printf(sc->sc_dev, "using %u rx buffers\n", mwl_rxbuf);
if (bootverbose || mwl_txbuf != MWL_TXBUF)
- if_printf(ifp, "using %u tx buffers\n", mwl_txbuf);
+ device_printf(sc->sc_dev, "using %u tx buffers\n", mwl_txbuf);
if (bootverbose && mwl_hal_ismbsscapable(sc->sc_mh))
- if_printf(ifp, "multi-bss support\n");
+ device_printf(sc->sc_dev, "multi-bss support\n");
#ifdef MWL_TX_NODROP
if (bootverbose)
- if_printf(ifp, "no tx drop\n");
+ device_printf(sc->sc_dev, "no tx drop\n");
#endif
}
diff --git a/sys/dev/mwl/if_mwl_pci.c b/sys/dev/mwl/if_mwl_pci.c
index ef7009c..d9da128 100644
--- a/sys/dev/mwl/if_mwl_pci.c
+++ b/sys/dev/mwl/if_mwl_pci.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
+#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/errno.h>
diff --git a/sys/dev/mwl/if_mwlvar.h b/sys/dev/mwl/if_mwlvar.h
index 7071ba0..4a4b338 100644
--- a/sys/dev/mwl/if_mwlvar.h
+++ b/sys/dev/mwl/if_mwlvar.h
@@ -244,7 +244,8 @@ struct mwl_vap {
#define MWL_VAP_CONST(vap) ((const struct mwl_vap *)(vap))
struct mwl_softc {
- struct ifnet *sc_ifp; /* interface common */
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
struct mwl_stats sc_stats; /* interface statistics */
int sc_debug;
device_t sc_dev;
@@ -257,7 +258,8 @@ struct mwl_softc {
struct taskqueue *sc_tq; /* private task queue */
struct callout sc_watchdog;
int sc_tx_timer;
- unsigned int sc_invalid : 1, /* disable hardware accesses */
+ unsigned int sc_running : 1,
+ sc_invalid : 1, /* disable hardware accesses */
sc_recvsetup:1, /* recv setup */
sc_csapending:1,/* 11h channel switch pending */
sc_radarena : 1,/* radar detection enabled */
diff --git a/sys/dev/nand/nfc_rb.c b/sys/dev/nand/nfc_rb.c
index 20a4026..38b2844 100644
--- a/sys/dev/nand/nfc_rb.c
+++ b/sys/dev/nand/nfc_rb.c
@@ -31,16 +31,11 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/proc.h>
#include <sys/bus.h>
-#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/time.h>
#include <machine/bus.h>
diff --git a/sys/dev/nvme/nvme.c b/sys/dev/nvme/nvme.c
index 329c5e5..cc14d34 100644
--- a/sys/dev/nvme/nvme.c
+++ b/sys/dev/nvme/nvme.c
@@ -390,6 +390,15 @@ nvme_notify_fail_consumers(struct nvme_controller *ctrlr)
struct nvme_consumer *cons;
uint32_t i;
+ /*
+ * This controller failed during initialization (i.e. IDENTIFY
+ * command failed or timed out). Do not notify any nvme
+ * consumers of the failure here, since the consumer does not
+ * even know about the controller yet.
+ */
+ if (!ctrlr->is_initialized)
+ return;
+
for (i = 0; i < NVME_MAX_CONSUMERS; i++) {
cons = &nvme_consumer[i];
if (cons->id != INVALID_CONSUMER_ID && cons->fail_fn != NULL)
diff --git a/sys/dev/ofw/ofw_cpu.c b/sys/dev/ofw/ofw_cpu.c
index 59e49ee..4b89b53 100644
--- a/sys/dev/ofw/ofw_cpu.c
+++ b/sys/dev/ofw/ofw_cpu.c
@@ -281,11 +281,13 @@ ofw_cpu_early_foreach(ofw_cpu_foreach_cb callback, boolean_t only_runnable)
phandle_t node, child;
pcell_t addr_cells, reg[2];
char status[16];
- u_int id;
+ char device_type[16];
+ u_int id, next_id;
int count, rv;
count = 0;
id = 0;
+ next_id = 0;
node = OF_finddevice("/cpus");
if (node == -1)
@@ -296,7 +298,21 @@ ofw_cpu_early_foreach(ofw_cpu_foreach_cb callback, boolean_t only_runnable)
sizeof(addr_cells)) < 0)
return (-1);
- for (child = OF_child(node); child != 0; child = OF_peer(child), id++) {
+ for (child = OF_child(node); child != 0; child = OF_peer(child),
+ id = next_id) {
+
+ /* Check if child is a CPU */
+ memset(device_type, 0, sizeof(device_type));
+ rv = OF_getprop(child, "device_type", device_type,
+ sizeof(device_type) - 1);
+ if (rv < 0)
+ continue;
+ if (strcmp(device_type, "cpu") != 0)
+ continue;
+
+ /* We're processing CPU, update next_id used in the next iteration */
+ next_id++;
+
/*
* If we are filtering by runnable then limit to only
* those that have been enabled.
diff --git a/sys/dev/pms/freebsd/driver/common/lxutil.c b/sys/dev/pms/freebsd/driver/common/lxutil.c
index 4cc16c1..365ba5a 100644
--- a/sys/dev/pms/freebsd/driver/common/lxutil.c
+++ b/sys/dev/pms/freebsd/driver/common/lxutil.c
@@ -19,6 +19,7 @@
*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
******************************************************************************/
+/* $FreeBSD$ */
/******************************************************************************
This program is part of PMC-Sierra initiator/target device driver.
The functions here are commonly used by different type of drivers that support
@@ -756,37 +757,30 @@ STATIC int agtiapi_ProbeCard( device_t dev,
int thisCard )
{
int idx;
- static U32 cardMap[4] = { 0, 0, 0, 0 };
+ u_int16_t agtiapi_vendor; // PCI vendor ID
u_int16_t agtiapi_dev; // PCI device ID
AGTIAPI_PRINTK("agtiapi_ProbeCard: start\n");
- if ( ! atomic_cmpset_32( &cardMap[thisCard], 0, 5 ) ) { // card already ran
- AGTIAPI_PRINTK( "We'll only ID this card once -- %d\n", thisCard );
- return 2; // error return value; card already ran this function
- }
- else {
- agtiapi_dev = pci_get_device( dev ); // get PCI device ID
- for( idx = 0; idx < COUNT(ag_card_type); idx++ )
- {
- if( ag_card_type[idx].deviceId == agtiapi_dev )
- { // device ID match
- memset( (void *)&agCardInfoList[ thisCard ], 0,
- sizeof(ag_card_info_t) );
- thisCardInst->cardIdIndex = idx;
- thisCardInst->pPCIDev = dev;
- thisCardInst->cardNameIndex = ag_card_type[idx].cardNameIndex;
- thisCardInst->cardID =
- pci_read_config( dev, ag_card_type[idx].membar, 4 ); // memAddr
- AGTIAPI_PRINTK("agtiapi_ProbeCard: We've got PMC SAS, probe successful %p / %p\n",
- thisCardInst->pPCIDev, thisCardInst );
- device_printf( dev,
- "agtiapi PCI Probe Vendor ID : 0x%x Device ID : 0x%x\n",
- pci_get_vendor(dev), agtiapi_dev );
- device_set_desc( dev, ag_card_names[ag_card_type[idx].cardNameIndex] );
- return 0;
- }
+ agtiapi_vendor = pci_get_vendor( dev ); // get PCI vendor ID
+ agtiapi_dev = pci_get_device( dev ); // get PCI device ID
+ for( idx = 0; idx < COUNT(ag_card_type); idx++ )
+ {
+ if ( ag_card_type[idx].deviceId == agtiapi_dev &&
+ ag_card_type[idx].vendorId == agtiapi_vendor)
+ { // device ID match
+ memset( (void *)&agCardInfoList[ thisCard ], 0,
+ sizeof(ag_card_info_t) );
+ thisCardInst->cardIdIndex = idx;
+ thisCardInst->pPCIDev = dev;
+ thisCardInst->cardNameIndex = ag_card_type[idx].cardNameIndex;
+ thisCardInst->cardID =
+ pci_read_config( dev, ag_card_type[idx].membar, 4 ); // memAddr
+ AGTIAPI_PRINTK("agtiapi_ProbeCard: We've got PMC SAS, probe successful %p / %p\n",
+ thisCardInst->pPCIDev, thisCardInst );
+ device_set_desc( dev, ag_card_names[ag_card_type[idx].cardNameIndex] );
+ return 0;
}
}
- return 7;
+ return 1;
}
diff --git a/sys/dev/pms/freebsd/driver/ini/src/agtiapi.c b/sys/dev/pms/freebsd/driver/ini/src/agtiapi.c
index 47922db..0a500cb 100644
--- a/sys/dev/pms/freebsd/driver/ini/src/agtiapi.c
+++ b/sys/dev/pms/freebsd/driver/ini/src/agtiapi.c
@@ -214,7 +214,6 @@ STATIC void agtiapi_CheckIOTimeout(void *data);
-static unsigned char cardMap[AGTIAPI_MAX_CARDS] = { 0, 0, 0, 0 };
static ag_card_info_t agCardInfoList[ AGTIAPI_MAX_CARDS ]; // card info list
static void agtiapi_cam_action( struct cam_sim *, union ccb * );
static void agtiapi_cam_poll( struct cam_sim * );
@@ -695,37 +694,20 @@ Note:
static int agtiapi_probe( device_t dev )
{
int retVal;
-
- if ( pci_get_vendor(dev) == PCI_VENDOR_ID_PMC_SIERRA ||
- pci_get_vendor(dev) == PCI_VENDOR_ID_HIALEAH )
+ int thisCard;
+ ag_card_info_t *thisCardInst;
+
+ thisCard = device_get_unit( dev );
+ if ( thisCard >= AGTIAPI_MAX_CARDS )
{
- int thisCard = device_get_unit( dev );
-// AGTIAPI_PRINTK("agtiapi_probe: thisCard %d\n", thisCard);
- if( thisCard >= AGTIAPI_MAX_CARDS)
- {
- device_printf( dev, "Too many PMC-Sierra cards detected ERROR!\n" );
- return (ENXIO); // maybe change to different return value?
- }
- ag_card_info_t *thisCardInst = &agCardInfoList[ thisCard ];
- retVal = agtiapi_ProbeCard( dev, thisCardInst, thisCard );
- if ( retVal ) {
- // error on probe
- if( retVal == 2 ) return 0; // another thread ran probe on this card
- device_printf( dev,
- "agtiapi_probe: PCI DEVICE NOT SUPPORTED by this driver!!"
- "Vendor ID : 0x%x Device ID : 0x%x\n",
- pci_get_vendor(dev), pci_get_device( dev ) );
- return (ENXIO); // maybe change to different return value?
- }
- else {
- // AGTIAPI_PRINTK( "agtiapi_ProbeCard: returned with pointer values "
- // "%p / %p\n",
- // thisCardInst->pPCIDev, thisCardInst );
- cardMap[thisCard] = 11; // record this card is present
- return( BUS_PROBE_DEFAULT ); // successful probe
- }
+ device_printf( dev, "Too many PMC-Sierra cards detected ERROR!\n" );
+ return (ENXIO); // maybe change to different return value?
}
- return (ENXIO);
+ thisCardInst = &agCardInfoList[ thisCard ];
+ retVal = agtiapi_ProbeCard( dev, thisCardInst, thisCard );
+ if ( retVal )
+ return (ENXIO); // maybe change to different return value?
+ return( BUS_PROBE_DEFAULT ); // successful probe
}
diff --git a/sys/dev/proto/proto_busdma.c b/sys/dev/proto/proto_busdma.c
index 52f1146..6f6bf7b 100644
--- a/sys/dev/proto/proto_busdma.c
+++ b/sys/dev/proto/proto_busdma.c
@@ -325,7 +325,12 @@ static int
proto_busdma_sync(struct proto_busdma *busdma, struct proto_md *md,
struct proto_ioc_busdma *ioc)
{
-
+ u_int ops;
+
+ ops = BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE |
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE;
+ if (ioc->u.sync.op & ~ops)
+ return (EINVAL);
if (!md->physaddr)
return (ENXIO);
bus_dmamap_sync(md->bd_tag, md->bd_map, ioc->u.sync.op);
diff --git a/sys/dev/ral/if_ral_pci.c b/sys/dev/ral/if_ral_pci.c
index 519b4ca..42ec034 100644
--- a/sys/dev/ral/if_ral_pci.c
+++ b/sys/dev/ral/if_ral_pci.c
@@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
+#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/rman.h>
diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c
index 29ce8cb..ea9c416 100644
--- a/sys/dev/ral/rt2560.c
+++ b/sys/dev/ral/rt2560.c
@@ -127,10 +127,10 @@ static int rt2560_tx_mgt(struct rt2560_softc *, struct mbuf *,
struct ieee80211_node *);
static int rt2560_tx_data(struct rt2560_softc *, struct mbuf *,
struct ieee80211_node *);
-static void rt2560_start_locked(struct ifnet *);
-static void rt2560_start(struct ifnet *);
+static int rt2560_transmit(struct ieee80211com *, struct mbuf *);
+static void rt2560_start(struct rt2560_softc *);
static void rt2560_watchdog(void *);
-static int rt2560_ioctl(struct ifnet *, u_long, caddr_t);
+static void rt2560_parent(struct ieee80211com *);
static void rt2560_bbp_write(struct rt2560_softc *, uint8_t,
uint8_t);
static uint8_t rt2560_bbp_read(struct rt2560_softc *, uint8_t);
@@ -149,7 +149,8 @@ static void rt2560_set_basicrates(struct rt2560_softc *,
const struct ieee80211_rateset *);
static void rt2560_update_led(struct rt2560_softc *, int, int);
static void rt2560_set_bssid(struct rt2560_softc *, const uint8_t *);
-static void rt2560_set_macaddr(struct rt2560_softc *, uint8_t *);
+static void rt2560_set_macaddr(struct rt2560_softc *,
+ const uint8_t *);
static void rt2560_get_macaddr(struct rt2560_softc *, uint8_t *);
static void rt2560_update_promisc(struct ieee80211com *);
static const char *rt2560_get_rf(int);
@@ -197,11 +198,9 @@ int
rt2560_attach(device_t dev, int id)
{
struct rt2560_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic;
- struct ifnet *ifp;
- int error;
+ struct ieee80211com *ic = &sc->sc_ic;
uint8_t bands;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
+ int error;
sc->sc_dev = dev;
@@ -209,6 +208,7 @@ rt2560_attach(device_t dev, int id)
MTX_DEF | MTX_RECURSE);
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
/* retrieve RT2560 rev. no */
sc->asic_rev = RAL_READ(sc, RT2560_CSR0);
@@ -252,27 +252,9 @@ rt2560_attach(device_t dev, int id)
goto fail5;
}
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "can not if_alloc()\n");
- goto fail6;
- }
- ic = ifp->if_l2com;
-
/* retrieve MAC address */
- rt2560_get_macaddr(sc, macaddr);
-
- ifp->if_softc = sc;
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = rt2560_init;
- ifp->if_ioctl = rt2560_ioctl;
- ifp->if_start = rt2560_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
+ rt2560_get_macaddr(sc, ic->ic_macaddr);
+
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_opmode = IEEE80211_M_STA;
@@ -303,7 +285,7 @@ rt2560_attach(device_t dev, int id)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, macaddr);
+ ieee80211_ifattach(ic);
ic->ic_raw_xmit = rt2560_raw_xmit;
ic->ic_updateslot = rt2560_update_slot;
ic->ic_update_promisc = rt2560_update_promisc;
@@ -313,6 +295,8 @@ rt2560_attach(device_t dev, int id)
ic->ic_vap_create = rt2560_vap_create;
ic->ic_vap_delete = rt2560_vap_delete;
+ ic->ic_parent = rt2560_parent;
+ ic->ic_transmit = rt2560_transmit;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -341,7 +325,6 @@ rt2560_attach(device_t dev, int id)
return 0;
-fail6: rt2560_free_rx_ring(sc, &sc->rxq);
fail5: rt2560_free_tx_ring(sc, &sc->bcnq);
fail4: rt2560_free_tx_ring(sc, &sc->prioq);
fail3: rt2560_free_tx_ring(sc, &sc->atimq);
@@ -355,12 +338,12 @@ int
rt2560_detach(void *xsc)
{
struct rt2560_softc *sc = xsc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
rt2560_stop(sc);
ieee80211_ifdetach(ic);
+ mbufq_drain(&sc->sc_snd);
rt2560_free_tx_ring(sc, &sc->txq);
rt2560_free_tx_ring(sc, &sc->atimq);
@@ -368,8 +351,6 @@ rt2560_detach(void *xsc)
rt2560_free_tx_ring(sc, &sc->bcnq);
rt2560_free_rx_ring(sc, &sc->rxq);
- if_free(ifp);
-
mtx_destroy(&sc->sc_mtx);
return 0;
@@ -381,7 +362,7 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = ic->ic_ifp;
+ struct rt2560_softc *sc = ic->ic_softc;
struct rt2560_vap *rvp;
struct ieee80211vap *vap;
@@ -394,7 +375,7 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_MBSS:
/* XXXRP: TBD */
if (!TAILQ_EMPTY(&ic->ic_vaps)) {
- if_printf(ifp, "only 1 vap supported\n");
+ device_printf(sc->sc_dev, "only 1 vap supported\n");
return NULL;
}
if (opmode == IEEE80211_M_STA)
@@ -403,7 +384,8 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_WDS:
if (TAILQ_EMPTY(&ic->ic_vaps) ||
ic->ic_opmode != IEEE80211_M_HOSTAP) {
- if_printf(ifp, "wds only supported in ap mode\n");
+ device_printf(sc->sc_dev,
+ "wds only supported in ap mode\n");
return NULL;
}
/*
@@ -414,15 +396,12 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
flags &= ~IEEE80211_CLONE_BSSID;
break;
default:
- if_printf(ifp, "unknown opmode %d\n", opmode);
+ device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
return NULL;
}
- rvp = (struct rt2560_vap *) malloc(sizeof(struct rt2560_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (rvp == NULL)
- return NULL;
+ rvp = malloc(sizeof(struct rt2560_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &rvp->ral_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override state transition machine */
rvp->ral_newstate = vap->iv_newstate;
@@ -431,7 +410,8 @@ rt2560_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
/* complete setup */
- ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
+ ieee80211_vap_attach(vap, ieee80211_media_change,
+ ieee80211_media_status, mac);
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
ic->ic_opmode = opmode;
return vap;
@@ -451,9 +431,8 @@ void
rt2560_resume(void *xsc)
{
struct rt2560_softc *sc = xsc;
- struct ifnet *ifp = sc->sc_ifp;
- if (ifp->if_flags & IFF_UP)
+ if (sc->sc_ic.ic_nrunning > 0)
rt2560_init(sc);
}
@@ -763,8 +742,7 @@ static int
rt2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct rt2560_vap *rvp = RT2560_VAP(vap);
- struct ifnet *ifp = vap->iv_ic->ic_ifp;
- struct rt2560_softc *sc = ifp->if_softc;
+ struct rt2560_softc *sc = vap->iv_ic->ic_softc;
int error;
if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) {
@@ -792,7 +770,8 @@ rt2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
vap->iv_opmode == IEEE80211_M_MBSS) {
m = ieee80211_beacon_alloc(ni, &rvp->ral_bo);
if (m == NULL) {
- if_printf(ifp, "could not allocate beacon\n");
+ device_printf(sc->sc_dev,
+ "could not allocate beacon\n");
return ENOBUFS;
}
ieee80211_ref_node(ni);
@@ -926,14 +905,13 @@ rt2560_encryption_intr(struct rt2560_softc *sc)
static void
rt2560_tx_intr(struct rt2560_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
struct rt2560_tx_desc *desc;
struct rt2560_tx_data *data;
struct mbuf *m;
- uint32_t flags;
- int retrycnt;
struct ieee80211vap *vap;
struct ieee80211_node *ni;
+ uint32_t flags;
+ int retrycnt, status;
bus_dmamap_sync(sc->txq.desc_dmat, sc->txq.desc_map,
BUS_DMASYNC_POSTREAD);
@@ -961,7 +939,7 @@ rt2560_tx_intr(struct rt2560_softc *sc)
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS,
&retrycnt, NULL);
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ status = 0;
break;
case RT2560_TX_SUCCESS_RETRY:
@@ -973,7 +951,7 @@ rt2560_tx_intr(struct rt2560_softc *sc)
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS,
&retrycnt, NULL);
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ status = 0;
break;
case RT2560_TX_FAIL_RETRY:
@@ -985,7 +963,7 @@ rt2560_tx_intr(struct rt2560_softc *sc)
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_FAILURE,
&retrycnt, NULL);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ status = 1;
break;
case RT2560_TX_FAIL_INVALID:
@@ -993,16 +971,16 @@ rt2560_tx_intr(struct rt2560_softc *sc)
default:
device_printf(sc->sc_dev, "sending data frame failed "
"0x%08x\n", flags);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ status = 1;
}
bus_dmamap_sync(sc->txq.data_dmat, data->map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->txq.data_dmat, data->map);
- m_freem(m);
- data->m = NULL;
- ieee80211_free_node(data->ni);
+
+ ieee80211_tx_complete(ni, m, status);
data->ni = NULL;
+ data->m = NULL;
/* descriptor is no longer valid */
desc->flags &= ~htole32(RT2560_TX_VALID);
@@ -1019,19 +997,13 @@ rt2560_tx_intr(struct rt2560_softc *sc)
if (sc->prioq.queued == 0 && sc->txq.queued == 0)
sc->sc_tx_timer = 0;
- if (sc->txq.queued < RT2560_TX_RING_COUNT - 1) {
- sc->sc_flags &= ~RT2560_F_DATA_OACTIVE;
- if ((sc->sc_flags &
- (RT2560_F_DATA_OACTIVE | RT2560_F_PRIO_OACTIVE)) == 0)
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- rt2560_start_locked(ifp);
- }
+ if (sc->txq.queued < RT2560_TX_RING_COUNT - 1)
+ rt2560_start(sc);
}
static void
rt2560_prio_intr(struct rt2560_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
struct rt2560_tx_desc *desc;
struct rt2560_tx_data *data;
struct ieee80211_node *ni;
@@ -1103,13 +1075,8 @@ rt2560_prio_intr(struct rt2560_softc *sc)
if (sc->prioq.queued == 0 && sc->txq.queued == 0)
sc->sc_tx_timer = 0;
- if (sc->prioq.queued < RT2560_PRIO_RING_COUNT) {
- sc->sc_flags &= ~RT2560_F_PRIO_OACTIVE;
- if ((sc->sc_flags &
- (RT2560_F_DATA_OACTIVE | RT2560_F_PRIO_OACTIVE)) == 0)
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- rt2560_start_locked(ifp);
- }
+ if (sc->prioq.queued < RT2560_PRIO_RING_COUNT)
+ rt2560_start(sc);
}
/*
@@ -1119,8 +1086,7 @@ rt2560_prio_intr(struct rt2560_softc *sc)
static void
rt2560_decryption_intr(struct rt2560_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct rt2560_rx_desc *desc;
struct rt2560_rx_data *data;
bus_addr_t physaddr;
@@ -1146,13 +1112,13 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
break;
if (data->drop) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
if ((le32toh(desc->flags) & RT2560_RX_CIPHER_MASK) != 0 &&
(le32toh(desc->flags) & RT2560_RX_ICV_ERROR)) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@@ -1165,7 +1131,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
*/
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (mnew == NULL) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@@ -1188,7 +1154,7 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
panic("%s: could not load old rx mbuf",
device_get_name(sc->sc_dev));
}
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@@ -1201,7 +1167,6 @@ rt2560_decryption_intr(struct rt2560_softc *sc)
desc->physaddr = htole32(physaddr);
/* finalize mbuf */
- m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len =
(le32toh(desc->flags) >> 16) & 0xfff;
@@ -1321,8 +1286,7 @@ rt2560_beacon_update(struct ieee80211vap *vap, int item)
static void
rt2560_beacon_expire(struct rt2560_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct rt2560_vap *rvp = RT2560_VAP(vap);
struct rt2560_tx_data *data;
@@ -1363,7 +1327,6 @@ void
rt2560_intr(void *arg)
{
struct rt2560_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
uint32_t r;
RAL_LOCK(sc);
@@ -1372,7 +1335,7 @@ rt2560_intr(void *arg)
RAL_WRITE(sc, RT2560_CSR8, 0xffffffff);
/* don't re-enable interrupts if we're shutting down */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!(sc->sc_flags & RT2560_F_RUNNING)) {
RAL_UNLOCK(sc);
return;
}
@@ -1440,8 +1403,7 @@ static void
rt2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc,
uint32_t flags, int len, int rate, int encrypt, bus_addr_t physaddr)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t plcp_length;
int remainder;
@@ -1916,55 +1878,57 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0,
return 0;
}
+static int
+rt2560_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct rt2560_softc *sc = ic->ic_softc;
+ int error;
+
+ RAL_LOCK(sc);
+ if ((sc->sc_flags & RT2560_F_RUNNING) == 0) {
+ RAL_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ RAL_UNLOCK(sc);
+ return (error);
+ }
+ rt2560_start(sc);
+ RAL_UNLOCK(sc);
+
+ return (0);
+}
+
static void
-rt2560_start_locked(struct ifnet *ifp)
+rt2560_start(struct rt2560_softc *sc)
{
- struct rt2560_softc *sc = ifp->if_softc;
- struct mbuf *m;
struct ieee80211_node *ni;
+ struct mbuf *m;
RAL_LOCK_ASSERT(sc);
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
- if (sc->txq.queued >= RT2560_TX_RING_COUNT - 1) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- sc->sc_flags |= RT2560_F_DATA_OACTIVE;
- break;
- }
+ while (sc->txq.queued < RT2560_TX_RING_COUNT - 1 &&
+ (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (rt2560_tx_data(sc, m, ni) != 0) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
break;
}
-
sc->sc_tx_timer = 5;
}
}
static void
-rt2560_start(struct ifnet *ifp)
-{
- struct rt2560_softc *sc = ifp->if_softc;
-
- RAL_LOCK(sc);
- rt2560_start_locked(ifp);
- RAL_UNLOCK(sc);
-}
-
-static void
rt2560_watchdog(void *arg)
{
struct rt2560_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
RAL_LOCK_ASSERT(sc);
- KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
+ KASSERT(sc->sc_flags & RT2560_F_RUNNING, ("not running"));
if (sc->sc_invalid) /* card ejected */
return;
@@ -1973,51 +1937,33 @@ rt2560_watchdog(void *arg)
rt2560_tx_intr(sc);
if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) {
- if_printf(ifp, "device timeout\n");
+ device_printf(sc->sc_dev, "device timeout\n");
rt2560_init_locked(sc);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
/* NB: callout is reset in rt2560_init() */
return;
}
callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
}
-static int
-rt2560_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+rt2560_parent(struct ieee80211com *ic)
{
- struct rt2560_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ struct rt2560_softc *sc = ic->ic_softc;
+ int startall = 0;
- switch (cmd) {
- case SIOCSIFFLAGS:
- RAL_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- rt2560_init_locked(sc);
- startall = 1;
- } else
- rt2560_update_promisc(ic);
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- rt2560_stop_locked(sc);
- }
- RAL_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
- }
- return error;
+ RAL_LOCK(sc);
+ if (ic->ic_nrunning > 0) {
+ if ((sc->sc_flags & RT2560_F_RUNNING) == 0) {
+ rt2560_init_locked(sc);
+ startall = 1;
+ } else
+ rt2560_update_promisc(ic);
+ } else if (sc->sc_flags & RT2560_F_RUNNING)
+ rt2560_stop_locked(sc);
+ RAL_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
static void
@@ -2101,8 +2047,7 @@ rt2560_rf_write(struct rt2560_softc *sc, uint8_t reg, uint32_t val)
static void
rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint8_t power, tmp;
u_int i, chan;
@@ -2201,8 +2146,7 @@ rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c)
static void
rt2560_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct rt2560_softc *sc = ifp->if_softc;
+ struct rt2560_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
rt2560_set_chan(sc, ic->ic_curchan);
@@ -2238,8 +2182,7 @@ rt2560_disable_rf_tune(struct rt2560_softc *sc)
static void
rt2560_enable_tsf_sync(struct rt2560_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint16_t logcwmin, preload;
uint32_t tmp;
@@ -2280,8 +2223,7 @@ rt2560_enable_tsf(struct rt2560_softc *sc)
static void
rt2560_update_plcp(struct rt2560_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
/* no short preamble for 1Mbps */
RAL_WRITE(sc, RT2560_PLCP1MCSR, 0x00700400);
@@ -2360,8 +2302,7 @@ rt2560_set_basicrates(struct rt2560_softc *sc,
const struct ieee80211_rateset *rs)
{
#define RV(r) ((r) & IEEE80211_RATE_VAL)
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t mask = 0;
uint8_t rate;
int i;
@@ -2406,7 +2347,7 @@ rt2560_set_bssid(struct rt2560_softc *sc, const uint8_t *bssid)
}
static void
-rt2560_set_macaddr(struct rt2560_softc *sc, uint8_t *addr)
+rt2560_set_macaddr(struct rt2560_softc *sc, const uint8_t *addr)
{
uint32_t tmp;
@@ -2444,13 +2385,13 @@ rt2560_update_promisc(struct ieee80211com *ic)
tmp = RAL_READ(sc, RT2560_RXCSR0);
tmp &= ~RT2560_DROP_NOT_TO_ME;
- if (!(ic->ic_ifp->if_flags & IFF_PROMISC))
+ if (ic->ic_promisc == 0)
tmp |= RT2560_DROP_NOT_TO_ME;
RAL_WRITE(sc, RT2560_RXCSR0, tmp);
DPRINTF(sc, "%s promiscuous mode\n",
- (ic->ic_ifp->if_flags & IFF_PROMISC) ? "entering" : "leaving");
+ (ic->ic_promisc > 0) ? "entering" : "leaving");
}
static const char *
@@ -2516,19 +2457,17 @@ rt2560_read_config(struct rt2560_softc *sc)
static void
rt2560_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct rt2560_softc *sc = ifp->if_softc;
+ struct rt2560_softc *sc = ic->ic_softc;
/* abort TSF synchronization */
RAL_WRITE(sc, RT2560_CSR14, 0);
- rt2560_set_bssid(sc, ifp->if_broadcastaddr);
+ rt2560_set_bssid(sc, ieee80211broadcastaddr);
}
static void
rt2560_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct rt2560_softc *sc = ifp->if_softc;
+ struct rt2560_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = ic->ic_scan->ss_vap;
rt2560_enable_tsf_sync(sc);
@@ -2622,8 +2561,8 @@ static void
rt2560_init_locked(struct rt2560_softc *sc)
{
#define N(a) (sizeof (a) / sizeof ((a)[0]))
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
int i;
@@ -2654,7 +2593,7 @@ rt2560_init_locked(struct rt2560_softc *sc)
for (i = 0; i < N(rt2560_def_mac); i++)
RAL_WRITE(sc, rt2560_def_mac[i].reg, rt2560_def_mac[i].val);
- rt2560_set_macaddr(sc, IF_LLADDR(ifp));
+ rt2560_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
/* set basic rate set (will be updated later) */
RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x153);
@@ -2684,7 +2623,7 @@ rt2560_init_locked(struct rt2560_softc *sc)
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
ic->ic_opmode != IEEE80211_M_MBSS)
tmp |= RT2560_DROP_TODS;
- if (!(ifp->if_flags & IFF_PROMISC))
+ if (ic->ic_promisc == 0)
tmp |= RT2560_DROP_NOT_TO_ME;
}
RAL_WRITE(sc, RT2560_RXCSR0, tmp);
@@ -2699,8 +2638,7 @@ rt2560_init_locked(struct rt2560_softc *sc)
/* enable interrupts */
RAL_WRITE(sc, RT2560_CSR8, RT2560_INTR_MASK);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_flags |= RT2560_F_RUNNING;
callout_reset(&sc->watchdog_ch, hz, rt2560_watchdog, sc);
#undef N
@@ -2710,21 +2648,19 @@ static void
rt2560_init(void *priv)
{
struct rt2560_softc *sc = priv;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
RAL_LOCK(sc);
rt2560_init_locked(sc);
RAL_UNLOCK(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->sc_flags & RT2560_F_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
static void
rt2560_stop_locked(struct rt2560_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
volatile int *flags = &sc->sc_flags;
RAL_LOCK_ASSERT(sc);
@@ -2735,8 +2671,8 @@ rt2560_stop_locked(struct rt2560_softc *sc)
callout_stop(&sc->watchdog_ch);
sc->sc_tx_timer = 0;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ if (sc->sc_flags & RT2560_F_RUNNING) {
+ sc->sc_flags &= ~RT2560_F_RUNNING;
/* abort Tx */
RAL_WRITE(sc, RT2560_TXCSR0, RT2560_ABORT_TX);
@@ -2758,7 +2694,6 @@ rt2560_stop_locked(struct rt2560_softc *sc)
rt2560_reset_tx_ring(sc, &sc->bcnq);
rt2560_reset_rx_ring(sc, &sc->rxq);
}
- sc->sc_flags &= ~(RT2560_F_PRIO_OACTIVE | RT2560_F_DATA_OACTIVE);
}
void
@@ -2776,29 +2711,24 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct rt2560_softc *sc = ifp->if_softc;
+ struct rt2560_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!(sc->sc_flags & RT2560_F_RUNNING)) {
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
}
if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- sc->sc_flags |= RT2560_F_PRIO_OACTIVE;
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENOBUFS; /* XXX */
}
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
-
if (params == NULL) {
/*
* Legacy path; interpret frame contents to decide
@@ -2820,7 +2750,6 @@ rt2560_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
bad:
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
RAL_UNLOCK(sc);
return EIO; /* XXX */
diff --git a/sys/dev/ral/rt2560var.h b/sys/dev/ral/rt2560var.h
index b6a8d68..3a5fef9 100644
--- a/sys/dev/ral/rt2560var.h
+++ b/sys/dev/ral/rt2560var.h
@@ -105,13 +105,13 @@ struct rt2560_vap {
#define RT2560_VAP(vap) ((struct rt2560_vap *)(vap))
struct rt2560_softc {
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mtx sc_mtx;
+ struct mbufq sc_snd;
device_t sc_dev;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
- struct mtx sc_mtx;
-
struct callout watchdog_ch;
int sc_tx_timer;
@@ -152,8 +152,7 @@ struct rt2560_softc {
struct rt2560_tx_radiotap_header sc_txtap;
int sc_txtap_len;
#define RT2560_F_INPUT_RUNNING 0x1
-#define RT2560_F_PRIO_OACTIVE 0x2
-#define RT2560_F_DATA_OACTIVE 0x4
+#define RT2560_F_RUNNING 0x2
int sc_flags;
};
diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c
index 15a2364..c77d4f8 100644
--- a/sys/dev/ral/rt2661.c
+++ b/sys/dev/ral/rt2661.c
@@ -121,12 +121,12 @@ static int rt2661_tx_data(struct rt2661_softc *, struct mbuf *,
struct ieee80211_node *, int);
static int rt2661_tx_mgt(struct rt2661_softc *, struct mbuf *,
struct ieee80211_node *);
-static void rt2661_start_locked(struct ifnet *);
-static void rt2661_start(struct ifnet *);
+static int rt2661_transmit(struct ieee80211com *, struct mbuf *);
+static void rt2661_start(struct rt2661_softc *);
static int rt2661_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void rt2661_watchdog(void *);
-static int rt2661_ioctl(struct ifnet *, u_long, caddr_t);
+static void rt2661_parent(struct ieee80211com *);
static void rt2661_bbp_write(struct rt2661_softc *, uint8_t,
uint8_t);
static uint8_t rt2661_bbp_read(struct rt2661_softc *, uint8_t);
@@ -197,27 +197,19 @@ int
rt2661_attach(device_t dev, int id)
{
struct rt2661_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic;
- struct ifnet *ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t val;
int error, ac, ntries;
uint8_t bands;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_id = id;
sc->sc_dev = dev;
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "can not if_alloc()\n");
- return ENOMEM;
- }
- ic = ifp->if_l2com;
-
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
/* wait for NIC to initialize */
for (ntries = 0; ntries < 1000; ntries++) {
@@ -233,7 +225,7 @@ rt2661_attach(device_t dev, int id)
}
/* retrieve RF rev. no and various other things from EEPROM */
- rt2661_read_eeprom(sc, macaddr);
+ rt2661_read_eeprom(sc, ic->ic_macaddr);
device_printf(dev, "MAC/BBP RT%X, RF %s\n", val,
rt2661_get_rf(sc->rf_rev));
@@ -263,17 +255,6 @@ rt2661_attach(device_t dev, int id)
goto fail3;
}
- ifp->if_softc = sc;
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = rt2661_init;
- ifp->if_ioctl = rt2661_ioctl;
- ifp->if_start = rt2661_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_opmode = IEEE80211_M_STA;
@@ -305,7 +286,7 @@ rt2661_attach(device_t dev, int id)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, macaddr);
+ ieee80211_ifattach(ic);
#if 0
ic->ic_wme.wme_update = rt2661_wme_update;
#endif
@@ -315,7 +296,8 @@ rt2661_attach(device_t dev, int id)
ic->ic_updateslot = rt2661_update_slot;
ic->ic_update_promisc = rt2661_update_promisc;
ic->ic_raw_xmit = rt2661_raw_xmit;
-
+ ic->ic_transmit = rt2661_transmit;
+ ic->ic_parent = rt2661_parent;
ic->ic_vap_create = rt2661_vap_create;
ic->ic_vap_delete = rt2661_vap_delete;
@@ -339,7 +321,6 @@ fail3: rt2661_free_tx_ring(sc, &sc->mgtq);
fail2: while (--ac >= 0)
rt2661_free_tx_ring(sc, &sc->txq[ac]);
fail1: mtx_destroy(&sc->sc_mtx);
- if_free(ifp);
return error;
}
@@ -347,14 +328,14 @@ int
rt2661_detach(void *xsc)
{
struct rt2661_softc *sc = xsc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
RAL_LOCK(sc);
rt2661_stop_locked(sc);
RAL_UNLOCK(sc);
ieee80211_ifdetach(ic);
+ mbufq_drain(&sc->sc_snd);
rt2661_free_tx_ring(sc, &sc->txq[0]);
rt2661_free_tx_ring(sc, &sc->txq[1]);
@@ -363,8 +344,6 @@ rt2661_detach(void *xsc)
rt2661_free_tx_ring(sc, &sc->mgtq);
rt2661_free_rx_ring(sc, &sc->rxq);
- if_free(ifp);
-
mtx_destroy(&sc->sc_mtx);
return 0;
@@ -376,7 +355,7 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = ic->ic_ifp;
+ struct rt2661_softc *sc = ic->ic_softc;
struct rt2661_vap *rvp;
struct ieee80211vap *vap;
@@ -389,7 +368,7 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_MBSS:
/* XXXRP: TBD */
if (!TAILQ_EMPTY(&ic->ic_vaps)) {
- if_printf(ifp, "only 1 vap supported\n");
+ device_printf(sc->sc_dev, "only 1 vap supported\n");
return NULL;
}
if (opmode == IEEE80211_M_STA)
@@ -398,7 +377,8 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_WDS:
if (TAILQ_EMPTY(&ic->ic_vaps) ||
ic->ic_opmode != IEEE80211_M_HOSTAP) {
- if_printf(ifp, "wds only supported in ap mode\n");
+ device_printf(sc->sc_dev,
+ "wds only supported in ap mode\n");
return NULL;
}
/*
@@ -409,15 +389,12 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
flags &= ~IEEE80211_CLONE_BSSID;
break;
default:
- if_printf(ifp, "unknown opmode %d\n", opmode);
+ device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
return NULL;
}
- rvp = (struct rt2661_vap *) malloc(sizeof(struct rt2661_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (rvp == NULL)
- return NULL;
+ rvp = malloc(sizeof(struct rt2661_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &rvp->ral_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override state transition machine */
rvp->ral_newstate = vap->iv_newstate;
@@ -428,7 +405,8 @@ rt2661_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
/* complete setup */
- ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
+ ieee80211_vap_attach(vap, ieee80211_media_change,
+ ieee80211_media_status, mac);
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
ic->ic_opmode = opmode;
return vap;
@@ -464,9 +442,8 @@ void
rt2661_resume(void *xsc)
{
struct rt2661_softc *sc = xsc;
- struct ifnet *ifp = sc->sc_ifp;
- if (ifp->if_flags & IFF_UP)
+ if (sc->sc_ic.ic_nrunning > 0)
rt2661_init(sc);
}
@@ -770,7 +747,7 @@ rt2661_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct rt2661_vap *rvp = RT2661_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct rt2661_softc *sc = ic->ic_ifp->if_softc;
+ struct rt2661_softc *sc = ic->ic_softc;
int error;
if (nstate == IEEE80211_S_INIT && vap->iv_state == IEEE80211_S_RUN) {
@@ -869,11 +846,10 @@ rt2661_eeprom_read(struct rt2661_softc *sc, uint8_t addr)
static void
rt2661_tx_intr(struct rt2661_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
struct rt2661_tx_ring *txq;
struct rt2661_tx_data *data;
uint32_t val;
- int qid, retrycnt;
+ int error, qid, retrycnt;
struct ieee80211vap *vap;
for (;;) {
@@ -911,7 +887,7 @@ rt2661_tx_intr(struct rt2661_softc *sc)
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS,
&retrycnt, NULL);
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ error = 0;
break;
case RT2661_TX_RETRY_FAIL:
@@ -923,14 +899,14 @@ rt2661_tx_intr(struct rt2661_softc *sc)
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_FAILURE,
&retrycnt, NULL);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ error = 1;
break;
default:
/* other failure */
device_printf(sc->sc_dev,
"sending data frame failed 0x%08x\n", val);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ error = 1;
}
DPRINTFN(sc, 15, "tx done q=%d idx=%u\n", qid, txq->stat);
@@ -939,17 +915,12 @@ rt2661_tx_intr(struct rt2661_softc *sc)
if (++txq->stat >= txq->count) /* faster than % count */
txq->stat = 0;
- if (m->m_flags & M_TXCB)
- ieee80211_process_callback(ni, m,
- RT2661_TX_RESULT(val) != RT2661_TX_SUCCESS);
- m_freem(m);
- ieee80211_free_node(ni);
+ ieee80211_tx_complete(ni, m, error);
}
sc->sc_tx_timer = 0;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- rt2661_start_locked(ifp);
+ rt2661_start(sc);
}
static void
@@ -987,8 +958,7 @@ rt2661_tx_dma_intr(struct rt2661_softc *sc, struct rt2661_tx_ring *txq)
static void
rt2661_rx_intr(struct rt2661_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct rt2661_rx_desc *desc;
struct rt2661_rx_data *data;
bus_addr_t physaddr;
@@ -1017,12 +987,12 @@ rt2661_rx_intr(struct rt2661_softc *sc)
*/
DPRINTFN(sc, 5, "PHY or CRC error flags 0x%08x\n",
le32toh(desc->flags));
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
if ((le32toh(desc->flags) & RT2661_RX_CIPHER_MASK) != 0) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@@ -1035,7 +1005,7 @@ rt2661_rx_intr(struct rt2661_softc *sc)
*/
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (mnew == NULL) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@@ -1058,7 +1028,7 @@ rt2661_rx_intr(struct rt2661_softc *sc)
panic("%s: could not load old rx mbuf",
device_get_name(sc->sc_dev));
}
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@@ -1071,7 +1041,6 @@ rt2661_rx_intr(struct rt2661_softc *sc)
desc->physaddr = htole32(physaddr);
/* finalize mbuf */
- m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len =
(le32toh(desc->flags) >> 16) & 0xfff;
@@ -1156,7 +1125,6 @@ void
rt2661_intr(void *arg)
{
struct rt2661_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
uint32_t r1, r2;
RAL_LOCK(sc);
@@ -1166,7 +1134,7 @@ rt2661_intr(void *arg)
RAL_WRITE(sc, RT2661_MCU_INT_MASK_CSR, 0xffffffff);
/* don't re-enable interrupts if we're shutting down */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!(sc->sc_flags & RAL_RUNNING)) {
RAL_UNLOCK(sc);
return;
}
@@ -1242,8 +1210,7 @@ rt2661_setup_tx_desc(struct rt2661_softc *sc, struct rt2661_tx_desc *desc,
uint32_t flags, uint16_t xflags, int len, int rate,
const bus_dma_segment_t *segs, int nsegs, int ac)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t plcp_length;
int i, remainder;
@@ -1461,8 +1428,7 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
struct ieee80211_node *ni, int ac)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct rt2661_tx_ring *txq = &sc->txq[ac];
struct rt2661_tx_desc *desc;
struct rt2661_tx_data *data;
@@ -1604,10 +1570,31 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
return 0;
}
+static int
+rt2661_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct rt2661_softc *sc = ic->ic_softc;
+ int error;
+
+ RAL_LOCK(sc);
+ if ((sc->sc_flags & RAL_RUNNING) == 0) {
+ RAL_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ RAL_UNLOCK(sc);
+ return (error);
+ }
+ rt2661_start(sc);
+ RAL_UNLOCK(sc);
+
+ return (0);
+}
+
static void
-rt2661_start_locked(struct ifnet *ifp)
+rt2661_start(struct rt2661_softc *sc)
{
- struct rt2661_softc *sc = ifp->if_softc;
struct mbuf *m;
struct ieee80211_node *ni;
int ac;
@@ -1615,69 +1602,50 @@ rt2661_start_locked(struct ifnet *ifp)
RAL_LOCK_ASSERT(sc);
/* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING) || sc->sc_invalid)
+ if (!(sc->sc_flags & RAL_RUNNING) || sc->sc_invalid)
return;
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
-
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ac = M_WME_GETAC(m);
if (sc->txq[ac].queued >= RT2661_TX_RING_COUNT - 1) {
/* there is no place left in this ring */
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ mbufq_prepend(&sc->sc_snd, m);
break;
}
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (rt2661_tx_data(sc, m, ni, ac) != 0) {
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
break;
}
-
sc->sc_tx_timer = 5;
}
}
-static void
-rt2661_start(struct ifnet *ifp)
-{
- struct rt2661_softc *sc = ifp->if_softc;
-
- RAL_LOCK(sc);
- rt2661_start_locked(ifp);
- RAL_UNLOCK(sc);
-}
-
static int
rt2661_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct rt2661_softc *sc = ifp->if_softc;
+ struct rt2661_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!(sc->sc_flags & RAL_RUNNING)) {
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
}
if (sc->mgtq.queued >= RT2661_MGT_RING_COUNT) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENOBUFS; /* XXX */
}
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
-
/*
* Legacy path; interpret frame contents to decide
* precisely how to send the frame.
@@ -1691,7 +1659,6 @@ rt2661_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
bad:
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
RAL_UNLOCK(sc);
return EIO; /* XXX */
@@ -1701,61 +1668,42 @@ static void
rt2661_watchdog(void *arg)
{
struct rt2661_softc *sc = (struct rt2661_softc *)arg;
- struct ifnet *ifp = sc->sc_ifp;
RAL_LOCK_ASSERT(sc);
- KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
+ KASSERT(sc->sc_flags & RAL_RUNNING, ("not running"));
if (sc->sc_invalid) /* card ejected */
return;
if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) {
- if_printf(ifp, "device timeout\n");
+ device_printf(sc->sc_dev, "device timeout\n");
rt2661_init_locked(sc);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
/* NB: callout is reset in rt2661_init() */
return;
}
callout_reset(&sc->watchdog_ch, hz, rt2661_watchdog, sc);
}
-static int
-rt2661_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+rt2661_parent(struct ieee80211com *ic)
{
- struct rt2661_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ struct rt2661_softc *sc = ic->ic_softc;
+ int startall = 0;
- switch (cmd) {
- case SIOCSIFFLAGS:
- RAL_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- rt2661_init_locked(sc);
- startall = 1;
- } else
- rt2661_update_promisc(ic);
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- rt2661_stop_locked(sc);
- }
- RAL_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
- }
- return error;
+ RAL_LOCK(sc);
+ if (ic->ic_nrunning > 0) {
+ if ((sc->sc_flags & RAL_RUNNING) == 0) {
+ rt2661_init_locked(sc);
+ startall = 1;
+ } else
+ rt2661_update_promisc(ic);
+ } else if (sc->sc_flags & RAL_RUNNING)
+ rt2661_stop_locked(sc);
+ RAL_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
static void
@@ -1879,8 +1827,7 @@ rt2661_select_antenna(struct rt2661_softc *sc)
static void
rt2661_enable_mrr(struct rt2661_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
tmp = RAL_READ(sc, RT2661_TXRX_CSR4);
@@ -1896,8 +1843,7 @@ rt2661_enable_mrr(struct rt2661_softc *sc)
static void
rt2661_set_txpreamble(struct rt2661_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
tmp = RAL_READ(sc, RT2661_TXRX_CSR4);
@@ -1914,8 +1860,7 @@ rt2661_set_basicrates(struct rt2661_softc *sc,
const struct ieee80211_rateset *rs)
{
#define RV(r) ((r) & IEEE80211_RATE_VAL)
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t mask = 0;
uint8_t rate;
int i;
@@ -1984,8 +1929,7 @@ rt2661_select_band(struct rt2661_softc *sc, struct ieee80211_channel *c)
static void
rt2661_set_chan(struct rt2661_softc *sc, struct ieee80211_channel *c)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
const struct rfprog *rfprog;
uint8_t bbp3, bbp94 = RT2661_BBPR94_DEFAULT;
int8_t power;
@@ -2088,13 +2032,13 @@ rt2661_update_promisc(struct ieee80211com *ic)
tmp = RAL_READ(sc, RT2661_TXRX_CSR0);
tmp &= ~RT2661_DROP_NOT_TO_ME;
- if (!(ic->ic_ifp->if_flags & IFF_PROMISC))
+ if (ic->ic_promisc == 0)
tmp |= RT2661_DROP_NOT_TO_ME;
RAL_WRITE(sc, RT2661_TXRX_CSR0, tmp);
DPRINTF(sc, "%s promiscuous mode\n",
- (ic->ic_ifp->if_flags & IFF_PROMISC) ? "entering" : "leaving");
+ (ic->ic_promisc > 0) ? "entering" : "leaving");
}
/*
@@ -2103,7 +2047,7 @@ rt2661_update_promisc(struct ieee80211com *ic)
static int
rt2661_wme_update(struct ieee80211com *ic)
{
- struct rt2661_softc *sc = ic->ic_ifp->if_softc;
+ struct rt2661_softc *sc = ic->ic_softc;
const struct wmeParams *wmep;
wmep = ic->ic_wme.wme_chanParams.cap_wmeParams;
@@ -2301,8 +2245,8 @@ static void
rt2661_init_locked(struct rt2661_softc *sc)
{
#define N(a) (sizeof (a) / sizeof ((a)[0]))
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp, sta[3];
int i, error, ntries;
@@ -2311,7 +2255,7 @@ rt2661_init_locked(struct rt2661_softc *sc)
if ((sc->sc_flags & RAL_FW_LOADED) == 0) {
error = rt2661_load_microcode(sc);
if (error != 0) {
- if_printf(ifp,
+ device_printf(sc->sc_dev,
"%s: could not load 8051 microcode, error %d\n",
__func__, error);
return;
@@ -2364,7 +2308,7 @@ rt2661_init_locked(struct rt2661_softc *sc)
for (i = 0; i < N(rt2661_def_mac); i++)
RAL_WRITE(sc, rt2661_def_mac[i].reg, rt2661_def_mac[i].val);
- rt2661_set_macaddr(sc, IF_LLADDR(ifp));
+ rt2661_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
/* set host ready */
RAL_WRITE(sc, RT2661_MAC_CSR1, 3);
@@ -2403,7 +2347,7 @@ rt2661_init_locked(struct rt2661_softc *sc)
if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
ic->ic_opmode != IEEE80211_M_MBSS)
tmp |= RT2661_DROP_TODS;
- if (!(ifp->if_flags & IFF_PROMISC))
+ if (ic->ic_promisc == 0)
tmp |= RT2661_DROP_NOT_TO_ME;
}
@@ -2425,8 +2369,7 @@ rt2661_init_locked(struct rt2661_softc *sc)
/* kick Rx */
RAL_WRITE(sc, RT2661_RX_CNTL_CSR, 1);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_flags |= RAL_RUNNING;
callout_reset(&sc->watchdog_ch, hz, rt2661_watchdog, sc);
#undef N
@@ -2436,23 +2379,21 @@ static void
rt2661_init(void *priv)
{
struct rt2661_softc *sc = priv;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
RAL_LOCK(sc);
rt2661_init_locked(sc);
RAL_UNLOCK(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->sc_flags & RAL_RUNNING)
ieee80211_start_all(ic); /* start all vap's */
}
void
rt2661_stop_locked(struct rt2661_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- uint32_t tmp;
volatile int *flags = &sc->sc_flags;
+ uint32_t tmp;
while (*flags & RAL_INPUT_RUNNING)
msleep(sc, &sc->sc_mtx, 0, "ralrunning", hz/10);
@@ -2460,8 +2401,8 @@ rt2661_stop_locked(struct rt2661_softc *sc)
callout_stop(&sc->watchdog_ch);
sc->sc_tx_timer = 0;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ if (sc->sc_flags & RAL_RUNNING) {
+ sc->sc_flags &= ~RAL_RUNNING;
/* abort Tx (for all 5 Tx rings) */
RAL_WRITE(sc, RT2661_TX_CNTL_CSR, 0x1f << 16);
@@ -2505,7 +2446,6 @@ rt2661_stop(void *priv)
static int
rt2661_load_microcode(struct rt2661_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
const struct firmware *fp;
const char *imagename;
int ntries, error;
@@ -2517,7 +2457,7 @@ rt2661_load_microcode(struct rt2661_softc *sc)
case 0x0302: imagename = "rt2561fw"; break;
case 0x0401: imagename = "rt2661fw"; break;
default:
- if_printf(ifp, "%s: unexpected pci device id 0x%x, "
+ device_printf(sc->sc_dev, "%s: unexpected pci device id 0x%x, "
"don't know how to retrieve firmware\n",
__func__, sc->sc_id);
return EINVAL;
@@ -2526,7 +2466,8 @@ rt2661_load_microcode(struct rt2661_softc *sc)
fp = firmware_get(imagename);
RAL_LOCK(sc);
if (fp == NULL) {
- if_printf(ifp, "%s: unable to retrieve firmware image %s\n",
+ device_printf(sc->sc_dev,
+ "%s: unable to retrieve firmware image %s\n",
__func__, imagename);
return EINVAL;
}
@@ -2557,8 +2498,8 @@ rt2661_load_microcode(struct rt2661_softc *sc)
DELAY(100);
}
if (ntries == 500) {
- if_printf(ifp, "%s: timeout waiting for MCU to initialize\n",
- __func__);
+ device_printf(sc->sc_dev,
+ "%s: timeout waiting for MCU to initialize\n", __func__);
error = EIO;
} else
error = 0;
@@ -2726,8 +2667,7 @@ rt2661_prepare_beacon(struct rt2661_softc *sc, struct ieee80211vap *vap)
static void
rt2661_enable_tsf_sync(struct rt2661_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
@@ -2811,21 +2751,19 @@ rt2661_get_rssi(struct rt2661_softc *sc, uint8_t raw)
static void
rt2661_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct rt2661_softc *sc = ifp->if_softc;
+ struct rt2661_softc *sc = ic->ic_softc;
uint32_t tmp;
/* abort TSF synchronization */
tmp = RAL_READ(sc, RT2661_TXRX_CSR9);
RAL_WRITE(sc, RT2661_TXRX_CSR9, tmp & ~0xffffff);
- rt2661_set_bssid(sc, ifp->if_broadcastaddr);
+ rt2661_set_bssid(sc, ieee80211broadcastaddr);
}
static void
rt2661_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct rt2661_softc *sc = ifp->if_softc;
+ struct rt2661_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
rt2661_enable_tsf_sync(sc);
@@ -2836,8 +2774,7 @@ rt2661_scan_end(struct ieee80211com *ic)
static void
rt2661_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct rt2661_softc *sc = ifp->if_softc;
+ struct rt2661_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
rt2661_set_chan(sc, ic->ic_curchan);
diff --git a/sys/dev/ral/rt2661var.h b/sys/dev/ral/rt2661var.h
index 9927d13..7ea16f6 100644
--- a/sys/dev/ral/rt2661var.h
+++ b/sys/dev/ral/rt2661var.h
@@ -97,13 +97,13 @@ struct rt2661_vap {
#define RT2661_VAP(vap) ((struct rt2661_vap *)(vap))
struct rt2661_softc {
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mtx sc_mtx;
+ struct mbufq sc_snd;
device_t sc_dev;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
- struct mtx sc_mtx;
-
struct callout watchdog_ch;
int sc_tx_timer;
@@ -117,6 +117,7 @@ struct rt2661_softc {
int sc_flags;
#define RAL_FW_LOADED 0x1
#define RAL_INPUT_RUNNING 0x2
+#define RAL_RUNNING 0x4
int sc_id;
struct ieee80211_channel *sc_curchan;
diff --git a/sys/dev/ral/rt2860.c b/sys/dev/ral/rt2860.c
index 782fa1f..b3c737d 100644
--- a/sys/dev/ral/rt2860.c
+++ b/sys/dev/ral/rt2860.c
@@ -122,10 +122,10 @@ static int rt2860_raw_xmit(struct ieee80211_node *, struct mbuf *,
static int rt2860_tx_raw(struct rt2860_softc *, struct mbuf *,
struct ieee80211_node *,
const struct ieee80211_bpf_params *params);
-static void rt2860_start(struct ifnet *);
-static void rt2860_start_locked(struct ifnet *);
+static int rt2860_transmit(struct ieee80211com *, struct mbuf *);
+static void rt2860_start(struct rt2860_softc *);
static void rt2860_watchdog(void *);
-static int rt2860_ioctl(struct ifnet *, u_long, caddr_t);
+static void rt2860_parent(struct ieee80211com *);
static void rt2860_mcu_bbp_write(struct rt2860_softc *, uint8_t, uint8_t);
static uint8_t rt2860_mcu_bbp_read(struct rt2860_softc *, uint8_t);
static void rt2860_rf_write(struct rt2860_softc *, uint8_t, uint32_t);
@@ -156,7 +156,7 @@ static void rt2860_set_bssid(struct rt2860_softc *, const uint8_t *);
static void rt2860_set_macaddr(struct rt2860_softc *, const uint8_t *);
static void rt2860_update_promisc(struct ieee80211com *);
static void rt2860_updateslot(struct ieee80211com *);
-static void rt2860_updateprot(struct ifnet *);
+static void rt2860_updateprot(struct rt2860_softc *);
static int rt2860_updateedca(struct ieee80211com *);
#ifdef HW_CRYPTO
static int rt2860_set_key(struct ieee80211com *, struct ieee80211_node *,
@@ -230,27 +230,19 @@ int
rt2860_attach(device_t dev, int id)
{
struct rt2860_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic;
- struct ifnet *ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
int error, ntries, qid;
uint8_t bands;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
sc->sc_debug = 0;
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "can not if_alloc()\n");
- return ENOMEM;
- }
- ic = ifp->if_l2com;
-
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
/* wait for NIC to initialize */
for (ntries = 0; ntries < 100; ntries++) {
@@ -273,11 +265,11 @@ rt2860_attach(device_t dev, int id)
sc->sc_flags |= RT2860_ADVANCED_PS;
/* retrieve RF rev. no and various other things from EEPROM */
- rt2860_read_eeprom(sc, macaddr);
+ rt2860_read_eeprom(sc, ic->ic_macaddr);
device_printf(sc->sc_dev, "MAC/BBP RT%X (rev 0x%04X), "
"RF %s (MIMO %dT%dR), address %6D\n",
sc->mac_ver, sc->mac_rev, rt2860_get_rf(sc->rf_rev),
- sc->ntxchains, sc->nrxchains, macaddr, ":");
+ sc->ntxchains, sc->nrxchains, ic->ic_macaddr, ":");
/*
* Allocate Tx (4 EDCAs + HCCA + Mgt) and Rx rings.
@@ -304,17 +296,6 @@ rt2860_attach(device_t dev, int id)
sc->mgtqid = (sc->mac_ver == 0x2860 && sc->mac_rev == 0x0100) ?
WME_AC_VO : 5;
- ifp->if_softc = sc;
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = rt2860_init;
- ifp->if_ioctl = rt2860_ioctl;
- ifp->if_start = rt2860_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_opmode = IEEE80211_M_STA;
@@ -345,7 +326,7 @@ rt2860_attach(device_t dev, int id)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, macaddr);
+ ieee80211_ifattach(ic);
ic->ic_wme.wme_update = rt2860_updateedca;
ic->ic_scan_start = rt2860_scan_start;
@@ -357,7 +338,8 @@ rt2860_attach(device_t dev, int id)
sc->sc_node_free = ic->ic_node_free;
ic->ic_node_free = rt2860_node_free;
ic->ic_newassoc = rt2860_newassoc;
-
+ ic->ic_transmit = rt2860_transmit;
+ ic->ic_parent = rt2860_parent;
ic->ic_vap_create = rt2860_vap_create;
ic->ic_vap_delete = rt2860_vap_delete;
@@ -381,7 +363,6 @@ fail3: rt2860_free_rx_ring(sc, &sc->rxq);
fail2: while (--qid >= 0)
rt2860_free_tx_ring(sc, &sc->txq[qid]);
fail1: mtx_destroy(&sc->sc_mtx);
- if_free(ifp);
return error;
}
@@ -389,8 +370,7 @@ int
rt2860_detach(void *xsc)
{
struct rt2860_softc *sc = xsc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
int qid;
RAL_LOCK(sc);
@@ -398,14 +378,12 @@ rt2860_detach(void *xsc)
RAL_UNLOCK(sc);
ieee80211_ifdetach(ic);
-
+ mbufq_drain(&sc->sc_snd);
for (qid = 0; qid < 6; qid++)
rt2860_free_tx_ring(sc, &sc->txq[qid]);
rt2860_free_rx_ring(sc, &sc->rxq);
rt2860_free_tx_pool(sc);
- if_free(ifp);
-
mtx_destroy(&sc->sc_mtx);
return 0;
@@ -431,9 +409,8 @@ void
rt2860_resume(void *xsc)
{
struct rt2860_softc *sc = xsc;
- struct ifnet *ifp = sc->sc_ifp;
- if (ifp->if_flags & IFF_UP)
+ if (sc->sc_ic.ic_nrunning > 0)
rt2860_init(sc);
}
@@ -443,7 +420,7 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = ic->ic_ifp;
+ struct rt2860_softc *sc = ic->ic_softc;
struct rt2860_vap *rvp;
struct ieee80211vap *vap;
@@ -456,7 +433,7 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_MBSS:
/* XXXRP: TBD */
if (!TAILQ_EMPTY(&ic->ic_vaps)) {
- if_printf(ifp, "only 1 vap supported\n");
+ device_printf(sc->sc_dev, "only 1 vap supported\n");
return NULL;
}
if (opmode == IEEE80211_M_STA)
@@ -465,7 +442,8 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
case IEEE80211_M_WDS:
if (TAILQ_EMPTY(&ic->ic_vaps) ||
ic->ic_opmode != IEEE80211_M_HOSTAP) {
- if_printf(ifp, "wds only supported in ap mode\n");
+ device_printf(sc->sc_dev,
+ "wds only supported in ap mode\n");
return NULL;
}
/*
@@ -476,14 +454,12 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
flags &= ~IEEE80211_CLONE_BSSID;
break;
default:
- if_printf(ifp, "unknown opmode %d\n", opmode);
+ device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
return NULL;
}
- rvp = malloc(sizeof(struct rt2860_vap), M_80211_VAP, M_NOWAIT | M_ZERO);
- if (rvp == NULL)
- return NULL;
+ rvp = malloc(sizeof(struct rt2860_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &rvp->ral_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
/* override state transition machine */
rvp->ral_newstate = vap->iv_newstate;
@@ -497,7 +473,8 @@ rt2860_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
/* complete setup */
- ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
+ ieee80211_vap_attach(vap, ieee80211_media_change,
+ ieee80211_media_status, mac);
if (TAILQ_FIRST(&ic->ic_vaps) == vap)
ic->ic_opmode = opmode;
return vap;
@@ -829,7 +806,7 @@ rt2860_free_rx_ring(struct rt2860_softc *sc, struct rt2860_rx_ring *ring)
static void
rt2860_updatestats(struct rt2860_softc *sc)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
/*
* In IBSS or HostAP modes (when the hardware sends beacons), the
@@ -856,7 +833,7 @@ static void
rt2860_newassoc(struct ieee80211_node *ni, int isnew)
{
struct ieee80211com *ic = ni->ni_ic;
- struct rt2860_softc *sc = ic->ic_ifp->if_softc;
+ struct rt2860_softc *sc = ic->ic_softc;
uint8_t wcid;
wcid = IEEE80211_AID(ni->ni_associd);
@@ -875,7 +852,7 @@ static void
rt2860_node_free(struct ieee80211_node *ni)
{
struct ieee80211com *ic = ni->ni_ic;
- struct rt2860_softc *sc = ic->ic_ifp->if_softc;
+ struct rt2860_softc *sc = ic->ic_softc;
uint8_t wcid;
if (ni->ni_associd != 0) {
@@ -923,7 +900,7 @@ rt2860_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct rt2860_vap *rvp = RT2860_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct rt2860_softc *sc = ic->ic_ifp->if_softc;
+ struct rt2860_softc *sc = ic->ic_softc;
uint32_t tmp;
int error;
@@ -1101,7 +1078,6 @@ rt2860_intr_coherent(struct rt2860_softc *sc)
static void
rt2860_drain_stats_fifo(struct rt2860_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
struct ieee80211_node *ni;
uint32_t stat;
int retrycnt;
@@ -1137,7 +1113,8 @@ rt2860_drain_stats_fifo(struct rt2860_softc *sc)
} else {
ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &retrycnt, NULL);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
}
}
}
@@ -1145,7 +1122,6 @@ rt2860_drain_stats_fifo(struct rt2860_softc *sc)
static void
rt2860_tx_intr(struct rt2860_softc *sc, int qid)
{
- struct ifnet *ifp = sc->sc_ifp;
struct rt2860_tx_ring *ring = &sc->txq[qid];
uint32_t hw;
@@ -1163,15 +1139,11 @@ rt2860_tx_intr(struct rt2860_softc *sc, int qid)
ieee80211_process_callback(data->ni, data->m,
0);
}
- m_freem(data->m);
- ieee80211_free_node(data->ni);
- data->m = NULL;
+ ieee80211_tx_complete(data->ni, data->m, 0);
data->ni = NULL;
-
+ data->m = NULL;
SLIST_INSERT_HEAD(&sc->data_pool, data, next);
ring->data[ring->next] = NULL;
-
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
}
ring->queued--;
ring->next = (ring->next + 1) % RT2860_TX_RING_COUNT;
@@ -1180,8 +1152,7 @@ rt2860_tx_intr(struct rt2860_softc *sc, int qid)
sc->sc_tx_timer = 0;
if (ring->queued < RT2860_TX_RING_COUNT)
sc->qfullmsk &= ~(1 << qid);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- rt2860_start_locked(ifp);
+ rt2860_start(sc);
}
/*
@@ -1206,8 +1177,7 @@ static void
rt2860_rx_intr(struct rt2860_softc *sc)
{
struct rt2860_rx_radiotap_header *tap;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m, *m1;
@@ -1234,7 +1204,7 @@ rt2860_rx_intr(struct rt2860_softc *sc)
if (__predict_false(rxd->flags &
htole32(RT2860_RX_CRCERR | RT2860_RX_ICVERR))) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@@ -1243,14 +1213,14 @@ rt2860_rx_intr(struct rt2860_softc *sc)
/* report MIC failures to net80211 for TKIP */
ic->ic_stats.is_rx_locmicfail++;
ieee80211_michael_mic_failure(ic, 0/* XXX */);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
#endif
m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m1 == NULL)) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@@ -1274,7 +1244,7 @@ rt2860_rx_intr(struct rt2860_softc *sc)
}
/* physical address may have changed */
rxd->sdp0 = htole32(physaddr);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto skip;
}
@@ -1289,7 +1259,6 @@ rt2860_rx_intr(struct rt2860_softc *sc)
rxwi = mtod(m, struct rt2860_rxwi *);
/* finalize mbuf */
- m->m_pkthdr.rcvif = ifp;
m->m_data = (caddr_t)(rxwi + 1);
m->m_pkthdr.len = m->m_len = le16toh(rxwi->len) & 0xfff;
@@ -1399,7 +1368,7 @@ rt2860_tbtt_intr(struct rt2860_softc *sc)
#endif
/* check if protection mode has changed */
if ((sc->sc_ic_flags ^ ic->ic_flags) & IEEE80211_F_USEPROT) {
- rt2860_updateprot(ic);
+ rt2860_updateprot(sc);
sc->sc_ic_flags = ic->ic_flags;
}
#endif
@@ -1408,7 +1377,7 @@ rt2860_tbtt_intr(struct rt2860_softc *sc)
static void
rt2860_gp_intr(struct rt2860_softc *sc)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
DPRINTFN(2, ("GP timeout state=%d\n", vap->iv_state));
@@ -1480,8 +1449,7 @@ rt2860_intr(void *arg)
static int
rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct rt2860_tx_ring *ring;
struct rt2860_tx_data *data;
@@ -1725,14 +1693,13 @@ rt2860_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct rt2860_softc *sc = ifp->if_softc;
+ struct rt2860_softc *sc = ic->ic_softc;
int error;
RAL_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!(sc->sc_flags & RT2860_RUNNNING)) {
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
@@ -1754,7 +1721,6 @@ rt2860_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
if (error != 0) {
/* NB: m is reclaimed on tx failure */
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
sc->sc_tx_timer = 5;
RAL_UNLOCK(sc);
@@ -1765,8 +1731,7 @@ static int
rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m,
struct ieee80211_node *ni, const struct ieee80211_bpf_params *params)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct rt2860_tx_ring *ring;
struct rt2860_tx_data *data;
@@ -1973,41 +1938,46 @@ rt2860_tx_raw(struct rt2860_softc *sc, struct mbuf *m,
return 0;
}
-static void
-rt2860_start(struct ifnet *ifp)
+static int
+rt2860_transmit(struct ieee80211com *ic, struct mbuf *m)
{
- struct rt2860_softc *sc = ifp->if_softc;
+ struct rt2860_softc *sc = ic->ic_softc;
+ int error;
RAL_LOCK(sc);
- rt2860_start_locked(ifp);
+ if ((sc->sc_flags & RT2860_RUNNNING) == 0) {
+ RAL_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ RAL_UNLOCK(sc);
+ return (error);
+ }
+ rt2860_start(sc);
RAL_UNLOCK(sc);
+
+ return (0);
}
static void
-rt2860_start_locked(struct ifnet *ifp)
+rt2860_start(struct rt2860_softc *sc)
{
- struct rt2860_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
RAL_LOCK_ASSERT(sc);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
- (ifp->if_drv_flags & IFF_DRV_OACTIVE))
+ if ((sc->sc_flags & RT2860_RUNNNING) == 0)
return;
- for (;;) {
- if (SLIST_EMPTY(&sc->data_pool) || sc->qfullmsk != 0) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
+ while (!SLIST_EMPTY(&sc->data_pool) && sc->qfullmsk == 0 &&
+ (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (rt2860_tx(sc, m, ni) != 0) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
continue;
}
sc->sc_tx_timer = 5;
@@ -2018,61 +1988,42 @@ static void
rt2860_watchdog(void *arg)
{
struct rt2860_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
RAL_LOCK_ASSERT(sc);
- KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING, ("not running"));
+ KASSERT(sc->sc_flags & RT2860_RUNNNING, ("not running"));
if (sc->sc_invalid) /* card ejected */
return;
if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) {
- if_printf(ifp, "device timeout\n");
+ device_printf(sc->sc_dev, "device timeout\n");
rt2860_stop_locked(sc);
rt2860_init_locked(sc);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
return;
}
callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc);
}
-static int
-rt2860_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+rt2860_parent(struct ieee80211com *ic)
{
- struct rt2860_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *)data;
- int error = 0, startall = 0;
+ struct rt2860_softc *sc = ic->ic_softc;
+ int startall = 0;
- switch (cmd) {
- case SIOCSIFFLAGS:
- RAL_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- rt2860_init_locked(sc);
- startall = 1;
- } else
- rt2860_update_promisc(ic);
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- rt2860_stop_locked(sc);
- }
- RAL_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCSIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
- }
- return error;
+ RAL_LOCK(sc);
+ if (ic->ic_nrunning> 0) {
+ if (!(sc->sc_flags & RT2860_RUNNNING)) {
+ rt2860_init_locked(sc);
+ startall = 1;
+ } else
+ rt2860_update_promisc(ic);
+ } else if (sc->sc_flags & RT2860_RUNNNING)
+ rt2860_stop_locked(sc);
+ RAL_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
/*
@@ -2295,8 +2246,7 @@ rt2860_enable_mrr(struct rt2860_softc *sc)
static void
rt2860_set_txpreamble(struct rt2860_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
tmp = RAL_READ(sc, RT2860_AUTO_RSP_CFG);
@@ -2311,8 +2261,7 @@ rt2860_set_basicrates(struct rt2860_softc *sc,
const struct ieee80211_rateset *rs)
{
#define RV(r) ((r) & IEEE80211_RATE_VAL)
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t mask = 0;
uint8_t rate;
int i;
@@ -2333,8 +2282,7 @@ rt2860_set_basicrates(struct rt2860_softc *sc,
static void
rt2860_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct rt2860_softc *sc = ifp->if_softc;
+ struct rt2860_softc *sc = ic->ic_softc;
uint32_t tmp;
tmp = RAL_READ(sc, RT2860_BCN_TIME_CFG);
@@ -2347,8 +2295,7 @@ rt2860_scan_start(struct ieee80211com *ic)
static void
rt2860_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct rt2860_softc *sc = ifp->if_softc;
+ struct rt2860_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
if (vap->iv_state == IEEE80211_S_RUN) {
@@ -2360,8 +2307,7 @@ rt2860_scan_end(struct ieee80211com *ic)
static void
rt2860_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct rt2860_softc *sc = ifp->if_softc;
+ struct rt2860_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
rt2860_switch_chan(sc, ic->ic_curchan);
@@ -3113,10 +3059,9 @@ rt2860_updateslot(struct ieee80211com *ic)
}
static void
-rt2860_updateprot(struct ifnet *ifp)
+rt2860_updateprot(struct rt2860_softc *sc)
{
- struct rt2860_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL;
@@ -3145,7 +3090,7 @@ rt2860_update_promisc(struct ieee80211com *ic)
tmp = RAL_READ(sc, RT2860_RX_FILTR_CFG);
tmp &= ~RT2860_DROP_NOT_MYBSS;
- if (!(ic->ic_ifp->if_flags & IFF_PROMISC))
+ if (ic->ic_promisc == 0)
tmp |= RT2860_DROP_NOT_MYBSS;
RAL_WRITE(sc, RT2860_RX_FILTR_CFG, tmp);
}
@@ -3153,7 +3098,7 @@ rt2860_update_promisc(struct ieee80211com *ic)
static int
rt2860_updateedca(struct ieee80211com *ic)
{
- struct rt2860_softc *sc = ic->ic_ifp->if_softc;
+ struct rt2860_softc *sc = ic->ic_softc;
const struct wmeParams *wmep;
int aci;
@@ -3325,8 +3270,7 @@ rt2860_delete_key(struct ieee80211com *ic, struct ieee80211_node *ni,
static int8_t
rt2860_rssi2dbm(struct rt2860_softc *sc, uint8_t rssi, uint8_t rxchain)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *c = ic->ic_curchan;
int delta;
@@ -3801,8 +3745,7 @@ rt5390_bbp_init(struct rt2860_softc *sc)
static int
rt2860_txrx_enable(struct rt2860_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
int ntries;
@@ -3848,22 +3791,21 @@ static void
rt2860_init(void *arg)
{
struct rt2860_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
RAL_LOCK(sc);
rt2860_init_locked(sc);
RAL_UNLOCK(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->sc_flags & RT2860_RUNNNING)
ieee80211_start_all(ic);
}
static void
rt2860_init_locked(struct rt2860_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
uint8_t bbp1, bbp3;
int i, qid, ridx, ntries, error;
@@ -3899,7 +3841,7 @@ rt2860_init_locked(struct rt2860_softc *sc)
return;
}
- rt2860_set_macaddr(sc, IF_LLADDR(ifp));
+ rt2860_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
/* init Tx power for all Tx rates (from EEPROM) */
for (ridx = 0; ridx < 5; ridx++) {
@@ -4096,7 +4038,7 @@ rt2860_init_locked(struct rt2860_softc *sc)
RAL_WRITE(sc, RT2860_TX_RTS_CFG, tmp);
/* setup initial protection mode */
- rt2860_updateprot(ifp);
+ rt2860_updateprot(sc);
/* turn radio LED on */
rt2860_set_leds(sc, RT2860_LED_RADIO);
@@ -4115,8 +4057,7 @@ rt2860_init_locked(struct rt2860_softc *sc)
if (sc->sc_flags & RT2860_ADVANCED_PS)
rt2860_mcu_cmd(sc, RT2860_MCU_CMD_PSLEVEL, sc->pslevel, 0);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_flags |= RT2860_RUNNNING;
callout_reset(&sc->watchdog_ch, hz, rt2860_watchdog, sc);
}
@@ -4134,16 +4075,15 @@ rt2860_stop(void *arg)
static void
rt2860_stop_locked(struct rt2860_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
int qid;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->sc_flags & RT2860_RUNNNING)
rt2860_set_leds(sc, 0); /* turn all LEDs off */
callout_stop(&sc->watchdog_ch);
sc->sc_tx_timer = 0;
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_flags &= ~RT2860_RUNNNING;
/* disable interrupts */
RAL_WRITE(sc, RT2860_INT_MASK, 0);
@@ -4294,8 +4234,7 @@ rt3090_set_rx_antenna(struct rt2860_softc *sc, int aux)
static void
rt2860_switch_chan(struct rt2860_softc *sc, struct ieee80211_channel *c)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
u_int chan, group;
chan = ieee80211_chan2ieee(ic, c);
@@ -4364,8 +4303,7 @@ rt2860_setup_beacon(struct rt2860_softc *sc, struct ieee80211vap *vap)
static void
rt2860_enable_tsf_sync(struct rt2860_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
diff --git a/sys/dev/ral/rt2860var.h b/sys/dev/ral/rt2860var.h
index 28a3d59..3779e5b 100644
--- a/sys/dev/ral/rt2860var.h
+++ b/sys/dev/ral/rt2860var.h
@@ -115,13 +115,13 @@ struct rt2860_vap {
#define RT2860_VAP(vap) ((struct rt2860_vap *)(vap))
struct rt2860_softc {
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
+ struct mtx sc_mtx;
device_t sc_dev;
bus_space_tag_t sc_st;
bus_space_handle_t sc_sh;
- struct mtx sc_mtx;
-
struct callout watchdog_ch;
int sc_invalid;
@@ -139,6 +139,7 @@ struct rt2860_softc {
#define RT2860_ENABLED (1 << 0)
#define RT2860_ADVANCED_PS (1 << 1)
#define RT2860_PCIE (1 << 2)
+#define RT2860_RUNNNING (1 << 3)
struct ieee80211_node *wcid2ni[RT2860_WCID_MAX];
diff --git a/sys/dev/usb/controller/dwc_otg.c b/sys/dev/usb/controller/dwc_otg.c
index 17d792a..bd3e51b 100644
--- a/sys/dev/usb/controller/dwc_otg.c
+++ b/sys/dev/usb/controller/dwc_otg.c
@@ -453,8 +453,12 @@ static void
dwc_otg_enable_sof_irq(struct dwc_otg_softc *sc)
{
/* In device mode we don't use the SOF interrupt */
- if (sc->sc_flags.status_device_mode != 0 ||
- (sc->sc_irq_mask & GINTMSK_SOFMSK) != 0)
+ if (sc->sc_flags.status_device_mode != 0)
+ return;
+ /* Ensure the SOF interrupt is not disabled */
+ sc->sc_needsof = 1;
+ /* Check if the SOF interrupt is already enabled */
+ if ((sc->sc_irq_mask & GINTMSK_SOFMSK) != 0)
return;
sc->sc_irq_mask |= GINTMSK_SOFMSK;
DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask);
@@ -775,7 +779,7 @@ check_state:
case DWC_CHAN_ST_WAIT_ANE:
if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto send_pkt;
} else if (hcint & (HCINT_ACK | HCINT_NYET)) {
@@ -789,7 +793,7 @@ check_state:
case DWC_CHAN_ST_WAIT_S_ANE:
if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto send_pkt;
} else if (hcint & (HCINT_ACK | HCINT_NYET)) {
@@ -801,7 +805,7 @@ check_state:
if (hcint & HCINT_NYET) {
goto send_cpkt;
} else if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto send_pkt;
} else if (hcint & HCINT_ACK) {
@@ -1069,8 +1073,17 @@ dwc_otg_host_rate_check(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
if (!td->tt_scheduled)
goto busy;
td->tt_scheduled = 0;
- } else if (td->did_nak >= DWC_OTG_NAK_MAX) {
- goto busy;
+ } else if (td->did_nak != 0) {
+ uint8_t frame_num = (uint8_t)sc->sc_last_frame_num;
+ /* check if we should pause sending queries for 125us */
+ if (td->tmr_res == frame_num) {
+ /* wait a bit */
+ dwc_otg_enable_sof_irq(sc);
+ goto busy;
+ }
+ /* query for data one more time */
+ td->tmr_res = frame_num;
+ td->did_nak = 0;
} else if (td->set_toggle) {
td->set_toggle = 0;
td->toggle = 1;
@@ -1257,7 +1270,7 @@ dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
goto receive_pkt;
}
}
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
if (td->hcsplt != 0)
goto receive_spkt;
@@ -1312,7 +1325,7 @@ dwc_otg_host_data_rx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
* case of interrupt and isochronous transfers:
*/
if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto receive_spkt;
} else if (hcint & HCINT_NYET) {
@@ -1638,7 +1651,7 @@ dwc_otg_host_data_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
case DWC_CHAN_ST_WAIT_ANE:
if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto send_pkt;
} else if (hcint & (HCINT_ACK | HCINT_NYET)) {
@@ -1664,7 +1677,7 @@ dwc_otg_host_data_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
case DWC_CHAN_ST_WAIT_S_ANE:
if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto send_pkt;
} else if (hcint & (HCINT_ACK | HCINT_NYET)) {
@@ -1677,7 +1690,7 @@ dwc_otg_host_data_tx(struct dwc_otg_softc *sc, struct dwc_otg_td *td)
if (hcint & HCINT_NYET) {
goto send_cpkt;
} else if (hcint & (HCINT_RETRY | HCINT_ERRORS)) {
- td->did_nak++;
+ td->did_nak = 1;
td->tt_scheduled = 0;
goto send_pkt;
} else if (hcint & HCINT_ACK) {
@@ -2280,8 +2293,6 @@ static void
dwc_otg_timer(void *_sc)
{
struct dwc_otg_softc *sc = _sc;
- struct usb_xfer *xfer;
- struct dwc_otg_td *td;
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
@@ -2292,14 +2303,6 @@ dwc_otg_timer(void *_sc)
/* increment timer value */
sc->sc_tmr_val++;
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
- td = xfer->td_transfer_cache;
- if (td != NULL) {
- /* reset NAK counter */
- td->did_nak = 0;
- }
- }
-
/* enable SOF interrupt, which will poll jobs */
dwc_otg_enable_sof_irq(sc);
@@ -2459,8 +2462,7 @@ dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc)
TAILQ_FOREACH_SAFE(xfer, &sc->sc_bus.intr_q.head, wait_entry, xfer_next) {
td = xfer->td_transfer_cache;
if (td == NULL ||
- td->ep_type != UE_CONTROL ||
- td->did_nak >= DWC_OTG_NAK_MAX) {
+ td->ep_type != UE_CONTROL) {
continue;
}
@@ -2480,8 +2482,7 @@ dwc_otg_update_host_transfer_schedule_locked(struct dwc_otg_softc *sc)
TAILQ_FOREACH_SAFE(xfer, &sc->sc_bus.intr_q.head, wait_entry, xfer_next) {
td = xfer->td_transfer_cache;
if (td == NULL ||
- td->ep_type != UE_BULK ||
- td->did_nak >= DWC_OTG_NAK_MAX) {
+ td->ep_type != UE_BULK) {
continue;
}
@@ -2550,12 +2551,18 @@ static void
dwc_otg_interrupt_poll_locked(struct dwc_otg_softc *sc)
{
struct usb_xfer *xfer;
+ uint32_t count = 0;
uint32_t temp;
uint8_t got_rx_status;
uint8_t x;
repeat:
- /* get all channel interrupts */
+ if (++count == 16) {
+ /* give other interrupts a chance */
+ DPRINTF("Yield\n");
+ return;
+ }
+ /* get all host channel interrupts */
for (x = 0; x != sc->sc_host_ch_max; x++) {
temp = DWC_OTG_READ_4(sc, DOTG_HCINT(x));
if (temp != 0) {
@@ -3244,7 +3251,7 @@ dwc_otg_setup_standard_chain(struct usb_xfer *xfer)
td->tmr_res = 1;
} else {
td->tmr_val = 0;
- td->tmr_res = 0;
+ td->tmr_res = (uint8_t)sc->sc_last_frame_num;
}
break;
case USB_SPEED_HIGH:
@@ -3269,7 +3276,7 @@ dwc_otg_setup_standard_chain(struct usb_xfer *xfer)
td->tmr_res = 1 << usbd_xfer_get_fps_shift(xfer);
} else {
td->tmr_val = 0;
- td->tmr_res = 0;
+ td->tmr_res = (uint8_t)sc->sc_last_frame_num;
}
break;
default:
@@ -3309,8 +3316,6 @@ static void
dwc_otg_start_standard_chain(struct usb_xfer *xfer)
{
struct dwc_otg_softc *sc = DWC_OTG_BUS2SC(xfer->xroot->bus);
- struct usb_xfer_root *xroot;
- struct dwc_otg_td *td;
DPRINTFN(9, "\n");
@@ -3341,24 +3346,6 @@ dwc_otg_start_standard_chain(struct usb_xfer *xfer)
/* enable SOF interrupt, if any */
dwc_otg_enable_sof_irq(sc);
-
- td = xfer->td_transfer_cache;
- if (td->ep_type != UE_BULK)
- goto done;
-
- xroot = xfer->xroot;
-
- /*
- * Optimise the ping-pong effect by waking up other BULK
- * transfers belonging to the same device group:
- */
- TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
- td = xfer->td_transfer_cache;
- if (td == NULL || td->ep_type != UE_BULK || xfer->xroot != xroot)
- continue;
- /* reset NAK counter */
- td->did_nak = 0;
- }
done:
USB_BUS_SPIN_UNLOCK(&sc->sc_bus);
}
diff --git a/sys/dev/usb/controller/dwc_otg.h b/sys/dev/usb/controller/dwc_otg.h
index 1ba0a5e..39c9529 100644
--- a/sys/dev/usb/controller/dwc_otg.h
+++ b/sys/dev/usb/controller/dwc_otg.h
@@ -37,7 +37,6 @@
#define DWC_OTG_TT_SLOT_MAX 8
#define DWC_OTG_SLOT_IDLE_MAX 3
#define DWC_OTG_SLOT_IDLE_MIN 2
-#define DWC_OTG_NAK_MAX 16 /* 16 NAKs = 2 ms */
#ifndef DWC_OTG_TX_MAX_FIFO_SIZE
#define DWC_OTG_TX_MAX_FIFO_SIZE DWC_OTG_MAX_TXN
#endif
@@ -68,7 +67,6 @@ struct dwc_otg_td {
uint8_t errcnt;
uint8_t tmr_res;
uint8_t tmr_val;
- uint8_t did_nak; /* NAK counter */
uint8_t ep_no;
uint8_t ep_type;
uint8_t channel;
@@ -93,6 +91,7 @@ struct dwc_otg_td {
uint8_t set_toggle:1;
uint8_t got_short:1;
uint8_t tt_scheduled:1;
+ uint8_t did_nak:1;
};
struct dwc_otg_tt_info {
diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c
index c0dc79f..b33df36 100644
--- a/sys/dev/usb/serial/uftdi.c
+++ b/sys/dev/usb/serial/uftdi.c
@@ -161,6 +161,7 @@ struct uftdi_softc {
uint8_t sc_hdrlen;
uint8_t sc_msr;
uint8_t sc_lsr;
+ uint8_t sc_bitmode;
};
struct uftdi_param_config {
@@ -196,7 +197,7 @@ static void uftdi_cfg_get_status(struct ucom_softc *, uint8_t *,
uint8_t *);
static int uftdi_reset(struct ucom_softc *, int);
static int uftdi_set_bitmode(struct ucom_softc *, uint8_t, uint8_t);
-static int uftdi_get_bitmode(struct ucom_softc *, uint8_t *);
+static int uftdi_get_bitmode(struct ucom_softc *, uint8_t *, uint8_t *);
static int uftdi_set_latency(struct ucom_softc *, int);
static int uftdi_get_latency(struct ucom_softc *, int *);
static int uftdi_set_event_char(struct ucom_softc *, int);
@@ -1090,6 +1091,7 @@ uftdi_attach(device_t dev)
sc->sc_udev = uaa->device;
sc->sc_dev = dev;
sc->sc_unit = device_get_unit(dev);
+ sc->sc_bitmode = UFTDI_BITMODE_NONE;
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "uftdi", NULL, MTX_DEF);
@@ -1681,6 +1683,7 @@ uftdi_set_bitmode(struct ucom_softc *ucom, uint8_t bitmode, uint8_t iomask)
{
struct uftdi_softc *sc = ucom->sc_parent;
usb_device_request_t req;
+ int rv;
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
req.bRequest = FTDI_SIO_SET_BITMODE;
@@ -1693,11 +1696,15 @@ uftdi_set_bitmode(struct ucom_softc *ucom, uint8_t bitmode, uint8_t iomask)
else
USETW2(req.wValue, (1 << bitmode), iomask);
- return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL));
+ rv = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL);
+ if (rv == USB_ERR_NORMAL_COMPLETION)
+ sc->sc_bitmode = bitmode;
+
+ return (rv);
}
static int
-uftdi_get_bitmode(struct ucom_softc *ucom, uint8_t *iomask)
+uftdi_get_bitmode(struct ucom_softc *ucom, uint8_t *bitmode, uint8_t *iomask)
{
struct uftdi_softc *sc = ucom->sc_parent;
usb_device_request_t req;
@@ -1709,6 +1716,7 @@ uftdi_get_bitmode(struct ucom_softc *ucom, uint8_t *iomask)
USETW(req.wLength, 1);
USETW(req.wValue, 0);
+ *bitmode = sc->sc_bitmode;
return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, iomask));
}
@@ -1791,6 +1799,82 @@ uftdi_set_error_char(struct ucom_softc *ucom, int echar)
}
static int
+uftdi_read_eeprom(struct ucom_softc *ucom, struct uftdi_eeio *eeio)
+{
+ struct uftdi_softc *sc = ucom->sc_parent;
+ usb_device_request_t req;
+ usb_error_t err;
+ uint16_t widx, wlength, woffset;
+
+ /* Offset and length must both be evenly divisible by two. */
+ if ((eeio->offset | eeio->length) & 0x01)
+ return (EINVAL);
+
+ woffset = eeio->offset / 2U;
+ wlength = eeio->length / 2U;
+ for (widx = 0; widx < wlength; widx++) {
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = FTDI_SIO_READ_EEPROM;
+ USETW(req.wIndex, widx + woffset);
+ USETW(req.wLength, 2);
+ USETW(req.wValue, 0);
+ err = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req,
+ &eeio->data[widx]);
+ if (err != USB_ERR_NORMAL_COMPLETION)
+ return (err);
+ }
+ return (USB_ERR_NORMAL_COMPLETION);
+}
+
+static int
+uftdi_write_eeprom(struct ucom_softc *ucom, struct uftdi_eeio *eeio)
+{
+ struct uftdi_softc *sc = ucom->sc_parent;
+ usb_device_request_t req;
+ usb_error_t err;
+ uint16_t widx, wlength, woffset;
+
+ /* Offset and length must both be evenly divisible by two. */
+ if ((eeio->offset | eeio->length) & 0x01)
+ return (EINVAL);
+
+ woffset = eeio->offset / 2U;
+ wlength = eeio->length / 2U;
+ for (widx = 0; widx < wlength; widx++) {
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = FTDI_SIO_WRITE_EEPROM;
+ USETW(req.wIndex, widx + woffset);
+ USETW(req.wLength, 0);
+ USETW(req.wValue, eeio->data[widx]);
+ err = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL);
+ if (err != USB_ERR_NORMAL_COMPLETION)
+ return (err);
+ }
+ return (USB_ERR_NORMAL_COMPLETION);
+}
+
+static int
+uftdi_erase_eeprom(struct ucom_softc *ucom, int confirmation)
+{
+ struct uftdi_softc *sc = ucom->sc_parent;
+ usb_device_request_t req;
+ usb_error_t err;
+
+ /* Small effort to prevent accidental erasure. */
+ if (confirmation != UFTDI_CONFIRM_ERASE)
+ return (EINVAL);
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = FTDI_SIO_ERASE_EEPROM;
+ USETW(req.wIndex, 0);
+ USETW(req.wLength, 0);
+ USETW(req.wValue, 0);
+ err = usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL);
+
+ return (err);
+}
+
+static int
uftdi_ioctl(struct ucom_softc *ucom, uint32_t cmd, caddr_t data,
int flag, struct thread *td)
{
@@ -1815,7 +1899,7 @@ uftdi_ioctl(struct ucom_softc *ucom, uint32_t cmd, caddr_t data,
break;
case UFTDIIOC_GET_BITMODE:
mode = (struct uftdi_bitmode *)data;
- err = uftdi_get_bitmode(ucom, &mode->iomask);
+ err = uftdi_get_bitmode(ucom, &mode->mode, &mode->iomask);
break;
case UFTDIIOC_SET_LATENCY:
err = uftdi_set_latency(ucom, *((int *)data));
@@ -1833,6 +1917,15 @@ uftdi_ioctl(struct ucom_softc *ucom, uint32_t cmd, caddr_t data,
*(int *)data = sc->sc_bcdDevice;
err = 0;
break;
+ case UFTDIIOC_READ_EEPROM:
+ err = uftdi_read_eeprom(ucom, (struct uftdi_eeio *)data);
+ break;
+ case UFTDIIOC_WRITE_EEPROM:
+ err = uftdi_write_eeprom(ucom, (struct uftdi_eeio *)data);
+ break;
+ case UFTDIIOC_ERASE_EEPROM:
+ err = uftdi_erase_eeprom(ucom, *(int *)data);
+ break;
default:
return (ENOIOCTL);
}
diff --git a/sys/dev/usb/serial/uftdi_reg.h b/sys/dev/usb/serial/uftdi_reg.h
index a2d6e38..a1ea325 100644
--- a/sys/dev/usb/serial/uftdi_reg.h
+++ b/sys/dev/usb/serial/uftdi_reg.h
@@ -31,7 +31,10 @@
#define FTDI_SIO_SET_LATENCY 9 /* Set the latency timer */
#define FTDI_SIO_GET_LATENCY 10 /* Read the latency timer */
#define FTDI_SIO_SET_BITMODE 11 /* Set the bit bang I/O mode */
-#define FTDI_SIO_GET_BITMODE 12 /* Read pin states in bit bang mode */
+#define FTDI_SIO_GET_BITMODE 12 /* Read pin states from any mode */
+#define FTDI_SIO_READ_EEPROM 144 /* Read eeprom word */
+#define FTDI_SIO_WRITE_EEPROM 145 /* Write eeprom word */
+#define FTDI_SIO_ERASE_EEPROM 146 /* Erase entire eeprom */
/* Port Identifier Table */
#define FTDI_PIT_DEFAULT 0 /* SIOA */
diff --git a/sys/dev/usb/uftdiio.h b/sys/dev/usb/uftdiio.h
index 0db2f38..b624483 100644
--- a/sys/dev/usb/uftdiio.h
+++ b/sys/dev/usb/uftdiio.h
@@ -43,7 +43,7 @@ enum uftdi_bitmodes
UFTDI_BITMODE_CPU_EMUL = 3,
UFTDI_BITMODE_FAST_SERIAL = 4,
UFTDI_BITMODE_CBUS = 5,
- UFTDI_BITMODE_NONE = 0xff,
+ UFTDI_BITMODE_NONE = 0xff, /* aka UART mode. */
};
/*
@@ -52,8 +52,9 @@ enum uftdi_bitmodes
* iomask = Mask of bits enabled for bitbang output.
*
* For UFTDIIOC_GET_BITMODE:
- * mode = Unused.
- * iomask = Returned snapshot of bitbang pin states at time of call.
+ * mode = Mode most recently set using UFTDIIOC_SET_BITMODE.
+ * iomask = Returned snapshot of DBUS0..DBUS7 pin states at time of call.
+ * Pin states can be read in any mode, not just bitbang modes.
*/
struct uftdi_bitmode
{
@@ -61,6 +62,26 @@ struct uftdi_bitmode
uint8_t iomask;
};
+/*
+ * For UFTDIIOC_READ_EEPROM, UFTDIIOC_WRITE_EEPROM:
+ *
+ * IO is done in 16-bit words at the chip level; offset and length are in bytes,
+ * but must each be evenly divisible by two.
+ *
+ * It is not necessary to erase before writing. For the FT232R device (only)
+ * you must set the latency timer to 0x77 before doing a series of eeprom writes
+ * (and restore it to the prior value when done).
+ */
+struct uftdi_eeio
+{
+ uint16_t offset;
+ uint16_t length;
+ uint16_t data[64];
+};
+
+/* Pass this value to confirm that eeprom erase request is not accidental. */
+#define UFTDI_CONFIRM_ERASE 0x26139108
+
#define UFTDIIOC_RESET_IO _IO('c', 0) /* Reset config, flush fifos.*/
#define UFTDIIOC_RESET_RX _IO('c', 1) /* Flush input fifo. */
#define UFTDIIOC_RESET_TX _IO('c', 2) /* Flush output fifo. */
@@ -71,5 +92,8 @@ struct uftdi_bitmode
#define UFTDIIOC_SET_LATENCY _IOW('c', 7, int) /* 1-255 ms */
#define UFTDIIOC_GET_LATENCY _IOR('c', 8, int)
#define UFTDIIOC_GET_HWREV _IOR('c', 9, int)
+#define UFTDIIOC_READ_EEPROM _IOWR('c', 10, struct uftdi_eeio)
+#define UFTDIIOC_WRITE_EEPROM _IOW('c', 11, struct uftdi_eeio)
+#define UFTDIIOC_ERASE_EEPROM _IOW('c', 12, int)
#endif
diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c
index 89b8c00..463a9bd 100644
--- a/sys/dev/usb/wlan/if_rsu.c
+++ b/sys/dev/usb/wlan/if_rsu.c
@@ -187,15 +187,13 @@ static struct mbuf *
static void rsu_txeof(struct usb_xfer *, struct rsu_data *);
static int rsu_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
-static void rsu_init(void *);
-static void rsu_init_locked(struct rsu_softc *);
+static void rsu_init(struct rsu_softc *);
static int rsu_tx_start(struct rsu_softc *, struct ieee80211_node *,
struct mbuf *, struct rsu_data *);
-static void rsu_start(struct ifnet *);
-static void rsu_start_locked(struct ifnet *);
-static int rsu_ioctl(struct ifnet *, u_long, caddr_t);
-static void rsu_stop(struct ifnet *, int);
-static void rsu_stop_locked(struct ifnet *, int);
+static int rsu_transmit(struct ieee80211com *, struct mbuf *);
+static void rsu_start(struct rsu_softc *);
+static void rsu_parent(struct ieee80211com *);
+static void rsu_stop(struct rsu_softc *);
static void rsu_ms_delay(struct rsu_softc *);
static device_method_t rsu_methods[] = {
@@ -285,8 +283,7 @@ rsu_attach(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct rsu_softc *sc = device_get_softc(self);
- struct ifnet *ifp;
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
int error;
uint8_t iface_index, bands;
@@ -298,6 +295,7 @@ rsu_attach(device_t self)
MTX_DEF);
TIMEOUT_TASK_INIT(taskqueue_thread, &sc->calib_task, 0,
rsu_calib_task, sc);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
/* Allocate Tx/Rx buffers. */
error = rsu_alloc_rx_list(sc);
@@ -333,28 +331,9 @@ rsu_attach(device_t self)
device_printf(self, "could not read ROM\n");
goto fail_rom;
}
- IEEE80211_ADDR_COPY(sc->sc_bssid, &sc->rom[0x12]);
+ IEEE80211_ADDR_COPY(ic->ic_macaddr, &sc->rom[0x12]);
device_printf(self, "MAC/BB RTL8712 cut %d\n", sc->cut);
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(self, "cannot allocate interface\n");
- goto fail_ifalloc;
- }
- ic = ifp->if_l2com;
- ifp->if_softc = sc;
- if_initname(ifp, "rsu", device_get_unit(self));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = rsu_init;
- ifp->if_ioctl = rsu_ioctl;
- ifp->if_start = rsu_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
- ifp->if_capabilities |= IFCAP_RXCSUM;
- ifp->if_capenable |= IFCAP_RXCSUM;
- ifp->if_hwassist = CSUM_TCP;
-
- ic->ic_ifp = ifp;
+
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* Not only, but not used. */
@@ -387,7 +366,7 @@ rsu_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, sc->sc_bssid);
+ ieee80211_ifattach(ic);
ic->ic_raw_xmit = rsu_raw_xmit;
ic->ic_scan_start = rsu_scan_start;
ic->ic_scan_end = rsu_scan_end;
@@ -395,6 +374,8 @@ rsu_attach(device_t self)
ic->ic_vap_create = rsu_vap_create;
ic->ic_vap_delete = rsu_vap_delete;
ic->ic_update_mcast = rsu_update_mcast;
+ ic->ic_parent = rsu_parent;
+ ic->ic_transmit = rsu_transmit;
ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr,
sizeof(sc->sc_txtap), RSU_TX_RADIOTAP_PRESENT,
@@ -406,7 +387,6 @@ rsu_attach(device_t self)
return (0);
-fail_ifalloc:
fail_rom:
usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
fail_usb:
@@ -418,10 +398,11 @@ static int
rsu_detach(device_t self)
{
struct rsu_softc *sc = device_get_softc(self);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
- rsu_stop(ifp, 1);
+ RSU_LOCK(sc);
+ rsu_stop(sc);
+ RSU_UNLOCK(sc);
usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
ieee80211_ifdetach(ic);
@@ -431,7 +412,7 @@ rsu_detach(device_t self)
rsu_free_tx_list(sc);
rsu_free_rx_list(sc);
- if_free(ifp);
+ mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -471,14 +452,11 @@ rsu_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return (NULL);
- uvp = (struct rsu_vap *) malloc(sizeof(struct rsu_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (uvp == NULL)
- return (NULL);
+ uvp = malloc(sizeof(struct rsu_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &uvp->vap;
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
- flags, bssid, mac) != 0) {
+ flags, bssid) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@@ -490,7 +468,7 @@ rsu_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
- ieee80211_media_status);
+ ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return (vap);
@@ -508,9 +486,8 @@ rsu_vap_delete(struct ieee80211vap *vap)
static void
rsu_scan_start(struct ieee80211com *ic)
{
+ struct rsu_softc *sc = ic->ic_softc;
int error;
- struct ifnet *ifp = ic->ic_ifp;
- struct rsu_softc *sc = ifp->if_softc;
/* Scanning is done by the firmware. */
RSU_LOCK(sc);
@@ -676,11 +653,8 @@ rsu_getbuf(struct rsu_softc *sc)
RSU_ASSERT_LOCKED(sc);
bf = _rsu_getbuf(sc);
- if (bf == NULL) {
- struct ifnet *ifp = sc->sc_ifp;
+ if (bf == NULL)
DPRINTF("stop queue\n");
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- }
return (bf);
}
@@ -935,7 +909,7 @@ rsu_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct rsu_vap *uvp = RSU_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct rsu_softc *sc = ic->ic_ifp->if_softc;
+ struct rsu_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
struct ieee80211_rateset *rs;
enum ieee80211_state ostate;
@@ -1033,29 +1007,27 @@ static int
rsu_site_survey(struct rsu_softc *sc, struct ieee80211vap *vap)
{
struct r92s_fw_cmd_sitesurvey cmd;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
memset(&cmd, 0, sizeof(cmd));
- if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->scan_pass == 1)
+ if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->sc_scan_pass == 1)
cmd.active = htole32(1);
cmd.limit = htole32(48);
- if (sc->scan_pass == 1 && vap->iv_des_nssid > 0) {
+ if (sc->sc_scan_pass == 1 && vap->iv_des_nssid > 0) {
/* Do a directed scan for second pass. */
cmd.ssidlen = htole32(vap->iv_des_ssid[0].len);
memcpy(cmd.ssid, vap->iv_des_ssid[0].ssid,
vap->iv_des_ssid[0].len);
}
- DPRINTF("sending site survey command, pass=%d\n", sc->scan_pass);
+ DPRINTF("sending site survey command, pass=%d\n", sc->sc_scan_pass);
return (rsu_fw_cmd(sc, R92S_CMD_SITE_SURVEY, &cmd, sizeof(cmd)));
}
static int
rsu_join_bss(struct rsu_softc *sc, struct ieee80211_node *ni)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ndis_wlan_bssid_ex *bss;
struct ndis_802_11_fixed_ies *fixed;
@@ -1133,8 +1105,7 @@ rsu_disconnect(struct rsu_softc *sc)
static void
rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_channel *c;
struct ndis_wlan_bssid_ex *bss;
@@ -1165,7 +1136,7 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
IEEE80211_FC0_SUBTYPE_BEACON;
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
USETW(wh->i_dur, 0);
- IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
+ IEEE80211_ADDR_COPY(wh->i_addr1, ieee80211broadcastaddr);
IEEE80211_ADDR_COPY(wh->i_addr2, bss->macaddr);
IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr);
*(uint16_t *)wh->i_seq = 0;
@@ -1173,7 +1144,6 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
/* Finalize mbuf. */
m->m_pkthdr.len = m->m_len = pktlen;
- m->m_pkthdr.rcvif = ifp;
/* Fix the channel. */
c = ieee80211_find_channel_byieee(ic,
le32toh(bss->config.dsconfig),
@@ -1191,8 +1161,7 @@ rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
static void
rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni = vap->iv_bss;
struct r92s_event_join_bss *rsp;
@@ -1228,8 +1197,7 @@ rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
static void
rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
DPRINTFN(4, "Rx event code=%d len=%d\n", code, len);
@@ -1240,18 +1208,18 @@ rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
break;
case R92S_EVT_SURVEY_DONE:
DPRINTF("site survey pass %d done, found %d BSS\n",
- sc->scan_pass, le32toh(*(uint32_t *)buf));
+ sc->sc_scan_pass, le32toh(*(uint32_t *)buf));
if (vap->iv_state != IEEE80211_S_SCAN)
break; /* Ignore if not scanning. */
- if (sc->scan_pass == 0 && vap->iv_des_nssid != 0) {
+ if (sc->sc_scan_pass == 0 && vap->iv_des_nssid != 0) {
/* Schedule a directed scan for hidden APs. */
- sc->scan_pass = 1;
+ sc->sc_scan_pass = 1;
RSU_UNLOCK(sc);
ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
RSU_LOCK(sc);
break;
}
- sc->scan_pass = 0;
+ sc->sc_scan_pass = 0;
break;
case R92S_EVT_JOIN_BSS:
if (vap->iv_state == IEEE80211_S_AUTH)
@@ -1274,7 +1242,7 @@ XXX and disrupts the WLAN traffic. Disable for now.
DPRINTF("WPS PBC pushed.\n");
break;
case R92S_EVT_FWDBG:
- if (ifp->if_flags & IFF_DEBUG) {
+ if (vap->iv_ifp->if_flags & IFF_DEBUG) {
buf[60] = '\0';
printf("FWDBG: %s\n", (char *)buf);
}
@@ -1341,8 +1309,7 @@ rsu_get_rssi(struct rsu_softc *sc, int rate, void *physt)
static struct mbuf *
rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct r92s_rx_stat *stat;
uint32_t rxdw0, rxdw3;
@@ -1355,11 +1322,11 @@ rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
rxdw3 = le32toh(stat->rxdw3);
if (__predict_false(rxdw0 & R92S_RXDW0_CRCERR)) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return NULL;
}
if (__predict_false(pktlen < sizeof(*wh) || pktlen > MCLBYTES)) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return NULL;
}
@@ -1377,11 +1344,9 @@ rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m == NULL)) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return NULL;
}
- /* Finalize mbuf. */
- m->m_pkthdr.rcvif = ifp;
/* Hardware does Rx TCP checksum offload. */
if (rxdw3 & R92S_RXDW3_TCPCHKVALID) {
if (__predict_true(rxdw3 & R92S_RXDW3_TCPCHKRPT))
@@ -1479,6 +1444,7 @@ static struct mbuf *
rsu_rxeof(struct usb_xfer *xfer, struct rsu_data *data, int *rssi)
{
struct rsu_softc *sc = data->sc;
+ struct ieee80211com *ic = &sc->sc_ic;
struct r92s_rx_stat *stat;
int len;
@@ -1486,7 +1452,7 @@ rsu_rxeof(struct usb_xfer *xfer, struct rsu_data *data, int *rssi)
if (__predict_false(len < sizeof(*stat))) {
DPRINTF("xfer too short %d\n", len);
- if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
/* Determine if it is a firmware C2H event or an 802.11 frame. */
@@ -1503,8 +1469,7 @@ static void
rsu_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct rsu_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL, *next;
@@ -1564,7 +1529,7 @@ tr_setup:
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
break;
@@ -1572,35 +1537,16 @@ tr_setup:
}
-
static void
rsu_txeof(struct usb_xfer *xfer, struct rsu_data *data)
{
- struct rsu_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct mbuf *m;
-
- RSU_ASSERT_LOCKED(sc);
- /*
- * Do any tx complete callback. Note this must be done before releasing
- * the node reference.
- */
if (data->m) {
- m = data->m;
- if (m->m_flags & M_TXCB) {
- /* XXX status? */
- ieee80211_process_callback(data->ni, m, 0);
- }
- m_freem(m);
+ /* XXX status? */
+ ieee80211_tx_complete(data->ni, data->m, 0);
data->m = NULL;
- }
- if (data->ni) {
- ieee80211_free_node(data->ni);
data->ni = NULL;
}
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
@@ -1608,7 +1554,7 @@ rsu_bulk_tx_callback_sub(struct usb_xfer *xfer, usb_error_t error,
uint8_t which)
{
struct rsu_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
struct rsu_data *data;
RSU_ASSERT_LOCKED(sc);
@@ -1643,7 +1589,7 @@ tr_setup:
rsu_txeof(xfer, data);
STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
}
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(ic->ic_oerrors, 1);
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
@@ -1669,8 +1615,7 @@ static int
rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
struct mbuf *m0, struct rsu_data *data)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_frame *wh;
struct ieee80211_key *k = NULL;
@@ -1772,82 +1717,75 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
return (0);
}
-static void
-rsu_start(struct ifnet *ifp)
+static int
+rsu_transmit(struct ieee80211com *ic, struct mbuf *m)
{
- struct rsu_softc *sc = ifp->if_softc;
-
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return;
+ struct rsu_softc *sc = ic->ic_softc;
+ int error;
RSU_LOCK(sc);
- rsu_start_locked(ifp);
+ if (!sc->sc_running) {
+ RSU_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ RSU_UNLOCK(sc);
+ return (error);
+ }
+ rsu_start(sc);
RSU_UNLOCK(sc);
+
+ return (0);
}
static void
-rsu_start_locked(struct ifnet *ifp)
+rsu_start(struct rsu_softc *sc)
{
- struct rsu_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct rsu_data *bf;
struct mbuf *m;
RSU_ASSERT_LOCKED(sc);
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+ bf = rsu_getbuf(sc);
+ if (bf == NULL) {
+ mbufq_prepend(&sc->sc_snd, m);
break;
+ }
+
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
- bf = rsu_getbuf(sc);
- if (bf == NULL) {
- if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
- m_freem(m);
- ieee80211_free_node(ni);
- } else if (rsu_tx_start(sc, ni, m, bf) != 0) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if (rsu_tx_start(sc, ni, m, bf) != 0) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
ieee80211_free_node(ni);
+ break;
}
}
}
-static int
-rsu_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+rsu_parent(struct ieee80211com *ic)
{
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
-
- switch (cmd) {
- case SIOCSIFFLAGS:
- if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- rsu_init(ifp->if_softc);
- startall = 1;
- }
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- rsu_stop(ifp, 1);
+ struct rsu_softc *sc = ic->ic_softc;
+ int startall = 0;
+
+ RSU_LOCK(sc);
+ if (ic->ic_nrunning > 0) {
+ if (!sc->sc_running) {
+ rsu_init(sc);
+ startall = 1;
}
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
- }
+ } else if (sc->sc_running)
+ rsu_stop(sc);
+ RSU_UNLOCK(sc);
- return (error);
+ if (startall)
+ ieee80211_start_all(ic);
}
/*
@@ -2296,12 +2234,11 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct rsu_softc *sc = ifp->if_softc;
+ struct rsu_softc *sc = ic->ic_softc;
struct rsu_data *bf;
/* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!sc->sc_running) {
m_freem(m);
ieee80211_free_node(ni);
return (ENETDOWN);
@@ -2314,10 +2251,8 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
RSU_UNLOCK(sc);
return (ENOBUFS);
}
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (rsu_tx_start(sc, ni, m, bf) != 0) {
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
RSU_UNLOCK(sc);
return (EIO);
@@ -2328,23 +2263,17 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
}
static void
-rsu_init(void *arg)
+rsu_init(struct rsu_softc *sc)
{
- struct rsu_softc *sc = arg;
-
- RSU_LOCK(sc);
- rsu_init_locked(arg);
- RSU_UNLOCK(sc);
-}
-
-static void
-rsu_init_locked(struct rsu_softc *sc)
-{
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
struct r92s_set_pwr_mode cmd;
int error;
int i;
+ RSU_ASSERT_LOCKED(sc);
+
/* Init host async commands ring. */
sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
@@ -2384,14 +2313,14 @@ rsu_init_locked(struct rsu_softc *sc)
rsu_read_1(sc, 0xfe5c) | 0x80);
/* Set MAC address. */
- rsu_write_region_1(sc, R92S_MACID, IF_LLADDR(ifp),
- IEEE80211_ADDR_LEN);
+ IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr);
+ rsu_write_region_1(sc, R92S_MACID, macaddr, IEEE80211_ADDR_LEN);
/* It really takes 1.5 seconds for the firmware to boot: */
usb_pause_mtx(&sc->sc_mtx, (3 * hz) / 2);
- DPRINTF("setting MAC address to %s\n", ether_sprintf(IF_LLADDR(ifp)));
- error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp),
+ DPRINTF("setting MAC address to %s\n", ether_sprintf(macaddr));
+ error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, macaddr,
IEEE80211_ADDR_LEN);
if (error != 0) {
device_printf(sc->sc_dev, "could not set MAC address\n");
@@ -2427,12 +2356,11 @@ rsu_init_locked(struct rsu_softc *sc)
/* Set default channel. */
ic->ic_bss->ni_chan = ic->ic_ibss_chan;
#endif
- sc->scan_pass = 0;
+ sc->sc_scan_pass = 0;
usbd_transfer_start(sc->sc_xfer[RSU_BULK_RX]);
/* We're ready to go. */
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_running = 1;
return;
fail:
/* Need to stop all failed transfers, if any */
@@ -2441,22 +2369,11 @@ fail:
}
static void
-rsu_stop(struct ifnet *ifp, int disable)
-{
- struct rsu_softc *sc = ifp->if_softc;
-
- RSU_LOCK(sc);
- rsu_stop_locked(ifp, disable);
- RSU_UNLOCK(sc);
-}
-
-static void
-rsu_stop_locked(struct ifnet *ifp, int disable __unused)
+rsu_stop(struct rsu_softc *sc)
{
- struct rsu_softc *sc = ifp->if_softc;
int i;
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_running = 0;
sc->sc_calibrating = 0;
taskqueue_cancel_timeout(taskqueue_thread, &sc->calib_task, NULL);
diff --git a/sys/dev/usb/wlan/if_rsureg.h b/sys/dev/usb/wlan/if_rsureg.h
index db0751d..4e6cd88 100644
--- a/sys/dev/usb/wlan/if_rsureg.h
+++ b/sys/dev/usb/wlan/if_rsureg.h
@@ -726,7 +726,8 @@ struct rsu_vap {
#define RSU_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
struct rsu_softc {
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
int (*sc_newstate)(struct ieee80211com *,
@@ -736,17 +737,17 @@ struct rsu_softc {
const uint8_t *qid2idx;
struct mtx sc_mtx;
+ u_int sc_running:1,
+ sc_calibrating:1,
+ sc_scan_pass:1;
u_int cut;
- int scan_pass;
struct rsu_host_cmd_ring cmdq;
struct rsu_data sc_rx[RSU_RX_LIST_COUNT];
struct rsu_data sc_tx[RSU_TX_LIST_COUNT];
struct rsu_data *fwcmd_data;
uint8_t cmd_seq;
uint8_t rom[128];
- uint8_t sc_bssid[IEEE80211_ADDR_LEN];
struct usb_xfer *sc_xfer[RSU_N_TRANSFER];
- uint8_t sc_calibrating;
STAILQ_HEAD(, rsu_data) sc_rx_active;
STAILQ_HEAD(, rsu_data) sc_rx_inactive;
diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c
index d5142ea..6a558f6 100644
--- a/sys/dev/usb/wlan/if_rum.c
+++ b/sys/dev/usb/wlan/if_rum.c
@@ -175,8 +175,9 @@ static int rum_tx_raw(struct rum_softc *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int rum_tx_data(struct rum_softc *, struct mbuf *,
struct ieee80211_node *);
-static void rum_start(struct ifnet *);
-static int rum_ioctl(struct ifnet *, u_long, caddr_t);
+static int rum_transmit(struct ieee80211com *, struct mbuf *);
+static void rum_start(struct rum_softc *);
+static void rum_parent(struct ieee80211com *);
static void rum_eeprom_read(struct rum_softc *, uint16_t, void *,
int);
static uint32_t rum_read(struct rum_softc *, uint16_t);
@@ -198,7 +199,7 @@ static void rum_set_chan(struct rum_softc *,
struct ieee80211_channel *);
static void rum_enable_tsf_sync(struct rum_softc *);
static void rum_enable_tsf(struct rum_softc *);
-static void rum_update_slot(struct ifnet *);
+static void rum_update_slot(struct rum_softc *);
static void rum_set_bssid(struct rum_softc *, const uint8_t *);
static void rum_set_macaddr(struct rum_softc *, const uint8_t *);
static void rum_update_mcast(struct ieee80211com *);
@@ -207,8 +208,7 @@ static void rum_setpromisc(struct rum_softc *);
static const char *rum_get_rf(int);
static void rum_read_eeprom(struct rum_softc *);
static int rum_bbp_init(struct rum_softc *);
-static void rum_init_locked(struct rum_softc *);
-static void rum_init(void *);
+static void rum_init(struct rum_softc *);
static void rum_stop(struct rum_softc *);
static void rum_load_microcode(struct rum_softc *, const uint8_t *,
size_t);
@@ -425,8 +425,7 @@ rum_attach(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct rum_softc *sc = device_get_softc(self);
- struct ieee80211com *ic;
- struct ifnet *ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
uint8_t iface_index, bands;
uint32_t tmp;
int error, ntries;
@@ -437,6 +436,7 @@ rum_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
MTX_NETWORK_LOCK, MTX_DEF);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = RT2573_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device, &iface_index,
@@ -470,24 +470,6 @@ rum_attach(device_t self)
rum_load_microcode(sc, rt2573_ucode, sizeof(rt2573_ucode));
RUM_UNLOCK(sc);
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "can not if_alloc()\n");
- goto detach;
- }
- ic = ifp->if_l2com;
-
- ifp->if_softc = sc;
- if_initname(ifp, "rum", device_get_unit(sc->sc_dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = rum_init;
- ifp->if_ioctl = rum_ioctl;
- ifp->if_start = rum_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -512,13 +494,14 @@ rum_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, sc->sc_bssid);
+ ieee80211_ifattach(ic);
ic->ic_update_promisc = rum_update_promisc;
ic->ic_raw_xmit = rum_raw_xmit;
ic->ic_scan_start = rum_scan_start;
ic->ic_scan_end = rum_scan_end;
ic->ic_set_channel = rum_set_channel;
-
+ ic->ic_transmit = rum_transmit;
+ ic->ic_parent = rum_parent;
ic->ic_vap_create = rum_vap_create;
ic->ic_vap_delete = rum_vap_delete;
ic->ic_update_mcast = rum_update_mcast;
@@ -543,8 +526,6 @@ static int
rum_detach(device_t self)
{
struct rum_softc *sc = device_get_softc(self);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic;
/* Prevent further ioctls */
RUM_LOCK(sc);
@@ -559,11 +540,9 @@ rum_detach(device_t self)
rum_unsetup_tx_list(sc);
RUM_UNLOCK(sc);
- if (ifp) {
- ic = ifp->if_l2com;
- ieee80211_ifdetach(ic);
- if_free(ifp);
- }
+ if (sc->sc_ic.ic_softc == sc)
+ ieee80211_ifdetach(&sc->sc_ic);
+ mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
}
@@ -595,21 +574,18 @@ rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct rum_softc *sc = ic->ic_ifp->if_softc;
+ struct rum_softc *sc = ic->ic_softc;
struct rum_vap *rvp;
struct ieee80211vap *vap;
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
- rvp = (struct rum_vap *) malloc(sizeof(struct rum_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (rvp == NULL)
- return NULL;
+ rvp = malloc(sizeof(struct rum_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &rvp->vap;
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
- flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(rvp, M_80211_VAP);
return (NULL);
@@ -624,7 +600,8 @@ rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
/* complete setup */
- ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
+ ieee80211_vap_attach(vap, ieee80211_media_change,
+ ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return vap;
}
@@ -648,13 +625,8 @@ rum_tx_free(struct rum_tx_data *data, int txerr)
struct rum_softc *sc = data->sc;
if (data->m != NULL) {
- if (data->m->m_flags & M_TXCB)
- ieee80211_process_callback(data->ni, data->m,
- txerr ? ETIMEDOUT : 0);
- m_freem(data->m);
+ ieee80211_tx_complete(data->ni, data->m, txerr);
data->m = NULL;
-
- ieee80211_free_node(data->ni);
data->ni = NULL;
}
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
@@ -711,7 +683,7 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct rum_vap *rvp = RUM_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct rum_softc *sc = ic->ic_ifp->if_softc;
+ struct rum_softc *sc = ic->ic_softc;
const struct ieee80211_txparam *tp;
enum ieee80211_state ostate;
struct ieee80211_node *ni;
@@ -745,12 +717,12 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_free_node(ni);
return (-1);
}
- rum_update_slot(ic->ic_ifp);
+ rum_update_slot(sc);
rum_enable_mrr(sc);
rum_set_txpreamble(sc);
rum_set_basicrates(sc);
- IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
- rum_set_bssid(sc, sc->sc_bssid);
+ IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
+ rum_set_bssid(sc, ic->ic_macaddr);
}
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
@@ -780,7 +752,6 @@ static void
rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct rum_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap;
struct rum_tx_data *data;
struct mbuf *m;
@@ -799,9 +770,6 @@ rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
rum_tx_free(data, 0);
usbd_xfer_set_priv(xfer, NULL);
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
@@ -844,16 +812,14 @@ tr_setup:
usbd_transfer_submit(xfer);
}
- RUM_UNLOCK(sc);
- rum_start(ifp);
- RUM_LOCK(sc);
+ rum_start(sc);
break;
default: /* Error */
DPRINTFN(11, "transfer error, %s\n",
usbd_errstr(error));
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
data = usbd_xfer_get_priv(xfer);
if (data != NULL) {
rum_tx_free(data, error);
@@ -880,8 +846,7 @@ static void
rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct rum_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
struct usb_page_cache *pc;
@@ -899,7 +864,7 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
if (len < (int)(RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN)) {
DPRINTF("%s: xfer too short %d\n",
device_get_nameunit(sc->sc_dev), len);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
@@ -916,21 +881,20 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
* filled RUM_TXRX_CSR2:
*/
DPRINTFN(5, "PHY or CRC error\n");
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL) {
DPRINTF("could not allocate mbuf\n");
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
usbd_copy_out(pc, RT2573_RX_DESC_SIZE,
mtod(m, uint8_t *), len);
/* finalize mbuf */
- m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
if (ieee80211_radiotap_active(ic)) {
@@ -968,10 +932,8 @@ tr_setup:
(void) ieee80211_input_all(ic, m, rssi,
RT2573_NOISE_FLOOR);
}
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
- !IFQ_IS_EMPTY(&ifp->if_snd))
- rum_start(ifp);
RUM_LOCK(sc);
+ rum_start(sc);
return;
default: /* Error */
@@ -1011,8 +973,7 @@ static void
rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
uint32_t flags, uint16_t xflags, int len, int rate)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t plcp_length;
int remainder;
@@ -1109,8 +1070,7 @@ static int
rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct rum_tx_data *data;
struct ieee80211_frame *wh;
const struct ieee80211_txparam *tp;
@@ -1221,8 +1181,7 @@ static int
rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct rum_tx_data *data;
struct ieee80211_frame *wh;
const struct ieee80211_txparam *tp;
@@ -1299,80 +1258,73 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
return 0;
}
+static int
+rum_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct rum_softc *sc = ic->ic_softc;
+ int error;
+
+ RUM_LOCK(sc);
+ if (!sc->sc_running) {
+ RUM_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ RUM_UNLOCK(sc);
+ return (error);
+ }
+ rum_start(sc);
+ RUM_UNLOCK(sc);
+
+ return (0);
+}
+
static void
-rum_start(struct ifnet *ifp)
+rum_start(struct rum_softc *sc)
{
- struct rum_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
- RUM_LOCK(sc);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- RUM_UNLOCK(sc);
+ RUM_LOCK_ASSERT(sc, MA_OWNED);
+
+ if (!sc->sc_running)
return;
- }
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
- if (sc->tx_nfree < RUM_TX_MINFREE) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
+
+ while (sc->tx_nfree >= RUM_TX_MINFREE &&
+ (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (rum_tx_data(sc, m, ni) != 0) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
break;
}
}
- RUM_UNLOCK(sc);
}
-static int
-rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+rum_parent(struct ieee80211com *ic)
{
- struct rum_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error;
+ struct rum_softc *sc = ic->ic_softc;
int startall = 0;
RUM_LOCK(sc);
- error = sc->sc_detached ? ENXIO : 0;
- RUM_UNLOCK(sc);
- if (error)
- return (error);
-
- switch (cmd) {
- case SIOCSIFFLAGS:
- RUM_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- rum_init_locked(sc);
- startall = 1;
- } else
- rum_setpromisc(sc);
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- rum_stop(sc);
- }
+ if (sc->sc_detached) {
RUM_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
+ return;
}
- return error;
+ if (ic->ic_nrunning > 0) {
+ if (!sc->sc_running) {
+ rum_init(sc);
+ startall = 1;
+ } else
+ rum_setpromisc(sc);
+ } else if (sc->sc_running)
+ rum_stop(sc);
+ RUM_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
static void
@@ -1572,8 +1524,7 @@ rum_select_antenna(struct rum_softc *sc)
static void
rum_enable_mrr(struct rum_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
tmp = rum_read(sc, RT2573_TXRX_CSR4);
@@ -1589,8 +1540,7 @@ rum_enable_mrr(struct rum_softc *sc)
static void
rum_set_txpreamble(struct rum_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
tmp = rum_read(sc, RT2573_TXRX_CSR4);
@@ -1605,8 +1555,7 @@ rum_set_txpreamble(struct rum_softc *sc)
static void
rum_set_basicrates(struct rum_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
/* update basic rate set */
if (ic->ic_curmode == IEEE80211_MODE_11B) {
@@ -1671,8 +1620,7 @@ rum_select_band(struct rum_softc *sc, struct ieee80211_channel *c)
static void
rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
const struct rfprog *rfprog;
uint8_t bbp3, bbp94 = RT2573_BBPR94_DEFAULT;
int8_t power;
@@ -1748,8 +1696,7 @@ rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c)
static void
rum_enable_tsf_sync(struct rum_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
@@ -1784,10 +1731,9 @@ rum_enable_tsf(struct rum_softc *sc)
}
static void
-rum_update_slot(struct ifnet *ifp)
+rum_update_slot(struct rum_softc *sc)
{
- struct rum_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint8_t slottime;
uint32_t tmp;
@@ -1827,18 +1773,17 @@ rum_set_macaddr(struct rum_softc *sc, const uint8_t *addr)
static void
rum_setpromisc(struct rum_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
tmp = rum_read(sc, RT2573_TXRX_CSR0);
tmp &= ~RT2573_DROP_NOT_TO_ME;
- if (!(ifp->if_flags & IFF_PROMISC))
+ if (sc->sc_ic.ic_promisc == 0)
tmp |= RT2573_DROP_NOT_TO_ME;
rum_write(sc, RT2573_TXRX_CSR0, tmp);
- DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
+ DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc > 0 ?
"entering" : "leaving");
}
@@ -1847,10 +1792,11 @@ rum_update_promisc(struct ieee80211com *ic)
{
struct rum_softc *sc = ic->ic_softc;
- if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return;
-
RUM_LOCK(sc);
+ if (!sc->sc_running) {
+ RUM_UNLOCK(sc);
+ return;
+ }
rum_setpromisc(sc);
RUM_UNLOCK(sc);
}
@@ -1887,7 +1833,7 @@ rum_read_eeprom(struct rum_softc *sc)
#endif
/* read MAC address */
- rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_bssid, 6);
+ rum_eeprom_read(sc, RT2573_EEPROM_ADDRESS, sc->sc_ic.ic_macaddr, 6);
rum_eeprom_read(sc, RT2573_EEPROM_ANTENNA, &val, 2);
val = le16toh(val);
@@ -1994,10 +1940,10 @@ rum_bbp_init(struct rum_softc *sc)
}
static void
-rum_init_locked(struct rum_softc *sc)
+rum_init(struct rum_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
usb_error_t error;
int i, ntries;
@@ -2039,7 +1985,7 @@ rum_init_locked(struct rum_softc *sc)
/* clear STA registers */
rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta);
- rum_set_macaddr(sc, IF_LLADDR(ifp));
+ rum_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
/* initialize ASIC */
rum_write(sc, RT2573_MAC_CSR1, 4);
@@ -2058,13 +2004,12 @@ rum_init_locked(struct rum_softc *sc)
RT2573_DROP_ACKCTS;
if (ic->ic_opmode != IEEE80211_M_HOSTAP)
tmp |= RT2573_DROP_TODS;
- if (!(ifp->if_flags & IFF_PROMISC))
+ if (ic->ic_promisc == 0)
tmp |= RT2573_DROP_NOT_TO_ME;
}
rum_write(sc, RT2573_TXRX_CSR0, tmp);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_running = 1;
usbd_xfer_set_stall(sc->sc_xfer[RUM_BULK_WR]);
usbd_transfer_start(sc->sc_xfer[RUM_BULK_RD]);
return;
@@ -2074,29 +2019,13 @@ fail: rum_stop(sc);
}
static void
-rum_init(void *priv)
-{
- struct rum_softc *sc = priv;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
-
- RUM_LOCK(sc);
- rum_init_locked(sc);
- RUM_UNLOCK(sc);
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ieee80211_start_all(ic); /* start all vap's */
-}
-
-static void
rum_stop(struct rum_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
RUM_LOCK_ASSERT(sc, MA_OWNED);
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_running = 0;
RUM_UNLOCK(sc);
@@ -2188,27 +2117,23 @@ static int
rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
- struct ifnet *ifp = ni->ni_ic->ic_ifp;
- struct rum_softc *sc = ifp->if_softc;
+ struct rum_softc *sc = ni->ni_ic->ic_softc;
RUM_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!sc->sc_running) {
RUM_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
}
if (sc->tx_nfree < RUM_TX_MINFREE) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
RUM_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return EIO;
}
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
-
if (params == NULL) {
/*
* Legacy path; interpret frame contents to decide
@@ -2228,7 +2153,6 @@ rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
bad:
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
RUM_UNLOCK(sc);
ieee80211_free_node(ni);
return EIO;
@@ -2262,8 +2186,7 @@ rum_ratectl_task(void *arg, int pending)
struct rum_vap *rvp = arg;
struct ieee80211vap *vap = &rvp->vap;
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct rum_softc *sc = ifp->if_softc;
+ struct rum_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
int ok, fail;
int sum, retrycnt;
@@ -2283,7 +2206,8 @@ rum_ratectl_task(void *arg, int pending)
(void) ieee80211_ratectl_rate(ni, NULL, 0);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */
+ /* count TX retry-fail as Tx errors */
+ if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail);
usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp);
RUM_UNLOCK(sc);
@@ -2292,15 +2216,14 @@ rum_ratectl_task(void *arg, int pending)
static void
rum_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct rum_softc *sc = ifp->if_softc;
+ struct rum_softc *sc = ic->ic_softc;
uint32_t tmp;
RUM_LOCK(sc);
/* abort TSF synchronization */
tmp = rum_read(sc, RT2573_TXRX_CSR9);
rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
- rum_set_bssid(sc, ifp->if_broadcastaddr);
+ rum_set_bssid(sc, ieee80211broadcastaddr);
RUM_UNLOCK(sc);
}
@@ -2308,11 +2231,11 @@ rum_scan_start(struct ieee80211com *ic)
static void
rum_scan_end(struct ieee80211com *ic)
{
- struct rum_softc *sc = ic->ic_ifp->if_softc;
+ struct rum_softc *sc = ic->ic_softc;
RUM_LOCK(sc);
rum_enable_tsf_sync(sc);
- rum_set_bssid(sc, sc->sc_bssid);
+ rum_set_bssid(sc, ic->ic_macaddr);
RUM_UNLOCK(sc);
}
@@ -2320,7 +2243,7 @@ rum_scan_end(struct ieee80211com *ic)
static void
rum_set_channel(struct ieee80211com *ic)
{
- struct rum_softc *sc = ic->ic_ifp->if_softc;
+ struct rum_softc *sc = ic->ic_softc;
RUM_LOCK(sc);
rum_set_chan(sc, ic->ic_curchan);
@@ -2330,8 +2253,7 @@ rum_set_channel(struct ieee80211com *ic)
static int
rum_get_rssi(struct rum_softc *sc, uint8_t raw)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
int lna, agc, rssi;
lna = (raw >> 5) & 0x3;
diff --git a/sys/dev/usb/wlan/if_rumvar.h b/sys/dev/usb/wlan/if_rumvar.h
index 17944aa..35da6d3 100644
--- a/sys/dev/usb/wlan/if_rumvar.h
+++ b/sys/dev/usb/wlan/if_rumvar.h
@@ -85,7 +85,8 @@ enum {
};
struct rum_softc {
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
@@ -105,8 +106,8 @@ struct rum_softc {
uint32_t sta[6];
uint32_t rf_regs[4];
uint8_t txpow[44];
- uint8_t sc_bssid[6];
- uint8_t sc_detached;
+ u_int sc_detached:1,
+ sc_running:1;
struct {
uint8_t val;
diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c
index ac14178..193b9ad 100644
--- a/sys/dev/usb/wlan/if_run.c
+++ b/sys/dev/usb/wlan/if_run.c
@@ -410,8 +410,9 @@ static int run_tx_param(struct run_softc *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int run_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
-static void run_start(struct ifnet *);
-static int run_ioctl(struct ifnet *, u_long, caddr_t);
+static int run_transmit(struct ieee80211com *, struct mbuf *);
+static void run_start(struct run_softc *);
+static void run_parent(struct ieee80211com *);
static void run_iq_calib(struct run_softc *, u_int);
static void run_set_agc(struct run_softc *, uint8_t);
static void run_select_chan_group(struct run_softc *, int);
@@ -457,7 +458,6 @@ static void run_rt3593_rf_setup(struct run_softc *);
static void run_rt5390_rf_setup(struct run_softc *);
static int run_txrx_enable(struct run_softc *);
static void run_adjust_freq_offset(struct run_softc *);
-static void run_init(void *);
static void run_init_locked(struct run_softc *);
static void run_stop(void *);
static void run_delay(struct run_softc *, u_int);
@@ -702,8 +702,7 @@ run_attach(device_t self)
{
struct run_softc *sc = device_get_softc(self);
struct usb_attach_arg *uaa = device_get_ivars(self);
- struct ieee80211com *ic;
- struct ifnet *ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t ver;
int ntries, error;
uint8_t iface_index, bands;
@@ -716,6 +715,7 @@ run_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
MTX_NETWORK_LOCK, MTX_DEF);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = RT2860_IFACE_INDEX;
@@ -754,28 +754,10 @@ run_attach(device_t self)
device_printf(sc->sc_dev,
"MAC/BBP RT%04X (rev 0x%04X), RF %s (MIMO %dT%dR), address %s\n",
sc->mac_ver, sc->mac_rev, run_get_rf(sc->rf_rev),
- sc->ntxchains, sc->nrxchains, ether_sprintf(sc->sc_bssid));
+ sc->ntxchains, sc->nrxchains, ether_sprintf(ic->ic_macaddr));
RUN_UNLOCK(sc);
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "can not if_alloc()\n");
- goto detach;
- }
- ic = ifp->if_l2com;
-
- ifp->if_softc = sc;
- if_initname(ifp, "run", device_get_unit(sc->sc_dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = run_init;
- ifp->if_ioctl = run_ioctl;
- ifp->if_start = run_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -812,7 +794,7 @@ run_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, sc->sc_bssid);
+ ieee80211_ifattach(ic);
ic->ic_scan_start = run_scan_start;
ic->ic_scan_end = run_scan_end;
@@ -824,9 +806,10 @@ run_attach(device_t self)
ic->ic_wme.wme_update = run_wme_update;
ic->ic_raw_xmit = run_raw_xmit;
ic->ic_update_promisc = run_update_promisc;
-
ic->ic_vap_create = run_vap_create;
ic->ic_vap_delete = run_vap_delete;
+ ic->ic_transmit = run_transmit;
+ ic->ic_parent = run_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -852,8 +835,7 @@ static int
run_detach(device_t self)
{
struct run_softc *sc = device_get_softc(self);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
int i;
RUN_LOCK(sc);
@@ -872,16 +854,15 @@ run_detach(device_t self)
run_unsetup_tx_list(sc, &sc->sc_epq[i]);
RUN_UNLOCK(sc);
- if (ifp) {
- ic = ifp->if_l2com;
+ if (sc->sc_ic.ic_softc == sc) {
/* drain tasks */
usb_callout_drain(&sc->ratectl_ch);
ieee80211_draintask(ic, &sc->cmdq_task);
ieee80211_draintask(ic, &sc->ratectl_task);
ieee80211_ifdetach(ic);
- if_free(ifp);
}
+ mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -893,14 +874,13 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = ic->ic_ifp;
- struct run_softc *sc = ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
struct run_vap *rvp;
struct ieee80211vap *vap;
int i;
if (sc->rvp_cnt >= RUN_VAP_MAX) {
- if_printf(ifp, "number of VAPs maxed out\n");
+ device_printf(sc->sc_dev, "number of VAPs maxed out\n");
return (NULL);
}
@@ -926,23 +906,21 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
break;
}
if (vap == NULL) {
- if_printf(ifp, "wds only supported in ap mode\n");
+ device_printf(sc->sc_dev,
+ "wds only supported in ap mode\n");
return (NULL);
}
break;
default:
- if_printf(ifp, "unknown opmode %d\n", opmode);
+ device_printf(sc->sc_dev, "unknown opmode %d\n", opmode);
return (NULL);
}
- rvp = (struct run_vap *) malloc(sizeof(struct run_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (rvp == NULL)
- return (NULL);
+ rvp = malloc(sizeof(struct run_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &rvp->vap;
- if (ieee80211_vap_setup(ic, vap, name, unit,
- opmode, flags, bssid, mac) != 0) {
+ if (ieee80211_vap_setup(ic, vap, name, unit, opmode, flags,
+ bssid) != 0) {
/* out of memory */
free(rvp, M_80211_VAP);
return (NULL);
@@ -969,7 +947,8 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
/* complete setup */
- ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status);
+ ieee80211_vap_attach(vap, run_media_change, ieee80211_media_status,
+ mac);
/* make sure id is always unique */
for (i = 0; i < RUN_VAP_MAX; i++) {
@@ -995,7 +974,6 @@ static void
run_vap_delete(struct ieee80211vap *vap)
{
struct run_vap *rvp = RUN_VAP(vap);
- struct ifnet *ifp;
struct ieee80211com *ic;
struct run_softc *sc;
uint8_t rvp_id;
@@ -1004,9 +982,7 @@ run_vap_delete(struct ieee80211vap *vap)
return;
ic = vap->iv_ic;
- ifp = ic->ic_ifp;
-
- sc = ifp->if_softc;
+ sc = ic->ic_softc;
RUN_LOCK(sc);
@@ -1740,6 +1716,7 @@ run_get_txpower(struct run_softc *sc)
static int
run_read_eeprom(struct run_softc *sc)
{
+ struct ieee80211com *ic = &sc->sc_ic;
int8_t delta_2ghz, delta_5ghz;
uint32_t tmp;
uint16_t val;
@@ -1760,14 +1737,14 @@ run_read_eeprom(struct run_softc *sc)
/* read MAC address */
run_srom_read(sc, RT2860_EEPROM_MAC01, &val);
- sc->sc_bssid[0] = val & 0xff;
- sc->sc_bssid[1] = val >> 8;
+ ic->ic_macaddr[0] = val & 0xff;
+ ic->ic_macaddr[1] = val >> 8;
run_srom_read(sc, RT2860_EEPROM_MAC23, &val);
- sc->sc_bssid[2] = val & 0xff;
- sc->sc_bssid[3] = val >> 8;
+ ic->ic_macaddr[2] = val & 0xff;
+ ic->ic_macaddr[3] = val >> 8;
run_srom_read(sc, RT2860_EEPROM_MAC45, &val);
- sc->sc_bssid[4] = val & 0xff;
- sc->sc_bssid[5] = val >> 8;
+ ic->ic_macaddr[4] = val & 0xff;
+ ic->ic_macaddr[5] = val >> 8;
if (sc->mac_ver < 0x3593) {
/* read vender BBP settings */
@@ -2002,7 +1979,7 @@ run_media_change(struct ifnet *ifp)
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
const struct ieee80211_txparam *tp;
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
uint8_t rate, ridx;
int error;
@@ -2033,7 +2010,7 @@ run_media_change(struct ifnet *ifp)
#if 0
if ((ifp->if_flags & IFF_UP) &&
- (ifp->if_drv_flags & IFF_DRV_RUNNING)){
+ (ifp->if_drv_flags & RUN_RUNNING)){
run_init_locked(sc);
}
#endif
@@ -2048,7 +2025,7 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
const struct ieee80211_txparam *tp;
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
struct run_vap *rvp = RUN_VAP(vap);
enum ieee80211_state ostate;
uint32_t sta[3];
@@ -2144,7 +2121,7 @@ run_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
run_set_txpreamble(sc);
run_set_basicrates(sc);
ni = ieee80211_ref_node(vap->iv_bss);
- IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
+ IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
run_set_bssid(sc, ni->ni_bssid);
ieee80211_free_node(ni);
run_enable_tsf_sync(sc);
@@ -2181,7 +2158,7 @@ static void
run_wme_update_cb(void *arg)
{
struct ieee80211com *ic = arg;
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
struct ieee80211_wme_state *wmesp = &ic->ic_wme;
int aci, error = 0;
@@ -2234,7 +2211,7 @@ err:
static int
run_wme_update(struct ieee80211com *ic)
{
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
/* sometime called wothout lock */
if (mtx_owned(&ic->ic_comlock.mtx)) {
@@ -2277,7 +2254,7 @@ run_key_set_cb(void *arg)
struct ieee80211vap *vap = cmdq->arg1;
struct ieee80211_key *k = cmdq->k;
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
uint32_t attr;
uint16_t base, associd;
@@ -2399,7 +2376,7 @@ run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k,
const uint8_t mac[IEEE80211_ADDR_LEN])
{
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
uint32_t i;
i = RUN_CMDQ_GET(&sc->cmdq_store);
@@ -2467,7 +2444,7 @@ static int
run_key_delete(struct ieee80211vap *vap, struct ieee80211_key *k)
{
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
struct ieee80211_key *k0;
uint32_t i;
@@ -2498,7 +2475,7 @@ run_ratectl_to(void *arg)
struct run_softc *sc = arg;
/* do it in a process context, so it can go sleep */
- ieee80211_runtask(sc->sc_ifp->if_l2com, &sc->ratectl_task);
+ ieee80211_runtask(&sc->sc_ic, &sc->ratectl_task);
/* next timeout will be rescheduled in the callback task */
}
@@ -2507,7 +2484,7 @@ static void
run_ratectl_cb(void *arg, int pending)
{
struct run_softc *sc = arg;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
if (vap == NULL)
@@ -2540,7 +2517,6 @@ static void
run_drain_fifo(void *arg)
{
struct run_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
uint32_t stat;
uint16_t (*wstat)[3];
uint8_t wcid, mcs, pid;
@@ -2577,7 +2553,7 @@ run_drain_fifo(void *arg)
if (stat & RT2860_TXQ_OK)
(*wstat)[RUN_SUCCESS]++;
else
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
/*
* Check if there were retries, ie if the Tx success rate is
* different from the requested rate. Note that it works only
@@ -2600,8 +2576,6 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
{
struct run_softc *sc = arg;
struct ieee80211vap *vap = ni->ni_vap;
- struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
struct run_node *rn = (void *)ni;
union run_stats sta[2];
uint16_t (*wstat)[3];
@@ -2623,7 +2597,8 @@ run_iter_func(void *arg, struct ieee80211_node *ni)
goto fail;
/* count failed TX as errors */
- if_inc_counter(ifp, IFCOUNTER_OERRORS, le16toh(sta[0].error.fail));
+ if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS,
+ le16toh(sta[0].error.fail));
retrycnt = le16toh(sta[1].tx.retry);
success = le16toh(sta[1].tx.success);
@@ -2661,7 +2636,7 @@ run_newassoc_cb(void *arg)
{
struct run_cmdq *cmdq = arg;
struct ieee80211_node *ni = cmdq->arg1;
- struct run_softc *sc = ni->ni_vap->iv_ic->ic_ifp->if_softc;
+ struct run_softc *sc = ni->ni_vap->iv_ic->ic_softc;
uint8_t wcid = cmdq->wcid;
RUN_LOCK_ASSERT(sc, MA_OWNED);
@@ -2679,7 +2654,7 @@ run_newassoc(struct ieee80211_node *ni, int isnew)
struct ieee80211_rateset *rs = &ni->ni_rates;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
uint8_t rate;
uint8_t ridx;
uint8_t wcid;
@@ -2769,8 +2744,7 @@ run_maxrssi_chain(struct run_softc *sc, const struct rt2860_rxwi *rxwi)
static void
run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct rt2870_rxd *rxd;
@@ -2789,7 +2763,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
rxwisize += sizeof(uint32_t);
if (__predict_false(len > dmalen)) {
m_freem(m);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
DPRINTF("bad RXWI length %u > %u\n", len, dmalen);
return;
}
@@ -2799,7 +2773,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
if (__predict_false(flags & (RT2860_RX_CRCERR | RT2860_RX_ICVERR))) {
m_freem(m);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
DPRINTF("%s error.\n", (flags & RT2860_RX_CRCERR)?"CRC":"ICV");
return;
}
@@ -2828,7 +2802,7 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
ieee80211_notify_michael_failure(ni->ni_vap, wh,
rxwi->keyidx);
m_freem(m);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
DPRINTF("MIC error. Someone is lying.\n");
return;
}
@@ -2837,7 +2811,6 @@ run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
rssi = rxwi->rssi[ant];
nf = run_rssi2dbm(sc, rssi, ant);
- m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = len;
if (ni != NULL) {
@@ -2890,7 +2863,7 @@ static void
run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct run_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *m = NULL;
struct mbuf *m0;
uint32_t dmalen;
@@ -2928,7 +2901,7 @@ tr_setup:
}
if (sc->rx_m == NULL) {
DPRINTF("could not allocate mbuf - idle with stall\n");
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
usbd_xfer_set_stall(xfer);
usbd_xfer_set_frames(xfer, 0);
} else {
@@ -2948,12 +2921,9 @@ tr_setup:
if (error != USB_ERR_CANCELLED) {
/* try to clear stall first */
usbd_xfer_set_stall(xfer);
-
if (error == USB_ERR_TIMEOUT)
device_printf(sc->sc_dev, "device timeout\n");
-
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
-
+ counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
if (sc->rx_m != NULL) {
@@ -3001,7 +2971,7 @@ tr_setup:
m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (__predict_false(m0 == NULL)) {
DPRINTF("could not allocate mbuf\n");
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
break;
}
m_copydata(m, 4 /* skip 32-bit DMA-len header */,
@@ -3048,8 +3018,7 @@ static void
run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
{
struct run_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct run_tx_data *data;
struct ieee80211vap *vap = NULL;
struct usb_page_cache *pc;
@@ -3067,14 +3036,9 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index)
"bytes @ index %d\n", actlen, index);
data = usbd_xfer_get_priv(xfer);
-
run_tx_free(pq, data, 0);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
usbd_xfer_set_priv(xfer, NULL);
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
-
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
@@ -3091,11 +3055,7 @@ tr_setup:
size + 3 + 8) > RUN_MAX_TXSZ) {
DPRINTF("data overflow, %u bytes\n",
m->m_pkthdr.len);
-
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
-
run_tx_free(pq, data, 1);
-
goto tr_setup;
}
@@ -3132,12 +3092,8 @@ tr_setup:
usbd_xfer_set_frame_len(xfer, 0, size);
usbd_xfer_set_priv(xfer, data);
-
usbd_transfer_submit(xfer);
-
- RUN_UNLOCK(sc);
- run_start(ifp);
- RUN_LOCK(sc);
+ run_start(sc);
break;
@@ -3147,14 +3103,13 @@ tr_setup:
data = usbd_xfer_get_priv(xfer);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
-
if (data != NULL) {
if(data->ni != NULL)
vap = data->ni->ni_vap;
run_tx_free(pq, data, error);
usbd_xfer_set_priv(xfer, NULL);
}
+
if (vap == NULL)
vap = TAILQ_FIRST(&ic->ic_vaps);
@@ -3220,7 +3175,7 @@ static void
run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data)
{
struct mbuf *m = data->m;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = data->ni->ni_vap;
struct ieee80211_frame *wh;
struct rt2870_txd *txd;
@@ -3283,7 +3238,7 @@ run_set_tx_desc(struct run_softc *sc, struct run_tx_data *data)
static int
run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_frame *wh;
struct ieee80211_channel *chan;
@@ -3451,8 +3406,7 @@ run_tx(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
static int
run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct run_node *rn = (void *)ni;
struct run_tx_data *data;
struct ieee80211_frame *wh;
@@ -3483,11 +3437,9 @@ run_tx_mgt(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
USETW(wh->i_dur, dur);
}
- if (sc->sc_epq[0].tx_nfree == 0) {
+ if (sc->sc_epq[0].tx_nfree == 0)
/* let caller free mbuf */
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
return (EIO);
- }
data = STAILQ_FIRST(&sc->sc_epq[0].tx_fh);
STAILQ_REMOVE_HEAD(&sc->sc_epq[0].tx_fh, next);
sc->sc_epq[0].tx_nfree--;
@@ -3555,11 +3507,9 @@ run_sendprot(struct run_softc *sc,
wflags = RT2860_TX_FRAG;
/* check that there are free slots before allocating the mbuf */
- if (sc->sc_epq[0].tx_nfree == 0) {
+ if (sc->sc_epq[0].tx_nfree == 0)
/* let caller free mbuf */
- sc->sc_ifp->if_drv_flags |= IFF_DRV_OACTIVE;
return (ENOBUFS);
- }
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
@@ -3570,7 +3520,7 @@ run_sendprot(struct run_softc *sc,
mprot = ieee80211_alloc_cts(ic, ni->ni_vap->iv_myaddr, dur);
}
if (mprot == NULL) {
- if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
DPRINTF("could not allocate mbuf\n");
return (ENOBUFS);
}
@@ -3652,7 +3602,6 @@ run_tx_param(struct run_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
if (sc->sc_epq[0].tx_nfree == 0) {
/* let caller free mbuf */
- sc->sc_ifp->if_drv_flags |= IFF_DRV_OACTIVE;
DPRINTF("sending raw frame, but tx ring is full\n");
return (EIO);
}
@@ -3691,36 +3640,31 @@ static int
run_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
- struct ifnet *ifp = ni->ni_ic->ic_ifp;
- struct run_softc *sc = ifp->if_softc;
+ struct run_softc *sc = ni->ni_ic->ic_softc;
int error = 0;
RUN_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- error = ENETDOWN;
+ if (!(sc->sc_flags & RUN_RUNNING)) {
+ error = ENETDOWN;
goto done;
}
if (params == NULL) {
/* tx mgt packet */
if ((error = run_tx_mgt(sc, m, ni)) != 0) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
DPRINTF("mgt tx failed\n");
goto done;
}
} else {
/* tx raw packet with param */
if ((error = run_tx_param(sc, m, ni, params)) != 0) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
DPRINTF("tx with param failed\n");
goto done;
}
}
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
-
done:
RUN_UNLOCK(sc);
@@ -3733,83 +3677,71 @@ done:
return (error);
}
+static int
+run_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct run_softc *sc = ic->ic_softc;
+ int error;
+
+ RUN_LOCK(sc);
+ if ((sc->sc_flags & RUN_RUNNING) == 0) {
+ RUN_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ RUN_UNLOCK(sc);
+ return (error);
+ }
+ run_start(sc);
+ RUN_UNLOCK(sc);
+
+ return (0);
+}
+
static void
-run_start(struct ifnet *ifp)
+run_start(struct run_softc *sc)
{
- struct run_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
- RUN_LOCK(sc);
+ RUN_LOCK_ASSERT(sc, MA_OWNED);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- RUN_UNLOCK(sc);
+ if ((sc->sc_flags & RUN_RUNNING) == 0)
return;
- }
-
- for (;;) {
- /* send data frames */
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (run_tx(sc, m, ni) != 0) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ mbufq_prepend(&sc->sc_snd, m);
break;
}
}
-
- RUN_UNLOCK(sc);
}
-static int
-run_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+run_parent(struct ieee80211com *ic)
{
- struct run_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
+ struct run_softc *sc = ic->ic_softc;
int startall = 0;
- int error;
RUN_LOCK(sc);
- error = sc->sc_detached ? ENXIO : 0;
- RUN_UNLOCK(sc);
- if (error)
- return (error);
-
- switch (cmd) {
- case SIOCSIFFLAGS:
- RUN_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)){
- startall = 1;
- run_init_locked(sc);
- } else
- run_update_promisc_locked(sc);
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
- (ic->ic_nrunning == 0 || sc->rvp_cnt <= 1)) {
- run_stop(sc);
- }
- }
+ if (sc->sc_detached) {
RUN_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
+ return;
}
- return (error);
+ if (ic->ic_nrunning > 0) {
+ if (!(sc->sc_flags & RUN_RUNNING)) {
+ startall = 1;
+ run_init_locked(sc);
+ } else
+ run_update_promisc_locked(sc);
+ } else if ((sc->sc_flags & RUN_RUNNING) && sc->rvp_cnt <= 1)
+ run_stop(sc);
+ RUN_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
static void
@@ -4796,7 +4728,7 @@ run_set_rx_antenna(struct run_softc *sc, int aux)
static int
run_set_chan(struct run_softc *sc, struct ieee80211_channel *c)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
u_int chan, group;
chan = ieee80211_chan2ieee(ic, c);
@@ -4841,7 +4773,7 @@ run_set_chan(struct run_softc *sc, struct ieee80211_channel *c)
static void
run_set_channel(struct ieee80211com *ic)
{
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
RUN_LOCK(sc);
run_set_chan(sc, ic->ic_curchan);
@@ -4853,7 +4785,7 @@ run_set_channel(struct ieee80211com *ic)
static void
run_scan_start(struct ieee80211com *ic)
{
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
uint32_t tmp;
RUN_LOCK(sc);
@@ -4863,7 +4795,7 @@ run_scan_start(struct ieee80211com *ic)
run_write(sc, RT2860_BCN_TIME_CFG,
tmp & ~(RT2860_BCN_TX_EN | RT2860_TSF_TIMER_EN |
RT2860_TBTT_TIMER_EN));
- run_set_bssid(sc, sc->sc_ifp->if_broadcastaddr);
+ run_set_bssid(sc, ieee80211broadcastaddr);
RUN_UNLOCK(sc);
@@ -4873,13 +4805,13 @@ run_scan_start(struct ieee80211com *ic)
static void
run_scan_end(struct ieee80211com *ic)
{
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
RUN_LOCK(sc);
run_enable_tsf_sync(sc);
/* XXX keep local copy */
- run_set_bssid(sc, sc->sc_bssid);
+ run_set_bssid(sc, ic->ic_macaddr);
RUN_UNLOCK(sc);
@@ -4894,7 +4826,7 @@ static void
run_update_beacon(struct ieee80211vap *vap, int item)
{
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
struct run_vap *rvp = RUN_VAP(vap);
int mcast = 0;
uint32_t i;
@@ -4939,7 +4871,7 @@ run_update_beacon_cb(void *arg)
struct ieee80211vap *vap = arg;
struct run_vap *rvp = RUN_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
struct rt2860_txwi txwi;
struct mbuf *m;
uint16_t txwisize;
@@ -4987,7 +4919,7 @@ run_update_beacon_cb(void *arg)
static void
run_updateprot(struct ieee80211com *ic)
{
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
uint32_t i;
i = RUN_CMDQ_GET(&sc->cmdq_store);
@@ -5001,7 +4933,7 @@ static void
run_updateprot_cb(void *arg)
{
struct ieee80211com *ic = arg;
- struct run_softc *sc = ic->ic_ifp->if_softc;
+ struct run_softc *sc = ic->ic_softc;
uint32_t tmp;
tmp = RT2860_RTSTH_EN | RT2860_PROT_NAV_SHORT | RT2860_TXOP_ALLOW_ALL;
@@ -5025,7 +4957,7 @@ static void
run_usb_timeout_cb(void *arg)
{
struct ieee80211vap *vap = arg;
- struct run_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct run_softc *sc = vap->iv_ic->ic_softc;
RUN_LOCK_ASSERT(sc, MA_OWNED);
@@ -5071,12 +5003,12 @@ run_update_promisc_locked(struct run_softc *sc)
run_read(sc, RT2860_RX_FILTR_CFG, &tmp);
tmp |= RT2860_DROP_UC_NOME;
- if (sc->sc_ifp->if_flags & IFF_PROMISC)
+ if (sc->sc_ic.ic_promisc > 0)
tmp &= ~RT2860_DROP_UC_NOME;
run_write(sc, RT2860_RX_FILTR_CFG, tmp);
- DPRINTF("%s promiscuous mode\n", (sc->sc_ifp->if_flags & IFF_PROMISC) ?
+ DPRINTF("%s promiscuous mode\n", (sc->sc_ic.ic_promisc > 0) ?
"entering" : "leaving");
}
@@ -5085,7 +5017,7 @@ run_update_promisc(struct ieee80211com *ic)
{
struct run_softc *sc = ic->ic_softc;
- if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ if ((sc->sc_flags & RUN_RUNNING) == 0)
return;
RUN_LOCK(sc);
@@ -5096,7 +5028,7 @@ run_update_promisc(struct ieee80211com *ic)
static void
run_enable_tsf_sync(struct run_softc *sc)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
@@ -5161,7 +5093,7 @@ run_enable_mrr(struct run_softc *sc)
static void
run_set_txpreamble(struct run_softc *sc)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
run_read(sc, RT2860_AUTO_RSP_CFG, &tmp);
@@ -5175,7 +5107,7 @@ run_set_txpreamble(struct run_softc *sc)
static void
run_set_basicrates(struct run_softc *sc)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
/* set basic rates mask */
if (ic->ic_curmode == IEEE80211_MODE_11B)
@@ -5220,7 +5152,7 @@ run_updateslot(struct ieee80211com *ic)
i = RUN_CMDQ_GET(&sc->cmdq_store);
DPRINTF("cmdq_store=%d\n", i);
sc->cmdq[i].func = run_updateslot_cb;
- sc->cmdq[i].arg0 = ic->ic_ifp;
+ sc->cmdq[i].arg0 = ic;
ieee80211_runtask(ic, &sc->cmdq_task);
return;
@@ -5230,9 +5162,8 @@ run_updateslot(struct ieee80211com *ic)
static void
run_updateslot_cb(void *arg)
{
- struct ifnet *ifp = arg;
- struct run_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = arg;
+ struct run_softc *sc = ic->ic_softc;
uint32_t tmp;
run_read(sc, RT2860_BKOFF_SLOT_CFG, &tmp);
@@ -5244,15 +5175,12 @@ run_updateslot_cb(void *arg)
static void
run_update_mcast(struct ieee80211com *ic)
{
-
- /* h/w filter supports getting everything or nothing */
- ic->ic_ifp->if_flags |= IFF_ALLMULTI;
}
static int8_t
run_rssi2dbm(struct run_softc *sc, uint8_t rssi, uint8_t rxchain)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_channel *c = ic->ic_curchan;
int delta;
@@ -5902,7 +5830,7 @@ run_rt5390_rf_setup(struct run_softc *sc)
static int
run_txrx_enable(struct run_softc *sc)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t tmp;
int error, ntries;
@@ -5962,8 +5890,8 @@ run_adjust_freq_offset(struct run_softc *sc)
static void
run_init_locked(struct run_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
uint8_t bbp1, bbp3;
int i;
@@ -5993,7 +5921,7 @@ run_init_locked(struct run_softc *sc)
for (i = 0; i != RUN_EP_QUEUES; i++)
run_setup_tx_list(sc, &sc->sc_epq[i]);
- run_set_macaddr(sc, IF_LLADDR(ifp));
+ run_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
for (ntries = 0; ntries < 100; ntries++) {
if (run_read(sc, RT2860_WPDMA_GLO_CFG, &tmp) != 0)
@@ -6166,8 +6094,7 @@ run_init_locked(struct run_softc *sc)
/* turn radio LED on */
run_set_leds(sc, RT2860_LED_RADIO);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_flags |= RUN_RUNNING;
sc->cmdq_run = RUN_CMDQ_GO;
for (i = 0; i != RUN_N_XFER; i++)
@@ -6185,35 +6112,19 @@ fail:
}
static void
-run_init(void *arg)
-{
- struct run_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
-
- RUN_LOCK(sc);
- run_init_locked(sc);
- RUN_UNLOCK(sc);
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ieee80211_start_all(ic);
-}
-
-static void
run_stop(void *arg)
{
struct run_softc *sc = (struct run_softc *)arg;
- struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
int i;
int ntries;
RUN_LOCK_ASSERT(sc, MA_OWNED);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->sc_flags & RUN_RUNNING)
run_set_leds(sc, 0); /* turn all LEDs off */
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_flags &= ~RUN_RUNNING;
sc->ratectl_run = RUN_RATECTL_OFF;
sc->cmdq_run = sc->cmdq_key_set;
diff --git a/sys/dev/usb/wlan/if_runvar.h b/sys/dev/usb/wlan/if_runvar.h
index ad0fc30..b8cb12f 100644
--- a/sys/dev/usb/wlan/if_runvar.h
+++ b/sys/dev/usb/wlan/if_runvar.h
@@ -151,13 +151,16 @@ struct run_endpoint_queue {
};
struct run_softc {
+ struct mtx sc_mtx;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
- struct ifnet *sc_ifp;
int sc_need_fwload;
int sc_flags;
#define RUN_FLAG_FWLOAD_NEEDED 0x01
+#define RUN_RUNNING 0x02
uint16_t wcid_stats[RT2870_WCID_MAX + 1][3];
#define RUN_TXCNT 0
@@ -203,10 +206,6 @@ struct run_softc {
uint32_t txpow40mhz_2ghz[5];
uint32_t txpow40mhz_5ghz[5];
- uint8_t sc_bssid[6];
-
- struct mtx sc_mtx;
-
struct run_endpoint_queue sc_epq[RUN_EP_QUEUES];
struct task ratectl_task;
diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c
index fca9e39..04e09204 100644
--- a/sys/dev/usb/wlan/if_uath.c
+++ b/sys/dev/usb/wlan/if_uath.c
@@ -279,12 +279,11 @@ static int uath_alloc_rx_data_list(struct uath_softc *);
static int uath_alloc_tx_data_list(struct uath_softc *);
static void uath_free_rx_data_list(struct uath_softc *);
static void uath_free_tx_data_list(struct uath_softc *);
-static int uath_init_locked(void *);
-static void uath_init(void *);
-static void uath_stop_locked(struct ifnet *);
-static void uath_stop(struct ifnet *);
-static int uath_ioctl(struct ifnet *, u_long, caddr_t);
-static void uath_start(struct ifnet *);
+static int uath_init(struct uath_softc *);
+static void uath_stop(struct uath_softc *);
+static void uath_parent(struct ieee80211com *);
+static int uath_transmit(struct ieee80211com *, struct mbuf *);
+static void uath_start(struct uath_softc *);
static int uath_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void uath_scan_start(struct ieee80211com *);
@@ -336,11 +335,9 @@ uath_attach(device_t dev)
{
struct uath_softc *sc = device_get_softc(dev);
struct usb_attach_arg *uaa = device_get_ivars(dev);
- struct ieee80211com *ic;
- struct ifnet *ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
uint8_t bands, iface_index = UATH_IFACE_INDEX; /* XXX */
usb_error_t error;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
sc->sc_udev = uaa->device;
@@ -356,6 +353,7 @@ uath_attach(device_t dev)
MTX_DEF);
callout_init(&sc->stat_ch, 0);
callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx);
@@ -387,31 +385,24 @@ uath_attach(device_t dev)
error = uath_host_available(sc);
if (error != 0) {
device_printf(sc->sc_dev, "could not initialize adapter\n");
- goto fail3;
+ goto fail2;
}
error = uath_get_devcap(sc);
if (error != 0) {
device_printf(sc->sc_dev,
"could not get device capabilities\n");
- goto fail3;
+ goto fail2;
}
UATH_UNLOCK(sc);
/* Create device sysctl node. */
uath_sysctl_node(sc);
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "can not allocate ifnet\n");
- error = ENXIO;
- goto fail2;
- }
-
UATH_LOCK(sc);
- error = uath_get_devstatus(sc, macaddr);
+ error = uath_get_devstatus(sc, ic->ic_macaddr);
if (error != 0) {
device_printf(sc->sc_dev, "could not get device status\n");
- goto fail4;
+ goto fail2;
}
/*
@@ -420,28 +411,15 @@ uath_attach(device_t dev)
error = uath_alloc_rx_data_list(sc);
if (error != 0) {
device_printf(sc->sc_dev, "could not allocate Rx data list\n");
- goto fail4;
+ goto fail2;
}
error = uath_alloc_tx_data_list(sc);
if (error != 0) {
device_printf(sc->sc_dev, "could not allocate Tx data list\n");
- goto fail4;
+ goto fail2;
}
UATH_UNLOCK(sc);
- ifp->if_softc = sc;
- if_initname(ifp, "uath", device_get_unit(sc->sc_dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = uath_init;
- ifp->if_ioctl = uath_ioctl;
- ifp->if_start = uath_start;
- /* XXX UATH_TX_DATA_LIST_COUNT */
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic = ifp->if_l2com;
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -469,16 +447,17 @@ uath_attach(device_t dev)
/* XXX turbo */
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, macaddr);
+ ieee80211_ifattach(ic);
ic->ic_raw_xmit = uath_raw_xmit;
ic->ic_scan_start = uath_scan_start;
ic->ic_scan_end = uath_scan_end;
ic->ic_set_channel = uath_set_channel;
-
ic->ic_vap_create = uath_vap_create;
ic->ic_vap_delete = uath_vap_delete;
ic->ic_update_mcast = uath_update_mcast;
ic->ic_update_promisc = uath_update_promisc;
+ ic->ic_transmit = uath_transmit;
+ ic->ic_parent = uath_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -491,9 +470,8 @@ uath_attach(device_t dev)
return (0);
-fail4: if_free(ifp);
-fail3: UATH_UNLOCK(sc);
-fail2: uath_free_cmd_list(sc, sc->sc_cmd);
+fail2: UATH_UNLOCK(sc);
+ uath_free_cmd_list(sc, sc->sc_cmd);
fail1: usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
fail:
return (error);
@@ -503,8 +481,7 @@ static int
uath_detach(device_t dev)
{
struct uath_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
unsigned int x;
/*
@@ -525,9 +502,9 @@ uath_detach(device_t dev)
STAILQ_INIT(&sc->sc_cmd_pending);
STAILQ_INIT(&sc->sc_cmd_waiting);
STAILQ_INIT(&sc->sc_cmd_inactive);
- UATH_UNLOCK(sc);
- uath_stop(ifp);
+ uath_stop(sc);
+ UATH_UNLOCK(sc);
callout_drain(&sc->stat_ch);
callout_drain(&sc->watchdog_ch);
@@ -547,7 +524,7 @@ uath_detach(device_t dev)
usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
ieee80211_ifdetach(ic);
- if_free(ifp);
+ mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
}
@@ -1067,15 +1044,12 @@ uath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return (NULL);
- uvp = (struct uath_vap *) malloc(sizeof(struct uath_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (uvp == NULL)
- return (NULL);
+ uvp = malloc(sizeof(struct uath_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &uvp->vap;
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
- flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@@ -1087,7 +1061,7 @@ uath_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
- ieee80211_media_status);
+ ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return (vap);
}
@@ -1102,18 +1076,17 @@ uath_vap_delete(struct ieee80211vap *vap)
}
static int
-uath_init_locked(void *arg)
+uath_init(struct uath_softc *sc)
{
- struct uath_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t val;
int error;
UATH_ASSERT_LOCKED(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- uath_stop_locked(ifp);
+ if (sc->sc_flags & UATH_FLAG_INITDONE)
+ uath_stop(sc);
/* reset variables */
sc->sc_intrx_nextnum = sc->sc_msgid = 0;
@@ -1122,7 +1095,8 @@ uath_init_locked(void *arg)
uath_cmd_write(sc, WDCMSG_BIND, &val, sizeof val, 0);
/* set MAC address */
- uath_config_multi(sc, CFG_MAC_ADDR, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
+ uath_config_multi(sc, CFG_MAC_ADDR,
+ vap ? vap->iv_myaddr : ic->ic_macaddr, IEEE80211_ADDR_LEN);
/* XXX honor net80211 state */
uath_config(sc, CFG_RATE_CONTROL_ENABLE, 0x00000001);
@@ -1171,8 +1145,6 @@ uath_init_locked(void *arg)
UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON,
UATH_FILTER_OP_SET);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= UATH_FLAG_INITDONE;
callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
@@ -1180,28 +1152,16 @@ uath_init_locked(void *arg)
return (0);
fail:
- uath_stop_locked(ifp);
+ uath_stop(sc);
return (error);
}
static void
-uath_init(void *arg)
-{
- struct uath_softc *sc = arg;
-
- UATH_LOCK(sc);
- (void)uath_init_locked(sc);
- UATH_UNLOCK(sc);
-}
-
-static void
-uath_stop_locked(struct ifnet *ifp)
+uath_stop(struct uath_softc *sc)
{
- struct uath_softc *sc = ifp->if_softc;
UATH_ASSERT_LOCKED(sc);
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_flags &= ~UATH_FLAG_INITDONE;
callout_stop(&sc->stat_ch);
@@ -1217,16 +1177,6 @@ uath_stop_locked(struct ifnet *ifp)
uath_cmd_write(sc, WDCMSG_TARGET_STOP, NULL, 0, 0);
}
-static void
-uath_stop(struct ifnet *ifp)
-{
- struct uath_softc *sc = ifp->if_softc;
-
- UATH_LOCK(sc);
- uath_stop_locked(ifp);
- UATH_UNLOCK(sc);
-}
-
static int
uath_config(struct uath_softc *sc, uint32_t reg, uint32_t val)
{
@@ -1329,13 +1279,13 @@ static void
uath_watchdog(void *arg)
{
struct uath_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
- /*uath_init(ifp); XXX needs a process context! */
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ /*uath_init(sc); XXX needs a process context! */
+ counter_u64_add(ic->ic_oerrors, 1);
return;
}
callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
@@ -1450,12 +1400,8 @@ uath_getbuf(struct uath_softc *sc)
UATH_ASSERT_LOCKED(sc);
bf = _uath_getbuf(sc);
- if (bf == NULL) {
- struct ifnet *ifp = sc->sc_ifp;
-
+ if (bf == NULL)
DPRINTF(sc, UATH_DEBUG_XMIT, "%s: stop queue\n", __func__);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- }
return (bf);
}
@@ -1474,8 +1420,7 @@ static int
uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c)
{
#ifdef UATH_DEBUG
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
#endif
struct uath_cmd_reset reset;
@@ -1554,47 +1499,28 @@ uath_wme_init(struct uath_softc *sc)
return (error);
}
-static int
-uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+uath_parent(struct ieee80211com *ic)
{
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- struct uath_softc *sc = ifp->if_softc;
- int error;
+ struct uath_softc *sc = ic->ic_softc;
int startall = 0;
UATH_LOCK(sc);
- error = (sc->sc_flags & UATH_FLAG_INVALID) ? ENXIO : 0;
- UATH_UNLOCK(sc);
- if (error)
- return (error);
-
- switch (cmd) {
- case SIOCSIFFLAGS:
- if (ifp->if_flags & IFF_UP) {
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- uath_init(ifp->if_softc);
- startall = 1;
- }
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- uath_stop(ifp);
- }
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
+ if (sc->sc_flags & UATH_FLAG_INVALID) {
+ UATH_UNLOCK(sc);
+ return;
}
- return (error);
+ if (ic->ic_nrunning > 0) {
+ if (!(sc->sc_flags & UATH_FLAG_INITDONE)) {
+ uath_init(sc);
+ startall = 1;
+ }
+ } else if (sc->sc_flags & UATH_FLAG_INITDONE)
+ uath_stop(sc);
+ UATH_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
static int
@@ -1763,31 +1689,49 @@ uath_freetx(struct mbuf *m)
} while ((m = next) != NULL);
}
+static int
+uath_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct uath_softc *sc = ic->ic_softc;
+ int error;
+
+ UATH_LOCK(sc);
+ if ((sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
+ UATH_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ UATH_UNLOCK(sc);
+ return (error);
+ }
+ uath_start(sc);
+ UATH_UNLOCK(sc);
+
+ return (0);
+}
+
static void
-uath_start(struct ifnet *ifp)
+uath_start(struct uath_softc *sc)
{
struct uath_data *bf;
- struct uath_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m, *next;
uath_datahead frags;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
+ UATH_ASSERT_LOCKED(sc);
+
+ if ((sc->sc_flags & UATH_FLAG_INITDONE) == 0 ||
(sc->sc_flags & UATH_FLAG_INVALID))
return;
- UATH_LOCK(sc);
- for (;;) {
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
bf = uath_getbuf(sc);
- if (bf == NULL)
- break;
-
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL) {
- STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
- UATH_STAT_INC(sc, st_tx_inactive);
+ if (bf == NULL) {
+ mbufq_prepend(&sc->sc_snd, m);
break;
}
+
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
@@ -1816,7 +1760,8 @@ uath_start(struct ifnet *ifp)
next = m->m_nextpkt;
if (uath_tx_start(sc, m, ni, bf) != 0) {
bad:
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
reclaim:
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
UATH_STAT_INC(sc, st_tx_inactive);
@@ -1847,7 +1792,6 @@ uath_start(struct ifnet *ifp)
sc->sc_tx_timer = 5;
}
- UATH_UNLOCK(sc);
}
static int
@@ -1855,19 +1799,19 @@ uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
struct uath_data *bf;
- struct uath_softc *sc = ifp->if_softc;
+ struct uath_softc *sc = ic->ic_softc;
+ UATH_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
- !(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ !(sc->sc_flags & UATH_FLAG_INITDONE)) {
m_freem(m);
ieee80211_free_node(ni);
+ UATH_UNLOCK(sc);
return (ENETDOWN);
}
- UATH_LOCK(sc);
/* grab a TX buffer */
bf = uath_getbuf(sc);
if (bf == NULL) {
@@ -1880,7 +1824,6 @@ uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
sc->sc_seqnum = 0;
if (uath_tx_start(sc, m, ni, bf) != 0) {
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
UATH_STAT_INC(sc, st_tx_inactive);
UATH_UNLOCK(sc);
@@ -1907,12 +1850,11 @@ uath_scan_end(struct ieee80211com *ic)
static void
uath_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct uath_softc *sc = ifp->if_softc;
+ struct uath_softc *sc = ic->ic_softc;
UATH_LOCK(sc);
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
- (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ (sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
UATH_UNLOCK(sc);
return;
}
@@ -1933,7 +1875,7 @@ uath_update_mcast(struct ieee80211com *ic)
UATH_LOCK(sc);
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
- (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ (sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
UATH_UNLOCK(sc);
return;
}
@@ -1953,7 +1895,7 @@ uath_update_promisc(struct ieee80211com *ic)
UATH_LOCK(sc);
if ((sc->sc_flags & UATH_FLAG_INVALID) ||
- (ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ (sc->sc_flags & UATH_FLAG_INITDONE) == 0) {
UATH_UNLOCK(sc);
return;
}
@@ -1970,7 +1912,7 @@ static int
uath_create_connection(struct uath_softc *sc, uint32_t connid)
{
const struct ieee80211_rateset *rs;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct uath_cmd_create_connection create;
@@ -2021,7 +1963,7 @@ uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs)
static int
uath_write_associd(struct uath_softc *sc)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct uath_cmd_set_associd associd;
@@ -2075,7 +2017,7 @@ uath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
int error;
struct ieee80211_node *ni;
struct ieee80211com *ic = vap->iv_ic;
- struct uath_softc *sc = ic->ic_ifp->if_softc;
+ struct uath_softc *sc = ic->ic_softc;
struct uath_vap *uvp = UATH_VAP(vap);
DPRINTF(sc, UATH_DEBUG_STATE,
@@ -2542,8 +2484,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
struct uath_rx_desc **pdesc)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct uath_chunk *chunk;
struct uath_rx_desc *desc;
struct mbuf *m = data->m, *mnew, *mp;
@@ -2555,14 +2496,14 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
if (actlen < (int)UATH_MIN_RXBUFSZ) {
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
"%s: wrong xfer size (len=%d)\n", __func__, actlen);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
chunk = (struct uath_chunk *)data->buf;
if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) {
device_printf(sc->sc_dev, "%s: strange response\n", __func__);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
UATH_RESET_INTRX(sc);
return (NULL);
}
@@ -2595,7 +2536,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
if ((sc->sc_intrx_len + sizeof(struct uath_rx_desc) +
chunklen) > UATH_MAX_INTRX_SIZE) {
UATH_STAT_INC(sc, st_invalidlen);
- if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
UATH_RESET_INTRX(sc);
@@ -2620,7 +2561,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
if (mnew == NULL) {
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
"%s: can't get new mbuf, drop frame\n", __func__);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
UATH_RESET_INTRX(sc);
@@ -2661,7 +2602,7 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
"%s: bad descriptor (len=%d)\n", __func__,
be32toh(desc->len));
- if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
UATH_STAT_INC(sc, st_toobigrxpkt);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
@@ -2673,13 +2614,11 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
/* finalize mbuf */
if (sc->sc_intrx_head == NULL) {
- m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len =
be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
m->m_data += sizeof(struct uath_chunk);
} else {
mp = sc->sc_intrx_head;
- mp->m_pkthdr.rcvif = ifp;
mp->m_flags |= M_PKTHDR;
mp->m_pkthdr.len = sc->sc_intrx_len;
m = mp;
@@ -2705,7 +2644,6 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
tap->wr_antnoise = -95;
}
- if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
UATH_RESET_INTRX(sc);
return (m);
@@ -2715,8 +2653,7 @@ static void
uath_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
@@ -2776,10 +2713,8 @@ setup:
m = NULL;
desc = NULL;
}
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
- !IFQ_IS_EMPTY(&ifp->if_snd))
- uath_start(ifp);
UATH_LOCK(sc);
+ uath_start(sc);
break;
default:
/* needs it to the inactive queue due to a error. */
@@ -2792,7 +2727,7 @@ setup:
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto setup;
}
break;
@@ -2803,40 +2738,22 @@ static void
uath_data_txeof(struct usb_xfer *xfer, struct uath_data *data)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct mbuf *m;
UATH_ASSERT_LOCKED(sc);
- /*
- * Do any tx complete callback. Note this must be done before releasing
- * the node reference.
- */
if (data->m) {
- m = data->m;
- if (m->m_flags & M_TXCB &&
- (sc->sc_flags & UATH_FLAG_INVALID) == 0) {
- /* XXX status? */
- ieee80211_process_callback(data->ni, m, 0);
- }
- m_freem(m);
+ /* XXX status? */
+ ieee80211_tx_complete(data->ni, data->m, 0);
data->m = NULL;
- }
- if (data->ni) {
- if ((sc->sc_flags & UATH_FLAG_INVALID) == 0)
- ieee80211_free_node(data->ni);
data->ni = NULL;
}
sc->sc_tx_timer = 0;
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
uath_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
struct uath_data *data;
UATH_ASSERT_LOCKED(sc);
@@ -2868,19 +2785,18 @@ setup:
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
- UATH_UNLOCK(sc);
- uath_start(ifp);
- UATH_LOCK(sc);
+ uath_start(sc);
break;
default:
data = STAILQ_FIRST(&sc->sc_tx_active);
if (data == NULL)
goto setup;
if (data->ni != NULL) {
+ if_inc_counter(data->ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
if ((sc->sc_flags & UATH_FLAG_INVALID) == 0)
ieee80211_free_node(data->ni);
data->ni = NULL;
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
diff --git a/sys/dev/usb/wlan/if_uathvar.h b/sys/dev/usb/wlan/if_uathvar.h
index fae3604..56b5ba3 100644
--- a/sys/dev/usb/wlan/if_uathvar.h
+++ b/sys/dev/usb/wlan/if_uathvar.h
@@ -183,7 +183,8 @@ struct uath_vap {
#define UATH_VAP(vap) ((struct uath_vap *)(vap))
struct uath_softc {
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
void *sc_cmd_dma_buf;
diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c
index a2e493e..b882fe3 100644
--- a/sys/dev/usb/wlan/if_upgt.c
+++ b/sys/dev/usb/wlan/if_upgt.c
@@ -128,10 +128,10 @@ static void upgt_eeprom_parse_freq4(struct upgt_softc *, uint8_t *, int);
static void upgt_eeprom_parse_freq6(struct upgt_softc *, uint8_t *, int);
static uint32_t upgt_chksum_le(const uint32_t *, size_t);
static void upgt_tx_done(struct upgt_softc *, uint8_t *);
-static void upgt_init(void *);
-static void upgt_init_locked(struct upgt_softc *);
-static int upgt_ioctl(struct ifnet *, u_long, caddr_t);
-static void upgt_start(struct ifnet *);
+static void upgt_init(struct upgt_softc *);
+static void upgt_parent(struct ieee80211com *);
+static int upgt_transmit(struct ieee80211com *, struct mbuf *);
+static void upgt_start(struct upgt_softc *);
static int upgt_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void upgt_scan_start(struct ieee80211com *);
@@ -240,12 +240,11 @@ upgt_match(device_t dev)
static int
upgt_attach(device_t dev)
{
- int error;
- struct ieee80211com *ic;
- struct ifnet *ifp;
struct upgt_softc *sc = device_get_softc(dev);
+ struct ieee80211com *ic = &sc->sc_ic;
struct usb_attach_arg *uaa = device_get_ivars(dev);
uint8_t bands, iface_index = UPGT_IFACE_INDEX;
+ int error;
sc->sc_dev = dev;
sc->sc_udev = uaa->device;
@@ -258,6 +257,7 @@ upgt_attach(device_t dev)
MTX_DEF);
callout_init(&sc->sc_led_ch, 0);
callout_init(&sc->sc_watchdog_ch, 0);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
upgt_config, UPGT_N_XFERS, sc, &sc->sc_mtx);
@@ -280,26 +280,20 @@ upgt_attach(device_t dev)
if (error)
goto fail3;
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(dev, "can not if_alloc()\n");
- goto fail4;
- }
-
/* Initialize the device. */
error = upgt_device_reset(sc);
if (error)
- goto fail5;
+ goto fail4;
/* Verify the firmware. */
error = upgt_fw_verify(sc);
if (error)
- goto fail5;
+ goto fail4;
/* Calculate device memory space. */
if (sc->sc_memaddr_frame_start == 0 || sc->sc_memaddr_frame_end == 0) {
device_printf(dev,
"could not find memory space addresses on FW\n");
error = EIO;
- goto fail5;
+ goto fail4;
}
sc->sc_memaddr_frame_end -= UPGT_MEMSIZE_RX + 1;
sc->sc_memaddr_rx_start = sc->sc_memaddr_frame_end + 1;
@@ -316,31 +310,19 @@ upgt_attach(device_t dev)
/* Load the firmware. */
error = upgt_fw_load(sc);
if (error)
- goto fail5;
+ goto fail4;
/* Read the whole EEPROM content and parse it. */
error = upgt_eeprom_read(sc);
if (error)
- goto fail5;
+ goto fail4;
error = upgt_eeprom_parse(sc);
if (error)
- goto fail5;
+ goto fail4;
/* all works related with the device have done here. */
upgt_abort_xfers(sc);
- /* Setup the 802.11 device. */
- ifp->if_softc = sc;
- if_initname(ifp, "upgt", device_get_unit(sc->sc_dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = upgt_init;
- ifp->if_ioctl = upgt_ioctl;
- ifp->if_start = upgt_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- IFQ_SET_READY(&ifp->if_snd);
-
- ic = ifp->if_l2com;
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -360,15 +342,16 @@ upgt_attach(device_t dev)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, sc->sc_myaddr);
+ ieee80211_ifattach(ic);
ic->ic_raw_xmit = upgt_raw_xmit;
ic->ic_scan_start = upgt_scan_start;
ic->ic_scan_end = upgt_scan_end;
ic->ic_set_channel = upgt_set_channel;
-
ic->ic_vap_create = upgt_vap_create;
ic->ic_vap_delete = upgt_vap_delete;
ic->ic_update_mcast = upgt_update_mcast;
+ ic->ic_transmit = upgt_transmit;
+ ic->ic_parent = upgt_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -383,7 +366,6 @@ upgt_attach(device_t dev)
return (0);
-fail5: if_free(ifp);
fail4: upgt_free_rx(sc);
fail3: upgt_free_tx(sc);
fail2: usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
@@ -395,30 +377,13 @@ fail1: mtx_destroy(&sc->sc_mtx);
static void
upgt_txeof(struct usb_xfer *xfer, struct upgt_data *data)
{
- struct upgt_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct mbuf *m;
-
- UPGT_ASSERT_LOCKED(sc);
- /*
- * Do any tx complete callback. Note this must be done before releasing
- * the node reference.
- */
if (data->m) {
- m = data->m;
- if (m->m_flags & M_TXCB) {
- /* XXX status? */
- ieee80211_process_callback(data->ni, m, 0);
- }
- m_freem(m);
+ /* XXX status? */
+ ieee80211_tx_complete(data->ni, data->m, 0);
data->m = NULL;
- }
- if (data->ni) {
- ieee80211_free_node(data->ni);
data->ni = NULL;
}
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
}
static void
@@ -462,77 +427,43 @@ upgt_get_stats(struct upgt_softc *sc)
upgt_bulk_tx(sc, data_cmd);
}
-static int
-upgt_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+upgt_parent(struct ieee80211com *ic)
{
- struct upgt_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error;
+ struct upgt_softc *sc = ic->ic_softc;
int startall = 0;
UPGT_LOCK(sc);
- error = (sc->sc_flags & UPGT_FLAG_DETACHED) ? ENXIO : 0;
- UPGT_UNLOCK(sc);
- if (error)
- return (error);
-
- switch (cmd) {
- case SIOCSIFFLAGS:
- if (ifp->if_flags & IFF_UP) {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if ((ifp->if_flags ^ sc->sc_if_flags) &
- (IFF_ALLMULTI | IFF_PROMISC))
- upgt_set_multi(sc);
- } else {
- upgt_init(sc);
- startall = 1;
- }
+ if (sc->sc_flags & UPGT_FLAG_DETACHED) {
+ UPGT_UNLOCK(sc);
+ return;
+ }
+ if (ic->ic_nrunning > 0) {
+ if (sc->sc_flags & UPGT_FLAG_INITDONE) {
+ if (ic->ic_allmulti > 0 || ic->ic_promisc > 0)
+ upgt_set_multi(sc);
} else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- upgt_stop(sc);
+ upgt_init(sc);
+ startall = 1;
}
- sc->sc_if_flags = ifp->if_flags;
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
- }
- return error;
+ } else if (sc->sc_flags & UPGT_FLAG_INITDONE)
+ upgt_stop(sc);
+ UPGT_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
static void
-upgt_stop_locked(struct upgt_softc *sc)
+upgt_stop(struct upgt_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
UPGT_ASSERT_LOCKED(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->sc_flags & UPGT_FLAG_INITDONE)
upgt_set_macfilter(sc, IEEE80211_S_INIT);
upgt_abort_xfers_locked(sc);
-}
-
-static void
-upgt_stop(struct upgt_softc *sc)
-{
- struct ifnet *ifp = sc->sc_ifp;
-
- UPGT_LOCK(sc);
- upgt_stop_locked(sc);
- UPGT_UNLOCK(sc);
-
/* device down */
sc->sc_tx_timer = 0;
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
sc->sc_flags &= ~UPGT_FLAG_INITDONE;
}
@@ -624,36 +555,18 @@ upgt_set_led_blink(void *arg)
}
static void
-upgt_init(void *priv)
-{
- struct upgt_softc *sc = priv;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
-
- UPGT_LOCK(sc);
- upgt_init_locked(sc);
- UPGT_UNLOCK(sc);
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ieee80211_start_all(ic); /* start all vap's */
-}
-
-static void
-upgt_init_locked(struct upgt_softc *sc)
+upgt_init(struct upgt_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
UPGT_ASSERT_LOCKED(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- upgt_stop_locked(sc);
+ if (sc->sc_flags & UPGT_FLAG_INITDONE)
+ upgt_stop(sc);
usbd_transfer_start(sc->sc_xfer[UPGT_BULK_RX]);
(void)upgt_set_macfilter(sc, IEEE80211_S_SCAN);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
sc->sc_flags |= UPGT_FLAG_INITDONE;
callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc);
@@ -662,14 +575,12 @@ upgt_init_locked(struct upgt_softc *sc)
static int
upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct upgt_data *data_cmd;
struct upgt_lmac_mem *mem;
struct upgt_lmac_filter *filter;
- uint8_t broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
UPGT_ASSERT_LOCKED(sc);
@@ -709,10 +620,11 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
case IEEE80211_S_SCAN:
DPRINTF(sc, UPGT_DEBUG_STATE,
"set MAC filter to SCAN (bssid %s)\n",
- ether_sprintf(broadcast));
+ ether_sprintf(ieee80211broadcastaddr));
filter->type = htole16(UPGT_FILTER_TYPE_NONE);
- IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr);
- IEEE80211_ADDR_COPY(filter->src, broadcast);
+ IEEE80211_ADDR_COPY(filter->dst,
+ vap ? vap->iv_myaddr : ic->ic_macaddr);
+ IEEE80211_ADDR_COPY(filter->src, ieee80211broadcastaddr);
filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1);
filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
filter->unknown2 = htole16(UPGT_FILTER_UNKNOWN2);
@@ -724,7 +636,8 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
/* XXX monitor mode isn't tested yet. */
if (vap->iv_opmode == IEEE80211_M_MONITOR) {
filter->type = htole16(UPGT_FILTER_TYPE_MONITOR);
- IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr);
+ IEEE80211_ADDR_COPY(filter->dst,
+ vap ? vap->iv_myaddr : ic->ic_macaddr);
IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid);
filter->unknown1 = htole16(UPGT_FILTER_MONITOR_UNKNOWN1);
filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
@@ -736,7 +649,8 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
"set MAC filter to RUN (bssid %s)\n",
ether_sprintf(ni->ni_bssid));
filter->type = htole16(UPGT_FILTER_TYPE_STA);
- IEEE80211_ADDR_COPY(filter->dst, sc->sc_myaddr);
+ IEEE80211_ADDR_COPY(filter->dst,
+ vap ? vap->iv_myaddr : ic->ic_macaddr);
IEEE80211_ADDR_COPY(filter->src, ni->ni_bssid);
filter->unknown1 = htole16(UPGT_FILTER_UNKNOWN1);
filter->rxaddr = htole32(sc->sc_memaddr_rx_start);
@@ -765,8 +679,7 @@ upgt_set_macfilter(struct upgt_softc *sc, uint8_t state)
static void
upgt_setup_rates(struct ieee80211vap *vap, struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct upgt_softc *sc = ifp->if_softc;
+ struct upgt_softc *sc = ic->ic_softc;
const struct ieee80211_txparam *tp;
/*
@@ -813,39 +726,48 @@ upgt_setup_rates(struct ieee80211vap *vap, struct ieee80211com *ic)
static void
upgt_set_multi(void *arg)
{
- struct upgt_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- if (!(ifp->if_flags & IFF_UP))
- return;
+ /* XXX don't know how to set a device. Lack of docs. */
+}
- /*
- * XXX don't know how to set a device. Lack of docs. Just try to set
- * IFF_ALLMULTI flag here.
- */
- ifp->if_flags |= IFF_ALLMULTI;
+static int
+upgt_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct upgt_softc *sc = ic->ic_softc;
+ int error;
+
+ UPGT_LOCK(sc);
+ if ((sc->sc_flags & UPGT_FLAG_INITDONE) == 0) {
+ UPGT_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ UPGT_UNLOCK(sc);
+ return (error);
+ }
+ upgt_start(sc);
+ UPGT_UNLOCK(sc);
+
+ return (0);
}
static void
-upgt_start(struct ifnet *ifp)
+upgt_start(struct upgt_softc *sc)
{
- struct upgt_softc *sc = ifp->if_softc;
struct upgt_data *data_tx;
struct ieee80211_node *ni;
struct mbuf *m;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return;
+ UPGT_ASSERT_LOCKED(sc);
- UPGT_LOCK(sc);
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
+ if ((sc->sc_flags & UPGT_FLAG_INITDONE) == 0)
+ return;
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
data_tx = upgt_gettxbuf(sc);
if (data_tx == NULL) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
+ mbufq_prepend(&sc->sc_snd, m);
break;
}
@@ -853,15 +775,15 @@ upgt_start(struct ifnet *ifp)
m->m_pkthdr.rcvif = NULL;
if (upgt_tx_start(sc, m, ni, data_tx) != 0) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next);
UPGT_STAT_INC(sc, st_tx_inactive);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
continue;
}
sc->sc_tx_timer = 5;
}
- UPGT_UNLOCK(sc);
}
static int
@@ -869,18 +791,18 @@ upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct upgt_softc *sc = ifp->if_softc;
+ struct upgt_softc *sc = ic->ic_softc;
struct upgt_data *data_tx = NULL;
+ UPGT_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!(sc->sc_flags & UPGT_FLAG_INITDONE)) {
m_freem(m);
ieee80211_free_node(ni);
+ UPGT_UNLOCK(sc);
return ENETDOWN;
}
- UPGT_LOCK(sc);
data_tx = upgt_gettxbuf(sc);
if (data_tx == NULL) {
ieee80211_free_node(ni);
@@ -893,7 +815,6 @@ upgt_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, data_tx, next);
UPGT_STAT_INC(sc, st_tx_inactive);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
UPGT_UNLOCK(sc);
return (EIO);
}
@@ -907,13 +828,13 @@ static void
upgt_watchdog(void *arg)
{
struct upgt_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
if (sc->sc_tx_timer > 0) {
if (--sc->sc_tx_timer == 0) {
device_printf(sc->sc_dev, "watchdog timeout\n");
- /* upgt_init(ifp); XXX needs a process context ? */
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ /* upgt_init(sc); XXX needs a process context ? */
+ counter_u64_add(ic->ic_oerrors, 1);
return;
}
callout_reset(&sc->sc_watchdog_ch, hz, upgt_watchdog, sc);
@@ -950,7 +871,7 @@ upgt_scan_end(struct ieee80211com *ic)
static void
upgt_set_channel(struct ieee80211com *ic)
{
- struct upgt_softc *sc = ic->ic_ifp->if_softc;
+ struct upgt_softc *sc = ic->ic_softc;
UPGT_LOCK(sc);
upgt_set_chan(sc, ic->ic_curchan);
@@ -960,8 +881,7 @@ upgt_set_channel(struct ieee80211com *ic)
static void
upgt_set_chan(struct upgt_softc *sc, struct ieee80211_channel *c)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct upgt_data *data_cmd;
struct upgt_lmac_mem *mem;
struct upgt_lmac_channel *chan;
@@ -1044,7 +964,7 @@ upgt_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
- flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@@ -1059,7 +979,7 @@ upgt_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
- ieee80211_media_status);
+ ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return vap;
}
@@ -1069,7 +989,7 @@ upgt_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct upgt_vap *uvp = UPGT_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct upgt_softc *sc = ic->ic_ifp->if_softc;
+ struct upgt_softc *sc = ic->ic_softc;
/* do it in a process context */
sc->sc_state = nstate;
@@ -1125,6 +1045,7 @@ upgt_update_mcast(struct ieee80211com *ic)
static int
upgt_eeprom_parse(struct upgt_softc *sc)
{
+ struct ieee80211com *ic = &sc->sc_ic;
struct upgt_eeprom_header *eeprom_header;
struct upgt_eeprom_option *eeprom_option;
uint16_t option_len;
@@ -1169,7 +1090,8 @@ upgt_eeprom_parse(struct upgt_softc *sc)
DPRINTF(sc, UPGT_DEBUG_FW,
"EEPROM mac len=%d\n", option_len);
- IEEE80211_ADDR_COPY(sc->sc_myaddr, eeprom_option->data);
+ IEEE80211_ADDR_COPY(ic->ic_macaddr,
+ eeprom_option->data);
break;
case UPGT_EEPROM_TYPE_HWRX:
DPRINTF(sc, UPGT_DEBUG_FW,
@@ -1518,8 +1440,7 @@ upgt_chksum_le(const uint32_t *buf, size_t size)
static struct mbuf *
upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct upgt_lmac_rx_desc *rxdesc;
struct mbuf *m;
@@ -1527,7 +1448,7 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
* don't pass packets to the ieee80211 framework if the driver isn't
* RUNNING.
*/
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ if (!(sc->sc_flags & UPGT_FLAG_INITDONE))
return (NULL);
/* access RX packet descriptor */
@@ -1545,7 +1466,6 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
memcpy(mtod(m, char *), rxdesc->data, pkglen);
/* trim FCS */
m->m_len = m->m_pkthdr.len = pkglen - IEEE80211_CRC_LEN;
- m->m_pkthdr.rcvif = ifp;
if (ieee80211_radiotap_active(ic)) {
struct upgt_rx_radiotap_header *tap = &sc->sc_rxtap;
@@ -1554,7 +1474,6 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
tap->wr_rate = upgt_rx_rate(sc, rxdesc->rate);
tap->wr_antsignal = rxdesc->rssi;
}
- if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
DPRINTF(sc, UPGT_DEBUG_RX_PROC, "%s: RX done\n", __func__);
*rssi = rxdesc->rssi;
@@ -1564,8 +1483,7 @@ upgt_rx(struct upgt_softc *sc, uint8_t *data, int pkglen, int *rssi)
static uint8_t
upgt_rx_rate(struct upgt_softc *sc, const int rate)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
static const uint8_t cck_upgt2rate[4] = { 2, 4, 11, 22 };
static const uint8_t ofdm_upgt2rate[12] =
{ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
@@ -1584,7 +1502,6 @@ upgt_rx_rate(struct upgt_softc *sc, const int rate)
static void
upgt_tx_done(struct upgt_softc *sc, uint8_t *data)
{
- struct ifnet *ifp = sc->sc_ifp;
struct upgt_lmac_tx_done_desc *desc;
int i, freed = 0;
@@ -1613,10 +1530,9 @@ upgt_tx_done(struct upgt_softc *sc, uint8_t *data)
}
if (freed != 0) {
- sc->sc_tx_timer = 0;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
UPGT_UNLOCK(sc);
- upgt_start(ifp);
+ sc->sc_tx_timer = 0;
+ upgt_start(sc);
UPGT_LOCK(sc);
}
}
@@ -2022,8 +1938,7 @@ static int
upgt_detach(device_t dev)
{
struct upgt_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
unsigned int x;
/*
@@ -2039,9 +1954,9 @@ upgt_detach(device_t dev)
STAILQ_INIT(&sc->sc_rx_active);
STAILQ_INIT(&sc->sc_rx_inactive);
- UPGT_UNLOCK(sc);
upgt_stop(sc);
+ UPGT_UNLOCK(sc);
callout_drain(&sc->sc_led_ch);
callout_drain(&sc->sc_watchdog_ch);
@@ -2060,7 +1975,7 @@ upgt_detach(device_t dev)
usbd_transfer_unsetup(sc->sc_xfer, UPGT_N_XFERS);
ieee80211_ifdetach(ic);
- if_free(ifp);
+ mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -2168,12 +2083,8 @@ upgt_getbuf(struct upgt_softc *sc)
UPGT_ASSERT_LOCKED(sc);
bf = _upgt_getbuf(sc);
- if (bf == NULL) {
- struct ifnet *ifp = sc->sc_ifp;
-
+ if (bf == NULL)
DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: stop queue\n", __func__);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- }
return (bf);
}
@@ -2191,14 +2102,10 @@ upgt_gettxbuf(struct upgt_softc *sc)
bf->addr = upgt_mem_alloc(sc);
if (bf->addr == 0) {
- struct ifnet *ifp = sc->sc_ifp;
-
DPRINTF(sc, UPGT_DEBUG_XMIT, "%s: no free prism memory!\n",
__func__);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
UPGT_STAT_INC(sc, st_tx_inactive);
- if (!(ifp->if_drv_flags & IFF_DRV_OACTIVE))
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
return (NULL);
}
return (bf);
@@ -2212,7 +2119,6 @@ upgt_tx_start(struct upgt_softc *sc, struct mbuf *m, struct ieee80211_node *ni,
int error = 0, len;
struct ieee80211_frame *wh;
struct ieee80211_key *k;
- struct ifnet *ifp = sc->sc_ifp;
struct upgt_lmac_mem *mem;
struct upgt_lmac_tx_desc *txdesc;
@@ -2295,7 +2201,7 @@ done:
* will stall. It's strange, but it works, so we keep reading
* the statistics here. *shrug*
*/
- if (!(ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS) %
+ if (!(vap->iv_ifp->if_get_counter(vap->iv_ifp, IFCOUNTER_OPACKETS) %
UPGT_TX_STAT_INTERVAL))
upgt_get_stats(sc);
@@ -2306,8 +2212,7 @@ static void
upgt_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct upgt_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
@@ -2355,10 +2260,8 @@ setup:
(void) ieee80211_input_all(ic, m, rssi, nf);
m = NULL;
}
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
- !IFQ_IS_EMPTY(&ifp->if_snd))
- upgt_start(ifp);
UPGT_LOCK(sc);
+ upgt_start(sc);
break;
default:
/* needs it to the inactive queue due to a error. */
@@ -2369,7 +2272,7 @@ setup:
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto setup;
}
break;
@@ -2380,7 +2283,6 @@ static void
upgt_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct upgt_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
struct upgt_data *data;
UPGT_ASSERT_LOCKED(sc);
@@ -2410,18 +2312,17 @@ setup:
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
- UPGT_UNLOCK(sc);
- upgt_start(ifp);
- UPGT_LOCK(sc);
+ upgt_start(sc);
break;
default:
data = STAILQ_FIRST(&sc->sc_tx_active);
if (data == NULL)
goto setup;
if (data->ni != NULL) {
+ if_inc_counter(data->ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(data->ni);
data->ni = NULL;
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
diff --git a/sys/dev/usb/wlan/if_upgtvar.h b/sys/dev/usb/wlan/if_upgtvar.h
index c50276b..3dcd335 100644
--- a/sys/dev/usb/wlan/if_upgtvar.h
+++ b/sys/dev/usb/wlan/if_upgtvar.h
@@ -418,8 +418,9 @@ struct upgt_vap {
#define UPGT_VAP(vap) ((struct upgt_vap *)(vap))
struct upgt_softc {
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
device_t sc_dev;
- struct ifnet *sc_ifp;
struct usb_device *sc_udev;
void *sc_rx_dma_buf;
void *sc_tx_dma_buf;
@@ -429,11 +430,8 @@ struct upgt_softc {
#define UPGT_FLAG_FWLOADED (1 << 0)
#define UPGT_FLAG_INITDONE (1 << 1)
#define UPGT_FLAG_DETACHED (1 << 2)
- int sc_if_flags;
int sc_debug;
- uint8_t sc_myaddr[IEEE80211_ADDR_LEN];
-
enum ieee80211_state sc_state;
int sc_arg;
int sc_led_blink;
diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c
index 79a5be0..e8224ba 100644
--- a/sys/dev/usb/wlan/if_ural.c
+++ b/sys/dev/usb/wlan/if_ural.c
@@ -149,8 +149,9 @@ static int ural_tx_mgt(struct ural_softc *, struct mbuf *,
struct ieee80211_node *);
static int ural_tx_data(struct ural_softc *, struct mbuf *,
struct ieee80211_node *);
-static void ural_start(struct ifnet *);
-static int ural_ioctl(struct ifnet *, u_long, caddr_t);
+static int ural_transmit(struct ieee80211com *, struct mbuf *);
+static void ural_start(struct ural_softc *);
+static void ural_parent(struct ieee80211com *);
static void ural_set_testmode(struct ural_softc *);
static void ural_eeprom_read(struct ural_softc *, uint16_t, void *,
int);
@@ -171,12 +172,12 @@ static void ural_set_chan(struct ural_softc *,
static void ural_disable_rf_tune(struct ural_softc *);
static void ural_enable_tsf_sync(struct ural_softc *);
static void ural_enable_tsf(struct ural_softc *);
-static void ural_update_slot(struct ifnet *);
+static void ural_update_slot(struct ural_softc *);
static void ural_set_txpreamble(struct ural_softc *);
static void ural_set_basicrates(struct ural_softc *,
const struct ieee80211_channel *);
static void ural_set_bssid(struct ural_softc *, const uint8_t *);
-static void ural_set_macaddr(struct ural_softc *, uint8_t *);
+static void ural_set_macaddr(struct ural_softc *, const uint8_t *);
static void ural_update_promisc(struct ieee80211com *);
static void ural_setpromisc(struct ural_softc *);
static const char *ural_get_rf(int);
@@ -184,8 +185,7 @@ static void ural_read_eeprom(struct ural_softc *);
static int ural_bbp_init(struct ural_softc *);
static void ural_set_txantenna(struct ural_softc *, int);
static void ural_set_rxantenna(struct ural_softc *, int);
-static void ural_init_locked(struct ural_softc *);
-static void ural_init(void *);
+static void ural_init(struct ural_softc *);
static void ural_stop(struct ural_softc *);
static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
@@ -422,8 +422,7 @@ ural_attach(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct ural_softc *sc = device_get_softc(self);
- struct ifnet *ifp;
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
uint8_t iface_index, bands;
int error;
@@ -433,6 +432,7 @@ ural_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
MTX_NETWORK_LOCK, MTX_DEF);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = RAL_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device,
@@ -455,24 +455,6 @@ ural_attach(device_t self)
device_printf(self, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
sc->asic_rev, ural_get_rf(sc->rf_rev));
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "can not if_alloc()\n");
- goto detach;
- }
- ic = ifp->if_l2com;
-
- ifp->if_softc = sc;
- if_initname(ifp, "ural", device_get_unit(sc->sc_dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = ural_init;
- ifp->if_ioctl = ural_ioctl;
- ifp->if_start = ural_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -497,13 +479,14 @@ ural_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, sc->sc_bssid);
+ ieee80211_ifattach(ic);
ic->ic_update_promisc = ural_update_promisc;
ic->ic_raw_xmit = ural_raw_xmit;
ic->ic_scan_start = ural_scan_start;
ic->ic_scan_end = ural_scan_end;
ic->ic_set_channel = ural_set_channel;
-
+ ic->ic_parent = ural_parent;
+ ic->ic_transmit = ural_transmit;
ic->ic_vap_create = ural_vap_create;
ic->ic_vap_delete = ural_vap_delete;
@@ -527,8 +510,7 @@ static int
ural_detach(device_t self)
{
struct ural_softc *sc = device_get_softc(self);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
/* prevent further ioctls */
RAL_LOCK(sc);
@@ -543,11 +525,9 @@ ural_detach(device_t self)
ural_unsetup_tx_list(sc);
RAL_UNLOCK(sc);
- if (ifp) {
- ic = ifp->if_l2com;
+ if (ic->ic_softc == sc)
ieee80211_ifdetach(ic);
- if_free(ifp);
- }
+ mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -580,7 +560,7 @@ ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct ural_softc *sc = ic->ic_ifp->if_softc;
+ struct ural_softc *sc = ic->ic_softc;
struct ural_vap *uvp;
struct ieee80211vap *vap;
@@ -594,7 +574,7 @@ ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
- flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@@ -610,7 +590,8 @@ ural_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
/* complete setup */
- ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
+ ieee80211_vap_attach(vap, ieee80211_media_change,
+ ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return vap;
}
@@ -634,13 +615,8 @@ ural_tx_free(struct ural_tx_data *data, int txerr)
struct ural_softc *sc = data->sc;
if (data->m != NULL) {
- if (data->m->m_flags & M_TXCB)
- ieee80211_process_callback(data->ni, data->m,
- txerr ? ETIMEDOUT : 0);
- m_freem(data->m);
+ ieee80211_tx_complete(data->ni, data->m, txerr);
data->m = NULL;
-
- ieee80211_free_node(data->ni);
data->ni = NULL;
}
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
@@ -697,7 +673,7 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ural_vap *uvp = URAL_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct ural_softc *sc = ic->ic_ifp->if_softc;
+ struct ural_softc *sc = ic->ic_softc;
const struct ieee80211_txparam *tp;
struct ieee80211_node *ni;
struct mbuf *m;
@@ -731,11 +707,11 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_free_node(ni);
return (-1);
}
- ural_update_slot(ic->ic_ifp);
+ ural_update_slot(sc);
ural_set_txpreamble(sc);
ural_set_basicrates(sc, ic->ic_bsschan);
- IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
- ural_set_bssid(sc, sc->sc_bssid);
+ IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
+ ural_set_bssid(sc, ic->ic_macaddr);
}
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
@@ -789,7 +765,6 @@ static void
ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct ural_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap;
struct ural_tx_data *data;
struct mbuf *m;
@@ -807,9 +782,6 @@ ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
ural_tx_free(data, 0);
usbd_xfer_set_priv(xfer, NULL);
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
@@ -852,16 +824,13 @@ tr_setup:
usbd_transfer_submit(xfer);
}
- RAL_UNLOCK(sc);
- ural_start(ifp);
- RAL_LOCK(sc);
+ ural_start(sc);
break;
default: /* Error */
DPRINTFN(11, "transfer error, %s\n",
usbd_errstr(error));
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
data = usbd_xfer_get_priv(xfer);
if (data != NULL) {
ural_tx_free(data, error);
@@ -883,8 +852,7 @@ static void
ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct ural_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
struct usb_page_cache *pc;
@@ -902,7 +870,7 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
if (len < (int)(RAL_RX_DESC_SIZE + IEEE80211_MIN_LEN)) {
DPRINTF("%s: xfer too short %d\n",
device_get_nameunit(sc->sc_dev), len);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
@@ -921,20 +889,19 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
* filled RAL_TXRX_CSR2:
*/
DPRINTFN(5, "PHY or CRC error\n");
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL) {
DPRINTF("could not allocate mbuf\n");
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
usbd_copy_out(pc, 0, mtod(m, uint8_t *), len);
/* finalize mbuf */
- m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
if (ieee80211_radiotap_active(ic)) {
@@ -973,10 +940,8 @@ tr_setup:
} else
(void) ieee80211_input_all(ic, m, rssi, nf);
}
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
- !IFQ_IS_EMPTY(&ifp->if_snd))
- ural_start(ifp);
RAL_LOCK(sc);
+ ural_start(sc);
return;
default: /* Error */
@@ -1016,8 +981,7 @@ static void
ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc,
uint32_t flags, int len, int rate)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t plcp_length;
int remainder;
@@ -1066,12 +1030,10 @@ ural_tx_bcn(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = sc->sc_ifp;
const struct ieee80211_txparam *tp;
struct ural_tx_data *data;
if (sc->tx_nfree == 0) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
m_freem(m0);
ieee80211_free_node(ni);
return (EIO);
@@ -1348,78 +1310,73 @@ ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
return 0;
}
+static int
+ural_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct ural_softc *sc = ic->ic_softc;
+ int error;
+
+ RAL_LOCK(sc);
+ if (!sc->sc_running) {
+ RAL_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ RAL_UNLOCK(sc);
+ return (error);
+ }
+ ural_start(sc);
+ RAL_UNLOCK(sc);
+
+ return (0);
+}
+
static void
-ural_start(struct ifnet *ifp)
+ural_start(struct ural_softc *sc)
{
- struct ural_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
- RAL_LOCK(sc);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- RAL_UNLOCK(sc);
+ RAL_LOCK_ASSERT(sc, MA_OWNED);
+
+ if (sc->sc_running == 0)
return;
- }
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
- if (sc->tx_nfree < RAL_TX_MINFREE) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
+
+ while (sc->tx_nfree >= RAL_TX_MINFREE &&
+ (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
if (ural_tx_data(sc, m, ni) != 0) {
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
break;
}
}
- RAL_UNLOCK(sc);
}
-static int
-ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+ural_parent(struct ieee80211com *ic)
{
- struct ural_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error;
+ struct ural_softc *sc = ic->ic_softc;
int startall = 0;
RAL_LOCK(sc);
- error = sc->sc_detached ? ENXIO : 0;
- RAL_UNLOCK(sc);
- if (error)
- return (error);
-
- switch (cmd) {
- case SIOCSIFFLAGS:
- RAL_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- ural_init_locked(sc);
- startall = 1;
- } else
- ural_setpromisc(sc);
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ural_stop(sc);
- }
+ if (sc->sc_detached) {
RAL_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- case SIOCSIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- default:
- error = ether_ioctl(ifp, cmd, data);
- break;
+ return;
}
- return error;
+ if (ic->ic_nrunning > 0) {
+ if (sc->sc_running == 0) {
+ ural_init(sc);
+ startall = 1;
+ } else
+ ural_setpromisc(sc);
+ } else if (sc->sc_running)
+ ural_stop(sc);
+ RAL_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
static void
@@ -1614,23 +1571,22 @@ ural_rf_write(struct ural_softc *sc, uint8_t reg, uint32_t val)
static void
ural_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ural_softc *sc = ifp->if_softc;
+ struct ural_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
ural_write(sc, RAL_TXRX_CSR19, 0);
- ural_set_bssid(sc, ifp->if_broadcastaddr);
+ ural_set_bssid(sc, ieee80211broadcastaddr);
RAL_UNLOCK(sc);
}
static void
ural_scan_end(struct ieee80211com *ic)
{
- struct ural_softc *sc = ic->ic_ifp->if_softc;
+ struct ural_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
ural_enable_tsf_sync(sc);
- ural_set_bssid(sc, sc->sc_bssid);
+ ural_set_bssid(sc, ic->ic_macaddr);
RAL_UNLOCK(sc);
}
@@ -1638,7 +1594,7 @@ ural_scan_end(struct ieee80211com *ic)
static void
ural_set_channel(struct ieee80211com *ic)
{
- struct ural_softc *sc = ic->ic_ifp->if_softc;
+ struct ural_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
ural_set_chan(sc, ic->ic_curchan);
@@ -1648,8 +1604,7 @@ ural_set_channel(struct ieee80211com *ic)
static void
ural_set_chan(struct ural_softc *sc, struct ieee80211_channel *c)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint8_t power, tmp;
int i, chan;
@@ -1780,8 +1735,7 @@ ural_disable_rf_tune(struct ural_softc *sc)
static void
ural_enable_tsf_sync(struct ural_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint16_t logcwmin, preload, tmp;
@@ -1817,10 +1771,9 @@ ural_enable_tsf(struct ural_softc *sc)
#define RAL_RXTX_TURNAROUND 5 /* us */
static void
-ural_update_slot(struct ifnet *ifp)
+ural_update_slot(struct ural_softc *sc)
{
- struct ural_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t slottime, sifs, eifs;
slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
@@ -1845,8 +1798,7 @@ ural_update_slot(struct ifnet *ifp)
static void
ural_set_txpreamble(struct ural_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t tmp;
tmp = ural_read(sc, RAL_TXRX_CSR10);
@@ -1893,7 +1845,7 @@ ural_set_bssid(struct ural_softc *sc, const uint8_t *bssid)
}
static void
-ural_set_macaddr(struct ural_softc *sc, uint8_t *addr)
+ural_set_macaddr(struct ural_softc *sc, const uint8_t *addr)
{
uint16_t tmp;
@@ -1912,18 +1864,17 @@ ural_set_macaddr(struct ural_softc *sc, uint8_t *addr)
static void
ural_setpromisc(struct ural_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
tmp = ural_read(sc, RAL_TXRX_CSR2);
tmp &= ~RAL_DROP_NOT_TO_ME;
- if (!(ifp->if_flags & IFF_PROMISC))
+ if (sc->sc_ic.ic_promisc == 0)
tmp |= RAL_DROP_NOT_TO_ME;
ural_write(sc, RAL_TXRX_CSR2, tmp);
- DPRINTF("%s promiscuous mode\n", (ifp->if_flags & IFF_PROMISC) ?
+ DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc ?
"entering" : "leaving");
}
@@ -1932,11 +1883,9 @@ ural_update_promisc(struct ieee80211com *ic)
{
struct ural_softc *sc = ic->ic_softc;
- if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return;
-
RAL_LOCK(sc);
- ural_setpromisc(sc);
+ if (sc->sc_running)
+ ural_setpromisc(sc);
RAL_UNLOCK(sc);
}
@@ -1958,6 +1907,7 @@ ural_get_rf(int rev)
static void
ural_read_eeprom(struct ural_softc *sc)
{
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t val;
ural_eeprom_read(sc, RAL_EEPROM_CONFIG0, &val, 2);
@@ -1970,7 +1920,7 @@ ural_read_eeprom(struct ural_softc *sc)
sc->nb_ant = val & 0x3;
/* read MAC address */
- ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, sc->sc_bssid, 6);
+ ural_eeprom_read(sc, RAL_EEPROM_ADDRESS, ic->ic_macaddr, 6);
/* read default values for BBP registers */
ural_eeprom_read(sc, RAL_EEPROM_BBP_BASE, sc->bbp_prom, 2 * 16);
@@ -2064,11 +2014,11 @@ ural_set_rxantenna(struct ural_softc *sc, int antenna)
}
static void
-ural_init_locked(struct ural_softc *sc)
+ural_init(struct ural_softc *sc)
{
#define N(a) ((int)(sizeof (a) / sizeof ((a)[0])))
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint16_t tmp;
int i, ntries;
@@ -2115,7 +2065,7 @@ ural_init_locked(struct ural_softc *sc)
ural_set_txantenna(sc, sc->tx_ant);
ural_set_rxantenna(sc, sc->rx_ant);
- ural_set_macaddr(sc, IF_LLADDR(ifp));
+ ural_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
/*
* Allocate Tx and Rx xfer queues.
@@ -2128,13 +2078,12 @@ ural_init_locked(struct ural_softc *sc)
tmp |= RAL_DROP_CTL | RAL_DROP_BAD_VERSION;
if (ic->ic_opmode != IEEE80211_M_HOSTAP)
tmp |= RAL_DROP_TODS;
- if (!(ifp->if_flags & IFF_PROMISC))
+ if (ic->ic_promisc == 0)
tmp |= RAL_DROP_NOT_TO_ME;
}
ural_write(sc, RAL_TXRX_CSR2, tmp);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_running = 1;
usbd_xfer_set_stall(sc->sc_xfer[URAL_BULK_WR]);
usbd_transfer_start(sc->sc_xfer[URAL_BULK_RD]);
return;
@@ -2144,28 +2093,12 @@ fail: ural_stop(sc);
}
static void
-ural_init(void *priv)
-{
- struct ural_softc *sc = priv;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
-
- RAL_LOCK(sc);
- ural_init_locked(sc);
- RAL_UNLOCK(sc);
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ieee80211_start_all(ic); /* start all vap's */
-}
-
-static void
ural_stop(struct ural_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
RAL_LOCK_ASSERT(sc, MA_OWNED);
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_running = 0;
/*
* Drain all the transfers, if not already drained:
@@ -2193,27 +2126,23 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct ural_softc *sc = ifp->if_softc;
+ struct ural_softc *sc = ic->ic_softc;
RAL_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!sc->sc_running) {
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
}
if (sc->tx_nfree < RAL_TX_MINFREE) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
RAL_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return EIO;
}
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
-
if (params == NULL) {
/*
* Legacy path; interpret frame contents to decide
@@ -2232,7 +2161,6 @@ ural_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
RAL_UNLOCK(sc);
return 0;
bad:
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
RAL_UNLOCK(sc);
ieee80211_free_node(ni);
return EIO; /* XXX */
@@ -2266,8 +2194,7 @@ ural_ratectl_task(void *arg, int pending)
struct ural_vap *uvp = arg;
struct ieee80211vap *vap = &uvp->vap;
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct ural_softc *sc = ifp->if_softc;
+ struct ural_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
int ok, fail;
int sum, retrycnt;
@@ -2286,7 +2213,8 @@ ural_ratectl_task(void *arg, int pending)
ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt);
(void) ieee80211_ratectl_rate(ni, NULL, 0);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, fail); /* count TX retry-fail as Tx errors */
+ /* count TX retry-fail as Tx errors */
+ if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail);
usb_callout_reset(&uvp->ratectl_ch, hz, ural_ratectl_timeout, uvp);
RAL_UNLOCK(sc);
diff --git a/sys/dev/usb/wlan/if_uralvar.h b/sys/dev/usb/wlan/if_uralvar.h
index c62b0e4..f40f71d 100644
--- a/sys/dev/usb/wlan/if_uralvar.h
+++ b/sys/dev/usb/wlan/if_uralvar.h
@@ -89,7 +89,8 @@ enum {
};
struct ural_softc {
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
@@ -109,8 +110,8 @@ struct ural_softc {
uint16_t sta[11];
uint32_t rf_regs[4];
uint8_t txpow[14];
- uint8_t sc_bssid[6];
- uint8_t sc_detached;
+ u_int sc_detached:1,
+ sc_running:1;
struct {
uint8_t val;
diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c
index f8b77d4..f0d2674 100644
--- a/sys/dev/usb/wlan/if_urtw.c
+++ b/sys/dev/usb/wlan/if_urtw.c
@@ -651,11 +651,11 @@ static struct ieee80211vap *urtw_vap_create(struct ieee80211com *,
int, const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void urtw_vap_delete(struct ieee80211vap *);
-static void urtw_init(void *);
-static void urtw_stop(struct ifnet *);
-static void urtw_stop_locked(struct ifnet *);
-static int urtw_ioctl(struct ifnet *, u_long, caddr_t);
-static void urtw_start(struct ifnet *);
+static void urtw_init(struct urtw_softc *);
+static void urtw_stop(struct urtw_softc *);
+static void urtw_parent(struct ieee80211com *);
+static int urtw_transmit(struct ieee80211com *, struct mbuf *);
+static void urtw_start(struct urtw_softc *);
static int urtw_alloc_rx_data_list(struct urtw_softc *);
static int urtw_alloc_tx_data_list(struct urtw_softc *);
static int urtw_raw_xmit(struct ieee80211_node *, struct mbuf *,
@@ -784,8 +784,7 @@ urtw_attach(device_t dev)
int ret = ENXIO;
struct urtw_softc *sc = device_get_softc(dev);
struct usb_attach_arg *uaa = device_get_ivars(dev);
- struct ieee80211com *ic;
- struct ifnet *ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
uint8_t bands, iface_index = URTW_IFACE_INDEX; /* XXX */
uint16_t n_setup;
uint32_t data;
@@ -807,6 +806,7 @@ urtw_attach(device_t dev)
TASK_INIT(&sc->sc_led_task, 0, urtw_ledtask, sc);
TASK_INIT(&sc->sc_updateslot_task, 0, urtw_updateslottask, sc);
callout_init(&sc->sc_watchdog_ch, 0);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
if (sc->sc_flags & URTW_RTL8187B) {
setup_start = urtw_8187b_usbconfig;
@@ -861,26 +861,6 @@ urtw_attach(device_t dev)
sc->sc_currate = 3;
sc->sc_preamble_mode = urtw_preamble_mode;
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "can not allocate ifnet\n");
- ret = ENOMEM;
- goto fail1;
- }
-
- ifp->if_softc = sc;
- if_initname(ifp, "urtw", device_get_unit(sc->sc_dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = urtw_init;
- ifp->if_ioctl = urtw_ioctl;
- ifp->if_start = urtw_start;
- /* XXX URTW_TX_DATA_LIST_COUNT */
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic = ifp->if_l2com;
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -901,7 +881,7 @@ urtw_attach(device_t dev)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, sc->sc_bssid);
+ ieee80211_ifattach(ic);
ic->ic_raw_xmit = urtw_raw_xmit;
ic->ic_scan_start = urtw_scan_start;
ic->ic_scan_end = urtw_scan_end;
@@ -910,6 +890,8 @@ urtw_attach(device_t dev)
ic->ic_vap_create = urtw_vap_create;
ic->ic_vap_delete = urtw_vap_delete;
ic->ic_update_mcast = urtw_update_mcast;
+ ic->ic_parent = urtw_parent;
+ ic->ic_transmit = urtw_transmit;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -923,8 +905,9 @@ urtw_attach(device_t dev)
ieee80211_announce(ic);
return (0);
-fail: URTW_UNLOCK(sc);
-fail1: usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
+fail:
+ URTW_UNLOCK(sc);
+ usbd_transfer_unsetup(sc->sc_xfer, (sc->sc_flags & URTW_RTL8187B) ?
URTW_8187B_N_XFERS : URTW_8187L_N_XFERS);
fail0:
return (ret);
@@ -934,18 +917,16 @@ static int
urtw_detach(device_t dev)
{
struct urtw_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
unsigned int x;
unsigned int n_xfers;
/* Prevent further ioctls */
URTW_LOCK(sc);
sc->sc_flags |= URTW_DETACHED;
+ urtw_stop(sc);
URTW_UNLOCK(sc);
- urtw_stop(ifp);
-
ieee80211_draintask(ic, &sc->sc_updateslot_task);
ieee80211_draintask(ic, &sc->sc_led_task);
@@ -979,7 +960,7 @@ urtw_detach(device_t dev)
usbd_transfer_unsetup(sc->sc_xfer, n_xfers);
ieee80211_ifdetach(ic);
- if_free(ifp);
+ mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
}
@@ -1032,15 +1013,12 @@ urtw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return (NULL);
- uvp = (struct urtw_vap *) malloc(sizeof(struct urtw_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (uvp == NULL)
- return (NULL);
+ uvp = malloc(sizeof(struct urtw_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &uvp->vap;
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
- flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@@ -1052,7 +1030,7 @@ urtw_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
- ieee80211_media_status);
+ ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return (vap);
}
@@ -1067,15 +1045,15 @@ urtw_vap_delete(struct ieee80211vap *vap)
}
static void
-urtw_init_locked(void *arg)
+urtw_init(struct urtw_softc *sc)
{
- int ret;
- struct urtw_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
usb_error_t error;
+ int ret;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- urtw_stop_locked(ifp);
+ URTW_ASSERT_LOCKED(sc);
+
+ if (sc->sc_flags & URTW_RUNNING)
+ urtw_stop(sc);
error = (sc->sc_flags & URTW_RTL8187B) ? urtw_adapter_start_b(sc) :
urtw_adapter_start(sc);
@@ -1105,24 +1083,13 @@ urtw_init_locked(void *arg)
if (sc->sc_flags & URTW_RTL8187B)
usbd_transfer_start(sc->sc_xfer[URTW_8187B_BULK_TX_STATUS]);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_flags |= URTW_RUNNING;
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
fail:
return;
}
-static void
-urtw_init(void *arg)
-{
- struct urtw_softc *sc = arg;
-
- URTW_LOCK(sc);
- urtw_init_locked(arg);
- URTW_UNLOCK(sc);
-}
-
static usb_error_t
urtw_adapter_start_b(struct urtw_softc *sc)
{
@@ -1215,6 +1182,7 @@ fail:
static usb_error_t
urtw_adapter_start(struct urtw_softc *sc)
{
+ struct ieee80211com *ic = &sc->sc_ic;
usb_error_t error;
error = urtw_reset(sc);
@@ -1234,8 +1202,8 @@ urtw_adapter_start(struct urtw_softc *sc)
if (error)
goto fail;
/* applying MAC address again. */
- urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]);
- urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff);
+ urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
+ urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
if (error)
goto fail;
@@ -1338,13 +1306,14 @@ urtw_do_request(struct urtw_softc *sc,
}
static void
-urtw_stop_locked(struct ifnet *ifp)
+urtw_stop(struct urtw_softc *sc)
{
- struct urtw_softc *sc = ifp->if_softc;
uint8_t data8;
usb_error_t error;
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ URTW_ASSERT_LOCKED(sc);
+
+ sc->sc_flags &= ~URTW_RUNNING;
error = urtw_intr_disable(sc);
if (error)
@@ -1377,16 +1346,6 @@ fail:
}
static void
-urtw_stop(struct ifnet *ifp)
-{
- struct urtw_softc *sc = ifp->if_softc;
-
- URTW_LOCK(sc);
- urtw_stop_locked(ifp);
- URTW_UNLOCK(sc);
-}
-
-static void
urtw_abort_xfers(struct urtw_softc *sc)
{
int i, max;
@@ -1401,72 +1360,71 @@ urtw_abort_xfers(struct urtw_softc *sc)
usbd_transfer_stop(sc->sc_xfer[i]);
}
-static int
-urtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+urtw_parent(struct ieee80211com *ic)
{
- struct urtw_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error;
+ struct urtw_softc *sc = ic->ic_softc;
int startall = 0;
URTW_LOCK(sc);
- error = (sc->sc_flags & URTW_DETACHED) ? ENXIO : 0;
- URTW_UNLOCK(sc);
- if (error)
- return (error);
+ if (sc->sc_flags & URTW_DETACHED) {
+ URTW_UNLOCK(sc);
+ return;
+ }
- switch (cmd) {
- case SIOCSIFFLAGS:
- if (ifp->if_flags & IFF_UP) {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if ((ifp->if_flags ^ sc->sc_if_flags) &
- (IFF_ALLMULTI | IFF_PROMISC))
- urtw_set_multi(sc);
- } else {
- urtw_init(ifp->if_softc);
- startall = 1;
- }
+ if (ic->ic_nrunning > 0) {
+ if (sc->sc_flags & URTW_RUNNING) {
+ if (ic->ic_promisc > 0 || ic->ic_allmulti > 0)
+ urtw_set_multi(sc);
} else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- urtw_stop(ifp);
+ urtw_init(sc);
+ startall = 1;
}
- sc->sc_if_flags = ifp->if_flags;
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
+ } else if (sc->sc_flags & URTW_RUNNING)
+ urtw_stop(sc);
+ URTW_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
+}
+
+static int
+urtw_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct urtw_softc *sc = ic->ic_softc;
+ int error;
+
+ URTW_LOCK(sc);
+ if ((sc->sc_flags & URTW_RUNNING) == 0) {
+ URTW_UNLOCK(sc);
+ return (ENXIO);
}
- return (error);
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ URTW_UNLOCK(sc);
+ return (error);
+ }
+ urtw_start(sc);
+ URTW_UNLOCK(sc);
+
+ return (0);
}
static void
-urtw_start(struct ifnet *ifp)
+urtw_start(struct urtw_softc *sc)
{
struct urtw_data *bf;
- struct urtw_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ URTW_ASSERT_LOCKED(sc);
+
+ if ((sc->sc_flags & URTW_RUNNING) == 0)
return;
- URTW_LOCK(sc);
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
bf = urtw_getbuf(sc);
if (bf == NULL) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
+ mbufq_prepend(&sc->sc_snd, m);
break;
}
@@ -1474,7 +1432,8 @@ urtw_start(struct ifnet *ifp)
m->m_pkthdr.rcvif = NULL;
if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_NORMAL) != 0) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
ieee80211_free_node(ni);
break;
@@ -1483,7 +1442,6 @@ urtw_start(struct ifnet *ifp)
sc->sc_txtimer = 5;
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
}
- URTW_UNLOCK(sc);
}
static int
@@ -1565,12 +1523,11 @@ urtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
+ struct urtw_softc *sc = ic->ic_softc;
struct urtw_data *bf;
- struct urtw_softc *sc = ifp->if_softc;
/* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!(sc->sc_flags & URTW_RUNNING)) {
m_freem(m);
ieee80211_free_node(ni);
return ENETDOWN;
@@ -1584,10 +1541,8 @@ urtw_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return (ENOBUFS); /* XXX */
}
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (urtw_tx_start(sc, ni, m, bf, URTW_PRIORITY_LOW) != 0) {
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
URTW_UNLOCK(sc);
return (EIO);
@@ -1615,8 +1570,7 @@ urtw_scan_end(struct ieee80211com *ic)
static void
urtw_set_channel(struct ieee80211com *ic)
{
- struct urtw_softc *sc = ic->ic_ifp->if_softc;
- struct ifnet *ifp = sc->sc_ifp;
+ struct urtw_softc *sc = ic->ic_softc;
uint32_t data, orig;
usb_error_t error;
@@ -1626,7 +1580,7 @@ urtw_set_channel(struct ieee80211com *ic)
* initialization would be failed if setting a channel is called before
* the init have done.
*/
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ if (!(sc->sc_flags & URTW_RUNNING))
return;
if (sc->sc_curchan != NULL && sc->sc_curchan == ic->ic_curchan)
@@ -1673,11 +1627,10 @@ static int
urtw_tx_start(struct urtw_softc *sc, struct ieee80211_node *ni, struct mbuf *m0,
struct urtw_data *data, int prior)
{
- struct ifnet *ifp = sc->sc_ifp;
struct ieee80211_frame *wh = mtod(m0, struct ieee80211_frame *);
struct ieee80211_key *k;
const struct ieee80211_txparam *tp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct usb_xfer *rtl8187b_pipes[URTW_8187B_TXPIPE_MAX] = {
sc->sc_xfer[URTW_8187B_BULK_TX_BE],
@@ -1862,7 +1815,7 @@ static int
urtw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
- struct urtw_softc *sc = ic->ic_ifp->if_softc;
+ struct urtw_softc *sc = ic->ic_softc;
struct urtw_vap *uvp = URTW_VAP(vap);
struct ieee80211_node *ni;
usb_error_t error = 0;
@@ -1915,12 +1868,11 @@ static void
urtw_watchdog(void *arg)
{
struct urtw_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
if (sc->sc_txtimer > 0) {
if (--sc->sc_txtimer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
return;
}
callout_reset(&sc->sc_watchdog_ch, hz, urtw_watchdog, sc);
@@ -1930,17 +1882,7 @@ urtw_watchdog(void *arg)
static void
urtw_set_multi(void *arg)
{
- struct urtw_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
-
- if (!(ifp->if_flags & IFF_UP))
- return;
-
- /*
- * XXX don't know how to set a device. Lack of docs. Just try to set
- * IFF_ALLMULTI flag here.
- */
- ifp->if_flags |= IFF_ALLMULTI;
+ /* XXX don't know how to set a device. Lack of docs. */
}
static usb_error_t
@@ -2002,8 +1944,7 @@ urtw_rtl2rate(uint32_t rate)
static usb_error_t
urtw_update_msr(struct urtw_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint8_t data;
usb_error_t error;
@@ -2144,24 +2085,25 @@ urtw_write32_c(struct urtw_softc *sc, int val, uint32_t data)
static usb_error_t
urtw_get_macaddr(struct urtw_softc *sc)
{
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t data;
usb_error_t error;
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR, &data);
if (error != 0)
goto fail;
- sc->sc_bssid[0] = data & 0xff;
- sc->sc_bssid[1] = (data & 0xff00) >> 8;
+ ic->ic_macaddr[0] = data & 0xff;
+ ic->ic_macaddr[1] = (data & 0xff00) >> 8;
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 1, &data);
if (error != 0)
goto fail;
- sc->sc_bssid[2] = data & 0xff;
- sc->sc_bssid[3] = (data & 0xff00) >> 8;
+ ic->ic_macaddr[2] = data & 0xff;
+ ic->ic_macaddr[3] = (data & 0xff00) >> 8;
error = urtw_eprom_read32(sc, URTW_EPROM_MACADDR + 2, &data);
if (error != 0)
goto fail;
- sc->sc_bssid[4] = data & 0xff;
- sc->sc_bssid[5] = (data & 0xff00) >> 8;
+ ic->ic_macaddr[4] = data & 0xff;
+ ic->ic_macaddr[5] = (data & 0xff00) >> 8;
fail:
return (error);
}
@@ -3233,7 +3175,7 @@ fail:
static usb_error_t
urtw_8225v2b_rf_init(struct urtw_softc *sc)
{
-#define N(a) ((int)(sizeof(a) / sizeof((a)[0])))
+ struct ieee80211com *ic = &sc->sc_ic;
int i;
uint8_t data8;
usb_error_t error;
@@ -3281,8 +3223,8 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
urtw_write8_m(sc, URTW_CONFIG1, data8);
/* applying MAC address again. */
- urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)sc->sc_bssid)[0]);
- urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)sc->sc_bssid)[1] & 0xffff);
+ urtw_write32_m(sc, URTW_MAC0, ((uint32_t *)ic->ic_macaddr)[0]);
+ urtw_write16_m(sc, URTW_MAC4, ((uint32_t *)ic->ic_macaddr)[1] & 0xffff);
error = urtw_set_mode(sc, URTW_EPROM_CMD_NORMAL);
if (error)
@@ -3293,7 +3235,7 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
/*
* MAC configuration
*/
- for (i = 0; i < N(urtw_8225v2b_rf_part1); i++)
+ for (i = 0; i < nitems(urtw_8225v2b_rf_part1); i++)
urtw_write8_m(sc, urtw_8225v2b_rf_part1[i].reg,
urtw_8225v2b_rf_part1[i].val);
urtw_write16_m(sc, URTW_TID_AC_MAP, 0xfa50);
@@ -3326,7 +3268,7 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
urtw_write16_m(sc, URTW_RF_PINS_ENABLE, 0x1fff);
usb_pause_mtx(&sc->sc_mtx, 1100);
- for (i = 0; i < N(urtw_8225v2b_rf_part0); i++) {
+ for (i = 0; i < nitems(urtw_8225v2b_rf_part0); i++) {
urtw_8225_write(sc, urtw_8225v2b_rf_part0[i].reg,
urtw_8225v2b_rf_part0[i].val);
usb_pause_mtx(&sc->sc_mtx, 1);
@@ -3372,7 +3314,7 @@ urtw_8225v2b_rf_init(struct urtw_softc *sc)
}
urtw_8187_write_phy_ofdm(sc, 0x80, 0x10);
- for (i = 0; i < N(urtw_8225v2b_rf_part2); i++)
+ for (i = 0; i < nitems(urtw_8225v2b_rf_part2); i++)
urtw_8187_write_phy_ofdm(sc, i, urtw_8225v2b_rf_part2[i].val);
urtw_write32_m(sc, URTW_8187B_AC_VO, (7 << 12) | (3 << 8) | 0x1c);
@@ -3787,8 +3729,7 @@ static void
urtw_led_ch(void *arg)
{
struct urtw_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
ieee80211_runtask(ic, &sc->sc_led_task);
}
@@ -3935,8 +3876,7 @@ fail:
static usb_error_t
urtw_rx_setconf(struct urtw_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t data;
usb_error_t error;
@@ -3961,7 +3901,7 @@ urtw_rx_setconf(struct urtw_softc *sc)
data = data | URTW_RX_FILTER_CRCERR;
if (ic->ic_opmode == IEEE80211_M_MONITOR ||
- (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) {
+ ic->ic_promisc > 0 || ic->ic_allmulti > 0) {
data = data | URTW_RX_FILTER_ALLMAC;
} else {
data = data | URTW_RX_FILTER_NICMAC;
@@ -3988,14 +3928,13 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
struct ieee80211_frame *wh;
struct mbuf *m, *mnew;
struct urtw_softc *sc = data->sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint8_t noise = 0, rate;
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
if (actlen < (int)URTW_MIN_RXBUFSZ) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
@@ -4006,7 +3945,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
(actlen - (sizeof(struct urtw_8187b_rxhdr))));
flen = le32toh(rx->flag) & 0xfff;
if (flen > actlen) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
rate = (le32toh(rx->flag) >> URTW_RX_FLAG_RXRATE_SHIFT) & 0xf;
@@ -4020,7 +3959,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
(actlen - (sizeof(struct urtw_8187l_rxhdr))));
flen = le32toh(rx->flag) & 0xfff;
if (flen > actlen) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
@@ -4032,7 +3971,7 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
mnew = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (mnew == NULL) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
@@ -4041,7 +3980,6 @@ urtw_rxeof(struct usb_xfer *xfer, struct urtw_data *data, int *rssi_p,
data->buf = mtod(mnew, uint8_t *);
/* finalize mbuf */
- m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = flen - IEEE80211_CRC_LEN;
if (ieee80211_radiotap_active(ic)) {
@@ -4067,8 +4005,7 @@ static void
urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
@@ -4129,7 +4066,7 @@ setup:
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto setup;
}
break;
@@ -4143,7 +4080,7 @@ static void
urtw_txstatus_eof(struct usb_xfer *xfer)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
int actlen, type, pktretry, seq;
uint64_t val;
@@ -4158,7 +4095,7 @@ urtw_txstatus_eof(struct usb_xfer *xfer)
pktretry = val & 0xff;
seq = (val >> 16) & 0xff;
if (pktretry == URTW_TX_MAXRETRY)
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(ic->ic_oerrors, 1);
DPRINTF(sc, URTW_DEBUG_TXSTATUS, "pktretry %d seq %#x\n",
pktretry, seq);
}
@@ -4168,7 +4105,7 @@ static void
urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0);
URTW_ASSERT_LOCKED(sc);
@@ -4186,7 +4123,7 @@ setup:
default:
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto setup;
}
break;
@@ -4197,38 +4134,22 @@ static void
urtw_txeof(struct usb_xfer *xfer, struct urtw_data *data)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct mbuf *m;
URTW_ASSERT_LOCKED(sc);
- /*
- * Do any tx complete callback. Note this must be done before releasing
- * the node reference.
- */
if (data->m) {
- m = data->m;
- if (m->m_flags & M_TXCB) {
- /* XXX status? */
- ieee80211_process_callback(data->ni, m, 0);
- }
- m_freem(m);
+ /* XXX status? */
+ ieee80211_tx_complete(data->ni, data->m, 0);
data->m = NULL;
- }
- if (data->ni) {
- ieee80211_free_node(data->ni);
data->ni = NULL;
}
sc->sc_txtimer = 0;
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
urtw_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtw_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
struct urtw_data *data;
URTW_ASSERT_LOCKED(sc);
@@ -4256,18 +4177,17 @@ setup:
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
- URTW_UNLOCK(sc);
- urtw_start(ifp);
- URTW_LOCK(sc);
+ urtw_start(sc);
break;
default:
data = STAILQ_FIRST(&sc->sc_tx_active);
if (data == NULL)
goto setup;
if (data->ni != NULL) {
+ if_inc_counter(data->ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(data->ni);
data->ni = NULL;
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
@@ -4301,12 +4221,8 @@ urtw_getbuf(struct urtw_softc *sc)
URTW_ASSERT_LOCKED(sc);
bf = _urtw_getbuf(sc);
- if (bf == NULL) {
- struct ifnet *ifp = sc->sc_ifp;
-
+ if (bf == NULL)
DPRINTF(sc, URTW_DEBUG_XMIT, "%s: stop queue\n", __func__);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- }
return (bf);
}
@@ -4378,14 +4294,14 @@ static void
urtw_updateslottask(void *arg, int pending)
{
struct urtw_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
int error;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return;
-
URTW_LOCK(sc);
+ if ((sc->sc_flags & URTW_RUNNING) == 0) {
+ URTW_UNLOCK(sc);
+ return;
+ }
if (sc->sc_flags & URTW_RTL8187B) {
urtw_write8_m(sc, URTW_SIFS, 0x22);
if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan))
diff --git a/sys/dev/usb/wlan/if_urtwn.c b/sys/dev/usb/wlan/if_urtwn.c
index 6b712b3..457a885 100644
--- a/sys/dev/usb/wlan/if_urtwn.c
+++ b/sys/dev/usb/wlan/if_urtwn.c
@@ -169,8 +169,8 @@ static device_detach_t urtwn_detach;
static usb_callback_t urtwn_bulk_tx_callback;
static usb_callback_t urtwn_bulk_rx_callback;
-static usb_error_t urtwn_do_request(struct urtwn_softc *sc,
- struct usb_device_request *req, void *data);
+static usb_error_t urtwn_do_request(struct urtwn_softc *,
+ struct usb_device_request *, void *);
static struct ieee80211vap *urtwn_vap_create(struct ieee80211com *,
const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
const uint8_t [IEEE80211_ADDR_LEN],
@@ -228,10 +228,9 @@ static int8_t urtwn_r88e_get_rssi(struct urtwn_softc *, int, void *);
static int urtwn_tx_start(struct urtwn_softc *,
struct ieee80211_node *, struct mbuf *,
struct urtwn_data *);
-static void urtwn_start(struct ifnet *);
-static void urtwn_start_locked(struct ifnet *,
- struct urtwn_softc *);
-static int urtwn_ioctl(struct ifnet *, u_long, caddr_t);
+static int urtwn_transmit(struct ieee80211com *, struct mbuf *);
+static void urtwn_start(struct urtwn_softc *);
+static void urtwn_parent(struct ieee80211com *);
static int urtwn_r92c_power_on(struct urtwn_softc *);
static int urtwn_r88e_power_on(struct urtwn_softc *);
static int urtwn_llt_init(struct urtwn_softc *);
@@ -269,10 +268,8 @@ static void urtwn_set_chan(struct urtwn_softc *,
static void urtwn_update_mcast(struct ieee80211com *);
static void urtwn_iq_calib(struct urtwn_softc *);
static void urtwn_lc_calib(struct urtwn_softc *);
-static void urtwn_init(void *);
-static void urtwn_init_locked(void *);
-static void urtwn_stop(struct ifnet *);
-static void urtwn_stop_locked(struct ifnet *);
+static void urtwn_init(struct urtwn_softc *);
+static void urtwn_stop(struct urtwn_softc *);
static void urtwn_abort_xfers(struct urtwn_softc *);
static int urtwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
@@ -368,8 +365,7 @@ urtwn_attach(device_t self)
{
struct usb_attach_arg *uaa = device_get_ivars(self);
struct urtwn_softc *sc = device_get_softc(self);
- struct ifnet *ifp;
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
uint8_t iface_index, bands;
int error;
@@ -382,6 +378,7 @@ urtwn_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
MTX_NETWORK_LOCK, MTX_DEF);
callout_init(&sc->sc_watchdog_ch, 0);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = URTWN_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
@@ -424,24 +421,6 @@ urtwn_attach(device_t self)
URTWN_UNLOCK(sc);
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "can not if_alloc()\n");
- goto detach;
- }
- ic = ifp->if_l2com;
-
- ifp->if_softc = sc;
- if_initname(ifp, "urtwn", device_get_unit(sc->sc_dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = urtwn_init;
- ifp->if_ioctl = urtwn_ioctl;
- ifp->if_start = urtwn_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(self);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -462,12 +441,13 @@ urtwn_attach(device_t self)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, sc->sc_bssid);
+ ieee80211_ifattach(ic);
ic->ic_raw_xmit = urtwn_raw_xmit;
ic->ic_scan_start = urtwn_scan_start;
ic->ic_scan_end = urtwn_scan_end;
ic->ic_set_channel = urtwn_set_channel;
-
+ ic->ic_transmit = urtwn_transmit;
+ ic->ic_parent = urtwn_parent;
ic->ic_vap_create = urtwn_vap_create;
ic->ic_vap_delete = urtwn_vap_delete;
ic->ic_update_mcast = urtwn_update_mcast;
@@ -491,17 +471,15 @@ static int
urtwn_detach(device_t self)
{
struct urtwn_softc *sc = device_get_softc(self);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
unsigned int x;
/* Prevent further ioctls. */
URTWN_LOCK(sc);
sc->sc_flags |= URTWN_DETACHED;
+ urtwn_stop(sc);
URTWN_UNLOCK(sc);
- urtwn_stop(ifp);
-
callout_drain(&sc->sc_watchdog_ch);
/* Prevent further allocations from RX/TX data lists. */
@@ -527,8 +505,7 @@ urtwn_detach(device_t self)
/* stop all USB transfers */
usbd_transfer_unsetup(sc->sc_xfer, URTWN_N_TRANSFER);
ieee80211_ifdetach(ic);
-
- if_free(ifp);
+ mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -599,15 +576,12 @@ urtwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return (NULL);
- uvp = (struct urtwn_vap *) malloc(sizeof(struct urtwn_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (uvp == NULL)
- return (NULL);
+ uvp = malloc(sizeof(struct urtwn_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &uvp->vap;
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
- flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(uvp, M_80211_VAP);
return (NULL);
@@ -619,7 +593,7 @@ urtwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
- ieee80211_media_status);
+ ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return (vap);
}
@@ -636,8 +610,7 @@ urtwn_vap_delete(struct ieee80211vap *vap)
static struct mbuf *
urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct mbuf *m;
struct r92c_rx_stat *stat;
@@ -650,7 +623,7 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
* don't pass packets to the ieee80211 framework if the driver isn't
* RUNNING.
*/
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ if (!(sc->sc_flags & URTWN_RUNNING))
return (NULL);
stat = (struct r92c_rx_stat *)buf;
@@ -662,11 +635,11 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
* This should not happen since we setup our Rx filter
* to not receive these frames.
*/
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
if (pktlen < sizeof(*wh) || pktlen > MCLBYTES) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
@@ -695,7 +668,6 @@ urtwn_rx_frame(struct urtwn_softc *sc, uint8_t *buf, int pktlen, int *rssi_p)
}
/* Finalize mbuf. */
- m->m_pkthdr.rcvif = ifp;
wh = (struct ieee80211_frame *)((uint8_t *)&stat[1] + infosz);
memcpy(mtod(m, uint8_t *), wh, pktlen);
m->m_pkthdr.len = m->m_len = pktlen;
@@ -741,7 +713,7 @@ urtwn_rxeof(struct usb_xfer *xfer, struct urtwn_data *data, int *rssi,
int8_t *nf)
{
struct urtwn_softc *sc = data->sc;
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
struct r92c_rx_stat *stat;
struct mbuf *m, *m0 = NULL, *prevm = NULL;
uint32_t rxdw0;
@@ -751,7 +723,7 @@ urtwn_rxeof(struct usb_xfer *xfer, struct urtwn_data *data, int *rssi,
usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
if (len < sizeof(*stat)) {
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return (NULL);
}
@@ -802,8 +774,7 @@ static void
urtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtwn_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_frame *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL, *next;
@@ -866,7 +837,7 @@ tr_setup:
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
break;
@@ -877,38 +848,19 @@ static void
urtwn_txeof(struct usb_xfer *xfer, struct urtwn_data *data)
{
struct urtwn_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct mbuf *m;
URTWN_ASSERT_LOCKED(sc);
-
- /*
- * Do any tx complete callback. Note this must be done before releasing
- * the node reference.
- */
- if (data->m) {
- m = data->m;
- if (m->m_flags & M_TXCB) {
- /* XXX status? */
- ieee80211_process_callback(data->ni, m, 0);
- }
- m_freem(m);
- data->m = NULL;
- }
- if (data->ni) {
- ieee80211_free_node(data->ni);
- data->ni = NULL;
- }
+ /* XXX status? */
+ ieee80211_tx_complete(data->ni, data->m, 0);
+ data->ni = NULL;
+ data->m = NULL;
sc->sc_txtimer = 0;
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static void
urtwn_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtwn_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
struct urtwn_data *data;
URTWN_ASSERT_LOCKED(sc);
@@ -933,16 +885,17 @@ tr_setup:
STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next);
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
- urtwn_start_locked(ifp, sc);
+ urtwn_start(sc);
break;
default:
data = STAILQ_FIRST(&sc->sc_tx_active);
if (data == NULL)
goto tr_setup;
if (data->ni != NULL) {
+ if_inc_counter(data->ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
ieee80211_free_node(data->ni);
data->ni = NULL;
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
@@ -975,11 +928,8 @@ urtwn_getbuf(struct urtwn_softc *sc)
URTWN_ASSERT_LOCKED(sc);
bf = _urtwn_getbuf(sc);
- if (bf == NULL) {
- struct ifnet *ifp = sc->sc_ifp;
+ if (bf == NULL)
DPRINTF("%s: stop queue\n", __func__);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- }
return (bf);
}
@@ -1302,7 +1252,7 @@ urtwn_read_rom(struct urtwn_softc *sc)
sc->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY);
DPRINTF("regulatory type=%d\n", sc->regulatory);
- IEEE80211_ADDR_COPY(sc->sc_bssid, rom->macaddr);
+ IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr);
sc->sc_rf_write = urtwn_r92c_rf_write;
sc->sc_power_on = urtwn_r92c_power_on;
@@ -1363,7 +1313,7 @@ urtwn_r88e_read_rom(struct urtwn_softc *sc)
if (sc->ofdm_tx_pwr_diff & 0x08)
sc->ofdm_tx_pwr_diff |= 0xf0;
sc->regulatory = MS(sc->r88e_rom[0xc1], R92C_ROM_RF1_REGULATORY);
- IEEE80211_ADDR_COPY(sc->sc_bssid, &sc->r88e_rom[0xd7]);
+ IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, &sc->r88e_rom[0xd7]);
sc->sc_rf_write = urtwn_r88e_rf_write;
sc->sc_power_on = urtwn_r88e_power_on;
@@ -1378,7 +1328,7 @@ urtwn_ra_init(struct urtwn_softc *sc)
{
static const uint8_t map[] =
{ 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 };
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct ieee80211_rateset *rs;
@@ -1455,8 +1405,7 @@ urtwn_ra_init(struct urtwn_softc *sc)
void
urtwn_tsf_sync_enable(struct urtwn_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni = vap->iv_bss;
@@ -1513,7 +1462,7 @@ urtwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct urtwn_vap *uvp = URTWN_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct urtwn_softc *sc = ic->ic_ifp->if_softc;
+ struct urtwn_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
enum ieee80211_state ostate;
uint32_t reg;
@@ -1669,12 +1618,11 @@ static void
urtwn_watchdog(void *arg)
{
struct urtwn_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
if (sc->sc_txtimer > 0) {
if (--sc->sc_txtimer == 0) {
device_printf(sc->sc_dev, "device timeout\n");
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
return;
}
callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc);
@@ -1800,10 +1748,9 @@ static int
urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni,
struct mbuf *m0, struct urtwn_data *data)
{
- struct ifnet *ifp = sc->sc_ifp;
struct ieee80211_frame *wh;
struct ieee80211_key *k;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct usb_xfer *xfer;
struct r92c_tx_desc *txd;
@@ -1942,89 +1889,78 @@ urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni,
return (0);
}
-static void
-urtwn_start(struct ifnet *ifp)
+static int
+urtwn_transmit(struct ieee80211com *ic, struct mbuf *m)
{
- struct urtwn_softc *sc = ifp->if_softc;
+ struct urtwn_softc *sc = ic->ic_softc;
+ int error;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return;
URTWN_LOCK(sc);
- urtwn_start_locked(ifp, sc);
+ if ((sc->sc_flags & URTWN_RUNNING) == 0) {
+ URTWN_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ URTWN_UNLOCK(sc);
+ return (error);
+ }
+ urtwn_start(sc);
URTWN_UNLOCK(sc);
+
+ return (0);
}
static void
-urtwn_start_locked(struct ifnet *ifp, struct urtwn_softc *sc)
+urtwn_start(struct urtwn_softc *sc)
{
struct ieee80211_node *ni;
struct mbuf *m;
struct urtwn_data *bf;
URTWN_ASSERT_LOCKED(sc);
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
bf = urtwn_getbuf(sc);
if (bf == NULL) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
+ mbufq_prepend(&sc->sc_snd, m);
break;
}
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
-
if (urtwn_tx_start(sc, ni, m, bf) != 0) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
ieee80211_free_node(ni);
break;
}
-
sc->sc_txtimer = 5;
callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc);
}
}
-static int
-urtwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+urtwn_parent(struct ieee80211com *ic)
{
- struct urtwn_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ struct urtwn_softc *sc = ic->ic_softc;
+ int startall = 0;
URTWN_LOCK(sc);
- error = (sc->sc_flags & URTWN_DETACHED) ? ENXIO : 0;
+ if (sc->sc_flags & URTWN_DETACHED) {
+ URTWN_UNLOCK(sc);
+ return;
+ }
+ if (ic->ic_nrunning > 0) {
+ if ((sc->sc_flags & URTWN_RUNNING) == 0) {
+ urtwn_init(sc);
+ startall = 1;
+ }
+ } else if (sc->sc_flags & URTWN_RUNNING)
+ urtwn_stop(sc);
URTWN_UNLOCK(sc);
- if (error != 0)
- return (error);
- switch (cmd) {
- case SIOCSIFFLAGS:
- if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- urtwn_init(ifp->if_softc);
- startall = 1;
- }
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- urtwn_stop(ifp);
- }
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
- }
- return (error);
+ if (startall)
+ ieee80211_start_all(ic);
}
static int
@@ -2938,7 +2874,7 @@ urtwn_get_txpower(struct urtwn_softc *sc, int chain,
struct ieee80211_channel *c, struct ieee80211_channel *extc,
uint16_t power[URTWN_RIDX_COUNT])
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct r92c_rom *rom = &sc->rom;
uint16_t cckpow, ofdmpow, htpow, diff, max;
const struct urtwn_txpwr *base;
@@ -3037,7 +2973,7 @@ urtwn_r88e_get_txpower(struct urtwn_softc *sc, int chain,
struct ieee80211_channel *c, struct ieee80211_channel *extc,
uint16_t power[URTWN_RIDX_COUNT])
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint16_t cckpow, ofdmpow, bw20pow, htpow;
const struct urtwn_r88e_txpwr *base;
int ridx, chan, group;
@@ -3134,7 +3070,7 @@ urtwn_scan_end(struct ieee80211com *ic)
static void
urtwn_set_channel(struct ieee80211com *ic)
{
- struct urtwn_softc *sc = ic->ic_ifp->if_softc;
+ struct urtwn_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
URTWN_LOCK(sc);
@@ -3156,7 +3092,7 @@ static void
urtwn_set_chan(struct urtwn_softc *sc, struct ieee80211_channel *c,
struct ieee80211_channel *extc)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t reg;
u_int chan;
int i;
@@ -3287,17 +3223,18 @@ urtwn_lc_calib(struct urtwn_softc *sc)
}
static void
-urtwn_init_locked(void *arg)
+urtwn_init(struct urtwn_softc *sc)
{
- struct urtwn_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
uint32_t reg;
int error;
URTWN_ASSERT_LOCKED(sc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- urtwn_stop_locked(ifp);
+ if (sc->sc_flags & URTWN_RUNNING)
+ urtwn_stop(sc);
/* Init firmware commands ring. */
sc->fwcur = 0;
@@ -3340,8 +3277,8 @@ urtwn_init_locked(void *arg)
}
/* Set MAC address. */
- urtwn_write_region_1(sc, R92C_MACID, IF_LLADDR(ifp),
- IEEE80211_ADDR_LEN);
+ IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr);
+ urtwn_write_region_1(sc, R92C_MACID, macaddr, IEEE80211_ADDR_LEN);
/* Set initial network type. */
reg = urtwn_read_4(sc, R92C_CR);
@@ -3465,8 +3402,7 @@ urtwn_init_locked(void *arg)
usbd_transfer_start(sc->sc_xfer[URTWN_BULK_RX]);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_flags |= URTWN_RUNNING;
callout_reset(&sc->sc_watchdog_ch, hz, urtwn_watchdog, sc);
fail:
@@ -3474,39 +3410,16 @@ fail:
}
static void
-urtwn_init(void *arg)
-{
- struct urtwn_softc *sc = arg;
-
- URTWN_LOCK(sc);
- urtwn_init_locked(arg);
- URTWN_UNLOCK(sc);
-}
-
-static void
-urtwn_stop_locked(struct ifnet *ifp)
+urtwn_stop(struct urtwn_softc *sc)
{
- struct urtwn_softc *sc = ifp->if_softc;
URTWN_ASSERT_LOCKED(sc);
-
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-
+ sc->sc_flags &= ~URTWN_RUNNING;
callout_stop(&sc->sc_watchdog_ch);
urtwn_abort_xfers(sc);
}
static void
-urtwn_stop(struct ifnet *ifp)
-{
- struct urtwn_softc *sc = ifp->if_softc;
-
- URTWN_LOCK(sc);
- urtwn_stop_locked(ifp);
- URTWN_UNLOCK(sc);
-}
-
-static void
urtwn_abort_xfers(struct urtwn_softc *sc)
{
int i;
@@ -3523,12 +3436,11 @@ urtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct urtwn_softc *sc = ifp->if_softc;
+ struct urtwn_softc *sc = ic->ic_softc;
struct urtwn_data *bf;
/* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!(sc->sc_flags & URTWN_RUNNING)) {
m_freem(m);
ieee80211_free_node(ni);
return (ENETDOWN);
@@ -3542,10 +3454,8 @@ urtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return (ENOBUFS);
}
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if (urtwn_tx_start(sc, ni, m, bf) != 0) {
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
URTWN_UNLOCK(sc);
return (EIO);
diff --git a/sys/dev/usb/wlan/if_urtwnreg.h b/sys/dev/usb/wlan/if_urtwnreg.h
index 2bbec7a..0ca9db7 100644
--- a/sys/dev/usb/wlan/if_urtwnreg.h
+++ b/sys/dev/usb/wlan/if_urtwnreg.h
@@ -1172,7 +1172,8 @@ enum {
#define URTWN_EP_QUEUES URTWN_BULK_RX
struct urtwn_softc {
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
@@ -1180,6 +1181,7 @@ struct urtwn_softc {
u_int sc_flags;
#define URTWN_FLAG_CCK_HIPWR 0x01
#define URTWN_DETACHED 0x02
+#define URTWN_RUNNING 0x04
u_int chip;
#define URTWN_CHIP_92C 0x01
@@ -1224,7 +1226,6 @@ struct urtwn_softc {
uint8_t ht40_tx_pwr[5];
int8_t bw20_tx_pwr_diff;
int8_t ofdm_tx_pwr_diff;
- uint8_t sc_bssid[IEEE80211_ADDR_LEN];
struct callout sc_watchdog_ch;
struct mtx sc_mtx;
diff --git a/sys/dev/usb/wlan/if_urtwvar.h b/sys/dev/usb/wlan/if_urtwvar.h
index e99cbf4..a423214 100644
--- a/sys/dev/usb/wlan/if_urtwvar.h
+++ b/sys/dev/usb/wlan/if_urtwvar.h
@@ -93,14 +93,14 @@ struct urtw_vap {
#define URTW_VAP(vap) ((struct urtw_vap *)(vap))
struct urtw_softc {
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
struct mtx sc_mtx;
void *sc_tx_dma_buf;
int sc_debug;
- int sc_if_flags;
int sc_flags;
#define URTW_INIT_ONCE (1 << 1)
#define URTW_RTL8187B (1 << 2)
@@ -108,13 +108,13 @@ struct urtw_softc {
#define URTW_RTL8187B_REV_D (1 << 4)
#define URTW_RTL8187B_REV_E (1 << 5)
#define URTW_DETACHED (1 << 6)
+#define URTW_RUNNING (1 << 7)
enum ieee80211_state sc_state;
int sc_epromtype;
#define URTW_EEPROM_93C46 0
#define URTW_EEPROM_93C56 1
uint8_t sc_crcmon;
- uint8_t sc_bssid[IEEE80211_ADDR_LEN];
struct ieee80211_channel *sc_curchan;
diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c
index 8f9035e..a86ab8a 100644
--- a/sys/dev/usb/wlan/if_zyd.c
+++ b/sys/dev/usb/wlan/if_zyd.c
@@ -154,12 +154,12 @@ static int zyd_set_beacon_interval(struct zyd_softc *, int);
static void zyd_rx_data(struct usb_xfer *, int, uint16_t);
static int zyd_tx_start(struct zyd_softc *, struct mbuf *,
struct ieee80211_node *);
-static void zyd_start(struct ifnet *);
+static int zyd_transmit(struct ieee80211com *, struct mbuf *);
+static void zyd_start(struct zyd_softc *);
static int zyd_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
-static int zyd_ioctl(struct ifnet *, u_long, caddr_t);
+static void zyd_parent(struct ieee80211com *);
static void zyd_init_locked(struct zyd_softc *);
-static void zyd_init(void *);
static void zyd_stop(struct zyd_softc *);
static int zyd_loadfirmware(struct zyd_softc *);
static void zyd_scan_start(struct ieee80211com *);
@@ -333,8 +333,7 @@ zyd_attach(device_t dev)
{
struct usb_attach_arg *uaa = device_get_ivars(dev);
struct zyd_softc *sc = device_get_softc(dev);
- struct ifnet *ifp;
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
uint8_t iface_index, bands;
int error;
@@ -353,6 +352,7 @@ zyd_attach(device_t dev)
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
MTX_NETWORK_LOCK, MTX_DEF);
STAILQ_INIT(&sc->sc_rqh);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = ZYD_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device,
@@ -372,22 +372,6 @@ zyd_attach(device_t dev)
}
ZYD_UNLOCK(sc);
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(sc->sc_dev, "can not if_alloc()\n");
- goto detach;
- }
- ifp->if_softc = sc;
- if_initname(ifp, "zyd", device_get_unit(sc->sc_dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = zyd_init;
- ifp->if_ioctl = zyd_ioctl;
- ifp->if_start = zyd_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- IFQ_SET_READY(&ifp->if_snd);
-
- ic = ifp->if_l2com;
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -408,16 +392,17 @@ zyd_attach(device_t dev)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic, sc->sc_bssid);
+ ieee80211_ifattach(ic);
ic->ic_raw_xmit = zyd_raw_xmit;
ic->ic_scan_start = zyd_scan_start;
ic->ic_scan_end = zyd_scan_end;
ic->ic_set_channel = zyd_set_channel;
-
ic->ic_vap_create = zyd_vap_create;
ic->ic_vap_delete = zyd_vap_delete;
ic->ic_update_mcast = zyd_update_mcast;
ic->ic_update_promisc = zyd_update_mcast;
+ ic->ic_parent = zyd_parent;
+ ic->ic_transmit = zyd_transmit;
ieee80211_radiotap_attach(ic,
&sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
@@ -439,8 +424,7 @@ static int
zyd_detach(device_t dev)
{
struct zyd_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
unsigned int x;
/*
@@ -465,11 +449,9 @@ zyd_detach(device_t dev)
/* free USB transfers and some data buffers */
usbd_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER);
- if (ifp) {
- ic = ifp->if_l2com;
+ if (ic->ic_softc == sc)
ieee80211_ifdetach(ic);
- if_free(ifp);
- }
+ mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -486,15 +468,12 @@ zyd_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return (NULL);
- zvp = (struct zyd_vap *) malloc(sizeof(struct zyd_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (zvp == NULL)
- return (NULL);
+ zvp = malloc(sizeof(struct zyd_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &zvp->vap;
/* enable s/w bmiss handling for sta mode */
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
- flags | IEEE80211_CLONE_NOBEACONS, bssid, mac) != 0) {
+ flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) {
/* out of memory */
free(zvp, M_80211_VAP);
return (NULL);
@@ -509,7 +488,7 @@ zyd_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change,
- ieee80211_media_status);
+ ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return (vap);
}
@@ -530,13 +509,8 @@ zyd_tx_free(struct zyd_tx_data *data, int txerr)
struct zyd_softc *sc = data->sc;
if (data->m != NULL) {
- if (data->m->m_flags & M_TXCB)
- ieee80211_process_callback(data->ni, data->m,
- txerr ? ETIMEDOUT : 0);
- m_freem(data->m);
+ ieee80211_tx_complete(data->ni, data->m, txerr);
data->m = NULL;
-
- ieee80211_free_node(data->ni);
data->ni = NULL;
}
STAILQ_INSERT_TAIL(&sc->tx_free, data, next);
@@ -593,7 +567,7 @@ zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct zyd_vap *zvp = ZYD_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct zyd_softc *sc = ic->ic_ifp->if_softc;
+ struct zyd_softc *sc = ic->ic_softc;
int error;
DPRINTF(sc, ZYD_DEBUG_STATE, "%s: %s -> %s\n", __func__,
@@ -618,8 +592,8 @@ zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
/* make data LED blink upon Tx */
zyd_write32_m(sc, sc->sc_fwbase + ZYD_FW_LINK_STATUS, 1);
- IEEE80211_ADDR_COPY(sc->sc_bssid, vap->iv_bss->ni_bssid);
- zyd_set_bssid(sc, sc->sc_bssid);
+ IEEE80211_ADDR_COPY(ic->ic_macaddr, vap->iv_bss->ni_bssid);
+ zyd_set_bssid(sc, ic->ic_macaddr);
break;
default:
break;
@@ -637,8 +611,7 @@ static void
zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct zyd_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
struct zyd_cmd *cmd = &sc->sc_ibuf;
@@ -681,7 +654,9 @@ zyd_intr_read_callback(struct usb_xfer *xfer, usb_error_t error)
ieee80211_free_node(ni);
}
if (le16toh(retry->count) & 0x100)
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); /* too many retries */
+ /* too many retries */
+ if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS,
+ 1);
break;
}
case ZYD_NOTIF_IORD:
@@ -1243,8 +1218,7 @@ zyd_al2230_bandedge6(struct zyd_rf *rf, struct ieee80211_channel *c)
#define N(a) ((int)(sizeof(a) / sizeof((a)[0])))
int error = 0, i;
struct zyd_softc *sc = rf->rf_sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct zyd_phy_pair r[] = ZYD_AL2230_PHY_BANDEDGE6;
int chan = ieee80211_chan2ieee(ic, c);
@@ -1932,7 +1906,7 @@ zyd_get_macaddr(struct zyd_softc *sc)
USETW(req.wIndex, 0);
USETW(req.wLength, IEEE80211_ADDR_LEN);
- error = zyd_do_request(sc, &req, sc->sc_bssid);
+ error = zyd_do_request(sc, &req, sc->sc_ic.ic_macaddr);
if (error != 0) {
device_printf(sc->sc_dev, "could not read EEPROM: %s\n",
usbd_errstr(error));
@@ -2004,36 +1978,41 @@ fail:
static void
zyd_set_multi(struct zyd_softc *sc)
{
- int error;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifmultiaddr *ifma;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t low, high;
- uint8_t v;
+ int error;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0)
return;
low = 0x00000000;
high = 0x80000000;
- if (ic->ic_opmode == IEEE80211_M_MONITOR ||
- (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC))) {
+ if (ic->ic_opmode == IEEE80211_M_MONITOR || ic->ic_allmulti > 0 ||
+ ic->ic_promisc > 0) {
low = 0xffffffff;
high = 0xffffffff;
} else {
- if_maddr_rlock(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- v = ((uint8_t *)LLADDR((struct sockaddr_dl *)
- ifma->ifma_addr))[5] >> 2;
- if (v < 32)
- low |= 1 << v;
- else
- high |= 1 << (v - 32);
+ struct ieee80211vap *vap;
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+ uint8_t v;
+
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ ifp = vap->iv_ifp;
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ v = ((uint8_t *)LLADDR((struct sockaddr_dl *)
+ ifma->ifma_addr))[5] >> 2;
+ if (v < 32)
+ low |= 1 << v;
+ else
+ high |= 1 << (v - 32);
+ }
+ if_maddr_runlock(ifp);
}
- if_maddr_runlock(ifp);
}
/* reprogram multicast global hash table */
@@ -2050,9 +2029,6 @@ zyd_update_mcast(struct ieee80211com *ic)
{
struct zyd_softc *sc = ic->ic_softc;
- if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return;
-
ZYD_LOCK(sc);
zyd_set_multi(sc);
ZYD_UNLOCK(sc);
@@ -2061,8 +2037,7 @@ zyd_update_mcast(struct ieee80211com *ic)
static int
zyd_set_rxfilter(struct zyd_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
uint32_t rxfilter;
switch (ic->ic_opmode) {
@@ -2087,8 +2062,7 @@ static void
zyd_set_chan(struct zyd_softc *sc, struct ieee80211_channel *c)
{
int error;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct zyd_rf *rf = &sc->sc_rf;
uint32_t tmp;
int chan;
@@ -2179,8 +2153,7 @@ static void
zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
{
struct zyd_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct zyd_plcphdr plcp;
struct zyd_rx_stat stat;
struct usb_page_cache *pc;
@@ -2190,7 +2163,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
if (len < ZYD_MIN_FRAGSZ) {
DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too short (length=%d)\n",
device_get_nameunit(sc->sc_dev), len);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return;
}
pc = usbd_xfer_get_frame(xfer, 0);
@@ -2201,7 +2174,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
DPRINTF(sc, ZYD_DEBUG_RECV,
"%s: RX status indicated error (%x)\n",
device_get_nameunit(sc->sc_dev), stat.flags);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return;
}
@@ -2213,7 +2186,7 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
if (rlen > (int)MCLBYTES) {
DPRINTF(sc, ZYD_DEBUG_RECV, "%s: frame too long (length=%d)\n",
device_get_nameunit(sc->sc_dev), rlen);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return;
} else if (rlen > (int)MHLEN)
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
@@ -2222,10 +2195,9 @@ zyd_rx_data(struct usb_xfer *xfer, int offset, uint16_t len)
if (m == NULL) {
DPRINTF(sc, ZYD_DEBUG_RECV, "%s: could not allocate rx mbuf\n",
device_get_nameunit(sc->sc_dev));
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
return;
}
- m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = rlen;
usbd_copy_out(pc, offset + sizeof(plcp), mtod(m, uint8_t *), rlen);
@@ -2255,8 +2227,7 @@ static void
zyd_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct zyd_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
struct zyd_rx_desc desc;
struct mbuf *m;
@@ -2328,10 +2299,8 @@ tr_setup:
} else
(void)ieee80211_input_all(ic, m, rssi, nf);
}
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
- !IFQ_IS_EMPTY(&ifp->if_snd))
- zyd_start(ifp);
ZYD_LOCK(sc);
+ zyd_start(sc);
break;
default: /* Error */
@@ -2386,7 +2355,6 @@ static void
zyd_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct zyd_softc *sc = usbd_xfer_softc(xfer);
- struct ifnet *ifp = sc->sc_ifp;
struct ieee80211vap *vap;
struct zyd_tx_data *data;
struct mbuf *m;
@@ -2405,9 +2373,6 @@ zyd_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
zyd_tx_free(data, 0);
usbd_xfer_set_priv(xfer, NULL);
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
@@ -2440,16 +2405,14 @@ tr_setup:
usbd_xfer_set_priv(xfer, data);
usbd_transfer_submit(xfer);
}
- ZYD_UNLOCK(sc);
- zyd_start(ifp);
- ZYD_LOCK(sc);
+ zyd_start(sc);
break;
default: /* Error */
DPRINTF(sc, ZYD_DEBUG_ANY, "transfer error, %s\n",
usbd_errstr(error));
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
data = usbd_xfer_get_priv(xfer);
usbd_xfer_set_priv(xfer, NULL);
if (data != NULL)
@@ -2590,31 +2553,45 @@ zyd_tx_start(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
return (0);
}
+static int
+zyd_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct zyd_softc *sc = ic->ic_softc;
+ int error;
+
+ ZYD_LOCK(sc);
+ if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0) {
+ ZYD_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ ZYD_UNLOCK(sc);
+ return (error);
+ }
+ zyd_start(sc);
+ ZYD_UNLOCK(sc);
+
+ return (0);
+}
+
static void
-zyd_start(struct ifnet *ifp)
+zyd_start(struct zyd_softc *sc)
{
- struct zyd_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct mbuf *m;
- ZYD_LOCK(sc);
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
- if (sc->tx_nfree == 0) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
+ ZYD_LOCK_ASSERT(sc, MA_OWNED);
+
+ while (sc->tx_nfree > 0 && (m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (zyd_tx_start(sc, m, ni) != 0) {
ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ if_inc_counter(ni->ni_vap->iv_ifp,
+ IFCOUNTER_OERRORS, 1);
break;
}
}
- ZYD_UNLOCK(sc);
}
static int
@@ -2622,19 +2599,17 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct zyd_softc *sc = ifp->if_softc;
+ struct zyd_softc *sc = ic->ic_softc;
ZYD_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (!(sc->sc_flags & ZYD_FLAG_RUNNING)) {
ZYD_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
return (ENETDOWN);
}
if (sc->tx_nfree == 0) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
ZYD_UNLOCK(sc);
m_freem(m);
ieee80211_free_node(ni);
@@ -2648,7 +2623,6 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
*/
if (zyd_tx_start(sc, m, ni) != 0) {
ZYD_UNLOCK(sc);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
ieee80211_free_node(ni);
return (EIO);
}
@@ -2656,56 +2630,35 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return (0);
}
-static int
-zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+zyd_parent(struct ieee80211com *ic)
{
- struct zyd_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error;
+ struct zyd_softc *sc = ic->ic_softc;
int startall = 0;
ZYD_LOCK(sc);
- error = (sc->sc_flags & ZYD_FLAG_DETACHED) ? ENXIO : 0;
- ZYD_UNLOCK(sc);
- if (error)
- return (error);
-
- switch (cmd) {
- case SIOCSIFFLAGS:
- ZYD_LOCK(sc);
- if (ifp->if_flags & IFF_UP) {
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- zyd_init_locked(sc);
- startall = 1;
- } else
- zyd_set_multi(sc);
- } else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- zyd_stop(sc);
- }
+ if (sc->sc_flags & ZYD_FLAG_DETACHED) {
ZYD_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
+ return;
}
- return (error);
+ if (ic->ic_nrunning > 0) {
+ if ((sc->sc_flags & ZYD_FLAG_RUNNING) == 0) {
+ zyd_init_locked(sc);
+ startall = 1;
+ } else
+ zyd_set_multi(sc);
+ } else if (sc->sc_flags & ZYD_FLAG_RUNNING)
+ zyd_stop(sc);
+ ZYD_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
static void
zyd_init_locked(struct zyd_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct usb_config_descriptor *cd;
int error;
uint32_t val;
@@ -2757,12 +2710,12 @@ zyd_init_locked(struct zyd_softc *sc)
sc->sc_flags |= ZYD_FLAG_INITONCE;
}
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ if (sc->sc_flags & ZYD_FLAG_RUNNING)
zyd_stop(sc);
DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %6D\n",
- IF_LLADDR(ifp), ":");
- error = zyd_set_macaddr(sc, IF_LLADDR(ifp));
+ vap ? vap->iv_myaddr : ic->ic_macaddr, ":");
+ error = zyd_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
if (error != 0)
return;
@@ -2798,8 +2751,7 @@ zyd_init_locked(struct zyd_softc *sc)
/* enable interrupts */
zyd_write32_m(sc, ZYD_CR_INTERRUPT, ZYD_HWINT_MASK);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_flags |= ZYD_FLAG_RUNNING;
usbd_xfer_set_stall(sc->sc_xfer[ZYD_BULK_WR]);
usbd_transfer_start(sc->sc_xfer[ZYD_BULK_RD]);
usbd_transfer_start(sc->sc_xfer[ZYD_INTR_RD]);
@@ -2811,29 +2763,13 @@ fail: zyd_stop(sc);
}
static void
-zyd_init(void *priv)
-{
- struct zyd_softc *sc = priv;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
-
- ZYD_LOCK(sc);
- zyd_init_locked(sc);
- ZYD_UNLOCK(sc);
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ieee80211_start_all(ic); /* start all vap's */
-}
-
-static void
zyd_stop(struct zyd_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
int error;
ZYD_LOCK_ASSERT(sc, MA_OWNED);
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_flags &= ~ZYD_FLAG_RUNNING;
/*
* Drain all the transfers, if not already drained:
@@ -2925,30 +2861,29 @@ zyd_loadfirmware(struct zyd_softc *sc)
static void
zyd_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct zyd_softc *sc = ifp->if_softc;
+ struct zyd_softc *sc = ic->ic_softc;
ZYD_LOCK(sc);
/* want broadcast address while scanning */
- zyd_set_bssid(sc, ifp->if_broadcastaddr);
+ zyd_set_bssid(sc, ieee80211broadcastaddr);
ZYD_UNLOCK(sc);
}
static void
zyd_scan_end(struct ieee80211com *ic)
{
- struct zyd_softc *sc = ic->ic_ifp->if_softc;
+ struct zyd_softc *sc = ic->ic_softc;
ZYD_LOCK(sc);
/* restore previous bssid */
- zyd_set_bssid(sc, sc->sc_bssid);
+ zyd_set_bssid(sc, ic->ic_macaddr);
ZYD_UNLOCK(sc);
}
static void
zyd_set_channel(struct ieee80211com *ic)
{
- struct zyd_softc *sc = ic->ic_ifp->if_softc;
+ struct zyd_softc *sc = ic->ic_softc;
ZYD_LOCK(sc);
zyd_set_chan(sc, ic->ic_curchan);
diff --git a/sys/dev/usb/wlan/if_zydreg.h b/sys/dev/usb/wlan/if_zydreg.h
index 05d94e3..ec61d06 100644
--- a/sys/dev/usb/wlan/if_zydreg.h
+++ b/sys/dev/usb/wlan/if_zydreg.h
@@ -1249,7 +1249,8 @@ enum {
};
struct zyd_softc {
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
device_t sc_dev;
struct usb_device *sc_udev;
@@ -1260,13 +1261,13 @@ struct zyd_softc {
#define ZYD_FLAG_INITONCE (1 << 1)
#define ZYD_FLAG_INITDONE (1 << 2)
#define ZYD_FLAG_DETACHED (1 << 3)
+#define ZYD_FLAG_RUNNING (1 << 4)
struct zyd_rf sc_rf;
STAILQ_HEAD(, zyd_rq) sc_rtx;
STAILQ_HEAD(, zyd_rq) sc_rqh;
- uint8_t sc_bssid[IEEE80211_ADDR_LEN];
uint16_t sc_fwbase;
uint8_t sc_regdomain;
uint8_t sc_macrev;
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index b316d46..f8af231 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -116,11 +116,9 @@ static struct ieee80211vap *wi_vap_create(struct ieee80211com *,
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void wi_vap_delete(struct ieee80211vap *vap);
-static void wi_stop_locked(struct wi_softc *sc, int disable);
-static void wi_start_locked(struct ifnet *);
-static void wi_start(struct ifnet *);
-static int wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr,
- struct mbuf *m0);
+static int wi_transmit(struct ieee80211com *, struct mbuf *);
+static void wi_start(struct wi_softc *);
+static int wi_start_tx(struct wi_softc *, struct wi_frame *, struct mbuf *);
static int wi_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int wi_newstate_sta(struct ieee80211vap *, enum ieee80211_state, int);
@@ -131,10 +129,8 @@ static void wi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
int rssi, int nf);
static int wi_reset(struct wi_softc *);
static void wi_watchdog(void *);
-static int wi_ioctl(struct ifnet *, u_long, caddr_t);
+static void wi_parent(struct ieee80211com *);
static void wi_media_status(struct ifnet *, struct ifmediareq *);
-static uint64_t wi_get_counter(struct ifnet *, ift_counter);
-
static void wi_rx_intr(struct wi_softc *);
static void wi_tx_intr(struct wi_softc *);
static void wi_tx_ex_intr(struct wi_softc *);
@@ -153,10 +149,10 @@ static int wi_write_ssid(struct wi_softc *, int, u_int8_t *, int);
static int wi_cmd(struct wi_softc *, int, int, int, int);
static int wi_seek_bap(struct wi_softc *, int, int);
static int wi_read_bap(struct wi_softc *, int, int, void *, int);
-static int wi_write_bap(struct wi_softc *, int, int, void *, int);
+static int wi_write_bap(struct wi_softc *, int, int, const void *, int);
static int wi_mwrite_bap(struct wi_softc *, int, int, struct mbuf *, int);
static int wi_read_rid(struct wi_softc *, int, void *, int *);
-static int wi_write_rid(struct wi_softc *, int, void *, int);
+static int wi_write_rid(struct wi_softc *, int, const void *, int);
static int wi_write_appie(struct wi_softc *, int, const struct ieee80211_appie *);
static void wi_scan_start(struct ieee80211com *);
@@ -237,8 +233,7 @@ int
wi_attach(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic;
- struct ifnet *ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
int i, nrates, buflen;
u_int16_t val;
u_int8_t ratebuf[2 + IEEE80211_RATE_SIZE];
@@ -249,15 +244,6 @@ wi_attach(device_t dev)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int error;
- uint8_t macaddr[IEEE80211_ADDR_LEN];
-
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(dev, "can not if_alloc\n");
- wi_free(dev);
- return ENOSPC;
- }
- ic = ifp->if_l2com;
sc->sc_firmware_type = WI_NOTYPE;
sc->wi_cmd_count = 500;
@@ -309,6 +295,7 @@ wi_attach(device_t dev)
mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
MTX_DEF | MTX_RECURSE);
callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0);
+ mbufq_init(&sc->sc_snd, ifqmaxlen);
/*
* Read the station address.
@@ -317,12 +304,13 @@ wi_attach(device_t dev)
* the probe to fail.
*/
buflen = IEEE80211_ADDR_LEN;
- error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen);
+ error = wi_read_rid(sc, WI_RID_MAC_NODE, &ic->ic_macaddr, &buflen);
if (error != 0) {
buflen = IEEE80211_ADDR_LEN;
- error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen);
+ error = wi_read_rid(sc, WI_RID_MAC_NODE, &ic->ic_macaddr,
+ &buflen);
}
- if (error || IEEE80211_ADDR_EQ(macaddr, empty_macaddr)) {
+ if (error || IEEE80211_ADDR_EQ(&ic->ic_macaddr, empty_macaddr)) {
if (error != 0)
device_printf(dev, "mac read failed %d\n", error);
else {
@@ -333,18 +321,6 @@ wi_attach(device_t dev)
return (error);
}
- ifp->if_softc = sc;
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = wi_ioctl;
- ifp->if_start = wi_start;
- ifp->if_init = wi_init;
- ifp->if_get_counter = wi_get_counter;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_DS;
@@ -458,16 +434,17 @@ wi_attach(device_t dev)
sc->sc_portnum = WI_DEFAULT_PORT;
- ieee80211_ifattach(ic, macaddr);
+ ieee80211_ifattach(ic);
ic->ic_raw_xmit = wi_raw_xmit;
ic->ic_scan_start = wi_scan_start;
ic->ic_scan_end = wi_scan_end;
ic->ic_set_channel = wi_set_channel;
-
ic->ic_vap_create = wi_vap_create;
ic->ic_vap_delete = wi_vap_delete;
ic->ic_update_mcast = wi_update_mcast;
ic->ic_update_promisc = wi_update_promisc;
+ ic->ic_transmit = wi_transmit;
+ ic->ic_parent = wi_parent;
ieee80211_radiotap_attach(ic,
&sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th),
@@ -483,7 +460,6 @@ wi_attach(device_t dev)
if (error) {
device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
ieee80211_ifdetach(ic);
- if_free(sc->sc_ifp);
wi_free(dev);
return error;
}
@@ -495,21 +471,20 @@ int
wi_detach(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
WI_LOCK(sc);
/* check if device was removed */
sc->wi_gone |= !bus_child_present(dev);
- wi_stop_locked(sc, 0);
+ wi_stop(sc, 0);
WI_UNLOCK(sc);
ieee80211_ifdetach(ic);
bus_teardown_intr(dev, sc->irq, sc->wi_intrhand);
- if_free(sc->sc_ifp);
wi_free(dev);
+ mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
}
@@ -520,19 +495,16 @@ wi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct wi_softc *sc = ic->ic_ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
struct wi_vap *wvp;
struct ieee80211vap *vap;
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
- wvp = (struct wi_vap *) malloc(sizeof(struct wi_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (wvp == NULL)
- return NULL;
+ wvp = malloc(sizeof(struct wi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &wvp->wv_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
vap->iv_max_aid = WI_MAX_AID;
@@ -566,7 +538,7 @@ wi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
}
/* complete setup */
- ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status);
+ ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status, mac);
ic->ic_opmode = opmode;
return vap;
}
@@ -585,7 +557,9 @@ wi_shutdown(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
+ WI_LOCK(sc);
wi_stop(sc, 1);
+ WI_UNLOCK(sc);
return (0);
}
@@ -593,12 +567,12 @@ void
wi_intr(void *arg)
{
struct wi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
u_int16_t status;
WI_LOCK(sc);
- if (sc->wi_gone || !sc->sc_enabled || (ifp->if_flags & IFF_UP) == 0) {
+ if (sc->wi_gone || !sc->sc_enabled ||
+ (sc->sc_flags & WI_FLAGS_RUNNING) == 0) {
CSR_WRITE_2(sc, WI_INT_EN, 0);
CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);
WI_UNLOCK(sc);
@@ -617,9 +591,8 @@ wi_intr(void *arg)
wi_tx_ex_intr(sc);
if (status & WI_EV_INFO)
wi_info_intr(sc);
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
- !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- wi_start_locked(ifp);
+ if (mbufq_first(&sc->sc_snd) != NULL)
+ wi_start(sc);
/* Re-enable interrupts. */
CSR_WRITE_2(sc, WI_INT_EN, WI_INTRS);
@@ -642,7 +615,7 @@ wi_enable(struct wi_softc *sc)
static int
wi_setup_locked(struct wi_softc *sc, int porttype, int mode,
- uint8_t mac[IEEE80211_ADDR_LEN])
+ const uint8_t mac[IEEE80211_ADDR_LEN])
{
int i;
@@ -676,26 +649,25 @@ wi_setup_locked(struct wi_softc *sc, int porttype, int mode,
return 0;
}
-static void
-wi_init_locked(struct wi_softc *sc)
+void
+wi_init(struct wi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
int wasenabled;
WI_LOCK_ASSERT(sc);
wasenabled = sc->sc_enabled;
if (wasenabled)
- wi_stop_locked(sc, 1);
+ wi_stop(sc, 1);
- if (wi_setup_locked(sc, sc->sc_porttype, 3, IF_LLADDR(ifp)) != 0) {
- if_printf(ifp, "interface not running\n");
- wi_stop_locked(sc, 1);
+ if (wi_setup_locked(sc, sc->sc_porttype, 3,
+ sc->sc_ic.ic_macaddr) != 0) {
+ device_printf(sc->sc_dev, "interface not running\n");
+ wi_stop(sc, 1);
return;
}
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ sc->sc_flags |= WI_FLAGS_RUNNING;
callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
@@ -703,24 +675,8 @@ wi_init_locked(struct wi_softc *sc)
}
void
-wi_init(void *arg)
-{
- struct wi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
-
- WI_LOCK(sc);
- wi_init_locked(sc);
- WI_UNLOCK(sc);
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ieee80211_start_all(ic); /* start all vap's */
-}
-
-static void
-wi_stop_locked(struct wi_softc *sc, int disable)
+wi_stop(struct wi_softc *sc, int disable)
{
- struct ifnet *ifp = sc->sc_ifp;
WI_LOCK_ASSERT(sc);
@@ -736,22 +692,13 @@ wi_stop_locked(struct wi_softc *sc, int disable)
sc->sc_tx_timer = 0;
sc->sc_false_syns = 0;
- ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE | IFF_DRV_RUNNING);
-}
-
-void
-wi_stop(struct wi_softc *sc, int disable)
-{
- WI_LOCK(sc);
- wi_stop_locked(sc, disable);
- WI_UNLOCK(sc);
+ sc->sc_flags &= ~WI_FLAGS_RUNNING;
}
static void
wi_set_channel(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct wi_softc *sc = ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
DPRINTF(("%s: channel %d, %sscanning\n", __func__,
ieee80211_chan2ieee(ic, ic->ic_curchan),
@@ -766,8 +713,7 @@ wi_set_channel(struct ieee80211com *ic)
static void
wi_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct wi_softc *sc = ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
struct ieee80211_scan_state *ss = ic->ic_scan;
DPRINTF(("%s\n", __func__));
@@ -790,8 +736,7 @@ wi_scan_start(struct ieee80211com *ic)
static void
wi_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct wi_softc *sc = ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
DPRINTF(("%s: restore port type %d\n", __func__, sc->sc_porttype));
@@ -824,9 +769,8 @@ static int
wi_newstate_sta(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
struct ieee80211_node *bss;
- struct wi_softc *sc = ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
DPRINTF(("%s: %s -> %s\n", __func__,
ieee80211_state_name[vap->iv_state],
@@ -894,9 +838,8 @@ static int
wi_newstate_hostap(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
struct ieee80211_node *bss;
- struct wi_softc *sc = ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
int error;
DPRINTF(("%s: %s -> %s\n", __func__,
@@ -953,10 +896,30 @@ wi_newstate_hostap(struct ieee80211vap *vap, enum ieee80211_state nstate, int ar
return error;
}
+static int
+wi_transmit(struct ieee80211com *ic, struct mbuf *m)
+{
+ struct wi_softc *sc = ic->ic_softc;
+ int error;
+
+ WI_LOCK(sc);
+ if ((sc->sc_flags & WI_FLAGS_RUNNING) == 0) {
+ WI_UNLOCK(sc);
+ return (ENXIO);
+ }
+ error = mbufq_enqueue(&sc->sc_snd, m);
+ if (error) {
+ WI_UNLOCK(sc);
+ return (error);
+ }
+ wi_start(sc);
+ WI_UNLOCK(sc);
+ return (0);
+}
+
static void
-wi_start_locked(struct ifnet *ifp)
+wi_start(struct wi_softc *sc)
{
- struct wi_softc *sc = ifp->if_softc;
struct ieee80211_node *ni;
struct ieee80211_frame *wh;
struct mbuf *m0;
@@ -972,15 +935,8 @@ wi_start_locked(struct ifnet *ifp)
memset(&frmhdr, 0, sizeof(frmhdr));
cur = sc->sc_txnext;
- for (;;) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
- if (m0 == NULL)
- break;
- if (sc->sc_txd[cur].d_len != 0) {
- IFQ_DRV_PREPEND(&ifp->if_snd, m0);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
+ while (sc->sc_txd[cur].d_len == 0 &&
+ (m0 = mbufq_dequeue(&sc->sc_snd)) != NULL) {
ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
/* reconstruct 802.3 header */
@@ -1029,28 +985,16 @@ wi_start_locked(struct ifnet *ifp)
m_adj(m0, sizeof(struct ieee80211_frame));
frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
ieee80211_free_node(ni);
- if (wi_start_tx(ifp, &frmhdr, m0))
+ if (wi_start_tx(sc, &frmhdr, m0))
continue;
sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
}
}
-static void
-wi_start(struct ifnet *ifp)
-{
- struct wi_softc *sc = ifp->if_softc;
-
- WI_LOCK(sc);
- wi_start_locked(ifp);
- WI_UNLOCK(sc);
-}
-
static int
-wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0)
+wi_start_tx(struct wi_softc *sc, struct wi_frame *frmhdr, struct mbuf *m0)
{
- struct wi_softc *sc = ifp->if_softc;
int cur = sc->sc_txnext;
int fid, off, error;
@@ -1060,13 +1004,13 @@ wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0)
|| wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0;
m_freem(m0);
if (error) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
return -1;
}
sc->sc_txd[cur].d_len = off;
if (sc->sc_txcur == cur) {
if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, fid, 0, 0)) {
- if_printf(ifp, "xmit failed\n");
+ device_printf(sc->sc_dev, "xmit failed\n");
sc->sc_txd[cur].d_len = 0;
return -1;
}
@@ -1080,9 +1024,8 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
struct ieee80211vap *vap = ni->ni_vap;
- struct wi_softc *sc = ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
struct ieee80211_key *k;
struct ieee80211_frame *wh;
struct wi_frame frmhdr;
@@ -1098,7 +1041,6 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
memset(&frmhdr, 0, sizeof(frmhdr));
cur = sc->sc_txnext;
if (sc->sc_txd[cur].d_len != 0) {
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
rc = ENOBUFS;
goto out;
}
@@ -1129,7 +1071,7 @@ wi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m0,
(caddr_t)&frmhdr.wi_whdr);
m_adj(m0, sizeof(struct ieee80211_frame));
frmhdr.wi_dat_len = htole16(m0->m_pkthdr.len);
- if (wi_start_tx(ifp, &frmhdr, m0) < 0) {
+ if (wi_start_tx(sc, &frmhdr, m0) < 0) {
m0 = NULL;
rc = EIO;
goto out;
@@ -1160,7 +1102,7 @@ wi_reset(struct wi_softc *sc)
}
sc->sc_reset = 1;
if (i == WI_INIT_TRIES) {
- if_printf(sc->sc_ifp, "reset failed\n");
+ device_printf(sc->sc_dev, "reset failed\n");
return error;
}
@@ -1178,7 +1120,6 @@ static void
wi_watchdog(void *arg)
{
struct wi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
WI_LOCK_ASSERT(sc);
@@ -1186,65 +1127,52 @@ wi_watchdog(void *arg)
return;
if (sc->sc_tx_timer && --sc->sc_tx_timer == 0) {
- if_printf(ifp, "device timeout\n");
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- wi_init_locked(ifp->if_softc);
+ device_printf(sc->sc_dev, "device timeout\n");
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
+ wi_init(sc);
return;
}
callout_reset(&sc->sc_watchdog, hz, wi_watchdog, sc);
}
-static int
-wi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+wi_parent(struct ieee80211com *ic)
{
- struct wi_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifreq *ifr = (struct ifreq *) data;
- int error = 0, startall = 0;
+ struct wi_softc *sc = ic->ic_softc;
+ int startall = 0;
- switch (cmd) {
- case SIOCSIFFLAGS:
- WI_LOCK(sc);
- /*
- * Can't do promisc and hostap at the same time. If all that's
- * changing is the promisc flag, try to short-circuit a call to
- * wi_init() by just setting PROMISC in the hardware.
- */
- if (ifp->if_flags & IFF_UP) {
- if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
- ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if ((ifp->if_flags ^ sc->sc_if_flags) & IFF_PROMISC) {
- wi_write_val(sc, WI_RID_PROMISC,
- (ifp->if_flags & IFF_PROMISC) != 0);
- } else {
- wi_init_locked(sc);
- startall = 1;
- }
+ WI_LOCK(sc);
+ /*
+ * Can't do promisc and hostap at the same time. If all that's
+ * changing is the promisc flag, try to short-circuit a call to
+ * wi_init() by just setting PROMISC in the hardware.
+ */
+ if (ic->ic_nrunning > 0) {
+ if (ic->ic_opmode != IEEE80211_M_HOSTAP &&
+ sc->sc_flags & WI_FLAGS_RUNNING) {
+ if (ic->ic_promisc > 0 &&
+ (sc->sc_flags & WI_FLAGS_PROMISC) == 0) {
+ wi_write_val(sc, WI_RID_PROMISC, 1);
+ sc->sc_flags |= WI_FLAGS_PROMISC;
+ } else if (ic->ic_promisc == 0 &&
+ (sc->sc_flags & WI_FLAGS_PROMISC) != 0) {
+ wi_write_val(sc, WI_RID_PROMISC, 0);
+ sc->sc_flags &= ~WI_FLAGS_PROMISC;
} else {
- wi_init_locked(sc);
+ wi_init(sc);
startall = 1;
}
} else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- wi_stop_locked(sc, 1);
- sc->wi_gone = 0;
+ wi_init(sc);
+ startall = 1;
}
- sc->sc_if_flags = ifp->if_flags;
- WI_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- error = EINVAL;
- break;
+ } else if (sc->sc_flags & WI_FLAGS_RUNNING) {
+ wi_stop(sc, 1);
+ sc->wi_gone = 0;
}
- return error;
+ WI_UNLOCK(sc);
+ if (startall)
+ ieee80211_start_all(ic);
}
static void
@@ -1252,7 +1180,7 @@ wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
{
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
- struct wi_softc *sc = ic->ic_ifp->if_softc;
+ struct wi_softc *sc = ic->ic_softc;
u_int16_t val;
int rate, len;
@@ -1280,8 +1208,7 @@ wi_media_status(struct ifnet *ifp, struct ifmediareq *imr)
static void
wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni = vap->iv_bss;
@@ -1295,7 +1222,7 @@ wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
* indicator of the firmware's BSSID. Damp spurious
* change-of-BSSID indications.
*/
- if ((ifp->if_flags & IFF_PROMISC) != 0 &&
+ if (ic->ic_promisc > 0 &&
!ppsratecheck(&sc->sc_last_syn, &sc->sc_false_syns,
WI_MAX_FALSE_SYNS))
return;
@@ -1316,8 +1243,7 @@ wi_sync_bssid(struct wi_softc *sc, u_int8_t new_bssid[IEEE80211_ADDR_LEN])
static __noinline void
wi_rx_intr(struct wi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct wi_frame frmhdr;
struct mbuf *m;
struct ieee80211_frame *wh;
@@ -1332,7 +1258,7 @@ wi_rx_intr(struct wi_softc *sc)
/* First read in the frame header */
if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
DPRINTF(("wi_rx_intr: read fid %x failed\n", fid));
return;
}
@@ -1343,7 +1269,7 @@ wi_rx_intr(struct wi_softc *sc)
status = le16toh(frmhdr.wi_status);
if (status & WI_STAT_ERRSTAT) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
return;
}
@@ -1358,7 +1284,7 @@ wi_rx_intr(struct wi_softc *sc)
if (off + len > MCLBYTES) {
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
DPRINTF(("wi_rx_intr: oversized packet\n"));
return;
} else
@@ -1371,7 +1297,7 @@ wi_rx_intr(struct wi_softc *sc)
m = m_gethdr(M_NOWAIT, MT_DATA);
if (m == NULL) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ counter_u64_add(ic->ic_ierrors, 1);
DPRINTF(("wi_rx_intr: MGET failed\n"));
return;
}
@@ -1380,7 +1306,6 @@ wi_rx_intr(struct wi_softc *sc)
wi_read_bap(sc, fid, sizeof(frmhdr),
m->m_data + sizeof(struct ieee80211_frame), len);
m->m_pkthdr.len = m->m_len = sizeof(struct ieee80211_frame) + len;
- m->m_pkthdr.rcvif = ifp;
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
@@ -1425,7 +1350,6 @@ wi_rx_intr(struct wi_softc *sc)
static __noinline void
wi_tx_ex_intr(struct wi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
struct wi_frame frmhdr;
int fid;
@@ -1440,7 +1364,7 @@ wi_tx_ex_intr(struct wi_softc *sc)
*/
if ((status & WI_TXSTAT_DISCONNECT) == 0) {
if (ppsratecheck(&lasttxerror, &curtxeps, wi_txerate)) {
- if_printf(ifp, "tx failed");
+ device_printf(sc->sc_dev, "tx failed");
if (status & WI_TXSTAT_RET_ERR)
printf(", retry limit exceeded");
if (status & WI_TXSTAT_AGED_ERR)
@@ -1455,7 +1379,7 @@ wi_tx_ex_intr(struct wi_softc *sc)
printf(", status=0x%x", status);
printf("\n");
}
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ counter_u64_add(sc->sc_ic.ic_oerrors, 1);
} else
DPRINTF(("port disconnected\n"));
} else
@@ -1466,7 +1390,6 @@ wi_tx_ex_intr(struct wi_softc *sc)
static __noinline void
wi_tx_intr(struct wi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
int fid, cur;
if (sc->wi_gone)
@@ -1477,19 +1400,17 @@ wi_tx_intr(struct wi_softc *sc)
cur = sc->sc_txcur;
if (sc->sc_txd[cur].d_fid != fid) {
- if_printf(ifp, "bad alloc %x != %x, cur %d nxt %d\n",
+ device_printf(sc->sc_dev, "bad alloc %x != %x, cur %d nxt %d\n",
fid, sc->sc_txd[cur].d_fid, cur, sc->sc_txnext);
return;
}
sc->sc_tx_timer = 0;
sc->sc_txd[cur].d_len = 0;
sc->sc_txcur = cur = (cur + 1) % sc->sc_ntxbuf;
- if (sc->sc_txd[cur].d_len == 0)
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- else {
+ if (sc->sc_txd[cur].d_len != 0) {
if (wi_cmd(sc, WI_CMD_TX | WI_RECLAIM, sc->sc_txd[cur].d_fid,
0, 0)) {
- if_printf(ifp, "xmit failed\n");
+ device_printf(sc->sc_dev, "xmit failed\n");
sc->sc_txd[cur].d_len = 0;
} else {
sc->sc_tx_timer = 5;
@@ -1500,7 +1421,7 @@ wi_tx_intr(struct wi_softc *sc)
static __noinline void
wi_info_intr(struct wi_softc *sc)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
int i, fid, len, off;
u_int16_t ltbuf[2];
@@ -1574,32 +1495,15 @@ finish:
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
}
-static uint64_t
-wi_get_counter(struct ifnet *ifp, ift_counter cnt)
-{
- struct wi_softc *sc;
-
- sc = if_getsoftc(ifp);
-
- switch (cnt) {
- case IFCOUNTER_COLLISIONS:
- return (sc->sc_stats.wi_tx_single_retries +
- sc->sc_stats.wi_tx_multi_retries +
- sc->sc_stats.wi_tx_retry_limit);
- default:
- return (if_get_counter_default(ifp, cnt));
- }
-}
-
static int
wi_write_multi(struct wi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- int n;
- struct ifmultiaddr *ifma;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211vap *vap;
struct wi_mcast mlist;
+ int n;
- if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
+ if (ic->ic_allmulti > 0 || ic->ic_promisc > 0) {
allmulti:
memset(&mlist, 0, sizeof(mlist));
return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
@@ -1607,17 +1511,23 @@ allmulti:
}
n = 0;
- if_maddr_rlock(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (n >= 16)
- goto allmulti;
- IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
- (LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
- n++;
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+
+ ifp = vap->iv_ifp;
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ if (n >= 16)
+ goto allmulti;
+ IEEE80211_ADDR_COPY(&mlist.wi_mcast[n],
+ (LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
+ n++;
+ }
+ if_maddr_runlock(ifp);
}
- if_maddr_runlock(ifp);
return wi_write_rid(sc, WI_RID_MCAST_LIST, &mlist,
IEEE80211_ADDR_LEN * n);
}
@@ -1638,7 +1548,7 @@ wi_update_promisc(struct ieee80211com *ic)
/* XXX handle WEP special case handling? */
wi_write_val(sc, WI_RID_PROMISC,
(ic->ic_opmode == IEEE80211_M_MONITOR ||
- (ic->ic_ifp->if_flags & IFF_PROMISC)));
+ (ic->ic_promisc > 0)));
WI_UNLOCK(sc);
}
@@ -1937,7 +1847,7 @@ wi_read_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
}
static int
-wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
+wi_write_bap(struct wi_softc *sc, int id, int off, const void *buf, int buflen)
{
int error, cnt;
@@ -1949,7 +1859,7 @@ wi_write_bap(struct wi_softc *sc, int id, int off, void *buf, int buflen)
return error;
}
cnt = (buflen + 1) / 2;
- CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (u_int16_t *)buf, cnt);
+ CSR_WRITE_MULTI_STREAM_2(sc, WI_DATA0, (const uint16_t *)buf, cnt);
sc->sc_bap_off += cnt * 2;
return 0;
@@ -2039,7 +1949,7 @@ wi_read_rid(struct wi_softc *sc, int rid, void *buf, int *buflenp)
}
static int
-wi_write_rid(struct wi_softc *sc, int rid, void *buf, int buflen)
+wi_write_rid(struct wi_softc *sc, int rid, const void *buf, int buflen)
{
int error;
u_int16_t ltbuf[2];
diff --git a/sys/dev/wi/if_wi_pccard.c b/sys/dev/wi/if_wi_pccard.c
index fd70e77..414dc20d 100644
--- a/sys/dev/wi/if_wi_pccard.c
+++ b/sys/dev/wi/if_wi_pccard.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/systm.h>
+#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/bus.h>
diff --git a/sys/dev/wi/if_wi_pci.c b/sys/dev/wi/if_wi_pci.c
index 198c599..b218c24 100644
--- a/sys/dev/wi/if_wi_pci.c
+++ b/sys/dev/wi/if_wi_pci.c
@@ -238,7 +238,9 @@ wi_pci_suspend(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
+ WI_LOCK(sc);
wi_stop(sc, 1);
+ WI_UNLOCK(sc);
return (0);
}
@@ -247,16 +249,15 @@ static int
wi_pci_resume(device_t dev)
{
struct wi_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
- if (sc->wi_bus_type != WI_BUS_PCI_NATIVE)
+ WI_LOCK(sc);
+ if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
return (0);
-
- if (ifp->if_flags & IFF_UP) {
- ifp->if_init(ifp->if_softc);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- ifp->if_start(ifp);
+ WI_UNLOCK(sc);
}
-
+ if (ic->ic_nrunning > 0)
+ wi_init(sc);
+ WI_UNLOCK(sc);
return (0);
}
diff --git a/sys/dev/wi/if_wivar.h b/sys/dev/wi/if_wivar.h
index f163744..9b668cc 100644
--- a/sys/dev/wi/if_wivar.h
+++ b/sys/dev/wi/if_wivar.h
@@ -68,7 +68,8 @@ struct wi_vap {
#define WI_VAP(vap) ((struct wi_vap *)(vap))
struct wi_softc {
- struct ifnet *sc_ifp;
+ struct ieee80211com sc_ic;
+ struct mbufq sc_snd;
device_t sc_dev;
struct mtx sc_mtx;
struct callout sc_watchdog;
@@ -107,7 +108,6 @@ struct wi_softc {
int wi_cmd_count;
int sc_flags;
- int sc_if_flags;
int sc_bap_id;
int sc_bap_off;
@@ -152,6 +152,8 @@ struct wi_softc {
#define WI_FLAGS_HAS_ROAMING 0x0020
#define WI_FLAGS_HAS_FRAGTHR 0x0200
#define WI_FLAGS_HAS_DBMADJUST 0x0400
+#define WI_FLAGS_RUNNING 0x0800
+#define WI_FLAGS_PROMISC 0x1000
struct wi_card_ident {
u_int16_t card_id;
@@ -180,7 +182,7 @@ int wi_shutdown(device_t);
int wi_alloc(device_t, int);
void wi_free(device_t);
extern devclass_t wi_devclass;
-void wi_init(void *);
void wi_intr(void *);
int wi_mgmt_xmit(struct wi_softc *, caddr_t, int);
void wi_stop(struct wi_softc *, int);
+void wi_init(struct wi_softc *);
diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c
index 3440605..01ce3e4 100644
--- a/sys/dev/wpi/if_wpi.c
+++ b/sys/dev/wpi/if_wpi.c
@@ -205,12 +205,12 @@ static int wpi_tx_data_raw(struct wpi_softc *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int wpi_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
-static void wpi_start(struct ifnet *);
-static void wpi_start_task(void *, int);
+static int wpi_transmit(struct ieee80211com *, struct mbuf *);
+static void wpi_start(void *, int);
static void wpi_watchdog_rfkill(void *);
static void wpi_scan_timeout(void *);
static void wpi_tx_timeout(void *);
-static int wpi_ioctl(struct ifnet *, u_long, caddr_t);
+static void wpi_parent(struct ieee80211com *);
static int wpi_cmd(struct wpi_softc *, int, const void *, size_t, int);
static int wpi_mrr_setup(struct wpi_softc *);
static int wpi_add_node(struct wpi_softc *, struct ieee80211_node *);
@@ -272,7 +272,7 @@ static int wpi_hw_init(struct wpi_softc *);
static void wpi_hw_stop(struct wpi_softc *);
static void wpi_radio_on(void *, int);
static void wpi_radio_off(void *, int);
-static void wpi_init(void *);
+static int wpi_init(struct wpi_softc *);
static void wpi_stop_locked(struct wpi_softc *);
static void wpi_stop(struct wpi_softc *);
static void wpi_scan_start(struct ieee80211com *);
@@ -329,13 +329,11 @@ wpi_attach(device_t dev)
{
struct wpi_softc *sc = (struct wpi_softc *)device_get_softc(dev);
struct ieee80211com *ic;
- struct ifnet *ifp;
int i, error, rid;
#ifdef WPI_DEBUG
int supportsa = 1;
const struct wpi_ident *ident;
#endif
- uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
@@ -445,14 +443,7 @@ wpi_attach(device_t dev)
/* Clear pending interrupts. */
WPI_WRITE(sc, WPI_INT, 0xffffffff);
- ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- device_printf(dev, "can not allocate ifnet structure\n");
- goto fail;
- }
-
- ic = ifp->if_l2com;
- ic->ic_ifp = ifp;
+ ic = &sc->sc_ic;
ic->ic_softc = sc;
ic->ic_name = device_get_nameunit(dev);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@@ -481,7 +472,7 @@ wpi_attach(device_t dev)
* Read in the eeprom and also setup the channels for
* net80211. We don't set the rates as net80211 does this for us
*/
- if ((error = wpi_read_eeprom(sc, macaddr)) != 0) {
+ if ((error = wpi_read_eeprom(sc, ic->ic_macaddr)) != 0) {
device_printf(dev, "could not read EEPROM, error %d\n",
error);
goto fail;
@@ -503,20 +494,12 @@ wpi_attach(device_t dev)
}
#endif
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_softc = sc;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_init = wpi_init;
- ifp->if_ioctl = wpi_ioctl;
- ifp->if_start = wpi_start;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ieee80211_ifattach(ic, macaddr);
+ ieee80211_ifattach(ic);
ic->ic_vap_create = wpi_vap_create;
ic->ic_vap_delete = wpi_vap_delete;
+ ic->ic_parent = wpi_parent;
ic->ic_raw_xmit = wpi_raw_xmit;
+ ic->ic_transmit = wpi_transmit;
ic->ic_node_alloc = wpi_node_alloc;
sc->sc_node_free = ic->ic_node_free;
ic->ic_node_free = wpi_node_free;
@@ -543,7 +526,7 @@ wpi_attach(device_t dev)
TASK_INIT(&sc->sc_reinittask, 0, wpi_hw_reset, sc);
TASK_INIT(&sc->sc_radiooff_task, 0, wpi_radio_off, sc);
TASK_INIT(&sc->sc_radioon_task, 0, wpi_radio_on, sc);
- TASK_INIT(&sc->sc_start_task, 0, wpi_start_task, sc);
+ TASK_INIT(&sc->sc_start_task, 0, wpi_start, sc);
sc->sc_tq = taskqueue_create("wpi_taskq", M_WAITOK,
taskqueue_thread_enqueue, &sc->sc_tq);
@@ -588,14 +571,13 @@ fail: wpi_detach(dev);
static void
wpi_radiotap_attach(struct wpi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct wpi_rx_radiotap_header *rxtap = &sc->sc_rxtap;
+ struct wpi_tx_radiotap_header *txtap = &sc->sc_txtap;
+
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
- ieee80211_radiotap_attach(ic,
- &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
- WPI_TX_RADIOTAP_PRESENT,
- &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
- WPI_RX_RADIOTAP_PRESENT);
+ ieee80211_radiotap_attach(&sc->sc_ic,
+ &txtap->wt_ihdr, sizeof(*txtap), WPI_TX_RADIOTAP_PRESENT,
+ &rxtap->wr_ihdr, sizeof(*rxtap), WPI_RX_RADIOTAP_PRESENT);
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
}
@@ -646,12 +628,9 @@ wpi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
- wvp = (struct wpi_vap *) malloc(sizeof(struct wpi_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (wvp == NULL)
- return NULL;
+ wvp = malloc(sizeof(struct wpi_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &wvp->wv_vap;
- ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+ ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid);
if (opmode == IEEE80211_M_IBSS || opmode == IEEE80211_M_HOSTAP) {
WPI_VAP_LOCK_INIT(wvp);
@@ -671,7 +650,7 @@ wpi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
ieee80211_ratectl_init(vap);
/* Complete setup. */
ieee80211_vap_attach(vap, ieee80211_media_change,
- ieee80211_media_status);
+ ieee80211_media_status, mac);
ic->ic_opmode = opmode;
return vap;
}
@@ -700,22 +679,21 @@ static int
wpi_detach(device_t dev)
{
struct wpi_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic;
+ struct ieee80211com *ic = &sc->sc_ic;
int qid;
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
- if (ifp != NULL) {
- ic = ifp->if_l2com;
-
+ if (ic->ic_vap_create == wpi_vap_create) {
ieee80211_draintask(ic, &sc->sc_radioon_task);
ieee80211_draintask(ic, &sc->sc_start_task);
wpi_stop(sc);
- taskqueue_drain_all(sc->sc_tq);
- taskqueue_free(sc->sc_tq);
+ if (sc->sc_tq != NULL) {
+ taskqueue_drain_all(sc->sc_tq);
+ taskqueue_free(sc->sc_tq);
+ }
callout_drain(&sc->watchdog_rfkill);
callout_drain(&sc->tx_timeout);
@@ -748,9 +726,6 @@ wpi_detach(device_t dev)
bus_release_resource(dev, SYS_RES_MEMORY,
rman_get_rid(sc->mem), sc->mem);
- if (ifp != NULL)
- if_free(ifp);
-
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
WPI_TXQ_STATE_LOCK_DESTROY(sc);
WPI_TXQ_LOCK_DESTROY(sc);
@@ -774,7 +749,7 @@ static int
wpi_suspend(device_t dev)
{
struct wpi_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
ieee80211_suspend_all(ic);
return 0;
@@ -784,7 +759,7 @@ static int
wpi_resume(device_t dev)
{
struct wpi_softc *sc = device_get_softc(dev);
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
/* Clear device-specific "PCI retry timeout" register (41h). */
pci_write_config(dev, 0x41, 0, 1);
@@ -1191,6 +1166,7 @@ wpi_alloc_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring, int qid)
ring->queued = 0;
ring->cur = 0;
ring->update = 0;
+ mbufq_init(&ring->snd, ifqmaxlen);
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
@@ -1318,6 +1294,7 @@ wpi_reset_tx_ring(struct wpi_softc *sc, struct wpi_tx_ring *ring)
memset(ring->desc, 0, ring->desc_dma.size);
bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
BUS_DMASYNC_PREWRITE);
+ mbufq_drain(&ring->snd);
sc->qfullmsk &= ~(1 << ring->qid);
ring->queued = 0;
ring->cur = 0;
@@ -1448,8 +1425,7 @@ wpi_eeprom_channel_flags(struct wpi_eeprom_chan *channel)
static void
wpi_read_eeprom_band(struct wpi_softc *sc, int n)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct wpi_eeprom_chan *channels = sc->eeprom_channels[n];
const struct wpi_chan_band *band = &wpi_bands[n];
struct ieee80211_channel *c;
@@ -1506,8 +1482,7 @@ wpi_read_eeprom_band(struct wpi_softc *sc, int n)
static int
wpi_read_eeprom_channels(struct wpi_softc *sc, int n)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
const struct wpi_chan_band *band = &wpi_bands[n];
int error;
@@ -1549,8 +1524,7 @@ static int
wpi_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd,
int nchan, struct ieee80211_channel chans[])
{
- struct ifnet *ifp = ic->ic_ifp;
- struct wpi_softc *sc = ifp->if_softc;
+ struct wpi_softc *sc = ic->ic_softc;
int i;
for (i = 0; i < nchan; i++) {
@@ -1559,8 +1533,7 @@ wpi_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd,
channel = wpi_find_eeprom_channel(sc, c);
if (channel == NULL) {
- if_printf(ic->ic_ifp,
- "%s: invalid channel %u freq %u/0x%x\n",
+ ic_printf(ic, "%s: invalid channel %u freq %u/0x%x\n",
__func__, c->ic_ieee, c->ic_freq, c->ic_flags);
return EINVAL;
}
@@ -1672,8 +1645,7 @@ wpi_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN])
static void
wpi_node_free(struct ieee80211_node *ni)
{
- struct ieee80211com *ic = ni->ni_ic;
- struct wpi_softc *sc = ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = ni->ni_ic->ic_softc;
struct wpi_node *wn = WPI_NODE(ni);
if (wn->id != WPI_ID_UNDEFINED) {
@@ -1700,7 +1672,7 @@ wpi_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype,
int rssi, int nf)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct wpi_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = vap->iv_ic->ic_softc;
struct wpi_vap *wvp = WPI_VAP(vap);
uint64_t ni_tstamp, rx_tstamp;
@@ -1744,7 +1716,7 @@ wpi_restore_node(void *arg, struct ieee80211_node *ni)
static void
wpi_restore_node_table(struct wpi_softc *sc, struct wpi_vap *wvp)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
/* Set group keys once. */
WPI_NT_LOCK(sc);
@@ -1763,12 +1735,20 @@ wpi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct wpi_vap *wvp = WPI_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct wpi_softc *sc = ifp->if_softc;
+ struct wpi_softc *sc = ic->ic_softc;
int error = 0;
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
+ WPI_TXQ_LOCK(sc);
+ if (nstate > IEEE80211_S_INIT && sc->sc_running == 0) {
+ DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__);
+ WPI_TXQ_UNLOCK(sc);
+
+ return ENXIO;
+ }
+ WPI_TXQ_UNLOCK(sc);
+
DPRINTF(sc, WPI_DEBUG_STATE, "%s: %s -> %s\n", __func__,
ieee80211_state_name[vap->iv_state],
ieee80211_state_name[nstate]);
@@ -1937,8 +1917,7 @@ static void
wpi_rx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc,
struct wpi_rx_data *data)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct wpi_rx_ring *ring = &sc->rxq;
struct wpi_rx_stat *stat;
struct wpi_rx_head *head;
@@ -2019,7 +1998,6 @@ wpi_rx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc,
BUS_DMASYNC_PREWRITE);
/* Finalize mbuf. */
- m->m_pkthdr.rcvif = ifp;
m->m_data = (caddr_t)(head + 1);
m->m_pkthdr.len = m->m_len = len;
@@ -2073,7 +2051,7 @@ wpi_rx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc,
fail2: m_freem(m);
-fail1: if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+fail1: counter_u64_add(ic->ic_ierrors, 1);
}
static void
@@ -2086,7 +2064,6 @@ wpi_rx_statistics(struct wpi_softc *sc, struct wpi_rx_desc *desc,
static void
wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc)
{
- struct ifnet *ifp = sc->sc_ifp;
struct wpi_tx_ring *ring = &sc->txq[desc->qid & 0x3];
struct wpi_tx_data *data = &ring->data[desc->idx];
struct wpi_tx_stat *stat = (struct wpi_tx_stat *)(desc + 1);
@@ -2119,14 +2096,11 @@ wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc)
* Update rate control statistics for the node.
*/
if (status & WPI_TX_STATUS_FAIL) {
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &ackfailcnt, NULL);
- } else {
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ } else
ieee80211_ratectl_tx_complete(vap, ni,
IEEE80211_RATECTL_TX_SUCCESS, &ackfailcnt, NULL);
- }
ieee80211_tx_complete(ni, m, (status & WPI_TX_STATUS_FAIL) != 0);
@@ -2135,17 +2109,10 @@ wpi_tx_done(struct wpi_softc *sc, struct wpi_rx_desc *desc)
if (ring->queued > 0) {
callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, sc);
- if (sc->qfullmsk != 0 &&
- ring->queued < WPI_TX_RING_LOMARK) {
+ if ((sc->qfullmsk & (1 << ring->qid)) != 0 &&
+ ring->queued < WPI_TX_RING_LOMARK) {
sc->qfullmsk &= ~(1 << ring->qid);
- IF_LOCK(&ifp->if_snd);
- if (sc->qfullmsk == 0 &&
- (ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
- ieee80211_runtask(ic, &sc->sc_start_task);
- } else
- IF_UNLOCK(&ifp->if_snd);
+ ieee80211_runtask(ic, &sc->sc_start_task);
}
} else
callout_stop(&sc->tx_timeout);
@@ -2203,8 +2170,7 @@ wpi_cmd_done(struct wpi_softc *sc, struct wpi_rx_desc *desc)
static void
wpi_notif_intr(struct wpi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t hw;
@@ -2239,7 +2205,7 @@ wpi_notif_intr(struct wpi_softc *sc)
/* An 802.11 frame has been received. */
wpi_rx_done(sc, desc, data);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ if (sc->sc_running == 0) {
/* wpi_stop() was called. */
return;
}
@@ -2328,6 +2294,7 @@ wpi_notif_intr(struct wpi_softc *sc)
device_printf(sc->sc_dev,
"microcontroller initialization failed\n");
wpi_stop_locked(sc);
+ return;
}
/* Save the address of the error log in SRAM. */
sc->errptr = le32toh(uc->errptr);
@@ -2558,7 +2525,6 @@ static void
wpi_intr(void *arg)
{
struct wpi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
uint32_t r1, r2;
WPI_LOCK(sc);
@@ -2608,7 +2574,7 @@ wpi_intr(void *arg)
done:
/* Re-enable interrupts. */
- if (ifp->if_flags & IFF_UP)
+ if (sc->sc_running)
WPI_WRITE(sc, WPI_INT_MASK, WPI_INT_MASK_DEF);
end: WPI_UNLOCK(sc);
@@ -2617,7 +2583,6 @@ end: WPI_UNLOCK(sc);
static int
wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf)
{
- struct ifnet *ifp = sc->sc_ifp;
struct ieee80211_frame *wh;
struct wpi_tx_cmd *cmd;
struct wpi_tx_data *data;
@@ -2633,7 +2598,7 @@ wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf)
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
- if (sc->txq_active == 0) {
+ if (sc->sc_running == 0) {
/* wpi_stop() was called */
error = ENETDOWN;
goto fail;
@@ -2730,14 +2695,8 @@ wpi_cmd2(struct wpi_softc *sc, struct wpi_buf *buf)
if (ring->qid < WPI_CMD_QUEUE_NUM) {
/* Mark TX ring as full if we reach a certain threshold. */
WPI_TXQ_STATE_LOCK(sc);
- if (++ring->queued > WPI_TX_RING_HIMARK) {
+ if (++ring->queued > WPI_TX_RING_HIMARK)
sc->qfullmsk |= 1 << ring->qid;
-
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- IF_UNLOCK(&ifp->if_snd);
- }
-
callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, sc);
WPI_TXQ_STATE_UNLOCK(sc);
}
@@ -3031,24 +2990,47 @@ wpi_tx_data_raw(struct wpi_softc *sc, struct mbuf *m,
return wpi_cmd2(sc, &tx_data);
}
+static __inline int
+wpi_tx_ring_is_full(struct wpi_softc *sc, int ac)
+{
+ struct wpi_tx_ring *ring = &sc->txq[ac];
+ int retval;
+
+ WPI_TXQ_STATE_LOCK(sc);
+ retval = (ring->queued > WPI_TX_RING_HIMARK);
+ WPI_TXQ_STATE_UNLOCK(sc);
+
+ return retval;
+}
+
+static __inline void
+wpi_handle_tx_failure(struct ieee80211_node *ni)
+{
+ /* NB: m is reclaimed on tx failure */
+ if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, 1);
+ ieee80211_free_node(ni);
+}
+
static int
wpi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
- struct ifnet *ifp = ic->ic_ifp;
- struct wpi_softc *sc = ifp->if_softc;
- int error = 0;
+ struct wpi_softc *sc = ic->ic_softc;
+ int ac, error = 0;
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- ieee80211_free_node(ni);
+ ac = M_WME_GETAC(m);
+
+ WPI_TX_LOCK(sc);
+
+ if (sc->sc_running == 0 || wpi_tx_ring_is_full(sc, ac)) {
m_freem(m);
- return ENETDOWN;
+ error = sc->sc_running ? ENOBUFS : ENETDOWN;
+ goto unlock;
}
- WPI_TX_LOCK(sc);
if (params == NULL) {
/*
* Legacy path; interpret frame contents to decide
@@ -3062,13 +3044,11 @@ wpi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
*/
error = wpi_tx_data_raw(sc, m, ni, params);
}
- WPI_TX_UNLOCK(sc);
- if (error != 0) {
- /* NB: m is reclaimed on tx failure */
- ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+unlock: WPI_TX_UNLOCK(sc);
+ if (error != 0) {
+ wpi_handle_tx_failure(ni);
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__);
return error;
@@ -3079,57 +3059,88 @@ wpi_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
}
-/**
- * Process data waiting to be sent on the IFNET output queue
- */
-static void
-wpi_start(struct ifnet *ifp)
+static int
+wpi_transmit(struct ieee80211com *ic, struct mbuf *m)
{
- struct wpi_softc *sc = ifp->if_softc;
+ struct wpi_softc *sc = ic->ic_softc;
struct ieee80211_node *ni;
- struct mbuf *m;
+ struct mbufq *sndq;
+ int ac, error;
WPI_TX_LOCK(sc);
DPRINTF(sc, WPI_DEBUG_XMIT, "%s: called\n", __func__);
- for (;;) {
- IF_LOCK(&ifp->if_snd);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
- (ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
- IF_UNLOCK(&ifp->if_snd);
- break;
- }
- IF_UNLOCK(&ifp->if_snd);
+ /* Check if interface is up & running. */
+ if (sc->sc_running == 0) {
+ error = ENXIO;
+ goto unlock;
+ }
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- break;
- ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
- if (wpi_tx_data(sc, m, ni) != 0) {
- ieee80211_free_node(ni);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- }
+ /* Check for available space. */
+ ac = M_WME_GETAC(m);
+ sndq = &sc->txq[ac].snd;
+ if (wpi_tx_ring_is_full(sc, ac) || mbufq_len(sndq) != 0) {
+ /* wpi_tx_done() will dequeue it. */
+ error = mbufq_enqueue(sndq, m);
+ goto unlock;
+ }
+
+ error = 0;
+ ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
+ if (wpi_tx_data(sc, m, ni) != 0) {
+ wpi_handle_tx_failure(ni);
}
DPRINTF(sc, WPI_DEBUG_XMIT, "%s: done\n", __func__);
- WPI_TX_UNLOCK(sc);
+
+unlock: WPI_TX_UNLOCK(sc);
+
+ return (error);
}
+/**
+ * Process data waiting to be sent on the output queue
+ */
static void
-wpi_start_task(void *arg0, int pending)
+wpi_start(void *arg0, int pending)
{
struct wpi_softc *sc = arg0;
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211_node *ni;
+ struct mbuf *m;
+ uint8_t i;
+
+ WPI_TX_LOCK(sc);
+ if (sc->sc_running == 0)
+ goto unlock;
- wpi_start(ifp);
+ DPRINTF(sc, WPI_DEBUG_XMIT, "%s: called\n", __func__);
+
+ for (i = 0; i < WPI_CMD_QUEUE_NUM; i++) {
+ struct mbufq *sndq = &sc->txq[i].snd;
+
+ for (;;) {
+ if (wpi_tx_ring_is_full(sc, i))
+ break;
+
+ if ((m = mbufq_dequeue(sndq)) == NULL)
+ break;
+
+ ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
+ if (wpi_tx_data(sc, m, ni) != 0) {
+ wpi_handle_tx_failure(ni);
+ }
+ }
+ }
+
+ DPRINTF(sc, WPI_DEBUG_XMIT, "%s: done\n", __func__);
+unlock: WPI_TX_UNLOCK(sc);
}
static void
wpi_watchdog_rfkill(void *arg)
{
struct wpi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
DPRINTF(sc, WPI_DEBUG_WATCHDOG, "RFkill Watchdog: tick\n");
@@ -3146,9 +3157,9 @@ static void
wpi_scan_timeout(void *arg)
{
struct wpi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
- if_printf(ifp, "scan timeout\n");
+ ic_printf(ic, "scan timeout\n");
taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask);
}
@@ -3156,44 +3167,28 @@ static void
wpi_tx_timeout(void *arg)
{
struct wpi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = &sc->sc_ic;
- if_printf(ifp, "device timeout\n");
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ ic_printf(ic, "device timeout\n");
taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask);
}
-static int
-wpi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+static void
+wpi_parent(struct ieee80211com *ic)
{
- struct wpi_softc *sc = ifp->if_softc;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct wpi_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
- struct ifreq *ifr = (struct ifreq *) data;
- int error = 0;
- switch (cmd) {
- case SIOCGIFADDR:
- error = ether_ioctl(ifp, cmd, data);
- break;
- case SIOCSIFFLAGS:
- if (ifp->if_flags & IFF_UP) {
- wpi_init(sc);
-
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 &&
- vap != NULL)
- ieee80211_stop(vap);
- } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
- wpi_stop(sc);
- break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- default:
- error = EINVAL;
- break;
- }
- return error;
+ if (ic->ic_nrunning > 0) {
+ if (wpi_init(sc) == 0) {
+ ieee80211_notify_radio(ic, 1);
+ ieee80211_start_all(ic);
+ } else {
+ ieee80211_notify_radio(ic, 0);
+ ieee80211_stop(vap);
+ }
+ } else
+ wpi_stop(sc);
}
/*
@@ -3215,9 +3210,13 @@ wpi_cmd(struct wpi_softc *sc, int code, const void *buf, size_t size,
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
- if (sc->txq_active == 0) {
+ if (sc->sc_running == 0) {
/* wpi_stop() was called */
- error = 0;
+ if (code == WPI_CMD_SCAN)
+ error = ENETDOWN;
+ else
+ error = 0;
+
goto fail;
}
@@ -3283,10 +3282,7 @@ wpi_cmd(struct wpi_softc *sc, int code, const void *buf, size_t size,
WPI_TXQ_UNLOCK(sc);
- if (async)
- return 0;
-
- return mtx_sleep(cmd, &sc->sc_mtx, PCATCH, "wpicmd", hz);
+ return async ? 0 : mtx_sleep(cmd, &sc->sc_mtx, PCATCH, "wpicmd", hz);
fail: DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__);
@@ -3301,8 +3297,7 @@ fail: DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__);
static int
wpi_mrr_setup(struct wpi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct wpi_mrr_setup mrr;
int i, error;
@@ -3399,14 +3394,13 @@ wpi_add_node(struct wpi_softc *sc, struct ieee80211_node *ni)
static int
wpi_add_broadcast_node(struct wpi_softc *sc, int async)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct wpi_node_info node;
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__);
memset(&node, 0, sizeof node);
- IEEE80211_ADDR_COPY(node.macaddr, ifp->if_broadcastaddr);
+ IEEE80211_ADDR_COPY(node.macaddr, ieee80211broadcastaddr);
node.id = WPI_ID_BROADCAST;
node.plcp = (ic->ic_curmode == IEEE80211_MODE_11A) ?
wpi_ridx_to_plcp[WPI_RIDX_OFDM6] : wpi_ridx_to_plcp[WPI_RIDX_CCK1];
@@ -3492,7 +3486,7 @@ static int
wpi_updateedca(struct ieee80211com *ic)
{
#define WPI_EXP2(x) ((1 << (x)) - 1) /* CWmin = 2^ECWmin - 1 */
- struct wpi_softc *sc = ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = ic->ic_softc;
struct wpi_edca_params cmd;
int aci, error;
@@ -3526,8 +3520,7 @@ wpi_updateedca(struct ieee80211com *ic)
static void
wpi_set_promisc(struct wpi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t promisc_filter;
@@ -3535,7 +3528,7 @@ wpi_set_promisc(struct wpi_softc *sc)
if (vap != NULL && vap->iv_opmode != IEEE80211_M_HOSTAP)
promisc_filter |= WPI_FILTER_PROMISC;
- if (ifp->if_flags & IFF_PROMISC)
+ if (ic->ic_promisc > 0)
sc->rxon.filter |= htole32(promisc_filter);
else
sc->rxon.filter &= ~htole32(promisc_filter);
@@ -3900,8 +3893,7 @@ wpi_send_rxon(struct wpi_softc *sc, int assoc, int async)
static int
wpi_config(struct wpi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_channel *c = ic->ic_curchan;
int error;
@@ -4011,7 +4003,7 @@ wpi_get_active_dwell_time(struct wpi_softc *sc,
static uint16_t
wpi_limit_dwell(struct wpi_softc *sc, uint16_t dwell_time)
{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
int bintval = 0;
@@ -4068,8 +4060,7 @@ wpi_get_scan_pause_time(uint32_t time, uint16_t bintval)
static int
wpi_scan(struct wpi_softc *sc, struct ieee80211_channel *c)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_scan_state *ss = ic->ic_scan;
struct ieee80211vap *vap = ss->ss_vap;
struct wpi_scan_hdr *hdr;
@@ -4171,11 +4162,9 @@ wpi_scan(struct wpi_softc *sc, struct ieee80211_channel *c)
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
IEEE80211_FC0_SUBTYPE_PROBE_REQ;
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
- IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
+ IEEE80211_ADDR_COPY(wh->i_addr1, ieee80211broadcastaddr);
IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr);
- IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr);
- *(uint16_t *)&wh->i_dur[0] = 0; /* filled by h/w */
- *(uint16_t *)&wh->i_seq[0] = 0; /* filled by h/w */
+ IEEE80211_ADDR_COPY(wh->i_addr3, ieee80211broadcastaddr);
frm = (uint8_t *)(wh + 1);
frm = ieee80211_add_ssid(frm, NULL, 0);
@@ -4206,7 +4195,6 @@ wpi_scan(struct wpi_softc *sc, struct ieee80211_channel *c)
/*
* Calculate the active/passive dwell times.
*/
-
dwell_active = wpi_get_active_dwell_time(sc, c, nssid);
dwell_passive = wpi_get_passive_dwell_time(sc, c);
@@ -4324,7 +4312,7 @@ wpi_config_beacon(struct wpi_vap *wvp)
struct ieee80211com *ic = wvp->wv_vap.iv_ic;
struct ieee80211_beacon_offsets *bo = &wvp->wv_boff;
struct wpi_buf *bcn = &wvp->wv_bcbuf;
- struct wpi_softc *sc = ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = ic->ic_softc;
struct wpi_cmd_beacon *cmd = (struct wpi_cmd_beacon *)&bcn->data;
struct ieee80211_tim_ie *tie;
struct mbuf *m;
@@ -4406,7 +4394,7 @@ wpi_setup_beacon(struct wpi_softc *sc, struct ieee80211_node *ni)
static void
wpi_update_beacon(struct ieee80211vap *vap, int item)
{
- struct wpi_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = vap->iv_ic->ic_softc;
struct wpi_vap *wvp = WPI_VAP(vap);
struct wpi_buf *bcn = &wvp->wv_bcbuf;
struct ieee80211_beacon_offsets *bo = &wvp->wv_boff;
@@ -4448,7 +4436,7 @@ static void
wpi_newassoc(struct ieee80211_node *ni, int isnew)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = ni->ni_ic->ic_softc;
struct wpi_node *wn = WPI_NODE(ni);
int error;
@@ -4575,7 +4563,7 @@ wpi_load_key(struct ieee80211_node *ni, const struct ieee80211_key *k)
{
const struct ieee80211_cipher *cip = k->wk_cipher;
struct ieee80211vap *vap = ni->ni_vap;
- struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = ni->ni_ic->ic_softc;
struct wpi_node *wn = WPI_NODE(ni);
struct wpi_node_info node;
uint16_t kflags;
@@ -4639,7 +4627,7 @@ wpi_load_key_cb(void *arg, struct ieee80211_node *ni)
{
const struct ieee80211_key *k = arg;
struct ieee80211vap *vap = ni->ni_vap;
- struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = ni->ni_ic->ic_softc;
struct wpi_node *wn = WPI_NODE(ni);
int error;
@@ -4674,7 +4662,7 @@ static int
wpi_del_key(struct ieee80211_node *ni, const struct ieee80211_key *k)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = ni->ni_ic->ic_softc;
struct wpi_node *wn = WPI_NODE(ni);
struct wpi_node_info node;
uint16_t kflags;
@@ -4724,7 +4712,7 @@ wpi_del_key_cb(void *arg, struct ieee80211_node *ni)
{
const struct ieee80211_key *k = arg;
struct ieee80211vap *vap = ni->ni_vap;
- struct wpi_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = ni->ni_ic->ic_softc;
struct wpi_node *wn = WPI_NODE(ni);
int error;
@@ -4746,7 +4734,7 @@ wpi_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k,
int set)
{
struct ieee80211com *ic = vap->iv_ic;
- struct wpi_softc *sc = ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = ic->ic_softc;
struct wpi_vap *wvp = WPI_VAP(vap);
struct ieee80211_node *ni;
int error, ni_ref = 0;
@@ -5396,34 +5384,29 @@ static void
wpi_radio_on(void *arg0, int pending)
{
struct wpi_softc *sc = arg0;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
device_printf(sc->sc_dev, "RF switch: radio enabled\n");
- if (vap != NULL) {
- wpi_init(sc);
- ieee80211_init(vap);
- }
+ WPI_LOCK(sc);
+ callout_stop(&sc->watchdog_rfkill);
+ WPI_UNLOCK(sc);
- if (WPI_READ(sc, WPI_GP_CNTRL) & WPI_GP_CNTRL_RFKILL) {
- WPI_LOCK(sc);
- callout_stop(&sc->watchdog_rfkill);
- WPI_UNLOCK(sc);
- }
+ if (vap != NULL)
+ ieee80211_init(vap);
}
static void
wpi_radio_off(void *arg0, int pending)
{
struct wpi_softc *sc = arg0;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
device_printf(sc->sc_dev, "RF switch: radio disabled\n");
+ ieee80211_notify_radio(ic, 0);
wpi_stop(sc);
if (vap != NULL)
ieee80211_stop(vap);
@@ -5433,19 +5416,16 @@ wpi_radio_off(void *arg0, int pending)
WPI_UNLOCK(sc);
}
-static void
-wpi_init(void *arg)
+static int
+wpi_init(struct wpi_softc *sc)
{
- struct wpi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- int error;
+ int error = 0;
WPI_LOCK(sc);
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ if (sc->sc_running != 0)
goto end;
/* Check that the radio is not disabled by hardware switch. */
@@ -5454,6 +5434,7 @@ wpi_init(void *arg)
"RF switch: radio disabled (%s)\n", __func__);
callout_reset(&sc->watchdog_rfkill, hz, wpi_watchdog_rfkill,
sc);
+ error = EINPROGRESS;
goto end;
}
@@ -5462,9 +5443,11 @@ wpi_init(void *arg)
device_printf(sc->sc_dev,
"%s: could not read firmware, error %d\n", __func__,
error);
- goto fail;
+ goto end;
}
+ sc->sc_running = 1;
+
/* Initialize hardware and upload firmware. */
error = wpi_hw_init(sc);
wpi_unload_firmware(sc);
@@ -5476,7 +5459,6 @@ wpi_init(void *arg)
}
/* Configure adapter now that it is ready. */
- sc->txq_active = 1;
if ((error = wpi_config(sc)) != 0) {
device_printf(sc->sc_dev,
"%s: could not configure device, error %d\n", __func__,
@@ -5484,34 +5466,34 @@ wpi_init(void *arg)
goto fail;
}
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- IF_UNLOCK(&ifp->if_snd);
-
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
WPI_UNLOCK(sc);
- ieee80211_start_all(ic);
-
- return;
+ return 0;
fail: wpi_stop_locked(sc);
+
end: DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__);
WPI_UNLOCK(sc);
+
+ return error;
}
static void
wpi_stop_locked(struct wpi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
WPI_LOCK_ASSERT(sc);
+ if (sc->sc_running == 0)
+ return;
+
+ WPI_TX_LOCK(sc);
WPI_TXQ_LOCK(sc);
- sc->txq_active = 0;
+ sc->sc_running = 0;
WPI_TXQ_UNLOCK(sc);
+ WPI_TX_UNLOCK(sc);
WPI_TXQ_STATE_LOCK(sc);
callout_stop(&sc->tx_timeout);
@@ -5522,10 +5504,6 @@ wpi_stop_locked(struct wpi_softc *sc)
callout_stop(&sc->calib_to);
WPI_RXON_UNLOCK(sc);
- IF_LOCK(&ifp->if_snd);
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
- IF_UNLOCK(&ifp->if_snd);
-
/* Power OFF hardware. */
wpi_hw_stop(sc);
}
@@ -5544,7 +5522,7 @@ wpi_stop(struct wpi_softc *sc)
static void
wpi_scan_start(struct ieee80211com *ic)
{
- struct wpi_softc *sc = ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = ic->ic_softc;
wpi_set_led(sc, WPI_LED_LINK, 20, 2);
}
@@ -5555,8 +5533,7 @@ wpi_scan_start(struct ieee80211com *ic)
static void
wpi_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct wpi_softc *sc = ifp->if_softc;
+ struct wpi_softc *sc = ic->ic_softc;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
if (vap->iv_state == IEEE80211_S_RUN)
@@ -5571,8 +5548,7 @@ static void
wpi_set_channel(struct ieee80211com *ic)
{
const struct ieee80211_channel *c = ic->ic_curchan;
- struct ifnet *ifp = ic->ic_ifp;
- struct wpi_softc *sc = ifp->if_softc;
+ struct wpi_softc *sc = ic->ic_softc;
int error;
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__);
@@ -5618,7 +5594,7 @@ wpi_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
{
struct ieee80211vap *vap = ss->ss_vap;
struct ieee80211com *ic = vap->iv_ic;
- struct wpi_softc *sc = ic->ic_ifp->if_softc;
+ struct wpi_softc *sc = ic->ic_softc;
int error;
WPI_RXON_LOCK(sc);
@@ -5644,19 +5620,18 @@ static void
wpi_hw_reset(void *arg, int pending)
{
struct wpi_softc *sc = arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__);
+ ieee80211_notify_radio(ic, 0);
if (vap != NULL && (ic->ic_flags & IEEE80211_F_SCAN))
ieee80211_cancel_scan(vap);
wpi_stop(sc);
- if (vap != NULL)
+ if (vap != NULL) {
ieee80211_stop(vap);
- wpi_init(sc);
- if (vap != NULL)
ieee80211_init(vap);
+ }
}
diff --git a/sys/dev/wpi/if_wpivar.h b/sys/dev/wpi/if_wpivar.h
index b783528..4e1baa5 100644
--- a/sys/dev/wpi/if_wpivar.h
+++ b/sys/dev/wpi/if_wpivar.h
@@ -72,6 +72,7 @@ struct wpi_tx_ring {
struct wpi_tx_cmd *cmd;
struct wpi_tx_data data[WPI_TX_RING_COUNT];
bus_dma_tag_t data_dmat;
+ struct mbufq snd;
int qid;
int queued;
int cur;
@@ -164,14 +165,15 @@ struct wpi_fw_info {
struct wpi_softc {
device_t sc_dev;
-
- struct ifnet *sc_ifp;
int sc_debug;
int sc_flags;
#define WPI_PS_PATH (1 << 0)
+ int sc_running;
struct mtx sc_mtx;
+ struct ieee80211com sc_ic;
+
struct mtx tx_mtx;
/* Shared area. */
@@ -181,7 +183,6 @@ struct wpi_softc {
struct wpi_tx_ring txq[WPI_NTXQUEUES];
struct mtx txq_mtx;
struct mtx txq_state_mtx;
- uint32_t txq_active;
struct wpi_rx_ring rxq;
uint64_t rx_tstamp;
diff --git a/sys/dev/wtap/if_wtap.c b/sys/dev/wtap/if_wtap.c
index 7e2eca7..526ce54 100644
--- a/sys/dev/wtap/if_wtap.c
+++ b/sys/dev/wtap/if_wtap.c
@@ -163,13 +163,13 @@ wtap_media_change(struct ifnet *ifp)
*/
static void
wtap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
- int subtype, int rssi, int nf)
+ int subtype, const struct ieee80211_rx_stats *stats, int rssi, int nf)
{
struct ieee80211vap *vap = ni->ni_vap;
#if 0
DWTAP_PRINTF("[%d] %s\n", myath_id(ni), __func__);
#endif
- WTAP_VAP(vap)->av_recv_mgmt(ni, m, subtype, rssi, nf);
+ WTAP_VAP(vap)->av_recv_mgmt(ni, m, subtype, stats, rssi, nf);
}
static int
@@ -261,7 +261,7 @@ static int
wtap_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
struct ieee80211com *ic = vap->iv_ic;
- struct wtap_softc *sc = ic->ic_ifp->if_softc;
+ struct wtap_softc *sc = ic->ic_softc;
struct wtap_vap *avp = WTAP_VAP(vap);
struct ieee80211_node *ni = NULL;
int error;
@@ -318,7 +318,7 @@ wtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct wtap_softc *sc = ic->ic_ifp->if_softc;
+ struct wtap_softc *sc = ic->ic_softc;
struct ieee80211vap *vap;
struct wtap_vap *avp;
int error;
@@ -326,15 +326,13 @@ wtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
DWTAP_PRINTF("%s\n", __func__);
- avp = malloc(sizeof(struct wtap_vap), M_80211_VAP, M_NOWAIT | M_ZERO);
- if (avp == NULL)
- return (NULL);
+ avp = malloc(sizeof(struct wtap_vap), M_80211_VAP, M_WAITOK | M_ZERO);
avp->id = sc->id;
avp->av_md = sc->sc_md;
avp->av_bcinterval = msecs_to_ticks(BEACON_INTRERVAL + 100*sc->id);
vap = (struct ieee80211vap *) avp;
error = ieee80211_vap_setup(ic, vap, name, unit, IEEE80211_M_MBSS,
- flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
+ flags | IEEE80211_CLONE_NOBEACONS, bssid);
if (error) {
free(avp, M_80211_VAP);
return (NULL);
@@ -351,9 +349,10 @@ wtap_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ],
vap->iv_bmiss = wtap_bmiss;
/* complete setup */
- ieee80211_vap_attach(vap, wtap_media_change, ieee80211_media_status);
+ ieee80211_vap_attach(vap, wtap_media_change, ieee80211_media_status,
+ mac);
avp->av_dev = make_dev(&wtap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
- "%s", (const char *)ic->ic_ifp->if_xname);
+ "%s", (const char *)sc->name);
/* TODO this is a hack to force it to choose the rate we want */
ni = ieee80211_ref_node(vap->iv_bss);
@@ -374,148 +373,16 @@ wtap_vap_delete(struct ieee80211vap *vap)
free((struct wtap_vap*) vap, M_80211_VAP);
}
-/* NB: This function is not used.
- * I had the problem of the queue
- * being empty all the time.
- * Maybe I am setting the queue wrong?
- */
static void
-wtap_start(struct ifnet *ifp)
+wtap_parent(struct ieee80211com *ic)
{
- struct ieee80211com *ic = ifp->if_l2com;
- struct ifnet *icifp = ic->ic_ifp;
- struct wtap_softc *sc = icifp->if_softc;
- struct ieee80211_node *ni;
- struct mbuf *m;
-
- DWTAP_PRINTF("my_start, with id=%u\n", sc->id);
-
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->up == 0)
- return;
- for (;;) {
- if(IFQ_IS_EMPTY(&ifp->if_snd)){
- printf("queue empty, just trying to see "
- "if the other queue is empty\n");
-#if 0
- printf("queue for id=1, %u\n",
- IFQ_IS_EMPTY(&global_mscs[1]->ifp->if_snd));
- printf("queue for id=0, %u\n",
- IFQ_IS_EMPTY(&global_mscs[0]->ifp->if_snd));
-#endif
- break;
- }
- IFQ_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL) {
- printf("error dequeueing from ifp->snd\n");
- break;
- }
- ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- /*
- * Check for fragmentation. If this frame
- * has been broken up verify we have enough
- * buffers to send all the fragments so all
- * go out or none...
- */
-#if 0
- STAILQ_INIT(&frags);
-#endif
- if ((m->m_flags & M_FRAG)){
- printf("dont support frags\n");
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- return;
- }
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- if(wtap_raw_xmit(ni, m, NULL) < 0){
- printf("error raw_xmiting\n");
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- return;
- }
- }
-}
-
-static int
-wtap_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
-{
-#if 0
- DWTAP_PRINTF("%s\n", __func__);
- uprintf("%s, command %lu\n", __func__, cmd);
-#endif
-#define IS_RUNNING(ifp) \
- ((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
- struct ieee80211com *ic = ifp->if_l2com;
- struct wtap_softc *sc = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *)data;
- int error = 0;
-
- switch (cmd) {
- case SIOCSIFFLAGS:
- //printf("%s: %s\n", __func__, "SIOCSIFFLAGS");
- if (IS_RUNNING(ifp)) {
- DWTAP_PRINTF("running\n");
-#if 0
- /*
- * To avoid rescanning another access point,
- * do not call ath_init() here. Instead,
- * only reflect promisc mode settings.
- */
- //ath_mode_init(sc);
-#endif
- } else if (ifp->if_flags & IFF_UP) {
- DWTAP_PRINTF("up\n");
- sc->up = 1;
-#if 0
- /*
- * Beware of being called during attach/detach
- * to reset promiscuous mode. In that case we
- * will still be marked UP but not RUNNING.
- * However trying to re-init the interface
- * is the wrong thing to do as we've already
- * torn down much of our state. There's
- * probably a better way to deal with this.
- */
- //if (!sc->sc_invalid)
- // ath_init(sc); /* XXX lose error */
-#endif
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ieee80211_start_all(ic);
- } else {
- DWTAP_PRINTF("stoping\n");
-#if 0
- ath_stop_locked(ifp);
-#ifdef notyet
- /* XXX must wakeup in places like ath_vap_delete */
- if (!sc->sc_invalid)
- ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP);
-#endif
-#endif
- }
- break;
- case SIOCGIFMEDIA:
- case SIOCSIFMEDIA:
-#if 0
- DWTAP_PRINTF("%s: %s\n", __func__, "SIOCGIFMEDIA|SIOCSIFMEDIA");
-#endif
- error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
- break;
- case SIOCGIFADDR:
-#if 0
- DWTAP_PRINTF("%s: %s\n", __func__, "SIOCGIFADDR");
-#endif
- error = ether_ioctl(ifp, cmd, data);
- break;
- default:
- DWTAP_PRINTF("%s: %s [%lu]\n", __func__, "EINVAL", cmd);
- error = EINVAL;
- break;
- }
- return error;
-#undef IS_RUNNING
-}
-
-static void
-wtap_init(void *arg){
+ struct wtap_softc *sc = ic->ic_softc;
- DWTAP_PRINTF("%s\n", __func__);
+ if (ic->ic_nrunning > 0) {
+ sc->up = 1;
+ ieee80211_start_all(ic);
+ } else
+ sc->up = 0;
}
static void
@@ -581,8 +448,7 @@ wtap_inject(struct wtap_softc *sc, struct mbuf *m)
void
wtap_rx_deliver(struct wtap_softc *sc, struct mbuf *m)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
int type;
#if 0
@@ -591,11 +457,9 @@ wtap_rx_deliver(struct wtap_softc *sc, struct mbuf *m)
DWTAP_PRINTF("[%d] receiving m=%p\n", sc->id, m);
if (m == NULL) { /* NB: shouldn't happen */
- if_printf(ifp, "%s: no mbuf!\n", __func__);
+ ic_printf(ic, "%s: no mbuf!\n", __func__);
}
- if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
-
ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0);
/*
@@ -620,8 +484,7 @@ static void
wtap_rx_proc(void *arg, int npending)
{
struct wtap_softc *sc = (struct wtap_softc *)arg;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
struct mbuf *m;
struct ieee80211_node *ni;
int type;
@@ -644,12 +507,10 @@ wtap_rx_proc(void *arg, int npending)
m = bf->m;
DWTAP_PRINTF("[%d] receiving m=%p\n", sc->id, bf->m);
if (m == NULL) { /* NB: shouldn't happen */
- if_printf(ifp, "%s: no mbuf!\n", __func__);
+ ic_printf(ic, "%s: no mbuf!\n", __func__);
free(bf, M_WTAP_RXBUF);
return;
}
-
- if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
#if 0
ieee80211_dump_pkt(ic, mtod(m, caddr_t), 0,0,0);
#endif
@@ -716,7 +577,7 @@ wtap_update_promisc(struct ieee80211com *ic)
}
static int
-wtap_if_transmit(struct ifnet *ifp, struct mbuf *m)
+wtap_transmit(struct ieee80211com *ic, struct mbuf *m)
{
struct ieee80211_node *ni =
(struct ieee80211_node *) m->m_pkthdr.rcvif;
@@ -753,7 +614,7 @@ static void
wtap_node_free(struct ieee80211_node *ni)
{
struct ieee80211com *ic = ni->ni_ic;
- struct wtap_softc *sc = ic->ic_ifp->if_softc;
+ struct wtap_softc *sc = ic->ic_softc;
DWTAP_PRINTF("%s\n", __func__);
sc->sc_node_free(ni);
@@ -762,41 +623,17 @@ wtap_node_free(struct ieee80211_node *ni)
int32_t
wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
{
- struct ifnet *ifp;
- struct ieee80211com *ic;
- char wtap_name[] = {'w','T','a','p',sc->id,
- '_','t','a','s','k','q','\0'};
+ struct ieee80211com *ic = &sc->sc_ic;
DWTAP_PRINTF("%s\n", __func__);
- ifp = if_alloc(IFT_IEEE80211);
- if (ifp == NULL) {
- printf("can not if_alloc()\n");
- return -1;
- }
- ic = ifp->if_l2com;
- if_initname(ifp, "wtap", sc->id);
-
- sc->sc_ifp = ifp;
sc->up = 0;
-
STAILQ_INIT(&sc->sc_rxbuf);
- sc->sc_tq = taskqueue_create(wtap_name, M_NOWAIT | M_ZERO,
+ sc->sc_tq = taskqueue_create("wtap_taskq", M_NOWAIT | M_ZERO,
taskqueue_thread_enqueue, &sc->sc_tq);
- taskqueue_start_threads(&sc->sc_tq, 1, PI_SOFT, "%s taskQ",
- ifp->if_xname);
+ taskqueue_start_threads(&sc->sc_tq, 1, PI_SOFT, "%s taskQ", sc->name);
TASK_INIT(&sc->sc_rxtask, 0, wtap_rx_proc, sc);
- ifp->if_softc = sc;
- ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
- ifp->if_start = wtap_start;
- ifp->if_ioctl = wtap_ioctl;
- ifp->if_init = wtap_init;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
- ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
- IFQ_SET_READY(&ifp->if_snd);
-
- ic->ic_ifp = ifp;
ic->ic_softc = sc;
ic->ic_name = sc->name;
ic->ic_phytype = IEEE80211_T_DS;
@@ -815,17 +652,8 @@ wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
ic->ic_channels[0].ic_flags = IEEE80211_CHAN_B;
ic->ic_channels[0].ic_freq = 2412;
- ieee80211_ifattach(ic, macaddr);
-
-#if 0
- /* new prototype hook-ups */
- msc->if_input = ifp->if_input;
- ifp->if_input = myath_if_input;
- msc->if_output = ifp->if_output;
- ifp->if_output = myath_if_output;
-#endif
- sc->if_transmit = ifp->if_transmit;
- ifp->if_transmit = wtap_if_transmit;
+ IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
+ ieee80211_ifattach(ic);
/* override default methods */
ic->ic_newassoc = wtap_newassoc;
@@ -835,15 +663,14 @@ wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
ic->ic_raw_xmit = wtap_raw_xmit;
ic->ic_update_mcast = wtap_update_mcast;
ic->ic_update_promisc = wtap_update_promisc;
+ ic->ic_transmit = wtap_transmit;
+ ic->ic_parent = wtap_parent;
sc->sc_node_alloc = ic->ic_node_alloc;
ic->ic_node_alloc = wtap_node_alloc;
sc->sc_node_free = ic->ic_node_free;
ic->ic_node_free = wtap_node_free;
-#if 0
- ic->ic_node_getsignal = myath_node_getsignal;
-#endif
ic->ic_scan_start = wtap_scan_start;
ic->ic_scan_end = wtap_scan_end;
ic->ic_set_channel = wtap_set_channel;
@@ -882,13 +709,11 @@ wtap_attach(struct wtap_softc *sc, const uint8_t *macaddr)
int32_t
wtap_detach(struct wtap_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = &sc->sc_ic;
DWTAP_PRINTF("%s\n", __func__);
ieee80211_ageq_drain(&ic->ic_stageq);
ieee80211_ifdetach(ic);
- if_free(ifp);
return 0;
}
diff --git a/sys/dev/wtap/if_wtapvar.h b/sys/dev/wtap/if_wtapvar.h
index 3bdc898..04a1818 100644
--- a/sys/dev/wtap/if_wtapvar.h
+++ b/sys/dev/wtap/if_wtapvar.h
@@ -120,7 +120,7 @@ struct wtap_vap {
struct callout av_swba; /* software beacon alert */
uint32_t av_bcinterval; /* beacon interval */
void (*av_recv_mgmt)(struct ieee80211_node *,
- struct mbuf *, int, int, int);
+ struct mbuf *, int, const struct ieee80211_rx_stats *, int, int);
int (*av_newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
void (*av_bmiss)(struct ieee80211vap *);
@@ -130,18 +130,14 @@ struct wtap_vap {
struct taskqueue;
struct wtap_softc {
+ struct ieee80211com sc_ic;
char name[7]; /* wtapXX\0 */
int32_t id;
int32_t up;
- struct ifnet *sc_ifp; /* interface common */
struct wtap_medium *sc_md; /* interface medium */
struct ieee80211_node* (* sc_node_alloc)
(struct ieee80211vap *, const uint8_t [IEEE80211_ADDR_LEN]);
void (*sc_node_free)(struct ieee80211_node *);
- int (*if_output) /* output routine (enqueue) */
- (struct ifnet *, struct mbuf *, struct sockaddr *, struct route *);
- void (*if_input) (struct ifnet *, struct mbuf *);/* from h/w driver */
- int (*if_transmit)(struct ifnet *, struct mbuf *);/* output routine */
struct mtx sc_mtx; /* master lock (recursive) */
struct taskqueue *sc_tq; /* private task queue */
wtap_bufhead sc_rxbuf; /* receive buffer */
diff --git a/sys/dev/xen/balloon/balloon.c b/sys/dev/xen/balloon/balloon.c
index a6036d8..773644f 100644
--- a/sys/dev/xen/balloon/balloon.c
+++ b/sys/dev/xen/balloon/balloon.c
@@ -49,8 +49,6 @@ __FBSDID("$FreeBSD$");
#include <xen/features.h>
#include <xen/xenstore/xenstorevar.h>
-#include <machine/xen/xenvar.h>
-
static MALLOC_DEFINE(M_BALLOON, "Balloon", "Xen Balloon Driver");
/* Convert from KB (as fetched from xenstore) to number of PAGES */
diff --git a/sys/dev/xen/blkfront/blkfront.c b/sys/dev/xen/blkfront/blkfront.c
index 0610732..5ff9d38 100644
--- a/sys/dev/xen/blkfront/blkfront.c
+++ b/sys/dev/xen/blkfront/blkfront.c
@@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$");
#include <xen/xenbus/xenbusvar.h>
#include <machine/_inttypes.h>
-#include <machine/xen/xenvar.h>
#include <geom/geom_disk.h>
@@ -84,6 +83,11 @@ static void xbd_startio(struct xbd_softc *sc);
/*---------------------------- Global Static Data ----------------------------*/
static MALLOC_DEFINE(M_XENBLOCKFRONT, "xbd", "Xen Block Front driver data");
+static int xbd_enable_indirect = 1;
+SYSCTL_NODE(_hw, OID_AUTO, xbd, CTLFLAG_RD, 0, "xbd driver parameters");
+SYSCTL_INT(_hw_xbd, OID_AUTO, xbd_enable_indirect, CTLFLAG_RDTUN,
+ &xbd_enable_indirect, 0, "Enable xbd indirect segments");
+
/*---------------------------- Command Processing ----------------------------*/
static void
xbd_freeze(struct xbd_softc *sc, xbd_flag_t xbd_flag)
@@ -205,7 +209,6 @@ xbd_queue_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
struct xbd_softc *sc;
struct xbd_command *cm;
- blkif_request_t *ring_req;
int op;
cm = arg;
@@ -218,22 +221,47 @@ xbd_queue_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
return;
}
- KASSERT(nsegs <= BLKIF_MAX_SEGMENTS_PER_REQUEST,
+ KASSERT(nsegs <= sc->xbd_max_request_segments,
("Too many segments in a blkfront I/O"));
- /* Fill out a communications ring structure. */
- ring_req = RING_GET_REQUEST(&sc->xbd_ring, sc->xbd_ring.req_prod_pvt);
- sc->xbd_ring.req_prod_pvt++;
- ring_req->id = cm->cm_id;
- ring_req->operation = cm->cm_operation;
- ring_req->sector_number = cm->cm_sector_number;
- ring_req->handle = (blkif_vdev_t)(uintptr_t)sc->xbd_disk;
- ring_req->nr_segments = nsegs;
- cm->cm_nseg = nsegs;
- xbd_mksegarray(segs, nsegs, &cm->cm_gref_head,
- xenbus_get_otherend_id(sc->xbd_dev),
- cm->cm_operation == BLKIF_OP_WRITE,
- cm->cm_sg_refs, ring_req->seg);
+ if (nsegs <= BLKIF_MAX_SEGMENTS_PER_REQUEST) {
+ blkif_request_t *ring_req;
+
+ /* Fill out a blkif_request_t structure. */
+ ring_req = (blkif_request_t *)
+ RING_GET_REQUEST(&sc->xbd_ring, sc->xbd_ring.req_prod_pvt);
+ sc->xbd_ring.req_prod_pvt++;
+ ring_req->id = cm->cm_id;
+ ring_req->operation = cm->cm_operation;
+ ring_req->sector_number = cm->cm_sector_number;
+ ring_req->handle = (blkif_vdev_t)(uintptr_t)sc->xbd_disk;
+ ring_req->nr_segments = nsegs;
+ cm->cm_nseg = nsegs;
+ xbd_mksegarray(segs, nsegs, &cm->cm_gref_head,
+ xenbus_get_otherend_id(sc->xbd_dev),
+ cm->cm_operation == BLKIF_OP_WRITE,
+ cm->cm_sg_refs, ring_req->seg);
+ } else {
+ blkif_request_indirect_t *ring_req;
+
+ /* Fill out a blkif_request_indirect_t structure. */
+ ring_req = (blkif_request_indirect_t *)
+ RING_GET_REQUEST(&sc->xbd_ring, sc->xbd_ring.req_prod_pvt);
+ sc->xbd_ring.req_prod_pvt++;
+ ring_req->id = cm->cm_id;
+ ring_req->operation = BLKIF_OP_INDIRECT;
+ ring_req->indirect_op = cm->cm_operation;
+ ring_req->sector_number = cm->cm_sector_number;
+ ring_req->handle = (blkif_vdev_t)(uintptr_t)sc->xbd_disk;
+ ring_req->nr_segments = nsegs;
+ cm->cm_nseg = nsegs;
+ xbd_mksegarray(segs, nsegs, &cm->cm_gref_head,
+ xenbus_get_otherend_id(sc->xbd_dev),
+ cm->cm_operation == BLKIF_OP_WRITE,
+ cm->cm_sg_refs, cm->cm_indirectionpages);
+ memcpy(ring_req->indirect_grefs, &cm->cm_indirectionrefs,
+ sizeof(grant_ref_t) * sc->xbd_max_request_indirectpages);
+ }
if (cm->cm_operation == BLKIF_OP_READ)
op = BUS_DMASYNC_PREREAD;
@@ -733,7 +761,7 @@ xbd_alloc_ring(struct xbd_softc *sc)
i++, sring_page_addr += PAGE_SIZE) {
error = xenbus_grant_ring(sc->xbd_dev,
- (vtomach(sring_page_addr) >> PAGE_SHIFT),
+ (vtophys(sring_page_addr) >> PAGE_SHIFT),
&sc->xbd_ring_ref[i]);
if (error) {
xenbus_dev_fatal(sc->xbd_dev, error,
@@ -1015,6 +1043,16 @@ xbd_free(struct xbd_softc *sc)
cm->cm_sg_refs = NULL;
}
+ if (cm->cm_indirectionpages != NULL) {
+ gnttab_end_foreign_access_references(
+ sc->xbd_max_request_indirectpages,
+ &cm->cm_indirectionrefs[0]);
+ contigfree(cm->cm_indirectionpages, PAGE_SIZE *
+ sc->xbd_max_request_indirectpages,
+ M_XENBLOCKFRONT);
+ cm->cm_indirectionpages = NULL;
+ }
+
bus_dmamap_destroy(sc->xbd_io_dmat, cm->cm_map);
}
free(sc->xbd_shadow, M_XENBLOCKFRONT);
@@ -1051,9 +1089,6 @@ xbd_initialize(struct xbd_softc *sc)
*/
max_ring_page_order = 0;
sc->xbd_ring_pages = 1;
- sc->xbd_max_request_segments = BLKIF_MAX_SEGMENTS_PER_REQUEST;
- sc->xbd_max_request_size =
- XBD_SEGS_TO_SIZE(sc->xbd_max_request_segments);
/*
* Protocol negotiation.
@@ -1167,7 +1202,7 @@ xbd_connect(struct xbd_softc *sc)
unsigned long sectors, sector_size;
unsigned int binfo;
int err, feature_barrier, feature_flush;
- int i;
+ int i, j;
if (sc->xbd_state == XBD_STATE_CONNECTED ||
sc->xbd_state == XBD_STATE_SUSPENDED)
@@ -1198,6 +1233,22 @@ xbd_connect(struct xbd_softc *sc)
if (err == 0 && feature_flush != 0)
sc->xbd_flags |= XBDF_FLUSH;
+ err = xs_gather(XST_NIL, xenbus_get_otherend_path(dev),
+ "feature-max-indirect-segments", "%" PRIu32,
+ &sc->xbd_max_request_segments, NULL);
+ if ((err != 0) || (xbd_enable_indirect == 0))
+ sc->xbd_max_request_segments = 0;
+ if (sc->xbd_max_request_segments > XBD_MAX_INDIRECT_SEGMENTS)
+ sc->xbd_max_request_segments = XBD_MAX_INDIRECT_SEGMENTS;
+ if (sc->xbd_max_request_segments > XBD_SIZE_TO_SEGS(MAXPHYS))
+ sc->xbd_max_request_segments = XBD_SIZE_TO_SEGS(MAXPHYS);
+ sc->xbd_max_request_indirectpages =
+ XBD_INDIRECT_SEGS_TO_PAGES(sc->xbd_max_request_segments);
+ if (sc->xbd_max_request_segments < BLKIF_MAX_SEGMENTS_PER_REQUEST)
+ sc->xbd_max_request_segments = BLKIF_MAX_SEGMENTS_PER_REQUEST;
+ sc->xbd_max_request_size =
+ XBD_SEGS_TO_SIZE(sc->xbd_max_request_segments);
+
/* Allocate datastructures based on negotiated values. */
err = bus_dma_tag_create(
bus_get_dma_tag(sc->xbd_dev), /* parent */
@@ -1230,6 +1281,7 @@ xbd_connect(struct xbd_softc *sc)
for (i = 0; i < sc->xbd_max_requests; i++) {
struct xbd_command *cm;
+ void * indirectpages;
cm = &sc->xbd_shadow[i];
cm->cm_sg_refs = malloc(
@@ -1242,6 +1294,24 @@ xbd_connect(struct xbd_softc *sc)
cm->cm_sc = sc;
if (bus_dmamap_create(sc->xbd_io_dmat, 0, &cm->cm_map) != 0)
break;
+ if (sc->xbd_max_request_indirectpages > 0) {
+ indirectpages = contigmalloc(
+ PAGE_SIZE * sc->xbd_max_request_indirectpages,
+ M_XENBLOCKFRONT, M_ZERO, 0, ~0, PAGE_SIZE, 0);
+ } else {
+ indirectpages = NULL;
+ }
+ for (j = 0; j < sc->xbd_max_request_indirectpages; j++) {
+ if (gnttab_grant_foreign_access(
+ xenbus_get_otherend_id(sc->xbd_dev),
+ (vtophys(indirectpages) >> PAGE_SHIFT) + j,
+ 1 /* grant read-only access */,
+ &cm->cm_indirectionrefs[j]))
+ break;
+ }
+ if (j < sc->xbd_max_request_indirectpages)
+ break;
+ cm->cm_indirectionpages = indirectpages;
xbd_free_command(cm);
}
diff --git a/sys/dev/xen/blkfront/block.h b/sys/dev/xen/blkfront/block.h
index 8dcd322..28c6ff2 100644
--- a/sys/dev/xen/blkfront/block.h
+++ b/sys/dev/xen/blkfront/block.h
@@ -75,11 +75,25 @@
__CONST_RING_SIZE(blkif, PAGE_SIZE * XBD_MAX_RING_PAGES)
/**
- * The maximum mapped region size per request we will allow in a negotiated
- * block-front/back communication channel.
+ * The maximum number of blkif segments which can be provided per indirect
+ * page in an indirect request.
+ */
+#define XBD_MAX_SEGMENTS_PER_PAGE \
+ (PAGE_SIZE / sizeof(struct blkif_request_segment))
+
+/**
+ * The maximum number of blkif segments which can be provided in an indirect
+ * request.
+ */
+#define XBD_MAX_INDIRECT_SEGMENTS \
+ (BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST * XBD_MAX_SEGMENTS_PER_PAGE)
+
+/**
+ * Compute the number of indirect segment pages required for an I/O with the
+ * specified number of indirect segments.
*/
-#define XBD_MAX_REQUEST_SIZE \
- MIN(MAXPHYS, XBD_SEGS_TO_SIZE(BLKIF_MAX_SEGMENTS_PER_REQUEST))
+#define XBD_INDIRECT_SEGS_TO_PAGES(segs) \
+ ((segs + XBD_MAX_SEGMENTS_PER_PAGE - 1) / XBD_MAX_SEGMENTS_PER_PAGE)
typedef enum {
XBDCF_Q_MASK = 0xFF,
@@ -111,6 +125,8 @@ struct xbd_command {
blkif_sector_t cm_sector_number;
int cm_status;
xbd_cbcf_t *cm_complete;
+ void *cm_indirectionpages;
+ grant_ref_t cm_indirectionrefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
};
typedef enum {
@@ -165,6 +181,7 @@ struct xbd_softc {
uint32_t xbd_max_requests;
uint32_t xbd_max_request_segments;
uint32_t xbd_max_request_size;
+ uint32_t xbd_max_request_indirectpages;
grant_ref_t xbd_ring_ref[XBD_MAX_RING_PAGES];
blkif_front_ring_t xbd_ring;
xen_intr_handle_t xen_intr_handle;
diff --git a/sys/dev/xen/control/control.c b/sys/dev/xen/control/control.c
index 2a0d459..219a395 100644
--- a/sys/dev/xen/control/control.c
+++ b/sys/dev/xen/control/control.c
@@ -145,9 +145,6 @@ __FBSDID("$FreeBSD$");
#include <xen/xenbus/xenbusvar.h>
-#include <machine/xen/xenvar.h>
-#include <machine/xen/xenfunc.h>
-
/*--------------------------- Forward Declarations --------------------------*/
/** Function signature for shutdown event handlers. */
typedef void (xctrl_shutdown_handler_t)(void);
diff --git a/sys/dev/xen/netback/netback.c b/sys/dev/xen/netback/netback.c
index 2233084..c58b324 100644
--- a/sys/dev/xen/netback/netback.c
+++ b/sys/dev/xen/netback/netback.c
@@ -87,8 +87,6 @@ __FBSDID("$FreeBSD$");
#include <xen/interface/io/netif.h>
#include <xen/xenbus/xenbusvar.h>
-#include <machine/xen/xenvar.h>
-
/*--------------------------- Compile-time Tunables --------------------------*/
/*---------------------------------- Macros ----------------------------------*/
@@ -132,7 +130,7 @@ static MALLOC_DEFINE(M_XENNETBACK, "xnb", "Xen Net Back Driver Data");
req < rsp ? req : rsp; \
})
-#define virt_to_mfn(x) (vtomach(x) >> PAGE_SHIFT)
+#define virt_to_mfn(x) (vtophys(x) >> PAGE_SHIFT)
#define virt_to_offset(x) ((x) & (PAGE_SIZE - 1))
/**
diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c
index 3eac25d..2f972b8 100644
--- a/sys/dev/xen/netfront/netfront.c
+++ b/sys/dev/xen/netfront/netfront.c
@@ -86,8 +86,6 @@ __FBSDID("$FreeBSD$");
#include <xen/interface/io/netif.h>
#include <xen/xenbus/xenbusvar.h>
-#include <machine/xen/xenvar.h>
-
#include "xenbus_if.h"
/* Features supported by all backends. TSO and LRO can be negotiated */
@@ -190,7 +188,7 @@ static int xennet_get_responses(struct netfront_info *np,
struct netfront_rx_info *rinfo, RING_IDX rp, RING_IDX *cons,
struct mbuf **list, int *pages_flipped_p);
-#define virt_to_mfn(x) (vtomach(x) >> PAGE_SHIFT)
+#define virt_to_mfn(x) (vtophys(x) >> PAGE_SHIFT)
#define INVALID_P2M_ENTRY (~0UL)
@@ -901,7 +899,7 @@ refill:
req->gref = ref;
sc->rx_pfn_array[i] =
- vtomach(mtod(m_new,vm_offset_t)) >> PAGE_SHIFT;
+ vtophys(mtod(m_new,vm_offset_t)) >> PAGE_SHIFT;
}
KASSERT(i, ("no mbufs processed")); /* should have returned earlier */
diff --git a/sys/dev/xen/pcifront/pcifront.c b/sys/dev/xen/pcifront/pcifront.c
index 1613e0a..1730bf8 100644
--- a/sys/dev/xen/pcifront/pcifront.c
+++ b/sys/dev/xen/pcifront/pcifront.c
@@ -78,7 +78,7 @@ __FBSDID("$FreeBSD$");
#define INVALID_GRANT_REF (0)
#define INVALID_EVTCHN (-1)
-#define virt_to_mfn(x) (vtomach(x) >> PAGE_SHIFT)
+#define virt_to_mfn(x) (vtophys(x) >> PAGE_SHIFT)
struct pcifront_device {
STAILQ_ENTRY(pcifront_device) next;
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index fe8e9ef..8068437 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -1774,13 +1774,24 @@ devfs_mmap_f(struct file *fp, vm_map_t map, vm_offset_t *addr, vm_size_t size,
return (EACCES);
/*
- * Character devices always share mappings, so
- * require a writable fd for writable mappings.
+ * If we are sharing potential changes via MAP_SHARED and we
+ * are trying to get write permission although we opened it
+ * without asking for it, bail out.
+ *
+ * Note that most character devices always share mappings.
+ * The one exception is that D_MMAP_ANON devices
+ * (i.e. /dev/zero) permit private writable mappings.
+ *
+ * Rely on vm_mmap_cdev() to fail invalid MAP_PRIVATE requests
+ * as well as updating maxprot to permit writing for
+ * D_MMAP_ANON devices rather than doing that here.
*/
- if ((fp->f_flag & FWRITE) != 0)
- maxprot |= VM_PROT_WRITE;
- else if ((prot & VM_PROT_WRITE) != 0)
- return (EACCES);
+ if ((flags & MAP_SHARED) != 0) {
+ if ((fp->f_flag & FWRITE) != 0)
+ maxprot |= VM_PROT_WRITE;
+ else if ((prot & VM_PROT_WRITE) != 0)
+ return (EACCES);
+ }
maxprot &= cap_maxprot;
fpop = td->td_fpop;
diff --git a/sys/fs/ext2fs/ext2_subr.c b/sys/fs/ext2fs/ext2_subr.c
index 6b9041d..1c5c3bb 100644
--- a/sys/fs/ext2fs/ext2_subr.c
+++ b/sys/fs/ext2fs/ext2_subr.c
@@ -54,10 +54,6 @@
#include <fs/ext2fs/ext2_mount.h>
#include <fs/ext2fs/ext2_dinode.h>
-#ifdef KDB
-void ext2_checkoverlap(struct buf *, struct inode *);
-#endif
-
/*
* Return buffer with the contents of block "offset" from the beginning of
* directory "ip". If "res" is non-zero, fill it in with a pointer to the
@@ -130,34 +126,6 @@ normal:
return (0);
}
-#ifdef KDB
-void
-ext2_checkoverlap(struct buf *bp, struct inode *ip)
-{
- struct buf *ebp, *ep;
- e4fs_daddr_t start, last;
- struct vnode *vp;
-
- ebp = &buf[nbuf];
- start = bp->b_blkno;
- last = start + btodb(bp->b_bcount) - 1;
- for (ep = buf; ep < ebp; ep++) {
- if (ep == bp || (ep->b_flags & B_INVAL))
- continue;
- vp = ip->i_ump->um_devvp;
- /* look for overlap */
- if (ep->b_bcount == 0 || ep->b_blkno > last ||
- ep->b_blkno + btodb(ep->b_bcount) <= start)
- continue;
- vprint("Disk overlap", vp);
- printf("\tstart %jd, end %jd overlap start %jd, end %jd\n",
- (intmax_t)start, (intmax_t)last, (intmax_t)ep->b_blkno,
- (intmax_t)(ep->b_blkno + btodb(ep->b_bcount) - 1));
- panic("ext2_checkoverlap: Disk buffer overlap");
- }
-}
-#endif /* KDB */
-
/*
* Update the cluster map because of an allocation of free like ffs.
*
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index d3bac30..a6a2167 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -42,7 +42,9 @@ __FBSDID("$FreeBSD$");
* generally, I don't like #includes inside .h files, but it seems to
* be the easiest way to handle the port.
*/
+#include <sys/fail.h>
#include <sys/hash.h>
+#include <sys/sysctl.h>
#include <fs/nfs/nfsport.h>
#include <netinet/if_ether.h>
#include <net/if_types.h>
@@ -83,6 +85,16 @@ NFSDLOCKMUTEX;
extern void (*ncl_call_invalcaches)(struct vnode *);
+SYSCTL_DECL(_vfs_nfs);
+static int ncl_fileid_maxwarnings = 10;
+SYSCTL_INT(_vfs_nfs, OID_AUTO, fileid_maxwarnings, CTLFLAG_RWTUN,
+ &ncl_fileid_maxwarnings, 0,
+ "Limit fileid corruption warnings; 0 is off; -1 is unlimited");
+static volatile int ncl_fileid_nwarnings;
+
+static void nfscl_warn_fileid(struct nfsmount *, struct nfsvattr *,
+ struct nfsvattr *);
+
/*
* Comparison function for vfs_hash functions.
*/
@@ -343,6 +355,37 @@ nfscl_ngetreopen(struct mount *mntp, u_int8_t *fhp, int fhsize,
return (EINVAL);
}
+static void
+nfscl_warn_fileid(struct nfsmount *nmp, struct nfsvattr *oldnap,
+ struct nfsvattr *newnap)
+{
+ int off;
+
+ if (ncl_fileid_maxwarnings >= 0 &&
+ ncl_fileid_nwarnings >= ncl_fileid_maxwarnings)
+ return;
+ off = 0;
+ if (ncl_fileid_maxwarnings >= 0) {
+ if (++ncl_fileid_nwarnings >= ncl_fileid_maxwarnings)
+ off = 1;
+ }
+
+ printf("newnfs: server '%s' error: fileid changed. "
+ "fsid %jx:%jx: expected fileid %#jx, got %#jx. "
+ "(BROKEN NFS SERVER OR MIDDLEWARE)\n",
+ nmp->nm_com.nmcom_hostname,
+ (uintmax_t)nmp->nm_fsid[0],
+ (uintmax_t)nmp->nm_fsid[1],
+ (uintmax_t)oldnap->na_fileid,
+ (uintmax_t)newnap->na_fileid);
+
+ if (off)
+ printf("newnfs: Logged %d times about fileid corruption; "
+ "going quiet to avoid spamming logs excessively. (Limit "
+ "is: %d).\n", ncl_fileid_nwarnings,
+ ncl_fileid_maxwarnings);
+}
+
/*
* Load the attribute cache (that lives in the nfsnode entry) with
* the attributes of the second argument and
@@ -361,7 +404,11 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper,
struct nfsmount *nmp;
struct timespec mtime_save;
u_quad_t nsize;
- int setnsize;
+ int setnsize, error, force_fid_err;
+
+ error = 0;
+ setnsize = 0;
+ nsize = 0;
/*
* If v_type == VNON it is a new node, so fill in the v_type,
@@ -389,6 +436,34 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper,
np->n_vattr.na_fsid = nap->na_fsid;
np->n_vattr.na_mode = nap->na_mode;
} else {
+ force_fid_err = 0;
+ KFAIL_POINT_ERROR(DEBUG_FP, nfscl_force_fileid_warning,
+ force_fid_err);
+ /*
+ * BROKEN NFS SERVER OR MIDDLEWARE
+ *
+ * Certain NFS servers (certain old proprietary filers ca.
+ * 2006) or broken middleboxes (e.g. WAN accelerator products)
+ * will respond to GETATTR requests with results for a
+ * different fileid.
+ *
+ * The WAN accelerator we've observed not only serves stale
+ * cache results for a given file, it also occasionally serves
+ * results for wholly different files. This causes surprising
+ * problems; for example the cached size attribute of a file
+ * may truncate down and then back up, resulting in zero
+ * regions in file contents read by applications. We observed
+ * this reliably with Clang and .c files during parallel build.
+ * A pcap revealed packet fragmentation and GETATTR RPC
+ * responses with wholly wrong fileids.
+ */
+ if ((np->n_vattr.na_fileid != 0 &&
+ np->n_vattr.na_fileid != nap->na_fileid) ||
+ force_fid_err) {
+ nfscl_warn_fileid(nmp, &np->n_vattr, nap);
+ error = EIDRM;
+ goto out;
+ }
NFSBCOPY((caddr_t)nap, (caddr_t)&np->n_vattr,
sizeof (struct nfsvattr));
}
@@ -419,8 +494,6 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper,
} else
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
np->n_attrstamp = time_second;
- setnsize = 0;
- nsize = 0;
if (vap->va_size != np->n_size) {
if (vap->va_type == VREG) {
if (dontshrink && vap->va_size < np->n_size) {
@@ -490,14 +563,16 @@ nfscl_loadattrcache(struct vnode **vpp, struct nfsvattr *nap, void *nvaper,
vaper->va_mtime = np->n_mtim;
}
}
+
+out:
#ifdef KDTRACE_HOOKS
if (np->n_attrstamp != 0)
- KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, vap, 0);
+ KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, vap, error);
#endif
NFSUNLOCKNODE(np);
if (setnsize)
vnode_pager_setsize(vp, nsize);
- return (0);
+ return (error);
}
/*
diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c
index 15f5243..d1ade4a 100644
--- a/sys/fs/nfsserver/nfs_nfsdstate.c
+++ b/sys/fs/nfsserver/nfs_nfsdstate.c
@@ -220,7 +220,8 @@ nfsrv_setclient(struct nfsrv_descript *nd, struct nfsclient **new_clpp,
break;
}
}
- i++;
+ if (gotit == 0)
+ i++;
}
if (!gotit ||
(clp->lc_flags & (LCL_NEEDSCONFIRM | LCL_ADMINREVOKED))) {
diff --git a/sys/geom/eli/g_eli_integrity.c b/sys/geom/eli/g_eli_integrity.c
index f7bf1fd..f688001 100644
--- a/sys/geom/eli/g_eli_integrity.c
+++ b/sys/geom/eli/g_eli_integrity.c
@@ -408,8 +408,8 @@ g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp)
struct cryptodesc *crde, *crda;
u_int i, lsec, nsec, data_secsize, decr_secsize, encr_secsize;
off_t dstoff;
- int err, error;
u_char *p, *data, *auth, *authkey, *plaindata;
+ int error;
G_ELI_LOGREQ(3, bp, "%s", __func__);
@@ -451,7 +451,6 @@ g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp)
bp->bio_inbed = 0;
bp->bio_children = nsec;
- error = 0;
for (i = 1; i <= nsec; i++, dstoff += encr_secsize) {
crp = (struct cryptop *)p; p += sizeof(*crp);
crde = (struct cryptodesc *)p; p += sizeof(*crde);
@@ -519,10 +518,8 @@ g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp)
crda->crd_klen = G_ELI_AUTH_SECKEYLEN * 8;
crp->crp_etype = 0;
- err = crypto_dispatch(crp);
- if (err != 0 && error == 0)
- error = err;
+ error = crypto_dispatch(crp);
+ KASSERT(error == 0, ("crypto_dispatch() failed (error=%d)",
+ error));
}
- if (bp->bio_error == 0)
- bp->bio_error = error;
}
diff --git a/sys/geom/eli/g_eli_privacy.c b/sys/geom/eli/g_eli_privacy.c
index a60efe8..d636e1f 100644
--- a/sys/geom/eli/g_eli_privacy.c
+++ b/sys/geom/eli/g_eli_privacy.c
@@ -230,10 +230,10 @@ g_eli_crypto_run(struct g_eli_worker *wr, struct bio *bp)
struct cryptop *crp;
struct cryptodesc *crd;
u_int i, nsec, secsize;
- int err, error;
off_t dstoff;
size_t size;
u_char *p, *data;
+ int error;
G_ELI_LOGREQ(3, bp, "%s", __func__);
@@ -271,7 +271,6 @@ g_eli_crypto_run(struct g_eli_worker *wr, struct bio *bp)
bcopy(bp->bio_data, data, bp->bio_length);
}
- error = 0;
for (i = 0, dstoff = bp->bio_offset; i < nsec; i++, dstoff += secsize) {
crp = (struct cryptop *)p; p += sizeof(*crp);
crd = (struct cryptodesc *)p; p += sizeof(*crd);
@@ -308,10 +307,8 @@ g_eli_crypto_run(struct g_eli_worker *wr, struct bio *bp)
crd->crd_next = NULL;
crp->crp_etype = 0;
- err = crypto_dispatch(crp);
- if (error == 0)
- error = err;
+ error = crypto_dispatch(crp);
+ KASSERT(error == 0, ("crypto_dispatch() failed (error=%d)",
+ error));
}
- if (bp->bio_error == 0)
- bp->bio_error = error;
}
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index 2539e1b..0d34ef5 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -358,6 +358,13 @@ g_dev_open(struct cdev *dev, int flags, int fmt, struct thread *td)
#else
e = 0;
#endif
+
+ /*
+ * This happens on attempt to open a device node with O_EXEC.
+ */
+ if (r + w + e == 0)
+ return (EINVAL);
+
if (w) {
/*
* When running in very secure mode, do not allow
@@ -401,6 +408,20 @@ g_dev_close(struct cdev *dev, int flags, int fmt, struct thread *td)
#else
e = 0;
#endif
+
+ /*
+ * The vgonel(9) - caused by eg. forced unmount of devfs - calls
+ * VOP_CLOSE(9) on devfs vnode without any FREAD or FWRITE flags,
+ * which would result in zero deltas, which in turn would cause
+ * panic in g_access(9).
+ *
+ * Note that we cannot zero the counters (ie. do "r = cp->acr"
+ * etc) instead, because the consumer might be opened in another
+ * devfs instance.
+ */
+ if (r + w + e == 0)
+ return (EINVAL);
+
sc = cp->private;
mtx_lock(&sc->sc_mtx);
sc->sc_open += r + w + e;
diff --git a/sys/geom/geom_io.c b/sys/geom/geom_io.c
index 0b8e118..e72e709 100644
--- a/sys/geom/geom_io.c
+++ b/sys/geom/geom_io.c
@@ -517,11 +517,11 @@ g_io_request(struct bio *bp, struct g_consumer *cp)
getbinuptime(&bp->bio_t0);
#ifdef GET_STACK_USAGE
- direct = (cp->flags & G_CF_DIRECT_SEND) &&
- (pp->flags & G_PF_DIRECT_RECEIVE) &&
- !g_is_geom_thread(curthread) &&
- (((pp->flags & G_PF_ACCEPT_UNMAPPED) == 0 &&
- (bp->bio_flags & BIO_UNMAPPED) != 0) || THREAD_CAN_SLEEP());
+ direct = (cp->flags & G_CF_DIRECT_SEND) != 0 &&
+ (pp->flags & G_PF_DIRECT_RECEIVE) != 0 &&
+ !g_is_geom_thread(curthread) &&
+ ((pp->flags & G_PF_ACCEPT_UNMAPPED) != 0 ||
+ (bp->bio_flags & BIO_UNMAPPED) == 0 || THREAD_CAN_SLEEP());
if (direct) {
/* Block direct execution if less then half of stack left. */
size_t st, su;
diff --git a/sys/geom/uzip/g_uzip.c b/sys/geom/uzip/g_uzip.c
index 732de9d..8363d06 100644
--- a/sys/geom/uzip/g_uzip.c
+++ b/sys/geom/uzip/g_uzip.c
@@ -94,8 +94,8 @@ g_uzip_softc_free(struct g_uzip_softc *sc, struct g_geom *gp)
{
if (gp != NULL) {
- printf("%s: %d requests, %d cached\n",
- gp->name, sc->req_total, sc->req_cached);
+ DPRINTF(("%s: %d requests, %d cached\n",
+ gp->name, sc->req_total, sc->req_cached));
}
if (sc->offsets != NULL) {
free(sc->offsets, M_GEOM_UZIP);
@@ -519,7 +519,7 @@ g_uzip_taste(struct g_class *mp, struct g_provider *pp, int flags)
gp->name,
pp2->sectorsize, (intmax_t)pp2->mediasize,
pp2->stripeoffset, pp2->stripesize, pp2->flags));
- printf("%s: %u x %u blocks\n", gp->name, sc->nblocks, sc->blksz);
+ DPRINTF(("%s: %u x %u blocks\n", gp->name, sc->nblocks, sc->blksz));
return (gp);
err:
@@ -547,7 +547,7 @@ g_uzip_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
g_topology_assert();
if (gp->softc == NULL) {
- printf("%s(%s): gp->softc == NULL\n", __func__, gp->name);
+ DPRINTF(("%s(%s): gp->softc == NULL\n", __func__, gp->name));
return (ENXIO);
}
diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c
index 7a00740..6a00d23 100644
--- a/sys/i386/i386/genassym.c
+++ b/sys/i386/i386/genassym.c
@@ -103,6 +103,7 @@ ASSYM(V_SYSCALL, offsetof(struct vmmeter, v_syscall));
ASSYM(V_INTR, offsetof(struct vmmeter, v_intr));
/* ASSYM(UPAGES, UPAGES);*/
ASSYM(KSTACK_PAGES, KSTACK_PAGES);
+ASSYM(TD0_KSTACK_PAGES, TD0_KSTACK_PAGES);
ASSYM(PAGE_SIZE, PAGE_SIZE);
ASSYM(NPTEPG, NPTEPG);
ASSYM(NPDEPG, NPDEPG);
diff --git a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s
index 5bf7944..4d8e22f 100644
--- a/sys/i386/i386/locore.s
+++ b/sys/i386/i386/locore.s
@@ -731,7 +731,7 @@ no_kernend:
movl %esi,R(IdlePTD)
/* Allocate KSTACK */
- ALLOCPAGES(KSTACK_PAGES)
+ ALLOCPAGES(TD0_KSTACK_PAGES)
movl %esi,R(p0kpa)
addl $KERNBASE, %esi
movl %esi, R(proc0kstack)
@@ -800,7 +800,7 @@ no_kernend:
/* Map proc0's KSTACK in the physical way ... */
movl R(p0kpa), %eax
- movl $(KSTACK_PAGES), %ecx
+ movl $(TD0_KSTACK_PAGES), %ecx
fillkptphys($PG_RW)
/* Map ISA hole */
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 2be5dbc..76790f0 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -2445,7 +2445,7 @@ init386(first)
#endif
thread0.td_kstack = proc0kstack;
- thread0.td_kstack_pages = KSTACK_PAGES;
+ thread0.td_kstack_pages = TD0_KSTACK_PAGES;
/*
* This may be done better later if it gets more high level
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c
index 083aa4a..0942523 100644
--- a/sys/i386/i386/mp_machdep.c
+++ b/sys/i386/i386/mp_machdep.c
@@ -247,6 +247,8 @@ init_secondary(void)
pc->pc_prvspace = pc;
pc->pc_curthread = 0;
+ intel_fix_cpuid();
+
gdt_segs[GPRIV_SEL].ssd_base = (int) pc;
gdt_segs[GPROC0_SEL].ssd_base = (int) &pc->pc_common_tss;
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index a642d10..f8ae6d9 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -118,11 +118,7 @@ __FBSDID("$FreeBSD$");
#include <sys/vmmeter.h>
#include <sys/sched.h>
#include <sys/sysctl.h>
-#ifdef SMP
#include <sys/smp.h>
-#else
-#include <sys/cpuset.h>
-#endif
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -512,6 +508,22 @@ pmap_bootstrap(vm_paddr_t firstaddr)
pmap_set_pg();
}
+static void
+pmap_init_qpages(void)
+{
+ struct pcpu *pc;
+ int i;
+
+ CPU_FOREACH(i) {
+ pc = pcpu_find(i);
+ pc->pc_qmap_addr = kva_alloc(PAGE_SIZE);
+ if (pc->pc_qmap_addr == 0)
+ panic("pmap_init_qpages: unable to allocate KVA");
+ }
+}
+
+SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL);
+
/*
* Setup the PAT MSR.
*/
@@ -5400,6 +5412,39 @@ pmap_align_superpage(vm_object_t object, vm_ooffset_t offset,
*addr = ((*addr + PDRMASK) & ~PDRMASK) + superpage_offset;
}
+vm_offset_t
+pmap_quick_enter_page(vm_page_t m)
+{
+ vm_offset_t qaddr;
+ pt_entry_t *pte;
+
+ critical_enter();
+ qaddr = PCPU_GET(qmap_addr);
+ pte = vtopte(qaddr);
+
+ KASSERT(*pte == 0, ("pmap_quick_enter_page: PTE busy"));
+ *pte = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M |
+ pmap_cache_bits(pmap_page_get_memattr(m), 0);
+ invlpg(qaddr);
+
+ return (qaddr);
+}
+
+void
+pmap_quick_remove_page(vm_offset_t addr)
+{
+ vm_offset_t qaddr;
+ pt_entry_t *pte;
+
+ qaddr = PCPU_GET(qmap_addr);
+ pte = vtopte(qaddr);
+
+ KASSERT(*pte != 0, ("pmap_quick_remove_page: PTE not in use"));
+ KASSERT(addr == qaddr, ("pmap_quick_remove_page: invalid address"));
+
+ *pte = 0;
+ critical_exit();
+}
#if defined(PMAP_DEBUG)
pmap_pid_dump(int pid)
@@ -5461,51 +5506,3 @@ pmap_pid_dump(int pid)
return (npte);
}
#endif
-
-#if defined(DEBUG)
-
-static void pads(pmap_t pm);
-void pmap_pvdump(vm_paddr_t pa);
-
-/* print address space of pmap*/
-static void
-pads(pmap_t pm)
-{
- int i, j;
- vm_paddr_t va;
- pt_entry_t *ptep;
-
- if (pm == kernel_pmap)
- return;
- for (i = 0; i < NPDEPTD; i++)
- if (pm->pm_pdir[i])
- for (j = 0; j < NPTEPG; j++) {
- va = (i << PDRSHIFT) + (j << PAGE_SHIFT);
- if (pm == kernel_pmap && va < KERNBASE)
- continue;
- if (pm != kernel_pmap && va > UPT_MAX_ADDRESS)
- continue;
- ptep = pmap_pte(pm, va);
- if (pmap_pte_v(ptep))
- printf("%x:%x ", va, *ptep);
- };
-
-}
-
-void
-pmap_pvdump(vm_paddr_t pa)
-{
- pv_entry_t pv;
- pmap_t pmap;
- vm_page_t m;
-
- printf("pa %x", pa);
- m = PHYS_TO_VM_PAGE(pa);
- TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
- pmap = PV_PMAP(pv);
- printf(" -> pmap %p, va %x", (void *)pmap, pv->pv_va);
- pads(pmap);
- }
- printf(" ");
-}
-#endif
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index f67b279..62e99aa 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -111,8 +111,8 @@ _Static_assert(OFFSETOF_CURTHREAD == offsetof(struct pcpu, pc_curthread),
"OFFSETOF_CURTHREAD does not correspond with offset of pc_curthread.");
_Static_assert(OFFSETOF_CURPCB == offsetof(struct pcpu, pc_curpcb),
"OFFSETOF_CURPCB does not correspond with offset of pc_curpcb.");
-_Static_assert(OFFSETOF_MONITORBUF == offsetof(struct pcpu, pc_monitorbuf),
- "OFFSETOF_MONINORBUF does not correspond with offset of pc_monitorbuf.");
+_Static_assert(__OFFSETOF_MONITORBUF == offsetof(struct pcpu, pc_monitorbuf),
+ "__OFFSETOF_MONINORBUF does not correspond with offset of pc_monitorbuf.");
static void cpu_reset_real(void);
#ifdef SMP
diff --git a/sys/i386/include/atomic.h b/sys/i386/include/atomic.h
index adc86ca..3242d76 100644
--- a/sys/i386/include/atomic.h
+++ b/sys/i386/include/atomic.h
@@ -37,9 +37,31 @@
#include <machine/specialreg.h>
#endif
-#define mb() __asm __volatile("lock; addl $0,(%%esp)" : : : "memory", "cc")
-#define wmb() __asm __volatile("lock; addl $0,(%%esp)" : : : "memory", "cc")
-#define rmb() __asm __volatile("lock; addl $0,(%%esp)" : : : "memory", "cc")
+#ifndef __OFFSETOF_MONITORBUF
+/*
+ * __OFFSETOF_MONITORBUF == __pcpu_offset(pc_monitorbuf).
+ *
+ * The open-coded number is used instead of the symbolic expression to
+ * avoid a dependency on sys/pcpu.h in machine/atomic.h consumers.
+ * An assertion in i386/vm_machdep.c ensures that the value is correct.
+ */
+#define __OFFSETOF_MONITORBUF 0x180
+
+static __inline void
+__mbk(void)
+{
+
+ __asm __volatile("lock; addl $0,%%fs:%0"
+ : "+m" (*(u_int *)__OFFSETOF_MONITORBUF) : : "memory", "cc");
+}
+
+static __inline void
+__mbu(void)
+{
+
+ __asm __volatile("lock; addl $0,(%%esp)" : : : "memory", "cc");
+}
+#endif
/*
* Various simple operations on memory, each of which is atomic in the
@@ -233,71 +255,36 @@ atomic_testandset_int(volatile u_int *p, u_int v)
* IA32 memory model, a simple store guarantees release semantics.
*
* However, a load may pass a store if they are performed on distinct
- * addresses, so for atomic_load_acq we introduce a Store/Load barrier
- * before the load in SMP kernels. We use "lock addl $0,mem", as
- * recommended by the AMD Software Optimization Guide, and not mfence.
- * In the kernel, we use a private per-cpu cache line as the target
- * for the locked addition, to avoid introducing false data
- * dependencies. In userspace, a word at the top of the stack is
- * utilized.
+ * addresses, so we need Store/Load barrier for sequentially
+ * consistent fences in SMP kernels. We use "lock addl $0,mem" for a
+ * Store/Load barrier, as recommended by the AMD Software Optimization
+ * Guide, and not mfence. In the kernel, we use a private per-cpu
+ * cache line for "mem", to avoid introducing false data
+ * dependencies. In user space, we use the word at the top of the
+ * stack.
*
* For UP kernels, however, the memory of the single processor is
* always consistent, so we only need to stop the compiler from
* reordering accesses in a way that violates the semantics of acquire
* and release.
*/
-#if defined(_KERNEL)
-
-/*
- * OFFSETOF_MONITORBUF == __pcpu_offset(pc_monitorbuf).
- *
- * The open-coded number is used instead of the symbolic expression to
- * avoid a dependency on sys/pcpu.h in machine/atomic.h consumers.
- * An assertion in i386/vm_machdep.c ensures that the value is correct.
- */
-#define OFFSETOF_MONITORBUF 0x180
+#if defined(_KERNEL)
#if defined(SMP)
-static __inline void
-__storeload_barrier(void)
-{
-
- __asm __volatile("lock; addl $0,%%fs:%0"
- : "+m" (*(u_int *)OFFSETOF_MONITORBUF) : : "memory", "cc");
-}
+#define __storeload_barrier() __mbk()
#else /* _KERNEL && UP */
-static __inline void
-__storeload_barrier(void)
-{
-
- __compiler_membar();
-}
+#define __storeload_barrier() __compiler_membar()
#endif /* SMP */
#else /* !_KERNEL */
-static __inline void
-__storeload_barrier(void)
-{
-
- __asm __volatile("lock; addl $0,(%%esp)" : : : "memory", "cc");
-}
+#define __storeload_barrier() __mbu()
#endif /* _KERNEL*/
-/*
- * C11-standard acq/rel semantics only apply when the variable in the
- * call is the same for acq as it is for rel. However, our previous
- * (x86) implementations provided much stronger ordering than required
- * (essentially what is called seq_cst order in C11). This
- * implementation provides the historical strong ordering since some
- * callers depend on it.
- */
-
#define ATOMIC_LOAD(TYPE) \
static __inline u_##TYPE \
atomic_load_acq_##TYPE(volatile u_##TYPE *p) \
{ \
u_##TYPE res; \
\
- __storeload_barrier(); \
res = *p; \
__compiler_membar(); \
return (res); \
@@ -786,4 +773,14 @@ u_long atomic_swap_long(volatile u_long *p, u_long v);
#endif /* !WANT_FUNCTIONS */
+#if defined(_KERNEL)
+#define mb() __mbk()
+#define wmb() __mbk()
+#define rmb() __mbk()
+#else
+#define mb() __mbu()
+#define wmb() __mbu()
+#define rmb() __mbu()
+#endif
+
#endif /* !_MACHINE_ATOMIC_H_ */
diff --git a/sys/i386/include/in_cksum.h b/sys/i386/include/in_cksum.h
index 34d85be..8816f3c 100644
--- a/sys/i386/include/in_cksum.h
+++ b/sys/i386/include/in_cksum.h
@@ -10,7 +10,7 @@
* 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h
index e610240..13655ee 100644
--- a/sys/i386/include/md_var.h
+++ b/sys/i386/include/md_var.h
@@ -118,6 +118,7 @@ void fillw(int /*u_short*/ pat, void *base, size_t cnt);
void fill_based_sd(struct segment_descriptor *sdp, uint32_t base);
void initializecpu(void);
void initializecpucache(void);
+bool intel_fix_cpuid(void);
void i686_pagezero(void *addr);
void sse2_pagezero(void *addr);
void init_AMD_Elan_sc520(void);
diff --git a/sys/i386/include/param.h b/sys/i386/include/param.h
index b3fd85f..f7968f8 100644
--- a/sys/i386/include/param.h
+++ b/sys/i386/include/param.h
@@ -114,6 +114,11 @@
#define KSTACK_PAGES 2 /* Includes pcb! */
#endif
#define KSTACK_GUARD_PAGES 1 /* pages of kstack guard; 0 disables */
+#if KSTACK_PAGES < 4
+#define TD0_KSTACK_PAGES 4
+#else
+#define TD0_KSTACK_PAGES KSTACK_PAGES
+#endif
/*
* Ceiling on amount of swblock kva space, can be changed via
diff --git a/sys/i386/include/pcpu.h b/sys/i386/include/pcpu.h
index 231f80f..cfd8d03 100644
--- a/sys/i386/include/pcpu.h
+++ b/sys/i386/include/pcpu.h
@@ -58,7 +58,8 @@
int pc_private_tss; /* Flag indicating private tss*/\
u_int pc_cmci_mask; /* MCx banks for CMCI */ \
u_int pc_vcpu_id; /* Xen vCPU ID */ \
- char __pad[233]
+ vm_offset_t pc_qmap_addr; /* KVA for temporary mappings */\
+ char __pad[229]
#ifdef _KERNEL
diff --git a/sys/i386/include/privatespace.h b/sys/i386/include/privatespace.h
deleted file mode 100644
index 5eb54c2..0000000
--- a/sys/i386/include/privatespace.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*-
- * Copyright (c) Peter Wemm
- * 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$
- */
-
-#ifndef _MACHINE_PRIVATESPACE_H_
-#define _MACHINE_PRIVATESPACE_H_
-
-/*
- * This is the upper (0xff800000) address space layout that is per-cpu.
- * It is setup in locore.s and pmap.c for the BSP and in mp_machdep.c for
- * each AP. This is only applicable to the x86 SMP kernel.
- */
-struct privatespace {
- /* page 0 - data page */
- struct pcpu pcpu;
- char __filler0[PAGE_SIZE - sizeof(struct pcpu)];
-
- /* page 1 - idle stack (KSTACK_PAGES pages) */
- char idlekstack[KSTACK_PAGES * PAGE_SIZE];
- /* page 1+KSTACK_PAGES... */
-};
-
-extern struct privatespace SMP_prvspace[];
-
-#endif /* ! _MACHINE_PRIVATESPACE_H_ */
diff --git a/sys/i386/include/xen/xenfunc.h b/sys/i386/include/xen/xenfunc.h
deleted file mode 100644
index f48b1f1..0000000
--- a/sys/i386/include/xen/xenfunc.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*-
- * Copyright (c) 2004, 2005 Kip Macy
- * 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$
- */
-
-#ifndef _XEN_XENFUNC_H_
-#define _XEN_XENFUNC_H_
-
-#include <xen/xen-os.h>
-#include <xen/hypervisor.h>
-
-#include <vm/pmap.h>
-
-#include <machine/segments.h>
-
-#include <sys/pcpu.h>
-#define BKPT __asm__("int3");
-#define XPQ_CALL_DEPTH 5
-#define XPQ_CALL_COUNT 2
-#define PG_PRIV PG_AVAIL3
-typedef struct {
- unsigned long pt_ref;
- unsigned long pt_eip[XPQ_CALL_COUNT][XPQ_CALL_DEPTH];
-} pteinfo_t;
-
-extern pteinfo_t *pteinfo_list;
-#ifdef XENDEBUG_LOW
-#define __PRINTK(x) printk x
-#else
-#define __PRINTK(x)
-#endif
-
-char *xen_setbootenv(char *cmd_line);
-
-int xen_boothowto(char *envp);
-
-void _xen_machphys_update(vm_paddr_t, vm_paddr_t, char *file, int line);
-
-#ifdef INVARIANTS
-#define xen_machphys_update(a, b) _xen_machphys_update((a), (b), __FILE__, __LINE__)
-#else
-#define xen_machphys_update(a, b) _xen_machphys_update((a), (b), NULL, 0)
-#endif
-
-void xen_update_descriptor(union descriptor *, union descriptor *);
-
-extern struct mtx balloon_lock;
-#if 0
-#define balloon_lock(__flags) mtx_lock_irqsave(&balloon_lock, __flags)
-#define balloon_unlock(__flags) mtx_unlock_irqrestore(&balloon_lock, __flags)
-#else
-#define balloon_lock(__flags) __flags = 1
-#define balloon_unlock(__flags) __flags = 0
-#endif
-
-
-
-#endif /* _XEN_XENFUNC_H_ */
diff --git a/sys/i386/include/xen/xenvar.h b/sys/i386/include/xen/xenvar.h
deleted file mode 100644
index 484c279..0000000
--- a/sys/i386/include/xen/xenvar.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*-
- * Copyright (c) 2008 Kip Macy
- * 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$
- */
-
-#ifndef XENVAR_H_
-#define XENVAR_H_
-
-#include <xen/features.h>
-
-#define vtomach(va) pmap_kextract((vm_offset_t) (va))
-
-#endif
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index a362d00..efb7317 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -831,7 +831,7 @@ create_init(const void *udata __unused)
int error;
error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc,
- NULL, 0);
+ NULL, 0, NULL);
if (error)
panic("cannot fork init: %d\n", error);
KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1"));
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 933e4cc..dc0ee49 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1707,7 +1707,8 @@ fdallocn(struct thread *td, int minfd, int *fds, int n)
* release the FILEDESC lock.
*/
int
-falloc(struct thread *td, struct file **resultfp, int *resultfd, int flags)
+falloc_caps(struct thread *td, struct file **resultfp, int *resultfd, int flags,
+ struct filecaps *fcaps)
{
struct file *fp;
int error, fd;
@@ -1716,7 +1717,7 @@ falloc(struct thread *td, struct file **resultfp, int *resultfd, int flags)
if (error)
return (error); /* no reference held on error */
- error = finstall(td, fp, &fd, flags, NULL);
+ error = finstall(td, fp, &fd, flags, fcaps);
if (error) {
fdrop(fp, td); /* one reference (fp only) */
return (error);
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index f8c6cf09..06cb763 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -738,11 +738,11 @@ int
sys_kqueue(struct thread *td, struct kqueue_args *uap)
{
- return (kern_kqueue(td, 0));
+ return (kern_kqueue(td, 0, NULL));
}
int
-kern_kqueue(struct thread *td, int flags)
+kern_kqueue(struct thread *td, int flags, struct filecaps *fcaps)
{
struct filedesc *fdp;
struct kqueue *kq;
@@ -760,7 +760,7 @@ kern_kqueue(struct thread *td, int flags)
}
fdp = p->p_fd;
- error = falloc(td, &fp, &fd, flags);
+ error = falloc_caps(td, &fp, &fd, flags, fcaps);
if (error)
goto done2;
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 517b689..56207a0 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -562,6 +562,10 @@ interpret:
goto exec_fail_dealloc;
}
+ /* ABI enforces the use of Capsicum. Switch into capabilities mode. */
+ if (SV_PROC_FLAG(p, SV_CAPSICUM))
+ sys_cap_enter(td, NULL);
+
/*
* Copy out strings (args and env) and initialize stack base
*/
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index a031435..85dbd94 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -104,7 +104,7 @@ sys_fork(struct thread *td, struct fork_args *uap)
int error;
struct proc *p2;
- error = fork1(td, RFFDG | RFPROC, 0, &p2, NULL, 0);
+ error = fork1(td, RFFDG | RFPROC, 0, &p2, NULL, 0, NULL);
if (error == 0) {
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
@@ -127,7 +127,7 @@ sys_pdfork(td, uap)
* itself from the parent using the return value.
*/
error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2,
- &fd, uap->flags);
+ &fd, uap->flags, NULL);
if (error == 0) {
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
@@ -144,7 +144,7 @@ sys_vfork(struct thread *td, struct vfork_args *uap)
struct proc *p2;
flags = RFFDG | RFPROC | RFPPWAIT | RFMEM;
- error = fork1(td, flags, 0, &p2, NULL, 0);
+ error = fork1(td, flags, 0, &p2, NULL, 0, NULL);
if (error == 0) {
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
@@ -163,7 +163,7 @@ sys_rfork(struct thread *td, struct rfork_args *uap)
return (EINVAL);
AUDIT_ARG_FFLAGS(uap->flags);
- error = fork1(td, uap->flags, 0, &p2, NULL, 0);
+ error = fork1(td, uap->flags, 0, &p2, NULL, 0, NULL);
if (error == 0) {
td->td_retval[0] = p2 ? p2->p_pid : 0;
td->td_retval[1] = 0;
@@ -768,7 +768,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
int
fork1(struct thread *td, int flags, int pages, struct proc **procp,
- int *procdescp, int pdflags)
+ int *procdescp, int pdflags, struct filecaps *fcaps)
{
struct proc *p1;
struct proc *newproc;
@@ -824,7 +824,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
* later.
*/
if (flags & RFPROCDESC) {
- error = falloc(td, &fp_procdesc, procdescp, 0);
+ error = falloc_caps(td, &fp_procdesc, procdescp, 0, fcaps);
if (error != 0)
return (error);
}
diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c
index 68903ba..2072dc7 100644
--- a/sys/kern/kern_kthread.c
+++ b/sys/kern/kern_kthread.c
@@ -89,7 +89,7 @@ kproc_create(void (*func)(void *), void *arg,
panic("kproc_create called too soon");
error = fork1(&thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags,
- pages, &p2, NULL, 0);
+ pages, &p2, NULL, 0, NULL);
if (error)
return error;
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index bb92e18..a4fde06 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -292,10 +292,10 @@ linker_file_register_sysctls(linker_file_t lf)
return;
sx_xunlock(&kld_sx);
- sysctl_wlock();
+ sysctl_xlock();
for (oidp = start; oidp < stop; oidp++)
sysctl_register_oid(*oidp);
- sysctl_wunlock();
+ sysctl_xunlock();
sx_xlock(&kld_sx);
}
@@ -313,10 +313,10 @@ linker_file_unregister_sysctls(linker_file_t lf)
return;
sx_xunlock(&kld_sx);
- sysctl_wlock();
+ sysctl_xlock();
for (oidp = start; oidp < stop; oidp++)
sysctl_unregister_oid(*oidp);
- sysctl_wunlock();
+ sysctl_xunlock();
sx_xlock(&kld_sx);
}
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c
index 36a8470..aa67180 100644
--- a/sys/kern/kern_lock.c
+++ b/sys/kern/kern_lock.c
@@ -69,12 +69,8 @@ CTASSERT(LK_UNLOCKED == (LK_UNLOCKED &
#ifndef INVARIANTS
#define _lockmgr_assert(lk, what, file, line)
-#define TD_LOCKS_INC(td)
-#define TD_LOCKS_DEC(td)
-#else
-#define TD_LOCKS_INC(td) ((td)->td_locks++)
-#define TD_LOCKS_DEC(td) ((td)->td_locks--)
#endif
+
#define TD_SLOCKS_INC(td) ((td)->td_lk_slocks++)
#define TD_SLOCKS_DEC(td) ((td)->td_lk_slocks--)
diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c
index 97e1985..bec8f6b 100644
--- a/sys/kern/kern_mutex.c
+++ b/sys/kern/kern_mutex.c
@@ -224,7 +224,7 @@ __mtx_lock_flags(volatile uintptr_t *c, int opts, const char *file, int line)
line);
WITNESS_LOCK(&m->lock_object, (opts & ~MTX_RECURSE) | LOP_EXCLUSIVE,
file, line);
- curthread->td_locks++;
+ TD_LOCKS_INC(curthread);
}
void
@@ -248,7 +248,7 @@ __mtx_unlock_flags(volatile uintptr_t *c, int opts, const char *file, int line)
mtx_assert(m, MA_OWNED);
__mtx_unlock(m, curthread, opts, file, line);
- curthread->td_locks--;
+ TD_LOCKS_DEC(curthread);
}
void
@@ -347,7 +347,7 @@ _mtx_trylock_flags_(volatile uintptr_t *c, int opts, const char *file, int line)
if (rval) {
WITNESS_LOCK(&m->lock_object, opts | LOP_EXCLUSIVE | LOP_TRYLOCK,
file, line);
- curthread->td_locks++;
+ TD_LOCKS_INC(curthread);
if (m->mtx_recurse == 0)
LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(adaptive__acquire,
m, contested, waittime, file, line);
@@ -958,7 +958,7 @@ _mtx_destroy(volatile uintptr_t *c)
if (LOCK_CLASS(&m->lock_object) == &lock_class_mtx_spin)
spinlock_exit();
else
- curthread->td_locks--;
+ TD_LOCKS_DEC(curthread);
lock_profile_release_lock(&m->lock_object);
/* Tell witness this isn't locked to make it happy. */
diff --git a/sys/kern/kern_rmlock.c b/sys/kern/kern_rmlock.c
index 945608d..2667e6e 100644
--- a/sys/kern/kern_rmlock.c
+++ b/sys/kern/kern_rmlock.c
@@ -608,11 +608,8 @@ _rm_wlock_debug(struct rmlock *rm, const char *file, int line)
_rm_wlock(rm);
LOCK_LOG_LOCK("RMWLOCK", &rm->lock_object, 0, 0, file, line);
-
WITNESS_LOCK(&rm->lock_object, LOP_EXCLUSIVE, file, line);
-
- curthread->td_locks++;
-
+ TD_LOCKS_INC(curthread);
}
void
@@ -628,7 +625,7 @@ _rm_wunlock_debug(struct rmlock *rm, const char *file, int line)
WITNESS_UNLOCK(&rm->lock_object, LOP_EXCLUSIVE, file, line);
LOCK_LOG_LOCK("RMWUNLOCK", &rm->lock_object, 0, 0, file, line);
_rm_wunlock(rm);
- curthread->td_locks--;
+ TD_LOCKS_DEC(curthread);
}
int
@@ -670,9 +667,7 @@ _rm_rlock_debug(struct rmlock *rm, struct rm_priotracker *tracker,
LOCK_LOG_LOCK("RMRLOCK", &rm->lock_object, 0, 0, file,
line);
WITNESS_LOCK(&rm->lock_object, 0, file, line);
-
- curthread->td_locks++;
-
+ TD_LOCKS_INC(curthread);
return (1);
} else if (trylock)
LOCK_LOG_TRY("RMRLOCK", &rm->lock_object, 0, 0, file, line);
@@ -694,7 +689,7 @@ _rm_runlock_debug(struct rmlock *rm, struct rm_priotracker *tracker,
WITNESS_UNLOCK(&rm->lock_object, 0, file, line);
LOCK_LOG_LOCK("RMRUNLOCK", &rm->lock_object, 0, 0, file, line);
_rm_runlock(rm, tracker);
- curthread->td_locks--;
+ TD_LOCKS_DEC(curthread);
}
#else
diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c
index 370d0d6..6541724 100644
--- a/sys/kern/kern_rwlock.c
+++ b/sys/kern/kern_rwlock.c
@@ -268,7 +268,7 @@ _rw_wlock_cookie(volatile uintptr_t *c, const char *file, int line)
__rw_wlock(rw, curthread, file, line);
LOCK_LOG_LOCK("WLOCK", &rw->lock_object, 0, rw->rw_recurse, file, line);
WITNESS_LOCK(&rw->lock_object, LOP_EXCLUSIVE, file, line);
- curthread->td_locks++;
+ TD_LOCKS_INC(curthread);
}
int
@@ -303,7 +303,7 @@ __rw_try_wlock(volatile uintptr_t *c, const char *file, int line)
if (!rw_recursed(rw))
LOCKSTAT_PROFILE_OBTAIN_RWLOCK_SUCCESS(rw__acquire,
rw, 0, 0, file, line, LOCKSTAT_WRITER);
- curthread->td_locks++;
+ TD_LOCKS_INC(curthread);
}
return (rval);
}
@@ -325,8 +325,9 @@ _rw_wunlock_cookie(volatile uintptr_t *c, const char *file, int line)
LOCK_LOG_LOCK("WUNLOCK", &rw->lock_object, 0, rw->rw_recurse, file,
line);
__rw_wunlock(rw, curthread, file, line);
- curthread->td_locks--;
+ TD_LOCKS_DEC(curthread);
}
+
/*
* Determines whether a new reader can acquire a lock. Succeeds if the
* reader already owns a read lock and the lock is locked for read to
@@ -565,7 +566,7 @@ __rw_rlock(volatile uintptr_t *c, const char *file, int line)
waittime, file, line, LOCKSTAT_READER);
LOCK_LOG_LOCK("RLOCK", &rw->lock_object, 0, 0, file, line);
WITNESS_LOCK(&rw->lock_object, 0, file, line);
- curthread->td_locks++;
+ TD_LOCKS_INC(curthread);
curthread->td_rw_rlocks++;
}
@@ -596,7 +597,7 @@ __rw_try_rlock(volatile uintptr_t *c, const char *file, int line)
WITNESS_LOCK(&rw->lock_object, LOP_TRYLOCK, file, line);
LOCKSTAT_PROFILE_OBTAIN_RWLOCK_SUCCESS(rw__acquire,
rw, 0, 0, file, line, LOCKSTAT_READER);
- curthread->td_locks++;
+ TD_LOCKS_INC(curthread);
curthread->td_rw_rlocks++;
return (1);
}
@@ -714,7 +715,7 @@ _rw_runlock_cookie(volatile uintptr_t *c, const char *file, int line)
break;
}
LOCKSTAT_PROFILE_RELEASE_RWLOCK(rw__release, rw, LOCKSTAT_READER);
- curthread->td_locks--;
+ TD_LOCKS_DEC(curthread);
curthread->td_rw_rlocks--;
}
diff --git a/sys/kern/kern_sharedpage.c b/sys/kern/kern_sharedpage.c
index fd619cd..6ad2ed8 100644
--- a/sys/kern/kern_sharedpage.c
+++ b/sys/kern/kern_sharedpage.c
@@ -119,6 +119,13 @@ shared_page_init(void *dummy __unused)
SYSINIT(shp, SI_SUB_EXEC, SI_ORDER_FIRST, (sysinit_cfunc_t)shared_page_init,
NULL);
+/*
+ * Push the timehands update to the shared page.
+ *
+ * The lockless update scheme is similar to the one used to update the
+ * in-kernel timehands, see sys/kern/kern_tc.c:tc_windup() (which
+ * calls us after the timehands are updated).
+ */
static void
timehands_update(struct sysentvec *sv)
{
@@ -127,47 +134,56 @@ timehands_update(struct sysentvec *sv)
uint32_t enabled, idx;
enabled = tc_fill_vdso_timehands(&th);
- tk = (struct vdso_timekeep *)(shared_page_mapping +
- sv->sv_timekeep_off);
+ th.th_gen = 0;
idx = sv->sv_timekeep_curr;
- atomic_store_rel_32(&tk->tk_th[idx].th_gen, 0);
if (++idx >= VDSO_TH_NUM)
idx = 0;
sv->sv_timekeep_curr = idx;
if (++sv->sv_timekeep_gen == 0)
sv->sv_timekeep_gen = 1;
- th.th_gen = 0;
+
+ tk = (struct vdso_timekeep *)(shared_page_mapping +
+ sv->sv_timekeep_off);
+ tk->tk_th[idx].th_gen = 0;
+ atomic_thread_fence_rel();
if (enabled)
tk->tk_th[idx] = th;
- tk->tk_enabled = enabled;
atomic_store_rel_32(&tk->tk_th[idx].th_gen, sv->sv_timekeep_gen);
- tk->tk_current = idx;
+ atomic_store_rel_32(&tk->tk_current, idx);
+
+ /*
+ * The ordering of the assignment to tk_enabled relative to
+ * the update of the vdso_timehands is not important.
+ */
+ tk->tk_enabled = enabled;
}
#ifdef COMPAT_FREEBSD32
static void
timehands_update32(struct sysentvec *sv)
{
- struct vdso_timekeep32 *tk;
struct vdso_timehands32 th;
+ struct vdso_timekeep32 *tk;
uint32_t enabled, idx;
enabled = tc_fill_vdso_timehands32(&th);
- tk = (struct vdso_timekeep32 *)(shared_page_mapping +
- sv->sv_timekeep_off);
+ th.th_gen = 0;
idx = sv->sv_timekeep_curr;
- atomic_store_rel_32(&tk->tk_th[idx].th_gen, 0);
if (++idx >= VDSO_TH_NUM)
idx = 0;
sv->sv_timekeep_curr = idx;
if (++sv->sv_timekeep_gen == 0)
sv->sv_timekeep_gen = 1;
- th.th_gen = 0;
+
+ tk = (struct vdso_timekeep32 *)(shared_page_mapping +
+ sv->sv_timekeep_off);
+ tk->tk_th[idx].th_gen = 0;
+ atomic_thread_fence_rel();
if (enabled)
tk->tk_th[idx] = th;
- tk->tk_enabled = enabled;
atomic_store_rel_32(&tk->tk_th[idx].th_gen, sv->sv_timekeep_gen);
- tk->tk_current = idx;
+ atomic_store_rel_32(&tk->tk_current, idx);
+ tk->tk_enabled = enabled;
}
#endif
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index 4d57fd3..3a91673 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -275,24 +275,13 @@ doadump(boolean_t textdump)
return (error);
}
-static int
-isbufbusy(struct buf *bp)
-{
- if (((bp->b_flags & (B_INVAL | B_PERSISTENT)) == 0 &&
- BUF_ISLOCKED(bp)) ||
- ((bp->b_flags & (B_DELWRI | B_INVAL)) == B_DELWRI))
- return (1);
- return (0);
-}
-
/*
* Shutdown the system cleanly to prepare for reboot, halt, or power off.
*/
void
kern_reboot(int howto)
{
- static int first_buf_printf = 1;
- static int waittime = -1;
+ static int once = 0;
#if defined(SMP)
/*
@@ -321,116 +310,9 @@ kern_reboot(int howto)
/*
* Now sync filesystems
*/
- if (!cold && (howto & RB_NOSYNC) == 0 && waittime < 0) {
- register struct buf *bp;
- int iter, nbusy, pbusy;
-#ifndef PREEMPTION
- int subiter;
-#endif
-
- waittime = 0;
-
- wdog_kern_pat(WD_LASTVAL);
- sys_sync(curthread, NULL);
-
- /*
- * With soft updates, some buffers that are
- * written will be remarked as dirty until other
- * buffers are written.
- */
- for (iter = pbusy = 0; iter < 20; iter++) {
- nbusy = 0;
- for (bp = &buf[nbuf]; --bp >= buf; )
- if (isbufbusy(bp))
- nbusy++;
- if (nbusy == 0) {
- if (first_buf_printf)
- printf("All buffers synced.");
- break;
- }
- if (first_buf_printf) {
- printf("Syncing disks, buffers remaining... ");
- first_buf_printf = 0;
- }
- printf("%d ", nbusy);
- if (nbusy < pbusy)
- iter = 0;
- pbusy = nbusy;
-
- wdog_kern_pat(WD_LASTVAL);
- sys_sync(curthread, NULL);
-
-#ifdef PREEMPTION
- /*
- * Drop Giant and spin for a while to allow
- * interrupt threads to run.
- */
- DROP_GIANT();
- DELAY(50000 * iter);
- PICKUP_GIANT();
-#else
- /*
- * Drop Giant and context switch several times to
- * allow interrupt threads to run.
- */
- DROP_GIANT();
- for (subiter = 0; subiter < 50 * iter; subiter++) {
- thread_lock(curthread);
- mi_switch(SW_VOL, NULL);
- thread_unlock(curthread);
- DELAY(1000);
- }
- PICKUP_GIANT();
-#endif
- }
- printf("\n");
- /*
- * Count only busy local buffers to prevent forcing
- * a fsck if we're just a client of a wedged NFS server
- */
- nbusy = 0;
- for (bp = &buf[nbuf]; --bp >= buf; ) {
- if (isbufbusy(bp)) {
-#if 0
-/* XXX: This is bogus. We should probably have a BO_REMOTE flag instead */
- if (bp->b_dev == NULL) {
- TAILQ_REMOVE(&mountlist,
- bp->b_vp->v_mount, mnt_list);
- continue;
- }
-#endif
- nbusy++;
- if (show_busybufs > 0) {
- printf(
- "%d: buf:%p, vnode:%p, flags:%0x, blkno:%jd, lblkno:%jd, buflock:",
- nbusy, bp, bp->b_vp, bp->b_flags,
- (intmax_t)bp->b_blkno,
- (intmax_t)bp->b_lblkno);
- BUF_LOCKPRINTINFO(bp);
- if (show_busybufs > 1)
- vn_printf(bp->b_vp,
- "vnode content: ");
- }
- }
- }
- if (nbusy) {
- /*
- * Failed to sync all blocks. Indicate this and don't
- * unmount filesystems (thus forcing an fsck on reboot).
- */
- printf("Giving up on %d buffers\n", nbusy);
- DELAY(5000000); /* 5 seconds */
- } else {
- if (!first_buf_printf)
- printf("Final sync complete\n");
- /*
- * Unmount filesystems
- */
- if (panicstr == 0)
- vfs_unmountall();
- }
- swapoff_all();
- DELAY(100000); /* wait for console output to finish */
+ if (!cold && (howto & RB_NOSYNC) == 0 && once == 0) {
+ once = 1;
+ bufshutdown(show_busybufs);
}
print_uptime();
diff --git a/sys/kern/kern_sx.c b/sys/kern/kern_sx.c
index 1ba1ab2..96e117b 100644
--- a/sys/kern/kern_sx.c
+++ b/sys/kern/kern_sx.c
@@ -261,7 +261,7 @@ _sx_slock(struct sx *sx, int opts, const char *file, int line)
if (!error) {
LOCK_LOG_LOCK("SLOCK", &sx->lock_object, 0, 0, file, line);
WITNESS_LOCK(&sx->lock_object, 0, file, line);
- curthread->td_locks++;
+ TD_LOCKS_INC(curthread);
}
return (error);
@@ -290,7 +290,7 @@ sx_try_slock_(struct sx *sx, const char *file, int line)
WITNESS_LOCK(&sx->lock_object, LOP_TRYLOCK, file, line);
LOCKSTAT_PROFILE_OBTAIN_RWLOCK_SUCCESS(sx__acquire,
sx, 0, 0, file, line, LOCKSTAT_READER);
- curthread->td_locks++;
+ TD_LOCKS_INC(curthread);
return (1);
}
}
@@ -318,7 +318,7 @@ _sx_xlock(struct sx *sx, int opts, const char *file, int line)
LOCK_LOG_LOCK("XLOCK", &sx->lock_object, 0, sx->sx_recurse,
file, line);
WITNESS_LOCK(&sx->lock_object, LOP_EXCLUSIVE, file, line);
- curthread->td_locks++;
+ TD_LOCKS_INC(curthread);
}
return (error);
@@ -353,7 +353,7 @@ sx_try_xlock_(struct sx *sx, const char *file, int line)
if (!sx_recursed(sx))
LOCKSTAT_PROFILE_OBTAIN_RWLOCK_SUCCESS(sx__acquire,
sx, 0, 0, file, line, LOCKSTAT_WRITER);
- curthread->td_locks++;
+ TD_LOCKS_INC(curthread);
}
return (rval);
@@ -371,7 +371,7 @@ _sx_sunlock(struct sx *sx, const char *file, int line)
WITNESS_UNLOCK(&sx->lock_object, 0, file, line);
LOCK_LOG_LOCK("SUNLOCK", &sx->lock_object, 0, 0, file, line);
__sx_sunlock(sx, file, line);
- curthread->td_locks--;
+ TD_LOCKS_DEC(curthread);
}
void
@@ -387,7 +387,7 @@ _sx_xunlock(struct sx *sx, const char *file, int line)
LOCK_LOG_LOCK("XUNLOCK", &sx->lock_object, 0, sx->sx_recurse, file,
line);
__sx_xunlock(sx, curthread, file, line);
- curthread->td_locks--;
+ TD_LOCKS_DEC(curthread);
}
/*
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index 52075e4..b32198f 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$");
#include <sys/jail.h>
#include <sys/lock.h>
#include <sys/mutex.h>
-#include <sys/rmlock.h>
#include <sys/sbuf.h>
#include <sys/sx.h>
#include <sys/sysproto.h>
@@ -78,7 +77,7 @@ static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer");
* The sysctllock protects the MIB tree. It also protects sysctl
* contexts used with dynamic sysctls. The sysctl_register_oid() and
* sysctl_unregister_oid() routines require the sysctllock to already
- * be held, so the sysctl_wlock() and sysctl_wunlock() routines are
+ * be held, so the sysctl_xlock() and sysctl_xunlock() routines are
* provided for the few places in the kernel which need to use that
* API rather than using the dynamic API. Use of the dynamic API is
* strongly encouraged for most code.
@@ -87,21 +86,20 @@ static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer");
* sysctl requests. This is implemented by serializing any userland
* sysctl requests larger than a single page via an exclusive lock.
*/
-static struct rmlock sysctllock;
+static struct sx sysctllock;
static struct sx sysctlmemlock;
-#define SYSCTL_WLOCK() rm_wlock(&sysctllock)
-#define SYSCTL_WUNLOCK() rm_wunlock(&sysctllock)
-#define SYSCTL_RLOCK(tracker) rm_rlock(&sysctllock, (tracker))
-#define SYSCTL_RUNLOCK(tracker) rm_runlock(&sysctllock, (tracker))
-#define SYSCTL_WLOCKED() rm_wowned(&sysctllock)
-#define SYSCTL_ASSERT_LOCKED() rm_assert(&sysctllock, RA_LOCKED)
-#define SYSCTL_ASSERT_WLOCKED() rm_assert(&sysctllock, RA_WLOCKED)
-#define SYSCTL_ASSERT_RLOCKED() rm_assert(&sysctllock, RA_RLOCKED)
-#define SYSCTL_INIT() rm_init_flags(&sysctllock, "sysctl lock", \
- RM_SLEEPABLE)
+#define SYSCTL_XLOCK() sx_xlock(&sysctllock)
+#define SYSCTL_XUNLOCK() sx_xunlock(&sysctllock)
+#define SYSCTL_SLOCK() sx_slock(&sysctllock)
+#define SYSCTL_SUNLOCK() sx_sunlock(&sysctllock)
+#define SYSCTL_XLOCKED() sx_xlocked(&sysctllock)
+#define SYSCTL_ASSERT_LOCKED() sx_assert(&sysctllock, SA_LOCKED)
+#define SYSCTL_ASSERT_XLOCKED() sx_assert(&sysctllock, SA_XLOCKED)
+#define SYSCTL_ASSERT_SLOCKED() sx_assert(&sysctllock, SA_SLOCKED)
+#define SYSCTL_INIT() sx_init(&sysctllock, "sysctl lock")
#define SYSCTL_SLEEP(ch, wmesg, timo) \
- rm_sleep(ch, &sysctllock, 0, wmesg, timo)
+ sx_sleep(ch, &sysctllock, 0, wmesg, timo)
static int sysctl_root(SYSCTL_HANDLER_ARGS);
@@ -113,6 +111,29 @@ static int sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del,
static int sysctl_old_kernel(struct sysctl_req *, const void *, size_t);
static int sysctl_new_kernel(struct sysctl_req *, void *, size_t);
+static void
+sysctl_lock(bool xlock)
+{
+
+ if (xlock)
+ SYSCTL_XLOCK();
+ else
+ SYSCTL_SLOCK();
+}
+
+static bool
+sysctl_unlock(void)
+{
+ bool xlocked;
+
+ xlocked = SYSCTL_XLOCKED();
+ if (xlocked)
+ SYSCTL_XUNLOCK();
+ else
+ SYSCTL_SUNLOCK();
+ return (xlocked);
+}
+
static struct sysctl_oid *
sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
{
@@ -133,32 +154,29 @@ sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
* Order by number in each list.
*/
void
-sysctl_wlock(void)
+sysctl_xlock(void)
{
- SYSCTL_WLOCK();
+ SYSCTL_XLOCK();
}
void
-sysctl_wunlock(void)
+sysctl_xunlock(void)
{
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
}
static int
sysctl_root_handler_locked(struct sysctl_oid *oid, void *arg1, intptr_t arg2,
- struct sysctl_req *req, struct rm_priotracker *tracker)
+ struct sysctl_req *req)
{
int error;
+ bool xlocked;
if (oid->oid_kind & CTLFLAG_DYN)
atomic_add_int(&oid->oid_running, 1);
-
- if (tracker != NULL)
- SYSCTL_RUNLOCK(tracker);
- else
- SYSCTL_WUNLOCK();
+ xlocked = sysctl_unlock();
if (!(oid->oid_kind & CTLFLAG_MPSAFE))
mtx_lock(&Giant);
@@ -166,11 +184,7 @@ sysctl_root_handler_locked(struct sysctl_oid *oid, void *arg1, intptr_t arg2,
if (!(oid->oid_kind & CTLFLAG_MPSAFE))
mtx_unlock(&Giant);
- if (tracker != NULL)
- SYSCTL_RLOCK(tracker);
- else
- SYSCTL_WLOCK();
-
+ sysctl_lock(xlocked);
if (oid->oid_kind & CTLFLAG_DYN) {
if (atomic_fetchadd_int(&oid->oid_running, -1) == 1 &&
(oid->oid_kind & CTLFLAG_DYING) != 0)
@@ -269,7 +283,7 @@ sysctl_load_tunable_by_oid_locked(struct sysctl_oid *oidp)
return;
}
error = sysctl_root_handler_locked(oidp, oidp->oid_arg1,
- oidp->oid_arg2, &req, NULL);
+ oidp->oid_arg2, &req);
if (error != 0)
printf("Setting sysctl %s failed: %d\n", path + rem, error);
if (penv != NULL)
@@ -289,7 +303,7 @@ sysctl_register_oid(struct sysctl_oid *oidp)
* First check if another oid with the same name already
* exists in the parent's list.
*/
- SYSCTL_ASSERT_WLOCKED();
+ SYSCTL_ASSERT_XLOCKED();
p = sysctl_find_oidname(oidp->oid_name, parent);
if (p != NULL) {
if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
@@ -383,7 +397,7 @@ sysctl_unregister_oid(struct sysctl_oid *oidp)
struct sysctl_oid *p;
int error;
- SYSCTL_ASSERT_WLOCKED();
+ SYSCTL_ASSERT_XLOCKED();
error = ENOENT;
if (oidp->oid_number == OID_AUTO) {
error = EINVAL;
@@ -439,7 +453,7 @@ sysctl_ctx_free(struct sysctl_ctx_list *clist)
* XXX This algorithm is a hack. But I don't know any
* XXX better solution for now...
*/
- SYSCTL_WLOCK();
+ SYSCTL_XLOCK();
TAILQ_FOREACH(e, clist, link) {
error = sysctl_remove_oid_locked(e->entry, 0, 0);
if (error)
@@ -459,7 +473,7 @@ sysctl_ctx_free(struct sysctl_ctx_list *clist)
e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);
}
if (error) {
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
return(EBUSY);
}
/* Now really delete the entries */
@@ -473,7 +487,7 @@ sysctl_ctx_free(struct sysctl_ctx_list *clist)
free(e, M_SYSCTLOID);
e = e1;
}
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
return (error);
}
@@ -483,7 +497,7 @@ sysctl_ctx_entry_add(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
{
struct sysctl_ctx_entry *e;
- SYSCTL_ASSERT_WLOCKED();
+ SYSCTL_ASSERT_XLOCKED();
if (clist == NULL || oidp == NULL)
return(NULL);
e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK);
@@ -498,7 +512,7 @@ sysctl_ctx_entry_find(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
{
struct sysctl_ctx_entry *e;
- SYSCTL_ASSERT_WLOCKED();
+ SYSCTL_ASSERT_XLOCKED();
if (clist == NULL || oidp == NULL)
return(NULL);
TAILQ_FOREACH(e, clist, link) {
@@ -520,15 +534,15 @@ sysctl_ctx_entry_del(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp)
if (clist == NULL || oidp == NULL)
return (EINVAL);
- SYSCTL_WLOCK();
+ SYSCTL_XLOCK();
e = sysctl_ctx_entry_find(clist, oidp);
if (e != NULL) {
TAILQ_REMOVE(clist, e, link);
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
free(e, M_SYSCTLOID);
return (0);
} else {
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
return (ENOENT);
}
}
@@ -544,9 +558,9 @@ sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse)
{
int error;
- SYSCTL_WLOCK();
+ SYSCTL_XLOCK();
error = sysctl_remove_oid_locked(oidp, del, recurse);
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
return (error);
}
@@ -558,14 +572,14 @@ sysctl_remove_name(struct sysctl_oid *parent, const char *name,
int error;
error = ENOENT;
- SYSCTL_WLOCK();
+ SYSCTL_XLOCK();
SLIST_FOREACH_SAFE(p, SYSCTL_CHILDREN(parent), oid_link, tmp) {
if (strcmp(p->oid_name, name) == 0) {
error = sysctl_remove_oid_locked(p, del, recurse);
break;
}
}
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
return (error);
}
@@ -577,7 +591,7 @@ sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse)
struct sysctl_oid *p, *tmp;
int error;
- SYSCTL_ASSERT_WLOCKED();
+ SYSCTL_ASSERT_XLOCKED();
if (oidp == NULL)
return(EINVAL);
if ((oidp->oid_kind & CTLFLAG_DYN) == 0) {
@@ -652,7 +666,7 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
if (parent == NULL)
return(NULL);
/* Check if the node already exists, otherwise create it */
- SYSCTL_WLOCK();
+ SYSCTL_XLOCK();
oidp = sysctl_find_oidname(name, parent);
if (oidp != NULL) {
if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
@@ -660,10 +674,10 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
/* Update the context */
if (clist != NULL)
sysctl_ctx_entry_add(clist, oidp);
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
return (oidp);
} else {
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
printf("can't re-use a leaf (%s)!\n", name);
return (NULL);
}
@@ -686,7 +700,7 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent,
sysctl_ctx_entry_add(clist, oidp);
/* Register this oid */
sysctl_register_oid(oidp);
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
return (oidp);
}
@@ -700,10 +714,10 @@ sysctl_rename_oid(struct sysctl_oid *oidp, const char *name)
char *oldname;
newname = strdup(name, M_SYSCTLOID);
- SYSCTL_WLOCK();
+ SYSCTL_XLOCK();
oldname = __DECONST(char *, oidp->oid_name);
oidp->oid_name = newname;
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
free(oldname, M_SYSCTLOID);
}
@@ -715,21 +729,21 @@ sysctl_move_oid(struct sysctl_oid *oid, struct sysctl_oid_list *parent)
{
struct sysctl_oid *oidp;
- SYSCTL_WLOCK();
+ SYSCTL_XLOCK();
if (oid->oid_parent == parent) {
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
return (0);
}
oidp = sysctl_find_oidname(oid->oid_name, parent);
if (oidp != NULL) {
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
return (EEXIST);
}
sysctl_unregister_oid(oid);
oid->oid_parent = parent;
oid->oid_number = OID_AUTO;
sysctl_register_oid(oid);
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
return (0);
}
@@ -745,10 +759,10 @@ sysctl_register_all(void *arg)
sx_init(&sysctlmemlock, "sysctl mem");
SYSCTL_INIT();
- SYSCTL_WLOCK();
+ SYSCTL_XLOCK();
SET_FOREACH(oidp, sysctl_set)
sysctl_register_oid(*oidp);
- SYSCTL_WUNLOCK();
+ SYSCTL_XUNLOCK();
}
SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_register_all, 0);
@@ -818,15 +832,14 @@ sysctl_sysctl_debug_dump_node(struct sysctl_oid_list *l, int i)
static int
sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS)
{
- struct rm_priotracker tracker;
int error;
error = priv_check(req->td, PRIV_SYSCTL_DEBUG);
if (error)
return (error);
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_SLOCK();
sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_SUNLOCK();
return (ENOENT);
}
@@ -842,10 +855,9 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
int error = 0;
struct sysctl_oid *oid;
struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
- struct rm_priotracker tracker;
char buf[10];
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_SLOCK();
while (namelen) {
if (!lsp) {
snprintf(buf,sizeof(buf),"%d",*name);
@@ -888,7 +900,7 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
}
error = SYSCTL_OUT(req, "", 1);
out:
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_SUNLOCK();
return (error);
}
@@ -967,12 +979,11 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
int i, j, error;
struct sysctl_oid *oid;
struct sysctl_oid_list *lsp = &sysctl__children;
- struct rm_priotracker tracker;
int newoid[CTL_MAXNAME];
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_SLOCK();
i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid);
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_SUNLOCK();
if (i)
return (ENOENT);
error = SYSCTL_OUT(req, newoid, j * sizeof (int));
@@ -1031,7 +1042,6 @@ sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
char *p;
int error, oid[CTL_MAXNAME], len = 0;
struct sysctl_oid *op = 0;
- struct rm_priotracker tracker;
if (!req->newlen)
return (ENOENT);
@@ -1048,9 +1058,9 @@ sysctl_sysctl_name2oid(SYSCTL_HANDLER_ARGS)
p [req->newlen] = '\0';
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_SLOCK();
error = name2oid(p, oid, &len, &op);
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_SUNLOCK();
free(p, M_SYSCTL);
@@ -1073,10 +1083,9 @@ static int
sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
{
struct sysctl_oid *oid;
- struct rm_priotracker tracker;
int error;
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_SLOCK();
error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
if (error)
goto out;
@@ -1090,7 +1099,7 @@ sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
goto out;
error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1);
out:
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_SUNLOCK();
return (error);
}
@@ -1102,10 +1111,9 @@ static int
sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
{
struct sysctl_oid *oid;
- struct rm_priotracker tracker;
int error;
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_SLOCK();
error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
if (error)
goto out;
@@ -1116,7 +1124,7 @@ sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
}
error = SYSCTL_OUT(req, oid->oid_descr, strlen(oid->oid_descr) + 1);
out:
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_SUNLOCK();
return (error);
}
@@ -1421,7 +1429,9 @@ kernel_sysctl(struct thread *td, int *name, u_int namelen, void *old,
req.newfunc = sysctl_new_kernel;
req.lock = REQ_UNWIRED;
+ SYSCTL_SLOCK();
error = sysctl_root(0, name, namelen, &req);
+ SYSCTL_SUNLOCK();
if (req.lock == REQ_WIRED && req.validlen > 0)
vsunlock(req.oldptr, req.validlen);
@@ -1598,14 +1608,13 @@ static int
sysctl_root(SYSCTL_HANDLER_ARGS)
{
struct sysctl_oid *oid;
- struct rm_priotracker tracker;
int error, indx, lvl;
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_ASSERT_SLOCKED();
error = sysctl_find_oid(arg1, arg2, &oid, &indx, req);
if (error)
- goto out;
+ return (error);
if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
/*
@@ -1613,17 +1622,13 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
* no handler. Inform the user that it's a node.
* The indx may or may not be the same as namelen.
*/
- if (oid->oid_handler == NULL) {
- error = EISDIR;
- goto out;
- }
+ if (oid->oid_handler == NULL)
+ return (EISDIR);
}
/* Is this sysctl writable? */
- if (req->newptr && !(oid->oid_kind & CTLFLAG_WR)) {
- error = EPERM;
- goto out;
- }
+ if (req->newptr && !(oid->oid_kind & CTLFLAG_WR))
+ return (EPERM);
KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL"));
@@ -1633,11 +1638,10 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
* writing unless specifically granted for the node.
*/
if (IN_CAPABILITY_MODE(req->td)) {
- if ((req->oldptr && !(oid->oid_kind & CTLFLAG_CAPRD)) ||
- (req->newptr && !(oid->oid_kind & CTLFLAG_CAPWR))) {
- error = EPERM;
- goto out;
- }
+ if (req->oldptr && !(oid->oid_kind & CTLFLAG_CAPRD))
+ return (EPERM);
+ if (req->newptr && !(oid->oid_kind & CTLFLAG_CAPWR))
+ return (EPERM);
}
#endif
@@ -1646,7 +1650,7 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE;
error = securelevel_gt(req->td->td_ucred, lvl);
if (error)
- goto out;
+ return (error);
}
/* Is this sysctl writable by only privileged users? */
@@ -1664,13 +1668,11 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
priv = PRIV_SYSCTL_WRITE;
error = priv_check(req->td, priv);
if (error)
- goto out;
+ return (error);
}
- if (!oid->oid_handler) {
- error = EINVAL;
- goto out;
- }
+ if (!oid->oid_handler)
+ return (EINVAL);
if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
arg1 = (int *)arg1 + indx;
@@ -1683,18 +1685,16 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
error = mac_system_check_sysctl(req->td->td_ucred, oid, arg1, arg2,
req);
if (error != 0)
- goto out;
+ return (error);
#endif
#ifdef VIMAGE
if ((oid->oid_kind & CTLFLAG_VNET) && arg1 != NULL)
arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1);
#endif
- error = sysctl_root_handler_locked(oid, arg1, arg2, req, &tracker);
+ error = sysctl_root_handler_locked(oid, arg1, arg2, req);
KFAIL_POINT_ERROR(_debug_fail_point, sysctl_running, error);
-out:
- SYSCTL_RUNLOCK(&tracker);
return (error);
}
@@ -1794,7 +1794,9 @@ userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
for (;;) {
req.oldidx = 0;
req.newidx = 0;
+ SYSCTL_SLOCK();
error = sysctl_root(0, name, namelen, &req);
+ SYSCTL_SUNLOCK();
if (error != EAGAIN)
break;
kern_yield(PRI_USER);
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index 8ff8f76..a40aa5a 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -793,7 +793,7 @@ umtxq_sleep(struct umtx_q *uq, const char *wmesg, struct abs_timeout *abstime)
* Convert userspace address into unique logical address.
*/
int
-umtx_key_get(void *addr, int type, int share, struct umtx_key *key)
+umtx_key_get(const void *addr, int type, int share, struct umtx_key *key)
{
struct thread *td = curthread;
vm_map_t map;
@@ -820,8 +820,8 @@ umtx_key_get(void *addr, int type, int share, struct umtx_key *key)
(share == AUTO_SHARE &&
VM_INHERIT_SHARE == entry->inheritance)) {
key->shared = 1;
- key->info.shared.offset = entry->offset + entry->start -
- (vm_offset_t)addr;
+ key->info.shared.offset = (vm_offset_t)addr -
+ entry->start + entry->offset;
vm_object_reference(key->info.shared.object);
} else {
key->shared = 0;
diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c
index 59bd387..da77c4b 100644
--- a/sys/kern/sched_4bsd.c
+++ b/sys/kern/sched_4bsd.c
@@ -792,6 +792,8 @@ sched_fork_thread(struct thread *td, struct thread *childtd)
{
struct td_sched *ts;
+ childtd->td_oncpu = NOCPU;
+ childtd->td_lastcpu = NOCPU;
childtd->td_estcpu = td->td_estcpu;
childtd->td_lock = &sched_lock;
childtd->td_cpuset = cpuset_ref(td->td_cpuset);
@@ -1671,6 +1673,8 @@ sched_throw(struct thread *td)
} else {
lock_profile_release_lock(&sched_lock.lock_object);
MPASS(td->td_lock == &sched_lock);
+ td->td_lastcpu = td->td_oncpu;
+ td->td_oncpu = NOCPU;
}
mtx_assert(&sched_lock, MA_OWNED);
KASSERT(curthread->td_md.md_spinlock_count == 1, ("invalid count"));
diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
index 74ae85f..708478f 100644
--- a/sys/kern/sched_ule.c
+++ b/sys/kern/sched_ule.c
@@ -2080,6 +2080,8 @@ sched_fork_thread(struct thread *td, struct thread *child)
*/
ts = td->td_sched;
ts2 = child->td_sched;
+ child->td_oncpu = NOCPU;
+ child->td_lastcpu = NOCPU;
child->td_lock = TDQ_LOCKPTR(tdq);
child->td_cpuset = cpuset_ref(td->td_cpuset);
ts2->ts_cpu = ts->ts_cpu;
@@ -2703,6 +2705,8 @@ sched_throw(struct thread *td)
MPASS(td->td_lock == TDQ_LOCKPTR(tdq));
tdq_load_rem(tdq, td);
lock_profile_release_lock(&TDQ_LOCKPTR(tdq)->lock_object);
+ td->td_lastcpu = td->td_oncpu;
+ td->td_oncpu = NOCPU;
}
KASSERT(curthread->td_md.md_spinlock_count == 1, ("invalid count"));
newtd = choosethread();
diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c
index cba656a..5043a57 100644
--- a/sys/kern/subr_param.c
+++ b/sys/kern/subr_param.c
@@ -139,13 +139,6 @@ SYSCTL_PROC(_kern, OID_AUTO, vm_guest, CTLFLAG_RD | CTLTYPE_STRING,
"Virtual machine guest detected?");
/*
- * These have to be allocated somewhere; allocating
- * them here forces loader errors if this file is omitted
- * (if they've been externed everywhere else; hah!).
- */
-struct buf *swbuf;
-
-/*
* The elements of this array are ordered based upon the values of the
* corresponding enum VM_GUEST members.
*/
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 70e76ad..a81c9de 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -397,14 +397,8 @@ pipe_dtor(struct pipe *dpipe)
* the zone pick up the pieces via pipeclose().
*/
int
-kern_pipe(struct thread *td, int fildes[2])
-{
-
- return (kern_pipe2(td, fildes, 0));
-}
-
-int
-kern_pipe2(struct thread *td, int fildes[2], int flags)
+kern_pipe(struct thread *td, int fildes[2], int flags, struct filecaps *fcaps1,
+ struct filecaps *fcaps2)
{
struct file *rf, *wf;
struct pipe *rpipe, *wpipe;
@@ -414,13 +408,13 @@ kern_pipe2(struct thread *td, int fildes[2], int flags)
pipe_paircreate(td, &pp);
rpipe = &pp->pp_rpipe;
wpipe = &pp->pp_wpipe;
- error = falloc(td, &rf, &fd, flags);
+ error = falloc_caps(td, &rf, &fd, flags, fcaps1);
if (error) {
pipeclose(rpipe);
pipeclose(wpipe);
return (error);
}
- /* An extra reference on `rf' has been held for us by falloc(). */
+ /* An extra reference on `rf' has been held for us by falloc_caps(). */
fildes[0] = fd;
fflags = FREAD | FWRITE;
@@ -434,7 +428,7 @@ kern_pipe2(struct thread *td, int fildes[2], int flags)
* side while we are blocked trying to allocate the write side.
*/
finit(rf, fflags, DTYPE_PIPE, rpipe, &pipeops);
- error = falloc(td, &wf, &fd, flags);
+ error = falloc_caps(td, &wf, &fd, flags, fcaps2);
if (error) {
fdclose(td, rf, fildes[0]);
fdrop(rf, td);
@@ -442,7 +436,7 @@ kern_pipe2(struct thread *td, int fildes[2], int flags)
pipeclose(wpipe);
return (error);
}
- /* An extra reference on `wf' has been held for us by falloc(). */
+ /* An extra reference on `wf' has been held for us by falloc_caps(). */
finit(wf, fflags, DTYPE_PIPE, wpipe, &pipeops);
fdrop(wf, td);
fildes[1] = fd;
@@ -458,7 +452,7 @@ sys_pipe(struct thread *td, struct pipe_args *uap)
int error;
int fildes[2];
- error = kern_pipe(td, fildes);
+ error = kern_pipe(td, fildes, 0, NULL, NULL);
if (error)
return (error);
@@ -475,7 +469,7 @@ sys_pipe2(struct thread *td, struct pipe2_args *uap)
if (uap->flags & ~(O_CLOEXEC | O_NONBLOCK))
return (EINVAL);
- error = kern_pipe2(td, fildes, uap->flags);
+ error = kern_pipe(td, fildes, uap->flags, NULL, NULL);
if (error)
return (error);
error = copyout(fildes, uap->fildes, 2 * sizeof(int));
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index cb88034..6610960 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -947,7 +947,15 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
}
break;
case PT_DETACH:
- /* reset process parent */
+ /*
+ * Reset the process parent.
+ *
+ * NB: This clears P_TRACED before reparenting
+ * a detached process back to its original
+ * parent. Otherwise the debugee will be set
+ * as an orphan of the debugger.
+ */
+ p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
if (p->p_oppid != p->p_pptr->p_pid) {
PROC_LOCK(p->p_pptr);
sigqueue_take(p->p_ksi);
@@ -963,7 +971,6 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
} else
CTR1(KTR_PTRACE, "PT_DETACH: pid %d", p->p_pid);
p->p_oppid = 0;
- p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
p->p_stops = 0;
/* should we send SIGCHLD? */
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index fb84330..21cbe49 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$");
#include <sys/resourcevar.h>
#include <sys/rwlock.h>
#include <sys/stat.h>
+#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysproto.h>
#include <sys/systm.h>
@@ -683,9 +684,9 @@ shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred)
return (ENOENT);
}
-/* System calls. */
int
-sys_shm_open(struct thread *td, struct shm_open_args *uap)
+kern_shm_open(struct thread *td, const char *userpath, int flags, mode_t mode,
+ struct filecaps *fcaps)
{
struct filedesc *fdp;
struct shmfd *shmfd;
@@ -699,28 +700,27 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
/*
* shm_open(2) is only allowed for anonymous objects.
*/
- if (IN_CAPABILITY_MODE(td) && (uap->path != SHM_ANON))
+ if (IN_CAPABILITY_MODE(td) && (userpath != SHM_ANON))
return (ECAPMODE);
#endif
- if ((uap->flags & O_ACCMODE) != O_RDONLY &&
- (uap->flags & O_ACCMODE) != O_RDWR)
+ if ((flags & O_ACCMODE) != O_RDONLY && (flags & O_ACCMODE) != O_RDWR)
return (EINVAL);
- if ((uap->flags & ~(O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC)) != 0)
+ if ((flags & ~(O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC)) != 0)
return (EINVAL);
fdp = td->td_proc->p_fd;
- cmode = (uap->mode & ~fdp->fd_cmask) & ACCESSPERMS;
+ cmode = (mode & ~fdp->fd_cmask) & ACCESSPERMS;
- error = falloc(td, &fp, &fd, O_CLOEXEC);
+ error = falloc_caps(td, &fp, &fd, O_CLOEXEC, fcaps);
if (error)
return (error);
/* A SHM_ANON path pointer creates an anonymous object. */
- if (uap->path == SHM_ANON) {
+ if (userpath == SHM_ANON) {
/* A read-only anonymous object is pointless. */
- if ((uap->flags & O_ACCMODE) == O_RDONLY) {
+ if ((flags & O_ACCMODE) == O_RDONLY) {
fdclose(td, fp, fd);
fdrop(fp, td);
return (EINVAL);
@@ -728,7 +728,7 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
shmfd = shm_alloc(td->td_ucred, cmode);
} else {
path = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK);
- error = copyinstr(uap->path, path, MAXPATHLEN, NULL);
+ error = copyinstr(userpath, path, MAXPATHLEN, NULL);
#ifdef KTRACE
if (error == 0 && KTRPOINT(curthread, KTR_NAMEI))
ktrnamei(path);
@@ -748,7 +748,7 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
shmfd = shm_lookup(path, fnv);
if (shmfd == NULL) {
/* Object does not yet exist, create it if requested. */
- if (uap->flags & O_CREAT) {
+ if (flags & O_CREAT) {
#ifdef MAC
error = mac_posixshm_check_create(td->td_ucred,
path);
@@ -769,17 +769,16 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
* reference if requested and permitted.
*/
free(path, M_SHMFD);
- if ((uap->flags & (O_CREAT | O_EXCL)) ==
- (O_CREAT | O_EXCL))
+ if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
error = EEXIST;
else {
#ifdef MAC
error = mac_posixshm_check_open(td->td_ucred,
- shmfd, FFLAGS(uap->flags & O_ACCMODE));
+ shmfd, FFLAGS(flags & O_ACCMODE));
if (error == 0)
#endif
error = shm_access(shmfd, td->td_ucred,
- FFLAGS(uap->flags & O_ACCMODE));
+ FFLAGS(flags & O_ACCMODE));
}
/*
@@ -788,7 +787,7 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
* opened with read/write.
*/
if (error == 0 &&
- (uap->flags & (O_ACCMODE | O_TRUNC)) ==
+ (flags & (O_ACCMODE | O_TRUNC)) ==
(O_RDWR | O_TRUNC)) {
#ifdef MAC
error = mac_posixshm_check_truncate(
@@ -809,7 +808,7 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
}
}
- finit(fp, FFLAGS(uap->flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops);
+ finit(fp, FFLAGS(flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops);
td->td_retval[0] = fd;
fdrop(fp, td);
@@ -817,6 +816,14 @@ sys_shm_open(struct thread *td, struct shm_open_args *uap)
return (0);
}
+/* System calls. */
+int
+sys_shm_open(struct thread *td, struct shm_open_args *uap)
+{
+
+ return (kern_shm_open(td, uap->path, uap->flags, uap->mode, NULL));
+}
+
int
sys_shm_unlink(struct thread *td, struct shm_unlink_args *uap)
{
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index d29c308..5f68bde 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -64,9 +64,11 @@ __FBSDID("$FreeBSD$");
#include <sys/resourcevar.h>
#include <sys/rwlock.h>
#include <sys/sysctl.h>
+#include <sys/sysproto.h>
#include <sys/vmem.h>
#include <sys/vmmeter.h>
#include <sys/vnode.h>
+#include <sys/watchdog.h>
#include <geom/geom.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -76,6 +78,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_object.h>
#include <vm/vm_extern.h>
#include <vm/vm_map.h>
+#include <vm/swap_pager.h>
#include "opt_compat.h"
#include "opt_swap.h"
@@ -91,11 +94,8 @@ struct buf_ops buf_ops_bio = {
.bop_bdflush = bufbdflush,
};
-/*
- * XXX buf is global because kern_shutdown.c and ffs_checkoverlap has
- * carnal knowledge of buffers. This knowledge should be moved to vfs_bio.c.
- */
-struct buf *buf; /* buffer header pool */
+static struct buf *buf; /* buffer header pool */
+extern struct buf *swbuf; /* Swap buffer header pool. */
caddr_t unmapped_buf;
/* Used below and for softdep flushing threads in ufs/ffs/ffs_softdep.c */
@@ -309,13 +309,12 @@ static int bdirtywait;
/*
* Definitions for the buffer free lists.
*/
-#define BUFFER_QUEUES 5 /* number of free buffer queues */
+#define BUFFER_QUEUES 4 /* number of free buffer queues */
#define QUEUE_NONE 0 /* on no queue */
#define QUEUE_CLEAN 1 /* non-B_DELWRI buffers */
#define QUEUE_DIRTY 2 /* B_DELWRI buffers */
-#define QUEUE_EMPTYKVA 3 /* empty buffer headers w/KVA assignment */
-#define QUEUE_EMPTY 4 /* empty buffer headers */
+#define QUEUE_EMPTY 3 /* empty buffer headers */
#define QUEUE_SENTINEL 1024 /* not an queue index, but mark for sentinel */
/* Queues for free buffers with various properties */
@@ -956,7 +955,7 @@ vfs_buf_check_mapped(struct buf *bp)
("mapped buf: b_kvabase was not updated %p", bp));
KASSERT(bp->b_data != unmapped_buf,
("mapped buf: b_data was not updated %p", bp));
- KASSERT(bp->b_data < unmapped_buf || bp->b_data > unmapped_buf +
+ KASSERT(bp->b_data < unmapped_buf || bp->b_data >= unmapped_buf +
MAXPHYS, ("b_data + b_offset unmapped %p", bp));
}
@@ -975,6 +974,135 @@ vfs_buf_check_unmapped(struct buf *bp)
#define BUF_CHECK_UNMAPPED(bp) do {} while (0)
#endif
+static int
+isbufbusy(struct buf *bp)
+{
+ if (((bp->b_flags & (B_INVAL | B_PERSISTENT)) == 0 &&
+ BUF_ISLOCKED(bp)) ||
+ ((bp->b_flags & (B_DELWRI | B_INVAL)) == B_DELWRI))
+ return (1);
+ return (0);
+}
+
+/*
+ * Shutdown the system cleanly to prepare for reboot, halt, or power off.
+ */
+void
+bufshutdown(int show_busybufs)
+{
+ static int first_buf_printf = 1;
+ struct buf *bp;
+ int iter, nbusy, pbusy;
+#ifndef PREEMPTION
+ int subiter;
+#endif
+
+ /*
+ * Sync filesystems for shutdown
+ */
+ wdog_kern_pat(WD_LASTVAL);
+ sys_sync(curthread, NULL);
+
+ /*
+ * With soft updates, some buffers that are
+ * written will be remarked as dirty until other
+ * buffers are written.
+ */
+ for (iter = pbusy = 0; iter < 20; iter++) {
+ nbusy = 0;
+ for (bp = &buf[nbuf]; --bp >= buf; )
+ if (isbufbusy(bp))
+ nbusy++;
+ if (nbusy == 0) {
+ if (first_buf_printf)
+ printf("All buffers synced.");
+ break;
+ }
+ if (first_buf_printf) {
+ printf("Syncing disks, buffers remaining... ");
+ first_buf_printf = 0;
+ }
+ printf("%d ", nbusy);
+ if (nbusy < pbusy)
+ iter = 0;
+ pbusy = nbusy;
+
+ wdog_kern_pat(WD_LASTVAL);
+ sys_sync(curthread, NULL);
+
+#ifdef PREEMPTION
+ /*
+ * Drop Giant and spin for a while to allow
+ * interrupt threads to run.
+ */
+ DROP_GIANT();
+ DELAY(50000 * iter);
+ PICKUP_GIANT();
+#else
+ /*
+ * Drop Giant and context switch several times to
+ * allow interrupt threads to run.
+ */
+ DROP_GIANT();
+ for (subiter = 0; subiter < 50 * iter; subiter++) {
+ thread_lock(curthread);
+ mi_switch(SW_VOL, NULL);
+ thread_unlock(curthread);
+ DELAY(1000);
+ }
+ PICKUP_GIANT();
+#endif
+ }
+ printf("\n");
+ /*
+ * Count only busy local buffers to prevent forcing
+ * a fsck if we're just a client of a wedged NFS server
+ */
+ nbusy = 0;
+ for (bp = &buf[nbuf]; --bp >= buf; ) {
+ if (isbufbusy(bp)) {
+#if 0
+/* XXX: This is bogus. We should probably have a BO_REMOTE flag instead */
+ if (bp->b_dev == NULL) {
+ TAILQ_REMOVE(&mountlist,
+ bp->b_vp->v_mount, mnt_list);
+ continue;
+ }
+#endif
+ nbusy++;
+ if (show_busybufs > 0) {
+ printf(
+ "%d: buf:%p, vnode:%p, flags:%0x, blkno:%jd, lblkno:%jd, buflock:",
+ nbusy, bp, bp->b_vp, bp->b_flags,
+ (intmax_t)bp->b_blkno,
+ (intmax_t)bp->b_lblkno);
+ BUF_LOCKPRINTINFO(bp);
+ if (show_busybufs > 1)
+ vn_printf(bp->b_vp,
+ "vnode content: ");
+ }
+ }
+ }
+ if (nbusy) {
+ /*
+ * Failed to sync all blocks. Indicate this and don't
+ * unmount filesystems (thus forcing an fsck on reboot).
+ */
+ printf("Giving up on %d buffers\n", nbusy);
+ DELAY(5000000); /* 5 seconds */
+ } else {
+ if (!first_buf_printf)
+ printf("Final sync complete\n");
+ /*
+ * Unmount filesystems
+ */
+ if (panicstr == 0)
+ vfs_unmountall();
+ }
+ swapoff_all();
+ DELAY(100000); /* wait for console output to finish */
+}
+
static void
bpmap_qenter(struct buf *bp)
{
@@ -1862,10 +1990,8 @@ brelse(struct buf *bp)
bp->b_xflags &= ~(BX_BKGRDWRITE | BX_ALTDATA);
if (bp->b_vflags & BV_BKGRDINPROG)
panic("losing buffer 1");
- if (bp->b_kvasize)
- qindex = QUEUE_EMPTYKVA;
- else
- qindex = QUEUE_EMPTY;
+ bufkvafree(bp);
+ qindex = QUEUE_EMPTY;
bp->b_flags |= B_AGE;
/* buffers with junk contents */
} else if (bp->b_flags & (B_INVAL | B_NOCACHE | B_RELBUF) ||
@@ -2251,8 +2377,6 @@ getnewbuf_reuse_bp(struct buf *bp, int qindex)
LIST_INIT(&bp->b_dep);
}
-static int flushingbufs;
-
static struct buf *
getnewbuf_scan(int maxsize, int defrag, int unmapped, int metadata)
{
@@ -2261,64 +2385,25 @@ getnewbuf_scan(int maxsize, int defrag, int unmapped, int metadata)
KASSERT(!unmapped || !defrag, ("both unmapped and defrag"));
- pass = 1;
+ pass = 0;
restart:
- atomic_add_int(&getnewbufrestarts, 1);
+ if (pass != 0)
+ atomic_add_int(&getnewbufrestarts, 1);
- /*
- * Setup for scan. If we do not have enough free buffers,
- * we setup a degenerate case that immediately fails. Note
- * that if we are specially marked process, we are allowed to
- * dip into our reserves.
- *
- * The scanning sequence is nominally: EMPTY->EMPTYKVA->CLEAN
- * for the allocation of the mapped buffer. For unmapped, the
- * easiest is to start with EMPTY outright.
- *
- * We start with EMPTYKVA. If the list is empty we backup to EMPTY.
- * However, there are a number of cases (defragging, reusing, ...)
- * where we cannot backup.
- */
nbp = NULL;
mtx_lock(&bqclean);
- if (!defrag && unmapped) {
- nqindex = QUEUE_EMPTY;
- nbp = TAILQ_FIRST(&bufqueues[QUEUE_EMPTY]);
- }
- if (nbp == NULL) {
- nqindex = QUEUE_EMPTYKVA;
- nbp = TAILQ_FIRST(&bufqueues[QUEUE_EMPTYKVA]);
- }
-
- /*
- * If no EMPTYKVA buffers and we are either defragging or
- * reusing, locate a CLEAN buffer to free or reuse. If
- * bufspace useage is low skip this step so we can allocate a
- * new buffer.
- */
- if (nbp == NULL && (defrag || bufspace >= lobufspace)) {
- nqindex = QUEUE_CLEAN;
- nbp = TAILQ_FIRST(&bufqueues[QUEUE_CLEAN]);
- }
-
/*
- * If we could not find or were not allowed to reuse a CLEAN
- * buffer, check to see if it is ok to use an EMPTY buffer.
- * We can only use an EMPTY buffer if allocating its KVA would
- * not otherwise run us out of buffer space. No KVA is needed
- * for the unmapped allocation.
+ * If we're not defragging or low on bufspace attempt to make a new
+ * buf from a header.
*/
- if (nbp == NULL && defrag == 0 && (bufspace + maxsize < hibufspace ||
- metadata)) {
+ if (defrag == 0 && bufspace + maxsize < hibufspace) {
nqindex = QUEUE_EMPTY;
- nbp = TAILQ_FIRST(&bufqueues[QUEUE_EMPTY]);
+ nbp = TAILQ_FIRST(&bufqueues[nqindex]);
}
-
/*
- * All available buffers might be clean, retry ignoring the
- * lobufspace as the last resort.
+ * All available buffers might be clean or we need to start recycling.
*/
- if (nbp == NULL && !TAILQ_EMPTY(&bufqueues[QUEUE_CLEAN])) {
+ if (nbp == NULL) {
nqindex = QUEUE_CLEAN;
nbp = TAILQ_FIRST(&bufqueues[QUEUE_CLEAN]);
}
@@ -2332,28 +2417,21 @@ restart:
/*
* Calculate next bp (we can only use it if we do not
- * block or do other fancy things).
+ * release the bqlock)
*/
if ((nbp = TAILQ_NEXT(bp, b_freelist)) == NULL) {
switch (qindex) {
case QUEUE_EMPTY:
- nqindex = QUEUE_EMPTYKVA;
- nbp = TAILQ_FIRST(&bufqueues[QUEUE_EMPTYKVA]);
- if (nbp != NULL)
- break;
- /* FALLTHROUGH */
- case QUEUE_EMPTYKVA:
nqindex = QUEUE_CLEAN;
- nbp = TAILQ_FIRST(&bufqueues[QUEUE_CLEAN]);
+ nbp = TAILQ_FIRST(&bufqueues[nqindex]);
if (nbp != NULL)
break;
/* FALLTHROUGH */
case QUEUE_CLEAN:
- if (metadata && pass == 1) {
- pass = 2;
+ if (metadata && pass == 0) {
+ pass = 1;
nqindex = QUEUE_EMPTY;
- nbp = TAILQ_FIRST(
- &bufqueues[QUEUE_EMPTY]);
+ nbp = TAILQ_FIRST(&bufqueues[nqindex]);
}
/*
* nbp is NULL.
@@ -2399,11 +2477,11 @@ restart:
bremfreel(bp);
mtx_unlock(&bqclean);
+
/*
* NOTE: nbp is now entirely invalid. We can only restart
* the scan from this point on.
*/
-
getnewbuf_reuse_bp(bp, qindex);
mtx_assert(&bqclean, MA_NOTOWNED);
@@ -2412,7 +2490,6 @@ restart:
*/
if (defrag) {
bp->b_flags |= B_INVAL;
- bufkvafree(bp);
brelse(bp);
defrag = 0;
goto restart;
@@ -2424,7 +2501,6 @@ restart:
*/
if (qindex == QUEUE_CLEAN && BUF_LOCKWAITERS(bp)) {
bp->b_flags |= B_INVAL;
- bufkvafree(bp);
brelse(bp);
goto restart;
}
@@ -2437,16 +2513,11 @@ restart:
* KVM space. This occurs in rare situations when multiple
* processes are blocked in getnewbuf() or allocbuf().
*/
- if (bufspace >= hibufspace)
- flushingbufs = 1;
- if (flushingbufs && bp->b_kvasize != 0) {
+ if (bufspace >= hibufspace && bp->b_kvasize != 0) {
bp->b_flags |= B_INVAL;
- bufkvafree(bp);
brelse(bp);
goto restart;
}
- if (bufspace < lobufspace)
- flushingbufs = 0;
break;
}
return (bp);
@@ -2492,7 +2563,6 @@ getnewbuf(struct vnode *vp, int slpflag, int slptimeo, int size, int maxsize,
* async I/O rather then sync I/O.
*/
atomic_add_int(&getnewbufcalls, 1);
- atomic_subtract_int(&getnewbufrestarts, 1);
restart:
bp = getnewbuf_scan(maxsize, defrag, (gbflags & (GB_UNMAPPED |
GB_KVAALLOC)) == GB_UNMAPPED, metadata);
diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
index 9ac193a..f935954 100644
--- a/sys/kern/vfs_init.c
+++ b/sys/kern/vfs_init.c
@@ -291,7 +291,7 @@ vfs_register(struct vfsconf *vfc)
* preserved by re-registering the oid after modifying its
* number.
*/
- sysctl_wlock();
+ sysctl_xlock();
SLIST_FOREACH(oidp, SYSCTL_CHILDREN(&sysctl___vfs), oid_link) {
if (strcmp(oidp->oid_name, vfc->vfc_name) == 0) {
sysctl_unregister_oid(oidp);
@@ -300,7 +300,7 @@ vfs_register(struct vfsconf *vfc)
break;
}
}
- sysctl_wunlock();
+ sysctl_xunlock();
return (0);
}
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index b24a6ae..3c189d1 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -2850,7 +2850,7 @@ unlock:
/*
* vgone, with the vp interlock held.
*/
-void
+static void
vgonel(struct vnode *vp)
{
struct thread *td;
@@ -4622,7 +4622,7 @@ filt_vfsread(struct knote *kn, long hint)
VI_LOCK(vp);
kn->kn_data = va.va_size - kn->kn_fp->f_offset;
- res = (kn->kn_data != 0);
+ res = (kn->kn_sfflags & NOTE_FILE_POLL) != 0 || kn->kn_data != 0;
VI_UNLOCK(vp);
return (res);
}
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index c8c4981..ecc93e1 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -116,6 +116,9 @@ static const int io_hold_cnt = 16;
static int vn_io_fault_enable = 1;
SYSCTL_INT(_debug, OID_AUTO, vn_io_fault_enable, CTLFLAG_RW,
&vn_io_fault_enable, 0, "Enable vn_io_fault lock avoidance");
+static int vn_io_fault_prefault = 0;
+SYSCTL_INT(_debug, OID_AUTO, vn_io_fault_prefault, CTLFLAG_RW,
+ &vn_io_fault_prefault, 0, "Enable vn_io_fault prefaulting");
static u_long vn_io_faults_cnt;
SYSCTL_ULONG(_debug, OID_AUTO, vn_io_faults, CTLFLAG_RD,
&vn_io_faults_cnt, 0, "Count of vn_io_fault lock avoidance triggers");
@@ -1020,6 +1023,59 @@ vn_io_fault_doio(struct vn_io_fault_args *args, struct uio *uio,
uio->uio_rw);
}
+static int
+vn_io_fault_touch(char *base, const struct uio *uio)
+{
+ int r;
+
+ r = fubyte(base);
+ if (r == -1 || (uio->uio_rw == UIO_READ && subyte(base, r) == -1))
+ return (EFAULT);
+ return (0);
+}
+
+static int
+vn_io_fault_prefault_user(const struct uio *uio)
+{
+ char *base;
+ const struct iovec *iov;
+ size_t len;
+ ssize_t resid;
+ int error, i;
+
+ KASSERT(uio->uio_segflg == UIO_USERSPACE,
+ ("vn_io_fault_prefault userspace"));
+
+ error = i = 0;
+ iov = uio->uio_iov;
+ resid = uio->uio_resid;
+ base = iov->iov_base;
+ len = iov->iov_len;
+ while (resid > 0) {
+ error = vn_io_fault_touch(base, uio);
+ if (error != 0)
+ break;
+ if (len < PAGE_SIZE) {
+ if (len != 0) {
+ error = vn_io_fault_touch(base + len - 1, uio);
+ if (error != 0)
+ break;
+ resid -= len;
+ }
+ if (++i >= uio->uio_iovcnt)
+ break;
+ iov = uio->uio_iov + i;
+ base = iov->iov_base;
+ len = iov->iov_len;
+ } else {
+ len -= PAGE_SIZE;
+ base += PAGE_SIZE;
+ resid -= PAGE_SIZE;
+ }
+ }
+ return (error);
+}
+
/*
* Common code for vn_io_fault(), agnostic to the kind of i/o request.
* Uses vn_io_fault_doio() to make the call to an actual i/o function.
@@ -1041,6 +1097,12 @@ vn_io_fault1(struct vnode *vp, struct uio *uio, struct vn_io_fault_args *args,
ssize_t adv;
int error, cnt, save, saveheld, prev_td_ma_cnt;
+ if (vn_io_fault_prefault) {
+ error = vn_io_fault_prefault_user(uio);
+ if (error != 0)
+ return (error); /* Or ignore ? */
+ }
+
prot = uio->uio_rw == UIO_READ ? VM_PROT_WRITE : VM_PROT_READ;
/*
diff --git a/sys/mips/conf/XLR b/sys/mips/conf/XLR
index d1e0da0..0133fad 100644
--- a/sys/mips/conf/XLR
+++ b/sys/mips/conf/XLR
@@ -135,7 +135,7 @@ device ic
device iic
device iicbb
device iicbus
-device ds1374u # RTC on XLR boards
+device ds1374 # RTC on XLR boards
device max6657 # Temparature sensor on XLR boards
device at24co2n # EEPROM on XLR boards
diff --git a/sys/mips/conf/XLR64 b/sys/mips/conf/XLR64
index 1db8d85..c8b1dfb 100644
--- a/sys/mips/conf/XLR64
+++ b/sys/mips/conf/XLR64
@@ -109,7 +109,7 @@ device ic
device iic
device iicbb
device iicbus
-device ds1374u # RTC on XLR boards
+device ds1374 # RTC on XLR boards
device max6657 # Temparature sensor on XLR boards
device at24co2n # EEPROM on XLR boards
diff --git a/sys/mips/conf/XLRN32 b/sys/mips/conf/XLRN32
index c23b451..e2f4468 100644
--- a/sys/mips/conf/XLRN32
+++ b/sys/mips/conf/XLRN32
@@ -113,7 +113,7 @@ device ic
device iic
device iicbb
device iicbus
-device ds1374u # RTC on XLR boards
+device ds1374 # RTC on XLR boards
device max6657 # Temparature sensor on XLR boards
device at24co2n # EEPROM on XLR boards
diff --git a/sys/mips/include/float.h b/sys/mips/include/float.h
index 2aa661a..86efd02 100644
--- a/sys/mips/include/float.h
+++ b/sys/mips/include/float.h
@@ -10,7 +10,7 @@
* 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
diff --git a/sys/mips/include/in_cksum.h b/sys/mips/include/in_cksum.h
index 633efa1..72edfba 100644
--- a/sys/mips/include/in_cksum.h
+++ b/sys/mips/include/in_cksum.h
@@ -10,7 +10,7 @@
* 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c
index 7ab4244..0d126e4 100644
--- a/sys/mips/mips/pmap.c
+++ b/sys/mips/mips/pmap.c
@@ -2638,6 +2638,62 @@ pmap_copy_pages(vm_page_t ma[], vm_offset_t a_offset, vm_page_t mb[],
}
}
+vm_offset_t
+pmap_quick_enter_page(vm_page_t m)
+{
+#if defined(__mips_n64)
+ return MIPS_PHYS_TO_DIRECT(VM_PAGE_TO_PHYS(m));
+#else
+ vm_paddr_t pa;
+ struct local_sysmaps *sysm;
+ pt_entry_t *pte;
+
+ pa = VM_PAGE_TO_PHYS(m);
+
+ if (MIPS_DIRECT_MAPPABLE(pa))
+ return (MIPS_PHYS_TO_DIRECT(pa));
+
+ critical_enter();
+ sysm = &sysmap_lmem[PCPU_GET(cpuid)];
+
+ KASSERT(sysm->valid1 == 0, ("pmap_quick_enter_page: PTE busy"));
+
+ pte = pmap_pte(kernel_pmap, sysm->base);
+ *pte = TLBLO_PA_TO_PFN(pa) | PTE_D | PTE_V | PTE_G |
+ (is_cacheable_mem(pa) ? PTE_C_CACHE : PTE_C_UNCACHED);
+ sysm->valid1 = 1;
+
+ return (sysm->base);
+#endif
+}
+
+void
+pmap_quick_remove_page(vm_offset_t addr)
+{
+ mips_dcache_wbinv_range(addr, PAGE_SIZE);
+
+#if !defined(__mips_n64)
+ struct local_sysmaps *sysm;
+ pt_entry_t *pte;
+
+ if (addr >= MIPS_KSEG0_START && addr < MIPS_KSEG0_END)
+ return;
+
+ sysm = &sysmap_lmem[PCPU_GET(cpuid)];
+
+ KASSERT(sysm->valid1 != 0,
+ ("pmap_quick_remove_page: PTE not in use"));
+ KASSERT(sysm->base == addr,
+ ("pmap_quick_remove_page: invalid address"));
+
+ pte = pmap_pte(kernel_pmap, addr);
+ *pte = PTE_G;
+ tlb_invalidate_address(kernel_pmap, addr);
+ sysm->valid1 = 0;
+ critical_exit();
+#endif
+}
+
/*
* Returns true if the pmap's pv is one of the first
* 16 pvs linked to from this page. This count may
@@ -3294,56 +3350,6 @@ DB_SHOW_COMMAND(ptable, ddb_pid_dump)
}
#endif
-#if defined(DEBUG)
-
-static void pads(pmap_t pm);
-void pmap_pvdump(vm_offset_t pa);
-
-/* print address space of pmap*/
-static void
-pads(pmap_t pm)
-{
- unsigned va, i, j;
- pt_entry_t *ptep;
-
- if (pm == kernel_pmap)
- return;
- for (i = 0; i < NPTEPG; i++)
- if (pm->pm_segtab[i])
- for (j = 0; j < NPTEPG; j++) {
- va = (i << SEGSHIFT) + (j << PAGE_SHIFT);
- if (pm == kernel_pmap && va < KERNBASE)
- continue;
- if (pm != kernel_pmap &&
- va >= VM_MAXUSER_ADDRESS)
- continue;
- ptep = pmap_pte(pm, va);
- if (pte_test(ptep, PTE_V))
- printf("%x:%x ", va, *(int *)ptep);
- }
-
-}
-
-void
-pmap_pvdump(vm_offset_t pa)
-{
- register pv_entry_t pv;
- vm_page_t m;
-
- printf("pa %x", pa);
- m = PHYS_TO_VM_PAGE(pa);
- for (pv = TAILQ_FIRST(&m->md.pv_list); pv;
- pv = TAILQ_NEXT(pv, pv_list)) {
- printf(" -> pmap %p, va %x", (void *)pv->pv_pmap, pv->pv_va);
- pads(pv->pv_pmap);
- }
- printf(" ");
-}
-
-/* N/C */
-#endif
-
-
/*
* Allocate TLB address space tag (called ASID or TLBPID) and return it.
* It takes almost as much or more time to search the TLB for a
diff --git a/sys/mips/rmi/dev/iic/ds1374u.c b/sys/mips/rmi/dev/iic/ds1374u.c
deleted file mode 100644
index 0c0b823..0000000
--- a/sys/mips/rmi/dev/iic/ds1374u.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*-
- * Copyright (c) 2003-2009 RMI Corporation
- * 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. Neither the name of RMI Corporation, 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 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.
- *
- * RMI_BSD */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-/*
- * RTC chip sitting on the I2C bus.
- */
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/clock.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/rman.h>
-
-#include <mips/include/bus.h>
-#include <mips/include/cpu.h>
-#include <mips/include/cpufunc.h>
-#include <mips/include/frame.h>
-#include <mips/include/resource.h>
-
-#include <dev/iicbus/iiconf.h>
-#include <dev/iicbus/iicbus.h>
-
-#include "iicbus_if.h"
-#include "clock_if.h"
-
-#define DS1374_RTC_COUNTER 0 /* counter (bytes 0-3) */
-
-struct ds1374u_softc {
- uint32_t sc_addr;
- device_t sc_dev;
-};
-
-static int
-ds1374u_probe(device_t dev)
-{
- device_set_desc(dev, "DS1374U-33 RTC");
- return (0);
-}
-
-static int
-ds1374u_attach(device_t dev)
-{
- struct ds1374u_softc *sc = device_get_softc(dev);
-
- if(sc==NULL) {
- printf("ds1374u_attach device_get_softc failed\n");
- return (0);
- }
- sc->sc_dev = dev;
- sc->sc_addr = iicbus_get_addr(dev);
-
- clock_register(dev, 1000);
- return (0);
-}
-
-static int
-ds1374u_settime(device_t dev, struct timespec *ts)
-{
- /* NB: register pointer precedes actual data */
- uint8_t data[5] = { DS1374_RTC_COUNTER };
- struct ds1374u_softc *sc = device_get_softc(dev);
- struct iic_msg msgs[1] = {
- { sc->sc_addr, IIC_M_WR, 5, data },
- };
-
- data[1] = (ts->tv_sec >> 0) & 0xff;
- data[2] = (ts->tv_sec >> 8) & 0xff;
- data[3] = (ts->tv_sec >> 16) & 0xff;
- data[4] = (ts->tv_sec >> 24) & 0xff;
-
- return iicbus_transfer(dev, msgs, 1);
-}
-
-static int
-ds1374u_gettime(device_t dev, struct timespec *ts)
-{
- struct ds1374u_softc *sc = device_get_softc(dev);
- uint8_t addr[1] = { DS1374_RTC_COUNTER };
- uint8_t secs[4];
- struct iic_msg msgs[2] = {
- { sc->sc_addr, IIC_M_WR, 1, addr },
- { sc->sc_addr, IIC_M_RD, 4, secs },
- };
- int error;
-
- error = iicbus_transfer(dev, msgs, 2);
- if (error == 0) {
- /* counter has seconds since epoch */
- ts->tv_sec = (secs[3] << 24) | (secs[2] << 16)
- | (secs[1] << 8) | (secs[0] << 0);
- ts->tv_nsec = 0;
- }
- return error;
-}
-
-static device_method_t ds1374u_methods[] = {
- DEVMETHOD(device_probe, ds1374u_probe),
- DEVMETHOD(device_attach, ds1374u_attach),
-
- DEVMETHOD(clock_gettime, ds1374u_gettime),
- DEVMETHOD(clock_settime, ds1374u_settime),
-
- {0, 0},
-};
-
-static driver_t ds1374u_driver = {
- "ds1374u",
- ds1374u_methods,
- sizeof(struct ds1374u_softc),
-};
-static devclass_t ds1374u_devclass;
-
-DRIVER_MODULE(ds1374u, iicbus, ds1374u_driver, ds1374u_devclass, 0, 0);
-MODULE_VERSION(ds1374u, 1);
-MODULE_DEPEND(ds1374u, iicbus, 1, 1, 1);
diff --git a/sys/mips/rmi/files.xlr b/sys/mips/rmi/files.xlr
index 0827ca7..ed85a1b 100644
--- a/sys/mips/rmi/files.xlr
+++ b/sys/mips/rmi/files.xlr
@@ -22,6 +22,5 @@ mips/rmi/dev/sec/rmisec.c optional rmisec
mips/rmi/dev/sec/rmilib.c optional rmisec
mips/rmi/dev/xlr/rge.c optional rge
mips/rmi/dev/nlge/if_nlge.c optional nlge
-mips/rmi/dev/iic/ds1374u.c optional ds1374u
mips/rmi/dev/iic/max6657.c optional max6657
mips/rmi/dev/iic/at24co2n.c optional at24co2n
diff --git a/sys/mips/rmi/xlr_i2c.c b/sys/mips/rmi/xlr_i2c.c
index 96f9820..2605887 100644
--- a/sys/mips/rmi/xlr_i2c.c
+++ b/sys/mips/rmi/xlr_i2c.c
@@ -187,7 +187,7 @@ xlr_i2c_attach(device_t dev)
return -1;
}
if(xlr_board_info.xlr_i2c_device[I2C_RTC].enabled == 1) {
- tmpd = device_add_child(sc->iicbus, "ds1374u", 0);
+ tmpd = device_add_child(sc->iicbus, "ds1374_rtc", 0);
device_set_ivars(tmpd, &xlr_board_info.xlr_i2c_device[I2C_RTC]);
}
if(xlr_board_info.xlr_i2c_device[I2C_THERMAL].enabled == 1) {
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 5084884..7b0e286 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -149,7 +149,7 @@ SUBDIR= \
${_if_me} \
if_lagg \
${_if_ndis} \
- if_stf \
+ ${_if_stf} \
if_tap \
if_tun \
if_vlan \
@@ -411,6 +411,11 @@ _if_gif= if_gif
_if_gre= if_gre
.endif
+.if (${MK_INET_SUPPORT} != "no" && ${MK_INET6_SUPPORT} != "no") || \
+ defined(ALL_MODULES)
+_if_stf= if_stf
+.endif
+
.if ${MK_INET_SUPPORT} != "no" || defined(ALL_MODULES)
_if_me= if_me
_ipdivert= ipdivert
diff --git a/sys/modules/cxgbe/t4_firmware/Makefile b/sys/modules/cxgbe/t4_firmware/Makefile
index 16be940..391632c 100644
--- a/sys/modules/cxgbe/t4_firmware/Makefile
+++ b/sys/modules/cxgbe/t4_firmware/Makefile
@@ -17,7 +17,7 @@ FIRMWS+= ${F}:${F:C/.txt//}:1.0.0.0
.endif
.endfor
-T4FW_VER= 1.14.2.0
+T4FW_VER= 1.14.4.0
FIRMWS+= t4fw.fw:t4fw:${T4FW_VER}
CLEANFILES+= t4fw.fw
diff --git a/sys/modules/cxgbe/t5_firmware/Makefile b/sys/modules/cxgbe/t5_firmware/Makefile
index eba2faa..c74e3c1 100644
--- a/sys/modules/cxgbe/t5_firmware/Makefile
+++ b/sys/modules/cxgbe/t5_firmware/Makefile
@@ -17,7 +17,7 @@ FIRMWS+= ${F}:${F:C/.txt//}:1.0.0.0
.endif
.endfor
-T5FW_VER= 1.14.2.0
+T5FW_VER= 1.14.4.0
FIRMWS+= t5fw.fw:t5fw:${T5FW_VER}
CLEANFILES+= t5fw.fw
diff --git a/sys/modules/if_stf/Makefile b/sys/modules/if_stf/Makefile
index 709c255..4eb2f01 100644
--- a/sys/modules/if_stf/Makefile
+++ b/sys/modules/if_stf/Makefile
@@ -3,6 +3,6 @@
.PATH: ${.CURDIR}/../../net
KMOD= if_stf
-SRCS= if_stf.c opt_inet.h opt_inet6.h
+SRCS= if_stf.c
.include <bsd.kmod.mk>
diff --git a/sys/modules/zfs/Makefile b/sys/modules/zfs/Makefile
index 05d226c..ffbd9ba 100644
--- a/sys/modules/zfs/Makefile
+++ b/sys/modules/zfs/Makefile
@@ -4,7 +4,7 @@ SYSDIR?=${.CURDIR}/../..
KMOD= zfs
-SRCS= bus_if.h device_if.h vnode_if.h
+SRCS= bus_if.h device_if.h vnode_if.h opt_kstack_pages.h
SUNW= ${SYSDIR}/cddl/contrib/opensolaris
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 9fc5e9f..985208b 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -620,7 +620,7 @@ bpf_attachd(struct bpf_d *d, struct bpf_if *bp)
bpf_detachd_locked(d);
/*
* Point d at bp, and add d to the interface's list.
- * Since there are many applicaiotns using BPF for
+ * Since there are many applications using BPF for
* sending raw packets only (dhcpd, cdpd are good examples)
* we can delay adding d to the list of active listeners until
* some filter is configured.
@@ -718,7 +718,7 @@ bpf_check_upgrade(u_long cmd, struct bpf_d *d, struct bpf_insn *fcode, int flen)
/*
* Add d to the list of active bp filters.
- * Reuqires bpf_attachd() to be called before
+ * Requires bpf_attachd() to be called before.
*/
static void
bpf_upgraded(struct bpf_d *d)
@@ -862,7 +862,7 @@ static int
bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
struct bpf_d *d;
- int error, size;
+ int error;
d = malloc(sizeof(*d), M_BPF, M_WAITOK | M_ZERO);
error = devfs_set_cdevpriv(d, bpf_dtor);
@@ -892,10 +892,6 @@ bpfopen(struct cdev *dev, int flags, int fmt, struct thread *td)
callout_init_mtx(&d->bd_callout, &d->bd_lock, 0);
knlist_init_mtx(&d->bd_sel.si_note, &d->bd_lock);
- /* Allocate default buffers */
- size = d->bd_bufsize;
- bpf_buffer_ioctl_sblen(d, &size);
-
return (0);
}
@@ -1472,10 +1468,33 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
* Set interface.
*/
case BIOCSETIF:
- BPF_LOCK();
- error = bpf_setif(d, (struct ifreq *)addr);
- BPF_UNLOCK();
- break;
+ {
+ int alloc_buf, size;
+
+ /*
+ * Behavior here depends on the buffering model. If
+ * we're using kernel memory buffers, then we can
+ * allocate them here. If we're using zero-copy,
+ * then the user process must have registered buffers
+ * by the time we get here.
+ */
+ alloc_buf = 0;
+ BPFD_LOCK(d);
+ if (d->bd_bufmode == BPF_BUFMODE_BUFFER &&
+ d->bd_sbuf == NULL)
+ alloc_buf = 1;
+ BPFD_UNLOCK(d);
+ if (alloc_buf) {
+ size = d->bd_bufsize;
+ error = bpf_buffer_ioctl_sblen(d, &size);
+ if (error != 0)
+ break;
+ }
+ BPF_LOCK();
+ error = bpf_setif(d, (struct ifreq *)addr);
+ BPF_UNLOCK();
+ break;
+ }
/*
* Set read timeout.
@@ -1912,10 +1931,8 @@ bpf_setif(struct bpf_d *d, struct ifreq *ifr)
BPFIF_RUNLOCK(bp);
/*
- * Behavior here depends on the buffering model. If we're using
- * kernel memory buffers, then we can allocate them here. If we're
- * using zero-copy, then the user process must have registered
- * buffers by the time we get here. If not, return an error.
+ * At this point, we expect the buffer is already allocated. If not,
+ * return an error.
*/
switch (d->bd_bufmode) {
case BPF_BUFMODE_BUFFER:
@@ -2018,10 +2035,10 @@ filt_bpfread(struct knote *kn, long hint)
ready = bpf_ready(d);
if (ready) {
kn->kn_data = d->bd_slen;
- while (d->bd_hbuf_in_use)
- mtx_sleep(&d->bd_hbuf_in_use, &d->bd_lock,
- PRINET, "bd_hbuf", 0);
- if (d->bd_hbuf)
+ /*
+ * Ignore the hold buffer if it is being copied to user space.
+ */
+ if (!d->bd_hbuf_in_use && d->bd_hbuf)
kn->kn_data += d->bd_hlen;
} else if (d->bd_rtout > 0 && d->bd_state == BPF_IDLE) {
callout_reset(&d->bd_callout, d->bd_rtout,
@@ -2353,9 +2370,6 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
* spot to do it.
*/
if (d->bd_fbuf == NULL && bpf_canfreebuf(d)) {
- while (d->bd_hbuf_in_use)
- mtx_sleep(&d->bd_hbuf_in_use, &d->bd_lock,
- PRINET, "bd_hbuf", 0);
d->bd_fbuf = d->bd_hbuf;
d->bd_hbuf = NULL;
d->bd_hlen = 0;
@@ -2398,9 +2412,7 @@ catchpacket(struct bpf_d *d, u_char *pkt, u_int pktlen, u_int snaplen,
++d->bd_dcount;
return;
}
- while (d->bd_hbuf_in_use)
- mtx_sleep(&d->bd_hbuf_in_use, &d->bd_lock,
- PRINET, "bd_hbuf", 0);
+ KASSERT(!d->bd_hbuf_in_use, ("hold buffer is in use"));
ROTATE_BUFFERS(d);
do_wakeup = 1;
curlen = 0;
diff --git a/sys/net/bpf.h b/sys/net/bpf.h
index df326e6..a74b521 100644
--- a/sys/net/bpf.h
+++ b/sys/net/bpf.h
@@ -1436,9 +1436,9 @@ SYSCTL_DECL(_net_bpf);
/*
* Rotate the packet buffers in descriptor d. Move the store buffer into the
- * hold slot, and the free buffer ino the store slot. Zero the length of the
- * new store buffer. Descriptor lock should be held. Hold buffer must
- * not be marked "in use".
+ * hold slot, and the free buffer into the store slot. Zero the length of the
+ * new store buffer. Descriptor lock should be held. One must be careful to
+ * not rotate the buffers twice, i.e. if fbuf != NULL.
*/
#define ROTATE_BUFFERS(d) do { \
(d)->bd_hbuf = (d)->bd_sbuf; \
diff --git a/sys/net/bpf_buffer.c b/sys/net/bpf_buffer.c
index 74e1ae4..64bb982 100644
--- a/sys/net/bpf_buffer.c
+++ b/sys/net/bpf_buffer.c
@@ -79,8 +79,6 @@ __FBSDID("$FreeBSD$");
#include <net/bpf_buffer.h>
#include <net/bpfdesc.h>
-#define PRINET 26 /* interruptible */
-
/*
* Implement historical kernel memory buffering model for BPF: two malloc(9)
* kernel buffers are hung off of the descriptor. The size is fixed prior to
@@ -191,9 +189,6 @@ bpf_buffer_ioctl_sblen(struct bpf_d *d, u_int *i)
return (EINVAL);
}
- while (d->bd_hbuf_in_use)
- mtx_sleep(&d->bd_hbuf_in_use, &d->bd_lock,
- PRINET, "bd_hbuf", 0);
/* Free old buffers if set */
if (d->bd_fbuf != NULL)
free(d->bd_fbuf, M_BPF);
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index 48a842a..78b4d9d 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -280,9 +280,9 @@ int
gif_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
{
GIF_RLOCK_TRACKER;
+ const struct ip *ip;
struct gif_softc *sc;
int ret;
- uint8_t ver;
sc = (struct gif_softc *)arg;
if (sc == NULL || (GIF2IFP(sc)->if_flags & IFF_UP) == 0)
@@ -309,11 +309,12 @@ gif_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
}
/* Bail on short packets */
+ M_ASSERTPKTHDR(m);
if (m->m_pkthdr.len < sizeof(struct ip))
goto done;
- m_copydata(m, 0, 1, &ver);
- switch (ver >> 4) {
+ ip = mtod(m, const struct ip *);
+ switch (ip->ip_v) {
#ifdef INET
case 4:
if (sc->gif_family != AF_INET)
diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c
index 6743981..841a0f2 100644
--- a/sys/net/if_spppsubr.c
+++ b/sys/net/if_spppsubr.c
@@ -28,7 +28,9 @@
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/module.h>
+#include <sys/rmlock.h>
#include <sys/sockio.h>
#include <sys/socket.h>
#include <sys/syslog.h>
diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c
index aed2a37..cbcee14 100644
--- a/sys/net/if_stf.c
+++ b/sys/net/if_stf.c
@@ -74,9 +74,6 @@
* Note that there is no way to be 100% secure.
*/
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
@@ -84,10 +81,12 @@
#include <sys/mbuf.h>
#include <sys/errno.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/module.h>
#include <sys/protosw.h>
#include <sys/proc.h>
#include <sys/queue.h>
+#include <sys/rmlock.h>
#include <sys/sysctl.h>
#include <machine/cpu.h>
@@ -273,10 +272,7 @@ stf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
}
static int
-stfmodevent(mod, type, data)
- module_t mod;
- int type;
- void *data;
+stfmodevent(module_t mod, int type, void *data)
{
switch (type) {
@@ -303,11 +299,7 @@ static moduledata_t stf_mod = {
DECLARE_MODULE(if_stf, stf_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
static int
-stf_encapcheck(m, off, proto, arg)
- const struct mbuf *m;
- int off;
- int proto;
- void *arg;
+stf_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
{
struct ip ip;
struct stf_softc *sc;
@@ -402,7 +394,7 @@ stf_getsrcifa6(struct ifnet *ifp, struct in6_addr *addr, struct in6_addr *mask)
static int
stf_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
- struct route *ro)
+ struct route *ro)
{
struct stf_softc *sc;
const struct sockaddr_in6 *dst6;
@@ -508,8 +500,7 @@ stf_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
}
static int
-isrfc1918addr(in)
- struct in_addr *in;
+isrfc1918addr(struct in_addr *in)
{
/*
* returns 1 if private address range:
@@ -525,11 +516,9 @@ isrfc1918addr(in)
}
static int
-stf_checkaddr4(sc, in, inifp)
- struct stf_softc *sc;
- struct in_addr *in;
- struct ifnet *inifp; /* incoming interface */
+stf_checkaddr4(struct stf_softc *sc, struct in_addr *in, struct ifnet *inifp)
{
+ struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia4;
/*
@@ -553,16 +542,16 @@ stf_checkaddr4(sc, in, inifp)
/*
* reject packets with broadcast
*/
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia4, &V_in_ifaddrhead, ia_link) {
if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
continue;
if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr) {
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return -1;
}
}
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* perform ingress filter
@@ -594,10 +583,7 @@ stf_checkaddr4(sc, in, inifp)
}
static int
-stf_checkaddr6(sc, in6, inifp)
- struct stf_softc *sc;
- struct in6_addr *in6;
- struct ifnet *inifp; /* incoming interface */
+stf_checkaddr6(struct stf_softc *sc, struct in6_addr *in6, struct ifnet *inifp)
{
/*
* check 6to4 addresses
@@ -720,10 +706,7 @@ in_stf_input(struct mbuf **mp, int *offp, int proto)
}
static int
-stf_ioctl(ifp, cmd, data)
- struct ifnet *ifp;
- u_long cmd;
- caddr_t data;
+stf_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct ifaddr *ifa;
struct ifreq *ifr;
diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h
index 98ffd4a..bab26fe 100644
--- a/sys/net/pfkeyv2.h
+++ b/sys/net/pfkeyv2.h
@@ -218,7 +218,6 @@ struct sadb_x_sa2 {
};
/* XXX Policy Extension */
-/* sizeof(struct sadb_x_policy) == 16 */
struct sadb_x_policy {
u_int16_t sadb_x_policy_len;
u_int16_t sadb_x_policy_exttype;
@@ -228,6 +227,8 @@ struct sadb_x_policy {
u_int32_t sadb_x_policy_id;
u_int32_t sadb_x_policy_reserved2;
};
+_Static_assert(sizeof(struct sadb_x_policy) == 16, "struct size mismatch");
+
/*
* When policy_type == IPSEC, it is followed by some of
* the ipsec policy request.
@@ -256,31 +257,31 @@ struct sadb_x_ipsecrequest {
};
/* NAT-Traversal type, see RFC 3948 (and drafts). */
-/* sizeof(struct sadb_x_nat_t_type) == 8 */
struct sadb_x_nat_t_type {
u_int16_t sadb_x_nat_t_type_len;
u_int16_t sadb_x_nat_t_type_exttype;
u_int8_t sadb_x_nat_t_type_type;
u_int8_t sadb_x_nat_t_type_reserved[3];
};
+_Static_assert(sizeof(struct sadb_x_nat_t_type) == 8, "struct size mismatch");
/* NAT-Traversal source or destination port. */
-/* sizeof(struct sadb_x_nat_t_port) == 8 */
struct sadb_x_nat_t_port {
u_int16_t sadb_x_nat_t_port_len;
u_int16_t sadb_x_nat_t_port_exttype;
u_int16_t sadb_x_nat_t_port_port;
u_int16_t sadb_x_nat_t_port_reserved;
};
+_Static_assert(sizeof(struct sadb_x_nat_t_port) == 8, "struct size mismatch");
/* ESP fragmentation size. */
-/* sizeof(struct sadb_x_nat_t_frag) == 8 */
struct sadb_x_nat_t_frag {
u_int16_t sadb_x_nat_t_frag_len;
u_int16_t sadb_x_nat_t_frag_exttype;
u_int16_t sadb_x_nat_t_frag_fraglen;
u_int16_t sadb_x_nat_t_frag_reserved;
};
+_Static_assert(sizeof(struct sadb_x_nat_t_frag) == 8, "struct size mismatch");
#define SADB_EXT_RESERVED 0
@@ -332,46 +333,47 @@ struct sadb_x_nat_t_frag {
#define SADB_SAFLAGS_PFS 1
-/* RFC2367 numbers - meets RFC2407 */
+/*
+ * Though some of these numbers (both _AALG and _EALG) appear to be
+ * IKEv2 numbers and others original IKE numbers, they have no meaning.
+ * These are constants that the various IKE daemons use to tell the kernel
+ * what cipher to use.
+ *
+ * Do not use these constants directly to decide which Transformation ID
+ * to send. You are responsible for mapping them yourself.
+ */
#define SADB_AALG_NONE 0
#define SADB_AALG_MD5HMAC 2
#define SADB_AALG_SHA1HMAC 3
#define SADB_AALG_MAX 252
-/* private allocations - based on RFC2407/IANA assignment */
#define SADB_X_AALG_SHA2_256 5
#define SADB_X_AALG_SHA2_384 6
#define SADB_X_AALG_SHA2_512 7
#define SADB_X_AALG_RIPEMD160HMAC 8
-#define SADB_X_AALG_AES_XCBC_MAC 9 /* draft-ietf-ipsec-ciph-aes-xcbc-mac-04 */
+#define SADB_X_AALG_AES_XCBC_MAC 9 /* RFC3566 */
#define SADB_X_AALG_AES128GMAC 11 /* RFC4543 + Errata1821 */
#define SADB_X_AALG_AES192GMAC 12
#define SADB_X_AALG_AES256GMAC 13
-/* private allocations should use 249-255 (RFC2407) */
#define SADB_X_AALG_MD5 249 /* Keyed MD5 */
#define SADB_X_AALG_SHA 250 /* Keyed SHA */
#define SADB_X_AALG_NULL 251 /* null authentication */
#define SADB_X_AALG_TCP_MD5 252 /* Keyed TCP-MD5 (RFC2385) */
-/* RFC2367 numbers - meets RFC2407 */
#define SADB_EALG_NONE 0
#define SADB_EALG_DESCBC 2
#define SADB_EALG_3DESCBC 3
-#define SADB_EALG_NULL 11
-#define SADB_EALG_MAX 250
-/* private allocations - based on RFC2407/IANA assignment */
#define SADB_X_EALG_CAST128CBC 6
#define SADB_X_EALG_BLOWFISHCBC 7
+#define SADB_EALG_NULL 11
#define SADB_X_EALG_RIJNDAELCBC 12
#define SADB_X_EALG_AES 12
+#define SADB_X_EALG_AESCTR 13
#define SADB_X_EALG_AESGCM8 18 /* RFC4106 */
#define SADB_X_EALG_AESGCM12 19
#define SADB_X_EALG_AESGCM16 20
-/* private allocations - based on RFC4312/IANA assignment */
-#define SADB_X_EALG_CAMELLIACBC 22
-#define SADB_X_EALG_AESGMAC 23 /* RFC4543 + Errata1821 */
-/* private allocations should use 249-255 (RFC2407) */
-#define SADB_X_EALG_SKIPJACK 249 /*250*/ /* for IPSEC */
-#define SADB_X_EALG_AESCTR 250 /*249*/ /* draft-ietf-ipsec-ciph-aes-ctr-03 */
+#define SADB_X_EALG_CAMELLIACBC 22
+#define SADB_X_EALG_AESGMAC 23 /* RFC4543 + Errata1821 */
+#define SADB_EALG_MAX 23 /* !!! keep updated !!! */
/* private allocations - based on RFC2407/IANA assignment */
#define SADB_X_CALG_NONE 0
diff --git a/sys/net/radix.c b/sys/net/radix.c
index d16c924..d6db35e 100644
--- a/sys/net/radix.c
+++ b/sys/net/radix.c
@@ -533,7 +533,7 @@ rn_addmask(void *n_arg, struct radix_node_head *maskhead, int search, int skip)
x = rn_insert(cp, maskhead, &maskduplicated, x);
if (maskduplicated) {
log(LOG_ERR, "rn_addmask: mask impossibly already in tree");
- Free(saved_x);
+ R_Free(saved_x);
return (x);
}
/*
@@ -829,7 +829,7 @@ rn_delete(void *v_arg, void *netmask_arg, struct radix_node_head *head)
for (mp = &x->rn_mklist; (m = *mp); mp = &m->rm_mklist)
if (m == saved_m) {
*mp = m->rm_mklist;
- Free(m);
+ R_Free(m);
break;
}
if (m == 0) {
@@ -920,7 +920,7 @@ on1:
struct radix_mask *mm = m->rm_mklist;
x->rn_mklist = 0;
if (--(m->rm_refs) < 0)
- Free(m);
+ R_Free(m);
m = mm;
}
if (m)
@@ -1152,7 +1152,7 @@ rn_detachhead_internal(void **head)
rnh = *head;
/* Free <left,root,right> nodes. */
- Free(rnh);
+ R_Free(rnh);
*head = NULL;
}
@@ -1186,7 +1186,7 @@ rn_freeentry(struct radix_node *rn, void *arg)
x = (struct radix_node *)rn_delete(rn + 2, NULL, rnh);
if (x != NULL)
- Free(x);
+ R_Free(x);
return (0);
}
diff --git a/sys/net/radix.h b/sys/net/radix.h
index cc262fa..d4bb58a 100644
--- a/sys/net/radix.h
+++ b/sys/net/radix.h
@@ -137,7 +137,7 @@ struct radix_node_head {
#else
#define R_Malloc(p, t, n) (p = (t) malloc((unsigned long)(n), M_RTABLE, M_NOWAIT))
#define R_Zalloc(p, t, n) (p = (t) malloc((unsigned long)(n), M_RTABLE, M_NOWAIT | M_ZERO))
-#define Free(p) free((caddr_t)p, M_RTABLE);
+#define R_Free(p) free((caddr_t)p, M_RTABLE);
#define RADIX_NODE_HEAD_LOCK_INIT(rnh) \
rw_init_flags(&(rnh)->rnh_lock, "radix node head", 0)
diff --git a/sys/net/route.c b/sys/net/route.c
index 992cf8e..a887422 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -519,7 +519,7 @@ rtfree(struct rtentry *rt)
* This also frees the gateway, as they are always malloc'd
* together.
*/
- Free(rt_key(rt));
+ R_Free(rt_key(rt));
/*
* and the rtentry itself of course
@@ -1352,7 +1352,7 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
if (rn_mpath_capable(rnh) &&
rt_mpath_conflict(rnh, rt, netmask)) {
ifa_free(rt->rt_ifa);
- Free(rt_key(rt));
+ R_Free(rt_key(rt));
uma_zfree(V_rtzone, rt);
senderr(EEXIST);
}
@@ -1419,7 +1419,7 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
*/
if (rn == NULL) {
ifa_free(rt->rt_ifa);
- Free(rt_key(rt));
+ R_Free(rt_key(rt));
uma_zfree(V_rtzone, rt);
#ifdef FLOWTABLE
if (rt0 != NULL)
@@ -1641,7 +1641,7 @@ rt_setgate(struct rtentry *rt, struct sockaddr *dst, struct sockaddr *gate)
* Free()/free() handle a NULL argument just fine.
*/
bcopy(dst, new, dlen);
- Free(rt_key(rt)); /* free old block, if any */
+ R_Free(rt_key(rt)); /* free old block, if any */
rt_key(rt) = (struct sockaddr *)new;
rt->rt_gateway = (struct sockaddr *)(new + dlen);
}
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c
index 3902227..39e03ea 100644
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
+#include <sys/sbuf.h>
#include <machine/stdarg.h>
@@ -91,8 +92,6 @@ static void ieee80211_syncflag_ext_locked(struct ieee80211com *ic, int flag);
static int ieee80211_media_setup(struct ieee80211com *ic,
struct ifmedia *media, int caps, int addsta,
ifm_change_cb_t media_change, ifm_stat_cb_t media_stat);
-static void ieee80211com_media_status(struct ifnet *, struct ifmediareq *);
-static int ieee80211com_media_change(struct ifnet *);
static int media_status(enum ieee80211_opmode,
const struct ieee80211_channel *);
static uint64_t ieee80211_get_counter(struct ifnet *, ift_counter);
@@ -121,7 +120,7 @@ static const struct ieee80211_rateset ieee80211_rateset_11g =
* all available channels as active, and pick
* a default channel if not already specified.
*/
-static void
+void
ieee80211_chan_init(struct ieee80211com *ic)
{
#define DEFAULTRATES(m, def) do { \
@@ -238,29 +237,6 @@ null_update_promisc(struct ieee80211com *ic)
ic_printf(ic, "need promiscuous mode update callback\n");
}
-static int
-null_transmit(struct ifnet *ifp, struct mbuf *m)
-{
- m_freem(m);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- return EACCES; /* XXX EIO/EPERM? */
-}
-
-static int
-null_output(struct ifnet *ifp, struct mbuf *m,
- const struct sockaddr *dst, struct route *ro)
-{
- if_printf(ifp, "discard raw packet\n");
- return null_transmit(ifp, m);
-}
-
-static void
-null_input(struct ifnet *ifp, struct mbuf *m)
-{
- if_printf(ifp, "if_input should not be called\n");
- m_freem(m);
-}
-
static void
null_update_chw(struct ieee80211com *ic)
{
@@ -281,19 +257,43 @@ ic_printf(struct ieee80211com *ic, const char * fmt, ...)
return (retval);
}
+static LIST_HEAD(, ieee80211com) ic_head = LIST_HEAD_INITIALIZER(ic_head);
+static struct mtx ic_list_mtx;
+MTX_SYSINIT(ic_list, &ic_list_mtx, "ieee80211com list", MTX_DEF);
+
+static int
+sysctl_ieee80211coms(SYSCTL_HANDLER_ARGS)
+{
+ struct ieee80211com *ic;
+ struct sbuf *sb;
+ char *sp;
+ int error;
+
+ sb = sbuf_new_auto();
+ sp = "";
+ mtx_lock(&ic_list_mtx);
+ LIST_FOREACH(ic, &ic_head, ic_next) {
+ sbuf_printf(sb, "%s%s", sp, ic->ic_name);
+ sp = " ";
+ }
+ mtx_unlock(&ic_list_mtx);
+ sbuf_finish(sb);
+ error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
+ sbuf_delete(sb);
+ return (error);
+}
+
+SYSCTL_PROC(_net_wlan, OID_AUTO, devices,
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_ieee80211coms, "A", "names of available 802.11 devices");
+
/*
* Attach/setup the common net80211 state. Called by
* the driver on attach to prior to creating any vap's.
*/
void
-ieee80211_ifattach(struct ieee80211com *ic,
- const uint8_t macaddr[IEEE80211_ADDR_LEN])
+ieee80211_ifattach(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct sockaddr_dl *sdl;
- struct ifaddr *ifa;
-
- KASSERT(ifp->if_type == IFT_IEEE80211, ("if_type %d", ifp->if_type));
IEEE80211_LOCK_INIT(ic, ic->ic_name);
IEEE80211_TX_LOCK_INIT(ic, ic->ic_name);
@@ -311,7 +311,7 @@ ieee80211_ifattach(struct ieee80211com *ic,
* available channels as active, and pick a default
* channel if not already specified.
*/
- ieee80211_media_init(ic);
+ ieee80211_chan_init(ic);
ic->ic_update_mcast = null_update_mcast;
ic->ic_update_promisc = null_update_promisc;
@@ -336,28 +336,9 @@ ieee80211_ifattach(struct ieee80211com *ic,
ieee80211_sysctl_attach(ic);
- ifp->if_addrlen = IEEE80211_ADDR_LEN;
- ifp->if_hdrlen = 0;
-
- CURVNET_SET(vnet0);
-
- if_attach(ifp);
-
- ifp->if_mtu = IEEE80211_MTU_MAX;
- ifp->if_broadcastaddr = ieee80211broadcastaddr;
- ifp->if_output = null_output;
- ifp->if_input = null_input; /* just in case */
- ifp->if_resolvemulti = NULL; /* NB: callers check */
-
- ifa = ifaddr_byindex(ifp->if_index);
- KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__));
- sdl = (struct sockaddr_dl *)ifa->ifa_addr;
- sdl->sdl_type = IFT_ETHER; /* XXX IFT_IEEE80211? */
- sdl->sdl_alen = IEEE80211_ADDR_LEN;
- IEEE80211_ADDR_COPY(LLADDR(sdl), macaddr);
- ifa_free(ifa);
-
- CURVNET_RESTORE();
+ mtx_lock(&ic_list_mtx);
+ LIST_INSERT_HEAD(&ic_head, ic, ic_next);
+ mtx_unlock(&ic_list_mtx);
}
/*
@@ -369,16 +350,11 @@ ieee80211_ifattach(struct ieee80211com *ic,
void
ieee80211_ifdetach(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
struct ieee80211vap *vap;
- /*
- * This detaches the main interface, but not the vaps.
- * Each VAP may be in a separate VIMAGE.
- */
- CURVNET_SET(ifp->if_vnet);
- if_detach(ifp);
- CURVNET_RESTORE();
+ mtx_lock(&ic_list_mtx);
+ LIST_REMOVE(ic, ic_next);
+ mtx_unlock(&ic_list_mtx);
/*
* The VAP is responsible for setting and clearing
@@ -402,8 +378,6 @@ ieee80211_ifdetach(struct ieee80211com *ic)
ieee80211_power_detach(ic);
ieee80211_node_detach(ic);
- /* XXX VNET needed? */
- ifmedia_removeall(&ic->ic_media);
counter_u64_free(ic->ic_ierrors);
counter_u64_free(ic->ic_oerrors);
@@ -412,6 +386,20 @@ ieee80211_ifdetach(struct ieee80211com *ic)
IEEE80211_LOCK_DESTROY(ic);
}
+struct ieee80211com *
+ieee80211_find_com(const char *name)
+{
+ struct ieee80211com *ic;
+
+ mtx_lock(&ic_list_mtx);
+ LIST_FOREACH(ic, &ic_head, ic_next)
+ if (strcmp(ic->ic_name, name) == 0)
+ break;
+ mtx_unlock(&ic_list_mtx);
+
+ return (ic);
+}
+
/*
* Default reset method for use with the ioctl support. This
* method is invoked after any state change in the 802.11
@@ -460,8 +448,7 @@ ieee80211_get_counter(struct ifnet *ifp, ift_counter cnt)
int
ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode,
- int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
- const uint8_t macaddr[IEEE80211_ADDR_LEN])
+ int flags, const uint8_t bssid[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp;
@@ -490,6 +477,7 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
vap->iv_htextcaps = ic->ic_htextcaps;
vap->iv_opmode = opmode;
vap->iv_caps |= ieee80211_opcap[opmode];
+ vap->iv_myaddr = ic->ic_macaddr;
switch (opmode) {
case IEEE80211_M_WDS:
/*
@@ -556,8 +544,6 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
*/
vap->iv_reset = default_reset;
- IEEE80211_ADDR_COPY(vap->iv_myaddr, macaddr);
-
ieee80211_sysctl_vattach(vap);
ieee80211_crypto_vattach(vap);
ieee80211_node_vattach(vap);
@@ -581,8 +567,8 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
* from this call the vap is ready for use.
*/
int
-ieee80211_vap_attach(struct ieee80211vap *vap,
- ifm_change_cb_t media_change, ifm_stat_cb_t media_stat)
+ieee80211_vap_attach(struct ieee80211vap *vap, ifm_change_cb_t media_change,
+ ifm_stat_cb_t media_stat, const uint8_t macaddr[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp = vap->iv_ifp;
struct ieee80211com *ic = vap->iv_ic;
@@ -610,7 +596,8 @@ ieee80211_vap_attach(struct ieee80211vap *vap,
if (maxrate)
ifp->if_baudrate = IF_Mbps(maxrate);
- ether_ifattach(ifp, vap->iv_myaddr);
+ ether_ifattach(ifp, macaddr);
+ vap->iv_myaddr = IF_LLADDR(ifp);
/* hook output method setup by ether_ifattach */
vap->iv_output = ifp->if_output;
ifp->if_output = ieee80211_output;
@@ -626,8 +613,6 @@ ieee80211_vap_attach(struct ieee80211vap *vap,
ieee80211_syncflag_locked(ic, IEEE80211_F_BURST);
ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_HT);
ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40);
- ieee80211_syncifflag_locked(ic, IFF_PROMISC);
- ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
IEEE80211_UNLOCK(ic);
return 1;
@@ -677,8 +662,10 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
ieee80211_syncflag_ht_locked(ic, IEEE80211_FHT_USEHT40);
/* NB: this handles the bpfdetach done below */
ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_BPF);
- ieee80211_syncifflag_locked(ic, IFF_PROMISC);
- ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
+ if (vap->iv_ifflags & IFF_PROMISC)
+ ieee80211_promisc(vap, false);
+ if (vap->iv_ifflags & IFF_ALLMULTI)
+ ieee80211_allmulti(vap, false);
IEEE80211_UNLOCK(ic);
ifmedia_removeall(&vap->iv_media);
@@ -703,49 +690,57 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
}
/*
- * Synchronize flag bit state in the parent ifnet structure
- * according to the state of all vap ifnet's. This is used,
- * for example, to handle IFF_PROMISC and IFF_ALLMULTI.
+ * Count number of vaps in promisc, and issue promisc on
+ * parent respectively.
*/
void
-ieee80211_syncifflag_locked(struct ieee80211com *ic, int flag)
+ieee80211_promisc(struct ieee80211vap *vap, bool on)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct ieee80211vap *vap;
- int bit, oflags;
+ struct ieee80211com *ic = vap->iv_ic;
- IEEE80211_LOCK_ASSERT(ic);
+ /*
+ * XXX the bridge sets PROMISC but we don't want to
+ * enable it on the device, discard here so all the
+ * drivers don't need to special-case it
+ */
+ if (!(vap->iv_opmode == IEEE80211_M_MONITOR ||
+ (vap->iv_opmode == IEEE80211_M_AHDEMO &&
+ (vap->iv_caps & IEEE80211_C_TDMA) == 0)))
+ return;
- bit = 0;
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
- if (vap->iv_ifp->if_flags & flag) {
- /*
- * XXX the bridge sets PROMISC but we don't want to
- * enable it on the device, discard here so all the
- * drivers don't need to special-case it
- */
- if (flag == IFF_PROMISC &&
- !(vap->iv_opmode == IEEE80211_M_MONITOR ||
- (vap->iv_opmode == IEEE80211_M_AHDEMO &&
- (vap->iv_caps & IEEE80211_C_TDMA) == 0)))
- continue;
- bit = 1;
- break;
- }
- oflags = ifp->if_flags;
- if (bit)
- ifp->if_flags |= flag;
- else
- ifp->if_flags &= ~flag;
- if ((ifp->if_flags ^ oflags) & flag) {
- /* XXX should we return 1/0 and let caller do this? */
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if (flag == IFF_PROMISC)
- ieee80211_runtask(ic, &ic->ic_promisc_task);
- else if (flag == IFF_ALLMULTI)
- ieee80211_runtask(ic, &ic->ic_mcast_task);
- }
+ IEEE80211_LOCK(ic);
+ if (on) {
+ if (++ic->ic_promisc == 1)
+ ieee80211_runtask(ic, &ic->ic_promisc_task);
+ } else {
+ KASSERT(ic->ic_promisc > 0, ("%s: ic %p not promisc",
+ __func__, ic));
+ if (--ic->ic_promisc == 0)
+ ieee80211_runtask(ic, &ic->ic_promisc_task);
}
+ IEEE80211_UNLOCK(ic);
+}
+
+/*
+ * Count number of vaps in allmulti, and issue allmulti on
+ * parent respectively.
+ */
+void
+ieee80211_allmulti(struct ieee80211vap *vap, bool on)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+
+ IEEE80211_LOCK(ic);
+ if (on) {
+ if (++ic->ic_allmulti == 1)
+ ieee80211_runtask(ic, &ic->ic_mcast_task);
+ } else {
+ KASSERT(ic->ic_allmulti > 0, ("%s: ic %p not allmulti",
+ __func__, ic));
+ if (--ic->ic_allmulti == 0)
+ ieee80211_runtask(ic, &ic->ic_mcast_task);
+ }
+ IEEE80211_UNLOCK(ic);
}
/*
@@ -1234,39 +1229,6 @@ ieee80211_media_setup(struct ieee80211com *ic,
return maxrate;
}
-void
-ieee80211_media_init(struct ieee80211com *ic)
-{
- struct ifnet *ifp = ic->ic_ifp;
- int maxrate;
-
- /* NB: this works because the structure is initialized to zero */
- if (!LIST_EMPTY(&ic->ic_media.ifm_list)) {
- /*
- * We are re-initializing the channel list; clear
- * the existing media state as the media routines
- * don't suppress duplicates.
- */
- ifmedia_removeall(&ic->ic_media);
- }
- ieee80211_chan_init(ic);
-
- /*
- * Recalculate media settings in case new channel list changes
- * the set of available modes.
- */
- maxrate = ieee80211_media_setup(ic, &ic->ic_media, ic->ic_caps, 1,
- ieee80211com_media_change, ieee80211com_media_status);
- /* NB: strip explicit mode; we're actually in autoselect */
- ifmedia_set(&ic->ic_media,
- media_status(ic->ic_opmode, ic->ic_curchan) &~
- (IFM_MMASK | IFM_IEEE80211_TURBO));
- if (maxrate)
- ifp->if_baudrate = IF_Mbps(maxrate);
-
- /* XXX need to propagate new media settings to vap's */
-}
-
/* XXX inline or eliminate? */
const struct ieee80211_rateset *
ieee80211_get_suprates(struct ieee80211com *ic, const struct ieee80211_channel *c)
@@ -1395,15 +1357,6 @@ media2mode(const struct ifmedia_entry *ime, uint32_t flags, uint16_t *mode)
}
/*
- * Handle a media change request on the underlying interface.
- */
-int
-ieee80211com_media_change(struct ifnet *ifp)
-{
- return EINVAL;
-}
-
-/*
* Handle a media change request on the vap interface.
*/
int
@@ -1480,23 +1433,6 @@ media_status(enum ieee80211_opmode opmode, const struct ieee80211_channel *chan)
return status;
}
-static void
-ieee80211com_media_status(struct ifnet *ifp, struct ifmediareq *imr)
-{
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap;
-
- imr->ifm_status = IFM_AVALID;
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
- if (vap->iv_ifp->if_flags & IFF_UP) {
- imr->ifm_status |= IFM_ACTIVE;
- break;
- }
- imr->ifm_active = media_status(ic->ic_opmode, ic->ic_curchan);
- if (imr->ifm_status & IFM_ACTIVE)
- imr->ifm_current = imr->ifm_active;
-}
-
void
ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr)
{
diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c
index e646cf2..ae4910c 100644
--- a/sys/net80211/ieee80211_ddb.c
+++ b/sys/net80211/ieee80211_ddb.c
@@ -520,7 +520,7 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta,
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
db_printf(" %s(%p)", vap->iv_ifp->if_xname, vap);
db_printf("\n");
- db_printf("\tifp %p(%s)", ic->ic_ifp, ic->ic_ifp->if_xname);
+ db_printf("\tsoftc %p", ic->ic_softc);
db_printf("\tname %s", ic->ic_name);
db_printf(" comlock %p", &ic->ic_comlock);
db_printf("\n");
@@ -528,7 +528,6 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta,
db_printf(" phytype %d", ic->ic_phytype);
db_printf(" opmode %s", ieee80211_opmode_name[ic->ic_opmode]);
db_printf("\n");
- db_printf("\tmedia %p", &ic->ic_media);
db_printf(" inact %p", &ic->ic_inact);
db_printf("\n");
diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c
index 3af75df..9a8e941 100644
--- a/sys/net80211/ieee80211_freebsd.c
+++ b/sys/net80211/ieee80211_freebsd.c
@@ -69,58 +69,27 @@ static MALLOC_DEFINE(M_80211_COM, "80211com", "802.11 com state");
static const char wlanname[] = "wlan";
static struct if_clone *wlan_cloner;
-/*
- * Allocate/free com structure in conjunction with ifnet;
- * these routines are registered with if_register_com_alloc
- * below and are called automatically by the ifnet code
- * when the ifnet of the parent device is created.
- */
-static void *
-wlan_alloc(u_char type, struct ifnet *ifp)
-{
- struct ieee80211com *ic;
-
- ic = IEEE80211_MALLOC(sizeof(struct ieee80211com), M_80211_COM,
- IEEE80211_M_WAITOK | IEEE80211_M_ZERO);
- ic->ic_ifp = ifp;
-
- return (ic);
-}
-
-static void
-wlan_free(void *ic, u_char type)
-{
- IEEE80211_FREE(ic, M_80211_COM);
-}
-
static int
wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
{
struct ieee80211_clone_params cp;
struct ieee80211vap *vap;
struct ieee80211com *ic;
- struct ifnet *ifp;
int error;
error = copyin(params, &cp, sizeof(cp));
if (error)
return error;
- ifp = ifunit(cp.icp_parent);
- if (ifp == NULL)
+ ic = ieee80211_find_com(cp.icp_parent);
+ if (ic == NULL)
return ENXIO;
- /* XXX move printfs to DIAGNOSTIC before release */
- if (ifp->if_type != IFT_IEEE80211) {
- if_printf(ifp, "%s: reject, not an 802.11 device\n", __func__);
- return ENXIO;
- }
if (cp.icp_opmode >= IEEE80211_OPMODE_MAX) {
- if_printf(ifp, "%s: invalid opmode %d\n",
- __func__, cp.icp_opmode);
+ ic_printf(ic, "%s: invalid opmode %d\n", __func__,
+ cp.icp_opmode);
return EINVAL;
}
- ic = ifp->if_l2com;
if ((ic->ic_caps & ieee80211_opcap[cp.icp_opmode]) == 0) {
- if_printf(ifp, "%s mode not supported\n",
+ ic_printf(ic, "%s mode not supported\n",
ieee80211_opmode_name[cp.icp_opmode]);
return EOPNOTSUPP;
}
@@ -131,13 +100,13 @@ wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
(1)
#endif
) {
- if_printf(ifp, "TDMA not supported\n");
+ ic_printf(ic, "TDMA not supported\n");
return EOPNOTSUPP;
}
vap = ic->ic_vap_create(ic, wlanname, unit,
cp.icp_opmode, cp.icp_flags, cp.icp_bssid,
cp.icp_flags & IEEE80211_CLONE_MACADDR ?
- cp.icp_macaddr : (const uint8_t *)IF_LLADDR(ifp));
+ cp.icp_macaddr : ic->ic_macaddr);
return (vap == NULL ? EIO : 0);
}
@@ -528,17 +497,19 @@ ieee80211_process_callback(struct ieee80211_node *ni,
* (the callers will first need modifying.)
*/
int
-ieee80211_parent_xmitpkt(struct ieee80211com *ic,
- struct mbuf *m)
+ieee80211_parent_xmitpkt(struct ieee80211com *ic, struct mbuf *m)
{
- struct ifnet *parent = ic->ic_ifp;
+ int error;
+
/*
* Assert the IC TX lock is held - this enforces the
* processing -> queuing order is maintained
*/
IEEE80211_TX_LOCK_ASSERT(ic);
-
- return (parent->if_transmit(parent, m));
+ error = ic->ic_transmit(ic, m);
+ if (error)
+ m_freem(m);
+ return (error);
}
/*
@@ -836,7 +807,6 @@ ieee80211_load_module(const char *modname)
}
static eventhandler_tag wlan_bpfevent;
-static eventhandler_tag wlan_ifllevent;
static void
bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
@@ -864,33 +834,6 @@ bpf_track(void *arg, struct ifnet *ifp, int dlt, int attach)
}
}
-static void
-wlan_iflladdr(void *arg __unused, struct ifnet *ifp)
-{
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap, *next;
-
- if (ifp->if_type != IFT_IEEE80211 || ic == NULL)
- return;
-
- IEEE80211_LOCK(ic);
- TAILQ_FOREACH_SAFE(vap, &ic->ic_vaps, iv_next, next) {
- /*
- * If the MAC address has changed on the parent and it was
- * copied to the vap on creation then re-sync.
- */
- if (vap->iv_ic == ic &&
- (vap->iv_flags_ext & IEEE80211_FEXT_UNIQMAC) == 0) {
- IEEE80211_ADDR_COPY(vap->iv_myaddr, IF_LLADDR(ifp));
- IEEE80211_UNLOCK(ic);
- if_setlladdr(vap->iv_ifp, IF_LLADDR(ifp),
- IEEE80211_ADDR_LEN);
- IEEE80211_LOCK(ic);
- }
- }
- IEEE80211_UNLOCK(ic);
-}
-
/*
* Module glue.
*
@@ -905,17 +848,12 @@ wlan_modevent(module_t mod, int type, void *unused)
printf("wlan: <802.11 Link Layer>\n");
wlan_bpfevent = EVENTHANDLER_REGISTER(bpf_track,
bpf_track, 0, EVENTHANDLER_PRI_ANY);
- wlan_ifllevent = EVENTHANDLER_REGISTER(iflladdr_event,
- wlan_iflladdr, NULL, EVENTHANDLER_PRI_ANY);
wlan_cloner = if_clone_simple(wlanname, wlan_clone_create,
wlan_clone_destroy, 0);
- if_register_com_alloc(IFT_IEEE80211, wlan_alloc, wlan_free);
return 0;
case MOD_UNLOAD:
- if_deregister_com_alloc(IFT_IEEE80211);
if_clone_detach(wlan_cloner);
EVENTHANDLER_DEREGISTER(bpf_track, wlan_bpfevent);
- EVENTHANDLER_DEREGISTER(iflladdr_event, wlan_ifllevent);
return 0;
}
return EINVAL;
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index 54ab390..1c7ddb9 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -1329,13 +1329,12 @@ static int
setmlme_dropsta(struct ieee80211vap *vap,
const uint8_t mac[IEEE80211_ADDR_LEN], struct mlmeop *mlmeop)
{
- struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_node_table *nt = &ic->ic_sta;
+ struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta;
struct ieee80211_node *ni;
int error = 0;
/* NB: the broadcast address means do 'em all */
- if (!IEEE80211_ADDR_EQ(mac, ic->ic_ifp->if_broadcastaddr)) {
+ if (!IEEE80211_ADDR_EQ(mac, vap->iv_ifp->if_broadcastaddr)) {
IEEE80211_NODE_LOCK(nt);
ni = ieee80211_find_node_locked(nt, mac);
IEEE80211_NODE_UNLOCK(nt);
@@ -2529,14 +2528,9 @@ ieee80211_scanreq(struct ieee80211vap *vap, struct ieee80211_scan_req *sr)
static __noinline int
ieee80211_ioctl_scanreq(struct ieee80211vap *vap, struct ieee80211req *ireq)
{
- struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_scan_req sr; /* XXX off stack? */
int error;
- /* NB: parent must be running */
- if ((ic->ic_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- return ENXIO;
-
if (ireq->i_len != sizeof(sr))
return EINVAL;
error = copyin(ireq->i_data, &sr, sizeof(sr));
@@ -3300,41 +3294,6 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
return error;
}
-/*
- * Rebuild the parent's multicast address list after an add/del
- * of a multicast address for a vap. We have no way to tell
- * what happened above to optimize the work so we purge the entire
- * list and rebuild from scratch. This is way expensive.
- * Note also the half-baked workaround for if_addmulti calling
- * back to the parent device; there's no way to insert mcast
- * entries quietly and/or cheaply.
- */
-static void
-ieee80211_ioctl_updatemulti(struct ieee80211com *ic)
-{
- struct ifnet *parent = ic->ic_ifp;
- struct ieee80211vap *vap;
- void *ioctl;
-
- IEEE80211_LOCK(ic);
- if_delallmulti(parent);
- ioctl = parent->if_ioctl; /* XXX WAR if_allmulti */
- parent->if_ioctl = NULL;
- TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
- struct ifnet *ifp = vap->iv_ifp;
- struct ifmultiaddr *ifma;
-
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- (void) if_addmulti(parent, ifma->ifma_addr, NULL);
- }
- }
- parent->if_ioctl = ioctl;
- ieee80211_runtask(ic, &ic->ic_mcast_task);
- IEEE80211_UNLOCK(ic);
-}
-
int
ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
@@ -3347,8 +3306,11 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
switch (cmd) {
case SIOCSIFFLAGS:
IEEE80211_LOCK(ic);
- ieee80211_syncifflag_locked(ic, IFF_PROMISC);
- ieee80211_syncifflag_locked(ic, IFF_ALLMULTI);
+ if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_PROMISC)
+ ieee80211_promisc(vap, ifp->if_flags & IFF_PROMISC);
+ if ((ifp->if_flags ^ vap->iv_ifflags) & IFF_ALLMULTI)
+ ieee80211_allmulti(vap, ifp->if_flags & IFF_ALLMULTI);
+ vap->iv_ifflags = ifp->if_flags;
if (ifp->if_flags & IFF_UP) {
/*
* Bring ourself up unless we're already operational.
@@ -3371,7 +3333,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
- ieee80211_ioctl_updatemulti(ic);
+ ieee80211_runtask(ic, &ic->ic_mcast_task);
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
@@ -3427,17 +3389,16 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
break;
}
break;
- /* Pass NDIS ioctls up to the driver */
- case SIOCGDRVSPEC:
- case SIOCSDRVSPEC:
- case SIOCGPRIVATE_0: {
- struct ifnet *parent = vap->iv_ic->ic_ifp;
- error = parent->if_ioctl(parent, cmd, data);
- break;
- }
default:
+ /*
+ * Pass unknown ioctls first to the driver, and if it
+ * returns ENOTTY, then to the generic Ethernet handler.
+ */
+ if (ic->ic_ioctl != NULL &&
+ (error = ic->ic_ioctl(ic, cmd, data)) != ENOTTY)
+ break;
error = ether_ioctl(ifp, cmd, data);
break;
}
- return error;
+ return (error);
}
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index d11628d..eb333da1 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -254,10 +254,6 @@ ieee80211_vap_pkt_send_dest(struct ieee80211vap *vap, struct mbuf *m,
/* NB: IFQ_HANDOFF reclaims mbuf */
ieee80211_free_node(ni);
if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- } else {
- if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
- if_inc_counter(ifp, IFCOUNTER_OMCASTS, mcast);
- if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
}
ic->ic_lastdata = ticks;
@@ -430,17 +426,6 @@ ieee80211_vap_transmit(struct ifnet *ifp, struct mbuf *m)
{
struct ieee80211vap *vap = ifp->if_softc;
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *parent = ic->ic_ifp;
-
- /* NB: parent must be up and running */
- if (!IFNET_IS_UP_RUNNING(parent)) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
- "%s: ignore queue, parent %s not up+running\n",
- __func__, parent->if_xname);
- m_freem(m);
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
- return (ENETDOWN);
- }
/*
* No data frames go out unless we're running.
@@ -507,6 +492,7 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni,
struct mbuf *m, const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = vap->iv_ic;
+ int error;
/*
* Set node - the caller has taken a reference, so ensure
@@ -528,7 +514,10 @@ ieee80211_raw_output(struct ieee80211vap *vap, struct ieee80211_node *ni,
if (params)
(void) ieee80211_add_xmit_params(m, params);
- return (ic->ic_raw_xmit(ni, m, params));
+ error = ic->ic_raw_xmit(ni, m, params);
+ if (error)
+ if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, 1);
+ return (error);
}
/*
@@ -3457,6 +3446,15 @@ ieee80211_tx_complete(struct ieee80211_node *ni, struct mbuf *m, int status)
{
if (ni != NULL) {
+ struct ifnet *ifp = ni->ni_vap->iv_ifp;
+
+ if (status == 0) {
+ if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
+ if (m->m_flags & M_MCAST)
+ if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
+ } else
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
if (m->m_flags & M_TXCB)
ieee80211_process_callback(ni, m, status);
ieee80211_free_node(ni);
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index 91668cc..2d216c2 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -418,7 +418,6 @@ pwrsave_flushq(struct ieee80211_node *ni)
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_psq_head *qhead;
- struct ifnet *parent, *ifp;
struct mbuf *parent_q = NULL, *ifp_q = NULL;
struct mbuf *m;
@@ -429,59 +428,51 @@ pwrsave_flushq(struct ieee80211_node *ni)
qhead = &psq->psq_head[0]; /* 802.11 frames */
if (qhead->head != NULL) {
/* XXX could dispatch through vap and check M_ENCAP */
- parent = vap->iv_ic->ic_ifp;
/* XXX need different driver interface */
/* XXX bypasses q max and OACTIVE */
parent_q = qhead->head;
qhead->head = qhead->tail = NULL;
qhead->len = 0;
- } else
- parent = NULL;
+ }
qhead = &psq->psq_head[1]; /* 802.3 frames */
if (qhead->head != NULL) {
- ifp = vap->iv_ifp;
/* XXX need different driver interface */
/* XXX bypasses q max and OACTIVE */
ifp_q = qhead->head;
qhead->head = qhead->tail = NULL;
qhead->len = 0;
- } else
- ifp = NULL;
+ }
psq->psq_len = 0;
IEEE80211_PSQ_UNLOCK(psq);
/* NB: do this outside the psq lock */
/* XXX packets might get reordered if parent is OACTIVE */
/* parent frames, should be encapsulated */
- if (parent != NULL) {
- while (parent_q != NULL) {
- m = parent_q;
- parent_q = m->m_nextpkt;
- m->m_nextpkt = NULL;
- /* must be encapsulated */
- KASSERT((m->m_flags & M_ENCAP),
- ("%s: parentq with non-M_ENCAP frame!\n",
- __func__));
- /*
- * For encaped frames, we need to free the node
- * reference upon failure.
- */
- if (ieee80211_parent_xmitpkt(ic, m) != 0)
- ieee80211_free_node(ni);
- }
+ while (parent_q != NULL) {
+ m = parent_q;
+ parent_q = m->m_nextpkt;
+ m->m_nextpkt = NULL;
+ /* must be encapsulated */
+ KASSERT((m->m_flags & M_ENCAP),
+ ("%s: parentq with non-M_ENCAP frame!\n",
+ __func__));
+ /*
+ * For encaped frames, we need to free the node
+ * reference upon failure.
+ */
+ if (ieee80211_parent_xmitpkt(ic, m) != 0)
+ ieee80211_free_node(ni);
}
/* VAP frames, aren't encapsulated */
- if (ifp != NULL) {
- while (ifp_q != NULL) {
- m = ifp_q;
- ifp_q = m->m_nextpkt;
- m->m_nextpkt = NULL;
- KASSERT((!(m->m_flags & M_ENCAP)),
- ("%s: vapq with M_ENCAP frame!\n", __func__));
- (void) ieee80211_vap_xmitpkt(vap, m);
- }
+ while (ifp_q != NULL) {
+ m = ifp_q;
+ ifp_q = m->m_nextpkt;
+ m->m_nextpkt = NULL;
+ KASSERT((!(m->m_flags & M_ENCAP)),
+ ("%s: vapq with M_ENCAP frame!\n", __func__));
+ (void) ieee80211_vap_xmitpkt(vap, m);
}
}
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index 01c60e1..7adf044 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -122,23 +122,23 @@ null_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
void
ieee80211_proto_attach(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
+ uint8_t hdrlen;
/* override the 802.3 setting */
- ifp->if_hdrlen = ic->ic_headroom
+ hdrlen = ic->ic_headroom
+ sizeof(struct ieee80211_qosframe_addr4)
+ IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN
+ IEEE80211_WEP_EXTIVLEN;
/* XXX no way to recalculate on ifdetach */
- if (ALIGN(ifp->if_hdrlen) > max_linkhdr) {
+ if (ALIGN(hdrlen) > max_linkhdr) {
/* XXX sanity check... */
- max_linkhdr = ALIGN(ifp->if_hdrlen);
+ max_linkhdr = ALIGN(hdrlen);
max_hdr = max_linkhdr + max_protohdr;
max_datalen = MHLEN - max_hdr;
}
ic->ic_protmode = IEEE80211_PROT_CTSONLY;
- TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ifp);
+ TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ic);
TASK_INIT(&ic->ic_mcast_task, 0, update_mcast, ic);
TASK_INIT(&ic->ic_promisc_task, 0, update_promisc, ic);
TASK_INIT(&ic->ic_chan_task, 0, update_channel, ic);
@@ -188,7 +188,10 @@ ieee80211_proto_vattach(struct ieee80211vap *vap)
int i;
/* override the 802.3 setting */
- ifp->if_hdrlen = ic->ic_ifp->if_hdrlen;
+ ifp->if_hdrlen = ic->ic_headroom
+ + sizeof(struct ieee80211_qosframe_addr4)
+ + IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN
+ + IEEE80211_WEP_EXTIVLEN;
vap->iv_rtsthreshold = IEEE80211_RTS_DEFAULT;
vap->iv_fragthreshold = IEEE80211_FRAG_DEFAULT;
@@ -1155,9 +1158,9 @@ ieee80211_wme_updateparams(struct ieee80211vap *vap)
static void
parent_updown(void *arg, int npending)
{
- struct ifnet *parent = arg;
+ struct ieee80211com *ic = arg;
- parent->if_ioctl(parent, SIOCSIFFLAGS, NULL);
+ ic->ic_parent(ic);
}
static void
@@ -1224,7 +1227,6 @@ ieee80211_start_locked(struct ieee80211vap *vap)
{
struct ifnet *ifp = vap->iv_ifp;
struct ieee80211com *ic = vap->iv_ic;
- struct ifnet *parent = ic->ic_ifp;
IEEE80211_LOCK_ASSERT(ic);
@@ -1246,12 +1248,10 @@ ieee80211_start_locked(struct ieee80211vap *vap)
* We are not running; if this we are the first vap
* to be brought up auto-up the parent if necessary.
*/
- if (ic->ic_nrunning++ == 0 &&
- (parent->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ if (ic->ic_nrunning++ == 0) {
IEEE80211_DPRINTF(vap,
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
- "%s: up parent %s\n", __func__, parent->if_xname);
- parent->if_flags |= IFF_UP;
+ "%s: up parent %s\n", __func__, ic->ic_name);
ieee80211_runtask(ic, &ic->ic_parent_task);
return;
}
@@ -1260,8 +1260,7 @@ ieee80211_start_locked(struct ieee80211vap *vap)
* If the parent is up and running, then kick the
* 802.11 state machine as appropriate.
*/
- if ((parent->if_drv_flags & IFF_DRV_RUNNING) &&
- vap->iv_roaming != IEEE80211_ROAMING_MANUAL) {
+ if (vap->iv_roaming != IEEE80211_ROAMING_MANUAL) {
if (vap->iv_opmode == IEEE80211_M_STA) {
#if 0
/* XXX bypasses scan too easily; disable for now */
@@ -1344,7 +1343,6 @@ ieee80211_stop_locked(struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = vap->iv_ifp;
- struct ifnet *parent = ic->ic_ifp;
IEEE80211_LOCK_ASSERT(ic);
@@ -1354,12 +1352,10 @@ ieee80211_stop_locked(struct ieee80211vap *vap)
ieee80211_new_state_locked(vap, IEEE80211_S_INIT, -1);
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
ifp->if_drv_flags &= ~IFF_DRV_RUNNING; /* mark us stopped */
- if (--ic->ic_nrunning == 0 &&
- (parent->if_drv_flags & IFF_DRV_RUNNING)) {
+ if (--ic->ic_nrunning == 0) {
IEEE80211_DPRINTF(vap,
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
- "down parent %s\n", parent->if_xname);
- parent->if_flags &= ~IFF_UP;
+ "down parent %s\n", ic->ic_name);
ieee80211_runtask(ic, &ic->ic_parent_task);
}
}
diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
index a812393..b5918b4 100644
--- a/sys/net80211/ieee80211_proto.h
+++ b/sys/net80211/ieee80211_proto.h
@@ -56,7 +56,8 @@ void ieee80211_proto_detach(struct ieee80211com *);
void ieee80211_proto_vattach(struct ieee80211vap *);
void ieee80211_proto_vdetach(struct ieee80211vap *);
-void ieee80211_syncifflag_locked(struct ieee80211com *, int flag);
+void ieee80211_promisc(struct ieee80211vap *, bool);
+void ieee80211_allmulti(struct ieee80211vap *, bool);
void ieee80211_syncflag(struct ieee80211vap *, int flag);
void ieee80211_syncflag_ht(struct ieee80211vap *, int flag);
void ieee80211_syncflag_ext(struct ieee80211vap *, int flag);
diff --git a/sys/net80211/ieee80211_regdomain.c b/sys/net80211/ieee80211_regdomain.c
index 9dfef2c..efbe1a8 100644
--- a/sys/net80211/ieee80211_regdomain.c
+++ b/sys/net80211/ieee80211_regdomain.c
@@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
-
#include <sys/socket.h>
#include <net/if.h>
@@ -487,7 +486,7 @@ ieee80211_setregdomain(struct ieee80211vap *vap,
memset(&ic->ic_channels[ic->ic_nchans], 0,
(IEEE80211_CHAN_MAX - ic->ic_nchans) *
sizeof(struct ieee80211_channel));
- ieee80211_media_init(ic);
+ ieee80211_chan_init(ic);
/*
* Invalidate channel-related state.
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index c0cbb7d..709710c 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -1706,26 +1706,6 @@ static const struct ieee80211_scanner adhoc_default = {
IEEE80211_SCANNER_ALG(ibss, IEEE80211_M_IBSS, adhoc_default);
IEEE80211_SCANNER_ALG(ahdemo, IEEE80211_M_AHDEMO, adhoc_default);
-static void
-ap_force_promisc(struct ieee80211com *ic)
-{
- struct ifnet *ifp = ic->ic_ifp;
-
- IEEE80211_LOCK(ic);
- /* set interface into promiscuous mode */
- ifp->if_flags |= IFF_PROMISC;
- ieee80211_runtask(ic, &ic->ic_promisc_task);
- IEEE80211_UNLOCK(ic);
-}
-
-static void
-ap_reset_promisc(struct ieee80211com *ic)
-{
- IEEE80211_LOCK(ic);
- ieee80211_syncifflag_locked(ic, IFF_PROMISC);
- IEEE80211_UNLOCK(ic);
-}
-
static int
ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
{
@@ -1741,7 +1721,7 @@ ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
st->st_scangen++;
st->st_newscan = 1;
- ap_force_promisc(vap->iv_ic);
+ ieee80211_promisc(vap, true);
return 0;
}
@@ -1751,7 +1731,7 @@ ap_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
static int
ap_cancel(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
{
- ap_reset_promisc(vap->iv_ic);
+ ieee80211_promisc(vap, false);
return 0;
}
@@ -1825,7 +1805,7 @@ ap_end(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
return 0;
}
}
- ap_reset_promisc(ic);
+ ieee80211_promisc(vap, false);
if (ss->ss_flags & (IEEE80211_SCAN_NOPICK | IEEE80211_SCAN_NOJOIN)) {
/*
* Manual/background scan, don't select+join the
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index 26238b8..a450701 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -116,16 +116,15 @@ struct ieee80211_superg;
struct ieee80211_frame;
struct ieee80211com {
- struct ifnet *ic_ifp; /* associated device */
void *ic_softc; /* driver softc */
const char *ic_name; /* usually device name */
ieee80211_com_lock_t ic_comlock; /* state update lock */
ieee80211_tx_lock_t ic_txlock; /* ic/vap TX lock */
+ LIST_ENTRY(ieee80211com) ic_next; /* on global list */
TAILQ_HEAD(, ieee80211vap) ic_vaps; /* list of vap instances */
int ic_headroom; /* driver tx headroom needs */
enum ieee80211_phytype ic_phytype; /* XXX wrong for multi-mode */
enum ieee80211_opmode ic_opmode; /* operation mode */
- struct ifmedia ic_media; /* interface media config */
struct callout ic_inact; /* inactivity processing */
struct taskqueue *ic_tq; /* deferred state thread */
struct task ic_parent_task; /* deferred parent processing */
@@ -151,6 +150,7 @@ struct ieee80211com {
uint8_t ic_allmulti; /* vap's needing all multicast*/
uint8_t ic_nrunning; /* vap's marked running */
uint8_t ic_curmode; /* current mode */
+ uint8_t ic_macaddr[IEEE80211_ADDR_LEN];
uint16_t ic_bintval; /* beacon interval */
uint16_t ic_lintval; /* listen interval */
uint16_t ic_holdover; /* PM hold over duration */
@@ -241,6 +241,11 @@ struct ieee80211com {
const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
void (*ic_vap_delete)(struct ieee80211vap *);
+ /* device specific ioctls */
+ int (*ic_ioctl)(struct ieee80211com *,
+ u_long, void *);
+ /* start/stop device */
+ void (*ic_parent)(struct ieee80211com *);
/* operating mode attachment */
ieee80211vap_attach ic_vattach[IEEE80211_OPMODE_MAX];
/* return hardware/radio capabilities */
@@ -254,6 +259,9 @@ struct ieee80211com {
int (*ic_set_quiet)(struct ieee80211_node *,
u_int8_t *quiet_elm);
+ /* regular transmit */
+ int (*ic_transmit)(struct ieee80211com *,
+ struct mbuf *);
/* send/recv 802.11 management frame */
int (*ic_send_mgmt)(struct ieee80211_node *,
int, int);
@@ -351,14 +359,15 @@ struct ieee80211vap {
TAILQ_ENTRY(ieee80211vap) iv_next; /* list of vap instances */
struct ieee80211com *iv_ic; /* back ptr to common state */
+ const uint8_t *iv_myaddr; /* MAC address: ifp or ic */
uint32_t iv_debug; /* debug msg flags */
struct ieee80211_stats iv_stats; /* statistics */
- uint8_t iv_myaddr[IEEE80211_ADDR_LEN];
uint32_t iv_flags; /* state flags */
uint32_t iv_flags_ext; /* extended state flags */
uint32_t iv_flags_ht; /* HT state flags */
uint32_t iv_flags_ven; /* vendor state flags */
+ uint32_t iv_ifflags; /* ifnet flags */
uint32_t iv_caps; /* capabilities */
uint32_t iv_htcaps; /* HT capabilities */
uint32_t iv_htextcaps; /* HT extended capabilities */
@@ -681,24 +690,24 @@ MALLOC_DECLARE(M_80211_VAP);
"\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS"
int ic_printf(struct ieee80211com *, const char *, ...) __printflike(2, 3);
-void ieee80211_ifattach(struct ieee80211com *,
- const uint8_t macaddr[IEEE80211_ADDR_LEN]);
+void ieee80211_ifattach(struct ieee80211com *);
void ieee80211_ifdetach(struct ieee80211com *);
int ieee80211_vap_setup(struct ieee80211com *, struct ieee80211vap *,
const char name[IFNAMSIZ], int unit,
enum ieee80211_opmode opmode, int flags,
- const uint8_t bssid[IEEE80211_ADDR_LEN],
- const uint8_t macaddr[IEEE80211_ADDR_LEN]);
+ const uint8_t bssid[IEEE80211_ADDR_LEN]);
int ieee80211_vap_attach(struct ieee80211vap *,
- ifm_change_cb_t, ifm_stat_cb_t);
+ ifm_change_cb_t, ifm_stat_cb_t,
+ const uint8_t macaddr[IEEE80211_ADDR_LEN]);
void ieee80211_vap_detach(struct ieee80211vap *);
const struct ieee80211_rateset *ieee80211_get_suprates(struct ieee80211com *ic,
const struct ieee80211_channel *);
void ieee80211_announce(struct ieee80211com *);
void ieee80211_announce_channels(struct ieee80211com *);
void ieee80211_drain(struct ieee80211com *);
-void ieee80211_media_init(struct ieee80211com *);
+void ieee80211_chan_init(struct ieee80211com *);
struct ieee80211com *ieee80211_find_vap(const uint8_t mac[IEEE80211_ADDR_LEN]);
+struct ieee80211com *ieee80211_find_com(const char *name);
int ieee80211_media_change(struct ifnet *);
void ieee80211_media_status(struct ifnet *, struct ifmediareq *);
int ieee80211_ioctl(struct ifnet *, u_long, caddr_t);
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index aa370d6..1012e93 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -42,12 +42,14 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/malloc.h>
#include <sys/proc.h>
+#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/syslog.h>
@@ -563,6 +565,7 @@ SYSCTL_INT(_net_link_ether_inet, OID_AUTO, max_log_per_second,
static void
in_arpinput(struct mbuf *m)
{
+ struct rm_priotracker in_ifa_tracker;
struct arphdr *ah;
struct ifnet *ifp = m->m_pkthdr.rcvif;
struct llentry *la = NULL;
@@ -621,7 +624,7 @@ in_arpinput(struct mbuf *m)
* of the receive interface. (This will change slightly
* when we have clusters of interfaces).
*/
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) {
if (((bridged && ia->ia_ifp->if_bridge == ifp->if_bridge) ||
ia->ia_ifp == ifp) &&
@@ -629,7 +632,7 @@ in_arpinput(struct mbuf *m)
(ia->ia_ifa.ifa_carp == NULL ||
(*carp_iamatch_p)(&ia->ia_ifa, &enaddr))) {
ifa_ref(&ia->ia_ifa);
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto match;
}
}
@@ -638,7 +641,7 @@ in_arpinput(struct mbuf *m)
ia->ia_ifp == ifp) &&
isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) {
ifa_ref(&ia->ia_ifa);
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto match;
}
@@ -657,13 +660,13 @@ in_arpinput(struct mbuf *m)
if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) {
ifa_ref(&ia->ia_ifa);
ifp = ia->ia_ifp;
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto match;
}
}
}
#undef BDG_MEMBER_MATCHES_ARP
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* No match, use the first inet address on the receive interface
@@ -684,13 +687,13 @@ in_arpinput(struct mbuf *m)
/*
* If bridging, fall back to using any inet address.
*/
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL) {
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto drop;
}
ifa_ref(&ia->ia_ifa);
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
match:
if (!enaddr)
enaddr = (u_int8_t *)IF_LLADDR(ifp);
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c
index a094a49..185f5c2 100644
--- a/sys/netinet/igmp.c
+++ b/sys/netinet/igmp.c
@@ -58,6 +58,8 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/protosw.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/rmlock.h>
#include <sys/sysctl.h>
#include <sys/ktr.h>
#include <sys/condvar.h>
@@ -1215,6 +1217,7 @@ static int
igmp_input_v1_report(struct ifnet *ifp, /*const*/ struct ip *ip,
/*const*/ struct igmp *igmp)
{
+ struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
struct in_multi *inm;
@@ -1237,7 +1240,7 @@ igmp_input_v1_report(struct ifnet *ifp, /*const*/ struct ip *ip,
* Replace 0.0.0.0 with the subnet address if told to do so.
*/
if (V_igmp_recvifkludge && in_nullhost(ip->ip_src)) {
- IFP_TO_IA(ifp, ia);
+ IFP_TO_IA(ifp, ia, &in_ifa_tracker);
if (ia != NULL) {
ip->ip_src.s_addr = htonl(ia->ia_subnet);
ifa_free(&ia->ia_ifa);
@@ -1323,6 +1326,7 @@ static int
igmp_input_v2_report(struct ifnet *ifp, /*const*/ struct ip *ip,
/*const*/ struct igmp *igmp)
{
+ struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
struct in_multi *inm;
@@ -1331,7 +1335,7 @@ igmp_input_v2_report(struct ifnet *ifp, /*const*/ struct ip *ip,
* leave requires knowing that we are the only member of a
* group.
*/
- IFP_TO_IA(ifp, ia);
+ IFP_TO_IA(ifp, ia, &in_ifa_tracker);
if (ia != NULL && in_hosteq(ip->ip_src, IA_SIN(ia)->sin_addr)) {
ifa_free(&ia->ia_ifa);
return (0);
@@ -3487,6 +3491,7 @@ out:
static struct mbuf *
igmp_v3_encap_report(struct ifnet *ifp, struct mbuf *m)
{
+ struct rm_priotracker in_ifa_tracker;
struct igmp_report *igmp;
struct ip *ip;
int hdrlen, igmpreclen;
@@ -3535,7 +3540,7 @@ igmp_v3_encap_report(struct ifnet *ifp, struct mbuf *m)
if (m->m_flags & M_IGMP_LOOP) {
struct in_ifaddr *ia;
- IFP_TO_IA(ifp, ia);
+ IFP_TO_IA(ifp, ia, &in_ifa_tracker);
if (ia != NULL) {
ip->ip_src = ia->ia_addr.sin_addr;
ifa_free(&ia->ia_ifa);
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index f47492d..c2c7ce0 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -44,7 +44,9 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/jail.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/proc.h>
+#include <sys/rmlock.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/sx.h>
@@ -93,17 +95,18 @@ SX_SYSINIT(in_control_sx, &in_control_sx, "in_control");
int
in_localaddr(struct in_addr in)
{
+ struct rm_priotracker in_ifa_tracker;
register u_long i = ntohl(in.s_addr);
register struct in_ifaddr *ia;
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if ((i & ia->ia_subnetmask) == ia->ia_subnet) {
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (1);
}
}
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (0);
}
@@ -114,16 +117,17 @@ in_localaddr(struct in_addr in)
int
in_localip(struct in_addr in)
{
+ struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) {
if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr) {
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (1);
}
}
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (0);
}
@@ -158,18 +162,19 @@ in_ifhasaddr(struct ifnet *ifp, struct in_addr in)
static struct in_ifaddr *
in_localip_more(struct in_ifaddr *ia)
{
+ struct rm_priotracker in_ifa_tracker;
in_addr_t in = IA_SIN(ia)->sin_addr.s_addr;
struct in_ifaddr *it;
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
LIST_FOREACH(it, INADDR_HASH(in), ia_hash) {
if (it != ia && IA_SIN(it)->sin_addr.s_addr == in) {
ifa_ref(&it->ia_ifa);
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (it);
}
}
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (NULL);
}
@@ -646,6 +651,7 @@ in_difaddr_ioctl(caddr_t data, struct ifnet *ifp, struct thread *td)
int
in_addprefix(struct in_ifaddr *target, int flags)
{
+ struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
struct in_addr prefix, mask, p, m;
int error;
@@ -659,7 +665,7 @@ in_addprefix(struct in_ifaddr *target, int flags)
prefix.s_addr &= mask.s_addr;
}
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
/* Look for an existing address with the same prefix, mask, and fib */
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (rtinitflags(ia)) {
@@ -687,13 +693,13 @@ in_addprefix(struct in_ifaddr *target, int flags)
#ifdef RADIX_MPATH
if (ia->ia_addr.sin_addr.s_addr ==
target->ia_addr.sin_addr.s_addr) {
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (EEXIST);
} else
break;
#endif
if (V_nosameprefix) {
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (EEXIST);
} else {
int fibnum;
@@ -701,12 +707,12 @@ in_addprefix(struct in_ifaddr *target, int flags)
fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS :
target->ia_ifp->if_fib;
rt_addrmsg(RTM_ADD, &target->ia_ifa, fibnum);
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return (0);
}
}
}
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* No-one seem to have this prefix route, so we try to insert it.
@@ -725,6 +731,7 @@ in_addprefix(struct in_ifaddr *target, int flags)
int
in_scrubprefix(struct in_ifaddr *target, u_int flags)
{
+ struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
struct in_addr prefix, mask, p, m;
int error = 0;
@@ -775,7 +782,7 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
return (0);
}
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (rtinitflags(ia)) {
p = ia->ia_dstaddr.sin_addr;
@@ -802,7 +809,7 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
*/
if ((ia->ia_flags & IFA_ROUTE) == 0) {
ifa_ref(&ia->ia_ifa);
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
error = rtinit(&(target->ia_ifa), (int)RTM_DELETE,
rtinitflags(target));
if (error == 0)
@@ -821,7 +828,7 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
return (error);
}
}
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* remove all L2 entries on the given prefix
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
index e634987..0afdea2 100644
--- a/sys/netinet/in_gif.c
+++ b/sys/netinet/in_gif.c
@@ -67,8 +67,6 @@ __FBSDID("$FreeBSD$");
#include <net/if_gif.h>
-static int gif_validate4(const struct ip *, struct gif_softc *,
- struct ifnet *);
static int in_gif_input(struct mbuf **, int *, int);
extern struct domain inetdomain;
@@ -163,16 +161,22 @@ in_gif_input(struct mbuf **mp, int *offp, int proto)
}
/*
- * validate outer address.
+ * we know that we are in IFF_UP, outer address available, and outer family
+ * matched the physical addr family. see gif_encapcheck().
*/
-static int
-gif_validate4(const struct ip *ip, struct gif_softc *sc, struct ifnet *ifp)
+int
+in_gif_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
{
+ const struct ip *ip;
+ struct gif_softc *sc;
int ret;
+ /* sanity check done in caller */
+ sc = (struct gif_softc *)arg;
GIF_RLOCK_ASSERT(sc);
/* check for address match */
+ ip = mtod(m, const struct ip *);
if (sc->gif_iphdr->ip_src.s_addr != ip->ip_dst.s_addr)
return (0);
ret = 32;
@@ -182,18 +186,8 @@ gif_validate4(const struct ip *ip, struct gif_softc *sc, struct ifnet *ifp)
} else
ret += 32;
- /* martian filters on outer source - NOT done in ip_input! */
- if (IN_MULTICAST(ntohl(ip->ip_src.s_addr)))
- return (0);
- switch ((ntohl(ip->ip_src.s_addr) & 0xff000000) >> 24) {
- case 0:
- case 127:
- case 255:
- return (0);
- }
-
/* ingress filters on outer source */
- if ((GIF2IFP(sc)->if_flags & IFF_LINK2) == 0 && ifp) {
+ if ((GIF2IFP(sc)->if_flags & IFF_LINK2) == 0) {
struct sockaddr_in sin;
struct rtentry *rt;
@@ -204,8 +198,8 @@ gif_validate4(const struct ip *ip, struct gif_softc *sc, struct ifnet *ifp)
/* XXX MRT check for the interface we would use on output */
rt = in_rtalloc1((struct sockaddr *)&sin, 0,
0UL, sc->gif_fibnum);
- if (!rt || rt->rt_ifp != ifp) {
- if (rt)
+ if (rt == NULL || rt->rt_ifp != m->m_pkthdr.rcvif) {
+ if (rt != NULL)
RTFREE_LOCKED(rt);
return (0);
}
@@ -214,26 +208,6 @@ gif_validate4(const struct ip *ip, struct gif_softc *sc, struct ifnet *ifp)
return (ret);
}
-/*
- * we know that we are in IFF_UP, outer address available, and outer family
- * matched the physical addr family. see gif_encapcheck().
- */
-int
-in_gif_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
-{
- struct ip ip;
- struct gif_softc *sc;
- struct ifnet *ifp;
-
- /* sanity check done in caller */
- sc = (struct gif_softc *)arg;
- GIF_RLOCK_ASSERT(sc);
-
- m_copydata(m, 0, sizeof(ip), (caddr_t)&ip);
- ifp = ((m->m_flags & M_PKTHDR) != 0) ? m->m_pkthdr.rcvif : NULL;
- return (gif_validate4(&ip, sc, ifp));
-}
-
int
in_gif_attach(struct gif_softc *sc)
{
diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c
index 93557f8..c168780 100644
--- a/sys/netinet/in_mcast.c
+++ b/sys/netinet/in_mcast.c
@@ -38,9 +38,11 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
+#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
@@ -1748,6 +1750,7 @@ inp_get_source_filters(struct inpcb *inp, struct sockopt *sopt)
int
inp_getmoptions(struct inpcb *inp, struct sockopt *sopt)
{
+ struct rm_priotracker in_ifa_tracker;
struct ip_mreqn mreqn;
struct ip_moptions *imo;
struct ifnet *ifp;
@@ -1787,7 +1790,7 @@ inp_getmoptions(struct inpcb *inp, struct sockopt *sopt)
mreqn.imr_address = imo->imo_multicast_addr;
} else if (ifp != NULL) {
mreqn.imr_ifindex = ifp->if_index;
- IFP_TO_IA(ifp, ia);
+ IFP_TO_IA(ifp, ia, &in_ifa_tracker);
if (ia != NULL) {
mreqn.imr_address =
IA_SIN(ia)->sin_addr;
@@ -1878,6 +1881,7 @@ static struct ifnet *
inp_lookup_mcast_ifp(const struct inpcb *inp,
const struct sockaddr_in *gsin, const struct in_addr ina)
{
+ struct rm_priotracker in_ifa_tracker;
struct ifnet *ifp;
KASSERT(gsin->sin_family == AF_INET, ("%s: not AF_INET", __func__));
@@ -1902,7 +1906,7 @@ inp_lookup_mcast_ifp(const struct inpcb *inp,
struct ifnet *mifp;
mifp = NULL;
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
mifp = ia->ia_ifp;
if (!(mifp->if_flags & IFF_LOOPBACK) &&
@@ -1911,7 +1915,7 @@ inp_lookup_mcast_ifp(const struct inpcb *inp,
break;
}
}
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
}
}
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index bc48e10..c721c6d 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -47,11 +47,13 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/callout.h>
#include <sys/domain.h>
#include <sys/protosw.h>
+#include <sys/rmlock.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/priv.h>
@@ -222,6 +224,7 @@ in_pcbinfo_init(struct inpcbinfo *pcbinfo, const char *name,
INP_INFO_LOCK_INIT(pcbinfo, name);
INP_HASH_LOCK_INIT(pcbinfo, "pcbinfohash"); /* XXXRW: argument? */
+ INP_LIST_LOCK_INIT(pcbinfo, "pcbinfolist");
#ifdef VIMAGE
pcbinfo->ipi_vnet = curvnet;
#endif
@@ -260,6 +263,7 @@ in_pcbinfo_destroy(struct inpcbinfo *pcbinfo)
in_pcbgroup_destroy(pcbinfo);
#endif
uma_zdestroy(pcbinfo->ipi_zone);
+ INP_LIST_LOCK_DESTROY(pcbinfo);
INP_HASH_LOCK_DESTROY(pcbinfo);
INP_INFO_LOCK_DESTROY(pcbinfo);
}
@@ -274,7 +278,14 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
struct inpcb *inp;
int error;
- INP_INFO_WLOCK_ASSERT(pcbinfo);
+#ifdef INVARIANTS
+ if (pcbinfo == &V_tcbinfo) {
+ INP_INFO_RLOCK_ASSERT(pcbinfo);
+ } else {
+ INP_INFO_WLOCK_ASSERT(pcbinfo);
+ }
+#endif
+
error = 0;
inp = uma_zalloc(pcbinfo->ipi_zone, M_NOWAIT);
if (inp == NULL)
@@ -306,6 +317,8 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
inp->inp_flags |= IN6P_IPV6_V6ONLY;
}
#endif
+ INP_WLOCK(inp);
+ INP_LIST_WLOCK(pcbinfo);
LIST_INSERT_HEAD(pcbinfo->ipi_listhead, inp, inp_list);
pcbinfo->ipi_count++;
so->so_pcb = (caddr_t)inp;
@@ -313,9 +326,9 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
if (V_ip6_auto_flowlabel)
inp->inp_flags |= IN6P_AUTOFLOWLABEL;
#endif
- INP_WLOCK(inp);
inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
refcount_init(&inp->inp_refcount, 1); /* Reference from inpcbinfo */
+ INP_LIST_WUNLOCK(pcbinfo);
#if defined(IPSEC) || defined(MAC)
out:
if (error != 0) {
@@ -992,6 +1005,7 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
in_addr_t *laddrp, u_short *lportp, in_addr_t *faddrp, u_short *fportp,
struct inpcb **oinpp, struct ucred *cred)
{
+ struct rm_priotracker in_ifa_tracker;
struct sockaddr_in *sin = (struct sockaddr_in *)nam;
struct in_ifaddr *ia;
struct inpcb *oinp;
@@ -1028,20 +1042,20 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
* choose the broadcast address for that interface.
*/
if (faddr.s_addr == INADDR_ANY) {
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
faddr =
IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr;
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
if (cred != NULL &&
(error = prison_get_ip4(cred, &faddr)) != 0)
return (error);
} else if (faddr.s_addr == (u_long)INADDR_BROADCAST) {
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
if (TAILQ_FIRST(&V_in_ifaddrhead)->ia_ifp->if_flags &
IFF_BROADCAST)
faddr = satosin(&TAILQ_FIRST(
&V_in_ifaddrhead)->ia_broadaddr)->sin_addr;
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
}
}
if (laddr.s_addr == INADDR_ANY) {
@@ -1059,7 +1073,7 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
imo = inp->inp_moptions;
if (imo->imo_multicast_ifp != NULL) {
ifp = imo->imo_multicast_ifp;
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if ((ia->ia_ifp == ifp) &&
(cred == NULL ||
@@ -1073,7 +1087,7 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
laddr = ia->ia_addr.sin_addr;
error = 0;
}
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
}
}
if (error)
@@ -1243,7 +1257,13 @@ in_pcbfree(struct inpcb *inp)
KASSERT(inp->inp_socket == NULL, ("%s: inp_socket != NULL", __func__));
- INP_INFO_WLOCK_ASSERT(pcbinfo);
+#ifdef INVARIANTS
+ if (pcbinfo == &V_tcbinfo) {
+ INP_INFO_RLOCK_ASSERT(pcbinfo);
+ } else {
+ INP_INFO_WLOCK_ASSERT(pcbinfo);
+ }
+#endif
INP_WLOCK_ASSERT(inp);
/* XXXRW: Do as much as possible here. */
@@ -1251,8 +1271,10 @@ in_pcbfree(struct inpcb *inp)
if (inp->inp_sp != NULL)
ipsec_delete_pcbpolicy(inp);
#endif
+ INP_LIST_WLOCK(pcbinfo);
inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
in_pcbremlists(inp);
+ INP_LIST_WUNLOCK(pcbinfo);
#ifdef INET6
if (inp->inp_vflag & INP_IPV6PROTO) {
ip6_freepcbopts(inp->in6p_outputopts);
@@ -1409,7 +1431,7 @@ in_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
struct ip_moptions *imo;
int i, gap;
- INP_INFO_RLOCK(pcbinfo);
+ INP_INFO_WLOCK(pcbinfo);
LIST_FOREACH(inp, pcbinfo->ipi_listhead, inp_list) {
INP_WLOCK(inp);
imo = inp->inp_moptions;
@@ -1439,7 +1461,7 @@ in_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
}
INP_WUNLOCK(inp);
}
- INP_INFO_RUNLOCK(pcbinfo);
+ INP_INFO_WUNLOCK(pcbinfo);
}
/*
@@ -2160,8 +2182,16 @@ in_pcbremlists(struct inpcb *inp)
{
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
- INP_INFO_WLOCK_ASSERT(pcbinfo);
+#ifdef INVARIANTS
+ if (pcbinfo == &V_tcbinfo) {
+ INP_INFO_RLOCK_ASSERT(pcbinfo);
+ } else {
+ INP_INFO_WLOCK_ASSERT(pcbinfo);
+ }
+#endif
+
INP_WLOCK_ASSERT(inp);
+ INP_LIST_WLOCK_ASSERT(pcbinfo);
inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
if (inp->inp_flags & INP_INHASHLIST) {
@@ -2306,13 +2336,13 @@ inp_apply_all(void (*func)(struct inpcb *, void *), void *arg)
{
struct inpcb *inp;
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_WLOCK(&V_tcbinfo);
LIST_FOREACH(inp, V_tcbinfo.ipi_listhead, inp_list) {
INP_WLOCK(inp);
func(inp, arg);
INP_WUNLOCK(inp);
}
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_WUNLOCK(&V_tcbinfo);
}
struct socket *
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index 606795a..2b79325 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -130,23 +130,35 @@ struct in_conninfo {
struct icmp6_filter;
/*-
- * struct inpcb captures the network layer state for TCP, UDP, and raw IPv4
- * and IPv6 sockets. In the case of TCP, further per-connection state is
+ * struct inpcb captures the network layer state for TCP, UDP, and raw IPv4 and
+ * IPv6 sockets. In the case of TCP and UDP, further per-connection state is
* hung off of inp_ppcb most of the time. Almost all fields of struct inpcb
* are static after creation or protected by a per-inpcb rwlock, inp_lock. A
- * few fields also require the global pcbinfo lock for the inpcb to be held,
- * when modified, such as the global connection lists and hashes, as well as
- * binding information (which affects which hash a connection is on). This
- * model means that connections can be looked up without holding the
- * per-connection lock, which is important for performance when attempting to
- * find the connection for a packet given its IP and port tuple. Writing to
- * these fields that write locks be held on both the inpcb and global locks.
+ * few fields are protected by multiple locks as indicated in the locking notes
+ * below. For these fields, all of the listed locks must be write-locked for
+ * any modifications. However, these fields can be safely read while any one of
+ * the listed locks are read-locked. This model can permit greater concurrency
+ * for read operations. For example, connections can be looked up while only
+ * holding a read lock on the global pcblist lock. This is important for
+ * performance when attempting to find the connection for a packet given its IP
+ * and port tuple.
+ *
+ * One noteworthy exception is that the global pcbinfo lock follows a different
+ * set of rules in relation to the inp_list field. Rather than being
+ * write-locked for modifications and read-locked for list iterations, it must
+ * be read-locked during modifications and write-locked during list iterations.
+ * This ensures that the relatively rare global list iterations safely walk a
+ * stable snapshot of connections while allowing more common list modifications
+ * to safely grab the pcblist lock just while adding or removing a connection
+ * from the global list.
*
* Key:
* (c) - Constant after initialization
* (g) - Protected by the pcbgroup lock
* (i) - Protected by the inpcb lock
* (p) - Protected by the pcbinfo lock for the inpcb
+ * (l) - Protected by the pcblist lock for the inpcb
+ * (h) - Protected by the pcbhash lock for the inpcb
* (s) - Protected by another subsystem's locks
* (x) - Undefined locking
*
@@ -161,15 +173,21 @@ struct icmp6_filter;
* socket has been freed), or there may be close(2)-related races.
*
* The inp_vflag field is overloaded, and would otherwise ideally be (c).
+ *
+ * TODO: Currently only the TCP stack is leveraging the global pcbinfo lock
+ * read-lock usage during modification, this model can be applied to other
+ * protocols (especially SCTP).
*/
struct inpcb {
- LIST_ENTRY(inpcb) inp_hash; /* (i/p) hash list */
+ LIST_ENTRY(inpcb) inp_hash; /* (h/i) hash list */
LIST_ENTRY(inpcb) inp_pcbgrouphash; /* (g/i) hash list */
- LIST_ENTRY(inpcb) inp_list; /* (i/p) list for all PCBs for proto */
+ LIST_ENTRY(inpcb) inp_list; /* (p/l) list for all PCBs for proto */
+ /* (p[w]) for list iteration */
+ /* (p[r]/l) for addition/removal */
void *inp_ppcb; /* (i) pointer to per-protocol pcb */
struct inpcbinfo *inp_pcbinfo; /* (c) PCB list info */
struct inpcbgroup *inp_pcbgroup; /* (g/i) PCB group list */
- LIST_ENTRY(inpcb) inp_pcbgroup_wild; /* (g/i/p) group wildcard entry */
+ LIST_ENTRY(inpcb) inp_pcbgroup_wild; /* (g/i/h) group wildcard entry */
struct socket *inp_socket; /* (i) back pointer to socket */
struct ucred *inp_cred; /* (c) cache of socket cred */
u_int32_t inp_flow; /* (i) IPv6 flow information */
@@ -188,7 +206,7 @@ struct inpcb {
* general use */
/* Local and foreign ports, local and foreign addr. */
- struct in_conninfo inp_inc; /* (i/p) list for PCB's local port */
+ struct in_conninfo inp_inc; /* (i) list for PCB's local port */
/* MAC and IPSEC policy information. */
struct label *inp_label; /* (i) MAC label */
@@ -213,8 +231,8 @@ struct inpcb {
int inp6_cksum;
short inp6_hops;
} inp_depend6;
- LIST_ENTRY(inpcb) inp_portlist; /* (i/p) */
- struct inpcbport *inp_phd; /* (i/p) head of this list */
+ LIST_ENTRY(inpcb) inp_portlist; /* (i/h) */
+ struct inpcbport *inp_phd; /* (i/h) head of this list */
#define inp_zero_size offsetof(struct inpcb, inp_gencnt)
inp_gen_t inp_gencnt; /* (c) generation count */
struct llentry *inp_lle; /* cached L2 information */
@@ -279,37 +297,46 @@ struct inpcbport {
* Global data structure for each high-level protocol (UDP, TCP, ...) in both
* IPv4 and IPv6. Holds inpcb lists and information for managing them.
*
- * Each pcbinfo is protected by two locks: ipi_lock and ipi_hash_lock,
- * the former covering mutable global fields (such as the global pcb list),
- * and the latter covering the hashed lookup tables. The lock order is:
+ * Each pcbinfo is protected by three locks: ipi_lock, ipi_hash_lock and
+ * ipi_list_lock:
+ * - ipi_lock covering the global pcb list stability during loop iteration,
+ * - ipi_hash_lock covering the hashed lookup tables,
+ * - ipi_list_lock covering mutable global fields (such as the global
+ * pcb list)
+ *
+ * The lock order is:
*
- * ipi_lock (before) inpcb locks (before) {ipi_hash_lock, pcbgroup locks}
+ * ipi_lock (before)
+ * inpcb locks (before)
+ * ipi_list locks (before)
+ * {ipi_hash_lock, pcbgroup locks}
*
* Locking key:
*
* (c) Constant or nearly constant after initialisation
* (g) Locked by ipi_lock
+ * (l) Locked by ipi_list_lock
* (h) Read using either ipi_hash_lock or inpcb lock; write requires both
* (p) Protected by one or more pcbgroup locks
* (x) Synchronisation properties poorly defined
*/
struct inpcbinfo {
/*
- * Global lock protecting global inpcb list, inpcb count, etc.
+ * Global lock protecting full inpcb list traversal
*/
struct rwlock ipi_lock;
/*
* Global list of inpcbs on the protocol.
*/
- struct inpcbhead *ipi_listhead; /* (g) */
- u_int ipi_count; /* (g) */
+ struct inpcbhead *ipi_listhead; /* (g/l) */
+ u_int ipi_count; /* (l) */
/*
* Generation count -- incremented each time a connection is allocated
* or freed.
*/
- u_quad_t ipi_gencnt; /* (g) */
+ u_quad_t ipi_gencnt; /* (l) */
/*
* Fields associated with port lookup and allocation.
@@ -367,6 +394,11 @@ struct inpcbinfo {
* general use 2
*/
void *ipi_pspare[2];
+
+ /*
+ * Global lock protecting global inpcb list, inpcb count, etc.
+ */
+ struct rwlock ipi_list_lock;
};
#ifdef _KERNEL
@@ -466,6 +498,25 @@ short inp_so_options(const struct inpcb *inp);
#define INP_INFO_WLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_WLOCKED)
#define INP_INFO_UNLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_UNLOCKED)
+#define INP_LIST_LOCK_INIT(ipi, d) \
+ rw_init_flags(&(ipi)->ipi_list_lock, (d), 0)
+#define INP_LIST_LOCK_DESTROY(ipi) rw_destroy(&(ipi)->ipi_list_lock)
+#define INP_LIST_RLOCK(ipi) rw_rlock(&(ipi)->ipi_list_lock)
+#define INP_LIST_WLOCK(ipi) rw_wlock(&(ipi)->ipi_list_lock)
+#define INP_LIST_TRY_RLOCK(ipi) rw_try_rlock(&(ipi)->ipi_list_lock)
+#define INP_LIST_TRY_WLOCK(ipi) rw_try_wlock(&(ipi)->ipi_list_lock)
+#define INP_LIST_TRY_UPGRADE(ipi) rw_try_upgrade(&(ipi)->ipi_list_lock)
+#define INP_LIST_RUNLOCK(ipi) rw_runlock(&(ipi)->ipi_list_lock)
+#define INP_LIST_WUNLOCK(ipi) rw_wunlock(&(ipi)->ipi_list_lock)
+#define INP_LIST_LOCK_ASSERT(ipi) \
+ rw_assert(&(ipi)->ipi_list_lock, RA_LOCKED)
+#define INP_LIST_RLOCK_ASSERT(ipi) \
+ rw_assert(&(ipi)->ipi_list_lock, RA_RLOCKED)
+#define INP_LIST_WLOCK_ASSERT(ipi) \
+ rw_assert(&(ipi)->ipi_list_lock, RA_WLOCKED)
+#define INP_LIST_UNLOCK_ASSERT(ipi) \
+ rw_assert(&(ipi)->ipi_list_lock, RA_UNLOCKED)
+
#define INP_HASH_LOCK_INIT(ipi, d) \
rw_init_flags(&(ipi)->ipi_hash_lock, (d), 0)
#define INP_HASH_LOCK_DESTROY(ipi) rw_destroy(&(ipi)->ipi_hash_lock)
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h
index 0318fb2..f9e9812 100644
--- a/sys/netinet/in_var.h
+++ b/sys/netinet/in_var.h
@@ -119,15 +119,15 @@ VNET_DECLARE(u_long, in_ifaddrhmask); /* mask for hash table */
#define INADDR_HASH(x) \
(&V_in_ifaddrhashtbl[INADDR_HASHVAL(x) & V_in_ifaddrhmask])
-extern struct rwlock in_ifaddr_lock;
+extern struct rmlock in_ifaddr_lock;
-#define IN_IFADDR_LOCK_ASSERT() rw_assert(&in_ifaddr_lock, RA_LOCKED)
-#define IN_IFADDR_RLOCK() rw_rlock(&in_ifaddr_lock)
-#define IN_IFADDR_RLOCK_ASSERT() rw_assert(&in_ifaddr_lock, RA_RLOCKED)
-#define IN_IFADDR_RUNLOCK() rw_runlock(&in_ifaddr_lock)
-#define IN_IFADDR_WLOCK() rw_wlock(&in_ifaddr_lock)
-#define IN_IFADDR_WLOCK_ASSERT() rw_assert(&in_ifaddr_lock, RA_WLOCKED)
-#define IN_IFADDR_WUNLOCK() rw_wunlock(&in_ifaddr_lock)
+#define IN_IFADDR_LOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_LOCKED)
+#define IN_IFADDR_RLOCK(t) rm_rlock(&in_ifaddr_lock, (t))
+#define IN_IFADDR_RLOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_RLOCKED)
+#define IN_IFADDR_RUNLOCK(t) rm_runlock(&in_ifaddr_lock, (t))
+#define IN_IFADDR_WLOCK() rm_wlock(&in_ifaddr_lock)
+#define IN_IFADDR_WLOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_WLOCKED)
+#define IN_IFADDR_WUNLOCK() rm_wunlock(&in_ifaddr_lock)
/*
* Macro for finding the internet address structure (in_ifaddr)
@@ -161,18 +161,19 @@ do { \
* Macro for finding the internet address structure (in_ifaddr) corresponding
* to a given interface (ifnet structure).
*/
-#define IFP_TO_IA(ifp, ia) \
+#define IFP_TO_IA(ifp, ia, t) \
/* struct ifnet *ifp; */ \
/* struct in_ifaddr *ia; */ \
+ /* struct rm_priotracker *t; */ \
do { \
- IN_IFADDR_RLOCK(); \
+ IN_IFADDR_RLOCK((t)); \
for ((ia) = TAILQ_FIRST(&V_in_ifaddrhead); \
(ia) != NULL && (ia)->ia_ifp != (ifp); \
(ia) = TAILQ_NEXT((ia), ia_link)) \
continue; \
if ((ia) != NULL) \
ifa_ref(&(ia)->ia_ifa); \
- IN_IFADDR_RUNLOCK(); \
+ IN_IFADDR_RUNLOCK((t)); \
} while (0)
/*
diff --git a/sys/netinet/ip_ecn.h b/sys/netinet/ip_ecn.h
index 0886cc8..c5c1c4e 100644
--- a/sys/netinet/ip_ecn.h
+++ b/sys/netinet/ip_ecn.h
@@ -38,10 +38,6 @@
#ifndef _NETINET_IP_ECN_H_
#define _NETINET_IP_ECN_H_
-#if defined(_KERNEL) && !defined(_LKM)
-#include "opt_inet.h"
-#endif
-
#define ECN_ALLOWED 1 /* ECN allowed */
#define ECN_FORBIDDEN 0 /* ECN forbidden */
#define ECN_NOCARE (-1) /* no consideration to ECN */
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index b6b967f..57553f5 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/rmlock.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
@@ -647,6 +649,7 @@ freeit:
static void
icmp_reflect(struct mbuf *m)
{
+ struct rm_priotracker in_ifa_tracker;
struct ip *ip = mtod(m, struct ip *);
struct ifaddr *ifa;
struct ifnet *ifp;
@@ -672,15 +675,15 @@ icmp_reflect(struct mbuf *m)
* If the incoming packet was addressed directly to one of our
* own addresses, use dst as the src for the reply.
*/
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
LIST_FOREACH(ia, INADDR_HASH(t.s_addr), ia_hash) {
if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr) {
t = IA_SIN(ia)->sin_addr;
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
goto match;
}
}
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* If the incoming packet was addressed to one of our broadcast
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 4140eda..e1cbb43 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/rmlock.h>
#include <sys/rwlock.h>
#include <sys/sdt.h>
#include <sys/syslog.h>
@@ -97,8 +98,8 @@ extern void ipreass_slowtimo(void);
extern void ipreass_destroy(void);
#endif
-struct rwlock in_ifaddr_lock;
-RW_SYSINIT(in_ifaddr_lock, &in_ifaddr_lock, "in_ifaddr_lock");
+struct rmlock in_ifaddr_lock;
+RM_SYSINIT(in_ifaddr_lock, &in_ifaddr_lock, "in_ifaddr_lock");
VNET_DEFINE(int, rsvp_on);
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 588bc05..086a8c9 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -44,11 +44,13 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/protosw.h>
+#include <sys/rmlock.h>
#include <sys/sdt.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
@@ -104,6 +106,97 @@ static void ip_mloopback
extern int in_mcast_loop;
extern struct protosw inetsw[];
+static inline int
+ip_output_pfil(struct mbuf **mp, struct ifnet *ifp, struct inpcb *inp,
+ struct sockaddr_in *dst, int *fibnum, int *error)
+{
+ struct m_tag *fwd_tag = NULL;
+ struct mbuf *m;
+ struct in_addr odst;
+ struct ip *ip;
+
+ m = *mp;
+ ip = mtod(m, struct ip *);
+
+ /* Run through list of hooks for output packets. */
+ odst.s_addr = ip->ip_dst.s_addr;
+ *error = pfil_run_hooks(&V_inet_pfil_hook, mp, ifp, PFIL_OUT, inp);
+ m = *mp;
+ if ((*error) != 0 || m == NULL)
+ return 1; /* Finished */
+
+ ip = mtod(m, struct ip *);
+
+ /* See if destination IP address was changed by packet filter. */
+ if (odst.s_addr != ip->ip_dst.s_addr) {
+ m->m_flags |= M_SKIP_FIREWALL;
+ /* If destination is now ourself drop to ip_input(). */
+ if (in_localip(ip->ip_dst)) {
+ m->m_flags |= M_FASTFWD_OURS;
+ if (m->m_pkthdr.rcvif == NULL)
+ m->m_pkthdr.rcvif = V_loif;
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ m->m_pkthdr.csum_flags |=
+ CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ m->m_pkthdr.csum_data = 0xffff;
+ }
+ m->m_pkthdr.csum_flags |=
+ CSUM_IP_CHECKED | CSUM_IP_VALID;
+#ifdef SCTP
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP)
+ m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+#endif
+ *error = netisr_queue(NETISR_IP, m);
+ return 1; /* Finished */
+ }
+
+ bzero(dst, sizeof(*dst));
+ dst->sin_family = AF_INET;
+ dst->sin_len = sizeof(*dst);
+ dst->sin_addr = ip->ip_dst;
+
+ return -1; /* Reloop */
+ }
+ /* See if fib was changed by packet filter. */
+ if ((*fibnum) != M_GETFIB(m)) {
+ m->m_flags |= M_SKIP_FIREWALL;
+ *fibnum = M_GETFIB(m);
+ return -1; /* Reloop for FIB change */
+ }
+
+ /* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */
+ if (m->m_flags & M_FASTFWD_OURS) {
+ if (m->m_pkthdr.rcvif == NULL)
+ m->m_pkthdr.rcvif = V_loif;
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ m->m_pkthdr.csum_flags |=
+ CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ m->m_pkthdr.csum_data = 0xffff;
+ }
+#ifdef SCTP
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP)
+ m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+#endif
+ m->m_pkthdr.csum_flags |=
+ CSUM_IP_CHECKED | CSUM_IP_VALID;
+
+ *error = netisr_queue(NETISR_IP, m);
+ return 1; /* Finished */
+ }
+ /* Or forward to some other address? */
+ if ((m->m_flags & M_IP_NEXTHOP) &&
+ ((fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL)) {
+ bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in));
+ m->m_flags |= M_SKIP_FIREWALL;
+ m->m_flags &= ~M_IP_NEXTHOP;
+ m_tag_delete(m, fwd_tag);
+
+ return -1; /* Reloop for CHANGE of dst */
+ }
+
+ return 0;
+}
+
/*
* IP output. The packet in mbuf chain m contains a skeletal IP
* header (with len, off, ttl, proto, tos, src, dst).
@@ -120,6 +213,7 @@ int
ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
struct ip_moptions *imo, struct inpcb *inp)
{
+ struct rm_priotracker in_ifa_tracker;
struct ip *ip;
struct ifnet *ifp = NULL; /* keep compiler happy */
struct mbuf *m0;
@@ -133,11 +227,8 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
uint16_t ip_len, ip_off;
struct route iproute;
struct rtentry *rte; /* cache for ro->ro_rt */
- struct in_addr odst;
- struct m_tag *fwd_tag = NULL;
uint32_t fibnum;
int have_ia_ref;
- int needfiblookup;
#ifdef IPSEC
int no_route_but_check_spd = 0;
#endif
@@ -191,32 +282,20 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
*/
gw = dst = (struct sockaddr_in *)&ro->ro_dst;
fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : M_GETFIB(m);
-again:
- ia = NULL;
- have_ia_ref = 0;
+ rte = ro->ro_rt;
/*
- * If there is a cached route, check that it is to the same
- * destination and is still up. If not, free it and try again.
* The address family should also be checked in case of sharing
* the cache with IPv6.
*/
- rte = ro->ro_rt;
- if (rte && ((rte->rt_flags & RTF_UP) == 0 ||
- rte->rt_ifp == NULL ||
- !RT_LINK_IS_UP(rte->rt_ifp) ||
- dst->sin_family != AF_INET ||
- dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
- RO_RTFREE(ro);
- ro->ro_lle = NULL;
- rte = NULL;
- gw = dst;
- }
- if (rte == NULL && fwd_tag == NULL) {
+ if (rte == NULL || dst->sin_family != AF_INET) {
bzero(dst, sizeof(*dst));
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = ip->ip_dst;
}
+again:
+ ia = NULL;
+ have_ia_ref = 0;
/*
* If routing to interface only, short circuit routing lookup.
* The use of an all-ones broadcast address implies this; an
@@ -258,7 +337,7 @@ again:
* packets if the interface is specified.
*/
ifp = imo->imo_multicast_ifp;
- IFP_TO_IA(ifp, ia);
+ IFP_TO_IA(ifp, ia, &in_ifa_tracker);
if (ia)
have_ia_ref = 1;
isbroadcast = 0; /* fool gcc */
@@ -279,6 +358,7 @@ again:
rte = ro->ro_rt;
}
if (rte == NULL ||
+ (rte->rt_flags & RTF_UP) == 0 ||
rte->rt_ifp == NULL ||
!RT_LINK_IS_UP(rte->rt_ifp)) {
#ifdef IPSEC
@@ -304,6 +384,7 @@ again:
else
isbroadcast = in_broadcast(gw->sin_addr, ifp);
}
+
/*
* Calculate MTU. If we have a route that is up, use that,
* otherwise use the interface's MTU.
@@ -315,6 +396,7 @@ again:
/* Catch a possible divide by zero later. */
KASSERT(mtu > 0, ("%s: mtu %d <= 0, rte=%p (rt_flags=0x%08x) ifp=%p",
__func__, mtu, rte, (rte != NULL) ? rte->rt_flags : 0, ifp));
+
if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
m->m_flags |= M_MCAST;
/*
@@ -472,87 +554,29 @@ sendit:
#endif /* IPSEC */
/* Jump over all PFIL processing if hooks are not active. */
- if (!PFIL_HOOKED(&V_inet_pfil_hook))
- goto passout;
-
- /* Run through list of hooks for output packets. */
- odst.s_addr = ip->ip_dst.s_addr;
- error = pfil_run_hooks(&V_inet_pfil_hook, &m, ifp, PFIL_OUT, inp);
- if (error != 0 || m == NULL)
- goto done;
+ if (PFIL_HOOKED(&V_inet_pfil_hook)) {
+ switch (ip_output_pfil(&m, ifp, inp, dst, &fibnum, &error)) {
+ case 1: /* Finished */
+ goto done;
- ip = mtod(m, struct ip *);
- needfiblookup = 0;
+ case 0: /* Continue normally */
+ ip = mtod(m, struct ip *);
+ break;
- /* See if destination IP address was changed by packet filter. */
- if (odst.s_addr != ip->ip_dst.s_addr) {
- m->m_flags |= M_SKIP_FIREWALL;
- /* If destination is now ourself drop to ip_input(). */
- if (in_localip(ip->ip_dst)) {
- m->m_flags |= M_FASTFWD_OURS;
- if (m->m_pkthdr.rcvif == NULL)
- m->m_pkthdr.rcvif = V_loif;
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
- m->m_pkthdr.csum_flags |=
- CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
- m->m_pkthdr.csum_data = 0xffff;
- }
- m->m_pkthdr.csum_flags |=
- CSUM_IP_CHECKED | CSUM_IP_VALID;
-#ifdef SCTP
- if (m->m_pkthdr.csum_flags & CSUM_SCTP)
- m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
-#endif
- error = netisr_queue(NETISR_IP, m);
- goto done;
- } else {
+ case -1: /* Need to try again */
+ /* Reset everything for a new round */
+ RO_RTFREE(ro);
if (have_ia_ref)
ifa_free(&ia->ia_ifa);
- needfiblookup = 1; /* Redo the routing table lookup. */
- }
- }
- /* See if fib was changed by packet filter. */
- if (fibnum != M_GETFIB(m)) {
- m->m_flags |= M_SKIP_FIREWALL;
- fibnum = M_GETFIB(m);
- RO_RTFREE(ro);
- needfiblookup = 1;
- }
- if (needfiblookup)
- goto again;
+ ro->ro_lle = NULL;
+ rte = NULL;
+ gw = dst;
+ ip = mtod(m, struct ip *);
+ goto again;
- /* See if local, if yes, send it to netisr with IP_FASTFWD_OURS. */
- if (m->m_flags & M_FASTFWD_OURS) {
- if (m->m_pkthdr.rcvif == NULL)
- m->m_pkthdr.rcvif = V_loif;
- if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
- m->m_pkthdr.csum_flags |=
- CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
- m->m_pkthdr.csum_data = 0xffff;
}
-#ifdef SCTP
- if (m->m_pkthdr.csum_flags & CSUM_SCTP)
- m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
-#endif
- m->m_pkthdr.csum_flags |=
- CSUM_IP_CHECKED | CSUM_IP_VALID;
-
- error = netisr_queue(NETISR_IP, m);
- goto done;
- }
- /* Or forward to some other address? */
- if ((m->m_flags & M_IP_NEXTHOP) &&
- (fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL)) != NULL) {
- bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in));
- m->m_flags |= M_SKIP_FIREWALL;
- m->m_flags &= ~M_IP_NEXTHOP;
- m_tag_delete(m, fwd_tag);
- if (have_ia_ref)
- ifa_free(&ia->ia_ifa);
- goto again;
}
-passout:
/* 127/8 must not appear on wire - RFC1122. */
if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
(ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
@@ -660,6 +684,13 @@ passout:
done:
if (ro == &iproute)
RO_RTFREE(ro);
+ else if (rte == NULL)
+ /*
+ * If the caller supplied a route but somehow the reference
+ * to it has been released need to prevent the caller
+ * calling RTFREE on it again.
+ */
+ ro->ro_rt = NULL;
if (have_ia_ref)
ifa_free(&ia->ia_ifa);
return (error);
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index a71d8ec..4e9feda 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/protosw.h>
+#include <sys/rmlock.h>
#include <sys/rwlock.h>
#include <sys/signalvar.h>
#include <sys/socket.h>
@@ -724,6 +725,7 @@ rip_ctloutput(struct socket *so, struct sockopt *sopt)
void
rip_ctlinput(int cmd, struct sockaddr *sa, void *vip)
{
+ struct rm_priotracker in_ifa_tracker;
struct in_ifaddr *ia;
struct ifnet *ifp;
int err;
@@ -731,12 +733,12 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip)
switch (cmd) {
case PRC_IFDOWN:
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (ia->ia_ifa.ifa_addr == sa
&& (ia->ia_flags & IFA_ROUTE)) {
ifa_ref(&ia->ia_ifa);
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
/*
* in_scrubprefix() kills the interface route.
*/
@@ -753,21 +755,21 @@ rip_ctlinput(int cmd, struct sockaddr *sa, void *vip)
}
}
if (ia == NULL) /* If ia matched, already unlocked. */
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
break;
case PRC_IFUP:
- IN_IFADDR_RLOCK();
+ IN_IFADDR_RLOCK(&in_ifa_tracker);
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (ia->ia_ifa.ifa_addr == sa)
break;
}
if (ia == NULL || (ia->ia_flags & IFA_ROUTE)) {
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
return;
}
ifa_ref(&ia->ia_ifa);
- IN_IFADDR_RUNLOCK();
+ IN_IFADDR_RUNLOCK(&in_ifa_tracker);
flags = RTF_UP;
ifp = ia->ia_ifa.ifa_ifp;
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c
index a64e7f9..540cc65 100644
--- a/sys/netinet/sctp_asconf.c
+++ b/sys/netinet/sctp_asconf.c
@@ -1680,8 +1680,14 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset,
* abort the asoc, since someone probably just hijacked us...
*/
if (serial_num == (asoc->asconf_seq_out + 1)) {
+ struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
+
SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n");
- sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, SCTP_SO_NOT_LOCKED);
+ snprintf(msg, sizeof(msg), "Never sent serial number %8.8x",
+ serial_num);
+ op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
*abort_no_unlock = 1;
return;
}
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index f8bf05f..7d92655 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -2312,11 +2312,8 @@ doit_again:
int
sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
- struct sockaddr *src, struct sockaddr *dst,
- struct sctphdr *sh, struct sctp_inpcb *inp,
- struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t * high_tsn,
- uint8_t mflowtype, uint32_t mflowid,
- uint32_t vrf_id, uint16_t port)
+ struct sctp_inpcb *inp, struct sctp_tcb *stcb,
+ struct sctp_nets *net, uint32_t * high_tsn)
{
struct sctp_data_chunk *ch, chunk_buf;
struct sctp_association *asoc;
@@ -2408,10 +2405,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
chk_length);
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_21;
- sctp_abort_association(inp, stcb, m, iphlen,
- src, dst, sh, op_err,
- mflowtype, mflowid,
- vrf_id, port);
+ sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
return (2);
}
if ((size_t)chk_length == sizeof(struct sctp_data_chunk)) {
@@ -2423,10 +2417,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
op_err = sctp_generate_no_user_data_cause(ch->dp.tsn);
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_22;
- sctp_abort_association(inp, stcb, m, iphlen,
- src, dst, sh, op_err,
- mflowtype, mflowid,
- vrf_id, port);
+ sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
return (2);
}
#ifdef SCTP_AUDITING_ENABLED
@@ -2488,14 +2479,12 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
*/
if (SCTP_BASE_SYSCTL(sctp_strict_data_order)) {
struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
- op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, "");
- sctp_abort_association(inp, stcb,
- m, iphlen,
- src, dst,
- sh, op_err,
- mflowtype, mflowid,
- vrf_id, port);
+ snprintf(msg, sizeof(msg), "DATA chunk followed by chunk of type %2.2x",
+ ch->ch.chunk_type);
+ op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
+ sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
return (2);
}
break;
diff --git a/sys/netinet/sctp_indata.h b/sys/netinet/sctp_indata.h
index 79a86e2..94cd49c 100644
--- a/sys/netinet/sctp_indata.h
+++ b/sys/netinet/sctp_indata.h
@@ -112,12 +112,8 @@ void
int
sctp_process_data(struct mbuf **, int, int *, int,
- struct sockaddr *src, struct sockaddr *dst,
- struct sctphdr *,
struct sctp_inpcb *, struct sctp_tcb *,
- struct sctp_nets *, uint32_t *,
- uint8_t, uint32_t,
- uint32_t, uint16_t);
+ struct sctp_nets *, uint32_t *);
void sctp_slide_mapping_arrays(struct sctp_tcb *stcb);
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index aa7c30c..9071bf6 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -4624,7 +4624,7 @@ __attribute__((noinline))
}
}
if (stcb == NULL) {
- snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+ snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __FUNCTION__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
/* no association, so it's out of the blue... */
@@ -4668,7 +4668,7 @@ __attribute__((noinline))
if (locked_tcb) {
SCTP_TCB_UNLOCK(locked_tcb);
}
- snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+ snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __FUNCTION__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
sctp_handle_ootb(m, iphlen, *offset, src, dst,
@@ -5834,7 +5834,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
*/
SCTP_TCB_UNLOCK(stcb);
stcb = NULL;
- snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+ snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __FUNCTION__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
@@ -5886,7 +5886,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
}
if (stcb == NULL) {
/* out of the blue DATA chunk */
- snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+ snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __FUNCTION__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
@@ -5958,7 +5958,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
/*
* We consider OOTB any data sent during asoc setup.
*/
- snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+ snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __FUNCTION__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
@@ -5981,10 +5981,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
}
/* plow through the data chunks while length > offset */
retval = sctp_process_data(mm, iphlen, &offset, length,
- src, dst, sh,
- inp, stcb, net, &high_tsn,
- mflowtype, mflowid,
- vrf_id, port);
+ inp, stcb, net, &high_tsn);
if (retval == 2) {
/*
* The association aborted, NO UNLOCK needed since
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 1beab07..1c56f9a 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -5524,7 +5524,7 @@ do_a_abort:
if (op_err == NULL) {
char msg[SCTP_DIAG_INFO_LEN];
- snprintf(msg, sizeof(msg), "%s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+ snprintf(msg, sizeof(msg), "%s:%d at %s", __FILE__, __LINE__, __FUNCTION__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
}
@@ -6682,10 +6682,17 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
(asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
+ struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
+
abort_anyway:
+ snprintf(msg, sizeof(msg),
+ "%s:%d at %s", __FILE__, __LINE__, __FUNCTION__);
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ msg);
atomic_add_int(&stcb->asoc.refcnt, 1);
sctp_abort_an_association(stcb->sctp_ep, stcb,
- NULL, SCTP_SO_NOT_LOCKED);
+ op_err, SCTP_SO_NOT_LOCKED);
atomic_add_int(&stcb->asoc.refcnt, -1);
goto no_chunk_output;
}
@@ -9454,12 +9461,16 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
}
if ((SCTP_BASE_SYSCTL(sctp_max_retran_chunk)) &&
(chk->snd_count >= SCTP_BASE_SYSCTL(sctp_max_retran_chunk))) {
- /* Gak, we have exceeded max unlucky retran, abort! */
- SCTP_PRINTF("Gak, chk->snd_count:%d >= max:%d - send abort\n",
- chk->snd_count,
- SCTP_BASE_SYSCTL(sctp_max_retran_chunk));
+ struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
+
+ snprintf(msg, sizeof(msg), "TSN %8.8x retransmitted %d times, giving up",
+ chk->rec.data.TSN_seq, chk->snd_count);
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ msg);
atomic_add_int(&stcb->asoc.refcnt, 1);
- sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, so_locked);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, op_err,
+ so_locked);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (SCTP_RETRAN_EXIT);
@@ -13344,13 +13355,20 @@ dataless_eof:
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
(asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
+ struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
+
abort_anyway:
if (free_cnt_applied) {
atomic_add_int(&stcb->asoc.refcnt, -1);
free_cnt_applied = 0;
}
+ snprintf(msg, sizeof(msg),
+ "%s:%d at %s", __FILE__, __LINE__, __FUNCTION__);
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ msg);
sctp_abort_an_association(stcb->sctp_ep, stcb,
- NULL, SCTP_SO_LOCKED);
+ op_err, SCTP_SO_LOCKED);
/*
* now relock the stcb so everything
* is sane
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 541d4ca..07119f1 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -6250,12 +6250,20 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
*/
if (stcb_tmp) {
if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) {
+ struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
+
/*
* in setup state we
* abort this guy
*/
+ snprintf(msg, sizeof(msg),
+ "%s:%d at %s", __FILE__, __LINE__, __FUNCTION__);
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ msg);
sctp_abort_an_association(stcb_tmp->sctp_ep,
- stcb_tmp, NULL, SCTP_SO_NOT_LOCKED);
+ stcb_tmp, op_err,
+ SCTP_SO_NOT_LOCKED);
goto add_it_now;
}
SCTP_TCB_UNLOCK(stcb_tmp);
@@ -6339,18 +6347,26 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
* strange, address is in another
* assoc? straighten out locks.
*/
- if (stcb_tmp)
+ if (stcb_tmp) {
if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) {
+ struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
+
/*
* in setup state we
* abort this guy
*/
+ snprintf(msg, sizeof(msg),
+ "%s:%d at %s", __FILE__, __LINE__, __FUNCTION__);
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ msg);
sctp_abort_an_association(stcb_tmp->sctp_ep,
- stcb_tmp, NULL, SCTP_SO_NOT_LOCKED);
+ stcb_tmp, op_err,
+ SCTP_SO_NOT_LOCKED);
goto add_it_now6;
}
- SCTP_TCB_UNLOCK(stcb_tmp);
-
+ SCTP_TCB_UNLOCK(stcb_tmp);
+ }
if (stcb->asoc.state == 0) {
/* the assoc was freed? */
return (-21);
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index 257d188..6c8589e 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -153,7 +153,7 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* Abort notification sends a ULP notify */
struct mbuf *op_err;
- op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION,
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
"Association error counter exceeded");
inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_2;
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
@@ -1046,7 +1046,7 @@ sctp_cookie_timer(struct sctp_inpcb *inp,
/* FOOBAR! */
struct mbuf *op_err;
- op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION,
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
"Cookie timer expired, but no cookie");
inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_3;
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index b613992..069ed34 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1445,6 +1445,7 @@ sctp_timeout_handler(void *t)
struct sctp_tcb *stcb;
struct sctp_nets *net;
struct sctp_timer *tmr;
+ struct mbuf *op_err;
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
@@ -1756,7 +1757,9 @@ sctp_timeout_handler(void *t)
break;
}
SCTP_STAT_INCR(sctps_timoshutdownguard);
- sctp_abort_an_association(inp, stcb, NULL, SCTP_SO_NOT_LOCKED);
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ "Shutdown guard timer expired");
+ sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
/* no need to unlock on tcb its gone */
goto out_decr;
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 9454a65..e7ef6db 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -608,7 +608,7 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
char *s = NULL; /* address and port logging */
int ti_locked;
#define TI_UNLOCKED 1
-#define TI_WLOCKED 2
+#define TI_RLOCKED 2
#ifdef TCPDEBUG
/*
@@ -797,8 +797,8 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
* connection in TIMEWAIT and SYNs not targeting a listening socket.
*/
if ((thflags & (TH_FIN | TH_RST)) != 0) {
- INP_INFO_WLOCK(&V_tcbinfo);
- ti_locked = TI_WLOCKED;
+ INP_INFO_RLOCK(&V_tcbinfo);
+ ti_locked = TI_RLOCKED;
} else
ti_locked = TI_UNLOCKED;
@@ -820,8 +820,8 @@ tcp_input(struct mbuf **mp, int *offp, int proto)
findpcb:
#ifdef INVARIANTS
- if (ti_locked == TI_WLOCKED) {
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
} else {
INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
}
@@ -969,20 +969,20 @@ findpcb:
relocked:
if (inp->inp_flags & INP_TIMEWAIT) {
if (ti_locked == TI_UNLOCKED) {
- if (INP_INFO_TRY_WLOCK(&V_tcbinfo) == 0) {
+ if (INP_INFO_TRY_RLOCK(&V_tcbinfo) == 0) {
in_pcbref(inp);
INP_WUNLOCK(inp);
- INP_INFO_WLOCK(&V_tcbinfo);
- ti_locked = TI_WLOCKED;
+ INP_INFO_RLOCK(&V_tcbinfo);
+ ti_locked = TI_RLOCKED;
INP_WLOCK(inp);
if (in_pcbrele_wlocked(inp)) {
inp = NULL;
goto findpcb;
}
} else
- ti_locked = TI_WLOCKED;
+ ti_locked = TI_RLOCKED;
}
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
if (thflags & TH_SYN)
tcp_dooptions(&to, optp, optlen, TO_SYN);
@@ -991,7 +991,7 @@ relocked:
*/
if (tcp_twcheck(inp, &to, th, m, tlen))
goto findpcb;
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (IPPROTO_DONE);
}
/*
@@ -1022,16 +1022,16 @@ relocked:
*/
#ifdef INVARIANTS
if ((thflags & (TH_FIN | TH_RST)) != 0)
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
#endif
if (!((tp->t_state == TCPS_ESTABLISHED && (thflags & TH_SYN) == 0) ||
(tp->t_state == TCPS_LISTEN && (thflags & TH_SYN)))) {
if (ti_locked == TI_UNLOCKED) {
- if (INP_INFO_TRY_WLOCK(&V_tcbinfo) == 0) {
+ if (INP_INFO_TRY_RLOCK(&V_tcbinfo) == 0) {
in_pcbref(inp);
INP_WUNLOCK(inp);
- INP_INFO_WLOCK(&V_tcbinfo);
- ti_locked = TI_WLOCKED;
+ INP_INFO_RLOCK(&V_tcbinfo);
+ ti_locked = TI_RLOCKED;
INP_WLOCK(inp);
if (in_pcbrele_wlocked(inp)) {
inp = NULL;
@@ -1039,9 +1039,9 @@ relocked:
}
goto relocked;
} else
- ti_locked = TI_WLOCKED;
+ ti_locked = TI_RLOCKED;
}
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
}
#ifdef MAC
@@ -1096,7 +1096,7 @@ relocked:
*/
if ((thflags & (TH_RST|TH_ACK|TH_SYN)) == TH_ACK) {
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
/*
* Parse the TCP options here because
* syncookies need access to the reflected
@@ -1148,7 +1148,11 @@ relocked:
*/
INP_WUNLOCK(inp); /* listen socket */
inp = sotoinpcb(so);
- INP_WLOCK(inp); /* new connection */
+ /*
+ * New connection inpcb is already locked by
+ * syncache_expand().
+ */
+ INP_WLOCK_ASSERT(inp);
tp = intotcpcb(inp);
KASSERT(tp->t_state == TCPS_SYN_RECEIVED,
("%s: ", __func__));
@@ -1379,8 +1383,8 @@ relocked:
* Entry added to syncache and mbuf consumed.
* Only the listen socket is unlocked by syncache_add().
*/
- if (ti_locked == TI_WLOCKED) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RUNLOCK(&V_tcbinfo);
ti_locked = TI_UNLOCKED;
}
INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
@@ -1429,8 +1433,8 @@ relocked:
dropwithreset:
TCP_PROBE5(receive, NULL, tp, mtod(m, const char *), tp, th);
- if (ti_locked == TI_WLOCKED) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RUNLOCK(&V_tcbinfo);
ti_locked = TI_UNLOCKED;
}
#ifdef INVARIANTS
@@ -1453,8 +1457,8 @@ dropunlock:
if (m != NULL)
TCP_PROBE5(receive, NULL, tp, mtod(m, const char *), tp, th);
- if (ti_locked == TI_WLOCKED) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RUNLOCK(&V_tcbinfo);
ti_locked = TI_UNLOCKED;
}
#ifdef INVARIANTS
@@ -1511,13 +1515,13 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((thflags & (TH_SYN | TH_FIN | TH_RST)) != 0 ||
tp->t_state != TCPS_ESTABLISHED) {
- KASSERT(ti_locked == TI_WLOCKED, ("%s ti_locked %d for "
+ KASSERT(ti_locked == TI_RLOCKED, ("%s ti_locked %d for "
"SYN/FIN/RST/!EST", __func__, ti_locked));
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
} else {
#ifdef INVARIANTS
- if (ti_locked == TI_WLOCKED)
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ if (ti_locked == TI_RLOCKED)
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
else {
KASSERT(ti_locked == TI_UNLOCKED, ("%s: EST "
"ti_locked: %d", __func__, ti_locked));
@@ -1665,7 +1669,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tp->snd_nxt == tp->snd_max &&
tiwin && tiwin == tp->snd_wnd &&
((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) == 0) &&
- tp->t_segq == NULL && ((to.to_flags & TOF_TS) == 0 ||
+ LIST_EMPTY(&tp->t_segq) &&
+ ((to.to_flags & TOF_TS) == 0 ||
TSTMP_GEQ(to.to_tsval, tp->ts_recent)) ) {
/*
@@ -1689,8 +1694,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
/*
* This is a pure ack for outstanding data.
*/
- if (ti_locked == TI_WLOCKED)
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ if (ti_locked == TI_RLOCKED)
+ INP_INFO_RUNLOCK(&V_tcbinfo);
ti_locked = TI_UNLOCKED;
TCPSTAT_INC(tcps_predack);
@@ -1793,8 +1798,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
* nothing on the reassembly queue and we have enough
* buffer space to take it.
*/
- if (ti_locked == TI_WLOCKED)
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ if (ti_locked == TI_RLOCKED)
+ INP_INFO_RUNLOCK(&V_tcbinfo);
ti_locked = TI_UNLOCKED;
/* Clean receiver SACK report if present */
@@ -2030,9 +2035,9 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tcp_state_change(tp, TCPS_SYN_RECEIVED);
}
- KASSERT(ti_locked == TI_WLOCKED, ("%s: trimthenstep6: "
+ KASSERT(ti_locked == TI_RLOCKED, ("%s: trimthenstep6: "
"ti_locked %d", __func__, ti_locked));
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(tp->t_inpcb);
/*
@@ -2105,8 +2110,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
SEQ_LT(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) ||
(tp->rcv_wnd == 0 && tp->last_ack_sent == th->th_seq)) {
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
- KASSERT(ti_locked == TI_WLOCKED,
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+ KASSERT(ti_locked == TI_RLOCKED,
("%s: TH_RST ti_locked %d, th %p tp %p",
__func__, ti_locked, th, tp));
KASSERT(tp->t_state != TCPS_SYN_SENT,
@@ -2149,9 +2154,9 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
* Send challenge ACK for any SYN in synchronized state.
*/
if ((thflags & TH_SYN) && tp->t_state != TCPS_SYN_SENT) {
- KASSERT(ti_locked == TI_WLOCKED,
+ KASSERT(ti_locked == TI_RLOCKED,
("tcp_do_segment: TH_SYN ti_locked %d", ti_locked));
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
TCPSTAT_INC(tcps_badsyn);
if (V_tcp_insecure_syn &&
@@ -2264,9 +2269,9 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((so->so_state & SS_NOFDREF) &&
tp->t_state > TCPS_CLOSE_WAIT && tlen) {
- KASSERT(ti_locked == TI_WLOCKED, ("%s: SS_NOFDEREF && "
+ KASSERT(ti_locked == TI_RLOCKED, ("%s: SS_NOFDEREF && "
"CLOSE_WAIT && tlen ti_locked %d", __func__, ti_locked));
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
if ((s = tcp_log_addrs(inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: %s: Received %d bytes of data "
@@ -2767,9 +2772,9 @@ process_ACK:
*/
case TCPS_CLOSING:
if (ourfinisacked) {
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
tcp_twstart(tp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
m_freem(m);
return;
}
@@ -2783,7 +2788,7 @@ process_ACK:
*/
case TCPS_LAST_ACK:
if (ourfinisacked) {
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
tp = tcp_close(tp);
goto drop;
}
@@ -2903,7 +2908,8 @@ dodata: /* XXX */
* immediately when segments are out of order (so
* fast retransmit can work).
*/
- if (th->th_seq == tp->rcv_nxt && tp->t_segq == NULL &&
+ if (th->th_seq == tp->rcv_nxt &&
+ LIST_EMPTY(&tp->t_segq) &&
TCPS_HAVEESTABLISHED(tp->t_state)) {
if (DELAY_ACK(tp, tlen))
tp->t_flags |= TF_DELACK;
@@ -2997,18 +3003,18 @@ dodata: /* XXX */
* standard timers.
*/
case TCPS_FIN_WAIT_2:
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
- KASSERT(ti_locked == TI_WLOCKED, ("%s: dodata "
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
+ KASSERT(ti_locked == TI_RLOCKED, ("%s: dodata "
"TCP_FIN_WAIT_2 ti_locked: %d", __func__,
ti_locked));
tcp_twstart(tp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return;
}
}
- if (ti_locked == TI_WLOCKED)
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ if (ti_locked == TI_RLOCKED)
+ INP_INFO_RUNLOCK(&V_tcbinfo);
ti_locked = TI_UNLOCKED;
#ifdef TCPDEBUG
@@ -3063,8 +3069,8 @@ dropafterack:
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
&tcp_savetcp, 0);
#endif
- if (ti_locked == TI_WLOCKED)
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ if (ti_locked == TI_RLOCKED)
+ INP_INFO_RUNLOCK(&V_tcbinfo);
ti_locked = TI_UNLOCKED;
tp->t_flags |= TF_ACKNOW;
@@ -3074,8 +3080,8 @@ dropafterack:
return;
dropwithreset:
- if (ti_locked == TI_WLOCKED)
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ if (ti_locked == TI_RLOCKED)
+ INP_INFO_RUNLOCK(&V_tcbinfo);
ti_locked = TI_UNLOCKED;
if (tp != NULL) {
@@ -3086,8 +3092,8 @@ dropwithreset:
return;
drop:
- if (ti_locked == TI_WLOCKED) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ if (ti_locked == TI_RLOCKED) {
+ INP_INFO_RUNLOCK(&V_tcbinfo);
ti_locked = TI_UNLOCKED;
}
#ifdef INVARIANTS
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index 17d9a79..77d8940 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -71,33 +71,80 @@ __FBSDID("$FreeBSD$");
#include <netinet/tcp_var.h>
#include <netinet6/tcp6_var.h>
#include <netinet/tcpip.h>
+#ifdef TCPDEBUG
+#include <netinet/tcp_debug.h>
+#endif /* TCPDEBUG */
+
+static SYSCTL_NODE(_net_inet_tcp, OID_AUTO, reass, CTLFLAG_RW, 0,
+ "TCP Segment Reassembly Queue");
+
+static int tcp_reass_maxseg = 0;
+SYSCTL_INT(_net_inet_tcp_reass, OID_AUTO, maxsegments, CTLFLAG_RDTUN,
+ &tcp_reass_maxseg, 0,
+ "Global maximum number of TCP Segments in Reassembly Queue");
+
+static uma_zone_t tcp_reass_zone;
+SYSCTL_UMA_CUR(_net_inet_tcp_reass, OID_AUTO, cursegments, CTLFLAG_VNET,
+ &tcp_reass_zone,
+ "Global number of TCP Segments currently in Reassembly Queue");
+
+/* Initialize TCP reassembly queue */
+static void
+tcp_reass_zone_change(void *tag)
+{
+
+ /* Set the zone limit and read back the effective value. */
+ tcp_reass_maxseg = nmbclusters / 16;
+ tcp_reass_maxseg = uma_zone_set_max(tcp_reass_zone,
+ tcp_reass_maxseg);
+}
+
+void
+tcp_reass_global_init(void)
+{
+
+ tcp_reass_maxseg = nmbclusters / 16;
+ TUNABLE_INT_FETCH("net.inet.tcp.reass.maxsegments",
+ &tcp_reass_maxseg);
+ tcp_reass_zone = uma_zcreate("tcpreass", sizeof (struct tseg_qent),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
+ /* Set the zone limit and read back the effective value. */
+ tcp_reass_maxseg = uma_zone_set_max(tcp_reass_zone,
+ tcp_reass_maxseg);
+ EVENTHANDLER_REGISTER(nmbclusters_change,
+ tcp_reass_zone_change, NULL, EVENTHANDLER_PRI_ANY);
+}
void
tcp_reass_flush(struct tcpcb *tp)
{
- struct mbuf *m;
+ struct tseg_qent *qe;
INP_WLOCK_ASSERT(tp->t_inpcb);
- while ((m = tp->t_segq) != NULL) {
- tp->t_segq = m->m_nextpkt;
- tp->t_segqlen -= m->m_pkthdr.len;
- m_freem(m);
+ while ((qe = LIST_FIRST(&tp->t_segq)) != NULL) {
+ LIST_REMOVE(qe, tqe_q);
+ m_freem(qe->tqe_m);
+ uma_zfree(tcp_reass_zone, qe);
+ tp->t_segqlen--;
}
KASSERT((tp->t_segqlen == 0),
- ("TCP reass queue %p length is %d instead of 0 after flush.",
+ ("TCP reass queue %p segment count is %d instead of 0 after flush.",
tp, tp->t_segqlen));
}
-#define M_TCPHDR(m) ((struct tcphdr *)((m)->m_pkthdr.pkt_tcphdr))
-
int
tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
{
+ struct tseg_qent *q;
+ struct tseg_qent *p = NULL;
+ struct tseg_qent *nq;
+ struct tseg_qent *te = NULL;
struct socket *so = tp->t_inpcb->inp_socket;
- struct mbuf *mq, *mp;
- int flags, wakeup;
+ char *s = NULL;
+ int flags;
+ struct tseg_qent tqs;
INP_WLOCK_ASSERT(tp->t_inpcb);
@@ -113,10 +160,6 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
if (th == NULL)
goto present;
- M_ASSERTPKTHDR(m);
- KASSERT(*tlenp == m->m_pkthdr.len, ("%s: tlenp %u len %u", __func__,
- *tlenp, m->m_pkthdr.len));
-
/*
* Limit the number of segments that can be queued to reduce the
* potential for mbuf exhaustion. For best performance, we want to be
@@ -127,15 +170,17 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
* Always let the missing segment through which caused this queue.
* NB: Access to the socket buffer is left intentionally unlocked as we
* can tolerate stale information here.
+ *
+ * XXXLAS: Using sbspace(so->so_rcv) instead of so->so_rcv.sb_hiwat
+ * should work but causes packets to be dropped when they shouldn't.
+ * Investigate why and re-evaluate the below limit after the behaviour
+ * is understood.
*/
if ((th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) &&
- tp->t_segqlen + m->m_pkthdr.len >= sbspace(&so->so_rcv)) {
- char *s;
-
+ tp->t_segqlen >= (so->so_rcv.sb_hiwat / tp->t_maxseg) + 1) {
TCPSTAT_INC(tcps_rcvreassfull);
*tlenp = 0;
- if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
- NULL))) {
+ if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: queue limit reached, "
"segment dropped\n", s, __func__);
free(s, M_TCPLOG);
@@ -145,13 +190,46 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
}
/*
+ * Allocate a new queue entry. If we can't, or hit the zone limit
+ * just drop the pkt.
+ *
+ * Use a temporary structure on the stack for the missing segment
+ * when the zone is exhausted. Otherwise we may get stuck.
+ */
+ te = uma_zalloc(tcp_reass_zone, M_NOWAIT);
+ if (te == NULL) {
+ if (th->th_seq != tp->rcv_nxt || !TCPS_HAVEESTABLISHED(tp->t_state)) {
+ TCPSTAT_INC(tcps_rcvmemdrop);
+ m_freem(m);
+ *tlenp = 0;
+ if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
+ NULL))) {
+ log(LOG_DEBUG, "%s; %s: global zone limit "
+ "reached, segment dropped\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ return (0);
+ } else {
+ bzero(&tqs, sizeof(struct tseg_qent));
+ te = &tqs;
+ if ((s = tcp_log_addrs(&tp->t_inpcb->inp_inc, th, NULL,
+ NULL))) {
+ log(LOG_DEBUG,
+ "%s; %s: global zone limit reached, using "
+ "stack for missing segment\n", s, __func__);
+ free(s, M_TCPLOG);
+ }
+ }
+ }
+ tp->t_segqlen++;
+
+ /*
* Find a segment which begins after this one does.
*/
- mp = NULL;
- for (mq = tp->t_segq; mq != NULL; mq = mq->m_nextpkt) {
- if (SEQ_GT(M_TCPHDR(mq)->th_seq, th->th_seq))
+ LIST_FOREACH(q, &tp->t_segq, tqe_q) {
+ if (SEQ_GT(q->tqe_th->th_seq, th->th_seq))
break;
- mp = mq;
+ p = q;
}
/*
@@ -159,16 +237,18 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
* our data already. If so, drop the data from the incoming
* segment. If it provides all of our data, drop us.
*/
- if (mp != NULL) {
+ if (p != NULL) {
int i;
-
/* conversion to int (in i) handles seq wraparound */
- i = M_TCPHDR(mp)->th_seq + mp->m_pkthdr.len - th->th_seq;
+ i = p->tqe_th->th_seq + p->tqe_len - th->th_seq;
if (i > 0) {
if (i >= *tlenp) {
TCPSTAT_INC(tcps_rcvduppack);
TCPSTAT_ADD(tcps_rcvdupbyte, *tlenp);
m_freem(m);
+ if (te != &tqs)
+ uma_zfree(tcp_reass_zone, te);
+ tp->t_segqlen--;
/*
* Try to present any queued data
* at the left window edge to the user.
@@ -190,54 +270,37 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
* While we overlap succeeding segments trim them or,
* if they are completely covered, dequeue them.
*/
- while (mq) {
- struct mbuf *nq;
- int i;
-
- i = (th->th_seq + *tlenp) - M_TCPHDR(mq)->th_seq;
+ while (q) {
+ int i = (th->th_seq + *tlenp) - q->tqe_th->th_seq;
if (i <= 0)
break;
- if (i < mq->m_pkthdr.len) {
- M_TCPHDR(mq)->th_seq += i;
- m_adj(mq, i);
- tp->t_segqlen -= i;
+ if (i < q->tqe_len) {
+ q->tqe_th->th_seq += i;
+ q->tqe_len -= i;
+ m_adj(q->tqe_m, i);
break;
}
- nq = mq->m_nextpkt;
- tp->t_segqlen -= mq->m_pkthdr.len;
- m_freem(mq);
- if (mp)
- mp->m_nextpkt = nq;
- else
- tp->t_segq = nq;
- mq = nq;
+ nq = LIST_NEXT(q, tqe_q);
+ LIST_REMOVE(q, tqe_q);
+ m_freem(q->tqe_m);
+ uma_zfree(tcp_reass_zone, q);
+ tp->t_segqlen--;
+ q = nq;
}
- /*
- * Insert the new segment queue entry into place. Try to collapse
- * mbuf chains if segments are adjacent.
- */
- if (mp) {
- if (M_TCPHDR(mp)->th_seq + mp->m_pkthdr.len == th->th_seq)
- m_catpkt(mp, m);
- else {
- m->m_nextpkt = mp->m_nextpkt;
- mp->m_nextpkt = m;
- m->m_pkthdr.pkt_tcphdr = th;
- }
+ /* Insert the new segment queue entry into place. */
+ te->tqe_m = m;
+ te->tqe_th = th;
+ te->tqe_len = *tlenp;
+
+ if (p == NULL) {
+ LIST_INSERT_HEAD(&tp->t_segq, te, tqe_q);
} else {
- mq = tp->t_segq;
- tp->t_segq = m;
- if (mq && th->th_seq + *tlenp == M_TCPHDR(mq)->th_seq) {
- m->m_nextpkt = mq->m_nextpkt;
- mq->m_nextpkt = NULL;
- m_catpkt(m, mq);
- } else
- m->m_nextpkt = mq;
- m->m_pkthdr.pkt_tcphdr = th;
+ KASSERT(te != &tqs, ("%s: temporary stack based entry not "
+ "first element in queue", __func__));
+ LIST_INSERT_AFTER(p, te, tqe_q);
}
- tp->t_segqlen += *tlenp;
present:
/*
@@ -246,30 +309,25 @@ present:
*/
if (!TCPS_HAVEESTABLISHED(tp->t_state))
return (0);
-
- flags = 0;
- wakeup = 0;
+ q = LIST_FIRST(&tp->t_segq);
+ if (!q || q->tqe_th->th_seq != tp->rcv_nxt)
+ return (0);
SOCKBUF_LOCK(&so->so_rcv);
- while ((mq = tp->t_segq) != NULL &&
- M_TCPHDR(mq)->th_seq == tp->rcv_nxt) {
- tp->t_segq = mq->m_nextpkt;
-
- tp->rcv_nxt += mq->m_pkthdr.len;
- tp->t_segqlen -= mq->m_pkthdr.len;
- flags = M_TCPHDR(mq)->th_flags & TH_FIN;
-
+ do {
+ tp->rcv_nxt += q->tqe_len;
+ flags = q->tqe_th->th_flags & TH_FIN;
+ nq = LIST_NEXT(q, tqe_q);
+ LIST_REMOVE(q, tqe_q);
if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
- m_freem(mq);
- else {
- mq->m_nextpkt = NULL;
- sbappendstream_locked(&so->so_rcv, mq, 0);
- wakeup = 1;
- }
- }
+ m_freem(q->tqe_m);
+ else
+ sbappendstream_locked(&so->so_rcv, q->tqe_m, 0);
+ if (q != &tqs)
+ uma_zfree(tcp_reass_zone, q);
+ tp->t_segqlen--;
+ q = nq;
+ } while (q && q->tqe_th->th_seq == tp->rcv_nxt);
ND6_HINT(tp);
- if (wakeup)
- sorwakeup_locked(so);
- else
- SOCKBUF_UNLOCK(&so->so_rcv);
+ sorwakeup_locked(so);
return (flags);
}
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 757bcf2..808eb97 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -385,6 +385,8 @@ tcp_init(void)
if (!IS_DEFAULT_VNET(curvnet))
return;
+ tcp_reass_global_init();
+
/* XXX virtualize those bellow? */
tcp_delacktime = TCPTV_DELACK;
tcp_keepinit = TCPTV_KEEP_INIT;
@@ -856,7 +858,7 @@ tcp_ccalgounload(struct cc_algo *unload_algo)
VNET_LIST_RLOCK();
VNET_FOREACH(vnet_iter) {
CURVNET_SET(vnet_iter);
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_WLOCK(&V_tcbinfo);
/*
* New connections already part way through being initialised
* with the CC algo we're removing will not race with this code
@@ -886,7 +888,7 @@ tcp_ccalgounload(struct cc_algo *unload_algo)
}
INP_WUNLOCK(inp);
}
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_WUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
}
VNET_LIST_RUNLOCK();
@@ -904,7 +906,7 @@ tcp_drop(struct tcpcb *tp, int errno)
{
struct socket *so = tp->t_inpcb->inp_socket;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(tp->t_inpcb);
if (TCPS_HAVERCVDSYN(tp->t_state)) {
@@ -1071,7 +1073,7 @@ tcp_timer_discard(struct tcpcb *tp, uint32_t timer_type)
struct inpcb *inp;
CURVNET_SET(tp->t_vnet);
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
inp = tp->t_inpcb;
KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL",
__func__, tp));
@@ -1086,13 +1088,13 @@ tcp_timer_discard(struct tcpcb *tp, uint32_t timer_type)
tp->t_inpcb = NULL;
uma_zfree(V_tcpcb_zone, tp);
if (in_pcbrele_wlocked(inp)) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
return;
}
}
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
}
@@ -1106,7 +1108,7 @@ tcp_close(struct tcpcb *tp)
struct inpcb *inp = tp->t_inpcb;
struct socket *so;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
#ifdef TCP_OFFLOAD
@@ -1154,7 +1156,7 @@ tcp_drain(void)
* where we're really low on mbufs, this is potentially
* useful.
*/
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_WLOCK(&V_tcbinfo);
LIST_FOREACH(inpb, V_tcbinfo.ipi_listhead, inp_list) {
if (inpb->inp_flags & INP_TIMEWAIT)
continue;
@@ -1165,7 +1167,7 @@ tcp_drain(void)
}
INP_WUNLOCK(inpb);
}
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_WUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
}
VNET_LIST_RUNLOCK_NOSLEEP();
@@ -1184,7 +1186,7 @@ tcp_notify(struct inpcb *inp, int error)
{
struct tcpcb *tp;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
if ((inp->inp_flags & INP_TIMEWAIT) ||
@@ -1248,10 +1250,10 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
/*
* OK, now we're committed to doing something.
*/
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_LIST_RLOCK(&V_tcbinfo);
gencnt = V_tcbinfo.ipi_gencnt;
n = V_tcbinfo.ipi_count;
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_LIST_RUNLOCK(&V_tcbinfo);
m = syncache_pcbcount();
@@ -1276,7 +1278,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
if (inp_list == NULL)
return (ENOMEM);
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_INFO_WLOCK(&V_tcbinfo);
for (inp = LIST_FIRST(V_tcbinfo.ipi_listhead), i = 0;
inp != NULL && i < n; inp = LIST_NEXT(inp, inp_list)) {
INP_WLOCK(inp);
@@ -1301,7 +1303,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
}
INP_WUNLOCK(inp);
}
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_INFO_WUNLOCK(&V_tcbinfo);
n = i;
error = 0;
@@ -1339,14 +1341,14 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
} else
INP_RUNLOCK(inp);
}
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
for (i = 0; i < n; i++) {
inp = inp_list[i];
INP_RLOCK(inp);
if (!in_pcbrele_rlocked(inp))
INP_RUNLOCK(inp);
}
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
if (!error) {
/*
@@ -1356,11 +1358,11 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
* while we were processing this request, and it
* might be necessary to retry.
*/
- INP_INFO_RLOCK(&V_tcbinfo);
+ INP_LIST_RLOCK(&V_tcbinfo);
xig.xig_gen = V_tcbinfo.ipi_gencnt;
xig.xig_sogen = so_gencnt;
xig.xig_count = V_tcbinfo.ipi_count + pcb_count;
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ INP_LIST_RUNLOCK(&V_tcbinfo);
error = SYSCTL_OUT(req, &xig, sizeof xig);
}
free(inp_list, M_TEMP);
@@ -1516,7 +1518,7 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
- offsetof(struct icmp, icmp_ip));
th = (struct tcphdr *)((caddr_t)ip
+ (ip->ip_hl << 2));
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
inp = in_pcblookup(&V_tcbinfo, faddr, th->th_dport,
ip->ip_src, th->th_sport, INPLOOKUP_WLOCKPCB, NULL);
if (inp != NULL) {
@@ -1576,7 +1578,7 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
inc.inc_laddr = ip->ip_src;
syncache_unreach(&inc, th);
}
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
} else
in_pcbnotifyall(&V_tcbinfo, faddr, inetctlerrmap[cmd], notify);
}
@@ -1646,9 +1648,9 @@ tcp6_ctlinput(int cmd, struct sockaddr *sa, void *d)
inc.inc6_faddr = ((struct sockaddr_in6 *)sa)->sin6_addr;
inc.inc6_laddr = ip6cp->ip6c_src->sin6_addr;
inc.inc_flags |= INC_ISIPV6;
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
syncache_unreach(&inc, &th);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
} else
in6_pcbnotify(&V_tcbinfo, sa, 0, (const struct sockaddr *)sa6_src,
0, cmd, NULL, notify);
@@ -1781,7 +1783,7 @@ tcp_drop_syn_sent(struct inpcb *inp, int errno)
{
struct tcpcb *tp;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
if ((inp->inp_flags & INP_TIMEWAIT) ||
@@ -2339,7 +2341,7 @@ sysctl_drop(SYSCTL_HANDLER_ARGS)
default:
return (EINVAL);
}
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
switch (addrs[0].ss_family) {
#ifdef INET6
case AF_INET6:
@@ -2378,7 +2380,7 @@ sysctl_drop(SYSCTL_HANDLER_ARGS)
INP_WUNLOCK(inp);
} else
error = ESRCH;
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (error);
}
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 7d97ae0..2c853b3 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -652,6 +652,8 @@ done:
/*
* Build a new TCP socket structure from a syncache entry.
+ *
+ * On success return the newly created socket with its underlying inp locked.
*/
static struct socket *
syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
@@ -662,7 +664,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
int error;
char *s;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
/*
* Ok, create the full blown connection, and set things up
@@ -693,6 +695,15 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
inp = sotoinpcb(so);
inp->inp_inc.inc_fibnum = so->so_fibnum;
INP_WLOCK(inp);
+ /*
+ * Exclusive pcbinfo lock is not required in syncache socket case even
+ * if two inpcb locks can be acquired simultaneously:
+ * - the inpcb in LISTEN state,
+ * - the newly created inp.
+ *
+ * In this case, an inp cannot be at same time in LISTEN state and
+ * just created by an accept() call.
+ */
INP_HASH_WLOCK(&V_tcbinfo);
/* Insert new socket into PCB hash list. */
@@ -907,8 +918,6 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
tp->t_keepcnt = sototcpcb(lso)->t_keepcnt;
tcp_timer_activate(tp, TT_KEEP, TP_KEEPINIT(tp));
- INP_WUNLOCK(inp);
-
soisconnected(so);
TCPSTAT_INC(tcps_accepts);
@@ -928,6 +937,9 @@ abort2:
* in the syncache, and if its there, we pull it out of
* the cache and turn it into a full-blown connection in
* the SYN-RECEIVED state.
+ *
+ * On syncache_socket() success the newly created socket
+ * has its underlying inp locked.
*/
int
syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
@@ -942,7 +954,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* Global TCP locks are held because we manipulate the PCB lists
* and create a new socket.
*/
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
KASSERT((th->th_flags & (TH_RST|TH_ACK|TH_SYN)) == TH_ACK,
("%s: can handle only ACK", __func__));
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index d992492..e007334 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -307,7 +307,7 @@ tcp_timer_2msl(void *xtp)
ostate = tp->t_state;
#endif
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
inp = tp->t_inpcb;
KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp));
INP_WLOCK(inp);
@@ -315,14 +315,14 @@ tcp_timer_2msl(void *xtp)
if (callout_pending(&tp->t_timers->tt_2msl) ||
!callout_active(&tp->t_timers->tt_2msl)) {
INP_WUNLOCK(tp->t_inpcb);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
return;
}
callout_deactivate(&tp->t_timers->tt_2msl);
if ((inp->inp_flags & INP_DROPPED) != 0) {
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
return;
}
@@ -363,7 +363,7 @@ tcp_timer_2msl(void *xtp)
#endif
if (tp != NULL)
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
}
@@ -379,21 +379,21 @@ tcp_timer_keep(void *xtp)
ostate = tp->t_state;
#endif
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
inp = tp->t_inpcb;
KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp));
INP_WLOCK(inp);
if (callout_pending(&tp->t_timers->tt_keep) ||
!callout_active(&tp->t_timers->tt_keep)) {
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
return;
}
callout_deactivate(&tp->t_timers->tt_keep);
if ((inp->inp_flags & INP_DROPPED) != 0) {
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
return;
}
@@ -447,7 +447,7 @@ tcp_timer_keep(void *xtp)
PRU_SLOWTIMO);
#endif
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
return;
@@ -462,7 +462,7 @@ dropit:
#endif
if (tp != NULL)
INP_WUNLOCK(tp->t_inpcb);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
}
@@ -477,21 +477,21 @@ tcp_timer_persist(void *xtp)
ostate = tp->t_state;
#endif
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
inp = tp->t_inpcb;
KASSERT(inp != NULL, ("%s: tp %p tp->t_inpcb == NULL", __func__, tp));
INP_WLOCK(inp);
if (callout_pending(&tp->t_timers->tt_persist) ||
!callout_active(&tp->t_timers->tt_persist)) {
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
return;
}
callout_deactivate(&tp->t_timers->tt_persist);
if ((inp->inp_flags & INP_DROPPED) != 0) {
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
return;
}
@@ -540,7 +540,7 @@ out:
#endif
if (tp != NULL)
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
}
@@ -589,22 +589,6 @@ tcp_timer_rexmt(void * xtp)
if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
tp->t_rxtshift = TCP_MAXRXTSHIFT;
TCPSTAT_INC(tcps_timeoutdrop);
- in_pcbref(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
- INP_WUNLOCK(inp);
- INP_INFO_WLOCK(&V_tcbinfo);
- INP_WLOCK(inp);
- if (in_pcbrele_wlocked(inp)) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
- CURVNET_RESTORE();
- return;
- }
- if (inp->inp_flags & INP_DROPPED) {
- INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
- CURVNET_RESTORE();
- return;
- }
tp = tcp_drop(tp, tp->t_softerror ?
tp->t_softerror : ETIMEDOUT);
@@ -803,7 +787,7 @@ out:
if (tp != NULL)
INP_WUNLOCK(inp);
if (headlocked)
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
}
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index 1ba74d8..4685fe7 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -202,10 +202,10 @@ tcp_tw_destroy(void)
{
struct tcptw *tw;
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
while ((tw = TAILQ_FIRST(&V_twq_2msl)) != NULL)
tcp_twclose(tw, 0);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
TW_LOCK_DESTROY(V_tw_lock);
uma_zdestroy(V_tcptw_zone);
@@ -228,7 +228,7 @@ tcp_twstart(struct tcpcb *tp)
int isipv6 = inp->inp_inc.inc_flags & INC_ISIPV6;
#endif
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
if (V_nolocaltimewait) {
@@ -265,8 +265,8 @@ tcp_twstart(struct tcpcb *tp)
* allowed. Remove a connection from TIMEWAIT queue in LRU
* fashion to make room for this connection.
*
- * pcbinfo lock is needed here to prevent deadlock as
- * two inpcb locks can be acquired simultaneously.
+ * XXX: Check if it possible to always have enough room
+ * in advance based on guarantees provided by uma_zalloc().
*/
tw = tcp_tw_2msl_scan(1);
if (tw == NULL) {
@@ -367,7 +367,7 @@ tcp_twcheck(struct inpcb *inp, struct tcpopt *to __unused, struct tcphdr *th,
int thflags;
tcp_seq seq;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
/*
@@ -468,7 +468,7 @@ tcp_twclose(struct tcptw *tw, int reuse)
inp = tw->tw_inpcb;
KASSERT((inp->inp_flags & INP_TIMEWAIT), ("tcp_twclose: !timewait"));
KASSERT(intotw(inp) == tw, ("tcp_twclose: inp_ppcb != tw"));
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo); /* in_pcbfree() */
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo); /* in_pcbfree() */
INP_WLOCK_ASSERT(inp);
tcp_tw_2msl_stop(tw, reuse);
@@ -623,7 +623,7 @@ static void
tcp_tw_2msl_reset(struct tcptw *tw, int rearm)
{
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(tw->tw_inpcb);
TW_WLOCK(V_tw_lock);
@@ -641,7 +641,7 @@ tcp_tw_2msl_stop(struct tcptw *tw, int reuse)
struct inpcb *inp;
int released;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
TW_WLOCK(V_tw_lock);
inp = tw->tw_inpcb;
@@ -671,13 +671,18 @@ tcp_tw_2msl_scan(int reuse)
#ifdef INVARIANTS
if (reuse) {
/*
- * pcbinfo lock is needed in reuse case to prevent deadlock
- * as two inpcb locks can be acquired simultaneously:
+ * Exclusive pcbinfo lock is not required in reuse case even if
+ * two inpcb locks can be acquired simultaneously:
* - the inpcb transitioning to TIME_WAIT state in
* tcp_tw_start(),
* - the inpcb closed by tcp_twclose().
+ *
+ * It is because only inpcbs in FIN_WAIT2 or CLOSING states can
+ * transition in TIME_WAIT state. Then a pcbcb cannot be in
+ * TIME_WAIT list and transitioning to TIME_WAIT state at same
+ * time.
*/
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
}
#endif
@@ -695,26 +700,26 @@ tcp_tw_2msl_scan(int reuse)
in_pcbref(inp);
TW_RUNLOCK(V_tw_lock);
- if (INP_INFO_TRY_WLOCK(&V_tcbinfo)) {
+ if (INP_INFO_TRY_RLOCK(&V_tcbinfo)) {
INP_WLOCK(inp);
tw = intotw(inp);
if (in_pcbrele_wlocked(inp)) {
KASSERT(tw == NULL, ("%s: held last inp "
"reference but tw not NULL", __func__));
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
continue;
}
if (tw == NULL) {
/* tcp_twclose() has already been called */
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
continue;
}
tcp_twclose(tw, reuse);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
if (reuse)
return tw;
} else {
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 4ea39e3..36d5312 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -163,7 +163,7 @@ tcp_detach(struct socket *so, struct inpcb *inp)
{
struct tcpcb *tp;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
KASSERT(so->so_pcb == inp, ("tcp_detach: so_pcb != inp"));
@@ -192,10 +192,10 @@ tcp_detach(struct socket *so, struct inpcb *inp)
* and leave inpcb present until timewait ends
* #2 tcp_detach is called at timewait end (or reuse) by
* tcp_twclose, then the tcptw has already been discarded
- * and inpcb is freed here
+ * (or reused) and inpcb is freed here
* #3 tcp_detach is called() after timewait ends (or reuse)
* (e.g. by soclose), then tcptw has already been discarded
- * and inpcb is freed here
+ * (or reused) and inpcb is freed here
*
* In all three cases the tcptw should not be freed here.
*/
@@ -244,12 +244,12 @@ tcp_usr_detach(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_detach: inp == NULL"));
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
KASSERT(inp->inp_socket != NULL,
("tcp_usr_detach: inp_socket == NULL"));
tcp_detach(so, inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
}
#ifdef INET
@@ -611,7 +611,7 @@ tcp_usr_disconnect(struct socket *so)
int error = 0;
TCPDEBUG0;
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_disconnect: inp == NULL"));
INP_WLOCK(inp);
@@ -627,7 +627,7 @@ tcp_usr_disconnect(struct socket *so)
out:
TCPDEBUG2(PRU_DISCONNECT);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (error);
}
@@ -742,7 +742,7 @@ tcp_usr_shutdown(struct socket *so)
struct tcpcb *tp = NULL;
TCPDEBUG0;
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("inp == NULL"));
INP_WLOCK(inp);
@@ -760,7 +760,7 @@ tcp_usr_shutdown(struct socket *so)
out:
TCPDEBUG2(PRU_SHUTDOWN);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (error);
}
@@ -822,7 +822,7 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
* this call.
*/
if (flags & PRUS_EOF)
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_send: inp == NULL"));
INP_WLOCK(inp);
@@ -883,7 +883,7 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
* Close the send side of the connection after
* the data is sent.
*/
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
socantsendmore(so);
tcp_usrclosed(tp);
}
@@ -950,7 +950,7 @@ out:
((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND));
INP_WUNLOCK(inp);
if (flags & PRUS_EOF)
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (error);
}
@@ -994,7 +994,7 @@ tcp_usr_abort(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_abort: inp == NULL"));
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
KASSERT(inp->inp_socket != NULL,
("tcp_usr_abort: inp_socket == NULL"));
@@ -1016,7 +1016,7 @@ tcp_usr_abort(struct socket *so)
inp->inp_flags |= INP_SOCKREF;
}
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
}
/*
@@ -1032,7 +1032,7 @@ tcp_usr_close(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_close: inp == NULL"));
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
KASSERT(inp->inp_socket != NULL,
("tcp_usr_close: inp_socket == NULL"));
@@ -1055,7 +1055,7 @@ tcp_usr_close(struct socket *so)
inp->inp_flags |= INP_SOCKREF;
}
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
}
/*
@@ -1655,10 +1655,10 @@ tcp_attach(struct socket *so)
}
so->so_rcv.sb_flags |= SB_AUTOSIZE;
so->so_snd.sb_flags |= SB_AUTOSIZE;
- INP_INFO_WLOCK(&V_tcbinfo);
+ INP_INFO_RLOCK(&V_tcbinfo);
error = in_pcballoc(so, &V_tcbinfo);
if (error) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (error);
}
inp = sotoinpcb(so);
@@ -1674,12 +1674,12 @@ tcp_attach(struct socket *so)
if (tp == NULL) {
in_pcbdetach(inp);
in_pcbfree(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (ENOBUFS);
}
tp->t_state = TCPS_CLOSED;
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
return (0);
}
@@ -1697,7 +1697,7 @@ tcp_disconnect(struct tcpcb *tp)
struct inpcb *inp = tp->t_inpcb;
struct socket *so = inp->inp_socket;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
/*
@@ -1735,7 +1735,7 @@ static void
tcp_usrclosed(struct tcpcb *tp)
{
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(tp->t_inpcb);
switch (tp->t_state) {
@@ -1977,7 +1977,7 @@ db_print_tcpcb(struct tcpcb *tp, const char *name, int indent)
db_print_indent(indent);
db_printf("t_segq first: %p t_segqlen: %d t_dupacks: %d\n",
- tp->t_segq, tp->t_segqlen, tp->t_dupacks);
+ LIST_FIRST(&tp->t_segq), tp->t_segqlen, tp->t_dupacks);
db_print_indent(indent);
db_printf("tt_rexmt: %p tt_persist: %p tt_keep: %p\n",
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index df01735..d16f27b 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -46,6 +46,15 @@ VNET_DECLARE(int, tcp_do_rfc1323);
#endif /* _KERNEL */
+/* TCP segment queue entry */
+struct tseg_qent {
+ LIST_ENTRY(tseg_qent) tqe_q;
+ int tqe_len; /* TCP segment data length */
+ struct tcphdr *tqe_th; /* a pointer to tcp header */
+ struct mbuf *tqe_m; /* mbuf contains packet */
+};
+LIST_HEAD(tsegqe_head, tseg_qent);
+
struct sackblk {
tcp_seq start; /* start seq no. of sack block */
tcp_seq end; /* end seq no. */
@@ -91,7 +100,7 @@ do { \
* Organized for 16 byte cacheline efficiency.
*/
struct tcpcb {
- struct mbuf *t_segq; /* segment reassembly queue */
+ struct tsegqe_head t_segq; /* segment reassembly queue */
void *t_pspare[2]; /* new reassembly queue */
int t_segqlen; /* segment reassembly queue length */
int t_dupacks; /* consecutive dup acks recd */
@@ -104,7 +113,7 @@ struct tcpcb {
struct vnet *t_vnet; /* back pointer to parent vnet */
- tcp_seq snd_una; /* send unacknowledged */
+ tcp_seq snd_una; /* sent but unacknowledged */
tcp_seq snd_max; /* highest sequence number sent;
* used to recognize retransmits
*/
@@ -667,6 +676,7 @@ char *tcp_log_addrs(struct in_conninfo *, struct tcphdr *, void *,
char *tcp_log_vain(struct in_conninfo *, struct tcphdr *, void *,
const void *);
int tcp_reass(struct tcpcb *, struct tcphdr *, int *, struct mbuf *);
+void tcp_reass_global_init(void);
void tcp_reass_flush(struct tcpcb *);
int tcp_input(struct mbuf **, int *, int);
u_long tcp_maxmtu(struct in_conninfo *, struct tcp_ifcap *);
diff --git a/sys/netinet/toecore.c b/sys/netinet/toecore.c
index 1021475..5ca4604 100644
--- a/sys/netinet/toecore.c
+++ b/sys/netinet/toecore.c
@@ -339,7 +339,7 @@ toe_syncache_expand(struct in_conninfo *inc, struct tcpopt *to,
struct tcphdr *th, struct socket **lsop)
{
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
return (syncache_expand(inc, to, th, lsop, NULL));
}
@@ -370,7 +370,7 @@ toe_4tuple_check(struct in_conninfo *inc, struct tcphdr *th, struct ifnet *ifp)
if ((inp->inp_flags & INP_TIMEWAIT) && th != NULL) {
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo); /* for twcheck */
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo); /* for twcheck */
if (!tcp_twcheck(inp, NULL, th, NULL, 0))
return (EADDRINUSE);
} else {
@@ -571,7 +571,7 @@ toe_connect_failed(struct toedev *tod, struct inpcb *inp, int err)
(void) tcp_output(tp);
} else {
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+ INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
tp = tcp_drop(tp, err);
if (tp == NULL)
INP_WLOCK(inp); /* re-acquire */
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 4340150..754a5f3 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -80,6 +80,8 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/time.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/rmlock.h>
#include <sys/syslog.h>
#include <net/if.h>
@@ -1499,9 +1501,10 @@ in6ifa_ifpforlinklocal(struct ifnet *ifp, int ignoreflags)
struct in6_ifaddr *
in6ifa_ifwithaddr(const struct in6_addr *addr, uint32_t zoneid)
{
+ struct rm_priotracker in6_ifa_tracker;
struct in6_ifaddr *ia;
- IN6_IFADDR_RLOCK();
+ IN6_IFADDR_RLOCK(&in6_ifa_tracker);
LIST_FOREACH(ia, IN6ADDR_HASH(addr), ia6_hash) {
if (IN6_ARE_ADDR_EQUAL(IA6_IN6(ia), addr)) {
if (zoneid != 0 &&
@@ -1511,7 +1514,7 @@ in6ifa_ifwithaddr(const struct in6_addr *addr, uint32_t zoneid)
break;
}
}
- IN6_IFADDR_RUNLOCK();
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (ia);
}
@@ -1649,20 +1652,21 @@ ip6_sprintf(char *ip6buf, const struct in6_addr *addr)
int
in6_localaddr(struct in6_addr *in6)
{
+ struct rm_priotracker in6_ifa_tracker;
struct in6_ifaddr *ia;
if (IN6_IS_ADDR_LOOPBACK(in6) || IN6_IS_ADDR_LINKLOCAL(in6))
return 1;
- IN6_IFADDR_RLOCK();
+ IN6_IFADDR_RLOCK(&in6_ifa_tracker);
TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
&ia->ia_prefixmask.sin6_addr)) {
- IN6_IFADDR_RUNLOCK();
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return 1;
}
}
- IN6_IFADDR_RUNLOCK();
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (0);
}
@@ -1674,16 +1678,17 @@ in6_localaddr(struct in6_addr *in6)
int
in6_localip(struct in6_addr *in6)
{
+ struct rm_priotracker in6_ifa_tracker;
struct in6_ifaddr *ia;
- IN6_IFADDR_RLOCK();
+ IN6_IFADDR_RLOCK(&in6_ifa_tracker);
LIST_FOREACH(ia, IN6ADDR_HASH(in6), ia6_hash) {
if (IN6_ARE_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr)) {
- IN6_IFADDR_RUNLOCK();
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (1);
}
}
- IN6_IFADDR_RUNLOCK();
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (0);
}
@@ -1720,19 +1725,20 @@ in6_ifhasaddr(struct ifnet *ifp, struct in6_addr *addr)
int
in6_is_addr_deprecated(struct sockaddr_in6 *sa6)
{
+ struct rm_priotracker in6_ifa_tracker;
struct in6_ifaddr *ia;
- IN6_IFADDR_RLOCK();
+ IN6_IFADDR_RLOCK(&in6_ifa_tracker);
LIST_FOREACH(ia, IN6ADDR_HASH(&sa6->sin6_addr), ia6_hash) {
if (IN6_ARE_ADDR_EQUAL(IA6_IN6(ia), &sa6->sin6_addr)) {
if (ia->ia6_flags & IN6_IFF_DEPRECATED) {
- IN6_IFADDR_RUNLOCK();
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (1); /* true */
}
break;
}
}
- IN6_IFADDR_RUNLOCK();
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (0); /* false */
}
diff --git a/sys/netinet6/in6_gif.c b/sys/netinet6/in6_gif.c
index 126890f..d714f23 100644
--- a/sys/netinet6/in6_gif.c
+++ b/sys/netinet6/in6_gif.c
@@ -81,8 +81,6 @@ SYSCTL_DECL(_net_inet6_ip6);
SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(ip6_gif_hlim), 0, "");
-static int gif_validate6(const struct ip6_hdr *, struct gif_softc *,
- struct ifnet *);
static int in6_gif_input(struct mbuf **, int *, int);
extern struct domain inet6domain;
@@ -174,20 +172,26 @@ in6_gif_input(struct mbuf **mp, int *offp, int proto)
}
/*
- * validate outer address.
+ * we know that we are in IFF_UP, outer address available, and outer family
+ * matched the physical addr family. see gif_encapcheck().
*/
-static int
-gif_validate6(const struct ip6_hdr *ip6, struct gif_softc *sc,
- struct ifnet *ifp)
+int
+in6_gif_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
{
+ const struct ip6_hdr *ip6;
+ struct gif_softc *sc;
int ret;
+ /* sanity check done in caller */
+ sc = (struct gif_softc *)arg;
GIF_RLOCK_ASSERT(sc);
+
/*
* Check for address match. Note that the check is for an incoming
* packet. We should compare the *source* address in our configuration
* and the *destination* address of the packet, and vice versa.
*/
+ ip6 = mtod(m, const struct ip6_hdr *);
if (!IN6_ARE_ADDR_EQUAL(&sc->gif_ip6hdr->ip6_src, &ip6->ip6_dst))
return (0);
ret = 128;
@@ -197,10 +201,8 @@ gif_validate6(const struct ip6_hdr *ip6, struct gif_softc *sc,
} else
ret += 128;
- /* martian filters on outer source - done in ip6_input */
-
/* ingress filters on outer source */
- if ((GIF2IFP(sc)->if_flags & IFF_LINK2) == 0 && ifp) {
+ if ((GIF2IFP(sc)->if_flags & IFF_LINK2) == 0) {
struct sockaddr_in6 sin6;
struct rtentry *rt;
@@ -212,37 +214,16 @@ gif_validate6(const struct ip6_hdr *ip6, struct gif_softc *sc,
rt = in6_rtalloc1((struct sockaddr *)&sin6, 0, 0UL,
sc->gif_fibnum);
- if (!rt || rt->rt_ifp != ifp) {
- if (rt)
+ if (rt == NULL || rt->rt_ifp != m->m_pkthdr.rcvif) {
+ if (rt != NULL)
RTFREE_LOCKED(rt);
return (0);
}
RTFREE_LOCKED(rt);
}
-
return (ret);
}
-/*
- * we know that we are in IFF_UP, outer address available, and outer family
- * matched the physical addr family. see gif_encapcheck().
- */
-int
-in6_gif_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
-{
- struct ip6_hdr ip6;
- struct gif_softc *sc;
- struct ifnet *ifp;
-
- /* sanity check done in caller */
- sc = (struct gif_softc *)arg;
- GIF_RLOCK_ASSERT(sc);
-
- m_copydata(m, 0, sizeof(ip6), (caddr_t)&ip6);
- ifp = ((m->m_flags & M_PKTHDR) != 0) ? m->m_pkthdr.rcvif : NULL;
- return (gif_validate6(&ip6, sc, ifp));
-}
-
int
in6_gif_attach(struct gif_softc *sc)
{
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 8c25e98..d8a32d5 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -39,7 +39,9 @@ __FBSDID("$FreeBSD$");
#include <sys/sockio.h>
#include <sys/jail.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/proc.h>
+#include <sys/rmlock.h>
#include <sys/syslog.h>
#include <sys/md5.h>
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index 10cd3f2..9f876a4 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -789,7 +789,7 @@ in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
struct ip6_moptions *im6o;
int i, gap;
- INP_INFO_RLOCK(pcbinfo);
+ INP_INFO_WLOCK(pcbinfo);
LIST_FOREACH(in6p, pcbinfo->ipi_listhead, inp_list) {
INP_WLOCK(in6p);
im6o = in6p->in6p_moptions;
@@ -820,7 +820,7 @@ in6_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
}
INP_WUNLOCK(in6p);
}
- INP_INFO_RUNLOCK(pcbinfo);
+ INP_INFO_WUNLOCK(pcbinfo);
}
/*
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index 227f234..020c5cf 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/jail.h>
#include <sys/kernel.h>
+#include <sys/rmlock.h>
#include <sys/sx.h>
#include <net/if.h>
@@ -178,6 +179,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct inpcb *inp, struct route_in6 *ro, struct ucred *cred,
struct ifnet **ifpp, struct in6_addr *srcp)
{
+ struct rm_priotracker in6_ifa_tracker;
struct in6_addr dst, tmp;
struct ifnet *ifp = NULL, *oifp = NULL;
struct in6_ifaddr *ia = NULL, *ia_best = NULL;
@@ -303,7 +305,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
return (error);
rule = 0;
- IN6_IFADDR_RLOCK();
+ IN6_IFADDR_RLOCK(&in6_ifa_tracker);
TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
int new_scope = -1, new_matchlen = -1;
struct in6_addrpolicy *new_policy = NULL;
@@ -501,7 +503,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
}
if ((ia = ia_best) == NULL) {
- IN6_IFADDR_RUNLOCK();
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
IP6STAT_INC(ip6s_sources_none);
return (EADDRNOTAVAIL);
}
@@ -518,7 +520,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
tmp = ia->ia_addr.sin6_addr;
if (cred != NULL && prison_local_ip6(cred, &tmp, (inp != NULL &&
(inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) {
- IN6_IFADDR_RUNLOCK();
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
IP6STAT_INC(ip6s_sources_none);
return (EADDRNOTAVAIL);
}
@@ -537,7 +539,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
IP6STAT_INC(ip6s_sources_otherscope[best_scope]);
if (IFA6_IS_DEPRECATED(ia))
IP6STAT_INC(ip6s_sources_deprecated[best_scope]);
- IN6_IFADDR_RUNLOCK();
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
return (0);
}
@@ -614,82 +616,38 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
*/
if (opts && opts->ip6po_nexthop) {
struct route_in6 *ron;
- struct llentry *la;
-
- sin6_next = satosin6(opts->ip6po_nexthop);
-
- /* at this moment, we only support AF_INET6 next hops */
- if (sin6_next->sin6_family != AF_INET6) {
- error = EAFNOSUPPORT; /* or should we proceed? */
- goto done;
- }
-
- /*
- * If the next hop is an IPv6 address, then the node identified
- * by that address must be a neighbor of the sending host.
- */
- ron = &opts->ip6po_nextroute;
- /*
- * XXX what do we do here?
- * PLZ to be fixing
- */
-
- if (ron->ro_rt == NULL) {
- in6_rtalloc(ron, fibnum); /* multi path case? */
- if (ron->ro_rt == NULL) {
- /* XXX-BZ WT.? */
- if (ron->ro_rt) {
- RTFREE(ron->ro_rt);
- ron->ro_rt = NULL;
- }
- error = EHOSTUNREACH;
+ sin6_next = satosin6(opts->ip6po_nexthop);
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6_next->sin6_addr)) {
+ /*
+ * Next hop is LLA, thus it should be neighbor.
+ * Determine outgoing interface by zone index.
+ */
+ zoneid = ntohs(in6_getscope(&sin6_next->sin6_addr));
+ if (zoneid > 0) {
+ ifp = in6_getlinkifnet(zoneid);
goto done;
- }
- }
-
- rt = ron->ro_rt;
- ifp = rt->rt_ifp;
- IF_AFDATA_RLOCK(ifp);
- la = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)sin6_next);
- IF_AFDATA_RUNLOCK(ifp);
- if (la != NULL)
- LLE_RUNLOCK(la);
- else {
- error = EHOSTUNREACH;
- goto done;
- }
-#if 0
- if ((ron->ro_rt &&
- (ron->ro_rt->rt_flags & (RTF_UP | RTF_LLINFO)) !=
- (RTF_UP | RTF_LLINFO)) ||
- !IN6_ARE_ADDR_EQUAL(&satosin6(&ron->ro_dst)->sin6_addr,
- &sin6_next->sin6_addr)) {
- if (ron->ro_rt) {
- RTFREE(ron->ro_rt);
- ron->ro_rt = NULL;
}
- *satosin6(&ron->ro_dst) = *sin6_next;
}
+ ron = &opts->ip6po_nextroute;
+ /* Use a cached route if it exists and is valid. */
+ if (ron->ro_rt != NULL && (
+ (ron->ro_rt->rt_flags & RTF_UP) == 0 ||
+ ron->ro_dst.sin6_family != AF_INET6 ||
+ !IN6_ARE_ADDR_EQUAL(&ron->ro_dst.sin6_addr,
+ &sin6_next->sin6_addr)))
+ RO_RTFREE(ron);
if (ron->ro_rt == NULL) {
+ ron->ro_dst = *sin6_next;
in6_rtalloc(ron, fibnum); /* multi path case? */
- if (ron->ro_rt == NULL ||
- !(ron->ro_rt->rt_flags & RTF_LLINFO)) {
- if (ron->ro_rt) {
- RTFREE(ron->ro_rt);
- ron->ro_rt = NULL;
- }
- error = EHOSTUNREACH;
- goto done;
- }
}
-#endif
-
/*
- * When cloning is required, try to allocate a route to the
- * destination so that the caller can store path MTU
- * information.
+ * The node identified by that address must be a
+ * neighbor of the sending host.
*/
+ if (ron->ro_rt == NULL ||
+ (ron->ro_rt->rt_flags & RTF_GATEWAY) != 0)
+ error = EHOSTUNREACH;
goto done;
}
diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h
index a486ce1..81ca839 100644
--- a/sys/netinet6/in6_var.h
+++ b/sys/netinet6/in6_var.h
@@ -535,14 +535,14 @@ in6_addrhash(const struct in6_addr *in6)
return (fnv_32_buf(&x, sizeof(x), FNV1_32_INIT));
}
-extern struct rwlock in6_ifaddr_lock;
-#define IN6_IFADDR_LOCK_ASSERT( ) rw_assert(&in6_ifaddr_lock, RA_LOCKED)
-#define IN6_IFADDR_RLOCK() rw_rlock(&in6_ifaddr_lock)
-#define IN6_IFADDR_RLOCK_ASSERT() rw_assert(&in6_ifaddr_lock, RA_RLOCKED)
-#define IN6_IFADDR_RUNLOCK() rw_runlock(&in6_ifaddr_lock)
-#define IN6_IFADDR_WLOCK() rw_wlock(&in6_ifaddr_lock)
-#define IN6_IFADDR_WLOCK_ASSERT() rw_assert(&in6_ifaddr_lock, RA_WLOCKED)
-#define IN6_IFADDR_WUNLOCK() rw_wunlock(&in6_ifaddr_lock)
+extern struct rmlock in6_ifaddr_lock;
+#define IN6_IFADDR_LOCK_ASSERT() rm_assert(&in6_ifaddr_lock, RA_LOCKED)
+#define IN6_IFADDR_RLOCK(t) rm_rlock(&in6_ifaddr_lock, (t))
+#define IN6_IFADDR_RLOCK_ASSERT() rm_assert(&in6_ifaddr_lock, RA_RLOCKED)
+#define IN6_IFADDR_RUNLOCK(t) rm_runlock(&in6_ifaddr_lock, (t))
+#define IN6_IFADDR_WLOCK() rm_wlock(&in6_ifaddr_lock)
+#define IN6_IFADDR_WLOCK_ASSERT() rm_assert(&in6_ifaddr_lock, RA_WLOCKED)
+#define IN6_IFADDR_WUNLOCK() rm_wunlock(&in6_ifaddr_lock)
#define in6_ifstat_inc(ifp, tag) \
do { \
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index 78e8ef3..e4e388f 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -82,6 +82,8 @@ __FBSDID("$FreeBSD$");
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/rmlock.h>
#include <sys/syslog.h>
#include <net/if.h>
@@ -144,8 +146,8 @@ VNET_PCPUSTAT_SYSINIT(ip6stat);
VNET_PCPUSTAT_SYSUNINIT(ip6stat);
#endif /* VIMAGE */
-struct rwlock in6_ifaddr_lock;
-RW_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock");
+struct rmlock in6_ifaddr_lock;
+RM_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock");
static void ip6_init2(void *);
static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c
index ae36070..a6611a7 100644
--- a/sys/netipsec/ipsec_output.c
+++ b/sys/netipsec/ipsec_output.c
@@ -158,6 +158,8 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
tdbi->spi = sav->spi;
m_tag_prepend(m, mtag);
+ key_sa_recordxfer(sav, m); /* record data transfer */
+
/*
* If there's another (bundled) SA to apply, do so.
* Note that this puts a burden on the kernel stack size.
@@ -202,7 +204,6 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
goto bad;
}
}
- key_sa_recordxfer(sav, m); /* record data transfer */
/*
* We're done with IPsec processing, transmit the packet using the
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index 34e8c41..9927509 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -2835,7 +2835,6 @@ key_cleansav(struct secasvar *sav)
sav->tdb_xform->xf_zeroize(sav);
sav->tdb_xform = NULL;
} else {
- KASSERT(sav->iv == NULL, ("iv but no xform"));
if (sav->key_auth != NULL)
bzero(sav->key_auth->key_data, _KEYLEN(sav->key_auth));
if (sav->key_enc != NULL)
@@ -3013,7 +3012,6 @@ key_setsaval(struct secasvar *sav, struct mbuf *m,
sav->key_enc = NULL;
sav->sched = NULL;
sav->schedlen = 0;
- sav->iv = NULL;
sav->lft_c = NULL;
sav->lft_h = NULL;
sav->lft_s = NULL;
diff --git a/sys/netipsec/key_debug.c b/sys/netipsec/key_debug.c
index 97ac061..b5bdb0e 100644
--- a/sys/netipsec/key_debug.c
+++ b/sys/netipsec/key_debug.c
@@ -577,11 +577,6 @@ kdebug_secasv(struct secasvar *sav)
kdebug_sadb_key((struct sadb_ext *)sav->key_auth);
if (sav->key_enc != NULL)
kdebug_sadb_key((struct sadb_ext *)sav->key_enc);
- if (sav->iv != NULL) {
- printf(" iv=");
- ipsec_hexdump(sav->iv, sav->ivlen ? sav->ivlen : 8);
- printf("\n");
- }
if (sav->replay != NULL)
kdebug_secreplay(sav->replay);
diff --git a/sys/netipsec/keydb.h b/sys/netipsec/keydb.h
index 15dbc9c..3fe28eb 100644
--- a/sys/netipsec/keydb.h
+++ b/sys/netipsec/keydb.h
@@ -122,10 +122,10 @@ struct secasvar {
struct seckey *key_auth; /* Key for Authentication */
struct seckey *key_enc; /* Key for Encryption */
- caddr_t iv; /* Initilization Vector */
u_int ivlen; /* length of IV */
void *sched; /* intermediate encryption key */
size_t schedlen;
+ uint64_t cntr; /* counter for GCM and CTR */
struct secreplay *replay; /* replay prevention */
time_t created; /* for lifetime */
@@ -163,6 +163,12 @@ struct secasvar {
#define SECASVAR_UNLOCK(_sav) mtx_unlock(&(_sav)->lock)
#define SECASVAR_LOCK_DESTROY(_sav) mtx_destroy(&(_sav)->lock)
#define SECASVAR_LOCK_ASSERT(_sav) mtx_assert(&(_sav)->lock, MA_OWNED)
+#define SAV_ISGCM(_sav) \
+ ((_sav)->alg_enc == SADB_X_EALG_AESGCM8 || \
+ (_sav)->alg_enc == SADB_X_EALG_AESGCM12 || \
+ (_sav)->alg_enc == SADB_X_EALG_AESGCM16)
+#define SAV_ISCTR(_sav) ((_sav)->alg_enc == SADB_X_EALG_AESCTR)
+#define SAV_ISCTRORGCM(_sav) (SAV_ISCTR((_sav)) || SAV_ISGCM((_sav)))
/* replay prevention */
struct secreplay {
diff --git a/sys/netipsec/xform.h b/sys/netipsec/xform.h
index 132717f..fee457b 100644
--- a/sys/netipsec/xform.h
+++ b/sys/netipsec/xform.h
@@ -105,6 +105,7 @@ struct xformsw {
#ifdef _KERNEL
extern void xform_register(struct xformsw*);
extern int xform_init(struct secasvar *sav, int xftype);
+extern int xform_ah_authsize(struct auth_hash *esph);
struct cryptoini;
diff --git a/sys/netipsec/xform_ah.c b/sys/netipsec/xform_ah.c
index 0710578..350a735 100644
--- a/sys/netipsec/xform_ah.c
+++ b/sys/netipsec/xform_ah.c
@@ -85,8 +85,8 @@
* Return authenticator size in bytes, based on a field in the
* algorithm descriptor.
*/
-#define AUTHSIZE(sav) \
- ((sav->flags & SADB_X_EXT_OLD) ? 16 : (sav)->tdb_authalgxform->hashsize)
+#define AUTHSIZE(sav) ((sav->flags & SADB_X_EXT_OLD) ? 16 : \
+ xform_ah_authsize((sav)->tdb_authalgxform))
VNET_DEFINE(int, ah_enable) = 1; /* control flow of packets with AH */
VNET_DEFINE(int, ah_cleartos) = 1; /* clear ip_tos when doing AH calc */
@@ -112,6 +112,35 @@ static unsigned char ipseczeroes[256]; /* larger than an ip6 extension hdr */
static int ah_input_cb(struct cryptop*);
static int ah_output_cb(struct cryptop*);
+int
+xform_ah_authsize(struct auth_hash *esph)
+{
+ int alen;
+
+ if (esph == NULL)
+ return 0;
+
+ switch (esph->type) {
+ case CRYPTO_SHA2_256_HMAC:
+ case CRYPTO_SHA2_384_HMAC:
+ case CRYPTO_SHA2_512_HMAC:
+ alen = esph->hashsize / 2; /* RFC4868 2.3 */
+ break;
+
+ case CRYPTO_AES_128_NIST_GMAC:
+ case CRYPTO_AES_192_NIST_GMAC:
+ case CRYPTO_AES_256_NIST_GMAC:
+ alen = esph->hashsize;
+ break;
+
+ default:
+ alen = AH_HMAC_HASHLEN;
+ break;
+ }
+
+ return alen;
+}
+
/*
* NB: this is public for use by the PF_KEY support.
*/
@@ -748,7 +777,7 @@ ah_input_cb(struct cryptop *crp)
/* Verify authenticator. */
ptr = (caddr_t) (tc + 1);
- if (bcmp(ptr + skip + rplen, calc, authsize)) {
+ if (timingsafe_bcmp(ptr + skip + rplen, calc, authsize)) {
DPRINTF(("%s: authentication hash mismatch for packet "
"in SA %s/%08lx\n", __func__,
ipsec_address(&saidx->dst, buf, sizeof(buf)),
diff --git a/sys/netipsec/xform_esp.c b/sys/netipsec/xform_esp.c
index e0dc2b2..a48c038 100644
--- a/sys/netipsec/xform_esp.c
+++ b/sys/netipsec/xform_esp.c
@@ -48,6 +48,8 @@
#include <sys/random.h>
#include <sys/rwlock.h>
#include <sys/sysctl.h>
+#include <sys/mutex.h>
+#include <machine/atomic.h>
#include <net/if.h>
#include <net/vnet.h>
@@ -115,8 +117,6 @@ esp_algorithm_lookup(int alg)
return &enc_xform_blf;
case SADB_X_EALG_CAST128CBC:
return &enc_xform_cast5;
- case SADB_X_EALG_SKIPJACK:
- return &enc_xform_skipjack;
case SADB_EALG_NULL:
return &enc_xform_null;
case SADB_X_EALG_CAMELLIACBC:
@@ -184,12 +184,14 @@ esp_init(struct secasvar *sav, struct xformsw *xsp)
__func__, txform->name));
return EINVAL;
}
- if ((sav->flags&(SADB_X_EXT_OLD|SADB_X_EXT_IV4B)) == SADB_X_EXT_IV4B) {
+ if ((sav->flags & (SADB_X_EXT_OLD | SADB_X_EXT_IV4B)) ==
+ SADB_X_EXT_IV4B) {
DPRINTF(("%s: 4-byte IV not supported with protocol\n",
__func__));
return EINVAL;
}
- keylen = _KEYLEN(sav->key_enc);
+ /* subtract off the salt, RFC4106, 8.1 and RFC3686, 5.1 */
+ keylen = _KEYLEN(sav->key_enc) - SAV_ISCTRORGCM(sav) * 4;
if (txform->minkey > keylen || keylen > txform->maxkey) {
DPRINTF(("%s: invalid key length %u, must be in the range "
"[%u..%u] for algorithm %s\n", __func__,
@@ -204,9 +206,10 @@ esp_init(struct secasvar *sav, struct xformsw *xsp)
* the ESP header will be processed incorrectly. The
* compromise is to force it to zero here.
*/
- sav->ivlen = (txform == &enc_xform_null ? 0 : txform->ivsize);
- sav->iv = (caddr_t) malloc(sav->ivlen, M_XDATA, M_WAITOK);
- key_randomfill(sav->iv, sav->ivlen); /*XXX*/
+ if (SAV_ISCTRORGCM(sav))
+ sav->ivlen = 8; /* RFC4106 3.1 and RFC3686 3.1 */
+ else
+ sav->ivlen = (txform == &enc_xform_null ? 0 : txform->ivsize);
/*
* Setup AH-related state.
@@ -228,15 +231,15 @@ esp_init(struct secasvar *sav, struct xformsw *xsp)
*/
if (sav->alg_enc == SADB_X_EALG_AESGCM16) {
switch (keylen) {
- case AES_128_HMAC_KEY_LEN:
+ case AES_128_GMAC_KEY_LEN:
sav->alg_auth = SADB_X_AALG_AES128GMAC;
sav->tdb_authalgxform = &auth_hash_nist_gmac_aes_128;
break;
- case AES_192_HMAC_KEY_LEN:
+ case AES_192_GMAC_KEY_LEN:
sav->alg_auth = SADB_X_AALG_AES192GMAC;
sav->tdb_authalgxform = &auth_hash_nist_gmac_aes_192;
break;
- case AES_256_HMAC_KEY_LEN:
+ case AES_256_GMAC_KEY_LEN:
sav->alg_auth = SADB_X_AALG_AES256GMAC;
sav->tdb_authalgxform = &auth_hash_nist_gmac_aes_256;
break;
@@ -248,19 +251,15 @@ esp_init(struct secasvar *sav, struct xformsw *xsp)
}
bzero(&cria, sizeof(cria));
cria.cri_alg = sav->tdb_authalgxform->type;
- cria.cri_klen = _KEYBITS(sav->key_enc) + 4;
cria.cri_key = sav->key_enc->key_data;
+ cria.cri_klen = _KEYBITS(sav->key_enc) - SAV_ISGCM(sav) * 32;
}
/* Initialize crypto session. */
- bzero(&crie, sizeof (crie));
+ bzero(&crie, sizeof(crie));
crie.cri_alg = sav->tdb_encalgxform->type;
- crie.cri_klen = _KEYBITS(sav->key_enc);
crie.cri_key = sav->key_enc->key_data;
- if (sav->alg_enc == SADB_X_EALG_AESGCM16)
- arc4rand(crie.cri_iv, sav->ivlen, 0);
-
- /* XXX Rounds ? */
+ crie.cri_klen = _KEYBITS(sav->key_enc) - SAV_ISCTRORGCM(sav) * 32;
if (sav->tdb_authalgxform && sav->tdb_encalgxform) {
/* init both auth & enc */
@@ -293,10 +292,6 @@ esp_zeroize(struct secasvar *sav)
if (sav->key_enc)
bzero(sav->key_enc->key_data, _KEYLEN(sav->key_enc));
- if (sav->iv) {
- free(sav->iv, M_XDATA);
- sav->iv = NULL;
- }
sav->tdb_encalgxform = NULL;
sav->tdb_xform = NULL;
return error;
@@ -312,6 +307,7 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
struct auth_hash *esph;
struct enc_xform *espx;
struct tdb_crypto *tc;
+ uint8_t *ivp;
int plen, alen, hlen;
struct newesp *esp;
struct cryptodesc *crde;
@@ -320,7 +316,6 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
IPSEC_ASSERT(sav != NULL, ("null SA"));
IPSEC_ASSERT(sav->tdb_encalgxform != NULL, ("null encoding xform"));
- alen = 0;
/* Valid IP Packet length ? */
if ( (skip&3) || (m->m_pkthdr.len&3) ){
DPRINTF(("%s: misaligned packet, skip %u pkt len %u",
@@ -335,13 +330,13 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
esph = sav->tdb_authalgxform;
espx = sav->tdb_encalgxform;
- /* Determine the ESP header length */
+ /* Determine the ESP header and auth length */
if (sav->flags & SADB_X_EXT_OLD)
hlen = sizeof (struct esp) + sav->ivlen;
else
hlen = sizeof (struct newesp) + sav->ivlen;
- /* Authenticator hash size */
- alen = esph ? esph->hashsize : 0;
+
+ alen = xform_ah_authsize(esph);
/*
* Verify payload length is multiple of encryption algorithm
@@ -353,15 +348,13 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
*/
plen = m->m_pkthdr.len - (skip + hlen + alen);
if ((plen & (espx->blocksize - 1)) || (plen <= 0)) {
- if (!espx || sav->alg_enc != SADB_X_EALG_AESGCM16) {
- DPRINTF(("%s: payload of %d octets not a multiple of %d octets,"
- " SA %s/%08lx\n", __func__,
- plen, espx->blocksize, ipsec_address(&sav->sah->saidx.dst,
- buf, sizeof(buf)), (u_long) ntohl(sav->spi)));
- ESPSTAT_INC(esps_badilen);
- m_freem(m);
- return EINVAL;
- }
+ DPRINTF(("%s: payload of %d octets not a multiple of %d octets,"
+ " SA %s/%08lx\n", __func__, plen, espx->blocksize,
+ ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
+ (u_long)ntohl(sav->spi)));
+ ESPSTAT_INC(esps_badilen);
+ m_freem(m);
+ return EINVAL;
}
/*
@@ -407,20 +400,13 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
/* Authentication descriptor */
crda->crd_skip = skip;
- if (espx && espx->type == CRYPTO_AES_NIST_GCM_16)
- crda->crd_len = hlen - sav->ivlen;
+ if (SAV_ISGCM(sav))
+ crda->crd_len = 8; /* RFC4106 5, SPI + SN */
else
crda->crd_len = m->m_pkthdr.len - (skip + alen);
crda->crd_inject = m->m_pkthdr.len - alen;
crda->crd_alg = esph->type;
- if (espx && (espx->type == CRYPTO_AES_NIST_GCM_16)) {
- crda->crd_key = sav->key_enc->key_data;
- crda->crd_klen = _KEYBITS(sav->key_enc);
- } else {
- crda->crd_key = sav->key_auth->key_data;
- crda->crd_klen = _KEYBITS(sav->key_auth);
- }
/* Copy the authenticator */
m_copydata(m, m->m_pkthdr.len - alen, alen,
@@ -455,13 +441,26 @@ esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen);
crde->crd_inject = skip + hlen - sav->ivlen;
- crde->crd_alg = espx->type;
- crde->crd_key = sav->key_enc->key_data;
- crde->crd_klen = _KEYBITS(sav->key_enc);
- if (espx && (espx->type == CRYPTO_AES_NIST_GCM_16))
+ if (SAV_ISCTRORGCM(sav)) {
+ ivp = &crde->crd_iv[0];
+
+ /* GCM IV Format: RFC4106 4 */
+ /* CTR IV Format: RFC3686 4 */
+ /* Salt is last four bytes of key, RFC4106 8.1 */
+ /* Nonce is last four bytes of key, RFC3686 5.1 */
+ memcpy(ivp, sav->key_enc->key_data +
+ _KEYLEN(sav->key_enc) - 4, 4);
+
+ if (SAV_ISCTR(sav)) {
+ /* Initial block counter is 1, RFC3686 4 */
+ be32enc(&ivp[sav->ivlen + 4], 1);
+ }
+
+ m_copydata(m, skip + hlen - sav->ivlen, sav->ivlen, &ivp[4]);
crde->crd_flags |= CRD_F_IV_EXPLICIT;
+ }
- /* XXX Rounds ? */
+ crde->crd_alg = espx->type;
return (crypto_dispatch(crp));
}
@@ -530,14 +529,14 @@ esp_input_cb(struct cryptop *crp)
/* If authentication was performed, check now. */
if (esph != NULL) {
- alen = esph->hashsize;
+ alen = xform_ah_authsize(esph);
AHSTAT_INC(ahs_hist[sav->alg_auth]);
/* Copy the authenticator from the packet */
m_copydata(m, m->m_pkthdr.len - alen, alen, aalg);
ptr = (caddr_t) (tc + 1);
/* Verify authenticator */
- if (bcmp(ptr, aalg, alen) != 0) {
+ if (timingsafe_bcmp(ptr, aalg, alen) != 0) {
DPRINTF(("%s: authentication hash mismatch for "
"packet in SA %s/%08lx\n", __func__,
ipsec_address(&saidx->dst, buf, sizeof(buf)),
@@ -667,6 +666,8 @@ esp_output(struct mbuf *m, struct ipsecrequest *isr, struct mbuf **mp,
char buf[INET6_ADDRSTRLEN];
struct enc_xform *espx;
struct auth_hash *esph;
+ uint8_t *ivp;
+ uint64_t cntr;
int hlen, rlen, padding, blks, alen, i, roff;
struct mbuf *mo = (struct mbuf *) NULL;
struct tdb_crypto *tc;
@@ -692,18 +693,14 @@ esp_output(struct mbuf *m, struct ipsecrequest *isr, struct mbuf **mp,
rlen = m->m_pkthdr.len - skip; /* Raw payload length. */
/*
- * NB: The null encoding transform has a blocksize of 4
- * so that headers are properly aligned.
+ * RFC4303 2.4 Requires 4 byte alignment.
*/
- blks = espx->ivsize; /* IV blocksize */
+ blks = MAX(4, espx->blocksize); /* Cipher blocksize */
/* XXX clamp padding length a la KAME??? */
padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
- if (esph)
- alen = esph->hashsize;
- else
- alen = 0;
+ alen = xform_ah_authsize(esph);
ESPSTAT_INC(esps_output);
@@ -822,7 +819,7 @@ esp_output(struct mbuf *m, struct ipsecrequest *isr, struct mbuf **mp,
m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot);
/* Get crypto descriptors. */
- crp = crypto_getreq(esph && espx ? 2 : 1);
+ crp = crypto_getreq(esph != NULL ? 2 : 1);
if (crp == NULL) {
DPRINTF(("%s: failed to acquire crypto descriptors\n",
__func__));
@@ -831,29 +828,9 @@ esp_output(struct mbuf *m, struct ipsecrequest *isr, struct mbuf **mp,
goto bad;
}
- if (espx) {
- crde = crp->crp_desc;
- crda = crde->crd_next;
-
- /* Encryption descriptor. */
- crde->crd_skip = skip + hlen;
- crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen);
- crde->crd_flags = CRD_F_ENCRYPT;
- crde->crd_inject = skip + hlen - sav->ivlen;
-
- /* Encryption operation. */
- crde->crd_alg = espx->type;
- crde->crd_key = sav->key_enc->key_data;
- crde->crd_klen = _KEYBITS(sav->key_enc);
- if (espx->type == CRYPTO_AES_NIST_GCM_16)
- crde->crd_flags |= CRD_F_IV_EXPLICIT;
- /* XXX Rounds ? */
- } else
- crda = crp->crp_desc;
-
/* IPsec-specific opaque crypto info. */
tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto),
- M_XDATA, M_NOWAIT|M_ZERO);
+ M_XDATA, M_NOWAIT|M_ZERO);
if (tc == NULL) {
crypto_freereq(crp);
DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
@@ -862,6 +839,40 @@ esp_output(struct mbuf *m, struct ipsecrequest *isr, struct mbuf **mp,
goto bad;
}
+ crde = crp->crp_desc;
+ crda = crde->crd_next;
+
+ /* Encryption descriptor. */
+ crde->crd_skip = skip + hlen;
+ crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen);
+ crde->crd_flags = CRD_F_ENCRYPT;
+ crde->crd_inject = skip + hlen - sav->ivlen;
+
+ /* Encryption operation. */
+ crde->crd_alg = espx->type;
+ if (SAV_ISCTRORGCM(sav)) {
+ ivp = &crde->crd_iv[0];
+
+ /* GCM IV Format: RFC4106 4 */
+ /* CTR IV Format: RFC3686 4 */
+ /* Salt is last four bytes of key, RFC4106 8.1 */
+ /* Nonce is last four bytes of key, RFC3686 5.1 */
+ memcpy(ivp, sav->key_enc->key_data +
+ _KEYLEN(sav->key_enc) - 4, 4);
+ SECASVAR_LOCK(sav);
+ cntr = sav->cntr++;
+ SECASVAR_UNLOCK(sav);
+ be64enc(&ivp[4], cntr);
+
+ if (SAV_ISCTR(sav)) {
+ /* Initial block counter is 1, RFC3686 4 */
+ be32enc(&ivp[sav->ivlen + 4], 1);
+ }
+
+ m_copyback(m, skip + hlen - sav->ivlen, sav->ivlen, &ivp[4]);
+ crde->crd_flags |= CRD_F_IV_EXPLICIT|CRD_F_IV_PRESENT;
+ }
+
/* Callback parameters */
tc->tc_isr = isr;
KEY_ADDREFSA(sav);
@@ -880,23 +891,13 @@ esp_output(struct mbuf *m, struct ipsecrequest *isr, struct mbuf **mp,
if (esph) {
/* Authentication descriptor. */
+ crda->crd_alg = esph->type;
crda->crd_skip = skip;
- if (espx && espx->type == CRYPTO_AES_NIST_GCM_16)
- crda->crd_len = hlen - sav->ivlen;
+ if (SAV_ISGCM(sav))
+ crda->crd_len = 8; /* RFC4106 5, SPI + SN */
else
crda->crd_len = m->m_pkthdr.len - (skip + alen);
crda->crd_inject = m->m_pkthdr.len - alen;
-
- /* Authentication operation. */
- crda->crd_alg = esph->type;
- if (espx && espx->type == CRYPTO_AES_NIST_GCM_16) {
- crda->crd_key = sav->key_enc->key_data;
- crda->crd_klen = _KEYBITS(sav->key_enc);
- } else {
- crda->crd_key = sav->key_auth->key_data;
- crda->crd_klen = _KEYBITS(sav->key_auth);
- }
-
}
return crypto_dispatch(crp);
@@ -927,7 +928,8 @@ esp_output_cb(struct cryptop *crp)
IPSEC_ASSERT(isr->sp != NULL, ("NULL isr->sp"));
IPSECREQUEST_LOCK(isr);
sav = tc->tc_sav;
- /* With the isr lock released SA pointer can be updated. */
+
+ /* With the isr lock released, SA pointer may have changed. */
if (sav != isr->sav) {
ESPSTAT_INC(esps_notdb);
DPRINTF(("%s: SA gone during crypto (SA %s/%08lx proto %u)\n",
@@ -983,21 +985,7 @@ esp_output_cb(struct cryptop *crp)
if (esph != NULL) {
int alen;
- switch (esph->type) {
- case CRYPTO_SHA2_256_HMAC:
- case CRYPTO_SHA2_384_HMAC:
- case CRYPTO_SHA2_512_HMAC:
- alen = esph->hashsize/2;
- break;
- case CRYPTO_AES_128_NIST_GMAC:
- case CRYPTO_AES_192_NIST_GMAC:
- case CRYPTO_AES_256_NIST_GMAC:
- alen = esph->hashsize;
- break;
- default:
- alen = AH_HMAC_HASHLEN;
- break;
- }
+ alen = xform_ah_authsize(esph);
m_copyback(m, m->m_pkthdr.len - alen,
alen, ipseczeroes);
}
diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c
index afa3944..e32c7cc 100644
--- a/sys/netpfil/ipfw/ip_fw2.c
+++ b/sys/netpfil/ipfw/ip_fw2.c
@@ -503,31 +503,35 @@ flow6id_match( int curr_flow, ipfw_insn_u32 *cmd )
}
/* support for IP6_*_ME opcodes */
+static const struct in6_addr lla_mask = {{{
+ 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+}}};
+
static int
-search_ip6_addr_net (struct in6_addr * ip6_addr)
+ipfw_localip6(struct in6_addr *in6)
{
- struct ifnet *mdc;
- struct ifaddr *mdc2;
- struct in6_ifaddr *fdm;
- struct in6_addr copia;
-
- TAILQ_FOREACH(mdc, &V_ifnet, if_link) {
- if_addr_rlock(mdc);
- TAILQ_FOREACH(mdc2, &mdc->if_addrhead, ifa_link) {
- if (mdc2->ifa_addr->sa_family == AF_INET6) {
- fdm = (struct in6_ifaddr *)mdc2;
- copia = fdm->ia_addr.sin6_addr;
- /* need for leaving scope_id in the sock_addr */
- in6_clearscope(&copia);
- if (IN6_ARE_ADDR_EQUAL(ip6_addr, &copia)) {
- if_addr_runlock(mdc);
- return 1;
- }
- }
+ struct rm_priotracker in6_ifa_tracker;
+ struct in6_ifaddr *ia;
+
+ if (IN6_IS_ADDR_MULTICAST(in6))
+ return (0);
+
+ if (!IN6_IS_ADDR_LINKLOCAL(in6))
+ return (in6_localip(in6));
+
+ IN6_IFADDR_RLOCK(&in6_ifa_tracker);
+ TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
+ if (!IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr))
+ continue;
+ if (IN6_ARE_MASKED_ADDR_EQUAL(&ia->ia_addr.sin6_addr,
+ in6, &lla_mask)) {
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
+ return (1);
}
- if_addr_runlock(mdc);
}
- return 0;
+ IN6_IFADDR_RUNLOCK(&in6_ifa_tracker);
+ return (0);
}
static int
@@ -1597,7 +1601,7 @@ do { \
#ifdef INET6
/* FALLTHROUGH */
case O_IP6_SRC_ME:
- match= is_ipv6 && search_ip6_addr_net(&args->f_id.src_ip6);
+ match= is_ipv6 && ipfw_localip6(&args->f_id.src_ip6);
#endif
break;
@@ -1636,7 +1640,7 @@ do { \
#ifdef INET6
/* FALLTHROUGH */
case O_IP6_DST_ME:
- match= is_ipv6 && search_ip6_addr_net(&args->f_id.dst_ip6);
+ match= is_ipv6 && ipfw_localip6(&args->f_id.dst_ip6);
#endif
break;
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 81d010f..fba0432 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -3681,7 +3681,7 @@ csfailed:
sh = &V_pf_srchash[pf_hashsrc(&nsn->addr, nsn->af)];
PF_HASHROW_LOCK(sh);
- if (--nsn->states == 1 && nsn->expire == 0) {
+ if (--nsn->states == 0 && nsn->expire == 0) {
pf_unlink_src_node(nsn);
uma_zfree(V_pf_sources_z, nsn);
counter_u64_add(
@@ -5895,7 +5895,7 @@ done:
!((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) {
action = PF_DROP;
REASON_SET(&reason, PFRES_IPOPTIONS);
- log = 1;
+ log = r->log;
DPFPRINTF(PF_DEBUG_MISC,
("pf: dropping packet with ip options\n"));
}
@@ -6329,7 +6329,7 @@ done:
!((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) {
action = PF_DROP;
REASON_SET(&reason, PFRES_IPOPTIONS);
- log = 1;
+ log = r->log;
DPFPRINTF(PF_DEBUG_MISC,
("pf: dropping packet with dangerous v6 headers\n"));
}
diff --git a/sys/netpfil/pf/pf_norm.c b/sys/netpfil/pf/pf_norm.c
index 384f565..497f0ed 100644
--- a/sys/netpfil/pf/pf_norm.c
+++ b/sys/netpfil/pf/pf_norm.c
@@ -431,6 +431,7 @@ pf_fillup_fragment(struct pf_fragment_cmp *key, struct pf_frent *frent,
}
*(struct pf_fragment_cmp *)frag = *key;
+ frag->fr_flags = 0;
frag->fr_timeout = time_second;
frag->fr_maxlen = frent->fe_len;
TAILQ_INIT(&frag->fr_queue);
@@ -1284,9 +1285,6 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
if (m == NULL)
return (PF_DROP);
- if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
- goto drop;
-
h = mtod(m, struct ip *);
} else {
/* non-buffering fragment cache (drops or masks overlaps) */
diff --git a/sys/ofed/drivers/infiniband/core/mad.c b/sys/ofed/drivers/infiniband/core/mad.c
index 11b3ba3..3eedca1 100644
--- a/sys/ofed/drivers/infiniband/core/mad.c
+++ b/sys/ofed/drivers/infiniband/core/mad.c
@@ -292,6 +292,7 @@ static struct tf_entry *tf_dequeue(struct to_fifo *tf, u32 *time_left_ms)
unsigned long flags;
unsigned long time_left;
struct tf_entry *tmp, *tmp1;
+ bool found = false;
spin_lock_irqsave(&tf->lists_lock, flags);
if (list_empty(&tf->fifo_head)) {
@@ -300,11 +301,13 @@ static struct tf_entry *tf_dequeue(struct to_fifo *tf, u32 *time_left_ms)
}
list_for_each_entry(tmp, &tf->fifo_head, fifo_list) {
- if (!tmp->canceled)
+ if (!tmp->canceled) {
+ found = true;
break;
+ }
}
- if (tmp->canceled) {
+ if (!found) {
spin_unlock_irqrestore(&tf->lists_lock, flags);
return NULL;
}
diff --git a/sys/ofed/drivers/net/mlx4/en_tx.c b/sys/ofed/drivers/net/mlx4/en_tx.c
index 2d7e8a8..2565f51 100644
--- a/sys/ofed/drivers/net/mlx4/en_tx.c
+++ b/sys/ofed/drivers/net/mlx4/en_tx.c
@@ -701,9 +701,13 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct mbuf *mb,
static uint32_t hashrandom;
static void hashrandom_init(void *arg)
{
+ /*
+ * It is assumed that the random subsystem has been
+ * initialized when this function is called:
+ */
hashrandom = m_ether_tcpip_hash_init();
}
-SYSINIT(hashrandom_init, SI_SUB_KLD, SI_ORDER_SECOND, &hashrandom_init, NULL);
+SYSINIT(hashrandom_init, SI_SUB_RANDOM, SI_ORDER_ANY, &hashrandom_init, NULL);
u16 mlx4_en_select_queue(struct net_device *dev, struct mbuf *mb)
{
diff --git a/sys/ofed/include/linux/in.h b/sys/ofed/include/linux/in.h
index d3e8add..102563f 100644
--- a/sys/ofed/include/linux/in.h
+++ b/sys/ofed/include/linux/in.h
@@ -37,7 +37,7 @@
#include <netinet/in.h>
#include <asm/byteorder.h>
-#define ipv4_is_zeronet IN_ZERONET
-#define ipv4_is_loopback IN_LOOPBACK
+#define ipv4_is_zeronet(be) IN_ZERONET(ntohl(be))
+#define ipv4_is_loopback(be) IN_LOOPBACK(ntohl(be))
#endif /* _LINUX_IN_H_ */
diff --git a/sys/opencrypto/cryptodev.h b/sys/opencrypto/cryptodev.h
index 5aa450f..d14fb3a 100644
--- a/sys/opencrypto/cryptodev.h
+++ b/sys/opencrypto/cryptodev.h
@@ -78,7 +78,7 @@
#define SHA2_512_HASH_LEN 64
#define MD5_KPDK_HASH_LEN 16
#define SHA1_KPDK_HASH_LEN 20
-#define AES_HASH_LEN 16
+#define AES_GMAC_HASH_LEN 16
/* Maximum hash algorithm result length */
#define HASH_MAX_LEN SHA2_512_HASH_LEN /* Keep this updated */
@@ -102,12 +102,12 @@
#define SHA2_256_HMAC_KEY_LEN 32
#define SHA2_384_HMAC_KEY_LEN 48
#define SHA2_512_HMAC_KEY_LEN 64
-#define AES_128_HMAC_KEY_LEN 16
-#define AES_192_HMAC_KEY_LEN 24
-#define AES_256_HMAC_KEY_LEN 32
+#define AES_128_GMAC_KEY_LEN 16
+#define AES_192_GMAC_KEY_LEN 24
+#define AES_256_GMAC_KEY_LEN 32
/* Encryption algorithm block sizes */
-#define NULL_BLOCK_LEN 4
+#define NULL_BLOCK_LEN 4 /* IPsec to maintain alignment */
#define DES_BLOCK_LEN 8
#define DES3_BLOCK_LEN 8
#define BLOWFISH_BLOCK_LEN 8
diff --git a/sys/opencrypto/cryptosoft.c b/sys/opencrypto/cryptosoft.c
index 77ab507..052916b 100644
--- a/sys/opencrypto/cryptosoft.c
+++ b/sys/opencrypto/cryptosoft.c
@@ -711,6 +711,7 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
struct enc_xform *txf;
struct comp_algo *cxf;
u_int32_t i;
+ int len;
int error;
if (sid == NULL || cri == NULL)
@@ -928,6 +929,10 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
case CRYPTO_AES_256_NIST_GMAC:
axf = &auth_hash_nist_gmac_aes_256;
auth4common:
+ len = cri->cri_klen / 8;
+ if (len != 16 && len != 24 && len != 32)
+ return EINVAL;
+
(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
if ((*swd)->sw_ictx == NULL) {
@@ -936,8 +941,7 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
return ENOBUFS;
}
axf->Init((*swd)->sw_ictx);
- axf->Setkey((*swd)->sw_ictx, cri->cri_key,
- cri->cri_klen / 8);
+ axf->Setkey((*swd)->sw_ictx, cri->cri_key, len);
(*swd)->sw_axf = axf;
break;
diff --git a/sys/opencrypto/xform.c b/sys/opencrypto/xform.c
index 9e8a1c1..cb44bfa 100644
--- a/sys/opencrypto/xform.c
+++ b/sys/opencrypto/xform.c
@@ -139,7 +139,7 @@ static int SHA512Update_int(void *, const u_int8_t *, u_int16_t);
static u_int32_t deflate_compress(u_int8_t *, u_int32_t, u_int8_t **);
static u_int32_t deflate_decompress(u_int8_t *, u_int32_t, u_int8_t **);
-#define AESICM_BLOCKSIZE 16
+#define AESICM_BLOCKSIZE AES_BLOCK_LEN
struct aes_icm_ctx {
u_int32_t ac_ek[4*(RIJNDAEL_MAXNR + 1)];
@@ -353,7 +353,7 @@ struct auth_hash auth_hash_hmac_sha2_512 = {
struct auth_hash auth_hash_nist_gmac_aes_128 = {
CRYPTO_AES_128_NIST_GMAC, "GMAC-AES-128",
- AES_128_HMAC_KEY_LEN, AES_HASH_LEN, sizeof(struct aes_gmac_ctx),
+ AES_128_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx),
GMAC_BLOCK_LEN,
(void (*)(void *)) AES_GMAC_Init,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey,
@@ -364,7 +364,7 @@ struct auth_hash auth_hash_nist_gmac_aes_128 = {
struct auth_hash auth_hash_nist_gmac_aes_192 = {
CRYPTO_AES_192_NIST_GMAC, "GMAC-AES-192",
- AES_192_HMAC_KEY_LEN, AES_HASH_LEN, sizeof(struct aes_gmac_ctx),
+ AES_192_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx),
GMAC_BLOCK_LEN,
(void (*)(void *)) AES_GMAC_Init,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey,
@@ -375,7 +375,7 @@ struct auth_hash auth_hash_nist_gmac_aes_192 = {
struct auth_hash auth_hash_nist_gmac_aes_256 = {
CRYPTO_AES_256_NIST_GMAC, "GMAC-AES-256",
- AES_256_HMAC_KEY_LEN, AES_HASH_LEN, sizeof(struct aes_gmac_ctx),
+ AES_256_GMAC_KEY_LEN, AES_GMAC_HASH_LEN, sizeof(struct aes_gmac_ctx),
GMAC_BLOCK_LEN,
(void (*)(void *)) AES_GMAC_Init,
(void (*)(void *, const u_int8_t *, u_int16_t)) AES_GMAC_Setkey,
@@ -719,6 +719,9 @@ aes_icm_setkey(u_int8_t **sched, u_int8_t *key, int len)
{
struct aes_icm_ctx *ctx;
+ if (len != 16 && len != 24 && len != 32)
+ return EINVAL;
+
*sched = malloc(sizeof(struct aes_icm_ctx), M_CRYPTO_DATA,
M_NOWAIT | M_ZERO);
if (*sched == NULL)
@@ -726,8 +729,6 @@ aes_icm_setkey(u_int8_t **sched, u_int8_t *key, int len)
ctx = (struct aes_icm_ctx *)*sched;
ctx->ac_nr = rijndaelKeySetupEnc(ctx->ac_ek, (u_char *)key, len * 8);
- if (ctx->ac_nr == 0)
- return EINVAL;
return 0;
}
diff --git a/sys/pc98/include/privatespace.h b/sys/pc98/include/privatespace.h
deleted file mode 100644
index 5db57c3..0000000
--- a/sys/pc98/include/privatespace.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/*-
- * This file is in the public domain.
- */
-/* $FreeBSD$ */
-
-#include <i386/privatespace.h>
diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c
index 6d4ddeb..4734738 100644
--- a/sys/powerpc/aim/mmu_oea.c
+++ b/sys/powerpc/aim/mmu_oea.c
@@ -316,6 +316,8 @@ boolean_t moea_dev_direct_mapped(mmu_t, vm_paddr_t, vm_size_t);
static void moea_sync_icache(mmu_t, pmap_t, vm_offset_t, vm_size_t);
void moea_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz, void **va);
void moea_scan_init(mmu_t mmu);
+vm_offset_t moea_quick_enter_page(mmu_t mmu, vm_page_t m);
+void moea_quick_remove_page(mmu_t mmu, vm_offset_t addr);
static mmu_method_t moea_methods[] = {
MMUMETHOD(mmu_clear_modify, moea_clear_modify),
@@ -351,6 +353,8 @@ static mmu_method_t moea_methods[] = {
MMUMETHOD(mmu_activate, moea_activate),
MMUMETHOD(mmu_deactivate, moea_deactivate),
MMUMETHOD(mmu_page_set_memattr, moea_page_set_memattr),
+ MMUMETHOD(mmu_quick_enter_page, moea_quick_enter_page),
+ MMUMETHOD(mmu_quick_remove_page, moea_quick_remove_page),
/* Internal interfaces */
MMUMETHOD(mmu_bootstrap, moea_bootstrap),
@@ -1082,6 +1086,18 @@ moea_zero_page_idle(mmu_t mmu, vm_page_t m)
moea_zero_page(mmu, m);
}
+vm_offset_t
+moea_quick_enter_page(mmu_t mmu, vm_page_t m)
+{
+
+ return (VM_PAGE_TO_PHYS(m));
+}
+
+void
+moea_quick_remove_page(mmu_t mmu, vm_offset_t addr)
+{
+}
+
/*
* Map the given physical page at the specified virtual address in the
* target pmap with the protection requested. If specified the page
diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c
index 9471c24..44caec6 100644
--- a/sys/powerpc/aim/mmu_oea64.c
+++ b/sys/powerpc/aim/mmu_oea64.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/vmmeter.h>
+#include <sys/smp.h>
#include <sys/kdb.h>
@@ -227,6 +228,7 @@ static u_int moea64_clear_bit(mmu_t, vm_page_t, uint64_t);
static void moea64_kremove(mmu_t, vm_offset_t);
static void moea64_syncicache(mmu_t, pmap_t pmap, vm_offset_t va,
vm_paddr_t pa, vm_size_t sz);
+static void moea64_pmap_init_qpages(void);
/*
* Kernel MMU interface
@@ -278,6 +280,8 @@ static void moea64_sync_icache(mmu_t, pmap_t, vm_offset_t, vm_size_t);
void moea64_dumpsys_map(mmu_t mmu, vm_paddr_t pa, size_t sz,
void **va);
void moea64_scan_init(mmu_t mmu);
+vm_offset_t moea64_quick_enter_page(mmu_t mmu, vm_page_t m);
+void moea64_quick_remove_page(mmu_t mmu, vm_offset_t addr);
static mmu_method_t moea64_methods[] = {
MMUMETHOD(mmu_clear_modify, moea64_clear_modify),
@@ -314,6 +318,8 @@ static mmu_method_t moea64_methods[] = {
MMUMETHOD(mmu_activate, moea64_activate),
MMUMETHOD(mmu_deactivate, moea64_deactivate),
MMUMETHOD(mmu_page_set_memattr, moea64_page_set_memattr),
+ MMUMETHOD(mmu_quick_enter_page, moea64_quick_enter_page),
+ MMUMETHOD(mmu_quick_remove_page, moea64_quick_remove_page),
/* Internal interfaces */
MMUMETHOD(mmu_mapdev, moea64_mapdev),
@@ -974,6 +980,29 @@ moea64_late_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend
}
}
+static void
+moea64_pmap_init_qpages(void)
+{
+ struct pcpu *pc;
+ int i;
+
+ if (hw_direct_map)
+ return;
+
+ CPU_FOREACH(i) {
+ pc = pcpu_find(i);
+ pc->pc_qmap_addr = kva_alloc(PAGE_SIZE);
+ if (pc->pc_qmap_addr == 0)
+ panic("pmap_init_qpages: unable to allocate KVA");
+ PMAP_LOCK(kernel_pmap);
+ pc->pc_qmap_pvo = moea64_pvo_find_va(kernel_pmap, pc->pc_qmap_addr);
+ PMAP_UNLOCK(kernel_pmap);
+ mtx_init(&pc->pc_qmap_lock, "qmap lock", NULL, MTX_DEF);
+ }
+}
+
+SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, moea64_pmap_init_qpages, NULL);
+
/*
* Activate a user pmap. This mostly involves setting some non-CPU
* state.
@@ -1206,6 +1235,48 @@ moea64_zero_page_idle(mmu_t mmu, vm_page_t m)
moea64_zero_page(mmu, m);
}
+vm_offset_t
+moea64_quick_enter_page(mmu_t mmu, vm_page_t m)
+{
+ struct pvo_entry *pvo;
+ vm_paddr_t pa = VM_PAGE_TO_PHYS(m);
+
+ if (hw_direct_map)
+ return (pa);
+
+ /*
+ * MOEA64_PTE_REPLACE does some locking, so we can't just grab
+ * a critical section and access the PCPU data like on i386.
+ * Instead, pin the thread and grab the PCPU lock to prevent
+ * a preempting thread from using the same PCPU data.
+ */
+ sched_pin();
+
+ mtx_assert(PCPU_PTR(qmap_lock), MA_NOTOWNED);
+ pvo = PCPU_GET(qmap_pvo);
+
+ mtx_lock(PCPU_PTR(qmap_lock));
+ pvo->pvo_pte.pa = moea64_calc_wimg(pa, pmap_page_get_memattr(m)) |
+ (uint64_t)pa;
+ MOEA64_PTE_REPLACE(mmu, pvo, MOEA64_PTE_INVALIDATE);
+ isync();
+
+ return (PCPU_GET(qmap_addr));
+}
+
+void
+moea64_quick_remove_page(mmu_t mmu, vm_offset_t addr)
+{
+ if (hw_direct_map)
+ return;
+
+ mtx_assert(PCPU_PTR(qmap_lock), MA_OWNED);
+ KASSERT(PCPU_GET(qmap_addr) == addr,
+ ("moea64_quick_remove_page: invalid address"));
+ mtx_unlock(PCPU_PTR(qmap_lock));
+ sched_unpin();
+}
+
/*
* Map the given physical page at the specified virtual address in the
* target pmap with the protection requested. If specified the page
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index 656b7a3..275ae8d 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -246,6 +246,8 @@ static void pv_free(pv_entry_t);
static void pv_insert(pmap_t, vm_offset_t, vm_page_t);
static void pv_remove(pmap_t, vm_offset_t, vm_page_t);
+static void booke_pmap_init_qpages(void);
+
/* Number of kva ptbl buffers, each covering one ptbl (PTBL_PAGES). */
#define PTBL_BUFS (128 * 16)
@@ -332,6 +334,8 @@ static void mmu_booke_dumpsys_map(mmu_t, vm_paddr_t pa, size_t,
static void mmu_booke_dumpsys_unmap(mmu_t, vm_paddr_t pa, size_t,
void *);
static void mmu_booke_scan_init(mmu_t);
+static vm_offset_t mmu_booke_quick_enter_page(mmu_t mmu, vm_page_t m);
+static void mmu_booke_quick_remove_page(mmu_t mmu, vm_offset_t addr);
static mmu_method_t mmu_booke_methods[] = {
/* pmap dispatcher interface */
@@ -371,6 +375,8 @@ static mmu_method_t mmu_booke_methods[] = {
MMUMETHOD(mmu_zero_page_idle, mmu_booke_zero_page_idle),
MMUMETHOD(mmu_activate, mmu_booke_activate),
MMUMETHOD(mmu_deactivate, mmu_booke_deactivate),
+ MMUMETHOD(mmu_quick_enter_page, mmu_booke_quick_enter_page),
+ MMUMETHOD(mmu_quick_remove_page, mmu_booke_quick_remove_page),
/* Internal interfaces */
MMUMETHOD(mmu_bootstrap, mmu_booke_bootstrap),
@@ -1351,6 +1357,22 @@ pmap_bootstrap_ap(volatile uint32_t *trcp __unused)
}
#endif
+static void
+booke_pmap_init_qpages(void)
+{
+ struct pcpu *pc;
+ int i;
+
+ CPU_FOREACH(i) {
+ pc = pcpu_find(i);
+ pc->pc_qmap_addr = kva_alloc(PAGE_SIZE);
+ if (pc->pc_qmap_addr == 0)
+ panic("pmap_init_qpages: unable to allocate KVA");
+ }
+}
+
+SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, booke_pmap_init_qpages, NULL);
+
/*
* Get the physical page address for the given pmap/virtual address.
*/
@@ -2272,6 +2294,61 @@ mmu_booke_zero_page_idle(mmu_t mmu, vm_page_t m)
mmu_booke_kremove(mmu, va);
}
+static vm_offset_t
+mmu_booke_quick_enter_page(mmu_t mmu, vm_page_t m)
+{
+ vm_paddr_t paddr;
+ vm_offset_t qaddr;
+ uint32_t flags;
+ pte_t *pte;
+
+ 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));
+
+ critical_enter();
+ qaddr = PCPU_GET(qmap_addr);
+
+ pte = &(kernel_pmap->pm_pdir[PDIR_IDX(qaddr)][PTBL_IDX(qaddr)]);
+
+ KASSERT(pte->flags == 0, ("mmu_booke_quick_enter_page: PTE busy"));
+
+ /*
+ * XXX: tlbivax is broadcast to other cores, but qaddr should
+ * not be present in other TLBs. Is there a better instruction
+ * sequence to use? Or just forget it & use mmu_booke_kenter()...
+ */
+ __asm __volatile("tlbivax 0, %0" :: "r"(qaddr & MAS2_EPN_MASK));
+ __asm __volatile("isync; msync");
+
+ pte->rpn = paddr & ~PTE_PA_MASK;
+ pte->flags = flags;
+
+ /* Flush the real memory from the instruction cache. */
+ if ((flags & (PTE_I | PTE_G)) == 0)
+ __syncicache((void *)qaddr, PAGE_SIZE);
+
+ return (qaddr);
+}
+
+static void
+mmu_booke_quick_remove_page(mmu_t mmu, vm_offset_t addr)
+{
+ pte_t *pte;
+
+ pte = &(kernel_pmap->pm_pdir[PDIR_IDX(addr)][PTBL_IDX(addr)]);
+
+ KASSERT(PCPU_GET(qmap_addr) == addr,
+ ("mmu_booke_quick_remove_page: invalid address"));
+ KASSERT(pte->flags != 0,
+ ("mmu_booke_quick_remove_page: PTE not in use"));
+
+ pte->flags = 0;
+ pte->rpn = 0;
+ critical_exit();
+}
+
/*
* Return whether or not the specified physical page was modified
* in any of physical maps.
diff --git a/sys/powerpc/include/float.h b/sys/powerpc/include/float.h
index 50da262..4eea0bd 100644
--- a/sys/powerpc/include/float.h
+++ b/sys/powerpc/include/float.h
@@ -10,7 +10,7 @@
* 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
diff --git a/sys/powerpc/include/in_cksum.h b/sys/powerpc/include/in_cksum.h
index 4fe1b40..37bfb20 100644
--- a/sys/powerpc/include/in_cksum.h
+++ b/sys/powerpc/include/in_cksum.h
@@ -10,7 +10,7 @@
* 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
diff --git a/sys/powerpc/include/pcpu.h b/sys/powerpc/include/pcpu.h
index 79b2d96..2c79cd6 100644
--- a/sys/powerpc/include/pcpu.h
+++ b/sys/powerpc/include/pcpu.h
@@ -35,6 +35,7 @@
#include <machine/tlb.h>
struct pmap;
+struct pvo_entry;
#define CPUSAVE_LEN 9
#define PCPU_MD_COMMON_FIELDS \
@@ -53,6 +54,9 @@ struct pmap;
void *pc_restore;
#define PCPU_MD_AIM32_FIELDS \
+ vm_offset_t pc_qmap_addr; \
+ struct pvo_entry *pc_qmap_pvo; \
+ struct mtx pc_qmap_lock; \
/* char __pad[0] */
#define PCPU_MD_AIM64_FIELDS \
@@ -60,7 +64,10 @@ struct pmap;
struct slb **pc_userslb; \
register_t pc_slbsave[18]; \
uint8_t pc_slbstack[1024]; \
- char __pad[1137]
+ vm_offset_t pc_qmap_addr; \
+ struct pvo_entry *pc_qmap_pvo; \
+ struct mtx pc_qmap_lock; \
+ char __pad[1121 - sizeof(struct mtx)]
#ifdef __powerpc64__
#define PCPU_MD_AIM_FIELDS PCPU_MD_AIM64_FIELDS
@@ -78,9 +85,10 @@ struct pmap;
register_t pc_booke_mchksave[CPUSAVE_LEN]; \
register_t pc_booke_tlbsave[BOOKE_TLBSAVE_LEN]; \
register_t pc_booke_tlb_level; \
+ vm_offset_t pc_qmap_addr; \
uint32_t *pc_booke_tlb_lock; \
int pc_tid_next; \
- char __pad[173]
+ char __pad[165]
/* Definitions for register offsets within the exception tmp save areas */
#define CPUSAVE_R27 0 /* where r27 gets saved */
diff --git a/sys/powerpc/powerpc/mmu_if.m b/sys/powerpc/powerpc/mmu_if.m
index 0089d76..6c41c74 100644
--- a/sys/powerpc/powerpc/mmu_if.m
+++ b/sys/powerpc/powerpc/mmu_if.m
@@ -933,3 +933,26 @@ METHOD void dumpsys_unmap {
METHOD void scan_init {
mmu_t _mmu;
};
+
+/**
+ * @brief Create a temporary thread-local KVA mapping of a single page.
+ *
+ * @param _pg The physical page to map
+ *
+ * @retval addr The temporary KVA
+ */
+METHOD vm_offset_t quick_enter_page {
+ mmu_t _mmu;
+ vm_page_t _pg;
+};
+
+/**
+ * @brief Undo a mapping created by quick_enter_page
+ *
+ * @param _va The mapped KVA
+ */
+METHOD void quick_remove_page {
+ mmu_t _mmu;
+ vm_offset_t _va;
+};
+
diff --git a/sys/powerpc/powerpc/pmap_dispatch.c b/sys/powerpc/powerpc/pmap_dispatch.c
index a27eb82..a071899 100644
--- a/sys/powerpc/powerpc/pmap_dispatch.c
+++ b/sys/powerpc/powerpc/pmap_dispatch.c
@@ -550,6 +550,20 @@ dumpsys_pa_init(void)
return (MMU_SCAN_INIT(mmu_obj));
}
+vm_offset_t
+pmap_quick_enter_page(vm_page_t m)
+{
+ CTR2(KTR_PMAP, "%s(%p)", __func__, m);
+ return (MMU_QUICK_ENTER_PAGE(mmu_obj, m));
+}
+
+void
+pmap_quick_remove_page(vm_offset_t addr)
+{
+ CTR2(KTR_PMAP, "%s(%#x)", __func__, addr);
+ MMU_QUICK_REMOVE_PAGE(mmu_obj, addr);
+}
+
/*
* MMU install routines. Highest priority wins, equal priority also
* overrides allowing last-set to win.
diff --git a/sys/rpc/svc_vc.c b/sys/rpc/svc_vc.c
index 1d3d041..6056345 100644
--- a/sys/rpc/svc_vc.c
+++ b/sys/rpc/svc_vc.c
@@ -860,7 +860,7 @@ svc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg,
len = mrep->m_pkthdr.len;
*mtod(mrep, uint32_t *) =
htonl(0x80000000 | (len - sizeof(uint32_t)));
- atomic_add_acq_32(&xprt->xp_snd_cnt, len);
+ atomic_add_32(&xprt->xp_snd_cnt, len);
error = sosend(xprt->xp_socket, NULL, NULL, mrep, NULL,
0, curthread);
if (!error) {
diff --git a/sys/sparc64/include/float.h b/sys/sparc64/include/float.h
index dcc626f..2703369 100644
--- a/sys/sparc64/include/float.h
+++ b/sys/sparc64/include/float.h
@@ -14,7 +14,7 @@
* 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
diff --git a/sys/sparc64/include/in_cksum.h b/sys/sparc64/include/in_cksum.h
index d5d167f..b13882e 100644
--- a/sys/sparc64/include/in_cksum.h
+++ b/sys/sparc64/include/in_cksum.h
@@ -10,7 +10,7 @@
* 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
diff --git a/sys/sparc64/include/pcpu.h b/sys/sparc64/include/pcpu.h
index dbcc59c..df43810 100644
--- a/sys/sparc64/include/pcpu.h
+++ b/sys/sparc64/include/pcpu.h
@@ -51,6 +51,7 @@ struct pmap;
struct intr_request *pc_irfree; \
struct pmap *pc_pmap; \
vm_offset_t pc_addr; \
+ vm_offset_t pc_qmap_addr; \
u_long pc_tickref; \
u_long pc_tickadj; \
u_long pc_tickincrement; \
@@ -61,7 +62,7 @@ struct pmap;
u_int pc_tlb_ctx; \
u_int pc_tlb_ctx_max; \
u_int pc_tlb_ctx_min; \
- char __pad[405]
+ char __pad[397]
#ifdef _KERNEL
diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c
index f10678e..e0dca86 100644
--- a/sys/sparc64/sparc64/pmap.c
+++ b/sys/sparc64/sparc64/pmap.c
@@ -143,6 +143,7 @@ static int pmap_protect_tte(struct pmap *pm1, struct pmap *pm2,
struct tte *tp, vm_offset_t va);
static int pmap_unwire_tte(pmap_t pm, pmap_t pm2, struct tte *tp,
vm_offset_t va);
+static void pmap_init_qpages(void);
/*
* Map the given physical page at the specified virtual address in the
@@ -680,6 +681,25 @@ pmap_bootstrap(u_int cpu_impl)
tlb_flush_nonlocked();
}
+static void
+pmap_init_qpages(void)
+{
+ struct pcpu *pc;
+ int i;
+
+ if (dcache_color_ignore != 0)
+ return;
+
+ CPU_FOREACH(i) {
+ pc = pcpu_find(i);
+ pc->pc_qmap_addr = kva_alloc(PAGE_SIZE * DCACHE_COLORS);
+ if (pc->pc_qmap_addr == 0)
+ panic("pmap_init_qpages: unable to allocate KVA");
+ }
+}
+
+SYSINIT(qpages_init, SI_SUB_CPU, SI_ORDER_ANY, pmap_init_qpages, NULL);
+
/*
* Map the 4MB kernel TSB pages.
*/
@@ -1934,6 +1954,54 @@ pmap_copy_page(vm_page_t msrc, vm_page_t mdst)
}
}
+vm_offset_t
+pmap_quick_enter_page(vm_page_t m)
+{
+ vm_paddr_t pa;
+ vm_offset_t qaddr;
+ struct tte *tp;
+
+ pa = VM_PAGE_TO_PHYS(m);
+ if (dcache_color_ignore != 0 || m->md.color == DCACHE_COLOR(pa))
+ return (TLB_PHYS_TO_DIRECT(pa));
+
+ critical_enter();
+ qaddr = PCPU_GET(qmap_addr);
+ qaddr += (PAGE_SIZE * ((DCACHE_COLORS + DCACHE_COLOR(pa) -
+ DCACHE_COLOR(qaddr)) % DCACHE_COLORS));
+ tp = tsb_kvtotte(qaddr);
+
+ KASSERT(tp->tte_data == 0, ("pmap_quick_enter_page: PTE busy"));
+
+ tp->tte_data = TD_V | TD_8K | TD_PA(pa) | TD_CP | TD_CV | TD_W;
+ tp->tte_vpn = TV_VPN(qaddr, TS_8K);
+
+ return (qaddr);
+}
+
+void
+pmap_quick_remove_page(vm_offset_t addr)
+{
+ vm_offset_t qaddr;
+ struct tte *tp;
+
+ if (addr >= VM_MIN_DIRECT_ADDRESS)
+ return;
+
+ tp = tsb_kvtotte(addr);
+ qaddr = PCPU_GET(qmap_addr);
+
+ KASSERT((addr >= qaddr) && (addr < (qaddr + (PAGE_SIZE * DCACHE_COLORS))),
+ ("pmap_quick_remove_page: invalid address"));
+ KASSERT(tp->tte_data != 0, ("pmap_quick_remove_page: PTE not in use"));
+
+ stxa(TLB_DEMAP_VA(addr) | TLB_DEMAP_NUCLEUS | TLB_DEMAP_PAGE, ASI_DMMU_DEMAP, 0);
+ stxa(TLB_DEMAP_VA(addr) | TLB_DEMAP_NUCLEUS | TLB_DEMAP_PAGE, ASI_IMMU_DEMAP, 0);
+ flush(KERNBASE);
+ TTE_ZERO(tp);
+ critical_exit();
+}
+
int unmapped_buf_allowed;
void
diff --git a/sys/sys/buf.h b/sys/sys/buf.h
index 2ffa4f5..d5ce0e5 100644
--- a/sys/sys/buf.h
+++ b/sys/sys/buf.h
@@ -465,8 +465,6 @@ extern int dirtybufthresh;
extern int bdwriteskip;
extern int dirtybufferflushes;
extern int altbufferflushes;
-extern struct buf *buf; /* The buffer headers. */
-extern struct buf *swbuf; /* Swap I/O buffer headers. */
extern int nswbuf; /* Number of swap I/O buffer headers. */
extern int cluster_pbuf_freecnt; /* Number of pbufs for clusters */
extern int vnode_pbuf_freecnt; /* Number of pbufs for vnode pager */
@@ -485,6 +483,7 @@ void runningbufwakeup(struct buf *);
void waitrunningbufspace(void);
caddr_t kern_vfs_bio_buffer_alloc(caddr_t v, long physmem_est);
void bufinit(void);
+void bufshutdown(int);
void bdata2bio(struct buf *bp, struct bio *bip);
void bwillwrite(void);
int buf_dirty_count_severe(void);
diff --git a/sys/sys/event.h b/sys/sys/event.h
index 089c9b3..0f13231 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -108,6 +108,7 @@ struct kevent {
* data/hint flags for EVFILT_{READ|WRITE}, shared with userspace
*/
#define NOTE_LOWAT 0x0001 /* low water mark */
+#define NOTE_FILE_POLL 0x0002 /* behave like poll() */
/*
* data/hint flags for EVFILT_VNODE, shared with userspace
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index b557706..f75927b 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -146,6 +146,10 @@ enum {
/* Flags for kern_dup(). */
#define FDDUP_FLAG_CLOEXEC 0x1 /* Atomically set UF_EXCLOSE. */
+/* For backward compatibility. */
+#define falloc(td, resultfp, resultfd, flags) \
+ falloc_caps(td, resultfp, resultfd, flags, NULL)
+
struct thread;
void filecaps_init(struct filecaps *fcaps);
@@ -156,8 +160,8 @@ void filecaps_free(struct filecaps *fcaps);
int closef(struct file *fp, struct thread *td);
int dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode,
int openerror, int *indxp);
-int falloc(struct thread *td, struct file **resultfp, int *resultfd,
- int flags);
+int falloc_caps(struct thread *td, struct file **resultfp, int *resultfd,
+ int flags, struct filecaps *fcaps);
int falloc_noinstall(struct thread *td, struct file **resultfp);
void _finstall(struct filedesc *fdp, struct file *fp, int fd, int flags,
struct filecaps *fcaps);
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index 3d5a7c1..39a41d3 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -150,7 +150,6 @@ struct pkthdr {
#define tso_segsz PH_per.sixteen[1]
#define csum_phsum PH_per.sixteen[2]
#define csum_data PH_per.thirtytwo[1]
-#define pkt_tcphdr PH_loc.ptr
/*
* Description of external storage mapped into mbuf; valid only if M_EXT is
diff --git a/sys/sys/msg.h b/sys/sys/msg.h
index f4193c8..8f56c94 100644
--- a/sys/sys/msg.h
+++ b/sys/sys/msg.h
@@ -163,8 +163,9 @@ struct msqid_kernel {
struct ucred *cred; /* creator's credentials */
};
-#else /* !_KERNEL */
+#endif /* _KERNEL */
+#if !defined(_KERNEL) || defined(_WANT_MSG_PROTOTYPES)
__BEGIN_DECLS
int msgctl(int, int, struct msqid_ds *);
int msgget(key_t, int);
@@ -176,6 +177,6 @@ int msgsys(int, ...);
#endif
__END_DECLS
-#endif /* _KERNEL */
+#endif /* !_KERNEL || _WANT_MSG_PROTOTYPES */
#endif /* !_SYS_MSG_H_ */
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 40893ed..62c4b05 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -161,6 +161,7 @@ struct pargs {
* for write access.
*/
struct cpuset;
+struct filecaps;
struct kaioinfo;
struct kaudit_record;
struct kdtrace_proc;
@@ -237,7 +238,7 @@ struct thread {
int td_oncpu; /* (t) Which cpu we are on. */
volatile u_char td_owepreempt; /* (k*) Preempt on last critical_exit */
u_char td_tsqueue; /* (t) Turnstile queue blocked on. */
- short td_locks; /* (k) Count of non-spin locks. */
+ short td_locks; /* (k) Debug: count of non-spin locks */
short td_rw_rlocks; /* (k) Count of rwlock read locks. */
short td_lk_slocks; /* (k) Count of lockmgr shared locks. */
short td_stopsched; /* (k) Scheduler stopped. */
@@ -350,8 +351,14 @@ do { \
KASSERT((__m == &blocked_lock || __m == (lock)), \
("Thread %p lock %p does not match %p", td, __m, (lock))); \
} while (0)
+
+#define TD_LOCKS_INC(td) ((td)->td_locks++)
+#define TD_LOCKS_DEC(td) ((td)->td_locks--)
#else
#define THREAD_LOCKPTR_ASSERT(td, lock)
+
+#define TD_LOCKS_INC(td)
+#define TD_LOCKS_DEC(td)
#endif
/*
@@ -916,7 +923,8 @@ int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp,
int enterthispgrp(struct proc *p, struct pgrp *pgrp);
void faultin(struct proc *p);
void fixjobc(struct proc *p, struct pgrp *pgrp, int entering);
-int fork1(struct thread *, int, int, struct proc **, int *, int);
+int fork1(struct thread *, int, int, struct proc **, int *, int,
+ struct filecaps *);
void fork_exit(void (*)(void *, struct trapframe *), void *,
struct trapframe *);
void fork_return(struct thread *, struct trapframe *);
diff --git a/sys/sys/sem.h b/sys/sys/sem.h
index 0ea259b..abfb7cd 100644
--- a/sys/sys/sem.h
+++ b/sys/sys/sem.h
@@ -137,8 +137,9 @@ struct semid_kernel {
*/
void semexit(struct proc *p);
-#else /* ! _KERNEL */
+#endif /* _KERNEL */
+#if !defined(_KERNEL) || defined(_WANT_SEM_PROTOTYPES)
__BEGIN_DECLS
#if __BSD_VISIBLE
int semsys(int, ...);
@@ -148,6 +149,6 @@ int semget(key_t, int, int);
int semop(int, struct sembuf *, size_t);
__END_DECLS
-#endif /* !_KERNEL */
+#endif /* !_KERNEL || _WANT_SEM_PROTOTYPES */
#endif /* !_SYS_SEM_H_ */
diff --git a/sys/sys/shm.h b/sys/sys/shm.h
index 799bbf5..f685df3 100644
--- a/sys/sys/shm.h
+++ b/sys/sys/shm.h
@@ -144,8 +144,9 @@ struct vmspace;
void shmexit(struct vmspace *);
void shmfork(struct proc *, struct proc *);
-#else /* !_KERNEL */
+#endif /* _KERNEL */
+#if !defined(_KERNEL) || defined(_WANT_SHM_PROTOTYPES)
#include <sys/cdefs.h>
#ifndef _SIZE_T_DECLARED
@@ -163,6 +164,6 @@ int shmctl(int, int, struct shmid_ds *);
int shmdt(const void *);
__END_DECLS
-#endif /* !_KERNEL */
+#endif /* _KERNEL || _WANT_SHM_PROTOTYPES */
#endif /* !_SYS_SHM_H_ */
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index d22c349..ce68ba8 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -35,6 +35,7 @@
#include <sys/mount.h>
struct file;
+struct filecaps;
enum idtype;
struct itimerval;
struct image_args;
@@ -125,7 +126,7 @@ int kern_kevent(struct thread *td, int fd, int nchanges, int nevents,
int kern_kevent_fp(struct thread *td, struct file *fp, int nchanges,
int nevents, struct kevent_copyops *k_ops,
const struct timespec *timeout);
-int kern_kqueue(struct thread *td, int flags);
+int kern_kqueue(struct thread *td, int flags, struct filecaps *fcaps);
int kern_kldload(struct thread *td, const char *file, int *fileid);
int kern_kldstat(struct thread *td, int fileid, struct kld_file_stat *stat);
int kern_kldunload(struct thread *td, int fileid, int flags);
@@ -150,8 +151,8 @@ int kern_openat(struct thread *td, int fd, char *path,
enum uio_seg pathseg, int flags, int mode);
int kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg,
int name, u_long flags);
-int kern_pipe(struct thread *td, int fildes[2]);
-int kern_pipe2(struct thread *td, int fildes[2], int flags);
+int kern_pipe(struct thread *td, int fildes[2], int flags,
+ struct filecaps *fcaps1, struct filecaps *fcaps2);
int kern_poll(struct thread *td, struct pollfd *fds, u_int nfds,
struct timespec *tsp, sigset_t *uset);
int kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len,
@@ -203,6 +204,8 @@ int kern_setsockopt(struct thread *td, int s, int level, int name,
void *optval, enum uio_seg valseg, socklen_t valsize);
int kern_settimeofday(struct thread *td, struct timeval *tv,
struct timezone *tzp);
+int kern_shm_open(struct thread *td, const char *userpath, int flags,
+ mode_t mode, struct filecaps *fcaps);
int kern_shmat(struct thread *td, int shmid, const void *shmaddr,
int shmflg);
int kern_shmctl(struct thread *td, int shmid, int cmd, void *buf,
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 4c66431..988dbae 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -807,8 +807,8 @@ int userland_sysctl(struct thread *td, int *name, u_int namelen, void *old,
size_t *retval, int flags);
int sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid,
int *nindx, struct sysctl_req *req);
-void sysctl_wlock(void);
-void sysctl_wunlock(void);
+void sysctl_xlock(void);
+void sysctl_xunlock(void);
int sysctl_wire_old_buffer(struct sysctl_req *req, size_t len);
struct sbuf;
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index 980c796..db92981 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -139,11 +139,12 @@ struct sysentvec {
void (*sv_thread_detach)(struct thread *);
};
-#define SV_ILP32 0x000100
-#define SV_LP64 0x000200
-#define SV_IA32 0x004000
-#define SV_AOUT 0x008000
-#define SV_SHP 0x010000
+#define SV_ILP32 0x000100 /* 32-bit executable. */
+#define SV_LP64 0x000200 /* 64-bit executable. */
+#define SV_IA32 0x004000 /* Intel 32-bit executable. */
+#define SV_AOUT 0x008000 /* a.out executable. */
+#define SV_SHP 0x010000 /* Shared page. */
+#define SV_CAPSICUM 0x020000 /* Force cap_enter() on startup. */
#define SV_ABI_MASK 0xff
#define SV_PROC_FLAG(p, x) ((p)->p_sysent->sv_flags & (x))
diff --git a/sys/sys/umtx.h b/sys/sys/umtx.h
index 07794df..1459507 100644
--- a/sys/sys/umtx.h
+++ b/sys/sys/umtx.h
@@ -153,7 +153,7 @@ umtx_key_match(const struct umtx_key *k1, const struct umtx_key *k2)
}
int umtx_copyin_timeout(const void *, struct timespec *);
-int umtx_key_get(void *, int, int, struct umtx_key *);
+int umtx_key_get(const void *, int, int, struct umtx_key *);
void umtx_key_release(struct umtx_key *);
struct umtx_q *umtxq_alloc(void);
void umtxq_free(struct umtx_q *);
diff --git a/sys/ufs/ffs/ffs_subr.c b/sys/ufs/ffs/ffs_subr.c
index e2460a3..67f7e5c 100644
--- a/sys/ufs/ffs/ffs_subr.c
+++ b/sys/ufs/ffs/ffs_subr.c
@@ -55,10 +55,6 @@ __FBSDID("$FreeBSD$");
#include <ufs/ffs/ffs_extern.h>
#include <ufs/ffs/fs.h>
-#ifdef KDB
-void ffs_checkoverlap(struct buf *, struct inode *);
-#endif
-
/*
* Return buffer with the contents of block "offset" from the beginning of
* directory "ip". If "res" is non-zero, fill it in with a pointer to the
@@ -165,37 +161,6 @@ ffs_fragacct(fs, fragmap, fraglist, cnt)
}
}
-#ifdef KDB
-void
-ffs_checkoverlap(bp, ip)
- struct buf *bp;
- struct inode *ip;
-{
- struct buf *ebp, *ep;
- ufs2_daddr_t start, last;
- struct vnode *vp;
-
- ebp = &buf[nbuf];
- start = bp->b_blkno;
- last = start + btodb(bp->b_bcount) - 1;
- for (ep = buf; ep < ebp; ep++) {
- if (ep == bp || (ep->b_flags & B_INVAL) ||
- ep->b_vp == NULLVP)
- continue;
- vp = ip->i_devvp;
- /* look for overlap */
- if (ep->b_bcount == 0 || ep->b_blkno > last ||
- ep->b_blkno + btodb(ep->b_bcount) <= start)
- continue;
- vprint("Disk overlap", vp);
- printf("\tstart %jd, end %jd overlap start %jd, end %jd\n",
- (intmax_t)start, (intmax_t)last, (intmax_t)ep->b_blkno,
- (intmax_t)(ep->b_blkno + btodb(ep->b_bcount) - 1));
- panic("ffs_checkoverlap: Disk buffer overlap");
- }
-}
-#endif /* KDB */
-
/*
* block operations
*
diff --git a/sys/vm/pmap.h b/sys/vm/pmap.h
index d73babc..1d18823 100644
--- a/sys/vm/pmap.h
+++ b/sys/vm/pmap.h
@@ -141,6 +141,8 @@ void pmap_pinit0(pmap_t);
void pmap_protect(pmap_t, vm_offset_t, vm_offset_t, vm_prot_t);
void pmap_qenter(vm_offset_t, vm_page_t *, int);
void pmap_qremove(vm_offset_t, int);
+vm_offset_t pmap_quick_enter_page(vm_page_t);
+void pmap_quick_remove_page(vm_offset_t);
void pmap_release(pmap_t);
void pmap_remove(pmap_t, vm_offset_t, vm_offset_t);
void pmap_remove_all(vm_page_t m);
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 7391465..50983ca 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -193,7 +193,7 @@ vm_fault_dirty(vm_map_entry_t entry, vm_page_t m, vm_prot_t prot,
VM_OBJECT_ASSERT_LOCKED(m->object);
need_dirty = ((fault_type & VM_PROT_WRITE) != 0 &&
- (fault_flags & VM_FAULT_CHANGE_WIRING) == 0) ||
+ (fault_flags & VM_FAULT_WIRE) == 0) ||
(fault_flags & VM_FAULT_DIRTY) != 0;
if (set_wd)
@@ -244,15 +244,6 @@ vm_fault_dirty(vm_map_entry_t entry, vm_page_t m, vm_prot_t prot,
}
/*
- * TRYPAGER - used by vm_fault to calculate whether the pager for the
- * current object *might* contain the page.
- *
- * default objects are zero-fill, there is no real pager.
- */
-#define TRYPAGER (fs.object->type != OBJT_DEFAULT && \
- ((fault_flags & VM_FAULT_CHANGE_WIRING) == 0 || wired))
-
-/*
* vm_fault:
*
* Handle a page fault occurring at the given address,
@@ -361,9 +352,12 @@ RetryFault:;
if (wired)
fault_type = prot | (fault_type & VM_PROT_COPY);
+ else
+ KASSERT((fault_flags & VM_FAULT_WIRE) == 0,
+ ("!wired && VM_FAULT_WIRE"));
if (fs.vp == NULL /* avoid locked vnode leak */ &&
- (fault_flags & (VM_FAULT_CHANGE_WIRING | VM_FAULT_DIRTY)) == 0 &&
+ (fault_flags & (VM_FAULT_WIRE | VM_FAULT_DIRTY)) == 0 &&
/* avoid calling vm_object_set_writeable_dirty() */
((prot & VM_PROT_WRITE) == 0 ||
(fs.first_object->type != OBJT_VNODE &&
@@ -509,10 +503,12 @@ fast_failed:
}
/*
- * Page is not resident, If this is the search termination
+ * Page is not resident. If this is the search termination
* or the pager might contain the page, allocate a new page.
+ * Default objects are zero-fill, there is no real pager.
*/
- if (TRYPAGER || fs.object == fs.first_object) {
+ if (fs.object->type != OBJT_DEFAULT ||
+ fs.object == fs.first_object) {
if (fs.pindex >= fs.object->size) {
unlock_and_deallocate(&fs);
return (KERN_PROTECTION_FAILURE);
@@ -556,9 +552,10 @@ readrest:
*
* Attempt to fault-in the page if there is a chance that the
* pager has it, and potentially fault in additional pages
- * at the same time.
+ * at the same time. For default objects simply provide
+ * zero-filled pages.
*/
- if (TRYPAGER) {
+ if (fs.object->type != OBJT_DEFAULT) {
int rv;
u_char behavior = vm_map_entry_behavior(fs.entry);
@@ -873,7 +870,7 @@ vnode_locked:
pmap_copy_page(fs.m, fs.first_m);
fs.first_m->valid = VM_PAGE_BITS_ALL;
if (wired && (fault_flags &
- VM_FAULT_CHANGE_WIRING) == 0) {
+ VM_FAULT_WIRE) == 0) {
vm_page_lock(fs.first_m);
vm_page_wire(fs.first_m);
vm_page_unlock(fs.first_m);
@@ -994,7 +991,7 @@ vnode_locked:
*/
pmap_enter(fs.map->pmap, vaddr, fs.m, prot,
fault_type | (wired ? PMAP_ENTER_WIRED : 0), 0);
- if (faultcount != 1 && (fault_flags & VM_FAULT_CHANGE_WIRING) == 0 &&
+ if (faultcount != 1 && (fault_flags & VM_FAULT_WIRE) == 0 &&
wired == 0)
vm_fault_prefault(&fs, vaddr, faultcount, reqpage);
VM_OBJECT_WLOCK(fs.object);
@@ -1004,11 +1001,9 @@ vnode_locked:
* If the page is not wired down, then put it where the pageout daemon
* can find it.
*/
- if (fault_flags & VM_FAULT_CHANGE_WIRING) {
- if (wired)
- vm_page_wire(fs.m);
- else
- vm_page_unwire(fs.m, PQ_ACTIVE);
+ if ((fault_flags & VM_FAULT_WIRE) != 0) {
+ KASSERT(wired, ("VM_FAULT_WIRE && !wired"));
+ vm_page_wire(fs.m);
} else
vm_page_activate(fs.m);
if (m_hold != NULL) {
@@ -1086,9 +1081,19 @@ vm_fault_dontneed(const struct faultstate *fs, vm_offset_t vaddr, int ahead)
if (m->valid != VM_PAGE_BITS_ALL ||
vm_page_busied(m))
continue;
+
+ /*
+ * Don't clear PGA_REFERENCED, since it would
+ * likely represent a reference by a different
+ * process.
+ *
+ * Typically, at this point, prefetched pages
+ * are still in the inactive queue. Only
+ * pages that triggered page faults are in the
+ * active queue.
+ */
vm_page_lock(m);
- if (m->hold_count == 0 && m->wire_count == 0)
- vm_page_advise(m, MADV_DONTNEED);
+ vm_page_deactivate(m);
vm_page_unlock(m);
}
}
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index f8172bd..65c3e2c 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -2591,7 +2591,7 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end,
* it into the physical map.
*/
if ((rv = vm_fault(map, faddr, VM_PROT_NONE,
- VM_FAULT_CHANGE_WIRING)) != KERN_SUCCESS)
+ VM_FAULT_WIRE)) != KERN_SUCCESS)
break;
} while ((faddr += PAGE_SIZE) < saved_end);
vm_map_lock(map);
diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
index 3bf7a67..2c0a4ad 100644
--- a/sys/vm/vm_map.h
+++ b/sys/vm/vm_map.h
@@ -326,9 +326,9 @@ long vmspace_resident_count(struct vmspace *vmspace);
/*
* vm_fault option flags
*/
-#define VM_FAULT_NORMAL 0 /* Nothing special */
-#define VM_FAULT_CHANGE_WIRING 1 /* Change the wiring as appropriate */
-#define VM_FAULT_DIRTY 2 /* Dirty the page; use w/VM_PROT_COPY */
+#define VM_FAULT_NORMAL 0 /* Nothing special */
+#define VM_FAULT_WIRE 1 /* Wire the mapped page */
+#define VM_FAULT_DIRTY 2 /* Dirty the page; use w/VM_PROT_COPY */
/*
* Initially, mappings are slightly sequential. The maximum window size must
diff --git a/sys/vm/vm_pager.c b/sys/vm/vm_pager.c
index a42061c..40d7d4e 100644
--- a/sys/vm/vm_pager.c
+++ b/sys/vm/vm_pager.c
@@ -86,6 +86,8 @@ __FBSDID("$FreeBSD$");
int cluster_pbuf_freecnt = -1; /* unlimited to begin with */
+struct buf *swbuf;
+
static int dead_pager_getpages(vm_object_t, vm_page_t *, int, int);
static vm_object_t dead_pager_alloc(void *, vm_ooffset_t, vm_prot_t,
vm_ooffset_t, struct ucred *);
diff --git a/sys/vm/vm_reserv.c b/sys/vm/vm_reserv.c
index 2cfc630..34e69e1 100644
--- a/sys/vm/vm_reserv.c
+++ b/sys/vm/vm_reserv.c
@@ -217,6 +217,11 @@ static long vm_reserv_freed;
SYSCTL_LONG(_vm_reserv, OID_AUTO, freed, CTLFLAG_RD,
&vm_reserv_freed, 0, "Cumulative number of freed reservations");
+static int sysctl_vm_reserv_fullpop(SYSCTL_HANDLER_ARGS);
+
+SYSCTL_PROC(_vm_reserv, OID_AUTO, fullpop, CTLTYPE_INT | CTLFLAG_RD, NULL, 0,
+ sysctl_vm_reserv_fullpop, "I", "Current number of full reservations");
+
static int sysctl_vm_reserv_partpopq(SYSCTL_HANDLER_ARGS);
SYSCTL_OID(_vm_reserv, OID_AUTO, partpopq, CTLTYPE_STRING | CTLFLAG_RD, NULL, 0,
@@ -235,6 +240,33 @@ static void vm_reserv_populate(vm_reserv_t rv, int index);
static void vm_reserv_reclaim(vm_reserv_t rv);
/*
+ * Returns the current number of full reservations.
+ *
+ * Since the number of full reservations is computed without acquiring the
+ * free page queue lock, the returned value may be inexact.
+ */
+static int
+sysctl_vm_reserv_fullpop(SYSCTL_HANDLER_ARGS)
+{
+ vm_paddr_t paddr;
+ struct vm_phys_seg *seg;
+ vm_reserv_t rv;
+ int fullpop, segind;
+
+ fullpop = 0;
+ for (segind = 0; segind < vm_phys_nsegs; segind++) {
+ seg = &vm_phys_segs[segind];
+ paddr = roundup2(seg->start, VM_LEVEL_0_SIZE);
+ while (paddr + VM_LEVEL_0_SIZE <= seg->end) {
+ rv = &vm_reserv_array[paddr >> VM_LEVEL_0_SHIFT];
+ fullpop += rv->popcnt == VM_LEVEL_0_NPAGES;
+ paddr += VM_LEVEL_0_SIZE;
+ }
+ }
+ return (sysctl_handle_int(oidp, &fullpop, 0, req));
+}
+
+/*
* Describes the current state of the partially-populated reservation queue.
*/
static int
diff --git a/sys/x86/include/_types.h b/sys/x86/include/_types.h
index 816a301..b130be3 100644
--- a/sys/x86/include/_types.h
+++ b/sys/x86/include/_types.h
@@ -152,8 +152,16 @@ typedef int ___wchar_t;
*/
#ifdef __GNUCLIKE_BUILTIN_VARARGS
typedef __builtin_va_list __va_list; /* internally known to gcc */
-#elif defined(lint)
-typedef char * __va_list; /* pretend */
+#else
+#ifdef __LP64__
+struct __s_va_list {
+ __uint32_t _pad1[2]; /* gp_offset, fp_offset */
+ __uint64_t _pad2[2]; /* overflow_arg_area, reg_save_area */
+};
+typedef struct __s_va_list __va_list;
+#else
+typedef char * __va_list;
+#endif
#endif
#if defined(__GNUC_VA_LIST_COMPATIBILITY) && !defined(__GNUC_VA_LIST) \
&& !defined(__NO_GNUC_VA_LIST)
diff --git a/sys/x86/include/float.h b/sys/x86/include/float.h
index 8af3039..32e338e 100644
--- a/sys/x86/include/float.h
+++ b/sys/x86/include/float.h
@@ -10,7 +10,7 @@
* 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
diff --git a/sys/x86/include/specialreg.h b/sys/x86/include/specialreg.h
index 6c849ff..e88a4d7 100644
--- a/sys/x86/include/specialreg.h
+++ b/sys/x86/include/specialreg.h
@@ -521,6 +521,17 @@
#define IA32_FEATURE_CONTROL_SMX_EN 0x02 /* enable VMX inside SMX */
#define IA32_FEATURE_CONTROL_VMX_EN 0x04 /* enable VMX outside SMX */
+/* MSR IA32_MISC_ENABLE */
+#define IA32_MISC_EN_FASTSTR 0x0000000000000001ULL
+#define IA32_MISC_EN_ATCCE 0x0000000000000008ULL
+#define IA32_MISC_EN_PERFMON 0x0000000000000080ULL
+#define IA32_MISC_EN_PEBSU 0x0000000000001000ULL
+#define IA32_MISC_EN_ESSTE 0x0000000000010000ULL
+#define IA32_MISC_EN_MONE 0x0000000000040000ULL
+#define IA32_MISC_EN_LIMCPUID 0x0000000000400000ULL
+#define IA32_MISC_EN_xTPRD 0x0000000000800000ULL
+#define IA32_MISC_EN_XDD 0x0000000400000000ULL
+
/*
* PAT modes.
*/
diff --git a/sys/x86/x86/identcpu.c b/sys/x86/x86/identcpu.c
index 548da4a..4fe3e3c 100644
--- a/sys/x86/x86/identcpu.c
+++ b/sys/x86/x86/identcpu.c
@@ -1295,6 +1295,33 @@ identify_hypervisor(void)
}
/*
+ * Clear "Limit CPUID Maxval" bit and return true if the caller should
+ * get the largest standard CPUID function number again if it is set
+ * from BIOS. It is necessary for probing correct CPU topology later
+ * and for the correct operation of the AVX-aware userspace.
+ */
+bool
+intel_fix_cpuid(void)
+{
+ uint64_t msr;
+
+ if (cpu_vendor_id != CPU_VENDOR_INTEL)
+ return (false);
+ if ((CPUID_TO_FAMILY(cpu_id) == 0xf &&
+ CPUID_TO_MODEL(cpu_id) >= 0x3) ||
+ (CPUID_TO_FAMILY(cpu_id) == 0x6 &&
+ CPUID_TO_MODEL(cpu_id) >= 0xe)) {
+ msr = rdmsr(MSR_IA32_MISC_ENABLE);
+ if ((msr & IA32_MISC_EN_LIMCPUID) != 0) {
+ msr &= ~IA32_MISC_EN_LIMCPUID;
+ wrmsr(MSR_IA32_MISC_ENABLE, msr);
+ return (true);
+ }
+ }
+ return (false);
+}
+
+/*
* Final stage of CPU identification.
*/
#ifdef __i386__
@@ -1328,22 +1355,9 @@ identify_cpu(void)
identify_hypervisor();
cpu_vendor_id = find_cpu_vendor_id();
- /*
- * Clear "Limit CPUID Maxval" bit and get the largest standard CPUID
- * function number again if it is set from BIOS. It is necessary
- * for probing correct CPU topology later.
- * XXX This is only done on the BSP package.
- */
- if (cpu_vendor_id == CPU_VENDOR_INTEL && cpu_high > 0 && cpu_high < 4 &&
- ((CPUID_TO_FAMILY(cpu_id) == 0xf && CPUID_TO_MODEL(cpu_id) >= 0x3) ||
- (CPUID_TO_FAMILY(cpu_id) == 0x6 && CPUID_TO_MODEL(cpu_id) >= 0xe))) {
- uint64_t msr;
- msr = rdmsr(MSR_IA32_MISC_ENABLE);
- if ((msr & 0x400000ULL) != 0) {
- wrmsr(MSR_IA32_MISC_ENABLE, msr & ~0x400000ULL);
- do_cpuid(0, regs);
- cpu_high = regs[0];
- }
+ if (intel_fix_cpuid()) {
+ do_cpuid(0, regs);
+ cpu_high = regs[0];
}
if (cpu_high >= 5 && (cpu_feature2 & CPUID2_MON) != 0) {
diff --git a/sys/x86/x86/mp_x86.c b/sys/x86/x86/mp_x86.c
index b4c66a5..c23108c 100644
--- a/sys/x86/x86/mp_x86.c
+++ b/sys/x86/x86/mp_x86.c
@@ -602,7 +602,7 @@ init_secondary_tail(void)
mtx_unlock_spin(&ap_boot_mtx);
/* Wait until all the AP's are up. */
- while (smp_started == 0)
+ while (atomic_load_acq_int(&smp_started) == 0)
ia32_pause();
/* Start per-CPU event timers. */
diff --git a/sys/x86/xen/xen_intr.c b/sys/x86/xen/xen_intr.c
index 3bc4b43..a728ddb 100644
--- a/sys/x86/xen/xen_intr.c
+++ b/sys/x86/xen/xen_intr.c
@@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$");
#include <machine/xen/synch_bitops.h>
#include <machine/xen/xen-os.h>
-#include <machine/xen/xenvar.h>
#include <xen/hypervisor.h>
#include <xen/xen_intr.h>
diff --git a/sys/xen/interface/io/blkif.h b/sys/xen/interface/io/blkif.h
index 160547a..9c73ae7 100644
--- a/sys/xen/interface/io/blkif.h
+++ b/sys/xen/interface/io/blkif.h
@@ -97,6 +97,28 @@
*
* The type of the backing device/object.
*
+ *
+ * direct-io-safe
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ *
+ * The underlying storage is not affected by the direct IO memory
+ * lifetime bug. See:
+ * http://lists.xen.org/archives/html/xen-devel/2012-12/msg01154.html
+ *
+ * Therefore this option gives the backend permission to use
+ * O_DIRECT, notwithstanding that bug.
+ *
+ * That is, if this option is enabled, use of O_DIRECT is safe,
+ * in circumstances where we would normally have avoided it as a
+ * workaround for that bug. This option is not relevant for all
+ * backends, and even not necessarily supported for those for
+ * which it is relevant. A backend which knows that it is not
+ * affected by the bug can ignore this option.
+ *
+ * This option doesn't require a backend to use O_DIRECT, so it
+ * should not be used to try to control the caching behaviour.
+ *
*--------------------------------- Features ---------------------------------
*
* feature-barrier
@@ -126,6 +148,34 @@
* of this type may still be returned at any time with the
* BLKIF_RSP_EOPNOTSUPP result code.
*
+ * feature-persistent
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ * Notes: 7
+ *
+ * A value of "1" indicates that the backend can keep the grants used
+ * by the frontend driver mapped, so the same set of grants should be
+ * used in all transactions. The maximum number of grants the backend
+ * can map persistently depends on the implementation, but ideally it
+ * should be RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST. Using this
+ * feature the backend doesn't need to unmap each grant, preventing
+ * costly TLB flushes. The backend driver should only map grants
+ * persistently if the frontend supports it. If a backend driver chooses
+ * to use the persistent protocol when the frontend doesn't support it,
+ * it will probably hit the maximum number of persistently mapped grants
+ * (due to the fact that the frontend won't be reusing the same grants),
+ * and fall back to non-persistent mode. Backend implementations may
+ * shrink or expand the number of persistently mapped grants without
+ * notifying the frontend depending on memory constraints (this might
+ * cause a performance degradation).
+ *
+ * If a backend driver wants to limit the maximum number of persistently
+ * mapped grants to a value less than RING_SIZE *
+ * BLKIF_MAX_SEGMENTS_PER_REQUEST a LRU strategy should be used to
+ * discard the grants that are less commonly used. Using a LRU in the
+ * backend driver paired with a LIFO queue in the frontend will
+ * allow us to have better performance in this scenario.
+ *
*----------------------- Request Transport Parameters ------------------------
*
* max-ring-page-order
@@ -147,6 +197,16 @@
*
*------------------------- Backend Device Properties -------------------------
*
+ * discard-enable
+ * Values: 0/1 (boolean)
+ * Default Value: 1
+ *
+ * This optional property, set by the toolstack, instructs the backend
+ * to offer discard to the frontend. If the property is missing the
+ * backend should offer discard if the backing storage actually supports
+ * it. This optional property, set by the toolstack, requests that the
+ * backend offer, or not offer, discard to the frontend.
+ *
* discard-alignment
* Values: <uint32_t>
* Default Value: 0
@@ -166,6 +226,7 @@
* discard-secure
* Values: 0/1 (boolean)
* Default Value: 0
+ * Notes: 10
*
* A value of "1" indicates that the backend can process BLKIF_OP_DISCARD
* requests with the BLKIF_DISCARD_SECURE flag set.
@@ -180,13 +241,17 @@
* sector-size
* Values: <uint32_t>
*
- * The size, in bytes, of the individually addressible data blocks
- * on the backend device.
+ * The logical sector size, in bytes, of the backend device.
+ *
+ * physical-sector-size
+ * Values: <uint32_t>
+ *
+ * The physical sector size, in bytes, of the backend device.
*
* sectors
* Values: <uint64_t>
*
- * The size of the backend device, expressed in units of its native
+ * The size of the backend device, expressed in units of its logical
* sector size ("sector-size").
*
*****************************************************************************
@@ -243,6 +308,27 @@
* The size of the frontend allocated request ring buffer in units of
* machine pages. The value must be a power of 2.
*
+ * feature-persistent
+ * Values: 0/1 (boolean)
+ * Default Value: 0
+ * Notes: 7, 8, 9
+ *
+ * A value of "1" indicates that the frontend will reuse the same grants
+ * for all transactions, allowing the backend to map them with write
+ * access (even when it should be read-only). If the frontend hits the
+ * maximum number of allowed persistently mapped grants, it can fallback
+ * to non persistent mode. This will cause a performance degradation,
+ * since the the backend driver will still try to map those grants
+ * persistently. Since the persistent grants protocol is compatible with
+ * the previous protocol, a frontend driver can choose to work in
+ * persistent mode even when the backend doesn't support it.
+ *
+ * It is recommended that the frontend driver stores the persistently
+ * mapped grants in a LIFO queue, so a subset of all persistently mapped
+ * grants gets used commonly. This is done in case the backend driver
+ * decides to limit the maximum number of persistently mapped grants
+ * to a value less than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
+ *
*------------------------- Virtual Device Properties -------------------------
*
* device-type
@@ -262,17 +348,23 @@
* -----
* (1) Multi-page ring buffer scheme first developed in the Citrix XenServer
* PV drivers.
- * (2) Multi-page ring buffer scheme first used in some Red Hat distributions
+ * (2) Multi-page ring buffer scheme first used in some RedHat distributions
* including a distribution deployed on certain nodes of the Amazon
* EC2 cluster.
* (3) Support for multi-page ring buffers was implemented independently,
- * in slightly different forms, by both Citrix and Red Hat/Amazon.
+ * in slightly different forms, by both Citrix and RedHat/Amazon.
* For full interoperability, block front and backends should publish
* identical ring parameters, adjusted for unit differences, to the
* XenStore nodes used in both schemes.
- * (4) Devices that support discard functionality may internally allocate
- * space (discardable extents) in units that are larger than the
- * exported logical block size.
+ * (4) Devices that support discard functionality may internally allocate space
+ * (discardable extents) in units that are larger than the exported logical
+ * block size. If the backing device has such discardable extents the
+ * backend should provide both discard-granularity and discard-alignment.
+ * Providing just one of the two may be considered an error by the frontend.
+ * Backends supporting discard should include discard-granularity and
+ * discard-alignment even if it supports discarding individual sectors.
+ * Frontends should assume discard-alignment == 0 and discard-granularity
+ * == sector size if these keys are missing.
* (5) The discard-alignment parameter allows a physical device to be
* partitioned into virtual devices that do not necessarily begin or
* end on a discardable extent boundary.
@@ -280,6 +372,19 @@
* 'ring-ref' is used to communicate the grant reference for this
* page to the backend. When using a multi-page ring, the 'ring-ref'
* node is not created. Instead 'ring-ref0' - 'ring-refN' are used.
+ * (7) When using persistent grants data has to be copied from/to the page
+ * where the grant is currently mapped. The overhead of doing this copy
+ * however doesn't suppress the speed improvement of not having to unmap
+ * the grants.
+ * (8) The frontend driver has to allow the backend driver to map all grants
+ * with write access, even when they should be mapped read-only, since
+ * further requests may reuse these grants and require write permissions.
+ * (9) Linux implementation doesn't have a limit on the maximum number of
+ * grants that can be persistently mapped in the frontend driver, but
+ * due to the frontent driver implementation it should never be bigger
+ * than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
+ *(10) The discard-secure property may be present and will be set to 1 if the
+ * backing device supports secure discard.
*/
/*
@@ -404,6 +509,30 @@
#define BLKIF_OP_DISCARD 5
/*
+ * Recognized if "feature-max-indirect-segments" in present in the backend
+ * xenbus info. The "feature-max-indirect-segments" node contains the maximum
+ * number of segments allowed by the backend per request. If the node is
+ * present, the frontend might use blkif_request_indirect structs in order to
+ * issue requests with more than BLKIF_MAX_SEGMENTS_PER_REQUEST (11). The
+ * maximum number of indirect segments is fixed by the backend, but the
+ * frontend can issue requests with any number of indirect segments as long as
+ * it's less than the number provided by the backend. The indirect_grefs field
+ * in blkif_request_indirect should be filled by the frontend with the
+ * grant references of the pages that are holding the indirect segments.
+ * These pages are filled with an array of blkif_request_segment that hold the
+ * information about the segments. The number of indirect pages to use is
+ * determined by the number of segments an indirect request contains. Every
+ * indirect page can contain a maximum of
+ * (PAGE_SIZE / sizeof(struct blkif_request_segment)) segments, so to
+ * calculate the number of indirect pages to use we have to do
+ * ceil(indirect_segments / (PAGE_SIZE / sizeof(struct blkif_request_segment))).
+ *
+ * If a backend does not recognize BLKIF_OP_INDIRECT, it should *not*
+ * create the "feature-max-indirect-segments" node!
+ */
+#define BLKIF_OP_INDIRECT 6
+
+/*
* Maximum scatter/gather segments per request.
* This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE.
* NB. This could be 12 if the ring indexes weren't stored in the same page.
@@ -411,11 +540,17 @@
#define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
/*
+ * Maximum number of indirect pages to use per request.
+ */
+#define BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST 8
+
+/*
* NB. first_sect and last_sect in blkif_request_segment, as well as
* sector_number in blkif_request, are always expressed in 512-byte units.
* However they must be properly aligned to the real sector size of the
- * physical disk, which is reported in the "sector-size" node in the backend
- * xenbus info. Also the xenbus "sectors" node is expressed in 512-byte units.
+ * physical disk, which is reported in the "physical-sector-size" node in
+ * the backend xenbus info. Also the xenbus "sectors" node is expressed in
+ * 512-byte units.
*/
struct blkif_request_segment {
grant_ref_t gref; /* reference to I/O buffer frame */
@@ -453,6 +588,20 @@ struct blkif_request_discard {
};
typedef struct blkif_request_discard blkif_request_discard_t;
+struct blkif_request_indirect {
+ uint8_t operation; /* BLKIF_OP_INDIRECT */
+ uint8_t indirect_op; /* BLKIF_OP_{READ/WRITE} */
+ uint16_t nr_segments; /* number of segments */
+ uint64_t id; /* private guest value, echoed in resp */
+ blkif_sector_t sector_number;/* start sector idx on disk (r/w only) */
+ blkif_vdev_t handle; /* same as for read/write requests */
+ grant_ref_t indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
+#ifdef __i386__
+ uint64_t pad; /* Make it 64 byte aligned on i386 */
+#endif
+};
+typedef struct blkif_request_indirect blkif_request_indirect_t;
+
struct blkif_response {
uint64_t id; /* copied from request */
uint8_t operation; /* copied from request */
@@ -484,7 +633,7 @@ DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response);
/*
* Local variables:
* mode: C
- * c-set-style: "BSD"
+ * c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
diff --git a/tests/sys/kern/ptrace_test.c b/tests/sys/kern/ptrace_test.c
index a64262a..c10c097 100644
--- a/tests/sys/kern/ptrace_test.c
+++ b/tests/sys/kern/ptrace_test.c
@@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$");
#exp " not met"); \
} while (0)
-static void __dead2
+static __dead2 void
child_fail_require(const char *file, int line, const char *str)
{
char buf[128];
@@ -60,6 +60,58 @@ child_fail_require(const char *file, int line, const char *str)
_exit(32);
}
+static void
+trace_me(void)
+{
+
+ /* Attach the parent process as a tracer of this process. */
+ CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
+
+ /* Trigger a stop. */
+ raise(SIGSTOP);
+}
+
+static void
+attach_child(pid_t pid)
+{
+ pid_t wpid;
+ int status;
+
+ ATF_REQUIRE(ptrace(PT_ATTACH, pid, NULL, 0) == 0);
+
+ wpid = waitpid(pid, &status, 0);
+ ATF_REQUIRE(wpid == pid);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+}
+
+static void
+wait_for_zombie(pid_t pid)
+{
+
+ /*
+ * Wait for a process to exit. This is kind of gross, but
+ * there is not a better way.
+ */
+ for (;;) {
+ struct kinfo_proc kp;
+ size_t len;
+ int mib[4];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = pid;
+ len = sizeof(kp);
+ if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
+ /* The KERN_PROC_PID sysctl fails for zombies. */
+ ATF_REQUIRE(errno == ESRCH);
+ break;
+ }
+ usleep(5000);
+ }
+}
+
/*
* Verify that a parent debugger process "sees" the exit of a debugged
* process exactly once when attached via PT_TRACE_ME.
@@ -73,10 +125,7 @@ ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc)
ATF_REQUIRE((child = fork()) != -1);
if (child == 0) {
/* Child process. */
- CHILD_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
-
- /* Trigger a stop. */
- raise(SIGSTOP);
+ trace_me();
exit(1);
}
@@ -131,13 +180,7 @@ ATF_TC_BODY(ptrace__parent_wait_after_attach, tc)
/* Parent process. */
/* Attach to the child process. */
- ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) == 0);
-
- /* The first wait() should report the SIGSTOP from PT_ATTACH. */
- wpid = waitpid(child, &status, 0);
- ATF_REQUIRE(wpid == child);
- ATF_REQUIRE(WIFSTOPPED(status));
- ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+ attach_child(child);
/* Continue the child ignoring the SIGSTOP. */
ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1);
@@ -223,27 +266,7 @@ ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc)
ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
close(cpipe[0]);
- /*
- * Wait for the child to exit. This is kind of gross, but
- * there is not a better way.
- */
- for (;;) {
- struct kinfo_proc kp;
- size_t len;
- int mib[4];
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PID;
- mib[3] = child;
- len = sizeof(kp);
- if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
- /* The KERN_PROC_PID sysctl fails for zombies. */
- ATF_REQUIRE(errno == ESRCH);
- break;
- }
- usleep(5000);
- }
+ wait_for_zombie(child);
/*
* This wait should return a pid of 0 to indicate no status to
@@ -357,27 +380,7 @@ ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0);
close(cpipe[0]);
- /*
- * Wait for the child to exit. This is kind of gross, but
- * there is not a better way.
- */
- for (;;) {
- struct kinfo_proc kp;
- size_t len;
- int mib[4];
-
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PID;
- mib[3] = child;
- len = sizeof(kp);
- if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) {
- /* The KERN_PROC_PID sysctl fails for zombies. */
- ATF_REQUIRE(errno == ESRCH);
- break;
- }
- usleep(5000);
- }
+ wait_for_zombie(child);
/*
* This wait should return a pid of 0 to indicate no status to
@@ -401,6 +404,468 @@ ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc)
ATF_REQUIRE(WEXITSTATUS(status) == 1);
}
+/*
+ * The parent process should always act the same regardless of how the
+ * debugger is attached to it.
+ */
+static __dead2 void
+follow_fork_parent(void)
+{
+ pid_t fpid, wpid;
+ int status;
+
+ CHILD_REQUIRE((fpid = fork()) != -1);
+
+ if (fpid == 0)
+ /* Child */
+ exit(2);
+
+ wpid = waitpid(fpid, &status, 0);
+ CHILD_REQUIRE(wpid == fpid);
+ CHILD_REQUIRE(WIFEXITED(status));
+ CHILD_REQUIRE(WEXITSTATUS(status) == 2);
+
+ exit(1);
+}
+
+/*
+ * Helper routine for follow fork tests. This waits for two stops
+ * that report both "sides" of a fork. It returns the pid of the new
+ * child process.
+ */
+static pid_t
+handle_fork_events(pid_t parent)
+{
+ struct ptrace_lwpinfo pl;
+ bool fork_reported[2];
+ pid_t child, wpid;
+ int i, status;
+
+ fork_reported[0] = false;
+ fork_reported[1] = false;
+ child = -1;
+
+ /*
+ * Each process should report a fork event. The parent should
+ * report a PL_FLAG_FORKED event, and the child should report
+ * a PL_FLAG_CHILD event.
+ */
+ for (i = 0; i < 2; i++) {
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid > 0);
+ ATF_REQUIRE(WIFSTOPPED(status));
+
+ ATF_REQUIRE(ptrace(PT_LWPINFO, wpid, (caddr_t)&pl,
+ sizeof(pl)) != -1);
+ ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
+ 0);
+ ATF_REQUIRE((pl.pl_flags & (PL_FLAG_FORKED | PL_FLAG_CHILD)) !=
+ (PL_FLAG_FORKED | PL_FLAG_CHILD));
+ if (pl.pl_flags & PL_FLAG_CHILD) {
+ ATF_REQUIRE(wpid != parent);
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+ ATF_REQUIRE(!fork_reported[1]);
+ if (child == -1)
+ child = wpid;
+ else
+ ATF_REQUIRE(child == wpid);
+ fork_reported[1] = true;
+ } else {
+ ATF_REQUIRE(wpid == parent);
+ ATF_REQUIRE(WSTOPSIG(status) == SIGTRAP);
+ ATF_REQUIRE(!fork_reported[0]);
+ if (child == -1)
+ child = pl.pl_child_pid;
+ else
+ ATF_REQUIRE(child == pl.pl_child_pid);
+ fork_reported[0] = true;
+ }
+ }
+
+ return (child);
+}
+
+/*
+ * Verify that a new child process is stopped after a followed fork and
+ * that the traced parent sees the exit of the child after the debugger
+ * when both processes remain attached to the debugger.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached);
+ATF_TC_BODY(ptrace__follow_fork_both_attached, tc)
+{
+ pid_t children[0], fpid, wpid;
+ int status;
+
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ trace_me();
+ follow_fork_parent();
+ }
+
+ /* Parent process. */
+ children[0] = fpid;
+
+ /* The first wait() should report the stop from SIGSTOP. */
+ wpid = waitpid(children[0], &status, 0);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
+
+ /* Continue the child ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+
+ children[1] = handle_fork_events(children[0]);
+ ATF_REQUIRE(children[1] > 0);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
+
+ /*
+ * The child can't exit until the grandchild reports status, so the
+ * grandchild should report its exit first to the debugger.
+ */
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[1]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 2);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+/*
+ * Verify that a new child process is stopped after a followed fork
+ * and that the traced parent sees the exit of the child when the new
+ * child process is detached after it reports its fork.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached);
+ATF_TC_BODY(ptrace__follow_fork_child_detached, tc)
+{
+ pid_t children[0], fpid, wpid;
+ int status;
+
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ trace_me();
+ follow_fork_parent();
+ }
+
+ /* Parent process. */
+ children[0] = fpid;
+
+ /* The first wait() should report the stop from SIGSTOP. */
+ wpid = waitpid(children[0], &status, 0);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
+
+ /* Continue the child ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+
+ children[1] = handle_fork_events(children[0]);
+ ATF_REQUIRE(children[1] > 0);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
+
+ /*
+ * Should not see any status from the grandchild now, only the
+ * child.
+ */
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+/*
+ * Verify that a new child process is stopped after a followed fork
+ * and that the traced parent sees the exit of the child when the
+ * traced parent is detached after the fork.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached);
+ATF_TC_BODY(ptrace__follow_fork_parent_detached, tc)
+{
+ pid_t children[0], fpid, wpid;
+ int status;
+
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ trace_me();
+ follow_fork_parent();
+ }
+
+ /* Parent process. */
+ children[0] = fpid;
+
+ /* The first wait() should report the stop from SIGSTOP. */
+ wpid = waitpid(children[0], &status, 0);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFSTOPPED(status));
+ ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP);
+
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
+
+ /* Continue the child ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+
+ children[1] = handle_fork_events(children[0]);
+ ATF_REQUIRE(children[1] > 0);
+
+ ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
+
+ /*
+ * The child can't exit until the grandchild reports status, so the
+ * grandchild should report its exit first to the debugger.
+ *
+ * Even though the child process is detached, it is still a
+ * child of the debugger, so it will still report it's exit
+ * after the grandchild.
+ */
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[1]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 2);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+static void
+attach_fork_parent(int cpipe[2])
+{
+ pid_t fpid;
+
+ close(cpipe[0]);
+
+ /* Double-fork to disassociate from the debugger. */
+ CHILD_REQUIRE((fpid = fork()) != -1);
+ if (fpid != 0)
+ exit(3);
+
+ /* Send the pid of the disassociated child to the debugger. */
+ fpid = getpid();
+ CHILD_REQUIRE(write(cpipe[1], &fpid, sizeof(fpid)) == sizeof(fpid));
+
+ /* Wait for the debugger to attach. */
+ CHILD_REQUIRE(read(cpipe[1], &fpid, sizeof(fpid)) == 0);
+}
+
+/*
+ * Verify that a new child process is stopped after a followed fork and
+ * that the traced parent sees the exit of the child after the debugger
+ * when both processes remain attached to the debugger. In this test
+ * the parent that forks is not a direct child of the debugger.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_both_attached_unrelated_debugger);
+ATF_TC_BODY(ptrace__follow_fork_both_attached_unrelated_debugger, tc)
+{
+ pid_t children[0], fpid, wpid;
+ int cpipe[2], status;
+
+ ATF_REQUIRE(pipe(cpipe) == 0);
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ attach_fork_parent(cpipe);
+ follow_fork_parent();
+ }
+
+ /* Parent process. */
+ close(cpipe[1]);
+
+ /* Wait for the direct child to exit. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 3);
+
+ /* Read the pid of the fork parent. */
+ ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
+ sizeof(children[0]));
+
+ /* Attach to the fork parent. */
+ attach_child(children[0]);
+
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
+
+ /* Continue the fork parent ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+
+ /* Signal the fork parent to continue. */
+ close(cpipe[0]);
+
+ children[1] = handle_fork_events(children[0]);
+ ATF_REQUIRE(children[1] > 0);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
+
+ /*
+ * The fork parent can't exit until the child reports status,
+ * so the child should report its exit first to the debugger.
+ */
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[1]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 2);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+/*
+ * Verify that a new child process is stopped after a followed fork
+ * and that the traced parent sees the exit of the child when the new
+ * child process is detached after it reports its fork. In this test
+ * the parent that forks is not a direct child of the debugger.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_child_detached_unrelated_debugger);
+ATF_TC_BODY(ptrace__follow_fork_child_detached_unrelated_debugger, tc)
+{
+ pid_t children[0], fpid, wpid;
+ int cpipe[2], status;
+
+ ATF_REQUIRE(pipe(cpipe) == 0);
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ attach_fork_parent(cpipe);
+ follow_fork_parent();
+ }
+
+ /* Parent process. */
+ close(cpipe[1]);
+
+ /* Wait for the direct child to exit. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 3);
+
+ /* Read the pid of the fork parent. */
+ ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
+ sizeof(children[0]));
+
+ /* Attach to the fork parent. */
+ attach_child(children[0]);
+
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
+
+ /* Continue the fork parent ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+
+ /* Signal the fork parent to continue. */
+ close(cpipe[0]);
+
+ children[1] = handle_fork_events(children[0]);
+ ATF_REQUIRE(children[1] > 0);
+
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_DETACH, children[1], (caddr_t)1, 0) != -1);
+
+ /*
+ * Should not see any status from the child now, only the fork
+ * parent.
+ */
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[0]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 1);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
+/*
+ * Verify that a new child process is stopped after a followed fork
+ * and that the traced parent sees the exit of the child when the
+ * traced parent is detached after the fork. In this test the parent
+ * that forks is not a direct child of the debugger.
+ */
+ATF_TC_WITHOUT_HEAD(ptrace__follow_fork_parent_detached_unrelated_debugger);
+ATF_TC_BODY(ptrace__follow_fork_parent_detached_unrelated_debugger, tc)
+{
+ pid_t children[0], fpid, wpid;
+ int cpipe[2], status;
+
+ ATF_REQUIRE(pipe(cpipe) == 0);
+ ATF_REQUIRE((fpid = fork()) != -1);
+ if (fpid == 0) {
+ attach_fork_parent(cpipe);
+ follow_fork_parent();
+ }
+
+ /* Parent process. */
+ close(cpipe[1]);
+
+ /* Wait for the direct child to exit. */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE(wpid == fpid);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 3);
+
+ /* Read the pid of the fork parent. */
+ ATF_REQUIRE(read(cpipe[0], &children[0], sizeof(children[0])) ==
+ sizeof(children[0]));
+
+ /* Attach to the fork parent. */
+ attach_child(children[0]);
+
+ ATF_REQUIRE(ptrace(PT_FOLLOW_FORK, children[0], NULL, 1) != -1);
+
+ /* Continue the fork parent ignoring the SIGSTOP. */
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[0], (caddr_t)1, 0) != -1);
+
+ /* Signal the fork parent to continue. */
+ close(cpipe[0]);
+
+ children[1] = handle_fork_events(children[0]);
+ ATF_REQUIRE(children[1] > 0);
+
+ ATF_REQUIRE(ptrace(PT_DETACH, children[0], (caddr_t)1, 0) != -1);
+ ATF_REQUIRE(ptrace(PT_CONTINUE, children[1], (caddr_t)1, 0) != -1);
+
+ /*
+ * Should not see any status from the fork parent now, only
+ * the child.
+ */
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == children[1]);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE(WEXITSTATUS(status) == 2);
+
+ wpid = wait(&status);
+ ATF_REQUIRE(wpid == -1);
+ ATF_REQUIRE(errno == ECHILD);
+}
+
ATF_TP_ADD_TCS(tp)
{
@@ -408,6 +873,14 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach);
ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger);
ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger);
+ ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached);
+ ATF_TP_ADD_TC(tp, ptrace__follow_fork_child_detached);
+ ATF_TP_ADD_TC(tp, ptrace__follow_fork_parent_detached);
+ ATF_TP_ADD_TC(tp, ptrace__follow_fork_both_attached_unrelated_debugger);
+ ATF_TP_ADD_TC(tp,
+ ptrace__follow_fork_child_detached_unrelated_debugger);
+ ATF_TP_ADD_TC(tp,
+ ptrace__follow_fork_parent_detached_unrelated_debugger);
return (atf_no_error());
}
diff --git a/tests/sys/kern/unix_seqpacket_test.c b/tests/sys/kern/unix_seqpacket_test.c
index ccbacaf..986b70e 100644
--- a/tests/sys/kern/unix_seqpacket_test.c
+++ b/tests/sys/kern/unix_seqpacket_test.c
@@ -751,35 +751,79 @@ ATF_TC_BODY(send_recv_with_connect, tc)
ATF_TC_WITHOUT_HEAD(shutdown_send);
ATF_TC_BODY(shutdown_send, tc)
{
- int s;
- const char data[] = "data";
+ struct sockaddr_un sun;
+ /* ATF's isolation mechanisms will guarantee uniqueness of this file */
+ const char *path = "sock";
+ const char *data = "data";
ssize_t ssize;
+ int s, err, s2;
s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
ATF_REQUIRE(s >= 0);
- ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
+
+ bzero(&sun, sizeof(sun));
+ sun.sun_family = AF_LOCAL;
+ sun.sun_len = sizeof(sun);
+ strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
+ err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
+ err = listen(s, -1);
+ ATF_CHECK_EQ(0, err);
+
+ /* Create the other socket */
+ s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
+ ATF_REQUIRE(s2 >= 0);
+ err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
+ if (err != 0) {
+ perror("connect");
+ atf_tc_fail("connect(2) failed");
+ }
+
+ ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
/* USE MSG_NOSIGNAL so we don't get SIGPIPE */
- ssize = send(s, data, sizeof(data), MSG_EOR | MSG_NOSIGNAL);
+ ssize = send(s2, data, sizeof(data), MSG_EOR | MSG_NOSIGNAL);
ATF_CHECK_EQ(EPIPE, errno);
ATF_CHECK_EQ(-1, ssize);
close(s);
+ close(s2);
}
/* send(2) should cause SIGPIPE on a shutdown socket */
ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
ATF_TC_BODY(shutdown_send_sigpipe, tc)
{
- int s;
- const char data[] = "data";
+ struct sockaddr_un sun;
+ /* ATF's isolation mechanisms will guarantee uniqueness of this file */
+ const char *path = "sock";
+ const char *data = "data";
ssize_t ssize;
+ int s, err, s2;
s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
ATF_REQUIRE(s >= 0);
- ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
+
+ bzero(&sun, sizeof(sun));
+ sun.sun_family = AF_LOCAL;
+ sun.sun_len = sizeof(sun);
+ strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
+ err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
+ err = listen(s, -1);
+ ATF_CHECK_EQ(0, err);
+
+ /* Create the other socket */
+ s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
+ ATF_REQUIRE(s2 >= 0);
+ err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
+ if (err != 0) {
+ perror("connect");
+ atf_tc_fail("connect(2) failed");
+ }
+
+ ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
- ssize = send(s, data, sizeof(data), MSG_EOR);
+ ssize = send(s2, data, sizeof(data), MSG_EOR);
ATF_CHECK_EQ(1, got_sigpipe);
close(s);
+ close(s2);
}
/* nonblocking send(2) and recv(2) a single short record */
diff --git a/tests/sys/vm/Makefile b/tests/sys/vm/Makefile
index 1795eef..08fbb21 100644
--- a/tests/sys/vm/Makefile
+++ b/tests/sys/vm/Makefile
@@ -2,6 +2,6 @@
TESTSDIR= ${TESTSBASE}/sys/vm
-TAP_TESTS_C+= mmap_test
+ATF_TESTS_C+= mmap_test
.include <bsd.test.mk>
diff --git a/tests/sys/vm/mmap_test.c b/tests/sys/vm/mmap_test.c
index 7591a09..00abeb6 100644
--- a/tests/sys/vm/mmap_test.c
+++ b/tests/sys/vm/mmap_test.c
@@ -29,16 +29,18 @@
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/sysctl.h>
-#include <sys/types.h>
+#include <atf-c.h>
#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
#include <stdio.h>
-#include <string.h>
+#include <stdlib.h>
static const struct {
void *addr;
int ok[2]; /* Depending on security.bsd.map_at_zero {0, !=0}. */
-} tests[] = {
+} map_at_zero_tests[] = {
{ (void *)0, { 0, 1 } }, /* Test sysctl. */
{ (void *)1, { 0, 0 } },
{ (void *)(PAGE_SIZE - 1), { 0, 0 } },
@@ -52,54 +54,111 @@ static const struct {
#define MAP_AT_ZERO "security.bsd.map_at_zero"
-int
-main(void)
+ATF_TC_WITHOUT_HEAD(mmap__map_at_zero);
+ATF_TC_BODY(mmap__map_at_zero, tc)
{
void *p;
size_t len;
- int i, error, mib[3], map_at_zero;
-
- error = 0;
-
- /* Get the current sysctl value of security.bsd.map_at_zero. */
- len = sizeof(mib) / sizeof(*mib);
- if (sysctlnametomib(MAP_AT_ZERO, mib, &len) == -1) {
- printf("1..0 # SKIP: sysctlnametomib(\"%s\") failed: %s\n",
- MAP_AT_ZERO, strerror(errno));
- return (0);
- }
+ unsigned int i;
+ int map_at_zero;
len = sizeof(map_at_zero);
- if (sysctl(mib, 3, &map_at_zero, &len, NULL, 0) == -1) {
- printf("1..0 # SKIP: sysctl for %s failed: %s\n", MAP_AT_ZERO,
+ if (sysctlbyname(MAP_AT_ZERO, &map_at_zero, &len, NULL, 0) == -1) {
+ atf_tc_skip("sysctl for %s failed: %s\n", MAP_AT_ZERO,
strerror(errno));
- return (0);
+ return;
}
/* Normalize to 0 or 1 for array access. */
map_at_zero = !!map_at_zero;
- printf("1..%zu\n", nitems(tests));
- for (i = 0; i < (int)nitems(tests); i++) {
- p = mmap((void *)tests[i].addr, PAGE_SIZE,
+ for (i = 0; i < nitems(map_at_zero_tests); i++) {
+ p = mmap((void *)map_at_zero_tests[i].addr, PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_FIXED,
-1, 0);
if (p == MAP_FAILED) {
- if (tests[i].ok[map_at_zero] != 0)
- error++;
- printf("%sok %d # mmap(%p, ...) failed\n",
- tests[i].ok[map_at_zero] == 0 ? "" : "not ",
- i + 1,
- tests[i].addr);
+ ATF_CHECK_MSG(map_at_zero_tests[i].ok[map_at_zero] == 0,
+ "mmap(%p, ...) failed", map_at_zero_tests[i].addr);
} else {
- if (tests[i].ok[map_at_zero] != 1)
- error++;
- printf("%sok %d # mmap(%p, ...) succeeded: p=%p\n",
- tests[i].ok[map_at_zero] == 1 ? "" : "not ",
- i + 1,
- tests[i].addr, p);
+ ATF_CHECK_MSG(map_at_zero_tests[i].ok[map_at_zero] == 1,
+ "mmap(%p, ...) succeeded: p=%p\n",
+ map_at_zero_tests[i].addr, p);
}
}
+}
+
+static void
+checked_mmap(int prot, int flags, int fd, int error, const char *msg)
+{
+ void *p;
+
+ p = mmap(NULL, getpagesize(), prot, flags, fd, 0);
+ if (p == MAP_FAILED) {
+ if (error == 0)
+ ATF_CHECK_MSG(0, "%s failed with errno %d", msg,
+ errno);
+ else
+ ATF_CHECK_EQ_MSG(error, errno,
+ "%s failed with wrong errno %d (expected %d)", msg,
+ errno, error);
+ } else {
+ ATF_CHECK_MSG(error == 0, "%s succeeded", msg);
+ munmap(p, getpagesize());
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(mmap__bad_arguments);
+ATF_TC_BODY(mmap__bad_arguments, tc)
+{
+ int fd;
+
+ ATF_REQUIRE((fd = shm_open(SHM_ANON, O_RDWR, 0644)) >= 0);
+ ATF_REQUIRE(ftruncate(fd, getpagesize()) == 0);
+
+ /* These should work. */
+ checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON, -1, 0,
+ "simple MAP_ANON");
+ checked_mmap(PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0,
+ "simple shm fd shared");
+ checked_mmap(PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0,
+ "simple shm fd private");
+
+ /* Extra PROT flags. */
+ checked_mmap(PROT_READ | PROT_WRITE | 0x100000, MAP_ANON, -1, EINVAL,
+ "MAP_ANON with extra PROT flags");
+ checked_mmap(0xffff, MAP_SHARED, fd, EINVAL,
+ "shm fd with garbage PROT");
+
+ /* Undefined flag. */
+ checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_RESERVED0080, -1,
+ EINVAL, "Undefined flag");
+
+ /* Both MAP_SHARED and MAP_PRIVATE */
+ checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE |
+ MAP_SHARED, -1, EINVAL, "MAP_ANON with both SHARED and PRIVATE");
+ checked_mmap(PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_SHARED, fd,
+ EINVAL, "shm fd with both SHARED and PRIVATE");
+
+ /* At least one of MAP_SHARED or MAP_PRIVATE without ANON */
+ checked_mmap(PROT_READ | PROT_WRITE, 0, fd, EINVAL,
+ "shm fd without sharing flag");
+
+ /* MAP_ANON with either sharing flag (impacts fork). */
+ checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0,
+ "shared MAP_ANON");
+ checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0,
+ "private MAP_ANON");
+
+ /* MAP_ANON should require an fd of -1. */
+ checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, EINVAL,
+ "MAP_ANON with fd != -1");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mmap__map_at_zero);
+ ATF_TP_ADD_TC(tp, mmap__bad_arguments);
- return (error != 0);
+ return (atf_no_error());
}
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index dbbe283..532db1e 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -184,9 +184,10 @@ OLD_DIRS+=usr/share/examples/bhyve
.if ${MK_BINUTILS} == no
OLD_FILES+=usr/bin/as
OLD_FILES+=usr/bin/ld
+.if ${MK_ELFTOOLCHAIN_TOOLS} != no && ${MK_ELFCOPY_AS_OBJCOPY} == no
OLD_FILES+=usr/bin/objcopy
+.endif
OLD_FILES+=usr/bin/objdump
-OLD_FILES+=usr/bin/readelf
OLD_FILES+=usr/libdata/ldscripts/elf_x86_64_fbsd.x
OLD_FILES+=usr/libdata/ldscripts/elf_x86_64_fbsd.xbn
OLD_FILES+=usr/libdata/ldscripts/elf_x86_64_fbsd.xc
@@ -202,9 +203,10 @@ OLD_FILES+=usr/libdata/ldscripts/elf_x86_64_fbsd.xu
OLD_FILES+=usr/libdata/ldscripts/elf_x86_64_fbsd.xw
OLD_FILES+=usr/share/man/man1/as.1.gz
OLD_FILES+=usr/share/man/man1/ld.1.gz
+.if ${MK_ELFTOOLCHAIN_TOOLS} != no && ${MK_ELFCOPY_AS_OBJCOPY} == no
OLD_FILES+=usr/share/man/man1/objcopy.1.gz
+.endif
OLD_FILES+=usr/share/man/man1/objdump.1.gz
-OLD_FILES+=usr/share/man/man1/readelf.1.gz
OLD_FILES+=usr/share/man/man7/as.7.gz
OLD_FILES+=usr/share/man/man7/ld.7.gz
OLD_FILES+=usr/share/man/man7/ldint.7.gz
@@ -1039,9 +1041,6 @@ OLD_DIRS+=usr/include/fs/cuse
.if ${MK_CXX} == no
OLD_FILES+=usr/bin/CC
OLD_FILES+=usr/bin/c++
-.if ${MK_ELFTOOLCHAIN_TOOLS} == no
-OLD_FILES+=usr/bin/c++filt
-.endif
OLD_FILES+=usr/bin/g++
OLD_FILES+=usr/libexec/cc1plus
.endif
@@ -1664,11 +1663,29 @@ OLD_FILES+=usr/share/nls/ru_RU.KOI8-R/ee.cat
OLD_FILES+=usr/share/nls/uk_UA.KOI8-U/ee.cat
.endif
-.if ${MK_ELFTOOLCHAIN_TOOLS} == no
+.if ${MK_ELFTOOLCHAIN_TOOLS} == no || \
+ (${MK_ELFTOOLCHAIN_TOOLS} != no && ${MK_ELFCOPY_AS_OBJCOPY} != no)
OLD_FILES+=usr/bin/elfcopy
OLD_FILES+=usr/share/man/man1/elfcopy.1.gz
.endif
+.if ${MK_ELFTOOLCHAIN_TOOLS} == no
+OLD_FILES+=usr/bin/addr2line
+OLD_FILES+=usr/bin/c++filt
+OLD_FILES+=usr/bin/nm
+OLD_FILES+=usr/bin/readelf
+OLD_FILES+=usr/bin/size
+OLD_FILES+=usr/bin/strings
+OLD_FILES+=usr/bin/strip
+OLD_FILES+=usr/share/man/man1/addr2line.1.gz
+OLD_FILES+=usr/share/man/man1/c++filt.1.gz
+OLD_FILES+=usr/share/man/man1/nm.1.gz
+OLD_FILES+=usr/share/man/man1/readelf.1.gz
+OLD_FILES+=usr/share/man/man1/size.1.gz
+OLD_FILES+=usr/share/man/man1/strings.1.gz
+OLD_FILES+=usr/share/man/man1/strip.1.gz
+.endif
+
#.if ${MK_EXAMPLES} == no
# to be filled in
#.endif
@@ -1751,9 +1768,6 @@ OLD_FILES+=usr/share/man/man8/unstr.8.gz
.endif
.if ${MK_GCC} == no
-.if ${MK_ELFTOOLCHAIN_TOOLS} == no
-OLD_FILES+=usr/bin/c++filt
-.endif
OLD_FILES+=usr/bin/g++
OLD_FILES+=usr/bin/gcc
OLD_FILES+=usr/bin/gcov
diff --git a/tools/build/options/WITHOUT_BINUTILS b/tools/build/options/WITHOUT_BINUTILS
index dd95162..b68aa52 100644
--- a/tools/build/options/WITHOUT_BINUTILS
+++ b/tools/build/options/WITHOUT_BINUTILS
@@ -1,5 +1,4 @@
.\" $FreeBSD$
-Set to not build or install binutils (as, c++-filt, gconv,
-ld, nm, objcopy, objdump, readelf, size and strip) as part
+Set to not build or install binutils (as, ld, objcopy, and objdump ) as part
of the normal system build.
The resulting system cannot build programs from source.
diff --git a/tools/build/options/WITHOUT_ELFCOPY_AS_OBJCOPY b/tools/build/options/WITHOUT_ELFCOPY_AS_OBJCOPY
new file mode 100644
index 0000000..f06a606
--- /dev/null
+++ b/tools/build/options/WITHOUT_ELFCOPY_AS_OBJCOPY
@@ -0,0 +1,4 @@
+.\" $FreeBSD$
+Set to build and install
+.Xr objcopy 1
+from GNU Binutils, instead of the one from ELF Tool Chain.
diff --git a/tools/build/options/WITHOUT_ELFTOOLCHAIN_TOOLS b/tools/build/options/WITHOUT_ELFTOOLCHAIN_TOOLS
index e478058..e30f48d 100644
--- a/tools/build/options/WITHOUT_ELFTOOLCHAIN_TOOLS
+++ b/tools/build/options/WITHOUT_ELFTOOLCHAIN_TOOLS
@@ -1,9 +1,10 @@
.\" $FreeBSD$
-Set to use
+Set to avoid building ELF Tool Chain tools
.Xr addr2line 1 ,
+.Xr c++filt 1 ,
.Xr nm 1 ,
+.Xr readelf 1 ,
.Xr size 1 ,
.Xr strings 1 ,
and
-.Xr strip 1
-from GNU binutils instead of the ELF Tool Chain project.
+.Xr strip 1 .
diff --git a/tools/build/options/WITH_DTRACE_TESTS b/tools/build/options/WITH_DTRACE_TESTS
new file mode 100644
index 0000000..dc85e2b
--- /dev/null
+++ b/tools/build/options/WITH_DTRACE_TESTS
@@ -0,0 +1,5 @@
+.\" $FreeBSD$
+Set to build and install the DTrace test suite in
+.Pa /usr/tests/cddl/usr.sbin/dtrace .
+This test suite is considered experimental on architectures other than
+amd64/amd64 and running it may cause system instability.
diff --git a/tools/build/options/WITH_ELFCOPY_AS_OBJCOPY b/tools/build/options/WITH_ELFCOPY_AS_OBJCOPY
new file mode 100644
index 0000000..eabaac3
--- /dev/null
+++ b/tools/build/options/WITH_ELFCOPY_AS_OBJCOPY
@@ -0,0 +1,4 @@
+.\" $FreeBSD$
+Set to build and install ELF Tool Chain's elfcopy as
+.Xr objcopy 1 ,
+instead of the one from GNU Binutils.
diff --git a/tools/bus_space/C/lang.c b/tools/bus_space/C/lang.c
index f9b404b..3ef4544 100644
--- a/tools/bus_space/C/lang.c
+++ b/tools/bus_space/C/lang.c
@@ -227,8 +227,15 @@ busdma_seg_get_size(busdma_seg_t seg)
}
int
-busdma_sync(busdma_md_t md, int op, bus_addr_t base, bus_size_t size)
+busdma_sync(busdma_md_t md, int op)
{
- return (bd_sync(md, op, base, size));
+ return (bd_sync(md, op, 0UL, ~0UL));
+}
+
+int
+busdma_sync_range(busdma_md_t md, int op, bus_size_t ofs, bus_size_t len)
+{
+
+ return (bd_sync(md, op, ofs, len));
}
diff --git a/tools/bus_space/C/libbus.h b/tools/bus_space/C/libbus.h
index 0fae987..1f0c3f1 100644
--- a/tools/bus_space/C/libbus.h
+++ b/tools/bus_space/C/libbus.h
@@ -78,6 +78,7 @@ bus_size_t busdma_seg_get_size(busdma_seg_t seg);
#define BUSDMA_SYNC_PREWRITE 4
#define BUSDMA_SYNC_POSTWRITE 8
-int busdma_sync(busdma_md_t md, int op, bus_addr_t, bus_size_t);
+int busdma_sync(busdma_md_t md, int op);
+int busdma_sync_range(busdma_md_t md, int op, bus_size_t, bus_size_t);
#endif /* _LIBBUS_SPACE_H_ */
diff --git a/tools/bus_space/Python/lang.c b/tools/bus_space/Python/lang.c
index 48a112b..0fde8fc 100644
--- a/tools/bus_space/Python/lang.c
+++ b/tools/bus_space/Python/lang.c
@@ -384,12 +384,27 @@ busdma_seg_get_size(PyObject *self, PyObject *args)
static PyObject *
busdma_sync(PyObject *self, PyObject *args)
{
- u_long base, size;
int error, mdid, op;
- if (!PyArg_ParseTuple(args, "iikk", &mdid, &op, &base, &size))
+ if (!PyArg_ParseTuple(args, "ii", &mdid, &op))
return (NULL);
- error = bd_sync(mdid, op, base, size);
+ error = bd_sync(mdid, op, 0UL, ~0UL);
+ if (error) {
+ PyErr_SetString(PyExc_IOError, strerror(error));
+ return (NULL);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+busdma_sync_range(PyObject *self, PyObject *args)
+{
+ u_long ofs, len;
+ int error, mdid, op;
+
+ if (!PyArg_ParseTuple(args, "iikk", &mdid, &op, &ofs, &len))
+ return (NULL);
+ error = bd_sync(mdid, op, ofs, len);
if (error) {
PyErr_SetString(PyExc_IOError, strerror(error));
return (NULL);
@@ -448,7 +463,9 @@ static PyMethodDef busdma_methods[] = {
"Return the size of the segment." },
{ "sync", busdma_sync, METH_VARARGS,
- "Keep memory/caches coherent WRT to DMA." },
+ "Make the entire memory descriptor coherent WRT to DMA." },
+ { "sync_range", busdma_sync_range, METH_VARARGS,
+ "Make part of the memory descriptor coherent WRT to DMA." },
{ NULL, NULL, 0, NULL }
};
diff --git a/tools/bus_space/busdma.c b/tools/bus_space/busdma.c
index 3f948b7..04a9da8 100644
--- a/tools/bus_space/busdma.c
+++ b/tools/bus_space/busdma.c
@@ -536,7 +536,7 @@ bd_seg_get_size(int sid, u_long *size_p)
}
int
-bd_sync(int mdid, u_int op, u_long base, u_long size)
+bd_sync(int mdid, u_int op, u_long ofs, u_long len)
{
struct proto_ioc_busdma ioc;
struct obj *md;
@@ -549,8 +549,8 @@ bd_sync(int mdid, u_int op, u_long base, u_long size)
ioc.request = PROTO_IOC_BUSDMA_SYNC;
ioc.key = md->key;
ioc.u.sync.op = op;
- ioc.u.sync.base = base;
- ioc.u.sync.size = size;
+ ioc.u.sync.base = ofs;
+ ioc.u.sync.size = len;
if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1)
return (errno);
diff --git a/tools/bus_space/busdma.h b/tools/bus_space/busdma.h
index cf9d4f2..ec4890d 100644
--- a/tools/bus_space/busdma.h
+++ b/tools/bus_space/busdma.h
@@ -51,6 +51,6 @@ int bd_md_next_seg(int mdid, int sid);
int bd_seg_get_addr(int sid, u_long *);
int bd_seg_get_size(int sid, u_long *);
-int bd_sync(int mdid, u_int op, u_long base, u_long size);
+int bd_sync(int mdid, u_int op, u_long ofs, u_long len);
#endif /* _TOOLS_BUS_DMA_H_ */
diff --git a/tools/bus_space/examples/am79c900_diag.py b/tools/bus_space/examples/am79c900_diag.py
new file mode 100644
index 0000000..bcea31b
--- /dev/null
+++ b/tools/bus_space/examples/am79c900_diag.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2014 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.
+# 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$
+#
+
+'''
+Simple diagnostics program fo the AMD Am89c900 series ILACC.
+This ethernet controller is emulated by VMware Fusion among
+possibly other virtualization platforms.
+
+The datasheet can be found here:
+ http://support.amd.com/TechDocs/18219.pdf
+
+This example program sends a single DHCP discovery packet,
+waits 2 seconds and then iterates over the receive ring for
+a targeted packet.
+
+For this program to function, connect the network interface
+to a network with a DHCP server. In VMware Fusion this can
+best be done by configuring the interface as a NAT interface
+using the "Share with my Mac" setting.
+'''
+
+import ctypes
+import logging
+import os
+import sys
+import time
+
+sys.path.append('/usr/lib')
+
+import bus
+import busdma
+
+
+# ILACC initialization block definition
+class initblock(ctypes.LittleEndianStructure):
+ _fields_ = [('mode', ctypes.c_uint32),
+ ('hwaddr', ctypes.c_uint8 * 6),
+ ('_pad1_', ctypes.c_uint16),
+ ('filter', ctypes.c_uint16 * 4),
+ ('rxdesc', ctypes.c_uint32),
+ ('txdesc', ctypes.c_uint32),
+ ('_pad2_', ctypes.c_uint32)]
+
+
+# ILACC ring buffer descriptor
+class bufdesc(ctypes.LittleEndianStructure):
+ _fields_ = [('buffer', ctypes.c_uint32),
+ ('flags', ctypes.c_uint32),
+ ('length', ctypes.c_uint32),
+ ('_pad_', ctypes.c_uint32)]
+
+
+# The DHCP packet definition (incl. all headers)
+class packet(ctypes.BigEndianStructure):
+ _pack_ = 1
+ _fields_ = [('eth_dest', ctypes.c_uint8 * 6),
+ ('eth_src', ctypes.c_uint8 * 6),
+ ('eth_type', ctypes.c_uint16),
+ ('ip_vl', ctypes.c_uint8),
+ ('ip_de', ctypes.c_uint8),
+ ('ip_len', ctypes.c_uint16),
+ ('ip_id', ctypes.c_uint16),
+ ('ip_ff', ctypes.c_uint16),
+ ('ip_ttl', ctypes.c_uint8),
+ ('ip_proto', ctypes.c_uint8),
+ ('ip_cksum', ctypes.c_uint16),
+ ('ip_src', ctypes.c_uint32),
+ ('ip_dest', ctypes.c_uint32),
+ ('udp_src', ctypes.c_uint16),
+ ('udp_dest', ctypes.c_uint16),
+ ('udp_len', ctypes.c_uint16),
+ ('udp_cksum', ctypes.c_uint16),
+ ('bootp_op', ctypes.c_uint8),
+ ('bootp_htype', ctypes.c_uint8),
+ ('bootp_hlen', ctypes.c_uint8),
+ ('bootp_hops', ctypes.c_uint8),
+ ('bootp_xid', ctypes.c_uint32),
+ ('bootp_secs', ctypes.c_uint16),
+ ('bootp_flags', ctypes.c_uint16),
+ ('bootp_ciaddr', ctypes.c_uint32),
+ ('bootp_yiaddr', ctypes.c_uint32),
+ ('bootp_siaddr', ctypes.c_uint32),
+ ('bootp_giaddr', ctypes.c_uint32),
+ ('bootp_chaddr', ctypes.c_uint8 * 16),
+ ('bootp_sname', ctypes.c_uint8 * 64),
+ ('bootp_file', ctypes.c_uint8 * 128),
+ ('dhcp_magic', ctypes.c_uint32),
+ ('dhcp_options', ctypes.c_uint8 * 60)]
+
+MACFMT = '%02x:%02x:%02x:%02x:%02x:%02x'
+
+dev = 'pci0:2:1:0'
+
+logging.basicConfig(level=logging.DEBUG)
+
+pcicfg = bus.map(dev, 'pcicfg')
+logging.debug('pcicfg=%s (%s)' % (pcicfg, dev))
+
+vendor = bus.read_2(pcicfg, 0)
+device = bus.read_2(pcicfg, 2)
+if vendor != 0x1022 or device != 0x2000:
+ logging.error('Not an AMD PCnet-PCI (vendor=%x, device=%x)' %
+ (vendor, device))
+ sys.exit(1)
+
+command = bus.read_2(pcicfg, 4)
+if not (command & 1):
+ logging.info('enabling I/O port decoding')
+ command |= 1
+ bus.write_2(pcicfg, 4, command)
+
+if not (command & 4):
+ logging.info('enabling bus mastering')
+ command |= 4
+ bus.write_2(pcicfg, 4, command)
+
+bus.unmap(pcicfg)
+
+io = bus.map(dev, '10.io')
+logging.debug('io=%s (%s)' % (io, dev))
+
+
+def delay(msec):
+ time.sleep(msec / 1000.0)
+
+
+def ffs(x):
+ y = (1 + (x ^ (x-1))) >> 1
+ return y.bit_length()
+
+
+def ip_str(a):
+ return '%d.%d.%d.%d' % ((a >> 24) & 255, (a >> 16) & 255, (a >> 8) & 255,
+ a & 255)
+
+
+def mac_is(l, r):
+ for i in xrange(6):
+ if l[i] != r[i]:
+ return False
+ return True
+
+
+def mac_str(m):
+ return MACFMT % (m[0], m[1], m[2], m[3], m[4], m[5])
+
+
+def rdbcr(reg):
+ bus.write_2(io, 0x12, reg & 0xffff)
+ return bus.read_2(io, 0x16)
+
+
+def wrbcr(reg, val):
+ bus.write_2(io, 0x12, reg & 0xffff)
+ bus.write_2(io, 0x16, val & 0xffff)
+
+
+def rdcsr(reg):
+ bus.write_2(io, 0x12, reg & 0xffff)
+ return bus.read_2(io, 0x10)
+
+
+def wrcsr(reg, val):
+ bus.write_2(io, 0x12, reg & 0xffff)
+ bus.write_2(io, 0x10, val & 0xffff)
+
+
+def start():
+ wrcsr(0, 0x42)
+ delay(100)
+
+
+def stop():
+ wrcsr(0, 4)
+ delay(100)
+
+
+mac = ()
+bcast = ()
+for o in xrange(6):
+ mac += (bus.read_1(io, o),)
+ bcast += (0xff,)
+logging.info('ethernet address = ' + MACFMT % mac)
+
+stop()
+wrbcr(20, 2) # reset
+wrcsr(3, 0) # byte swapping mode
+wrbcr(2, rdbcr(2) | 2) # Autoneg
+
+memsize = 32*1024
+bufsize = 1536
+nrxbufs = 16
+ntxbufs = 4
+logging.debug("DMA memory: size = %#x (TX buffers: %u, RX buffers: %u)" %
+ (memsize, ntxbufs, nrxbufs))
+
+mem_tag = busdma.tag_create(dev, 16, 0, 0xffffffff, memsize, 1, memsize, 0, 0)
+dmamem = busdma.mem_alloc(mem_tag, 0)
+busseg = busdma.md_first_seg(dmamem, busdma.MD_BUS_SPACE)
+cpuseg = busdma.md_first_seg(dmamem, busdma.MD_VIRT_SPACE)
+busaddr = busdma.seg_get_addr(busseg)
+cpuaddr = busdma.seg_get_addr(cpuseg)
+logging.debug("DMA memory: CPU address: %#x, device address: %#x" %
+ (cpuaddr, busaddr))
+
+addr_initblock = cpuaddr
+addr_rxdesc = addr_initblock + ctypes.sizeof(initblock)
+addr_txdesc = addr_rxdesc + ctypes.sizeof(bufdesc) * nrxbufs
+addr_rxbufs = addr_txdesc + ctypes.sizeof(bufdesc) * ntxbufs
+addr_txbufs = addr_rxbufs + bufsize * nrxbufs
+
+ib = initblock.from_address(addr_initblock)
+ib.mode = ((ffs(ntxbufs) - 1) << 28) | ((ffs(nrxbufs) - 1) << 20)
+for i in xrange(len(mac)):
+ ib.hwaddr[i] = mac[i]
+for i in xrange(4):
+ ib.filter[i] = 0xffff
+ib.rxdesc = busaddr + (addr_rxdesc - cpuaddr)
+ib.txdesc = busaddr + (addr_txdesc - cpuaddr)
+ib._pad1_ = 0
+ib._pad2_ = 0
+
+for i in xrange(nrxbufs):
+ bd = bufdesc.from_address(addr_rxdesc + ctypes.sizeof(bufdesc) * i)
+ bd.buffer = busaddr + (addr_rxbufs - cpuaddr) + bufsize * i
+ bd.flags = (1 << 31) | (15 << 12) | (-bufsize & 0xfff)
+ bd.length = 0
+ bd._pad_ = 0
+
+for i in xrange(ntxbufs):
+ bd = bufdesc.from_address(addr_txdesc + ctypes.sizeof(bufdesc) * i)
+ bd.buffer = busaddr + (addr_txbufs - cpuaddr) + bufsize * i
+ bd.flags = (15 << 12)
+ bd.length = 0
+ bd._pad_ = 0
+
+busdma.sync_range(dmamem, busdma.SYNC_PREWRITE, 0, addr_rxbufs - cpuaddr)
+
+# Program address of DMA memory
+wrcsr(1, busaddr)
+wrcsr(2, busaddr >> 16)
+delay(100)
+
+# Initialize hardware
+wrcsr(0, 1)
+logging.debug('Waiting for initialization to complete')
+csr = rdcsr(0)
+while (csr & 0x100) == 0:
+ logging.debug('CSR=%#x' % (csr))
+ csr = rdcsr(0)
+
+start()
+
+pkt = packet.from_address(addr_txbufs)
+ctypes.memset(addr_txbufs, 0, ctypes.sizeof(pkt))
+options = [53, 1, 1]
+for i in xrange(len(options)):
+ pkt.dhcp_options[i] = options[i]
+pkt.dhcp_magic = 0x63825363
+for i in xrange(6):
+ pkt.bootp_chaddr[i] = mac[i]
+pkt.bootp_hlen = 6
+pkt.bootp_htype = 1
+pkt.bootp_op = 1
+pkt.udp_len = ctypes.sizeof(pkt) - 34
+pkt.udp_dest = 67
+pkt.udp_src = 68
+pkt.ip_dest = 0xffffffff
+pkt.ip_cksum = 0x79a6
+pkt.ip_proto = 17
+pkt.ip_ttl = 64
+pkt.ip_len = ctypes.sizeof(pkt) - 14
+pkt.ip_vl = 0x45
+pkt.eth_type = 0x0800
+for i in xrange(6):
+ pkt.eth_src[i] = mac[i]
+ pkt.eth_dest[i] = bcast[i]
+pktlen = ctypes.sizeof(pkt)
+
+busdma.sync_range(dmamem, busdma.SYNC_PREWRITE, addr_txbufs - cpuaddr, bufsize)
+
+bd = bufdesc.from_address(addr_txdesc)
+bd.length = 0
+bd.flags = (1 << 31) | (1 << 25) | (1 << 24) | (0xf << 12) | (-pktlen & 0xfff)
+
+busdma.sync_range(dmamem, busdma.SYNC_PREWRITE, addr_txdesc - cpuaddr,
+ ctypes.sizeof(bufdesc))
+
+wrcsr(0, 0x48)
+
+logging.info('DHCP discovery packet sent')
+
+# Now wait 2 seconds for a DHCP offer to be received.
+logging.debug('Waiting 2 seconds for an offer to be received')
+time.sleep(2)
+
+stop()
+
+busdma.sync_range(dmamem, busdma.SYNC_PREWRITE, addr_rxdesc - cpuaddr,
+ ctypes.sizeof(bufdesc) * nrxbufs)
+
+for i in xrange(nrxbufs):
+ bd = bufdesc.from_address(addr_rxdesc + ctypes.sizeof(bufdesc) * i)
+ if (bd.flags & 0x80000000):
+ continue
+ pkt = packet.from_address(addr_rxbufs + i * bufsize)
+ if mac_is(pkt.eth_dest, bcast):
+ logging.debug('RX #%d: broadcast packet: length %u' % (i, bd.length))
+ continue
+ if not mac_is(pkt.eth_dest, mac):
+ logging.debug('RX #%d: packet for %s?' % (i, mac_str(pkt.eth_dest)))
+ continue
+ logging.debug('RX %d: packet from %s!' % (i, mac_str(pkt.eth_src)))
+ logging.info('Our IP address = %s' % (ip_str(pkt.ip_dest)))
+
+busdma.mem_free(dmamem)
+busdma.tag_destroy(mem_tag)
+bus.unmap(io)
diff --git a/tools/tools/iwn/iwnstats/main.c b/tools/tools/iwn/iwnstats/main.c
index 590c178..89582aa 100644
--- a/tools/tools/iwn/iwnstats/main.c
+++ b/tools/tools/iwn/iwnstats/main.c
@@ -50,7 +50,7 @@
#include "iwnstats.h"
#include "iwn_ioctl.h"
-#define IWN_DEFAULT_IF "iwn0"
+#define IWN_DEFAULT_IF "wlan0"
static struct iwnstats *
iwnstats_new(const char *ifname)
@@ -290,19 +290,6 @@ main(int argc, char *argv[])
if (ifname)
free(ifname);
ifname = strdup(optarg);
- if (strncmp(ifname, "wlan", 4) == 0) {
- free(ifname);
- len = 0;
- asprintf(&sysctlname, "net.wlan.%s.%%parent", ifname + 4);
- ret = sysctlbyname(sysctlname, NULL, &len, NULL, 0);
- if (ret != 0)
- err(1, "sysctl failed");
- ifname = calloc(len, 1);
- ret = sysctlbyname(sysctlname, ifname, &len, NULL, 0);
- if (ret != 0)
- err(1, "sysctl failed");
- free(sysctlname);
- }
break;
default:
case '?':
diff --git a/usr.bin/ar/ar.1 b/usr.bin/ar/ar.1
index 02e99f1..6998c04 100644
--- a/usr.bin/ar/ar.1
+++ b/usr.bin/ar/ar.1
@@ -210,6 +210,7 @@ and 0644 instead of file mode from the members named by arguments
.Ar .
This ensures that checksums on the resulting archives are reproducible
when member contents are identical.
+This option is enabled by default.
If multiple
.Fl D
and
diff --git a/usr.bin/ar/ar.c b/usr.bin/ar/ar.c
index 3d5e2b8..4dee029 100644
--- a/usr.bin/ar/ar.c
+++ b/usr.bin/ar/ar.c
@@ -100,10 +100,12 @@ main(int argc, char **argv)
struct bsdar *bsdar, bsdar_storage;
char *p;
size_t len;
- int i, opt;
+ int i, opt, Dflag, Uflag;
bsdar = &bsdar_storage;
memset(bsdar, 0, sizeof(*bsdar));
+ Dflag = 0;
+ Uflag = 0;
if ((bsdar->progname = getprogname()) == NULL)
bsdar->progname = "ar";
@@ -120,10 +122,12 @@ main(int argc, char **argv)
/* Ignored. */
break;
case 'D':
- bsdar->options |= AR_D;
+ Dflag = 1;
+ Uflag = 0;
break;
case 'U':
- bsdar->options &= ~AR_D;
+ Uflag = 1;
+ Dflag = 0;
break;
case 'V':
ranlib_version();
@@ -180,7 +184,8 @@ main(int argc, char **argv)
set_mode(bsdar, opt);
break;
case 'D':
- bsdar->options |= AR_D;
+ Dflag = 1;
+ Uflag = 0;
break;
case 'f':
case 'T':
@@ -220,7 +225,8 @@ main(int argc, char **argv)
set_mode(bsdar, opt);
break;
case 'U':
- bsdar->options &= ~AR_D;
+ Uflag = 1;
+ Dflag = 0;
break;
case 'u':
bsdar->options |= AR_U;
@@ -273,6 +279,10 @@ main(int argc, char **argv)
argv++;
}
+ /* Set determinstic mode for -D, and by default without -U. */
+ if (Dflag || (Uflag == 0 && (bsdar->mode == 'q' || bsdar->mode == 'r')))
+ bsdar->options |= AR_D;
+
if (bsdar->options & AR_A)
only_mode(bsdar, "-a", "mqr");
if (bsdar->options & AR_B)
@@ -281,8 +291,10 @@ main(int argc, char **argv)
only_mode(bsdar, "-c", "qr");
if (bsdar->options & AR_CC)
only_mode(bsdar, "-C", "x");
- if (bsdar->options & AR_D)
+ if (Dflag)
only_mode(bsdar, "-D", "qr");
+ if (Uflag)
+ only_mode(bsdar, "-U", "qr");
if (bsdar->options & AR_O)
only_mode(bsdar, "-o", "x");
if (bsdar->options & AR_SS)
diff --git a/usr.bin/brandelf/brandelf.1 b/usr.bin/brandelf/brandelf.1
index 6b84777..309f467 100644
--- a/usr.bin/brandelf/brandelf.1
+++ b/usr.bin/brandelf/brandelf.1
@@ -9,7 +9,7 @@
.\" 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 John-Mark Gurney AND CONTRIBUTORS ``AS IS''
+.\" 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
diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd
index 41e8ea6..4d473c9 100644
--- a/usr.bin/calendar/calendars/calendar.freebsd
+++ b/usr.bin/calendar/calendars/calendar.freebsd
@@ -122,6 +122,7 @@
04/03 Hellmuth Michaelis <hm@FreeBSD.org> born in Kiel, Schleswig-Holstein, Germany, 1958
04/03 Tong Liu <nemoliu@FreeBSD.org> born in Beijing, People's Republic of China, 1981
04/03 Gabor Pali <pgj@FreeBSD.org> born in Kunhegyes, Hungary, 1982
+04/04 Jason Unovitch <junovitch@FreeBSD.org> born in Scranton, Pennsylvania, United States, 1986
04/05 Stacey Son <sson@FreeBSD.org> born in Burley, Idaho, United States, 1967
04/06 Peter Jeremy <peterj@FreeBSD.org> born in Sydney, New South Wales, Australia, 1961
04/07 Edward Tomasz Napierala <trasz@FreeBSD.org> born in Wolsztyn, Poland, 1981
diff --git a/usr.bin/elfcopy/Makefile b/usr.bin/elfcopy/Makefile
index 8e7f31d..dc6dd47 100644
--- a/usr.bin/elfcopy/Makefile
+++ b/usr.bin/elfcopy/Makefile
@@ -7,7 +7,15 @@ ELFCOPYDIR= ${ELFTCDIR}/elfcopy
.PATH: ${ELFCOPYDIR}
+.if ${MK_ELFCOPY_AS_OBJCOPY} != "no"
+PROG= objcopy
+objcopy.1: elfcopy.1
+ sed -e 's/\.Dt ELFCOPY 1/.Dt OBJCOPY 1/' \
+ -e 's/\.Nm elfcopy/.Nm objcopy/' < ${.ALLSRC} > ${.TARGET}
+CLEANFILES+= objcopy.1
+.else
PROG= elfcopy
+.endif
SRCS= archive.c ascii.c binary.c main.c sections.c segments.c symbols.c
@@ -17,8 +25,8 @@ LIBADD= archive elftc elf
CFLAGS+=-I${ELFTCDIR}/libelftc -I${ELFTCDIR}/common
-MAN= elfcopy.1 strip.1
+MAN= ${PROG}.1 strip.1
-LINKS= ${BINDIR}/elfcopy ${BINDIR}/strip
+LINKS= ${BINDIR}/${PROG} ${BINDIR}/strip
.include <bsd.prog.mk>
diff --git a/usr.bin/find/extern.h b/usr.bin/find/extern.h
index 3afe6e4..b2e344a 100644
--- a/usr.bin/find/extern.h
+++ b/usr.bin/find/extern.h
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
-void brace_subst(char *, char **, char *, int);
+void brace_subst(char *, char **, char *, size_t);
PLAN *find_create(char ***);
int find_execute(PLAN *, char **);
PLAN *find_formplan(char **);
diff --git a/usr.bin/find/misc.c b/usr.bin/find/misc.c
index 11a26be..df2e502 100644
--- a/usr.bin/find/misc.c
+++ b/usr.bin/find/misc.c
@@ -57,23 +57,33 @@ __FBSDID("$FreeBSD$");
* Replace occurrences of {} in s1 with s2 and return the result string.
*/
void
-brace_subst(char *orig, char **store, char *path, int len)
+brace_subst(char *orig, char **store, char *path, size_t len)
{
- int plen;
- char ch, *p;
+ const char *pastorigend, *p, *q;
+ char *dst;
+ size_t newlen, plen;
plen = strlen(path);
- for (p = *store; (ch = *orig) != '\0'; ++orig)
- if (ch == '{' && orig[1] == '}') {
- while ((p - *store) + plen > len)
- if (!(*store = realloc(*store, len *= 2)))
- err(1, NULL);
- memmove(p, path, plen);
- p += plen;
- ++orig;
- } else
- *p++ = ch;
- *p = '\0';
+ newlen = strlen(orig) + 1;
+ pastorigend = orig + newlen;
+ for (p = orig; (q = strstr(p, "{}")) != NULL; p = q + 2) {
+ if (plen > 2 && newlen + plen - 2 < newlen)
+ errx(2, "brace_subst overflow");
+ newlen += plen - 2;
+ }
+ if (newlen > len) {
+ *store = reallocf(*store, newlen);
+ if (*store == NULL)
+ err(2, NULL);
+ }
+ dst = *store;
+ for (p = orig; (q = strstr(p, "{}")) != NULL; p = q + 2) {
+ memcpy(dst, p, q - p);
+ dst += q - p;
+ memcpy(dst, path, plen);
+ dst += plen;
+ }
+ memcpy(dst, p, pastorigend - p);
}
/*
diff --git a/usr.bin/getopt/getopt.1 b/usr.bin/getopt/getopt.1
index d827137..781b6e0 100644
--- a/usr.bin/getopt/getopt.1
+++ b/usr.bin/getopt/getopt.1
@@ -1,6 +1,6 @@
.\" $FreeBSD$
.\"
-.Dd January 26, 2011
+.Dd August 1, 2015
.Dt GETOPT 1
.Os
.Sh NAME
@@ -62,7 +62,7 @@ set \-\- $args
# You cannot use the set command with a backquoted getopt directly,
# since the exit code from getopt would be shadowed by those of set,
# which is zero by definition.
-while true; do
+while :; do
case "$1" in
\-a|\-b)
echo "flag $1 set"; sflags="${1#-}$sflags"
@@ -83,10 +83,10 @@ echo "oarg is '$oarg'"
.Pp
This code will accept any of the following as equivalent:
.Bd -literal -offset indent
-cmd \-aoarg file file
-cmd \-a \-o arg file file
-cmd \-oarg -a file file
-cmd \-a \-oarg \-\- file file
+cmd \-aoarg file1 file2
+cmd \-a \-o arg file1 file2
+cmd \-oarg -a file1 file2
+cmd \-a \-oarg \-\- file1 file2
.Ed
.Sh SEE ALSO
.Xr getopts 1 ,
diff --git a/usr.bin/ipcrm/ipcrm.c b/usr.bin/ipcrm/ipcrm.c
index 32887e0..98c4555 100644
--- a/usr.bin/ipcrm/ipcrm.c
+++ b/usr.bin/ipcrm/ipcrm.c
@@ -34,6 +34,9 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#define _WANT_MSG_PROTOTYPES
+#define _WANT_SEM_PROTOTYPES
+#define _WANT_SHM_PROTOTYPES
#define _KERNEL
#include <sys/sem.h>
#include <sys/shm.h>
@@ -50,18 +53,11 @@ __FBSDID("$FreeBSD$");
#include "ipc.h"
-int signaled;
-int errflg;
-int rmverbose = 0;
+static int signaled;
+static int errflg;
+static int rmverbose = 0;
-void usage(void);
-
-int msgrm(key_t, int);
-int shmrm(key_t, int);
-int semrm(key_t, int);
-void not_configured(int);
-
-void
+static void
usage(void)
{
@@ -72,7 +68,7 @@ usage(void)
exit(1);
}
-int
+static int
msgrm(key_t key, int id)
{
@@ -113,7 +109,7 @@ msgrm(key_t key, int id)
return msgctl(id, IPC_RMID, NULL);
}
-int
+static int
shmrm(key_t key, int id)
{
@@ -154,7 +150,7 @@ shmrm(key_t key, int id)
return shmctl(id, IPC_RMID, NULL);
}
-int
+static int
semrm(key_t key, int id)
{
union semun arg;
@@ -173,7 +169,7 @@ semrm(key_t key, int id)
if ((kxsema[num].u.sem_perm.mode & SEM_ALLOC) != 0) {
id = IXSEQ_TO_IPCID(num,
kxsema[num].u.sem_perm);
- if (semctl(id, IPC_RMID, NULL) < 0) {
+ if (semctl(id, 0, IPC_RMID, NULL) < 0) {
if (rmverbose > 1)
warn("semid(%d): ", id);
errflg++;
@@ -196,7 +192,7 @@ semrm(key_t key, int id)
return semctl(id, 0, IPC_RMID, arg);
}
-void
+static void
not_configured(int signo __unused)
{
diff --git a/usr.bin/mkimg/image.c b/usr.bin/mkimg/image.c
index be1c2e9..a3bec63 100644
--- a/usr.bin/mkimg/image.c
+++ b/usr.bin/mkimg/image.c
@@ -517,14 +517,14 @@ image_copyout_memory(int fd, size_t size, void *ptr)
return (0);
}
-static int
-image_copyout_zeroes(int fd, size_t size)
+int
+image_copyout_zeroes(int fd, size_t count)
{
static uint8_t *zeroes = NULL;
size_t sz;
int error;
- if (lseek(fd, (off_t)size, SEEK_CUR) != -1)
+ if (lseek(fd, (off_t)count, SEEK_CUR) != -1)
return (0);
/*
@@ -537,12 +537,12 @@ image_copyout_zeroes(int fd, size_t size)
return (ENOMEM);
}
- while (size > 0) {
- sz = (size > secsz) ? secsz : size;
+ while (count > 0) {
+ sz = (count > secsz) ? secsz : count;
error = image_copyout_memory(fd, sz, zeroes);
if (error)
return (error);
- size -= sz;
+ count -= sz;
}
return (0);
}
diff --git a/usr.bin/mkimg/image.h b/usr.bin/mkimg/image.h
index ce195d9..0405c5b 100644
--- a/usr.bin/mkimg/image.h
+++ b/usr.bin/mkimg/image.h
@@ -35,6 +35,7 @@ int image_copyin(lba_t blk, int fd, uint64_t *sizep);
int image_copyout(int fd);
int image_copyout_done(int fd);
int image_copyout_region(int fd, lba_t blk, lba_t size);
+int image_copyout_zeroes(int fd, size_t count);
int image_data(lba_t blk, lba_t size);
lba_t image_get_size(void);
int image_init(void);
diff --git a/usr.bin/mkimg/mkimg.1 b/usr.bin/mkimg/mkimg.1
index 3b1d63e..b982791 100644
--- a/usr.bin/mkimg/mkimg.1
+++ b/usr.bin/mkimg/mkimg.1
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 22, 2015
+.Dd August 7, 2015
.Dt MKIMG 1
.Os
.Sh NAME
@@ -141,7 +141,7 @@ utility will create images that are identical.
.Pp
A set of long options exist to query about the
.Nm
-utilty itself.
+utility itself.
Options in this set should be given by themselves because the
.Nm
utility exits immediately after providing the requested information.
@@ -165,6 +165,85 @@ run the
.Nm
utility without any arguments.
This will print a usage message with all the necessary details.
+.Sh DISK FORMATS
+The
+.Nm
+utility supports a number of output file formats.
+A short description of these is given below.
+.Ss QCOW and QCOW2
+QCOW stands for "QEMU Copy On Write".
+It's a sparse file format akin to VHD and VMDK and QCOW represents the
+first version.
+QCOW2 represents version 2 of the file format.
+Version 2 is not backward compatible with version 1 and adds support for
+snapshots among other things.
+The QCOW file formats are natively supported by QEMU and Xen.
+To write QCOW, specify
+.Fl f Ar qcow
+on the command line.
+To write version 2 QCOW, specify
+.Fl f Ar qcow2
+on the command line.
+The preferred file extension is ".qcow" and ".qcow2" for QCOW and QCOW2
+(resp.), but ".qcow" is sometimes used for version 2 files as well.
+.Ss RAW file format
+This file format is a sector by sector representation of an actual disk.
+There is no extra information that describes or relates to the format
+itself. The size of the file is the size of the (virtual) disk.
+This file format is suitable for being copyied onto a disk with utilities
+like
+.Nm dd .
+To write a raw disk file, either omit the
+.Fl f
+option, or specify
+.Fl f Ar raw
+on the command line.
+The preferred file extension is one of ".img" or ".raw", but there's no
+real convention for it.
+.Ss Dynamic VHD and Fixed VHD
+Microsoft's "Virtual Hard Disk" file formats.
+The dynamic format is a sparse format akin to QCOW and VMDK.
+The fixed format is effectively a raw format with a footer appended to the
+file and as such it's often indistinguishable from the raw format.
+The fixed file format has been added to support Microsoft's Azure platform
+and due to inconsistencies in interpretation of the footer is not compatible
+with utilities like
+.Nm qemu
+when it is specifically instructed to interpreted the file as a VHD file.
+By default
+.Nm qemu
+will treat the file as a raw disk file, which mostly works fine.
+To have
+.Nm
+create a dynamic VHD file, specify
+.Fl f Ar vhd
+on the command line.
+To create a fixed VHD file for use by Azure, specify
+.Fl f Ar vhdf
+on the command line.
+The preferred file extension is ".vhd".
+.Ss VMDK
+VMware's "Virtual Machine Disk" file format.
+It's a sparse file format akin to QCOW and VHD and supported by many
+virtualization solutions.
+To create a VMDK file, specify
+.Fl f Ar vmdk
+on the command line.
+The preferred file extension is ".vmdk".
+.Pp
+Not all virtualization solutions support all file formats, but often those
+virtualization environments have utilities to convert from one format to
+another.
+Note however that conversion may require that the virtual disk size is
+changed to match the constraints of the output format and this may invalidate
+the contents of the disk image.
+For example, the GUID Partition Table (GPT) scheme has a header in the last
+sector on the disk.
+When changing the disk size, the GPT must be changed so that the last header
+is moved accordingly.
+This is typically not part of the conversion process.
+If possible, use an output format specifically for the environment in which
+the file is intended to be used.
.Sh ENVIRONMENT
.Bl -tag -width "TMPDIR" -compact
.It Ev TMPDIR
@@ -235,6 +314,7 @@ utility supports assigning labels to the partitions specified.
In the following example the file system partition is labeled as 'backup':
.Dl % mkimg -s gpt -p freebsd-ufs/backup:=file-system.ufs -o gpt.img
.Sh SEE ALSO
+.Xr dd 1 ,
.Xr gpart 8 ,
.Xr makefs 8 ,
.Xr mdconfig 8 ,
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu
index 9b2f122..a2be9b1 100644
--- a/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu
@@ -1,18 +1,19 @@
# $FreeBSD$
begin 644 img-1x1-4096-apm.vhd.gz
-M'XL("'`EAE4``VEM9RTQ>#$M-#`Y-BUA<&TN=FAD+F]U=`"M5EUOVR`4?<^O
-MN-+>*LV":\#=XZ:U;Y.J5=,>6]?!E=6UC9I(ZT-^_+A\Q-C&;I+A$`3"]_AP
-M[@<PYAX`58)J06E0DL:5`/4%JDL`L^@;VI[[*>R;UQ?=[+KWPC_[E0/C++8:
-MFI,]EB#,1RK`FCZBUC2&?8`I/ET]7G3/CP$./1QZ(%F158F@'B;?4>S`CI!^
-M=_AD(>][=N6476]E_@\"F`#.HS?*P.[^P/$`)XQ5V]I6$2/2)[3!9+!`<$]%
-M,863;&05T4R)&FTV!:>6K$Z!NUAY7[A0,8%1F=Y(QZ%"&INP"3I,F@F5]^VF
-M?MOJ$3^<"15UX,<G:^7\=M&'"H:7/0-!X;RT7;`HNS%<(E3^2STUM!-^8$1@
-M,BR@W?Y0O1X*8GZ*LP7-YYTQRZ\F?B8U)?;99EKYT8:O?A(,&[NCGO'NV?HU
-MM&PR1*Q34=%/QKE[\R,9+@WQ$YS"F"*YH1@^AM_7S>:/3L!AKNTZN'+*3K8^
-MYVS2N1)M>U>Z91O8W9ELVW6[[O7E+L!1H:)2:Q&/9_=<;Y+L9&;?ZB-]>QGE
-M"9OX%@(_G3OVM'6'(N'IA)0@$*0YR`3@VA"7M&;F$\#K-ZV_W7[__.OZ-M9/
-MB[S\.#M"/XST<TD2ZQ?7%CYWB)_/;U$_.DRJ1&SV^FW_ND`,_'+K5WO]6)WH
-MYQ?V-\7PYP#1%]-LU1G[ZI>'H?"`V1B*/H=S,>1ZT9FG>EEYAIFNNFJ^RIQS
-KU26XC%==Y4O6K!4[Z:JK?,G*=-4EN(Q778++>M55MJ"N_@%!NLDU'PT`````
+M'XL("`0UQ%4``VEM9RTQ>#$M-#`Y-BUA<&TN=FAD+F]U=`"M5EUOVR`4?<^O
+MN%/?*BT"##A[7+7VK5*UJMICY3FXL[JV41.I?<C^>[E\%&R#E60X!$'(/3Z<
+M^P&$V`=`5B`[D`JDP''-07Z#>@6@%UUCIJ=N"OOVY5FUN_Y]Z9[]PH)1$EL-
+MS=&>5<#U2VI@#;Y$KG$,>P^S/+M\..^?'CP<<W#,`8D:K2H&\O?D/5S_NK+L
+M$.E7SQX-Y,6?3W;5E%VPTM]Z#80#I=$_*L].PRS_#3?+M577F58#448?WP:3
+MP4+8[$@[0496$<V4J"1L-@4GYZR.@3M?.%_84-&!4>N>@*10,QSKL/$Z3)H.
+ME??MIGG=JA$_E@D5^<F/3M:J_':9"Q7F_^P8<`SGN>V"0=F-X1*A\E_JR:$=
+M=P,M`A%^@9GM#]4+4!#SDY3,:)YW1I9?@_QT:@H6L@TI4:AF];O\B3!?^$B_
+M)N/=D_5K<5EG"%^GHB),QKE[<YT,EQ;Y<8IAC)'<8@P?PN_[9O-7)>!8J>U:
+MN&K*3G0NYTS2V1)M>ENZ1>?9W>MLV_6[_N7YWL-AH<)2:Q`/9_?4;)+L1&'?
+MJ@-]NXKRA$Q\"YZ?*AU[RKA#HO!X0@H\-(0^R#BPM28N<$W/)X!7KTI=W/[X
+M>G=U&^NG>%E^E!R@'XOTLTD2ZQ?7%IH[Q$_G-ZL?'B9U(C:#?MLW&XB>7VG]
+M&J<?:1)]?F%_LQQ^+"!SQ;18=6:A^I5AR!U@,88\Y'`IAE3-.O-8+TO'L-!5
+M5^:KS"E7780K>-65KF1EK<A15UWI2E:AJR["%;SJ(ES1JZXT!77Q`0\AJT,?
+##0``
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.gz.uu
index 2e3236d..f933544 100644
--- a/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.gz.uu
@@ -1,17 +1,17 @@
# $FreeBSD$
begin 644 img-1x1-4096-bsd.vhd.gz
-M'XL("',EAE4``VEM9RTQ>#$M-#`Y-BUB<V0N=FAD+F]U=`"METV/@C`0AN_^
-MBDGVYH&T0REXW<3[GM:KB&B,V8^L'CSPXW<&"K044'<+V)2T\_#.=*:I0C07
-M@(Y!'T"7H!/NIPKT"M(,@`;-@W4KS2M4Q==G65Q/M\A<U:*!26%;N>9LCS$H
-M^D@*F/-'])[[4+68Z&5]7)X^CBT.#0X-*$G9*D;0.^\[6G3JF+0YX;E&;GMU
-ML:^NMZ+?3H%0(*4U(V[5;3N-'4Z1U>%0/RDKXOBTC_/B###N'$4^+A$#*TOF
-M6%`M9\=P>L[J&=QR8=:B215*C)1:"IV$%+E/:=/&P7LH56Z7[_SG4@[TX42J
-MZ$Z?],;B:7?1I`JVDXT"Q>D\YR[4E.L0-Y(J_XJ>=NV4Z5`01-(.8.V^&[T>
-M!;8^+<5,S*<78U)?SOH4U5D^TDX/5*^1>W?`@H%4KU3NB88,'XW@9OT^MK[%
-M1+K\L3H*O(?K!,M'<+&I78L2][BI@08G#$OT.#6GCG.F?,K9)'`R%]G`SEYG
-MD`>0>Q"9E=46L%M?Z/6M?!GHN#NC#WQW<\:E[GQIX?".N^#B=K-K.Z].^.J*
-MP(NQ'U;&@Y7+$+=R&QR&W0BPWEDH`VF6WTX/5&^1>S=`-%M5L+T/VZTJE$)E
-M@,$4$K`,K!#+V61[-@NU41CH(,FX@`=)Q@4\2#(NX$&2<0$/DHP+>)!D7-"#
-0I*:_"$(L?@%=YQ4O?0P`````
+M'XL("`<UQ%4``VEM9RTQ>#$M-#`Y-BUB<V0N=FAD+F]U=`"METUOPR`,AN_]
+M%9YVZZ0('`+9=5+O.ZWG-$VW:MJ'UAYZR/[[[`12R-?:C8124O"3U\8@*D1[
+M`>@4]`YT!3KCME&@[\'D`-1I"S:UM(]0EQ_O57G<GQ)[U8L6)H5O%9JS/::@
+MZ"4&L."7Z"VWH7:8Y';UO-R_/3L<6AQ:4&;8*D70F\%[%/V:M^J8M-[C:X-\
+M>.G4I4-U9ROZF"T(!5)Z(U*GCC#)=^BL(JO=KBD&1-7$QY7@(>@X.]N+729Z
+M5I[,L:"*L[-C.#UG=0UNN;!ST:8*)8:A6H"68)#;E#8N#H-"J7(Z?!9?AZJG
+M#R=217?ZY*`OG787;:J@&VP5*$[G.7>AH1S[N)%4^5?T=&BG;(."(#+7@8W[
+M8?3.*/#U:2EF8CX]&9/Z"M9'BT$4(_5T1_V0A'<'+!E(ZY66>Z8AQTLCN%X]
+MC<UO.9$N?UP=)?Z&ZP3+2W"I7;MN9*H`N]URLJ/!J9L6Q=\.I^;4<<Y45SF;
+M14[F,N_9^?,,N`%1@LB]K/:`/+]W-I^=OONA#`S<G=$'0W<+QIEPO/1P^(N[
+M$.(VLW,[J\[-K8\K(T_&MK\R+ERY#`E7;HO#N!L!-CL+92"-&M;3'?5C$MXM
+M$.U6%6WO0[=5Q5*H+#":0@)6D15B-9MLUV:AM@HC'209%_$@R;B(!TG&13Q(
+<,B[B09)Q$0^2C(MZD-3T%T&(Q0_L]):$?0P`````
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.gz.uu
index b886967..583467c 100644
--- a/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-1x1-4096-ebr.vhd.gz
-M'XL("'<EAE4``VEM9RTQ>#$M-#`Y-BUE8G(N=FAD+F]U=`"METUSI"`0AN_S
-M*SJUMQPL:*&=7+<J][WLYAHUFII*[4=M<LC!'[\@H"!"QBRCPVA!/[[=-"W#
-MF/D`4`TT`@U`4E\W`N@.FC.`ZK0GSBVWMS#UOW\-_=OEO;*?Z61@G/E6H;FV
-MQQJ$>D@#V.J'T).^ALEAJB_WS[>7G\\.AQ:'%B0;;54C4!<]A]BB3I,>+O@R
-M(Q]7=76L;K52WTX`$\"Y-Z)VZAX7C0M.**MQG,]&*]+Q<6=P$W1HW$M5Q3C)
-M-E:>S+V@>L[NX2AG=01W>[)S85)%)4:C6A4Z#@WJ:Y4V+@[1J5+E_?5/^_=U
-MV.C#1*K0HH]'?77:7;2I@FZP52!T.N?<A9GRML7MI,I_18]".V$O5!"8=!TX
-MNQ]&;T6!KX\XR\0\/1E)?6W6KT\XW'6'@0F%!M<O#K=R]<@DR1I,Y&E]-S[N
-MJ;2[XS&@E-"V$?"[T]=K*Z'*7KO3ICNFKU5X+/H&#53E4U5?27#&:QU^N/^Q
-M-QU#8O4>CY_!X4>X13"_!E?;4NI&^IF1[IC6-#&_#B=RZO02'@XY*POGWG#>
-MV/GS#$RMDA[8V?9A"%SF%U9]=[$,#-S-Z(/8W5;CFG`\]W#X@;L0XKKLW.;5
-MW<3J^L*3,6Y7QI4K5T/"E6MP6+80X%Q95`:J47&;[IB^5>%A@&C?',5>16AK
-M7S&%P@*+*12NF)936+-LLAW-0K(*"^WK*5WN/[.O)Z_<%]C7DROW*2MV:%]/
->MMP7VM>3*_=E]O4:5W1?3^H?&V.G?Q5QFYT,#@``
+M'XL("`LUQ%4``VEM9RTQ>#$M-#`Y-BUE8G(N=FAD+F]U=`"M5\%RI"`0O<]7
+M=&IO.5C00F.NJ<I]+[LY.XXF4UN;I)(<<G#_?4%`0<6,"<HP.DT_WVN:EF',
+M'@!4`G5`+9`TUTH`W8"J`+31-1QZ[FZA;YZ?VN;]_%&XHS]8,,Y"K]C=^&,)
+M0C]$`=;F(70RU]![F.+'W</U^>^#AT,'APY(*N-5(M!Q\1RA?ZTL.X-T?\8_
+M`^3MX\BN7+*;O/1'G8`)X#P847IV&J;X%XL5VJOKAJ:`M4-\?(MN(L,D=A8[
+MR69>`<VUH+))[!H<;7GM@;L^N+FPJ:(30^F>`7%0:*YUVO@X+)I.E8^WE_KU
+MK9WQPT2JT,B/+VQE6BZZ5$$_V#$0)IVWY,*`\CZ'6TF5;T6/8C_A+G00F/0&
+M'.3'T9N@(.1'G&W$/#T927[UIJXO"#X>=P,F&%JX9A1<RTF139(IF,C3_*Y"
+MN%-NN=T^0"FAKA>`OSR_QGCIVL3JE3YMZ&^+^!SYM090ET]=?25!A9<*OK_[
+MO38=;6+U[H^?A<//X$;"_!*XTI52/S+,C+2AG]+$?GLXL<7.+.%VEUB9.??:
+M:N87SC,PO4H:8)6S80PXSB],_&Z6-#"2N\$/EG)K`Z?B\3R`PT_D0@QWW)S;
+M;7972W9-YLGHYBOCPI5K0.*5:^$P;R'`H;+H#-2CEGW:T/\LXM,"HGMS9'L5
+MH:M]V1@*!YB-H?#%-!_#DFTFV]XL),<PT[Z>TN7^*_MZ"LI]AGT]^7*?\F*[
+A]O7DRGVF?3WY<I]G7V_@LN[K2?]C8^SP'^[O5"8,#@``
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu
index 319ec0e..4631e38 100644
--- a/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu
@@ -1,22 +1,22 @@
# $FreeBSD$
begin 644 img-1x1-4096-gpt.vhd.gz
-M'XL("'LEAE4``VEM9RTQ>#$M-#`Y-BUG<'0N=FAD+F]U=`"MF$UOU#`0AN_]
-M%8.X%9'&CNUDA80$4I&X%03JA4/CK%.M$,O']M!#?CP>Q_EP8@>VG5TWVI5W
-MGKPS'H^GR?/^!:`*4"TH`TKBYU*`VD%9`=A)/[B[,O\5NN;GT30/A\?,O[J+
-M'L;RN55HCO:\`&%O4@*O\29JCY^A&S#9R^O[R\./^P''/8Y[D"S1JN"@].H^
-M*A_5(>GVP+\[Y-VDKEBKFZSLGQ:0"V!L]HMB4'<W:AQQPEJUK1LE%!IMQQ%\
-M"280]R;+UCB9+ZQF,F-!G3D;PZDMJW-PEQ=^+?I4L8E1VJL-'8.2XV>;-D,<
-M5L.FRN/I5_WG9!;Z>")5U*B/K>:*M+O<IPH??NP5"$SG+7?!41Z6N$BJ/"MZ
-M*K0;5M<&(9?#!'?NA]&;4##7IUB^$?/T8B3UU:A/V'U61Z[IB>Y]%KY'H-;G
-M`8<(AKC18=U@_%P=,&;RJ$^2*;#%QH+DL_CI/?'ZZO8\H)10URO@UT%?XY9#
-M@E`@=I@8MC@(!I*#G-+9^2Z;N;[K#Q_AYMWG+PC[-KG;8+KL.50--#MH]4+=
-M>J=MUY:&]]G'VZBS11)W%<?A9FOW&[C82./$EM5XEORWLS(/K:JY56%`%]#6
-M4.\3N+<+''5=-CBM%90-'N&20>/.\KW"@PPJNTTJ!^'`K41[L-M36".P.W[*
-MCCWL=?;[E==GF,^(V$A/I*)G7%VN4NZ64\%.N`LACKHNFPJC)\FBM_/)$AOI
-MB63TZCYZ\2!A]&);=SS5LNQ%B-.TT6/NU+#[P];O]34]T=UDX;L'<G\,D9UK
-MW!=2,H7"`\D4"K]_"14RL[F8YZZR\HM"5&$01UAA$$=881!'6F$02%AA$$=8
-M81!'6&$01UIA%&TCI'PC5%1@&/[CHL.L2;<T796=>F%7@;NN$4JV3QN-4'PQ
-M*!LA]:]&J#4I9T?.PEG"1DA1-T+*%U*B9QEJ:(36&I[R+$,-C5`^!?`9SS)4
-@O!%ZZK,,Q!$^RT`<X;,,Q!&G"K.]R\5?C-I*)``3````
+M'XL("`XUQ%4``VEM9RTQ>#$M-#`Y-BUG<'0N=FAD+F]U=`"MF$MOVS`,@._Y
+M%0QVZS!#;R>7`2O0`KMUPX9==K$=IRN&=8_VT(/WWT?*4FS9EK&T=%0CB<+/
+M)$61K(3H+P"GP1W!M>`LO2\-N#V4.P"<#$/YNPP?H6M^WK?-X]U3$:YNT\.D
+M&$NEXB2O-!A\2`FJHH>X`[V'+F**5U>W%W<_;B-.!9P*(%N2E%;@ZMES#'Z[
+MZ[4CTI<[]=TC+[^=M--S[08I_"L/(`Q(.?J%CMHAIOB;&FM0ZGCTP\&A)=G3
+M2#XD$X.Q$]]9,9$:J;GD5#$8NX1S:U+GX"XV82WZ4,'`*/$NP$DH%;W'L(E^
+MF`T,E:>'7]6?AW:BG\J$BCOI)V=S.F^N"J&BXH^#!H;"><U<\)3'*6XA5%[D
+M/9?*Q=5%)P@;)Y0W/_7>@(*Q?DZ*%9_G%R.K7T7ZX680U<(]/]%=%NGK!*SK
+M\X#1@RGN9'#=D/]\'FC;P:(^2(*P-J!D=D',=N2_^L"\OO7Q/*"U4%4SX.>H
+M7^.7PX)Q8/84&)@<C`2KP`[A[&VUS5B_J^OW<//NXR>"?1W,;2A<&@5-"7L%
+M<C_1;K[3UG-+0YM-ZZFW(T[G<'J[C*/-IN4*;FE`)S,XLR9UJB7_;:P5J=1N
+M+*5;J#4<*Z@.&=S;"8X[+[<T73LH&RKA5D+C:_G!42&#'6X37]_0`H4J8F%'
+M1]<$[.X_%/<][$WQ^W70KY4A(I9&?B+GO=;GY5W.W')(V!ES(<5QY^5V1]ZS
+M;-[;AV!9&OF)K/>JWGO+3B+O+6Z96-6*8IOB:E[O25\U<']@_I[?\Q/=39&^
+M>J`*98BMKJF02-DT-`'(IJ$)^Y=10]FN+N:YJVQ4J1@S#.$8,PSA&#,,X5@S
+M#`$9,PSA&#,,X1@S#.%8,PP"C>!KA`CG&R&LX>A]3=!$C6Q+0_I=$TJGYAJU
+MUC[E&Z',8AC&1HAPJXT0_A>=-]9?:F(L8R-$.-9&R(5$RG26X6(C--?A.6<9
+J+C9"8G#@"\XRW'(C]-RS#,(QGF40CO$L@W#,H2*Q=]G\`YT_-4@`$P``
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu
index a3ebac5..eee43f3 100644
--- a/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-1x1-4096-mbr.vhd.gz
-M'XL("'\EAE4``VEM9RTQ>#$M-#`Y-BUM8G(N=FAD+F]U=`"MESUOI#`0AOO]
-M%1-=EP+9@SV0]J3TUUS2!@A$JRBYTR5%"G[\V6`;&V.R)-YE69`]#^]\>-;+
-MV/P"H!)H`.J!I+ZN!-`-5#6`&C0'3F=N;F'L_KSVW?OYHS"O\33#./.M0G-M
-MCR4(]9`*L-$/H4=]#:/%%#]NGZ[/+T\6AP:'!B0K;54B4!L]AYA3ITGW9WR>
-MD`^+NC)6MUBI3RN`">#<FU%:=0].H\,)934,TU%I13H^]@AN@@&->RZ*&"?9
-MRLJ3N154S]DM'.U9'<%=GTPNYE)1A5&ILPH=APKUM2H;&X?H4*7R\?:W^??6
-MK_1AHE3(Z>/16)EV%TVIH)UL%`A=SGONPD1Y7^,V2N5;T:/03I@+%00F[0!.
-M[H?16U#@ZR/.=F*>3D927Z/U";7.FHUS>F#\681O!VS;8\":S0I#G'.X[9S#
-MC5P\FHMD"2;R=$*NO/BUCYGSVP['@%)"TT3`WU9?ESL=O0:J]JFZKR2H\5*'
-M[V_OMI9;GUB]7VQ6/7Z&<X+Y);C2M%([TZ^,],"XE,G\;7%B3YU>POTA9V7F
-MVNOKE9V?9V!JE73`:J_)>$"77UCTW<0R,'!W1Q_$[C8:5X7SN8?#3]R%$-?N
-MYG9?W56LKLN<C&&],BY<N1H2KMP9AWD;`4Z=156@FA6?TP/CKR)\ST`TOQS9
-M?HK0]+YL"H4!9E,H;#/-I[!DN\5VM`K)*,RTKZ=TN__*OIZ\=I]A7T^VW:>L
-CV*%]/9EVGVE?3[;=Y]G7:US6?3VI?VR,G?X#`*JO<PP.````
+M'XL("!$UQ%4``VEM9RTQ>#$M-#`Y-BUM8G(N=FAD+F]U=`"M5\]SG"`4ON]?
+M\3*]Y>#`$Y[FFIG<>VES5E?3G4[;3))##O9_+P@HB)@U15D6%][']W[*,F8N
+M`"J!!J`>2.IQ)8#NH*H!U*1M./7</L+8_?G==V^7]\)>X\F`<>9+A>):'DL0
+M:I,*L-&;T%F/870PQ9>'I]O+KR<'AQ8.+9"LM%2)0&VTCU"_UH:=1GJ\X,\)
+M\O['S*Z,V2U2ZE.=@0G@W%M1.G8*IO@;*BN4U#!,K0+63_9Q+7@()A9E5[:3
+M;"7ET=PR*EN4W8*C/:DC<+<GZPL3*BHP*M4S(`X5ZK$*&V>'J*E0>7]];EY>
+M^Q4_3(0*S?QX-%>FU44;*N@66P9"A_.>NC"AO*WA-D+EOZQ'H9RP`V4$)MT$
+M3NJ'UEN@P.='G.W8/.V,)+]&\U/)P)J-/CTQWA?A/0.V[3'`FAF&(=RL<-O-
+M"C=RT<@$R6),Y&F'W'CV:\^9_=L.QP"EA*:)`+\Y?EUN=_0:4)5/57TE08W7
+M*OSX\'TKW?I$]GZR6/7X$=Q,F%\#5]I2ZE;ZD9&>&)<P,=\.3NRQTRG<'U)6
+M9HZ]OE[)^7X&IK*D`U9[1<8#G/T+"[^[F`8&ZN[P@UC=1L-5X7KNP>$'ZD((
+MU^[Z=I_=3<RNR^R,89T95V:N!@DSU\!AWD*`4V51$:A6Q7UZ8OQ:A+<!1/OF
+MR/8J0EO[LC$4%C`;0^&*:3Z&)=L-MJ-12)9AIG,]I<O]9\[UY)7[#.=Z<N4^
+D)<4.G>O)EOM,YWIRY3[/N5[#93W7D_K'QMCI'_LT8,@,#@``
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu
index 3445c95..dbaca22 100644
--- a/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-1x1-4096-pc98.vhd.gz
-M'XL("(,EAE4``VEM9RTQ>#$M-#`Y-BUP8SDX+G9H9"YO=70`K9=-;X,P#(;O
-M_16N=NL!)2:$]CII]UVV74<IG:II'UI[Z($?/QL22`C0=@ND*"CXX;7CF%2(
-M]@#0*>@]Z`ITQOU<@=Y`O@:@0=.PN4IS"W7Y]5F5I\,Y,4>]:&%2N%:^.=MC
-M"HI>D@,6_!*]XS[4%I/</;RM#A]O%H<&AP:4Y6R5(NAM\!XM.G5,>CG@>X-\
-M[=6EH;K>BGY;!4*!E,X3J57WVFGL<(JL]ONFY:R(XV.;=^,-,.X]24)<)@96
-MCLRQH#K.CN'TG-4MN-7"S$6;*I08.5TI=!)RY#ZEC8U#T"A5SL?OXN=8#?3A
-M1*KH3I\,QM)I=]&D"MJ'C0+%Z3SG+C24TQ`WDBK_BI[V[93I4!!$9@>P<=^/
-M7H\"5Y^68B;FTY,QJ:]@?8K663%RG1ZH[Q/_[(#;_6W`+(,B!#Y9ATO6MU%0
-MJK&XNTY>M3K*B>S[\_Q6D>.'C<-4[ZA<9AK6>*W"EX?G$8<QGL,M#B_A.L'R
-M&EQJ:I]]DM1B][69'&AQ2\-:]C@UIX[77'63LUG<9,%R/;!SYQD$Y7`)8NU4
-M!0?8S2_T^C:A#/3<G=$'H;L%XW+_>>G@\(*[X..VLW,[KVX9JBLC3\9NN#*N
-M7+D,\5=NB\.XA4`UE9DRD&MD<)T>J!\3_VR!:$I]M&\'FMH<3:$RP&@*E:G.
-M$16J:C;9;LU";11&VH@S+N)&G'$1-^*,B[@19US$C3CC(F[$&1=U(Z[I+Y80
-*BU\\?ZUPO0T`````
+M'XL("!4UQ%4``VEM9RTQ>#$M-#`Y-BUP8SDX+G9H9"YO=70`K9?!<J,P#(;O
+M>0IE]M8#8PMCDVMG>N]EMV="2#?3V6VGR:$'^NZ5P`8;`TUV#<1#8NOCERP+
+M1XC^`-`YZ"/H!G3!]T:!WH$I`:C37MBUTGZ%MG[]V]27TT=FCW;3PZ3PK4)S
+MML<<%#W$`%;\$'W@>V@=)OOQ\'QW^O/L<&AQ:$&%8:L<0>^CYRCZM>S5,>GI
+MA"\=\O[WH"Z/U8U6]#$'$`JD]$;D3AUALL_06456QV-W&1!-%Q]W!5^"CM'9
+M2>P*,;'R9,X%58S.SN'TFM4MN+N-G8L^52@Q#+4"M`2#?$]IX^(0790J'^>W
+MZOW<3/3A0JKH09^,^O)E=]&F"KK!5H'B=%YS%SK*98J;297_BIX.[92]H2"(
+MPG5@YWX8O1$%OCXMQ4K,ER=C45_%^F@QB&JF7>YH[[/P'(#[XVW`HH`J!OYT
+M#M>L;Z>@5G-Q]YV\:G74"]GWS_/;)(X?=@Y3O:-R66@H\5J%3P^_9AS&=`[W
+M./P.-PB6U^!R6_O<2%*+P]MFL:/';2UK.^+4FCI><\U-SA9IDP7K<F+GSS,(
+MRN$:1.E5!0\XS"^,^G:Q#`S<7=$'L;L5XTPX7GHX_,9="''[U;E=5[>-U=6)
+M)^,P71E7KER&A"NWQV':0J"ZRDP9R#4R:I<[VL<L/'L@VE*?[-V!MC8G4Z@L
+M,)E"9:MS0H6J64VV6[-06X6)-N*,2[@19US"C3CC$F[$&9=P(\ZXA!MQQB7=
+0B&OZBR7$Y@L4!AU6O0T`````
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu
index baee4d3..9132726 100644
--- a/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu
@@ -1,17 +1,17 @@
# $FreeBSD$
begin 644 img-1x1-4096-vtoc8.vhd.gz
-M'XL("(<EAE4``VEM9RTQ>#$M-#`Y-BUV=&]C."YV:&0N;W5T`*V636_C(!"&
-M[_D5(_76@P4#'B?7JMW;2BOUT&MP3*JHVFW5Y-!#?OPR-O[`F#1M<3#"PO/X
-MG6&8($1W`9`"V@-9H)+'E0;:0+4&<).^8=M+_PCGW>L_NSL=/@I_G5<=3(JI
-M56C.]JA`NX]4@(8_0@V/X=QCBIN'Y]O#W^<>AQZ''E16;*40J(Z^0V)0QZ2G
-M`[ZTR.VH3L7J1BMWUQJ$!BDG;ZA>W7;0.."TL]KOVU:Q(HY/WX*'8()Q+T41
-MXTHQLYK(7`KJQ-DE'%VR^@KN=N77HDL5EQB5ZUWH)%3(8Y<V?1RBYE+EX_AF
-MWH]VI@\3J4*#/AG-J;2[Z%,%^Y>]`LWI?,E=:"FG.6XA57X4/0KMM!^X((BR
-MG\#6_3!Z(PJF^DB*"S%/+T92GV%]FGA%N0J4H!%*MUDU*'(33<KA7^_6WCW>
-MT^\P?B:QNM^.GUD'=I_LCC6(#5>-9+J8S6BU^?EF,R:7NQVNOA;'Y:N!QH*U
-M,]QV@MME7HPZ<M=R)JOK@&+N;LWNJMG[TO<)'!=2$>GK<*.[.#'!`!<5%U8'
-MPS:;XIH!-]?XB;-B49W-FBKU_EI<8Z"VH!2H,L*ITN-V;.7^B(19Z-,3YS]%
-M^.M2!7U=R5:H,+="[8'9%#J@S:Q0BHN9\=7]2UYAIE,?XS*>^AB7\=3'N(RG
-;/L9E//4Q+N.ICW%93WW4YM[J/Q`EJ(,J#```
+M'XL("!@UQ%4``VEM9RTQ>#$M-#`Y-BUV=&]C."YV:&0N;W5T`*V634_#,`R&
+M[_L5!FX[3(F;IML5`3<D)`Y<2==L3(@/`8<=QG_';I.U:9MM0+HL2I?ZZ6O'
+MSB)$<P'H#/0*M`6=\[A0H!=0S`%HTC6L>^EN8;=\>[7+K\UVYJ[=I(%)T;4*
+MS=D>,U#TD@+0\$MTQ6/8><SLXGH]W;RL/0X=#ATH+]@J0]#EX#V*?ITWZICT
+ML,'G&GGYM%>7#=6U5O0M*A`*I.P\D7EUA)E]A\XJLEJMZE:`L'5\?`MN@HG6
+MV5[L<M&SZL@<"ZIHG1W#Z4-6O\%-)VXMFE2AQ"BH%Z`E%,AC2AL?AT&C5-E^
+MOIN/3]O3AY%4T7M]<C"7Q=U%ERKH'W8*%*?S(7>AIGSU<2.I\J_HZ=!.N0$%
+M0>1^`FOWP^BU*.CJTU(<B'E\,:+Z#.M3FE>4=X&<"R.G8E604?Q4%7/XYL/:
+MR_LK=1O&ST16]\_Q,_/`[DAU4$4O>->(IHM9M%:+_Q>;,:G<;7#EJ3@J<E%!
+M9<':'NZQ@ULF7HQRX*[E3$99)\LQX)GJN5NRNXUQ?X5E#,<;:0L*<:V[V#'!
+M`#?87%@=[,NLBZM:7$_CD>B%^CS.)DV5<G4JKC)06D`<VT;//6[)5O1'),Q(
+M'Y_8W<W"3Y,JZ/:59!L5IE:H'#"90@+:Q`JE.)@9OZU?[10F.O4Q+N&ICW$)
+A3WV,2WCJ8US"4Q_C$I[Z&)?TU*?KW)O\`()N%&`J#```
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu
index b5d2305..a9aaac8 100644
--- a/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu
@@ -1,18 +1,19 @@
# $FreeBSD$
begin 644 img-1x1-512-apm.vhd.gz
-M'XL("%4EAE4``VEM9RTQ>#$M-3$R+6%P;2YV:&0N;W5T`*U6R6[;,!"]^RL&
-MZ"U`!7)$CMIC@R:W`D&#HL=$D:E`R&;$!IJ#/[X<BK16JK9+F29(4//T^&8A
-MA6@?`,J!:B`#I'E<**"O4'P!L(N^H>NEG\*^>GLUU:[YR/RS7[5@4O2MAN9L
-MCSDH^Y$"L.2/T)K'L`\PV:>KQXOFY3'`H8=##Z0+MLH1Z&'R'1('=HSTN\$G
-M!WG?L<NG[#HK^W]0(!1(V7LC#^SN#QP/<,I:U;5K!3-B?4(;3`8+#/>495,X
-M+496/9ISHO8V.P='2U:GP%VLO"_:4+&!4=C>2B>A0![;L`DZ3)H-E8_MIGS?
-MFA$_C(0*'?C)R5H>WR[Z4,'PLF>@.)R7M@L.93>&FPF5_U*/AG;*#ZP(0H<%
-M=-L?JM=!09\?2;&@>=P947XE\[.IJ;'+-MOR?VWXZB?#B+$[RHAWS]:OXF6;
-M(6H]%Q7=9)R[-S]FPZ5B?DIR&',D5QS#Q_#[MMD\FQDX3+7=%BZ?LM.USSF7
-M=&V)=GU;NG4=V-W9;-LUN^;M]2[`<:'B4NL0CV?W4FYFV>G$OC5'^C8D#7K`
-MH6\A\#.I8\\X=Q`+SR>D!H6@[4&F`->6N.8U.Y\`7K\;<WG[_?.OZ]N^?D:E
-MY2?%$?IA3[\V2?KZ]6N+C!WBY_-;U(\/DV(F-CO]MG_:0`S\4NN'7C]1SO3Q
-MA?U--ORU@.B+:;+JC%WU2\-0><!D#%67PZD82EITYJE>)L\PT567XE7FG*LN
-IPR6\ZI(O65$K<=)5EWS)2G359;B$5UV&2WK5)5=05W\!EOB&R!\-````
+M'XL(".XTQ%4``VEM9RTQ>#$M-3$R+6%P;2YV:&0N;W5T`*U6R6[;,!"]^RNF
+MZ"U`#7)$CM)C@R:W`D&#HL=`E:E4:),8L8'FX/Y[.5RBC1)LES)-D*;GZ?'-
+M0@KA'P`J@!H@`Z1Y7"J@CU!>`MC%T-#U,DSA4#\_F7K?OJ[#<UAY,"GZ5D-S
+MML<"E'U)"5CQ2VC#8SA$F/7[ZX>+]O$APF&`PP"D2[8J$.C'Y#W*_GKIV3'2
+M]Q9_.<BKGV_LBBF[SLI^RPT(!5+V_E%$=A9F_7>X666MFL:U$H1Q^L0VF`P6
+MNLV.M--B9-6CF1)5=)M-P=&2U2EP%ZO@"Q\J-C!*VPL@"27RV(9-U&'2;*B\
+M[K;5R\Z,^.%,J-`;/SE9*^:WBR%4,/XY,%`<SDO;!8>R'\,E0N6_U*.AG0H#
+M*X+0<0'=]H?J=5#0YT=2+&@^[XQ9?A7SLZFIL<LVIB2A6-3O^BO#O%,C_:H9
+M[YZM7\W+-D/4)A45W62<N[=?DN%2,S\E.8PYDFN.X6/X?=IN?YL$'.;:KH<K
+MINQT$W+.)9TOT:[WI5LWD=V]S;9]NV^?G^XC'!<J+K4.\7AVC]4VR4YG]JTY
+MTK<Q:3``#GT+D9_)'7O&N8-8>#XA-1\:VAYD"G!CB6M>L_,)X,V+,5=WGS]\
+MN[GKZV=47GY2'*$?]O3S2=+7KU];Y-PA?CZ_1?WX,"D3L=GIM_OC`S'RRZT?
+M!OU$E>CG%PZWZ^''`V(HIMFJ,W;5+P]#%0"S,51=#N=B*&G1F:=ZF0+#3%==
+MFJ\RYUQU&2[C59="R9JU$B===2F4K$Q778;+>-5EN*Q777(%=?4/V&/DOA\-
+"````
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu
index 9949cd1..04627e2 100644
--- a/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu
@@ -1,17 +1,17 @@
# $FreeBSD$
begin 644 img-1x1-512-bsd.vhd.gz
-M'XL("%@EAE4``VEM9RTQ>#$M-3$R+6)S9"YV:&0N;W5T`*V738^",!"&[_Z*
-M2?;F@;1#*7C=Q/N>UJN(:(S9CZP>//#C=P8*M!10=PO8E+3S\,YTIJE"-!>`
-MCD$?0)>@$^ZG"O0*T@R`!LV#=2O-*U3%UV=97$^WR%S5HH%)85NYYFR/,2CZ
-M2`J8\T?TGOM0M9CH97U<GCZ.+0X-#@TH2=DJ1M`[[SM:=.J8M#GAN49N>W6Q
-MKZZWHM].@5`@I34C;M5M.XT=3I'5X5`_*2OB^+2/\^(,,.X<13XN$0,K2^98
-M4"UGQW!ZSNH9W')AUJ))%4J,E%H*G804N4]IT\;!>RA5;I?O_.=2#O3A1*KH
-M3I_TQN)I=]&D"K:3C0+%Z3SG+M24ZQ`WDBK_BIYV[93I4!!$T@Y@[;X;O1X%
-MMCXMQ4S,IQ=C4E_.^A3563[23@]4KY%[=\""@52O5.Z)A@P?C>!F_3ZVOL5$
-MNORQ.@J\A^L$RT=PL:E=BQ+WN*F!!B<,2_0X-:>.<Z9\RMDD<#(7V<#.7F>0
-M!Y![$)F5U1:P6U_H]:U\&>BX.Z,/?'=SQJ7N?&GA\(Z[X.)VLVL[KT[XZHK`
-MB[$?5L:#E<L0MW(;'(;="+#>62@#:9;?3@]4;Y%[-T`T6U6PO0_;K2J40F6`
-MP102L`RL$,O99'LV"[51&.@@R;B`!TG&!3Q(,B[@09)Q`0^2C`MXD&1<T(.D
-/IK\(0BQ^`5WG%2]]#```
+M'XL("/$TQ%4``VEM9RTQ>#$M-3$R+6)S9"YV:&0N;W5T`*V736_#(`R&[_T5
+MGG;KI`@<`MEU4N\[K><T3;=JVH?6'GK(_OOL!%+(U]J-A%)2\)/7QB`J1'L!
+MZ!3T#G0%.N.V4:#OP>0`U&D+-K6TCU"7'^]5>=R?$GO5BQ8FA6\5FK,]IJ#H
+M)0:PX)?H+;>A=ICD=O6\W+\].QQ:'%I09M@J1=";P7L4_9JWZIBTWN-K@WQX
+MZ=2E0W5G*_J8+0@%4GHC4J>.,,EWZ*PBJ]VN*09$U<3'E>`AZ#@[VXM=)GI6
+MGLRQH(JSLV,X/6=U#6ZYL'/1I@HEAJ%:@)9@D-N4-BX.@T*I<CI\%E^'JJ</
+M)U)%=_KDH"^==A=MJJ`;;!4H3N<Y=Z&A'/NXD53Y5_1T:*=L@X(@,M>!C?MA
+M],XH\/5I*69B/CT9D_H*UD>+010C]71'_9"$=P<L&4CKE99[IB''2R.X7CV-
+MS6\YD2Y_7!TE_H;K!,M+<*E=NVYDJ@"[W7*RH\&IFQ;%WPZGYM1QSE17.9M%
+M3N8R[]GY\PRX`5&"R+VL]H`\OW<VGYV^^Z$,#-R=T0=#=PO&F7"\]'#XB[L0
+MXC:S<SNKSLVMCRLC3\:VOS(N7+D,"5=NB\.X&P$V.PME((T:UM,=]6,2WBT0
+M[585;>]#MU7%4J@L,)I"`E:1%6(UFVS79J&V"B,=)!D7\2#)N(@'2<9%/$@R
+;+N)!DG$1#Y*,BWJ0U/0708C%#^STEH1]#```
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu
index 7bbe238..d8b38b0 100644
--- a/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-1x1-512-ebr.vhd.gz
-M'XL("%PEAE4``VEM9RTQ>#$M-3$R+65B<BYV:&0N;W5T`*V737.D(!"&[_,K
-M.K6W'"QHH9U<MRKWO>SF&C6:FDKM1VURR,$?OR"@($+&+*/#:$$_OMTT+<.8
-M^0!0#30"#4!27S<"Z`Z:,X#JM"?.+;>W,/6_?PW]V^6]LI_I9&"<^5:AN;;'
-M&H1Z2`/8ZH?0D[Z&R6&J+_?/MY>?SPZ'%H<6)!MM52-0%SV'V*).DQXN^#(C
-M'U=U=:QNM5+?3@`3P+DWHG;J'A>-"TXHJW&<ST8KTO%Q9W`3=&C<2U7%.,DV
-M5I[,O:!ZSN[A*&=U!'=[LG-A4D4E1J-:%3H.#>IKE38N#M&I4N7]]4_[]W78
-MZ,-$JM"BCT=]==I=M*F";K!5('0ZY]R%F?*VQ>VDRG]%CT([82]4$)AT'3B[
-M'T9O18&OCSC+Q#P]&4E];=:O3SC<=8>!"84&UR\.MW+UR"3)&DSD:7TW/NZI
-MM+OC,:"4T+81\+O3UVLKH<I>N].F.Z:O57@L^@8-5.5355])<,9K'7ZX_[$W
-M'4-B]1Z/G\'A1[A%,+\&5]M2ZD;ZF9'NF-8T,;\.)W+J]!(>#CDK"^?><-[8
-M^?,,3*V2'MC9]F$(7.875GUWL0P,W,WH@]C=5N.:<#SW</B!NQ#BNNS<YM7=
-MQ.KZPI,Q;E?&E2M70\*5:W!8MA#@7%E4!JI1<9ONF+Y5X6&`:-\<Q5Y%:&M?
-M,87"`HLI%*Z8EE-8LVRR'<U"L@H+[>LI7>X_LZ\GK]P7V->3*_<I*W9H7T^V
-=W!?:UY,K]V7V]1I7=%]/ZA\;8Z=_%7&;G0P.````
+M'XL("/0TQ%4``VEM9RTQ>#$M-3$R+65B<BYV:&0N;W5T`*U7P7*D(!"]SU=T
+M:F\Y6-!"8ZZIRGTONSD[CB936YNDDAQR</]]04!!Q8P)RC`Z33_?:YJ68<P>
+M`%0"=4`MD#372@#=@*H`M-$U''KN;J%OGI_:YOW\4;BC/U@PSD*OV-WX8PE"
+M/T0!UN8A=#+7T'N8XL?=P_7Y[X.'0P>'#D@JXU4BT''Q'*%_K2P[@W1_QC\#
+MY.WCR*Y<LIN\]$>=@`G@/!A1>G8:IO@7BQ7:J^N&IH"U0WQ\BVXBPR1V%CO)
+M9EX!S;6@LDGL&AQM>>V!NSZXN;"IHA-#Z9X!<5!HKG7:^#@LFDZ5C[>7^O6M
+MG?'#1*K0R(\O;&5:+KI403_8,1`FG;?DPH#R/H=;295O18]B/^$N=!"8]`8<
+MY,?1FZ`@Y$><;<0\/1E)?O6FKB\(/AYW`R886KAF%%S+29%-DBF8R-/\KD*X
+M4VZYW3Y`*:&N%X"_/+_&>.G:Q.J5/FWH;XOX'/FU!E"73UU])4&%EPJ^O_N]
+M-AUM8O7NCY^%P\_@1L+\$KC2E5(_,LR,M*&?TL1^>SBQQ<XLX7:76)DY]]IJ
+MYA?.,S"]2AI@E;-A##C.+TS\;I8T,)*[P0^6<FL#I^+Q/(##3^1"#'?<G-MM
+M=E=+=DWFR>CF*^/"E6M`XI5KX3!O(<"ALN@,U*.6?=K0_RSBTP*B>W-D>Q6A
+MJWW9&`H'F(VA\,4T'\.2;2;;WBPDQS#3OI[2Y?XK^WH*RGV&?3WY<I_R8KOV
+@]>3*?:9]/?ERGV=?;^"R[NM)_V-C[/`?[N]4)@P.````
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.gz.uu
index 9e6e5ae..81f18cb 100644
--- a/usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.gz.uu
@@ -1,22 +1,22 @@
# $FreeBSD$
begin 644 img-1x1-512-gpt.vhd.gz
-M'XL("&`EAE4``VEM9RTQ>#$M-3$R+6=P="YV:&0N;W5T`*V82V_4,!"`[_LK
-M!G$K(CB.[63%":0B<2L(Q*6'YN%4*V!YM(<>\N/Q.'82;^R4;2?KC;+RSI=Y
-M>3PR8^,%H`I0/2@-2N)S*4#MH:P`S*0;W-YS]Q.&]M=1M_>'A\Q=PVZ$Y6PI
-M%8JC/"]`F)>4P&M\B>KP&0:/R5Y>WEX<?MYZ''<X[D"R1*F"@VI6[U%LT@Y)
-MWP[\NT7>S-H5:^UF*?-M!#`!>;[X1^&UNYETG'#"2/6]'244#<I.(_@13"#N
-M;9:M<9*=2"W4C#EU86P,I[:DSL%=[%PLQE0QB5&:NW%=#B7'9Y,VW@^K85+E
-MX>YW_?=.G^C'$ZFB)OWRU5R1-I>[5.'^STX#@>F\92Y8ROTI+I(JS_*>"N5\
-M=(T3F/03W)H?>F]&P5(_E;,-GZ>#D=2O1OV$66=UY)Z>&-YGX6<"-LUY0._!
-M$#<9W+3H/UL'M)XM&I-D=FRQ$1"V\%_3$<>WZ<\#2@EUO0)^]?JU-AP2A`*Q
-MQ\0PQ4'D(#G(.9VM[;)=ZG?YX2-<O?O\!6'7L[DMIHON<`69^MEW)]JM5]ID
-M[B&VV%H^9A_OH\862=R;Z-IM<;$9I=*XV$CCQ);4M)?\1VQ'G&2A5+64JB14
-M9CMJH:N3N!\!CKHN:YQN%)0M;N$RA];NY9W"C0PJLTPJ"^'`3=S-QFYVX0:!
-MP_%3=AQAK[,_KYQ^.G<9$1OIB93W--_*"%3J$7,AQ%'795VA]R29]_8N66(C
-M/9'T7CUZ+^XD5"JV=*==+<M>A+B&UGNY;1_-^C#U>WU/3PQ76?@9@=QM0V3[
-M&G>%E$Q#X8!D&@JW?@DUS,5F,,^-LG)!(:HPB".L,(@CK#"((ZTP""2L,(@C
-MK#"((ZPPB".M,(JV$5*N$6*E#4`!C0[52+8T@P^$;SD\CF^U3QN-4#P8E(V0
-M>JP1ZG726'^=&$O8""GJ1DBY0DITEJ%\([36X2EG&<HW0FQVX#/.,E2\$7KJ
-;60;B",\R$$=XEH$XXE3!OF7W#R':UU\`$P``
+M'XL("/<TQ%4``VEM9RTQ>#$M-3$R+6=P="YV:&0N;W5T`*V82W/3,!"`[_T5
+MF^%6!H_>=F[0F3)P*PP,%RY^I62`\&@//9C_CE:6;,NV#&G743U)E/V\+ZVV
+M8JR_`(P$<P#3@M'X/E=@]I`7`';2#^'NW'^$KOYQ:NO[XT/FK^ZBAW$VE8K%
+M45Y(4/8A.8@2'V(:?`]=P&3/KF\OC]]O`TYXG/`@G:.4%&"JQ7.4_;;HM4/2
+MIZ/XZI!77P;MY%*[4<K^Y0TP!9Q/?B&#=A:3_8F-55;J<'##0-.B[#"B#]'$
+M:.S,=YK-I"9JKCF5C<:NX<R6U#FXRPL?BSY5;&+D]L[`<,@%OK=I$_RP&#95
+M'NY^EK_OVIE^(I$J9M"/+^9DVESA4T6$'WL-%*;SEKG@*/=SW$JJ/,E[)I8+
+MT;5.8#I,"&=^[+T1!5/]#&<;/D\'(ZE?B?K9Q<#*E7MZHKO*XM<`K*KS@,&#
+M,6XPN*K1?ZX.M.UH49\D7E@J$#P9$+6;^*]JB.-;'<X#:@UEN0!^#/K5+AP:
+ME`&UQ\2PQ4%QT`+TF,[.5EU/];M^_19N7KW_@+#/H[FU2Y<&5('%DQ]FVBU7
+M6C#WC5A;;#4N-BGGW@XXF<+)W>K:K7&Q2;Z!6QO0\01.;4D->\E_Q+;':19+
+M%5.I0D-AMY`:FC*)^Q;AJ.MRB].5@;S&+5QSJ-U>WAC<R*"PR\3M;]8"8;<W
+MN[%;1U<([$[OLE,/>Y']>N[U:[G/B+61GDAYKQ5;&8%*_<-<B''4=;DMT'N:
+MS'M[GRQK(SV1]%[9>V_=2:C4ZI()NUJ6[6)<1>L][MI'NSYL_5[>TQ/=31:_
+M>J#PVQ#9OB9\(2734'D@F8;*KU]"#;G:#.:Y458B%X05!G&$%09QA!4&<:05
+M!H&$%09QA!4&<805!G&D%<8"73(3-4*(\WVS]7-E_Q6=J9%L:5"_EXB2L;E*
+M;+5/Z48H$0Q%V`@A;K,1DNG8^DO,C"5LA!!'V@@97TB)SC),:(26.CSF+,.$
+H1HB-#GS"6899;X0>>Y:!.,*S#,01GF4@CCA5L&^Y^`N^QF[[`!,`````
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu
index 831f819..6aa2b8a 100644
--- a/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-1x1-512-mbr.vhd.gz
-M'XL("&0EAE4``VEM9RTQ>#$M-3$R+6UB<BYV:&0N;W5T`*V7/6^D,!"&^_T5
-M$UV7`MF#/9#VI/377-(&"$2K*+G3)44*?OS98!L;8[(DWF59D#T/[WQXULO8
-M_`*@$F@`ZH&DOJX$T`U4-8`:-`=.9VYN8>S^O/;=^_FC,*_Q-,,X\ZU"<VV/
-M)0CUD`JPT0^A1WT-H\44/VZ?KL\O3Q:'!H<&)"MM52)0&SV'F%.G2?=G?)Z0
-M#XNZ,E:W6*E/*X`)X-R;45IU#TZCPPEE-0S346E%.C[V"&Z"`8U[+HH8)]G*
-MRI.Y%53/V2T<[5D=P5V?3"[F4E&%4:FS"AV'"O6U*AL;A^A0I?+Q]K?Y]]:O
-M]&&B5,CIX]%8F7873:F@G6P4"%W.>^["1'E?XS9*Y5O1H]!.F`L5!";M`$[N
-MA]%;4.#K(\YV8IY.1E)?H_4)M<Z:C7-Z8/Q9A&\';-MCP)K-"D.<<[CMG,.-
-M7#R:BV0))O)T0JZ\^+6/F?/;#L>`4D+31,#?5E^7.QV]!JKVJ;JO)*CQ4H?O
-M;^^VEEN?6+U?;%8]?H9S@ODEN-*T4CO3KXSTP+B4R?QM<6)/G5["_2%G9>;:
-MZ^N5G9]G8&J5=,!JK\EX0)=?6/3=Q#(P<'=''\3N-AI7A?.YA\-/W(40U^[F
-M=E_=5:RNRYR,8;TR+ERY&A*NW!F'>1L!3IU%5:":%9_3`^.O(GS/0#2_'-E^
-MBM#TOFP*A0%F4RAL,\VGL&2[Q7:T"LDHS+2OIW2[_\J^GKQVGV%?3[;=IZS8
-BH7T]F7:?:5]/MMWGV==K7-9]/:E_;(R=_@,`JJ]S#`X`````
+M'XL("/LTQ%4``VEM9RTQ>#$M-3$R+6UB<BYV:&0N;W5T`*U7SW.<(!2^[U_Q
+M,KWEX,`3GN::F=Q[:7-65].=3MM,DD,.]G\O""B(F#5%6187WL?W?LHR9BX`
+M*H$&H!Y(ZG$E@.Z@J@'4I&TX]=P^PMC]^=UW;Y?WPE[CR8!QYDN%XEH>2Q!J
+MDPJPT9O068]A=##%EX>GV\NO)P>'%@XMD*RT5(E`;;2/4+_6AIU&>KS@SPGR
+M_L?,KHS9+5+J4YV!">#<6U$Z=@JF^!LJ*Y34,$RM`M9/]G$M>`@F%F57MI-L
+M)>71W#(J6Y3=@J,]J2-PMR?K"Q,J*C`JU3,@#A7JL0H;9X>HJ5!Y?WUN7E[[
+M%3],A`K-_'@T5Z;511LJZ!9;!D*'\YZZ,*&\K>$V0N6_K$>AG+`#900FW01.
+MZH?66Z#`YT><[=@\[8PDOT;S4\G`FHT^/3'>%^$]`[;M,<":&88AW*QPV\T*
+M-W+1R`3)8DSD:8?<>/9KSYG]VP['`*6$IHD`OSE^76YW]!I0E4]5?25!C=<J
+M_/CP?2O=^D3V?K)8]?@1W$R87P-7VE+J5OJ1D9X8ES`QWPY.[+'3*=P?4E9F
+MCKV^7LGY?@:FLJ0#5GM%Q@.<_0L+O[N8!@;J[O"#6-U&PU7A>N[!X0?J0@C7
+M[OIVG]U-S*[+[(QAG1E79JX&"3/7P&'>0H!395$1J%;%?7IB_%J$MP%$^^;(
+M]BI"6_NR,106,!M#X8II/H8EVPVVHU%(EF&F<SVER_UGSO7DE?L,YWIRY3XE
+CQ0Z=Z\F6^TSG>G+E/L^Y7L-E/=>3^L?&V.D?^S1@R`P.````
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu
index 73e0637..fd654d6 100644
--- a/usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-1x1-512-pc98.vhd.gz
-M'XL("&DEAE4``VEM9RTQ>#$M-3$R+7!C.3@N=FAD+F]U=`"METUO@S`,AN_]
-M%:YVZP$E)H3V.FGW7;9=1RF=JFD?6GOH@1\_&Q)("-!V"Z0H*/CAM>.85(CV
-M`-`IZ#WH"G3&_5R!WD"^!J!!T["Y2G,+=?GU696GPSDQ1[UH85*X5KXYVV,*
-MBEZ2`Q;\$KWC/M06D]P]O*T.'V\6AP:'!I3E;)4BZ&WP'BTZ=4QZ.>![@WSM
-MU:6ANMZ*?EL%0H&4SA.I5??::>QPBJSV^Z;EK(CC8YMWXPTP[CU)0EPF!E:.
-MS+&@.LZ.X?2<U2VXU<+,19LJE!@Y72ET$G+D/J6-C4/0*%7.Q^_BYU@-].%$
-MJNA.GPS&TFEWT:0*VH>-`L7I/.<N-)33$#>2*O^*GO;ME.E0$$1F![!QWX]>
-MCP)7GY9B)N;3DS&IKV!]BM99,7*='JCO$__L@-O];<`L@R($/EF'2]:W45"J
-ML;B[3EZU.LJ)[/OS_%:1XX>-PU3OJ%QF&M9XK<*7A^<1AS&>PRT.+^$ZP?(:
-M7&IJGWV2U&+WM9D<:'%+PUKV.#6GCM=<=9.S6=QDP7(]L'/G&03E<`EB[50%
-M!]C-+_3Z-J$,]-R=T0>ANP7C<O]YZ>#P@KO@X[:S<SNO;AFJ*R-/QFZX,JY<
-MN0SQ5VZ+P[B%0#65F3*0:V1PG1ZH'Q/_;(%H2GVT;P>:VAQ-H3+`:`J5J<X1
-M%:IJ-MENS4)M%$;:B#,NXD:<<1$WXHR+N!%G7,2-..,B;L09%W4CKNDOEA"+
-)7SQ_K7"]#0``
+M'XL("/\TQ%4``VEM9RTQ>#$M-3$R+7!C.3@N=FAD+F]U=`"ME\%RHS`,AN]Y
+M"F7VU@-C"V.3:V=Z[V6W9T)(-]/9;:?)H0?Z[I7`!AL#378-Q$-BZ^.7+`M'
+MB/X`T#GH(^@&=,'W1H'>@2D!J-->V+72?H6V?OW;U)?31V:/=M/#I/"M0G.V
+MQQP4/<0`5OP0?>![:!TF^_'P?'?Z\^QP:'%H085AJQQ![Z/G*/JU[-4QZ>F$
+M+QWR_O>@+H_5C5;T,0<0"J3T1N1.'6&RS]!915;'8W<9$$T7'W<%7X*.T=E)
+M[`HQL?)DS@55C,[.X?2:U2VXNXV=BSY5*#$,M0*T!(-\3VGCXA!=E"H?Y[?J
+M_=Q,].%"JNA!GXSZ\F5WT:8*NL%6@>)T7G,7.LIEBIM)E?^*G@[ME+VA((C"
+M=6#G?AB]$06^/BW%2LR7)V-17\7Z:#&(:J9=[FCOL_`<@/OC;<"B@"H&_G0.
+MUZQOIZ!6<W'WG;QJ==0+V??/\]LDCA]V#E.]HW)9:"CQ6H5/#[]F',9T#O<X
+M_`XW");7X');^]Q(4HO#VV:QH\=M+6L[XM2:.EYSS4W.%FF3!>MR8N?/,PC*
+MX1I$Z54%#SC,+XSZ=K$,#-Q=T0>QNQ7C3#A>>CC\QET(<?O5N5U7MXW5U8DG
+MXS!=&5>N7(:$*[?'8=I"H+K*3!G(-3)JESO:QRP\>R#:4I_LW8&V-B=3J"PP
+MF4)EJW-"A:I93;9;LU!;A8DVXHQ+N!%G7,*-..,2;L09EW`CSKB$&W'&)=V(
+/:_J+)<3F"Q0&'5:]#0``
`
end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu
index a1c781c..d9a0c6e 100644
--- a/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu
@@ -1,17 +1,17 @@
# $FreeBSD$
begin 644 img-1x1-512-vtoc8.vhd.gz
-M'XL("&PEAE4``VEM9RTQ>#$M-3$R+79T;V,X+G9H9"YO=70`K99-;^,@$(;O
-M^14C]=:#!0,>)]>JW=M**_70:W!,JJC:;=7DT$-^_#(V_L"8-&UQ,,+"\_B=
-M89@@1'<!D`+:`UF@DL>5!MI`M09PD[YAVTO_".?=ZS^[.QT^"G^=5QU,BJE5
-M:,[VJ$"[CU2`AC]"#8_AW&.*FX?GV\/?YQZ''H<>5%9LI1"HCKY#8E#'I*<#
-MOK3([:A.Q>I&*W?7&H0&*2=OJ%[==M`XX+2SVN_;5K$BCD_?@H=@@G$O11'C
-M2C&SFLA<"NK$V24<7;+Z"NYVY=>B2Q67&)7K7>@D5,ACES9]'*+F4N7C^&;>
-MCW:F#Q.I0H,^&<VIM+OH4P7[E[T"S>E\R5UH*:<Y;B%5?A0]"NVT'[@@B+*?
-MP-;],'HC"J;Z2(H+,4\O1E*?87V:>$6Y"I2@$4JW634H<A--RN%?[];>/=[3
-M[S!^)K&ZWXZ?60=VG^R.-8@-5XUDNIC-:+7Y^68S)I>[':Z^%L?EJX'&@K4S
-MW':"VV5>C#IRUW(FJ^N`8NYNS>ZJV?O2]PD<%U(1Z>MPH[LX,<$`%Q475@?#
-M-IOBF@$WU_B)LV)1G<V:*O7^6EQCH+:@%*@RPJG2XW9LY?Z(A%GHTQ/G/T7X
-MZU(%?5W)5J@PMT+M@=D4.J#-K%"*BYGQU?U+7F&F4Q_C,I[Z&)?QU,>XC*<^
-:QF4\]3$NXZF/<5E/?=3FWNH_$"6H@RH,````
+M'XL("`(UQ%4``VEM9RTQ>#$M-3$R+79T;V,X+G9H9"YO=70`K99-3\,P#(;O
+M^Q4&;CM,B9NFVQ4!-R0D#EQ)UVQ,B`\!AQW&?\=ND[5IFVU`NBQ*E_KI:\?.
+M(D1S`>@,]`JT!9WSN%"@%U#,`6C2-:Q[Z6YAMWQ[M<NOS7;FKMVD@4G1M0K-
+MV1XS4/22`M#P2W3%8]AYS.SB>CW=O*P]#AT.'2@OV"I#T.7@/8I^G3?JF/2P
+MP><:>?FT5Y<-U;56]"TJ$`JD[#R1>76$F7V'SBJR6JWJ5H"P=7Q\"VZ"B=;9
+M7NQRT;/JR!P+JFB='</I0U:_P4TG;BV:5*'$**@7H"44R&-*&Q^'0:-4V7Z^
+MFX]/V].'D531>WUR,)?%W467*N@?=@H4I_,A=Z&F?/5Q(ZGRK^CIT$ZY`05!
+MY'X":_?#Z+4HZ.K34AR(>7PQHOH,ZU.:5Y1W@9P+(Z=B59!1_%05<_CFP]K+
+M^RMU&\;/1%;WS_$S\\#N2'5012]XUXBFBUFT5HO_%YLQJ=QM<.6I."IR44%E
+MP=H>[K&#6R9>C'+@KN5,1EDGRS'@F>JY6[*[C7%_A64,QQMI"PIQK;O8,<$`
+M-]A<6!WLRZR+JUI<3^.1Z(7Z/,XF395R=2JN,E!:0!S;1L\];LE6]$<DS$@?
+MG]C=S<)/DRKH]I5D&Q6F5J@<,)E"`MK$"J4XF!F_K5_M%"8Z]3$NX:F/<0E/
+@?8Q+>.IC7,)3'^,2GOH8E_34I^O<F_P`@FX48"H,````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu
index 883c81f..01a176d 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-4096-apm.vhd.gz
-M'XL("*@EAE4``VEM9RTV,W@R-34M-#`Y-BUA<&TN=FAD+F]U=`"M5LMNW"`4
-MW<]77*F[2!W!->!T535JLJL4-:JZ3%P/CJPTR2@S4K/PQY?+(\8/7&?*#,(@
-M?(\/YSZ`,?<#4`6H!I0&)6E<"E"?H#P',(N^H>VYGT)7/S_I^MB^;OVOVS@P
-MSF*KH3G98P'"?*0$K.@C:D=CZ`+,]L/E_5G[>!_@T,.A!Y(E614(ZM?D.XJ]
-ML2.DGRT^6,B[GETQ9==;N4?30-%$;Q2!W9WM/\>;%<;*O$]-42-]0AM,!@O]
-M9D?:23:RBFC.B1IM=@Y.+5F]!^YLXWWA0L4$1FEZ(QV'$FELPB;H,&DF5%X/
-M^^KEH$?\,!$JZHT?GZP5Z>VB#Q4,+WL&@L)Y:;M@48YCN)E0^2_UU-!.^($1
-M@<FP@';[0_5Z*(CY*<X6-$\[(\FO(GXF-27VV69:\:\-7WXG&#9V1Y7P[LGZ
-MU;1L,D3LYJ*BG_#A0G?];39<:N(G.(4Q17)-,;R&WY?]_K>>@<-<VW5PQ92=
-M;'S.V:1S)=KVKG3+)K"[-=EV;(_M\]-M@*-"1:76(JYG]UCM9]G)S+[5*WU[
-M'N4)F_@6`C^=._:T=8<BX>F$E"`0I#G(!.#.$)>T9N83P*L7K2]NOG[\<743
-MZZ=%7GZ<K=`/(_U<DL3ZQ;6%IP[QT_DMZD>'23D3F[U^AS\N$`._W/I57C]6
-MS?3IA>YZ._P[0/3%-%MUQK[ZY6$H/&`VAJ+/X5P,N5YTYGN]K#S#3%==E:XR
-MIUQU"2[C55?YDI6T<H^U5UWE2U:FJR[!9;SJ$ES6JZZR!77S%RXBXYX?#0``
+M'XL("#0UQ%4``VEM9RTV,W@R-34M-#`Y-BUA<&TN=FAD+F]U=`"M5DMKW#`0
+MON^O&.@MD$4:2_+FDI+2Y%8(#:7'X'CE8)K'DEU(#LY_KT8/)#_9)-H5PD:>
+M3]]\\Y`8<S\`58!J0&E0DIY+`>H,R@V`6?0#[<S]*W3U\Y.N#^W;VO^ZE0/C
+M++7JFY,]%B#,)B5@19NH+3U#%V#6WR[O3]K'^P"''@X]D"S)JD!0=Z-]RBUL
+MW#X6[F^+_RSD>V17C-E%*^=@TT#1)%\4@=V[G;^GS@IC9;ZG(>&NM/J$T7OI
+M+41G!]I)-K!*:$Z)RJ*S4W!JR>HC<"<K'PN7*B8Q2C,S4!Q*I&>3-D&'T3"I
+M\K;?52][/>"',ZFBDF`,U\2\N^A3!</'GH$@@DON@D79#^$F4N5+ZJF^G?`/
+M1@0FPP):]_OJ12A(^2G.%C2?#\8LOXKXF=*4&*O-C$)#S9<<OOQ-,.?#<%0S
+MT?VT?C4MFPH1VY%=+[Z\O]!=_YI,EYKX"4YI3)E<4PX?P^]BMWO0$W"8RUT'
+M5XS9R<;7G"TZUZ+M[%JW;`*[6U-MA_;0/C_=!CAJ5-1J+>+Q[!ZKW20[F3FV
+M^LC8;I(Z8:/80N"G<^>>MN%0)#R=D!($@C0'F0#<&N*2ULS["/#J1>L?-S]/
+M_US=I/IID9<?9T?HAXE^KDA2_=+>PN<.\<_S6]2/#I-R(C>C?OM7EXB!7V[]
+M*J\?JR;F^87N>MW_.T#TS31;=\;8_?(P%!XP&T,1:S@70ZX7@_G1*"O<6)<S
+K774)+N-5E^`R7G4)+N-5E^`R7G4)+N-5E^"R7G4-H,F]U7^P3V5T'PT`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu
index 1f4a1b9..97c5f24 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu
@@ -1,17 +1,17 @@
# $FreeBSD$
begin 644 img-63x255-4096-bsd.vhd.gz
-M'XL("*PEAE4``VEM9RTV,W@R-34M-#`Y-BUB<V0N=FAD+F]U=`"MESMO@S`0
-MQ_=\BI.Z=4#F;`Q=FJA2]T[M3`A$4=6'F@X=^/"]`Q/.O)*T!F(9V??C?P];
-MCE+M!6`UV`IL"3;A?FK`WD&:`="@>[!I8_<*=?'Q7A;?AY_(7?6JA<5*6OGF
-M;(\:#'TD!<SY(W;'?:@[3'3SN+\]O.T['#H<.E"2LI5&L-O1=S)U4L>DEP.^
-M#M7IL;K>JG6PJD!78H:6ZJ)H+7&&K&@^/Q:V21.?[O%>O`&)\]0E:F`E9$X%
-M53@[A;-+5M?@;E<N%VVI4&&DU"JP,:3(?2J;+@ZCATKEY_B9?QW+@3Z<*14K
-MDC$<,_/NHBL5["8[!88%+KD+#>4XQ$V4RK^B9WT[XSH4!)5T`]BX[T>O1X'4
-M9V.U$//Y9,SJRUF?H7663[3S`_5#Y-\G8,%`6J^TW!,+&5X:P9?'YZG\%C/E
-M\L?54>`Y7"=8[@8^;BUPNDU'3Q'%"T4,NNS?S03NGGZ;'F>6U''-E%,#L\XF
-M@8NYR`9V,L\0EQ!K4)FH:@$\Y1=Z?7=C&>BYNZ`/QN[FC$O]^;'`X1EWP<=M
-MW;XL)O<I/!.]S5A=$3@9N^'*N'#E,L1?N2T.PVX$V.PL5($T:]S.#]1/D7^W
-M0'1;5;"]#[NM*I1"XX#!%!*P#*P0R\5BN[8*K5,8Z"#)N(`'2<8%/$@R+N!!
-=DG$!#Y*,"WB09%S0@Z2EOPA*K7X!<\?WIGT,````
+M'XL("#8UQ%4``VEM9RTV,W@R-34M-#`Y-BUB<V0N=FAD+F]U=`"MELE.PS`0
+MAN]]BI&X<:B<L6.'"TA(W#G!.4U35"$640X]I._.C!=B9RN+F]1R9,_G?Q9;
+M%L+]`+0$O0/=@BZY;Q3H*S`5``WZ%VU;^$_HFK?7MOG<']?^UZT<K!"Q56K.
+M]BA!T2(&L.9%]);[T`7,^N+NZ7+_\A1PZ''H0:5A*XF@-Z-US!8JMX[%/>[Q
+MV2)/O3HY5M=;.0=W.Y"[:(8,ZDZVO8F=561%\_DM86-L?,*;?"0#O;.#V)5B
+M8!7)G`JJZ)V=PNDEJ]_@+E<^%ZY4J#`,M0)T`0:Y3V43XC!ZJ52.A_?ZX]`.
+M].%,J>@H&<,Q->\N^E+!,-DK4"QPR5VPE,,0-U$J_XJ>3NV4[U`01!D&T+J?
+M1J]'0:Q/%V(AYO/)F-57LSY%.Z&>:.<'NMMU^GP#&P;2?J7M7FJ_QWX2P<>[
+MAZG\-C/E\L?=T>`Y7!`<GP8I[B;"29>.GA(5+S0%R-9_Q/T(=^W^`:>6U''-
+MM%,#L\Z6F8NYJ09V<9ZA:*&0(*JHJB/@=WZAUW<UEH&)NPOZ8.QNS3B3SB\B
+M')YQ%U+<QI_+86:2PC/1NQZK:S(G8SO<&3_<N0Q)=Z[#8=Z#`.W)0A5(L\;M
+M_$!WOTX?!T1_5&4[^S`<5;D4*@_,II"`;6:%V"X6VV^K4&-E7<YTD61<QHLD
+CXS)>)!F7\2+)N(P72<9EO$@R+NM%DH!4>ZLOT2?4EGT,````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu
index e6addcc..9c75099 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-4096-ebr.vhd.gz
-M'XL("+`EAE4``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FAD+F]U=`"MESUOXS`,
-MAO?\"@*W=3!D6I+=)0$*=+_EFEEV["(H^H'FA@[^\2=:4D+Y*TU/L2/(H/CX
-MI431D!#N!Z`+T!WH%K2B?BE!WT-9`5BCOW%H<_\(??/^UC9_CU^9__4;!\L%
-M]XK=R1\+D/8E):"AE^@#]:$/F.S7X_/=\?4YX-#CT(-425X%@JXG[ZG$61V1
-M]D=\&:LKINHN7B[`KH.B8R,*KB[+=APGK9<=3[>&6@WS$^[H(3)P7*1.B9$7
-MDSDWJ2S8.9Q>\[H%=[?Q:^%2Q29&:5L!.H<2J6_3)LS#Y+:I\G7Z,)^G=J0/
-M%U)%L\48V^1RN.A3!<-@KT"2P+5P8:"<QKB95/FOV=.QG_0=.PE"!0,.X<>S
-M=T$!UZ=SL3+GRXNQJ,^LQO6#@.OZ=N#*[J@;OSL$&$4M[=+<[U7OW]CG=D;?
-MSFW;+<<=4H?;W094"HR9`/\$?4WBY:@J,DM;1\U,NVSH'[+X.@.'A+'UV)9S
-MI:'"[RK</S[-K&]E%LK![0$['%[#!<&\VL>X'<,5;KOQ5+UX\;SC?8;;NG_`
-MR35U5!/:.<-BL"IQLIAJY,?7&?(6\@)$Y6T8`\_K"Q=]]U,9&(6[H@^FX1K"
-ME?'XG.'P2K@0X^IS99E9PBNSMYVJ:Q(O1CW>&=_<N02)=Z[#8=I"8(;*8C/0
-MCIJVRX;^=Q9?#HC^4Y3LVX:^F"93*#TPF4(+;!,K-&F_']HK3'10(%S"@P+A
-C$AX4")?PH$"XA`<%PB4\*!`NZ4%!VR.@$)M_4*:1%ET.````
+M'XL("#HUQ%4``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FAD+F]U=`"ME\%NI#`,
+MAN_S%);VU@,*)@GT,B-5ZGTOVYX#A6JTVK9J]]`##[\V"9`08#K=#$P4E/CC
+M=^P810C[`]`%Z`YT"UIQOY2@;Z&L`&C0W3BTN7N$OGE]:9N_Y\_,_?J#A>7"
+MMPK-V1X+D/22$M#P2_03]Z$?,=F/^^>;\Y_G$8<.APZD2K8J$'0=O:>K04BK
+MCDF/9_R]5%?$ZF8K^YZN@Z+S9A2^NBP[^3A)5C2?;P6U'M9GO(.'8,#'!>J4
+M6%AY,M<65<S.KN'TGM4UN)N#BX5-%4J,DEH!.H<2N4]I,ZY#=%.J?'Z\F?>/
+M=J$/-U)%3_KR:*S:=A==JN`46*M`<FKON0L#Y76)6TF5_UH]'=I)UZ%%$&H<
+MP,']</5F%/CZ="YVUGP[&)OZS*Y?WW"XKJ\'[NR.NG&[0X!1W/(NS=U>=?8-
+M/;<K^DYVVQY]W%-J=[OK@$J!,1'PUZBO21R.JN)A2774K+3;`_U=%EX3<$@8
+MJL=4SI6&"K^J\/'^826^E=DH!]<[;'%X"3<*]JM]B#MYN,)N-S]59RL_[_R^
+MASO:_XB3>^JX)K1K`YO.JL3)8JJ%G1]GR%O("R[&=@Q#X!1?F/7=QC(P<'='
+M'\3N&L:5X?S<P^$%=R'$U5-E60GAA=4[QNJ:Q,&HESOCBSN7(>'.M3A,6PC,
+M4%DH`VE6W&X/]#^S\+)`=)^B9-\V=,4TF4+I@,D4$K!-K-"D_7YH98.2Z*#`
+HN(0'!<8E/"@P+N%!@7$)#PJ,2WA08%S2@P(!*?<._P`B"8'870X`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu
index f47328c..0e9500f 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu
@@ -1,22 +1,22 @@
# $FreeBSD$
begin 644 img-63x255-4096-gpt.vhd.gz
-M'XL("+0EAE4``VEM9RTV,W@R-34M-#`Y-BUG<'0N=FAD+F]U=`"M6$UOU#`0
-MO?=7#.)61!H[\21[`8%4)&X%@7KAT"3K5"O$\K$]])`?C\=Q/IS8@6UGUTJS
-M<N;ES9OQ>.HT[3\`F`&V@!I0T7V1`^Z@*`',I!O27H7["5WS\ZB;A\-CXC[=
-M10\FTKF5;T[V,H/<O*0`6=%+<$_WT`TPR<OK^\O#C_L!3CHXZ8!405:9!*Q7
-M[\%T9$=(MP?YW4+>3>RR-;O)JO_3MI"ULR>R@=V=O;Z=.YL;*_,\#80&(<VG
-MX?WP)B9G%]JI=&$UHQD2=>9L"`ZWK,Z!N[QPL>A3Q21&8:Y&.@&%I'N3-H,.
-MJV%2Y?'TJ_IST@M^,I(J./(3J[DL[JYTJ2*'AQV#G-)YRUVP*`]+N$"J/$L]
-M].V&Z!H14C5,2.N^K]X$!7-^*-(-S>/!B/*KB%]NUED5N,8GNO>)_QT!Z_H\
-MP$%!'VYTN&Y(/UL'M)X\ZI-D$C;;"$@ZTZ_>,\>W;L\#5`JJ:@7X=>#7V'`H
-MR!'R'26&*0ZY`"5!3>EL?5?-G-_UAX]P\^[S%P+[-KG;4+KL)90--#MHZP6[
-M]4K;KBV-[+-/MD%GLRC<51B.%EN[WX`+C3A<OF4U[B7_[:Q*?:MR;I5IJ#-H
-M*ZCV$;@W"SCNNJQIND8H&MK"E8#&[N5[!"$`2K-,2@LB01J*9F,WNW!-@-WQ
-M4W+LP5XGOU\Y?EJXC`B-^$1,/6WK<AESMY@*=L1=\.&XZ[(N23W%IM[.)4MH
-MQ">BZE6]>F&12+W0TAUWM21YX</5O.H)NVN8]6'J]_H:G^AN$O_;`TJW#;'M
-M:](54C:&N0-D8YB[]<O(4.C-8)X;971!8:HP!,=880B.L<(0'&N%(4#&"D-P
-MC!6&X!@K#,&Q5ACD;830-4)9"5K0/RZUGS7QEJ8KDU-/[,ISUS9"T?9IHQ$*
-M!X.S$<)_-4*MCCD[XBR<96R$D+L10E=(F<XR<&B$UAR><I:!0R.43@(^XRP#
-APXW04\\R"([Q+(/@&,\R"(XY583I72[^`K`XWC\`$P``
+M'XL("#XUQ%4``VEM9RTV,W@R-34M-#`Y-BUG<'0N=FAD+F]U=`"MF$N/TS`0
+M@._]%8.X+2*R'=M)+D4@+1*W!8&X["7/584HCW+80_O?F7&<)D[BB(IIK2B5
+M,U_F;=="]!\`FX+MP+9@#=UG&FP!60Z`DWXH=Y7^)YSK'\>V_G-X3OSGO.MA
+M4DRE0G&25REH?$D&JJ27V(;NX3Q@DI?W3W>'[T\#3GF<\B"3D52JP%:+]V0-
+MY/U['.[K07USR,NH7;K4;I3J#>PZ2+O)$^F@W<5=WTR-U2B%S],PD&<@]#B"
+M'\'$:.S,=T;,I"9JKCE5C,:NX>R6U"VXNYV/19\JF!@97@58"9FB>TR;P0^+
+M@:GR?/I9_CZU,_U4)%7L)!CSN0WO*9\J:GC8:Z!)P2USP5%.<]Q*JOR7]VPH
+M-T07G2#,,*$&\W'@^T50&4Y1,>AGI=CP>3P84?U*TD]C)90KU_C$^5T2?J_`
+MJKH-.'@PQ%T#4M7D/U>I;3M:U">)%ZXEI&T\(/M)?*N&.;Y5=QO0&"C+!?#+
+MH%_MPF%`6]`%)08V!RW!*##ZBG.VFWJJW_W[#_#P]M-G@CV.YM:NV+#5E5!;
+MZGFA=LM*&\V]K!1;3<6&`9EY>\"E4=Q^M79K*K:JW<"MC3A.;TE=UY)_B&V/
+M,R*4RJ=2J'.50E="V41P^QF.NR^W-%UA5&M:PHV$VJWEC04I`7(LD]Q!%"A4
+M$1=V7(4K`IZ/'Y-C#WN=_'KE]6NESXBU$9^(>:]U?3F/F9N-#3MB+H0X[K[<
+MYN0]P^:]PB?+VHA/1+U7]MY;=Q)Y;ZUTKZM:DKP(<16O]Z1;-;`^L'\OK_&)
+M\T,2?GN@\LL0V[JF?"-ETU![()N&VM<OHX:RW0SFK5&V7D,VDRW^26#5,&MR
+MSAY(.,8>2#C&'D@XUAY(0,8>2#C&'D@XQAY(.-8>F#6%2V:FK1KA*/=D`5)#
+ME]&&+5`CNND:]=M/S2WZO]"Q#=[&5FTU&(5@W*H1;G.K5G6W&LNX52,<ZU8M
+L]WV/Z;2%<(RG+81C/&TA'.-I"^$83UL(QWC:0CCN5,&MR^XO,$6$MJ(3````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu
index e6996d1..b8584d7 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu
@@ -1,18 +1,19 @@
# $FreeBSD$
begin 644 img-63x255-4096-mbr.vhd.gz
-M'XL("+DEAE4``VEM9RTV,W@R-34M-#`Y-BUM8G(N=FAD+F]U=`"METUOXR`0
-MAN_Y%2/UEH.%QX#I)9$J];Z7W9[!M:NHVFW5[*$'__AE##C@KS1;8@=AP3Q^
-M!V;&@C'W`Y`5R`YD"U)0O^8@[Z%6`';0WSBTI7^$OGG[TS9_3Y^%__4[!RM9
-M;)6:DSU6P.U+:D!-+Y'/U(<^8(J[QY?]Z?=+P*''H0>)FJPJ!&EF[U%L5$>D
-MIQ.^3M55<W47*^=@UT'513.J6%U1'&,<MU9V/MT2C!C6)]S)0S(0XQ)U@DVL
-M(IE+BQHYNX236U:WX/8[OQ<N5&Q@U+9E($NHD?HV;,(ZS&X;*I_G=_UQ;B?Z
-M<"549+09TS&^[B[Z4,$PV2O@)'#+71@HYREN(52^M7HRM>.^8Q>!B3"`@_OI
-MZEU0$.N3)=M8\_7-6-6G21^W>:87VO6!_J%(KQ%HS&U`Q5QVI+C18=/X[&"@
-M!;64I:7/5;]^C7UN%S;DZ-+V$*V?><Z\OZ:[#2@$:#T#_@SZFDT9M^M3*O/^
-MJB%@;#VVY5Q(4/A5A4^/OQ;R5^F5<O!_U4]IO(8+@N-JG^*.$:YRZ7:A1,4I
-MB;NX'^$.[A]P?$L=U81V:6#569$Y6+2:V,7[#&4+905,^3%,@>/^PD7?_5P&
-M)NYNZ(.YNYIP=3J_C'!XQ5U(<6:L+`M;>&7U#G-U3>;-,-/,^&+F$B3-7(?#
-MO(5`#Y7%1J"=-6_7!_H?17HY(/I/4;9O&_IBFDTA]\!L"BVPS:Q0Y_U^2*\P
-LTT&!<!D/"H3+>%`@7,:#`N$R'A0(E_&@0+BL!P5ICX",[?X!!W"B9UT.````
+M'XL("$$UQ%4``VEM9RTV,W@R-34M-#`Y-BUM8G(N=FAD+F]U=`"MESUOI#`0
+MAOO]%2-=EP*9P39.LRM%2G_-);5-(%J=+HF2*U+PX\^##=@8V&S."VN!S#R\
+MGB]DQMP/0%8@.Y`M2$'7-0=Y"[4"L)/^Q&$L_2WTS>M+V_P]?Q;^UQ\<K&2A
+M56Q.]E@!MR^I`36]1#[1-?0CIOAQ_WQS_O,\XM#CT(-$3585@C3)>SH#C#MU
+M1'H\X^^ENBI5-UNY]W0=5%WP1!6J*XI3B./6RCY/IP`C!_^,9W03382X2)U@
+M"ZM`YII3V;S8-9S<L[H&=W/PL7"I8A.CMB,#64*-=&W39O1#<MI4^?QXT^\?
+M[4(?;J2*G/25R9S:7B[Z5,$IL$X!I]3>6RX,E-<E;B55_LM[,K;C_L(Z@8EQ
+M`H?EQ]Z;41#JDR7;\?EV,#;U:=+';9WIE7%[HK\KXF,"&G,=4#%7'3%N6K!I
+M?'4PT()&JM+2UZKW7V/OVY6`G%S9'@/_F:?,\37==4`A0.L$^&O4U^S*N%Z?
+M4IGCJX:$L?W8MG,A0>%7%3[>/ZS4K](;[>![W4]IO(0;!8?=/L:=`ESERFVF
+M!,TIRKOP.L`=W7_$\3UUU!/:M8G-Q8K,R:+5PBZ,,Y0ME!4U8S9UK0`XQ1=F
+M?;>I#(R6NZ,/TN5JPM7Q\V6`PPO+A1AGILZR$L(+WCNFZIK,P3#+ROABY1(D
+MKER'P[R-0`^=Q6:@?2H=MR?ZGT5\."#Z3U&V;QOZ9II-(??`;`HML,VL4.?]
+M?DCA@I)IHT"XC!L%PF7<*!`NXT:!<!DW"H3+N%$@7-:-@@7:W#O\`W7?LJE=
+##@``
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu
index 6257a74..662d2c3 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-4096-pc98.vhd.gz
-M'XL("+\EAE4``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G9H9"YO=70`K9=-CYLP
-M$(;O^14C];8'9,8?.)>-5&GOO;1[-A164=5VM>EA#_SX>K`=;`QDTSH09&3/
-MPSL?MF7&W`]`<5`#J!Z4I'8C0!VAT0"VT]\X/6O_"F/W^U??_3F_5_XW'ARL
-M9K%5:D[VR$'8CS2`ACZBOE,;QH"I/CV]/)Q_O@0<>AQZD&S(BB.H-ON.9E=U
-M1'H^XX^E.IZKFZV<@\,`?(A&\%A=59UBG+!6=CS="EHYQ2?<R4O2$>,2=9(M
-MK"*9:T&-G%W#J3VK>W`/!Y\+5RJV,!K[9*!J:)#:MFQ"'++;ELK[Y=6\7?J%
-M/MPH%14E8]DGMMU%7RH8!GL%@@3NN0L3Y;+$K93*?T5/I7;"-VP0F`P=.+F?
-M1F]&0:Q/U6PGYMO)V-1G2)^P\\RL/+<[QL]5>EV![7`?4$HP.?!K<+@C?4<!
-MG5B+NY^R6<7,#I_2_'8;U??/^>T+QP_-KI#[%6I=6*&>%-H5V2[H4H'&CRI\
-M?OJV,H.U*982A\-;N"`X7N]3W"G"<3?A9DI4;-#5P'O_$K<CW*/[!YS84T>K
-M0K_6L>FL+%PL1B_LXCQ#W4/-@6G?ARGPFE^8]1US&9BXNZ,/<G<-X9IT?!WA
-M\(:[D.):O_.&D4D*;T3O,5?7%4Y&NYP9'YRY!$EGKL-AV87`3"N+K4!:Q;/G
-M=L?XI4HO!T2_&17;W=#O'L44"@\LIE#X_:.@0M/M%MN]5:B\PD)'!<(5/"H0
-DKN!1@7`%CPJ$*WA4(%S!HP+ABAX5E#T$,G;X"[Z,PAU?#@``
+M'XL("$8UQ%4``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G9H9"YO=70`K9?/;Z0@
+M%,?O\U>\9&\]&'@".I=.TJ3WO>SVC%:;2=-VL^VA!__XY0DHB#J=+J-C,/`^
+M?M\/(#!F?P"J!-6#ZD!):E<"U!&J&L!TNAO')W>O,+1OKUW[<?XLW&\X6!AG
+MH55L3O98@C`?J0`U?40]4AL&CRE^W#_=G%^>/`X=#AU(5F15(J@F^4[?`!-6
+M'9$>SOB\5%>FZF8K^YV^A[(/1I2ANJ(XA3AAK,QXNB4T:HR/OZ.7J"/$1>HD
+M6U@%,M>"RF9GUW!JS^H:W,W!Y<*6BBF,RCP9*`X54MN4C8]#<IM2^7S_H_^^
+M=PM]N%$J:M+'D[YZVUUTI8)38JT"0:6]YRZ,E+<E;J54_BMZ*K83KF&"P*3O
+MP-'].'HS"D)]BK.=F&\G8U.?)GW"S#.]\MSN&.Z*^)J`37\=4$K0*?"7=[@E
+M?4<!K5B+NYNR2<7,#I_B_+8;U??M_':9XX=Z5\CU"NLZL\)Z5&A69+.@2P4U
+M?E7AP_WOE1E<ZVPIL3B\A/."P_4^QIT"7&DGW$P)B@U:#F7G7L)V@+NU?X\3
+M>^IH5>C6.C:=E9F+1=<+NS#/P#O@)2W';%JW`N"47YCU'5,9&+F[HP]2=S7A
+MJG@\#W!XP5V(<8W;>?W(*(47HG>;JFLS)Z-9SHPOSER"Q#/7XC#O0J#'E<54
+M(*WBR7.[8_A9Q)<%HMN,LNUNZ':/;`J%`V93*-S^D5&A;G>+[=HJ5-(F)=-1
+I@7`9CPJ$RWA4(%S&HP+A,AX5")?QJ$"XK$<%`S2U=_@'6B6GGU\.````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu
index 995a75a..4b1226c 100644
--- a/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-4096-vtoc8.vhd.gz
-M'XL(",,EAE4``VEM9RTV,W@R-34M-#`Y-BUV=&]C."YV:&0N;W5T`*V636_;
-M,`R&[_D5!';KP9`I6;9/!?;1VX`!.^PZV9:+8-A:M#WTD!\_TI83R5]K5B:"
-M8T/BXY<4Q5"I\0-@-=@>K`=;\'UIP-905@`T&08.USP\PJE]^./;E^-K%CZG
-MPPC+56R5FK,]:C#TDA+0\4MLQ_=PFC#9AR_W-\??]Q,.`PX#J"C92B/89O:>
-M'"IU5L>D'T?\-5>GY^IB*_[1T/>@^VB%CM5EV6V,,V1%ZWE8:/(A/M-('I*)
-M&)>H*]3,*E*Z%M3(V36<W;.Z!G=S"'LQI@HE1DE7!3:'$OF>TF:*PV)0JKP^
-M/[JG9S_3AQNI8L_Z\L5<N^TNAE3!:7%08):IDKH+`V6>*KA(E7=&SZ9V)@U2
-M_#"NH.BH8MM=>XD>3D&C0:I5N;<9V>"O6N!0[5CMX3;<=>RNL9P@7%0*,`@%
-MG7W#AQ<TW76K\;M[\O[C]\^HOR;ZW$:R_/=VN"JQ^\=AJT#57(0VM\/5%ZOZ
-M_6?7.2EW1USS5AS5#-5!Y\'[&>YGA&N%-Z-9N.N'_%=#^;W:W69R5U\6C^>*
-M*OL&+JK+MW-<FQRU>"!<[%?4P:JZ[HQK6C`ZM=IU]M,:SHNF2M._%=<Y:"A/
-M<NAWJG*[*^+:5,%05\0*%4HKU%WE>9K^RI5;N6Y/G+YEZ7<$FJ!0S&4"RBJT
-M`2BFT%(3*:JP[&H4W>4J*!3JFQDGV#<S3K!O9IQ@W\PXP;Z9<8)],^-$^V8"
--4NX=_@(M$JX@;`T`````
+M'XL("$DUQ%4``VEM9RTV,W@R-34M-#`Y-BUV=&]C."YV:&0N;W5T`*V62V_D
+M(`S'[_,I+.VMAQ$QA"2G2GWL;:65]K#7DH14HZH/M3W,83[\VH$TD-=V6C(H
+M`H%_^=L8#T*X!T!+T!UH"SKG?J%`5U"4`#3I&_;OS`_AU#P_V>;]<-S[Y[1S
+ML$R$5K$YVZ,$11\I``U_1+?<A].`V?^XO;\X/-X/./0X]*"\8"N)H.O)=S(6
+M7&JGCDE_#_C0(X^C.CE5%UKQ6$+7@>R"%7)0YUR]#)U59$7KN>50YWU\AA8-
+MHHG1V4GL<C&Q"I0N!56,SB[A]);5.;B+G=\+ERH4L8+>`C1%#[E/:3/$8=8H
+M58YO+^;US4[TX4JJC)N1S>::=7?1IPH.B[T"-4^5V%WH*0]3W"Q5OAD]'=NI
+M.$CAP*V@Z(A\W5T]1@^'H%$CU:+8VHQ][Z^8X5!L6&WA5MPU[*[2G"!<5')0
+M"#F=?<6'%R3UVL7X_7RU]NK/#<I?D3ZSDBQ?W@Y31G;_.6PEB(J+T.IVF&JT
+MJKY_=HU)Y:[#U9_%4<T0+;06K)W@[@)<DW@SZIF[ML]_T9??L]VM!W?EN-B=
+M*ZKL*[B@+E].<4UTU,*&,-HOJ(-%=>T'KFY`R=AJT]GK)9Q-FBIU]UE<:Z"F
+M/,F@VZC*S::(<U,%?5U)5J@PM4+9EI:GZ:]<F(7W^L3I]S[^.:#R"I.Y3,"T
+M"K4')E.HZ1*95&'15IATE\NB[/,PT;V9<0GOS8Q+>&]F7,)[,^,2WIL9E_#>
+3S+BD]V8"TOG=_0-Y#+@L;`T`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu
index da8f61a..5aa8ba1 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-512-apm.vhd.gz
-M'XL("(HEAE4``VEM9RTV,W@R-34M-3$R+6%P;2YV:&0N;W5T`*U62VO<,!"^
-M[Z\8Z"W0Q1I+X_944IK<"J&A])@X7CF8-,F276@._O'5Z!'+SSI;[0I90I[/
-MG[YY2%GF?@"4`]5`&DCQN)!`GZ'X!&`6?4/;"S^%MGI^TM6Q>=WZ7[MQ8"*+
-MK?KF;(\Y2/.1`K#DC]".Q]`&F.V'B_NSYO$^P*&'0P^D"K;*$>AN]!W*WM@Q
-MTJ\&'RSD;<<N'[/KK-RCKB&OHS?RP.[6]E_BS4IC9=[G1MQ8G]!ZD]Y"M]F!
-M=BH;6$4TIT2--CL%1TM6[X$[VWA?N%`Q@5&8WD@GH$`>F[`).HR:"977P[Y\
-M.>@!/YP)%7KC)T9K^?QVT8<*AI<]`\GAO+1=L"C'(=Q$J/R7>M2WDWY@1,A4
-M6$"[_;YZ'13$_$AD"YK/.V.67\G\3&HJ[++-M/Q?&[[XP3#9T!WEC'=/UJ_B
-M99,A<C<5%=U$]!?:J^^3X5(Q/RDXC#F2*X[A-?S.]_O?>@(.4VW7P>5C=JKV
-M.6>3SI5HV[O2K>K`[L9DV[$Y-L]/-P&."Q676HNXGMUCN9]DIQ+[5J_T;4@:
-M](!]WT+@IU/'GK;N(!:>3T@%$D&9@TP"[@QQQ6MF/@*\?-'ZZ_6WCS\OKV/]
-MM$S+3V0K],-(/Y<DL7YQ;1%SA_CI_!;UX\.DF(C-3K_#'Q>(@5]J_=#KEY43
-M_?Q">[7M_QT@^F*:K#IC5_W2,)0>,!E#V>5P*H:"%IWY7B^39YCHJDOS5>:4
-KJR[#);SJDB]9LU;NL?:J2[YD);KJ,ES"JR[#);WJDBVHF[_Y8*QC'PT`````
+M'XL("!LUQ%4``VEM9RTV,W@R-34M-3$R+6%P;2YV:&0N;W5T`*U62VO<,!"^
+M[Z\8Z"V011I+\N:2DM+D5@@-I<?@>.5@FL>274@.SG^O1@\D/]DDVA7"1IY/
+MWWSSD!AS/P!5@&I`:5"2GDL!Z@S*#8!9]`/MS/TK=/7SDZX/[=O:_[J5`^,L
+MM>J;DST6(,PF)6!%FZ@M/4,78-;?+N]/VL?[`(<>#CV0+,FJ0%!WHWW*+6S<
+M/A;N;XO_+.1[9%>,V44KYV#30-$D7Q2!W;N=OZ?."F-EOJ<AX:ZT^H31>^DM
+M1&<'VDDVL$IH3HG*HK-3<&K)ZB-P)RL?"Y<J)C%*,S-0'$JD9Y,V08?1,*GR
+MMM]5+WL]X(<SJ:*28`S7Q+R[Z%,%P\>>@2""2^Z"1=D/X292Y4OJJ;Z=\`]&
+M!";#`EKW^^I%*$CY*<X6-)\/QBR_BOB9TI08J\V,0D/-EQR^_$TPY\-P5#/1
+M_;1^-2V;"A';D5TOOKR_T%W_FDR7FO@)3FE,F5Q3#A_#[V*W>]`3<)C+70=7
+MC-G)QM><+3K7HNWL6K=L`KM;4VV']M`^/]T&.&I4U&HMXO'L'JO=)#N9.;;Z
+MR-B&HD$/V(\M!'XZ=^YI&PY%PM,)*4$@2'.0"<"M(2YIS;R/`*]>M/YQ\_/T
+MS]5-JI\6>?EQ=H1^F.CGBB35+^TM?.X0_SR_1?WH,"DG<C/JMW]UB1CXY=8/
+MO7ZLFICG%[KK=?_O`-$WTVS=&6/WR\-0>,!L#$6LX5P,N5H,YD>CK'!C7<YT
+KU26XC%==@LMXU26XC%==@LMXU26XC%==@LMZU36`)IE7_P%G#2J)'PT`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu
index b965ffd..963b186 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu
@@ -1,17 +1,17 @@
# $FreeBSD$
begin 644 img-63x255-512-bsd.vhd.gz
-M'XL("(XEAE4``VEM9RTV,W@R-34M-3$R+6)S9"YV:&0N;W5T`*V7.V^#,!#'
-M]WR*D[IU0.9L#%V:J%+W3NU,"$11U8>:#AWX\+T#$\Z\DK0&8AG9]^-_#UN.
-M4NT%8#78"FP)-N%^:L#>09H!T*![L&EC]PIU\?%>%M^'G\A=]:J%Q4I:^>9L
-MCQH,?20%S/DC=L=]J#M,=/.XOSV\[3L<.APZ4)*RE4:PV]%W,G52QZ27`[X.
-MU>FQNMZJ=;"J0%=BAI;JHF@M<8:L:#X_%K9)$Y_N\5Z\`8GSU"5J8"5D3@55
-M.#N%LTM6U^!N5RX7;:E08:34*K`QI,A]*ILN#J.'2N7G^)E_'<N!/IPI%2N2
-M,1PS\^ZB*Q7L)CL%A@4NN0L-Y3C$393*OZ)G?3OC.A0$E70#V+CO1Z]'@=1G
-M8[40\_EDS.K+69^A=99/M/,#]4/DWR=@P4!:K[3<$PL97AK!E\?GJ?P6,^7R
-MQ]51X#E<)UCN!CYN+7"Z34=/$<4+10RZ[-_-!.Z>?IL>9Y;4<<V44P.SSB:!
-MB[G(!G8RSQ"7$&M0F:AJ`3SE%WI]=V,9Z+F[H`_&[N:,2_WYL<#A&7?!QVW=
-MOBPF]RD\$[W-6%T1.!F[X<JX<.4RQ%^Y+0[#;@38["Q4@31KW,X/U$^1?[=`
-M=%M5L+T/NZTJE$+C@,$4$K`,K!#+Q6*[M@JM4QCH(,FX@`=)Q@4\2#(NX$&2
-<<0$/DHP+>)!D7-"#I*6_"$JM?@%SQ_>F?0P`````
+M'XL("!XUQ%4``VEM9RTV,W@R-34M-3$R+6)S9"YV:&0N;W5T`*V6R4[#,!"&
+M[WV*D;AQJ)RQ8X<+2$C<.<$Y35-4(191#CVD[\Z,%V)G*XN;U')DS^=_%EL6
+MPOT`M`2]`]V"+KEO%.@K,!4`#?H7;5OX3^B:M]>V^=P?U_[7K1RL$+%5:L[V
+M*$'1(@:PYD7TEOO0!<SZXN[I<O_R%'#H<>A!I6$KB:`WHW7,%BJWCL4][O'9
+M(D^].CE6UULY!W<[D+MHA@SJ3K:]B9U59$7S^2UA8VQ\PIM\)`.]LX/8E6)@
+M%<F<"JKHG9W"Z26KW^`N5SX7KE2H,`RU`G0!!KE/91/B,'JI5(Z']_KCT`[T
+MX4RIZ"@9PS$U[R[Z4L$PV2M0+'#)7;"4PQ`W42K_BIY.[93O4!!$&0;0NI]&
+MKT=!K$\78B'F\\F8U5>S/D4[H9YHYP>ZVW7Z?`,;!M)^I>U>:K_'?A+!Q[N'
+MJ?PV,^7RQ]W1X#E<$!R?!BGN)L))EXZ>$A4O-`7(UG_$_0AW[?X!IY;4<<VT
+M4P.SSI:9B[FI!G9QGJ%HH9`@JJBJ(^!W?J'7=S66@8F["_I@[&[-.)/.+R(<
+MGG$74MS&G\MA9I+",]&['JMK,B=C.]P9/]RY#$EWKL-AWH,`[<E"%4BSQNW\
+M0'>_3A\'1']493O[,!Q5N10J#\RFD(!M9H78+A;;;ZM08V5=SG219%S&BR3C
+B,EXD&9?Q(LFXC!=)QF6\2#(NZT62@%1[JR_1)]26?0P`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu
index 5865a83..bf1b6b6 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-512-ebr.vhd.gz
-M'XL(")(EAE4``VEM9RTV,W@R-34M-3$R+65B<BYV:&0N;W5T`*V7/6_C,`R&
-M]_P*`K=U,&1:DMTE`0ITO^6:67;L(BCZ@>:&#O[Q)UI20ODK34^Q(\B@^/BE
-M1-&0$.X'H`O0'>@6M*)^*4'?0UD!6*._<6AS_PA]\_[6-G^/7YG_]1L'RP7W
-MBMW)'PN0]B4EH*&7Z`/UH0^8[-?C\]WQ]3G@T./0@U1)7@6"KB?OJ<19'9'V
-M1WP9JRNFZBY>+L"N@Z)C(PJN+LMV'">MEQU/MX9:#?,3[N@A,G!<I$Z)D1>3
-M.3>I+-@YG%[SN@5WM_%KX5+%)D9I6P$ZAQ*I;],FS,/DMJGR=?HPGZ=VI`\7
-M4D6SQ1C;Y'*XZ%,%PV"O0)+`M7!AH)S&N)E4^:_9T[&?]!T["4(%`P[AQ[-W
-M00'7IW.Q,N?+B[&HSZS&]8.`Z_IVX,KNJ!N_.P0812WMTMSO5>_?V.=V1M_.
-M;=LMQQU2A]O=!E0*C)D`_P1]3>+EJ"HR2UM'S4R[;.@?LO@Z`X>$L?78EG.E
-MH<+O*MP_/LVL;V46RL'M`3L<7L,%P;S:Q[@=PQ5NN_%4O7CQO.-]AMNZ?\#)
-M-754$]HYPV*P*G&RF&KDQ]<9\A;R`D3E;1@#S^L+%WWW4QD8A;NB#Z;A&L*5
-M\?B<X?!*N!#CZG-EF5G"*[.WG:IK$B]&/=X9W]RY!(EWKL-AVD)@ALIB,]".
-MFK;+AOYW%E\.B/Y3E.S;AKZ8)E,H/3"90@ML$RLT:;\?VBM,=%`@7,*#`N$2
-B'A0(E_"@0+B$!P7")3PH$"[I04';(Z`0FW]0II$670X`````
+M'XL(""$UQ%4``VEM9RTV,W@R-34M-3$R+65B<BYV:&0N;W5T`*V7P6ZD,`R&
+M[_,4EO;6`PHF"?0R(U7J?2_;G@.%:K3:MFKWT`,/OS8)D!!@.MT,3!24^.-W
+M[!A%"/L#T`7H#G0+6G&_E*!OH:P`:-#=.+2Y>X2^>7UIF[_GS\S]^H.%Y<*W
+M"LW9'@N0])(2T/!+]!/WH1\QV8_[YYOSG^<1APZ'#J1*MBH0=!V]IZM!2*N.
+M28]G_+U45\3J9BO[GJZ#HO-F%+ZZ+#OY.$E6-)]O!;4>UF>\@X=@P,<%ZI18
+M6'DRUQ95S,ZNX?2>U36XFX.+A4T52HR26@$ZAQ*Y3VDSKD-T4ZI\?KR9]X]V
+MH0\W4D5/^O)HK-IV%UVJX!18JT!R:N^Y"P/E=8E;297_6CT=VDG7H440:AS`
+MP?UP]684^/IT+G;6?#L8F_K,KE_?<+BNKP?N[(ZZ<;M#@%'<\B[-W5YU]@T]
+MMROZ3G;;'GW<4VIWN^N`2H$Q$?#7J*])'(ZJXF%)==2LM-L#_5T67A-P2!BJ
+MQU3.E88*OZKP\?YA);Z5V2@'USML<7@)-PKVJWV(.WFXPFXW/U5G*S_O_+Z'
+M.]K_B)-[ZK@FM&L#F\ZJQ,EBJH6='V?(6\@++L9V#$/@%%^8]=W&,C!P=T<?
+MQ.X:QI7A_-S#X05W(<354V59">&%U3O&ZIK$P:B7.^.+.Y<AX<ZU.$Q;",Q0
+M62@#:5;<;@_T/[/PLD!TGZ)DWS9TQ3290NF`R102L$VLT*3]?FAE@Y+HH,"X
+GA`<%QB4\*#`NX4&!<0D/"HQ+>%!@7-*#`@$I]P[_`"()@=A=#@``
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.gz.uu
index 438b398..b496241 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.gz.uu
@@ -1,22 +1,23 @@
# $FreeBSD$
begin 644 img-63x255-512-gpt.vhd.gz
-M'XL(")8EAE4``VEM9RTV,W@R-34M-3$R+6=P="YV:&0N;W5T`*U82V^<,!"^
-M[Z^8JK=4I6#L@3U5K91*O:55JUYR"+`F6K7=/I)##OSX>L`&##;I)@.6EY69
-MCV^>'CE-APL`<\`64`,J>BXDX!Z*$L`LVB'Z.;-_H6M^G71S?WQ([-7M!K`L
-MG4OYXB0O<I#F(P6(BCZ"!WJ&SL$D+R]O+XX_;QV<L'#"`JF"I'(!6*^^@^G(
-MCI"^'<7W'O)F8I>OV4U2PT_;0M[.WL@=NYM^?CM75AHI\SX-A`8AE=/P_G@+
-MD[(+VZET(36C&3+J3-D0'&Y)G0-WL;.^&$+%!$9A9F.Z#`I!SR9LG!U6PX3*
-MP]WOZN^=7O`3D5#!D5^V6LOCZ@H;*L*];!E("N<M=:%'N5_"!4+E6=9#7\YY
-MUQ@A56Y!].K[UIN@8,X/LW3#YG%G1/E5Q$^:/*L"<WRA>Y_X]PA8U^<!.@OZ
-M<*/"=4/VZ^N`UI-&0Y!,ALTW')+.[%<?F/U;M^<!*@55M0+\ZO@UO3L42`2Y
-MI\`PQ4%FH`2H*9Q[W54SYW?YX2-<O?O\A<"N)W4;"A=]H`PR];,]+-BM,VU4
-M]QA*MD8,T2?:H+)Y%.Y-,'<;2C9#*@X7&G$XN24U[B7_X=L!3J6^5#F7*A64
-M9CMJX%!%X7YX<-QU6=-RC5`TM(6K#)I^+S\@9)GA9]*D[$$$".-WL[&;7;@F
-MP.[T*3D-8*^3/Z\L/YW9B`B-^$+,>EIL1021>D1=\.&XZ[(NR7J*S7I[&RRA
-M$5^(6J\:K!<V$I$*I>ZXJR7)"Q^NYK5>UK>/)C],_5[/\87N*O'O`5#8;8AM
-M7Q.VD+(QE!:0C:&T^<O(,).;SCS7RVB=PE1A"(ZQPA`<8X4A.-8*0X",%8;@
-M&"L,P3%6&()CK3#(VPBA;832HG=`#K7V:41;FLXYPK4<#DYLM4\;C5#8&9R-
-M$#[6"+4ZJJR[%LHR-D+(W0BA+:1,9QGH&J$UAZ><9:!KA-+)@,\XR\!P(_34
-<LPR"8SS+(#C&LPR"8PX5ZEMV_P`=.$-$`!,`````
+M'XL(""4UQ%4``VEM9RTV,W@R-34M-3$R+6=P="YV:&0N;W5T`*V82X_3,!#'
+M[_LI!B%Q6$3D.+:37(I`6B1N"P+MA4OL)*L**(]R6(GL=\?C.`\G<:!B6BMJ
+MY<XO_WEX[(:Q_@6@,E`MJ`:4Q,^Y`%5"7@#823^XNZ;^*W3FVZDQOXX/B7]U
+M5STL97.KT!SM>0;"WB0'7N%-5(V?H1LPR=.;^^OCU_L!QSV.>Y#,T2KCH/3J
+M/GD-17\?A[L[\L\.^3BIR];J)JO>P;:%K)W](AO4/;KKR[FSPEK9W^.04.3`
+MQ#2"+\'$Y.PB=I(MK&8RMX+*)F>W<&K/ZA+<]97/15\JMC!R>V6@4L@Y?K9E
+M,\1A-6RI/)R_5S_/S4(?CY2*FB5C.;<3/>Y+A0\_]@H$"MQS%QSEO,1ME,I_
+M14^%=D-V;1"8'";XX+X=]OXL6!E.*!OTJ93MQ#R>C*B^"O4)NQ*JC6M\HGN=
+MA.\1J/5EP"&"(6Y,B#88/[=2FV;RJ"\2;VQ2R)IX0@ZS_.J:.+^ZO0PH)535
+M"OAQT&=<.B0(!:+$PK#-0:0@.4@QXISOTLSUW;QY"[>OWG]`V*?)78/E8MNF
+MK36E(-<+=>N5YG$\:7]O+#:#B\TF9!'M`9=%HW?87+L&%YMN=G!;(XX3>U;C
+M7O(/N>UQDH56Q=RJD+A_*`-U%<5]"7#4?;G!:6VS:G`+ERD8MY?7"M+4ZK/+
+MI'`0#KP&9C=VNPMK!':G=\FIA[U(?CSW^IK45\36B$_$HM?PO8I`47]Q%T(<
+M=5]N"HR>)(M>Z8ME:\0GHM&K^NAM!PE%;2W=<5=+DB<A3M-&+W7'1[L^;/]>
+M7^,3W6T2OGL@]]L0V;[&?2,E4R@\D$RA\.N74&$J=I-Y:9:55TCFLO)E0Z8P
+MKPO*'H@XPAZ(.,(>B#C2'HA`PAZ(.,(>B#C"'H@XTAZ8UZ4K9J*C&N*P]KB"
+M4N._W<*$,J*'KNY9<M<+.\S=+?N_T+$#WLY1;3,9)2,\JB%N]ZBFVYBS(V?A
+M+.%1#7&D1[7"]SVBIRV((WS:@CC"IRV((WS:@CC"IRV((WS:@CCJ4K%'EZL_
+(<L>MI:(3````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu
index 16d286a..27e7455 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu
@@ -1,18 +1,19 @@
# $FreeBSD$
begin 644 img-63x255-512-mbr.vhd.gz
-M'XL(")LEAE4``VEM9RTV,W@R-34M-3$R+6UB<BYV:&0N;W5T`*V736_C(!"&
-M[_D5(_66@X7'@.DED2KUOI?=GL&UJZC:;=7LH0?_^&4,.."O-%MB!V'!/'X'
-M9L:",?<#D!7(#F0+4E"_YB#OH58`=M#?.+2E?X2^>?O3-G]/GX7_]3L'*UEL
-ME9J3/5;`[4MJ0$TOD<_4ASY@BKO'E_WI]TO`H<>A!XF:K"H$:6;O46Q41Z2G
-M$[Y.U55S=1<KYV#70=5%,ZI875$<8QRW5G8^W1*,&-8GW,E#,A#C$G6"3:PB
-MF4N+&CF[A)-;5K?@]CN_%RY4;&#4MF4@2ZB1^C9LPCK,;ALJG^=W_7%N)_IP
-M)51DM!G3,;[N+OI0P3#9*^`D<,M=&"CG*6XA5+ZU>C*UX[YC%X&),("#^^GJ
-M75`0ZY,EVUCS]<U8U:=)'[=YIA?:]8'^H4BO$6C,;4#%7':DN-%AT_CL8*`%
-MM92EI<]5OWZ-?6X7-N3HTO80K9]YSKR_IKL-*`1H/0/^#/J:31FWZU,J\_ZJ
-M(6!L/;;E7$A0^%6%3X^_%O)7Z95R\'_53VF\A@N"XVJ?XHX1KG+I=J%$Q2F)
-MN[@?X0[N'W!\2QW5A'9I8-59D3E8M)K8Q?L,90ME!4SY,4R!X_["1=_]7`8F
-M[F[H@[F[FG!U.K^,<'C%74AQ9JPL"UMX9?4.<W5-YLTPT\SX8N82),U<A\.\
-MA4`/E<5&H)TU;]<'^A]%>CD@^D]1MF\;^F*:32'WP&P*+;#-K%#G_7Y(KS#3
-K08%P&0\*A,MX4"!<QH,"X3(>%`B7\:!`N*P'!6F/@(SM_@$'<*)G70X`````
+M'XL(""DUQ%4``VEM9RTV,W@R-34M-3$R+6UB<BYV:&0N;W5T`*V7/6^D,!"&
+M^_T5(UV7`IG!-DZS*T5*?\TEM4T@6ITNB9(K4O#CSX,-V!C8;,X+:X',/+R>
+M+V3&W`]`5B`[D"U(0=<U!WD+M0*PD_[$82S]+?3-ZTO;_#U_%O[7'QRL9*%5
+M;$[V6`&W+ZD!-;U$/M$U]".F^''_?'/^\SSBT./0@T1-5A6"-,E[.@.,.W5$
+M>CSC[Z6Z*E4W6[GW=!U47?!$%:HKBE.(X];*/D^G`",'_XQG=!--A+A(G6`+
+MJT#FFE/9O-@UG-RSN@9W<_"Q<*EB$Z.V(P-90HUT;=-F]$-RVE3Y_'C3[Q_M
+M0A]NI(J<])7)G-I>+OI4P2FP3@&GU-Y;+@R4UR5N)57^RWLRMN/^PCJ!B7$"
+MA^7'WIM1$.J3)=OQ^78P-O5ITL=MG>F5<7NBOROB8P(:<QU0,5<=,6Y:L&E\
+M=3#0@D:JTM+7JO=?8^_;E8"<7-D>`_^9I\SQ-=UU0"%`ZP3X:]37[,JX7I]2
+MF>.KAH2Q_=BV<R%!X5<5/MX_K-2OTAOMX'O=3VF\A!L%A]T^QIT"7.7*;:8$
+MS2G*N_`ZP!W=?\3Q/774$]JUB<W%BLS)HM7"+HPSE"V4%35C-G6M`#C%%V9]
+MMZD,C):[HP_2Y6K"U?'S98##"\N%&&>FSK(2P@O>.Z;JFLS!,,O*^&+E$B2N
+M7(?#O(U`#YW%9J!]*AVW)_J?17PX(/I/4;9O&_IFFDTA]\!L"BVPS:Q0Y_U^
+M2.&"DFFC0+B,&P7"9=PH$"[C1H%P&3<*A,NX42!<UHV"!=K<._P#==^RJ5T.
+"````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu
index 8d76c35..eada46f 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-512-pc98.vhd.gz
-M'XL("*$EAE4``VEM9RTV,W@R-34M-3$R+7!C.3@N=FAD+F]U=`"METV/FS`0
-MAN_Y%2/UM@=DQA\XEXU4:>^]M'LV%%91U7:UZ6$/_/AZL!UL#&33.A!D9,_#
-M.Q^V9<;<#T!Q4`.H'I2D=B-`':'1`+;3WS@]:_\*8_?[5]_].;]7_C<>'*QF
-ML55J3O;(0=B/-("&/J*^4QO&@*D^/;T\G'^^!!QZ''J0;,B*(Z@V^XYF5W5$
-M>C[CCZ4ZGJN;K9R#PP!\B$;P6%U5G6*<L%9V/-T*6CG%)]S)2](1XQ)UDBVL
-M(IEK08V<7<.I/:M[<`\'GPM7*K8P&OMDH&IHD-JV;$(<LMN6ROOEU;Q=^H4^
-MW"@5%25CV2>VW45?*A@&>P6"!.ZY"Q/ELL2ME,I_14^E=L(W;!"8#!TXN9]&
-M;T9!K$_5;"?FV\G8U&=(G[#SS*P\MSO&SU5Z78'M<!]02C`Y\&MPN"-]1P&=
-M6(N[G[)9Q<P.G]+\=AO5]\_Y[0O'#\VND/L5:EU8H9X4VA79+NA2@<:/*GQ^
-M^K8R@[4IEA*'PUNX(#A>[U/<*<)Q-^%F2E1LT-7`>_\2MR/<H_L'G-A31ZM"
-MO]:QZ:PL7"Q&+^SB/$/=0\V!:=^'*?":7YCU'7,9F+B[HP]R=PWAFG1\'>'P
-MAKN0XEJ_\X:120IO1.\Q5]<53D:[G!D?G+D$26>NPV'9A<!,*XNM0%K%L^=V
-MQ_BE2B\'1+\9%=O=T.\>Q10*#RRF4/C]HZ!"T^T6V[U5J+S"0D<%PA4\*A"N
-CX%&!<`6/"H0K>%0@7,&C`N&*'A64/00R=O@+OHS"'5\.````
+M'XL(""TUQ%4``VEM9RTV,W@R-34M-3$R+7!C.3@N=FAD+F]U=`"ME\]OI"`4
+MQ^_S5[QD;ST8>`(ZET[2I/>][/:,5IM)TW:S[:$'__CE"2B(.ITNHV,P\#Y^
+MWP\@,&9_`*H$U8/J0$EJ5P+4$:H:P'2Z&\<G=Z\PM&^O7?MQ_BS<;SA8&&>A
+M56Q.]EB",!^I`#5]1#U2&P:/*7[</]V<7YX\#AT.'4A69%4BJ";Y3M\`$U8=
+MD1[.^+Q45Z;J9BO[G;Z'L@]&E*&ZHCB%.&&LS'BZ)31JC(^_HY>H(\1%ZB1;
+M6`4RUX+*9F?7<&K/ZAK<S<'EPI:**8S*/!DH#A52VY2-CT-RFU+Y?/^C_[YW
+M"WVX42IJTL>3OGK;772E@E-BK0)!I;WG+HR4MR5NI53^*WHJMA.N88+`I._`
+MT?TX>C,*0GV*LYV8;R=C4Y\F?<+,,[WRW.X8[HKXFH!-?QU02M`I\)=WN"5]
+M1P&M6(N[F[))Q<P.G^+\MAO5]^W\=IGCAWI7R/4*ZSJSPGI4:%9DLZ!+!35^
+M5>'#_>^5&5SK;"FQ.+R$\X+#]3[&G0)<:2?<3`F*#5H.9>=>PG:`N[5_CQ-[
+MZFA5Z-8Z-IV5F8M%UPN[,,_`.^`E+<=L6K<"X)1?F/4=4QD8N;NC#U)W->&J
+M>#P/<'C!78AQC=MY_<@HA1>B=YNJ:S,GHUG.C"_.7(+$,]?B,.]"H,>5Q50@
+MK>+)<[MC^%G$EP6BVXRR[6[H=H]L"H4#9E,HW/Z14:%N=XOMVBI4TB8ETU&!
+H<!F/"H3+>%0@7,:C`N$R'A4(E_&H0+BL1P4#-+5W^`=:):>?7PX`````
`
end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu
index a38fd79..0355276 100644
--- a/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu
+++ b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu
@@ -1,18 +1,18 @@
# $FreeBSD$
begin 644 img-63x255-512-vtoc8.vhd.gz
-M'XL("*4EAE4``VEM9RTV,W@R-34M-3$R+79T;V,X+G9H9"YO=70`K99-;]LP
-M#(;O^14$=NO!D"E9MD\%]M';@`$[[#K9EHM@V%JT/?20'S_2EA/)7VM6)H)C
-M0^+CEQ3%4*GQ`V`UV!ZL!UOP?6G`UE!6`#09!@[7/#S"J7WXX]N7XVL6/J?#
-M",M5;)6:LSUJ,/22$M#Q2VS']W":,-F'+_<WQ]_W$PX##@.H*-E*(]AF]IX<
-M*G56QZ0?1_PU5Z?GZF(K_M'0]Z#[:(6.U679;8PS9$7K>5AH\B$^TT@>DHD8
-MEZ@KU,PJ4KH6U,C9-9S=L[H&=W,(>S&F"B5&25<%-H<2^9[29HK#8E"JO#X_
-MNJ=G/].'&ZEBS_KRQ5R[[2Z&5,%I<5!@EJF2N@L#99XJN$B5=T;/IG8F#5+\
-M,*Z@Z*ABVUU[B1Y.0:-!JE6YMQG9X*]:X%#M6.WA-MQU[*ZQG"!<5`HP"`6=
-M?<.'%S3==:OQNWOR_N/WSZB_)OK<1K+\]W:X*K'[QV&K0-5<A#:WP]47J_K]
-M9]<Y*7='7/-6'-4,U4'GP?L9[F>$:X4WHUFXZX?\5T/YO=K=9G)77Q:/YXHJ
-M^P8NJLNW<UR;'+5X(%SL5]3!JKKNC&M:,#JUVG7VTQK.BZ9*T[\5USEH*$]R
-MZ'>J<KLKXMI4P5!7Q`H52BO47>5YFO[*E5NY;D^<OF7I=P2:H%#,90+**K0!
-M**;04A,IJK#L:A3=Y2HH%.J;&2?8-S-.L&]FG&#?S#C!OIEQ@GTSXT3[9@)2
-,[AW^`BT2KB!L#0``
+M'XL("#$UQ%4``VEM9RTV,W@R-34M-3$R+79T;V,X+G9H9"YO=70`K99+;^0@
+M#,?O\RDL[:V'$3&$)*=*?>QMI97VL->2A%2CJ@^U/<QA/OS:@320UW9:,B@"
+M@7_YVQ@/0K@'0$O0'6@+.N=^H4!74)0`-.D;]N_,#^'4/#_9YOUPW/OGM'.P
+M3(16L3G;HP1%'RD`#7]$M]R'TX#9_[B]OS@\W@\X]#CTH+Q@*XF@Z\EW,A9<
+M:J>.27\/^-`CCZ,Z.5476O%80M>![((5<E#G7+T,G55D1>NYY5#G?7R&%@VB
+MB='92>QR,;$*E"X%58S.+N'TEM4YN(N=WPN7*A2Q@MX"-$4/N4]I,\1AUBA5
+MCF\OYO7-3O3A2JJ,FY'-YIIU=]&G"@Z+O0(U3Y787>@I#U/<+%6^&3T=VZDX
+M2.'`K:#HB'S=73U&#X>@42/5HMC:C'WOKYCA4&Q8;>%6W#7LKM*<(%Q4<E`(
+M.9U]Q8<7)/7:Q?C]?+7VZL\-RE^1/K.2+%_>#E-&=O\Y;"6(BHO0ZG:8:K2J
+MOG]VC4GEKL/5G\51S1`MM!:LG>#N`ER3>#/JF;NVSW_1E]^SW:T'=^6XV)TK
+MJNPKN*`N7TYQ3734PH8PVB^H@T5U[0>N;D#)V&K3V>LEG$V:*G7W65QKH*8\
+MR:#;J,K-IHAS4P5]74E6J#"U0MF6EJ?IKUR8A??ZQ.GW/OXYH/(*D[E,P+0*
+MM0<F4ZCI$IE48=%6F'27RZ+L\S#1O9EQ">_-C$MX;V9<PGLSXQ+>FQF7\-[,
+2N*3W9@+2^=W]`WD,N"QL#0``
`
end
diff --git a/usr.bin/mkimg/vhd.c b/usr.bin/mkimg/vhd.c
index 054f82f..c4c1d1d 100644
--- a/usr.bin/mkimg/vhd.c
+++ b/usr.bin/mkimg/vhd.c
@@ -159,6 +159,34 @@ vhd_geometry(uint64_t image_size, struct vhd_geom *geom)
geom->cylinders = cth / geom->heads;
}
+static uint64_t
+vhd_resize(uint64_t origsz)
+{
+ struct vhd_geom geom;
+ uint64_t newsz;
+
+ /*
+ * Round the image size to the pre-determined geometry that
+ * matches the image size. This circular dependency implies
+ * that we need to loop to handle boundary conditions.
+ * The first time, newsz equals origsz and the geometry will
+ * typically yield a new size that's smaller. We keep adding
+ * cylinder's worth of sectors to the new size until its
+ * larger or equal or origsz. But during those iterations,
+ * the geometry can change, so we need to account for that.
+ */
+ newsz = origsz;
+ while (1) {
+ vhd_geometry(newsz, &geom);
+ newsz = (int64_t)geom.cylinders * geom.heads *
+ geom.sectors * VHD_SECTOR_SIZE;
+ if (newsz >= origsz)
+ break;
+ newsz += geom.heads * geom.sectors * VHD_SECTOR_SIZE;
+ }
+ return (newsz);
+}
+
static uint32_t
vhd_timestamp(void)
{
@@ -256,8 +284,7 @@ vhd_dyn_resize(lba_t imgsz)
{
uint64_t imagesz;
- imagesz = imgsz * secsz;
- imagesz = (imagesz + VHD_BLOCK_SIZE - 1) & ~(VHD_BLOCK_SIZE - 1);
+ imagesz = vhd_resize(imgsz * secsz);
return (image_set_size(imagesz / secsz));
}
@@ -266,7 +293,7 @@ vhd_dyn_write(int fd)
{
struct vhd_footer footer;
struct vhd_dyn_header header;
- uint64_t imgsz;
+ uint64_t imgsz, rawsz;
lba_t blk, blkcnt, nblks;
uint32_t *bat;
void *bitmap;
@@ -274,13 +301,14 @@ vhd_dyn_write(int fd)
uint32_t sector;
int bat_entries, error, entry;
- imgsz = image_get_size() * secsz;
- bat_entries = imgsz / VHD_BLOCK_SIZE;
+ rawsz = image_get_size() * secsz;
+ imgsz = (rawsz + VHD_BLOCK_SIZE - 1) & ~(VHD_BLOCK_SIZE - 1);
- vhd_make_footer(&footer, imgsz, VHD_DISK_TYPE_DYNAMIC, sizeof(footer));
+ vhd_make_footer(&footer, rawsz, VHD_DISK_TYPE_DYNAMIC, sizeof(footer));
if (sparse_write(fd, &footer, sizeof(footer)) < 0)
return (errno);
+ bat_entries = imgsz / VHD_BLOCK_SIZE;
memset(&header, 0, sizeof(header));
be64enc(&header.cookie, VHD_HEADER_COOKIE);
be64enc(&header.data_offset, ~0ULL);
@@ -321,7 +349,7 @@ vhd_dyn_write(int fd)
blk = 0;
blkcnt = VHD_BLOCK_SIZE / secsz;
error = 0;
- nblks = image_get_size();
+ nblks = rawsz / secsz;
while (blk < nblks) {
if (!image_data(blk, blkcnt)) {
blk += blkcnt;
@@ -331,15 +359,20 @@ vhd_dyn_write(int fd)
error = errno;
break;
}
+ /* Handle partial last block */
+ if (blk + blkcnt > nblks)
+ blkcnt = nblks - blk;
error = image_copyout_region(fd, blk, blkcnt);
if (error)
break;
blk += blkcnt;
}
free(bitmap);
- if (blk != nblks)
+ if (error)
+ return (error);
+ error = image_copyout_zeroes(fd, imgsz - rawsz);
+ if (error)
return (error);
-
if (sparse_write(fd, &footer, sizeof(footer)) < 0)
return (errno);
@@ -362,24 +395,9 @@ FORMAT_DEFINE(vhd_dyn_format);
static int
vhd_fix_resize(lba_t imgsz)
{
- struct vhd_geom geom;
- int64_t imagesz;
+ uint64_t imagesz;
- /*
- * Round the image size to the pre-determined geometry that
- * matches the image size. This circular dependency implies
- * that we need to loop to handle boundary conditions.
- */
- imgsz *= secsz;
- imagesz = imgsz;
- while (1) {
- vhd_geometry(imagesz, &geom);
- imagesz = (int64_t)geom.cylinders * geom.heads *
- geom.sectors * VHD_SECTOR_SIZE;
- if (imagesz >= imgsz)
- break;
- imagesz += geom.heads * geom.sectors * VHD_SECTOR_SIZE;
- }
+ imagesz = vhd_resize(imgsz * secsz);
/*
* Azure demands that images are a whole number of megabytes.
*/
@@ -391,24 +409,24 @@ static int
vhd_fix_write(int fd)
{
struct vhd_footer footer;
- uint64_t imgsz;
+ uint64_t imagesz;
int error;
error = image_copyout(fd);
- if (!error) {
- imgsz = image_get_size() * secsz;
- vhd_make_footer(&footer, imgsz, VHD_DISK_TYPE_FIXED, ~0ULL);
- if (sparse_write(fd, &footer, sizeof(footer)) < 0)
- error = errno;
- }
+ if (error)
+ return (error);
+
+ imagesz = image_get_size() * secsz;
+ vhd_make_footer(&footer, imagesz, VHD_DISK_TYPE_FIXED, ~0ULL);
+ error = (sparse_write(fd, &footer, sizeof(footer)) < 0) ? errno : 0;
return (error);
}
static struct mkimg_format vhd_fix_format = {
- .name = "vhdf",
- .description = "Fixed Virtual Hard Disk",
- .resize = vhd_fix_resize,
- .write = vhd_fix_write,
+ .name = "vhdf",
+ .description = "Fixed Virtual Hard Disk",
+ .resize = vhd_fix_resize,
+ .write = vhd_fix_write,
};
FORMAT_DEFINE(vhd_fix_format);
diff --git a/usr.bin/patch/common.h b/usr.bin/patch/common.h
index 8963c83..f33abcf 100644
--- a/usr.bin/patch/common.h
+++ b/usr.bin/patch/common.h
@@ -43,12 +43,10 @@
#define LINENUM_MAX LONG_MAX
#define SCCSPREFIX "s."
-#define GET "get -e %s"
-#define SCCSDIFF "get -p %s | diff - %s >/dev/null"
#define RCSSUFFIX ",v"
-#define CHECKOUT "co -l %s"
-#define RCSDIFF "rcsdiff %s > /dev/null"
+#define CHECKOUT "/usr/bin/co"
+#define RCSDIFF "/usr/bin/rcsdiff"
#define ORIGEXT ".orig"
#define REJEXT ".rej"
diff --git a/usr.bin/patch/inp.c b/usr.bin/patch/inp.c
index 826f85b..e7fa351 100644
--- a/usr.bin/patch/inp.c
+++ b/usr.bin/patch/inp.c
@@ -31,8 +31,10 @@
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/mman.h>
+#include <sys/wait.h>
#include <ctype.h>
+#include <errno.h>
#include <libgen.h>
#include <stddef.h>
#include <stdint.h>
@@ -133,12 +135,14 @@ reallocate_lines(size_t *lines_allocated)
static bool
plan_a(const char *filename)
{
- int ifd, statfailed;
+ int ifd, statfailed, devnull, pstat;
char *p, *s, lbuf[INITLINELEN];
struct stat filestat;
ptrdiff_t sz;
size_t i;
size_t iline, lines_allocated;
+ pid_t pid;
+ char *argp[4] = {NULL};
#ifdef DEBUGGING
if (debug & 8)
@@ -166,13 +170,14 @@ plan_a(const char *filename)
}
if (statfailed && check_only)
fatal("%s not found, -C mode, can't probe further\n", filename);
- /* For nonexistent or read-only files, look for RCS or SCCS versions. */
+ /* For nonexistent or read-only files, look for RCS versions. */
+
if (statfailed ||
/* No one can write to it. */
(filestat.st_mode & 0222) == 0 ||
/* I can't write to it. */
((filestat.st_mode & 0022) == 0 && filestat.st_uid != getuid())) {
- const char *cs = NULL, *filebase, *filedir;
+ char *filebase, *filedir;
struct stat cstat;
char *tmp_filename1, *tmp_filename2;
@@ -180,43 +185,26 @@ plan_a(const char *filename)
tmp_filename2 = strdup(filename);
if (tmp_filename1 == NULL || tmp_filename2 == NULL)
fatal("strdupping filename");
+
filebase = basename(tmp_filename1);
filedir = dirname(tmp_filename2);
- /* Leave room in lbuf for the diff command. */
- s = lbuf + 20;
-
#define try(f, a1, a2, a3) \
- (snprintf(s, buf_size - 20, f, a1, a2, a3), stat(s, &cstat) == 0)
-
- if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
- try("%s/RCS/%s%s", filedir, filebase, "") ||
- try("%s/%s%s", filedir, filebase, RCSSUFFIX)) {
- snprintf(buf, buf_size, CHECKOUT, filename);
- snprintf(lbuf, sizeof lbuf, RCSDIFF, filename);
- cs = "RCS";
- } else if (try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) ||
- try("%s/%s%s", filedir, SCCSPREFIX, filebase)) {
- snprintf(buf, buf_size, GET, s);
- snprintf(lbuf, sizeof lbuf, SCCSDIFF, s, filename);
- cs = "SCCS";
- } else if (statfailed)
- fatal("can't find %s\n", filename);
-
- free(tmp_filename1);
- free(tmp_filename2);
+ (snprintf(lbuf, sizeof(lbuf), f, a1, a2, a3), stat(lbuf, &cstat) == 0)
/*
* else we can't write to it but it's not under a version
* control system, so just proceed.
*/
- if (cs) {
+ if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
+ try("%s/RCS/%s%s", filedir, filebase, "") ||
+ try("%s/%s%s", filedir, filebase, RCSSUFFIX)) {
if (!statfailed) {
if ((filestat.st_mode & 0222) != 0)
/* The owner can write to it. */
fatal("file %s seems to be locked "
- "by somebody else under %s\n",
- filename, cs);
+ "by somebody else under RCS\n",
+ filename);
/*
* It might be checked out unlocked. See if
* it's safe to check out the default version
@@ -224,21 +212,59 @@ plan_a(const char *filename)
*/
if (verbose)
say("Comparing file %s to default "
- "%s version...\n",
- filename, cs);
- if (system(lbuf))
+ "RCS version...\n", filename);
+
+ switch (pid = fork()) {
+ case -1:
+ fatal("can't fork: %s\n",
+ strerror(errno));
+ case 0:
+ devnull = open("/dev/null", O_RDONLY);
+ if (devnull == -1) {
+ fatal("can't open /dev/null: %s",
+ strerror(errno));
+ }
+ (void)dup2(devnull, STDOUT_FILENO);
+ argp[0] = strdup(RCSDIFF);
+ argp[1] = strdup(filename);
+ execv(RCSDIFF, argp);
+ exit(127);
+ }
+ pid = waitpid(pid, &pstat, 0);
+ if (pid == -1 || WEXITSTATUS(pstat) != 0) {
fatal("can't check out file %s: "
- "differs from default %s version\n",
- filename, cs);
+ "differs from default RCS version\n",
+ filename);
+ }
}
+
if (verbose)
- say("Checking out file %s from %s...\n",
- filename, cs);
- if (system(buf) || stat(filename, &filestat))
- fatal("can't check out file %s from %s\n",
- filename, cs);
+ say("Checking out file %s from RCS...\n",
+ filename);
+
+ switch (pid = fork()) {
+ case -1:
+ fatal("can't fork: %s\n", strerror(errno));
+ case 0:
+ argp[0] = strdup(CHECKOUT);
+ argp[1] = strdup("-l");
+ argp[2] = strdup(filename);
+ execv(CHECKOUT, argp);
+ exit(127);
+ }
+ pid = waitpid(pid, &pstat, 0);
+ if (pid == -1 || WEXITSTATUS(pstat) != 0 ||
+ stat(filename, &filestat)) {
+ fatal("can't check out file %s from RCS\n",
+ filename);
+ }
+ } else if (statfailed) {
+ fatal("can't find %s\n", filename);
}
+ free(tmp_filename1);
+ free(tmp_filename2);
}
+
filemode = filestat.st_mode;
if (!S_ISREG(filemode))
fatal("%s is not a normal file--can't patch\n", filename);
diff --git a/usr.bin/patch/pathnames.h b/usr.bin/patch/pathnames.h
index d31300e..79d8fae 100644
--- a/usr.bin/patch/pathnames.h
+++ b/usr.bin/patch/pathnames.h
@@ -9,4 +9,4 @@
#include <paths.h>
-#define _PATH_ED "/bin/ed"
+#define _PATH_RED "/bin/red"
diff --git a/usr.bin/patch/pch.c b/usr.bin/patch/pch.c
index e731ca1..5fadf62 100644
--- a/usr.bin/patch/pch.c
+++ b/usr.bin/patch/pch.c
@@ -1,4 +1,3 @@
-
/*-
* Copyright 1986, Larry Wall
*
@@ -1410,13 +1409,14 @@ do_ed_script(void)
char *t;
off_t beginning_of_this_line;
FILE *pipefp = NULL;
+ int continuation;
if (!skip_rest_of_patch) {
if (copy_file(filearg[0], TMPOUTNAME) < 0) {
unlink(TMPOUTNAME);
fatal("can't create temp file %s", TMPOUTNAME);
}
- snprintf(buf, buf_size, "%s%s%s", _PATH_ED,
+ snprintf(buf, buf_size, "%s%s%s", _PATH_RED,
verbose ? " " : " -s ", TMPOUTNAME);
pipefp = popen(buf, "w");
}
@@ -1434,7 +1434,19 @@ do_ed_script(void)
(*t == 'a' || *t == 'c' || *t == 'd' || *t == 'i' || *t == 's')) {
if (pipefp != NULL)
fputs(buf, pipefp);
- if (*t != 'd') {
+ if (*t == 's') {
+ for (;;) {
+ continuation = 0;
+ t = strchr(buf, '\0') - 1;
+ while (--t >= buf && *t == '\\')
+ continuation = !continuation;
+ if (!continuation ||
+ pgets(true) == 0)
+ break;
+ if (pipefp != NULL)
+ fputs(buf, pipefp);
+ }
+ } else if (*t != 'd') {
while (pgets(true)) {
p_input_line++;
if (pipefp != NULL)
diff --git a/usr.bin/truss/syscall.h b/usr.bin/truss/syscall.h
index a573611..a2fa826 100644
--- a/usr.bin/truss/syscall.h
+++ b/usr.bin/truss/syscall.h
@@ -41,7 +41,7 @@ enum Argtype { None = 1, Hex, Octal, Int, LongHex, Name, Ptr, Stat, Ioctl, Quad,
Sigset, Sigprocmask, Kevent, Sockdomain, Socktype, Open,
Fcntlflag, Rusage, BinString, Shutdown, Resource, Rlimit, Timeval2,
Pathconf, Rforkflags, ExitStatus, Waitoptions, Idtype, Procctl,
- LinuxSockArgs, Umtxop };
+ LinuxSockArgs, Umtxop, Atfd, Atflags, Timespec2, Accessmode };
#define ARG_MASK 0xff
#define OUT 0x100
diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c
index efd27e9..7ecb38b 100644
--- a/usr.bin/truss/syscalls.c
+++ b/usr.bin/truss/syscalls.c
@@ -93,7 +93,7 @@ static const char rcsid[] =
*/
static struct syscall syscalls[] = {
{ .name = "fcntl", .ret_type = 1, .nargs = 3,
- .args = { { Int, 0 } , { Fcntl, 1 }, { Fcntlflag | OUT, 2 } } },
+ .args = { { Int, 0 }, { Fcntl, 1 }, { Fcntlflag, 2 } } },
{ .name = "fork", .ret_type = 1, .nargs = 0 },
{ .name = "vfork", .ret_type = 1, .nargs = 0 },
{ .name = "rfork", .ret_type = 1, .nargs = 1,
@@ -101,9 +101,9 @@ static struct syscall syscalls[] = {
{ .name = "getegid", .ret_type = 1, .nargs = 0 },
{ .name = "geteuid", .ret_type = 1, .nargs = 0 },
{ .name = "linux_readlink", .ret_type = 1, .nargs = 3,
- .args = { { Name, 0 } , { Name | OUT, 1 }, { Int, 2 }}},
+ .args = { { Name, 0 }, { Name | OUT, 1 }, { Int, 2 } } },
{ .name = "linux_socketcall", .ret_type = 1, .nargs = 2,
- .args = { { Int, 0 } , { LinuxSockArgs, 1 }}},
+ .args = { { Int, 0 }, { LinuxSockArgs, 1 } } },
{ .name = "getgid", .ret_type = 1, .nargs = 0 },
{ .name = "getpid", .ret_type = 1, .nargs = 0 },
{ .name = "getpgid", .ret_type = 1, .nargs = 1,
@@ -114,47 +114,84 @@ static struct syscall syscalls[] = {
.args = { { Int, 0 } } },
{ .name = "getuid", .ret_type = 1, .nargs = 0 },
{ .name = "readlink", .ret_type = 1, .nargs = 3,
- .args = { { Name, 0 } , { Readlinkres | OUT, 1 }, { Int, 2 } } },
+ .args = { { Name, 0 }, { Readlinkres | OUT, 1 }, { Int, 2 } } },
+ { .name = "readlinkat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Readlinkres | OUT, 2 },
+ { Int, 3 } } },
{ .name = "lseek", .ret_type = 2, .nargs = 3,
- .args = { { Int, 0 }, { Quad, 1 + QUAD_ALIGN }, { Whence, 1 + QUAD_SLOTS + QUAD_ALIGN } } },
+ .args = { { Int, 0 }, { Quad, 1 + QUAD_ALIGN },
+ { Whence, 1 + QUAD_SLOTS + QUAD_ALIGN } } },
{ .name = "linux_lseek", .ret_type = 2, .nargs = 3,
.args = { { Int, 0 }, { Int, 1 }, { Whence, 2 } } },
{ .name = "mmap", .ret_type = 2, .nargs = 6,
- .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 }, { Int, 4 }, { Quad, 5 + QUAD_ALIGN } } },
+ .args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 },
+ { Int, 4 }, { Quad, 5 + QUAD_ALIGN } } },
{ .name = "linux_mkdir", .ret_type = 1, .nargs = 2,
- .args = { { Name | IN, 0} , {Int, 1}}},
+ .args = { { Name | IN, 0 }, { Int, 1 } } },
{ .name = "mprotect", .ret_type = 1, .nargs = 3,
.args = { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 } } },
{ .name = "open", .ret_type = 1, .nargs = 3,
- .args = { { Name | IN, 0 } , { Open, 1 }, { Octal, 2 } } },
+ .args = { { Name | IN, 0 }, { Open, 1 }, { Octal, 2 } } },
+ { .name = "openat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { Open, 2 },
+ { Octal, 3 } } },
{ .name = "mkdir", .ret_type = 1, .nargs = 2,
- .args = { { Name, 0 } , { Octal, 1 } } },
+ .args = { { Name, 0 }, { Octal, 1 } } },
+ { .name = "mkdirat", .ret_type = 1, .nargs = 3,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
{ .name = "linux_open", .ret_type = 1, .nargs = 3,
.args = { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } },
{ .name = "close", .ret_type = 1, .nargs = 1,
.args = { { Int, 0 } } },
{ .name = "link", .ret_type = 0, .nargs = 2,
.args = { { Name, 0 }, { Name, 1 } } },
+ { .name = "linkat", .ret_type = 0, .nargs = 5,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
+ { Atflags, 4 } } },
{ .name = "unlink", .ret_type = 0, .nargs = 1,
.args = { { Name, 0 } } },
+ { .name = "unlinkat", .ret_type = 0, .nargs = 3,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Atflags, 2 } } },
{ .name = "chdir", .ret_type = 0, .nargs = 1,
.args = { { Name, 0 } } },
{ .name = "chroot", .ret_type = 0, .nargs = 1,
.args = { { Name, 0 } } },
+ { .name = "mkfifo", .ret_type = 0, .nargs = 2,
+ .args = { { Name, 0 }, { Octal, 1 } } },
+ { .name = "mkfifoat", .ret_type = 0, .nargs = 3,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 } } },
{ .name = "mknod", .ret_type = 0, .nargs = 3,
- .args = { { Name, 0 }, { Octal, 1 }, { Int, 3 } } },
+ .args = { { Name, 0 }, { Octal, 1 }, { Int, 2 } } },
+ { .name = "mknodat", .ret_type = 0, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Int, 3 } } },
{ .name = "chmod", .ret_type = 0, .nargs = 2,
.args = { { Name, 0 }, { Octal, 1 } } },
+ { .name = "fchmod", .ret_type = 0, .nargs = 2,
+ .args = { { Int, 0 }, { Octal, 1 } } },
+ { .name = "lchmod", .ret_type = 0, .nargs = 2,
+ .args = { { Name, 0 }, { Octal, 1 } } },
+ { .name = "fchmodat", .ret_type = 0, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Octal, 2 }, { Atflags, 3 } } },
{ .name = "chown", .ret_type = 0, .nargs = 3,
.args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
+ { .name = "fchown", .ret_type = 0, .nargs = 3,
+ .args = { { Int, 0 }, { Int, 1 }, { Int, 2 } } },
+ { .name = "lchown", .ret_type = 0, .nargs = 3,
+ .args = { { Name, 0 }, { Int, 1 }, { Int, 2 } } },
+ { .name = "fchownat", .ret_type = 0, .nargs = 5,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Int, 2 }, { Int, 3 },
+ { Atflags, 4 } } },
{ .name = "linux_stat64", .ret_type = 1, .nargs = 3,
- .args = { { Name | IN, 0 }, { Ptr | OUT, 1 }, { Ptr | IN, 1 }}},
+ .args = { { Name | IN, 0 }, { Ptr | OUT, 1 }, { Ptr | IN, 1 } } },
{ .name = "mount", .ret_type = 0, .nargs = 4,
.args = { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 } } },
{ .name = "umount", .ret_type = 0, .nargs = 2,
.args = { { Name, 0 }, { Int, 2 } } },
{ .name = "fstat", .ret_type = 1, .nargs = 2,
- .args = { { Int, 0 }, { Stat | OUT , 1 } } },
+ .args = { { Int, 0 }, { Stat | OUT, 1 } } },
+ { .name = "fstatat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { Stat | OUT, 2 },
+ { Atflags, 3 } } },
{ .name = "stat", .ret_type = 1, .nargs = 2,
.args = { { Name | IN, 0 }, { Stat | OUT, 1 } } },
{ .name = "lstat", .ret_type = 1, .nargs = 2,
@@ -162,7 +199,7 @@ static struct syscall syscalls[] = {
{ .name = "linux_newstat", .ret_type = 1, .nargs = 2,
.args = { { Name | IN, 0 }, { Ptr | OUT, 1 } } },
{ .name = "linux_access", .ret_type = 1, .nargs = 2,
- .args = { { Name, 0 }, { Int, 1 }}},
+ .args = { { Name, 0 }, { Accessmode, 1 } } },
{ .name = "linux_newfstat", .ret_type = 1, .nargs = 2,
.args = { { Int, 0 }, { Ptr | OUT, 1 } } },
{ .name = "write", .ret_type = 1, .nargs = 3,
@@ -174,27 +211,43 @@ static struct syscall syscalls[] = {
{ .name = "exit", .ret_type = 0, .nargs = 1,
.args = { { Hex, 0 } } },
{ .name = "access", .ret_type = 1, .nargs = 2,
- .args = { { Name | IN, 0 }, { Int, 1 } } },
+ .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
+ { .name = "eaccess", .ret_type = 1, .nargs = 2,
+ .args = { { Name | IN, 0 }, { Accessmode, 1 } } },
+ { .name = "faccessat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { Accessmode, 2 },
+ { Atflags, 3 } } },
{ .name = "sigaction", .ret_type = 1, .nargs = 3,
- .args = { { Signal, 0 }, { Sigaction | IN, 1 }, { Sigaction | OUT, 2 } } },
+ .args = { { Signal, 0 }, { Sigaction | IN, 1 },
+ { Sigaction | OUT, 2 } } },
{ .name = "accept", .ret_type = 1, .nargs = 3,
.args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
{ .name = "bind", .ret_type = 1, .nargs = 3,
.args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
+ { .name = "bindat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
+ { Int, 3 } } },
{ .name = "connect", .ret_type = 1, .nargs = 3,
.args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Int, 2 } } },
+ { .name = "connectat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Int, 1 }, { Sockaddr | IN, 2 },
+ { Int, 3 } } },
{ .name = "getpeername", .ret_type = 1, .nargs = 3,
.args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
{ .name = "getsockname", .ret_type = 1, .nargs = 3,
.args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
{ .name = "recvfrom", .ret_type = 1, .nargs = 6,
- .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { Hex, 3 }, { Sockaddr | OUT, 4 }, { Ptr | OUT, 5 } } },
+ .args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 }, { Hex, 3 },
+ { Sockaddr | OUT, 4 }, { Ptr | OUT, 5 } } },
{ .name = "sendto", .ret_type = 1, .nargs = 6,
- .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Hex, 3 }, { Sockaddr | IN, 4 }, { Ptr | IN, 5 } } },
+ .args = { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }, { Hex, 3 },
+ { Sockaddr | IN, 4 }, { Ptr | IN, 5 } } },
{ .name = "execve", .ret_type = 1, .nargs = 3,
- .args = { { Name | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } } },
+ .args = { { Name | IN, 0 }, { StringArray | IN, 1 },
+ { StringArray | IN, 2 } } },
{ .name = "linux_execve", .ret_type = 1, .nargs = 3,
- .args = { { Name | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } } },
+ .args = { { Name | IN, 0 }, { StringArray | IN, 1 },
+ { StringArray | IN, 2 } } },
{ .name = "kldload", .ret_type = 0, .nargs = 1,
.args = { { Name | IN, 0 } } },
{ .name = "kldunload", .ret_type = 0, .nargs = 1,
@@ -210,7 +263,8 @@ static struct syscall syscalls[] = {
{ .name = "nanosleep", .ret_type = 0, .nargs = 1,
.args = { { Timespec, 0 } } },
{ .name = "select", .ret_type = 1, .nargs = 5,
- .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 }, { Timeval, 4 } } },
+ .args = { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 },
+ { Timeval, 4 } } },
{ .name = "poll", .ret_type = 1, .nargs = 3,
.args = { { Pollfd, 0 }, { Int, 1 }, { Int, 2 } } },
{ .name = "gettimeofday", .ret_type = 1, .nargs = 2,
@@ -220,11 +274,12 @@ static struct syscall syscalls[] = {
{ .name = "getitimer", .ret_type = 1, .nargs = 2,
.args = { { Int, 0 }, { Itimerval | OUT, 2 } } },
{ .name = "setitimer", .ret_type = 1, .nargs = 3,
- .args = { { Int, 0 }, { Itimerval, 1 } , { Itimerval | OUT, 2 } } },
+ .args = { { Int, 0 }, { Itimerval, 1 }, { Itimerval | OUT, 2 } } },
{ .name = "kse_release", .ret_type = 0, .nargs = 1,
.args = { { Timespec, 0 } } },
{ .name = "kevent", .ret_type = 0, .nargs = 6,
- .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } },
+ .args = { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 },
+ { Int, 4 }, { Timespec, 5 } } },
{ .name = "sigprocmask", .ret_type = 0, .nargs = 3,
.args = { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } },
{ .name = "unmount", .ret_type = 1, .nargs = 2,
@@ -246,7 +301,14 @@ static struct syscall syscalls[] = {
{ .name = "lutimes", .ret_type = 1, .nargs = 2,
.args = { { Name | IN, 0 }, { Timeval2 | IN, 1 } } },
{ .name = "futimes", .ret_type = 1, .nargs = 2,
- .args = { { Int, 0 }, { Timeval | IN, 1 } } },
+ .args = { { Int, 0 }, { Timeval2 | IN, 1 } } },
+ { .name = "futimesat", .ret_type = 1, .nargs = 3,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timeval2 | IN, 2 } } },
+ { .name = "futimens", .ret_type = 1, .nargs = 2,
+ .args = { { Int, 0 }, { Timespec2 | IN, 1 } } },
+ { .name = "utimensat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name | IN, 1 }, { Timespec2 | IN, 2 },
+ { Atflags, 3 } } },
{ .name = "chflags", .ret_type = 1, .nargs = 2,
.args = { { Name | IN, 0 }, { Hex, 1 } } },
{ .name = "lchflags", .ret_type = 1, .nargs = 2,
@@ -266,9 +328,13 @@ static struct syscall syscalls[] = {
{ .name = "read", .ret_type = 1, .nargs = 3,
.args = { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 } } },
{ .name = "rename", .ret_type = 1, .nargs = 2,
- .args = { { Name , 0 } , { Name, 1 } } },
+ .args = { { Name, 0 }, { Name, 1 } } },
+ { .name = "renameat", .ret_type = 1, .nargs = 4,
+ .args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 } } },
{ .name = "symlink", .ret_type = 1, .nargs = 2,
- .args = { { Name , 0 } , { Name, 1 } } },
+ .args = { { Name, 0 }, { Name, 1 } } },
+ { .name = "symlinkat", .ret_type = 1, .nargs = 3,
+ .args = { { Name, 0 }, { Atfd, 1 }, { Name, 2 } } },
{ .name = "posix_openpt", .ret_type = 1, .nargs = 1,
.args = { { Open, 0 } } },
{ .name = "wait4", .ret_type = 1, .nargs = 4,
@@ -297,12 +363,14 @@ struct xlat {
static struct xlat kevent_filters[] = {
X(EVFILT_READ) X(EVFILT_WRITE) X(EVFILT_AIO) X(EVFILT_VNODE)
X(EVFILT_PROC) X(EVFILT_SIGNAL) X(EVFILT_TIMER)
- X(EVFILT_FS) X(EVFILT_READ) XEND
+ X(EVFILT_PROCDESC) X(EVFILT_FS) X(EVFILT_LIO) X(EVFILT_USER)
+ X(EVFILT_SENDFILE) XEND
};
static struct xlat kevent_flags[] = {
X(EV_ADD) X(EV_DELETE) X(EV_ENABLE) X(EV_DISABLE) X(EV_ONESHOT)
- X(EV_CLEAR) X(EV_FLAG1) X(EV_ERROR) X(EV_EOF) XEND
+ X(EV_CLEAR) X(EV_RECEIPT) X(EV_DISPATCH) X(EV_FORCEONESHOT)
+ X(EV_DROP) X(EV_FLAG1) X(EV_ERROR) X(EV_EOF) XEND
};
static struct xlat poll_flags[] = {
@@ -315,7 +383,7 @@ static struct xlat mmap_flags[] = {
X(MAP_SHARED) X(MAP_PRIVATE) X(MAP_FIXED) X(MAP_RESERVED0020)
X(MAP_RESERVED0040) X(MAP_RESERVED0080) X(MAP_RESERVED0100)
X(MAP_HASSEMAPHORE) X(MAP_STACK) X(MAP_NOSYNC) X(MAP_ANON)
- X(MAP_NOCORE) X(MAP_PREFAULT_READ)
+ X(MAP_EXCL) X(MAP_NOCORE) X(MAP_PREFAULT_READ)
#ifdef MAP_32BIT
X(MAP_32BIT)
#endif
@@ -327,7 +395,7 @@ static struct xlat mprot_flags[] = {
};
static struct xlat whence_arg[] = {
- X(SEEK_SET) X(SEEK_CUR) X(SEEK_END) XEND
+ X(SEEK_SET) X(SEEK_CUR) X(SEEK_END) X(SEEK_DATA) X(SEEK_HOLE) XEND
};
static struct xlat sigaction_flags[] = {
@@ -337,7 +405,10 @@ static struct xlat sigaction_flags[] = {
static struct xlat fcntl_arg[] = {
X(F_DUPFD) X(F_GETFD) X(F_SETFD) X(F_GETFL) X(F_SETFL)
- X(F_GETOWN) X(F_SETOWN) X(F_GETLK) X(F_SETLK) X(F_SETLKW) XEND
+ X(F_GETOWN) X(F_SETOWN) X(F_OGETLK) X(F_OSETLK) X(F_OSETLKW)
+ X(F_DUP2FD) X(F_GETLK) X(F_SETLK) X(F_SETLKW) X(F_SETLK_REMOTE)
+ X(F_READAHEAD) X(F_RDAHEAD) X(F_DUPFD_CLOEXEC) X(F_DUP2FD_CLOEXEC)
+ XEND
};
static struct xlat fcntlfd_arg[] = {
@@ -346,7 +417,7 @@ static struct xlat fcntlfd_arg[] = {
static struct xlat fcntlfl_arg[] = {
X(O_APPEND) X(O_ASYNC) X(O_FSYNC) X(O_NONBLOCK) X(O_NOFOLLOW)
- X(O_DIRECT) XEND
+ X(FRDAHEAD) X(O_DIRECT) XEND
};
static struct xlat sockdomain_arg[] = {
@@ -357,7 +428,8 @@ static struct xlat sockdomain_arg[] = {
X(PF_LINK) X(PF_XTP) X(PF_COIP) X(PF_CNT) X(PF_SIP) X(PF_IPX)
X(PF_RTIP) X(PF_PIP) X(PF_ISDN) X(PF_KEY) X(PF_INET6)
X(PF_NATM) X(PF_ATM) X(PF_NETGRAPH) X(PF_SLOW) X(PF_SCLUSTER)
- X(PF_ARP) X(PF_BLUETOOTH) XEND
+ X(PF_ARP) X(PF_BLUETOOTH) X(PF_IEEE80211) X(PF_INET_SDP)
+ X(PF_INET6_SDP) XEND
};
static struct xlat socktype_arg[] = {
@@ -369,7 +441,8 @@ static struct xlat open_flags[] = {
X(O_RDONLY) X(O_WRONLY) X(O_RDWR) X(O_ACCMODE) X(O_NONBLOCK)
X(O_APPEND) X(O_SHLOCK) X(O_EXLOCK) X(O_ASYNC) X(O_FSYNC)
X(O_NOFOLLOW) X(O_CREAT) X(O_TRUNC) X(O_EXCL) X(O_NOCTTY)
- X(O_DIRECT) X(O_DIRECTORY) X(O_EXEC) X(O_TTY_INIT) X(O_CLOEXEC) XEND
+ X(O_DIRECT) X(O_DIRECTORY) X(O_EXEC) X(O_TTY_INIT) X(O_CLOEXEC)
+ X(O_VERIFY) XEND
};
static struct xlat shutdown_arg[] = {
@@ -379,7 +452,8 @@ static struct xlat shutdown_arg[] = {
static struct xlat resource_arg[] = {
X(RLIMIT_CPU) X(RLIMIT_FSIZE) X(RLIMIT_DATA) X(RLIMIT_STACK)
X(RLIMIT_CORE) X(RLIMIT_RSS) X(RLIMIT_MEMLOCK) X(RLIMIT_NPROC)
- X(RLIMIT_NOFILE) X(RLIMIT_SBSIZE) X(RLIMIT_VMEM) XEND
+ X(RLIMIT_NOFILE) X(RLIMIT_SBSIZE) X(RLIMIT_VMEM) X(RLIMIT_NPTS)
+ X(RLIMIT_SWAP) X(RLIMIT_KQUEUES) XEND
};
static struct xlat pathconf_arg[] = {
@@ -392,12 +466,12 @@ static struct xlat pathconf_arg[] = {
X(_PC_REC_MIN_XFER_SIZE) X(_PC_REC_XFER_ALIGN)
X(_PC_SYMLINK_MAX) X(_PC_ACL_EXTENDED) X(_PC_ACL_PATH_MAX)
X(_PC_CAP_PRESENT) X(_PC_INF_PRESENT) X(_PC_MAC_PRESENT)
- XEND
+ X(_PC_ACL_NFS4) X(_PC_MIN_HOLE_SIZE) XEND
};
static struct xlat rfork_flags[] = {
- X(RFPROC) X(RFNOWAIT) X(RFFDG) X(RFCFDG) X(RFTHREAD) X(RFMEM)
- X(RFSIGSHARE) X(RFTSIGZMB) X(RFLINUXTHPN) XEND
+ X(RFFDG) X(RFPROC) X(RFMEM) X(RFNOWAIT) X(RFCFDG) X(RFTHREAD)
+ X(RFSIGSHARE) X(RFLINUXTHPN) X(RFTSIGZMB) X(RFPPWAIT) XEND
};
static struct xlat wait_options[] = {
@@ -428,6 +502,15 @@ static struct xlat umtx_ops[] = {
XEND
};
+static struct xlat at_flags[] = {
+ X(AT_EACCESS) X(AT_SYMLINK_NOFOLLOW) X(AT_SYMLINK_FOLLOW)
+ X(AT_REMOVEDIR) XEND
+};
+
+static struct xlat access_modes[] = {
+ X(R_OK) X(W_OK) X(X_OK) XEND
+};
+
#undef X
#undef XEND
@@ -539,44 +622,56 @@ get_struct(pid_t pid, void *offset, void *buf, int len)
}
#define MAXSIZE 4096
-#define BLOCKSIZE 1024
+
/*
* get_string
* Copy a string from the process. Note that it is
* expected to be a C string, but if max is set, it will
* only get that much.
*/
-
static char *
-get_string(pid_t pid, void *offset, int max)
+get_string(pid_t pid, void *addr, int max)
{
struct ptrace_io_desc iorequest;
- char *buf;
- int diff, i, size, totalsize;
+ char *buf, *nbuf;
+ size_t offset, size, totalsize;
- diff = 0;
- totalsize = size = max ? (max + 1) : BLOCKSIZE;
+ offset = 0;
+ if (max)
+ size = max + 1;
+ else {
+ /* Read up to the end of the current page. */
+ size = PAGE_SIZE - ((uintptr_t)addr % PAGE_SIZE);
+ if (size > MAXSIZE)
+ size = MAXSIZE;
+ }
+ totalsize = size;
buf = malloc(totalsize);
if (buf == NULL)
return (NULL);
for (;;) {
- diff = totalsize - size;
iorequest.piod_op = PIOD_READ_D;
- iorequest.piod_offs = (char *)offset + diff;
- iorequest.piod_addr = buf + diff;
+ iorequest.piod_offs = (char *)addr + offset;
+ iorequest.piod_addr = buf + offset;
iorequest.piod_len = size;
if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
free(buf);
return (NULL);
}
- for (i = 0 ; i < size; i++) {
- if (buf[diff + i] == '\0')
+ if (memchr(buf + offset, '\0', size) != NULL)
+ return (buf);
+ offset += size;
+ if (totalsize < MAXSIZE && max == 0) {
+ size = MAXSIZE - totalsize;
+ if (size > PAGE_SIZE)
+ size = PAGE_SIZE;
+ nbuf = realloc(buf, totalsize + size);
+ if (nbuf == NULL) {
+ buf[totalsize - 1] = '\0';
return (buf);
- }
- if (totalsize < MAXSIZE - BLOCKSIZE && max == 0) {
- totalsize += BLOCKSIZE;
- buf = realloc(buf, totalsize);
- size = BLOCKSIZE;
+ }
+ buf = nbuf;
+ totalsize += size;
} else {
buf[totalsize - 1] = '\0';
return (buf);
@@ -752,17 +847,51 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
struct timespec ts;
if (get_struct(pid, (void *)args[sc->offset], &ts,
sizeof(ts)) != -1)
- asprintf(&tmp, "{%ld.%09ld }", (long)ts.tv_sec,
+ asprintf(&tmp, "{ %ld.%09ld }", (long)ts.tv_sec,
ts.tv_nsec);
else
asprintf(&tmp, "0x%lx", args[sc->offset]);
break;
}
+ case Timespec2: {
+ struct timespec ts[2];
+ FILE *fp;
+ size_t len;
+ const char *sep;
+ unsigned int i;
+
+ if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts))
+ != -1) {
+ fp = open_memstream(&tmp, &len);
+ fputs("{ ", fp);
+ sep = "";
+ for (i = 0; i < nitems(ts); i++) {
+ fputs(sep, fp);
+ sep = ", ";
+ switch (ts[i].tv_nsec) {
+ case UTIME_NOW:
+ fprintf(fp, "UTIME_NOW");
+ break;
+ case UTIME_OMIT:
+ fprintf(fp, "UTIME_OMIT");
+ break;
+ default:
+ fprintf(fp, "%ld.%09ld",
+ (long)ts[i].tv_sec, ts[i].tv_nsec);
+ break;
+ }
+ }
+ fputs(" }", fp);
+ fclose(fp);
+ } else
+ asprintf(&tmp, "0x%lx", args[sc->offset]);
+ break;
+ }
case Timeval: {
struct timeval tv;
if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
!= -1)
- asprintf(&tmp, "{%ld.%06ld }", (long)tv.tv_sec,
+ asprintf(&tmp, "{ %ld.%06ld }", (long)tv.tv_sec,
tv.tv_usec);
else
asprintf(&tmp, "0x%lx", args[sc->offset]);
@@ -772,7 +901,7 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
struct timeval tv[2];
if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv))
!= -1)
- asprintf(&tmp, "{%ld.%06ld, %ld.%06ld }",
+ asprintf(&tmp, "{ %ld.%06ld, %ld.%06ld }",
(long)tv[0].tv_sec, tv[0].tv_usec,
(long)tv[1].tv_sec, tv[1].tv_usec);
else
@@ -783,7 +912,7 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
struct itimerval itv;
if (get_struct(pid, (void *)args[sc->offset], &itv,
sizeof(itv)) != -1)
- asprintf(&tmp, "{%ld.%06ld, %ld.%06ld }",
+ asprintf(&tmp, "{ %ld.%06ld, %ld.%06ld }",
(long)itv.it_interval.tv_sec,
itv.it_interval.tv_usec,
(long)itv.it_value.tv_sec,
@@ -859,7 +988,8 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
what = buf;
break;
}
- asprintf(&tmp, "(0x%lx)%s, 0x%lx", args[sc->offset], what, (long unsigned int)largs.args);
+ asprintf(&tmp, "(0x%lx)%s, 0x%lx", args[sc->offset], what,
+ (long unsigned int)largs.args);
break;
}
case Pollfd: {
@@ -886,6 +1016,7 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
tmpsize);
tmp[used++] = '{';
+ tmp[used++] = ' ';
for (i = 0; i < numfds; i++) {
u = snprintf(tmp + used, per_fd, "%s%d/%s",
@@ -894,6 +1025,7 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
if (u > 0)
used += u < per_fd ? u : per_fd;
}
+ tmp[used++] = ' ';
tmp[used++] = '}';
tmp[used++] = '\0';
} else {
@@ -926,6 +1058,7 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
"output", tmpsize);
tmp[used++] = '{';
+ tmp[used++] = ' ';
for (i = 0; i < numfds; i++) {
if (FD_ISSET(i, fds)) {
u = snprintf(tmp + used, per_fd, "%d ",
@@ -934,8 +1067,6 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
used += u < per_fd ? u : per_fd;
}
}
- if (tmp[used-1] == ' ')
- used--;
tmp[used++] = '}';
tmp[used++] = '\0';
} else
@@ -1136,8 +1267,9 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
default:
sa = (struct sockaddr *)&ss;
asprintf(&tmp, "{ sa_len = %d, sa_family = %d, sa_data "
- "= {%n%*s } }", (int)sa->sa_len, (int)sa->sa_family,
- &i, 6 * (int)(sa->sa_len - ((char *)&sa->sa_data -
+ "= { %n%*s } }", (int)sa->sa_len,
+ (int)sa->sa_family, &i,
+ 6 * (int)(sa->sa_len - ((char *)&sa->sa_data -
(char *)sa)), "");
if (tmp != NULL) {
p = tmp + i;
@@ -1203,6 +1335,7 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
"output", tmpsize);
tmp[used++] = '{';
+ tmp[used++] = ' ';
for (i = 0; i < numevents; i++) {
u = snprintf(tmp + used, per_ke,
"%s%p,%s,%s,%d,%p,%p",
@@ -1216,6 +1349,7 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
if (u > 0)
used += u < per_ke ? u : per_ke;
}
+ tmp[used++] = ' ';
tmp[used++] = '}';
tmp[used++] = '\0';
} else {
@@ -1297,6 +1431,22 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval,
case Umtxop:
tmp = strdup(xlookup(umtx_ops, args[sc->offset]));
break;
+ case Atfd:
+ if ((int)args[sc->offset] == AT_FDCWD)
+ tmp = strdup("AT_FDCWD");
+ else
+ asprintf(&tmp, "%d", (int)args[sc->offset]);
+ break;
+ case Atflags:
+ tmp = strdup(xlookup_bits(at_flags, args[sc->offset]));
+ break;
+ case Accessmode:
+ if (args[sc->offset] == F_OK)
+ tmp = strdup("F_OK");
+ else
+ tmp = strdup(xlookup_bits(access_modes,
+ args[sc->offset]));
+ break;
default:
errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK);
}
diff --git a/usr.bin/vgrind/vgrindefs.c b/usr.bin/vgrind/vgrindefs.c
deleted file mode 100644
index 3c310a9..0000000
--- a/usr.bin/vgrind/vgrindefs.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (c) 1980, 1993
- * The Regents of the University of California. 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.
- * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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$");
-
-#define BUFSIZ 1024
-#define MAXHOP 32 /* max number of tc= indirections */
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-
-/*
- * grindcap - routines for dealing with the language definitions data base
- * (code stolen almost totally from termcap)
- *
- * BUG: Should use a "last" pointer in tbuf, so that searching
- * for capabilities alphabetically would not be a n**2/2
- * process when large numbers of capabilities are given.
- * Note: If we add a last pointer now we will screw up the
- * tc capability. We really should compile termcap.
- *
- * Essentially all the work here is scanning and decoding escapes
- * in string capabilities. We don't use stdio because the editor
- * doesn't, and because living w/o it is not hard.
- */
-
-static char *tbuf;
-static char *filename;
-static int hopcount; /* detect infinite loops in termcap, init 0 */
-
-static int tnchktc(void);
-static int tnamatch(char *);
-static char *tskip(register char *);
-static char *tdecode(register char *, char **);
-
-/*
- * Get an entry for terminal name in buffer bp,
- * from the termcap file. Parse is very rudimentary;
- * we just notice escaped newlines.
- */
-int
-tgetent(char *bp, char *name, char *file)
-{
- register char *cp;
- register int c;
- register int i = 0, cnt = 0;
- char ibuf[BUFSIZ];
- int tf;
-
- tbuf = bp;
- tf = 0;
- filename = file;
- tf = open(filename, O_RDONLY);
- if (tf < 0)
- return (-1);
- for (;;) {
- cp = bp;
- for (;;) {
- if (i == cnt) {
- cnt = read(tf, ibuf, BUFSIZ);
- if (cnt <= 0) {
- close(tf);
- return (0);
- }
- i = 0;
- }
- c = ibuf[i++];
- if (c == '\n') {
- if (cp > bp && cp[-1] == '\\'){
- cp--;
- continue;
- }
- break;
- }
- if (cp >= bp+BUFSIZ) {
- write(STDERR_FILENO, "Vgrind entry too long\n", 23);
- break;
- } else
- *cp++ = c;
- }
- *cp = 0;
-
- /*
- * The real work for the match.
- */
- if (tnamatch(name)) {
- close(tf);
- return(tnchktc());
- }
- }
-}
-
-/*
- * tnchktc: check the last entry, see if it's tc=xxx. If so,
- * recursively find xxx and append that entry (minus the names)
- * to take the place of the tc=xxx entry. This allows termcap
- * entries to say "like an HP2621 but doesn't turn on the labels".
- * Note that this works because of the left to right scan.
- */
-static int
-tnchktc(void)
-{
- register char *p, *q;
- char tcname[16]; /* name of similar terminal */
- char tcbuf[BUFSIZ];
- char *holdtbuf = tbuf;
- int l;
-
- p = tbuf + strlen(tbuf) - 2; /* before the last colon */
- while (*--p != ':')
- if (p<tbuf) {
- write(STDERR_FILENO, "Bad vgrind entry\n", 18);
- return (0);
- }
- p++;
- /* p now points to beginning of last field */
- if (p[0] != 't' || p[1] != 'c')
- return(1);
- strlcpy(tcname, p+3, 16);
- q = tcname;
- while (q && *q != ':')
- q++;
- *q = 0;
- if (++hopcount > MAXHOP) {
- write(STDERR_FILENO, "Infinite tc= loop\n", 18);
- return (0);
- }
- if (tgetent(tcbuf, tcname, filename) != 1)
- return(0);
- for (q=tcbuf; *q != ':'; q++)
- ;
- l = p - holdtbuf + strlen(q);
- if (l > BUFSIZ) {
- write(STDERR_FILENO, "Vgrind entry too long\n", 23);
- q[BUFSIZ - (p-tbuf)] = 0;
- }
- strlcpy(p, q+1, BUFSIZ - (p - holdtbuf));
- tbuf = holdtbuf;
- return(1);
-}
-
-/*
- * Tnamatch deals with name matching. The first field of the termcap
- * entry is a sequence of names separated by |'s, so we compare
- * against each such name. The normal : terminator after the last
- * name (before the first field) stops us.
- */
-static int
-tnamatch(char *np)
-{
- register char *Np, *Bp;
-
- Bp = tbuf;
- if (*Bp == '#')
- return(0);
- for (;;) {
- for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
- continue;
- if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
- return (1);
- while (*Bp && *Bp != ':' && *Bp != '|')
- Bp++;
- if (*Bp == 0 || *Bp == ':')
- return (0);
- Bp++;
- }
-}
-
-/*
- * Skip to the next field. Notice that this is very dumb, not
- * knowing about \: escapes or any such. If necessary, :'s can be put
- * into the termcap file in octal.
- */
-static char *
-tskip(register char *bp)
-{
-
- while (*bp && *bp != ':')
- bp++;
- if (*bp == ':')
- bp++;
- return (bp);
-}
-
-/*
- * Return the (numeric) option id.
- * Numeric options look like
- * li#80
- * i.e. the option string is separated from the numeric value by
- * a # character. If the option is not found we return -1.
- * Note that we handle octal numbers beginning with 0.
- */
-int
-tgetnum(char *id)
-{
- register int i, base;
- register char *bp = tbuf;
-
- for (;;) {
- bp = tskip(bp);
- if (*bp == 0)
- return (-1);
- if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
- continue;
- if (*bp == '@')
- return(-1);
- if (*bp != '#')
- continue;
- bp++;
- base = 10;
- if (*bp == '0')
- base = 8;
- i = 0;
- while (isdigit(*bp))
- i *= base, i += *bp++ - '0';
- return (i);
- }
-}
-
-/*
- * Handle a flag option.
- * Flag options are given "naked", i.e. followed by a : or the end
- * of the buffer. Return 1 if we find the option, or 0 if it is
- * not given.
- */
-int
-tgetflag(char *id)
-{
- register char *bp = tbuf;
-
- for (;;) {
- bp = tskip(bp);
- if (!*bp)
- return (0);
- if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
- if (!*bp || *bp == ':')
- return (1);
- else if (*bp == '@')
- return(0);
- }
- }
-}
-
-/*
- * Get a string valued option.
- * These are given as
- * cl=^Z
- * Much decoding is done on the strings, and the strings are
- * placed in area, which is a ref parameter which is updated.
- * No checking on area overflow.
- */
-char *
-tgetstr(char *id, char **area)
-{
- register char *bp = tbuf;
-
- for (;;) {
- bp = tskip(bp);
- if (!*bp)
- return (0);
- if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
- continue;
- if (*bp == '@')
- return(0);
- if (*bp != '=')
- continue;
- bp++;
- return (tdecode(bp, area));
- }
-}
-
-/*
- * Tdecode does the grung work to decode the
- * string capability escapes.
- */
-static char *
-tdecode(register char *str, char **area)
-{
- register char *cp;
- register int c;
-
- cp = *area;
- while ((c = *str++)) {
- if (c == ':' && *(cp-1) != '\\')
- break;
- *cp++ = c;
- }
- *cp++ = 0;
- str = *area;
- *area = cp;
- return (str);
-}
diff --git a/usr.bin/wall/ttymsg.c b/usr.bin/wall/ttymsg.c
index 37b09e9..1317a4b 100644
--- a/usr.bin/wall/ttymsg.c
+++ b/usr.bin/wall/ttymsg.c
@@ -62,7 +62,7 @@ ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout)
struct iovec localiov[7];
ssize_t left, wret;
int cnt, fd;
- static char device[MAXNAMLEN] = _PATH_DEV;
+ char device[MAXNAMLEN] = _PATH_DEV;
static char errbuf[1024];
char *p;
int forked;
@@ -71,8 +71,8 @@ ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout)
if (iovcnt > (int)(sizeof(localiov) / sizeof(localiov[0])))
return ("too many iov's (change code in wall/ttymsg.c)");
+ strlcat(device, line, sizeof(device));
p = device + sizeof(_PATH_DEV) - 1;
- strlcpy(p, line, sizeof(device));
if (strncmp(p, "pts/", 4) == 0)
p += 4;
if (strchr(p, '/') != NULL) {
diff --git a/usr.bin/xargs/xargs.1 b/usr.bin/xargs/xargs.1
index 934d6ed..607b966 100644
--- a/usr.bin/xargs/xargs.1
+++ b/usr.bin/xargs/xargs.1
@@ -33,7 +33,7 @@
.\" $FreeBSD$
.\" $xMach: xargs.1,v 1.2 2002/02/23 05:23:37 tim Exp $
.\"
-.Dd March 16, 2012
+.Dd August 4, 2015
.Dt XARGS 1
.Os
.Sh NAME
@@ -207,6 +207,11 @@ Parallel mode: run at most
invocations of
.Ar utility
at once.
+If
+.Ar maxprocs
+is set to 0,
+.Nm
+will run as many processes as possible.
.It Fl p
Echo each command to be executed and ask the user whether it should be
executed.
diff --git a/usr.bin/xargs/xargs.c b/usr.bin/xargs/xargs.c
index b95c7d4..c69a23a 100644
--- a/usr.bin/xargs/xargs.c
+++ b/usr.bin/xargs/xargs.c
@@ -46,9 +46,11 @@ static char sccsid[] = "@(#)xargs.c 8.1 (Berkeley) 6/6/93";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/param.h>
+#include <sys/types.h>
#include <sys/wait.h>
-
+#include <sys/time.h>
+#include <sys/limits.h>
+#include <sys/resource.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
@@ -100,6 +102,7 @@ main(int argc, char *argv[])
long arg_max;
int ch, Jflag, nargs, nflag, nline;
size_t linelen;
+ struct rlimit rl;
char *endptr;
const char *errstr;
@@ -166,6 +169,14 @@ main(int argc, char *argv[])
maxprocs = strtonum(optarg, 1, INT_MAX, &errstr);
if (errstr)
errx(1, "-P %s: %s", optarg, errstr);
+ if (getrlimit(RLIMIT_NPROC, &rl) != 0)
+ errx(1, "getrlimit failed");
+ if (*endptr != '\0')
+ errx(1, "invalid number for -P option");
+ if (maxprocs < 0)
+ errx(1, "value for -P option should be >= 0");
+ if (maxprocs == 0 || maxprocs > rl.rlim_cur)
+ maxprocs = rl.rlim_cur;
break;
case 'p':
pflag = 1;
diff --git a/usr.bin/ypcat/ypcat.c b/usr.bin/ypcat/ypcat.c
index 3484bc9..aad07cc 100644
--- a/usr.bin/ypcat/ypcat.c
+++ b/usr.bin/ypcat/ypcat.c
@@ -1,5 +1,7 @@
+/* $OpenBSD: ypcat.c,v 1.16 2015/02/08 23:40:35 deraadt Exp $ */
+
/*
- * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
+ * Copyright (c) 1992, 1993, 1996 Theo de Raadt <deraadt@theos.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -10,9 +12,6 @@
* 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
@@ -35,11 +34,6 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/socket.h>
-#include <rpc/rpc.h>
-#include <rpc/xdr.h>
-#include <rpcsvc/yp_prot.h>
-#include <rpcsvc/ypclnt.h>
-
#include <ctype.h>
#include <err.h>
#include <stdio.h>
@@ -47,7 +41,12 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
-struct ypalias {
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+
+static const struct ypalias {
char *alias, *name;
} ypaliases[] = {
{ "passwd", "passwd.byname" },
@@ -62,19 +61,20 @@ struct ypalias {
{ "ethers", "ethers.byname" },
};
-int key;
+static int key;
static void
usage(void)
{
fprintf(stderr, "%s\n%s\n",
- "usage: ypcat [-kt] [-d domainname] mapname",
- " ypcat -x");
+ "usage: ypcat [-kt] [-d domainname] mapname",
+ " ypcat -x");
exit(1);
}
static int
-printit(unsigned long instatus, char *inkey, int inkeylen, char *inval, int invallen, void *dummy __unused)
+printit(u_long instatus, char *inkey, int inkeylen, char *inval, int invallen,
+ void *indata)
{
if (instatus != YP_TRUE)
return (instatus);
@@ -87,31 +87,27 @@ printit(unsigned long instatus, char *inkey, int inkeylen, char *inval, int inva
int
main(int argc, char *argv[])
{
- char *domainname = NULL;
+ char *domain = NULL, *inmap;
struct ypall_callback ypcb;
- char *inmap;
- int notrans;
- int c, r;
+ int c, notrans, r;
u_int i;
notrans = key = 0;
-
while ((c = getopt(argc, argv, "xd:kt")) != -1)
switch (c) {
case 'x':
- for (i = 0; i<sizeof ypaliases/sizeof ypaliases[0]; i++)
+ for (i=0; i<sizeof ypaliases/sizeof ypaliases[0]; i++)
printf("Use \"%s\" for \"%s\"\n",
- ypaliases[i].alias,
- ypaliases[i].name);
+ ypaliases[i].alias, ypaliases[i].name);
exit(0);
case 'd':
- domainname = optarg;
+ domain = optarg;
break;
case 't':
- notrans++;
+ notrans = 1;
break;
case 'k':
- key++;
+ key = 1;
break;
default:
usage();
@@ -120,24 +116,27 @@ main(int argc, char *argv[])
if (optind + 1 != argc)
usage();
- if (!domainname)
- yp_get_default_domain(&domainname);
+ if (domain == NULL)
+ yp_get_default_domain(&domain);
inmap = argv[optind];
- for (i = 0; (!notrans) && i<sizeof ypaliases/sizeof ypaliases[0]; i++)
- if (strcmp(inmap, ypaliases[i].alias) == 0)
- inmap = ypaliases[i].name;
+ if (!notrans) {
+ for (i=0; i<sizeof ypaliases/sizeof ypaliases[0]; i++)
+ if (strcmp(inmap, ypaliases[i].alias) == 0)
+ inmap = ypaliases[i].name;
+ }
ypcb.foreach = printit;
ypcb.data = NULL;
- r = yp_all(domainname, inmap, &ypcb);
+ r = yp_all(domain, inmap, &ypcb);
switch (r) {
case 0:
break;
case YPERR_YPBIND:
errx(1, "not running ypbind");
default:
- errx(1, "no such map %s. reason: %s", inmap, yperr_string(r));
+ errx(1, "no such map %s. Reason: %s",
+ inmap, yperr_string(r));
}
exit(0);
}
diff --git a/usr.bin/ypmatch/ypmatch.c b/usr.bin/ypmatch/ypmatch.c
index a9c32ea..ff5365b 100644
--- a/usr.bin/ypmatch/ypmatch.c
+++ b/usr.bin/ypmatch/ypmatch.c
@@ -1,5 +1,8 @@
+/* $OpenBSD: ypmatch.c,v 1.16 2015/02/08 23:40:35 deraadt Exp $ */
+/* $NetBSD: ypmatch.c,v 1.8 1996/05/07 01:24:52 jtc Exp $ */
+
/*
- * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
+ * Copyright (c) 1992, 1993, 1996 Theo de Raadt <deraadt@theos.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -10,9 +13,6 @@
* 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
@@ -35,11 +35,6 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/socket.h>
-#include <rpc/rpc.h>
-#include <rpc/xdr.h>
-#include <rpcsvc/yp_prot.h>
-#include <rpcsvc/ypclnt.h>
-
#include <ctype.h>
#include <err.h>
#include <stdio.h>
@@ -47,7 +42,12 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
-struct ypalias {
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+
+static const struct ypalias {
char *alias, *name;
} ypaliases[] = {
{ "passwd", "passwd.byname" },
@@ -66,26 +66,31 @@ static void
usage(void)
{
fprintf(stderr, "%s\n%s\n",
- "usage: ypmatch [-kt] [-d domainname] key ... mapname",
- " ypmatch -x");
+ "usage: ypmatch [-kt] [-d domainname] key ... mapname",
+ " ypmatch -x");
+ fprintf(stderr,
+ "where\n"
+ "\tmapname may be either a mapname or a nickname for a map.\n"
+ "\t-k prints keys as well as values.\n"
+ "\t-t inhibits map nickname translation.\n"
+ "\t-x dumps the map nickname translation table.\n");
exit(1);
}
int
main(int argc, char *argv[])
{
- char *domainname = NULL;
- char *inkey, *inmap, *outbuf;
- int outbuflen, key, notrans;
+ char *domainname, *inkey, *inmap, *outbuf;
+ int outbuflen, key, notrans, rval;
int c, r;
u_int i;
+ domainname = NULL;
notrans = key = 0;
-
- while ((c = getopt(argc, argv, "xd:kt")) != -1)
+ while ((c=getopt(argc, argv, "xd:kt")) != -1)
switch (c) {
case 'x':
- for (i = 0; i<sizeof ypaliases/sizeof ypaliases[0]; i++)
+ for (i=0; i<sizeof ypaliases/sizeof ypaliases[0]; i++)
printf("Use \"%s\" for \"%s\"\n",
ypaliases[i].alias,
ypaliases[i].name);
@@ -94,25 +99,30 @@ main(int argc, char *argv[])
domainname = optarg;
break;
case 't':
- notrans++;
+ notrans = 1;
break;
case 'k':
- key++;
+ key = 1;
break;
default:
usage();
}
- if ((argc-optind) < 2)
+ if ((argc-optind) < 2 )
usage();
- if (!domainname)
+ if (domainname == NULL) {
yp_get_default_domain(&domainname);
+ }
inmap = argv[argc-1];
- for (i = 0; (!notrans) && i<sizeof ypaliases/sizeof ypaliases[0]; i++)
- if (strcmp(inmap, ypaliases[i].alias) == 0)
- inmap = ypaliases[i].name;
+ if (notrans == 0) {
+ for (i=0; i<sizeof ypaliases/sizeof ypaliases[0]; i++)
+ if (strcmp(inmap, ypaliases[i].alias) == 0)
+ inmap = ypaliases[i].name;
+ }
+
+ rval = 0;
for (; optind < argc-1; optind++) {
inkey = argv[optind];
@@ -121,15 +131,17 @@ main(int argc, char *argv[])
switch (r) {
case 0:
if (key)
- printf("%s ", inkey);
+ printf("%s: ", inkey);
printf("%*.*s\n", outbuflen, outbuflen, outbuf);
break;
case YPERR_YPBIND:
errx(1, "not running ypbind");
default:
- errx(1, "can't match key %s in map %s. reason: %s",
- inkey, inmap, yperr_string(r));
+ errx(1, "can't match key %s in map %s. Reason: %s",
+ inkey, inmap, yperr_string(r));
+ rval = 1;
+ break;
}
}
- exit(0);
+ exit(rval);
}
diff --git a/usr.bin/ypwhich/ypwhich.c b/usr.bin/ypwhich/ypwhich.c
index b31dcae..14fc1b3 100644
--- a/usr.bin/ypwhich/ypwhich.c
+++ b/usr.bin/ypwhich/ypwhich.c
@@ -59,7 +59,7 @@ __FBSDID("$FreeBSD$");
extern bool_t xdr_domainname();
-struct ypalias {
+static const struct ypalias {
char *alias, *name;
} ypaliases[] = {
{ "passwd", "passwd.byname" },
diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8
index c5de82a..4f0115f 100644
--- a/usr.sbin/bhyve/bhyve.8
+++ b/usr.sbin/bhyve/bhyve.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 17, 2014
+.Dd August 7, 2015
.Dt BHYVE 8
.Os
.Sh NAME
@@ -50,7 +50,7 @@ Parameters such as the number of virtual CPUs, amount of guest memory, and
I/O connectivity can be specified with command-line parameters.
.Pp
The guest operating system must be loaded with
-.Xr bhyveload 4
+.Xr bhyveload 8
or a similar boot loader before running
.Nm .
.Pp
@@ -61,8 +61,8 @@ exit is detected.
.Bl -tag -width 10n
.It Fl a
The guest's local APIC is configured in xAPIC mode.
-The xAPIC mode is the default setting so this option is redundant. It will be
-deprecated in a future version.
+The xAPIC mode is the default setting so this option is redundant.
+It will be deprecated in a future version.
.It Fl A
Generate ACPI tables.
Required for
@@ -124,7 +124,7 @@ Force the guest virtual CPU to exit when a PAUSE instruction is detected.
.It Fl s Ar slot,emulation Ns Op , Ns Ar conf
Configure a virtual PCI slot and function.
.Pp
-.Nm bhyve
+.Nm
provides PCI bus emulation and virtual devices that can be attached to
slots on the bus.
There are 32 available slots, with the option of providing up to 8 functions
@@ -136,11 +136,19 @@ per slot.
.Pp
The
.Ar pcislot
-value is 0 to 31. The optional function value is 0 to 7. The optional
+value is 0 to 31.
+The optional
+.Ar function
+value is 0 to 7.
+The optional
.Ar bus
value is 0 to 255.
-If not specified, the function value defaults to 0.
-If not specified, the bus value defaults to 0.
+If not specified, the
+.Ar function
+value defaults to 0.
+If not specified, the
+.Ar bus
+value defaults to 0.
.It Ar emulation
.Bl -tag -width 10n
.It Li hostbridge | Li amd_hostbridge
@@ -221,7 +229,9 @@ TTY devices:
.Bl -tag -width 10n
.It Li stdio
Connect the serial port to the standard input and output of
-the bhyve process.
+the
+.Nm
+process.
.It Pa /dev/xxx
Use the host TTY device for serial port I/O.
.El
@@ -265,7 +275,8 @@ in the guest's System Management BIOS System Information structure.
By default a UUID is generated from the host's hostname and
.Ar vmname .
.It Fl w
-Ignore accesses to unimplemented Model Specific Registers (MSRs). This is intended for debug purposes.
+Ignore accesses to unimplemented Model Specific Registers (MSRs).
+This is intended for debug purposes.
.It Fl W
Force virtio PCI device emulations to use MSI interrupts instead of MSI-X
interrupts.
@@ -280,7 +291,7 @@ This should be the same as that created by
.El
.Sh EXAMPLES
The guest operating system must have been loaded with
-.Xr bhyveload 4
+.Xr bhyveload 8
or a similar boot loader before
.Xr bhyve 4
can be run.
@@ -308,7 +319,7 @@ Run an 8GB quad-CPU virtual machine with 8 AHCI SATA disks, an AHCI ATAPI
CD-ROM, a single virtio network port, an AMD hostbridge, and the console
port connected to an
.Xr nmdm 4
-null-model device.
+null-modem device.
.Bd -literal -offset indent
bhyve -c 4 \e\
-s 0,amd_hostbridge -s 1,lpc \\
diff --git a/usr.sbin/bsdinstall/scripts/auto b/usr.sbin/bsdinstall/scripts/auto
index 891419a..166823d 100755
--- a/usr.sbin/bsdinstall/scripts/auto
+++ b/usr.sbin/bsdinstall/scripts/auto
@@ -284,7 +284,7 @@ if [ ! -z "$FETCH_DISTRIBUTIONS" ]; then
DISTDIR_IS_UNIONFS=1
mount_nullfs -o union "$BSDINSTALL_FETCHDEST" "$BSDINSTALL_DISTDIR"
else
- export DISTRIBUTIONS="MANIFEST $ALL_DISTRIBUTIONS"
+ export DISTRIBUTIONS="$ALL_DISTRIBUTIONS"
export BSDINSTALL_DISTDIR="$BSDINSTALL_FETCHDEST"
fi
diff --git a/usr.sbin/chkgrp/chkgrp.c b/usr.sbin/chkgrp/chkgrp.c
index d7c1506..81cb83b 100644
--- a/usr.sbin/chkgrp/chkgrp.c
+++ b/usr.sbin/chkgrp/chkgrp.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
#include <ctype.h>
+#include <inttypes.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
@@ -105,7 +106,8 @@ main(int argc, char *argv[])
/*
* Hack: special case for + line
*/
- if (strncmp(line, "+:::", len) == 0)
+ if (strncmp(line, "+:::", len) == 0 ||
+ strncmp(line, "+:*::", len) == 0)
continue;
/*
diff --git a/usr.sbin/crunch/crunchgen/crunchgen.c b/usr.sbin/crunch/crunchgen/crunchgen.c
index 79b240f..8ace15a 100644
--- a/usr.sbin/crunch/crunchgen/crunchgen.c
+++ b/usr.sbin/crunch/crunchgen/crunchgen.c
@@ -980,7 +980,7 @@ top_makefile_rules(FILE *outmk)
prog_t *p;
fprintf(outmk, "LD?= ld\n");
- fprintf(outmk, "STRIP?= strip\n");
+ fprintf(outmk, "STRIPBIN?= strip\n");
if ( subtract_strlst(&libs, &libs_so) )
fprintf(outmk, "# NOTE: Some LIBS declarations below overridden by LIBS_SO\n");
@@ -1028,7 +1028,7 @@ top_makefile_rules(FILE *outmk)
fprintf(outmk, "\t$(CC) -static -o %s %s.o $(CRUNCHED_OBJS) $(LIBS)\n",
execfname, execfname);
fprintf(outmk, ".endif\n");
- fprintf(outmk, "\t$(STRIP) %s\n", execfname);
+ fprintf(outmk, "\t$(STRIPBIN) %s\n", execfname);
fprintf(outmk, "realclean: clean subclean\n");
fprintf(outmk, "clean:\n\trm -f %s *.lo *.o *_stub.c\n", execfname);
fprintf(outmk, "subclean: $(SUBCLEAN_TARGETS)\n");
diff --git a/usr.sbin/pw/Makefile b/usr.sbin/pw/Makefile
index c265399..f26c9de 100644
--- a/usr.sbin/pw/Makefile
+++ b/usr.sbin/pw/Makefile
@@ -3,7 +3,8 @@
PROG= pw
MAN= pw.conf.5 pw.8
SRCS= pw.c pw_conf.c pw_user.c pw_group.c pw_log.c pw_nis.c pw_vpw.c \
- grupd.c pwupd.c psdate.c bitmap.c cpdir.c rm_r.c
+ grupd.c pwupd.c psdate.c bitmap.c cpdir.c rm_r.c strtounum.c \
+ pw_utils.c
WARNS?= 3
diff --git a/usr.sbin/pw/cpdir.c b/usr.sbin/pw/cpdir.c
index e84d0f3..334f789 100644
--- a/usr.sbin/pw/cpdir.c
+++ b/usr.sbin/pw/cpdir.c
@@ -29,17 +29,12 @@ static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
+#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
-#include <stdio.h>
#include <string.h>
-#include <stdlib.h>
#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <dirent.h>
#include "pw.h"
#include "pwupd.h"
diff --git a/usr.sbin/pw/grupd.c b/usr.sbin/pw/grupd.c
index d52a345..9cbe0cb 100644
--- a/usr.sbin/pw/grupd.c
+++ b/usr.sbin/pw/grupd.c
@@ -29,13 +29,11 @@ static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
+#include <err.h>
#include <grp.h>
#include <libutil.h>
-#include <err.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <sys/param.h>
#include "pwupd.h"
diff --git a/usr.sbin/pw/psdate.c b/usr.sbin/pw/psdate.c
index 8e3a951..bd2aa15 100644
--- a/usr.sbin/pw/psdate.c
+++ b/usr.sbin/pw/psdate.c
@@ -29,12 +29,11 @@ static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
-#include <stdio.h>
+#include <ctype.h>
+#include <err.h>
#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
#include <xlocale.h>
-#include <err.h>
#include "psdate.h"
diff --git a/usr.sbin/pw/pw.8 b/usr.sbin/pw/pw.8
index c29a8a9..3a9c0b0 100644
--- a/usr.sbin/pw/pw.8
+++ b/usr.sbin/pw/pw.8
@@ -35,11 +35,9 @@
.Op Fl R Ar rootdir
.Op Fl V Ar etcdir
.Ar useradd
-.Op name|uid
+.Oo Fl n Oc name Oo Fl u Ar uid Oc
.Op Fl C Ar config
.Op Fl q
-.Op Fl n Ar name
-.Op Fl u Ar uid
.Op Fl c Ar comment
.Op Fl d Ar dir
.Op Fl e Ar date
@@ -61,7 +59,6 @@
.Op Fl R Ar rootdir
.Op Fl V Ar etcdir
.Ar useradd
-.Op name|uid
.Fl D
.Op Fl C Ar config
.Op Fl q
@@ -81,27 +78,23 @@
.Op Fl R Ar rootdir
.Op Fl V Ar etcdir
.Ar userdel
-.Op name|uid
-.Op Fl n Ar name
-.Op Fl u Ar uid
+.Oo Fl n Oc name|uid | Fl u Ar uid
.Op Fl r
.Op Fl Y
.Nm
.Op Fl R Ar rootdir
.Op Fl V Ar etcdir
.Ar usermod
-.Op name|uid
+.Oo Fl n Oc name|uid Oo Fl u Ar newuid Oc | Fl u Ar uid
.Op Fl C Ar config
.Op Fl q
-.Op Fl n Ar name
-.Op Fl u Ar uid
.Op Fl c Ar comment
.Op Fl d Ar dir
.Op Fl e Ar date
.Op Fl p Ar date
.Op Fl g Ar group
.Op Fl G Ar grouplist
-.Op Fl l Ar name
+.Op Fl l Ar newname
.Op Fl m
.Op Fl M Ar mode
.Op Fl k Ar dir
@@ -116,9 +109,7 @@
.Op Fl R Ar rootdir
.Op Fl V Ar etcdir
.Ar usershow
-.Op name|uid
-.Op Fl n Ar name
-.Op Fl u Ar uid
+.Oo Fl n Oc name|uid | Fl u Ar uid
.Op Fl F
.Op Fl P
.Op Fl 7
@@ -133,11 +124,9 @@
.Op Fl R Ar rootdir
.Op Fl V Ar etcdir
.Ar groupadd
-.Op group|gid
+.Oo Fl n Oc name Oo Fl g Ar gid Oc
.Op Fl C Ar config
.Op Fl q
-.Op Fl n Ar group
-.Op Fl g Ar gid
.Op Fl M Ar members
.Op Fl o
.Op Fl h Ar fd | Fl H Ar fd
@@ -148,20 +137,16 @@
.Op Fl R Ar rootdir
.Op Fl V Ar etcdir
.Ar groupdel
-.Op group|gid
-.Op Fl n Ar name
-.Op Fl g Ar gid
+.Oo Fl n Oc name|gid | Fl g Ar gid
.Op Fl Y
.Nm
.Op Fl R Ar rootdir
.Op Fl V Ar etcdir
.Ar groupmod
-.Op group|gid
+.Oo Fl n Oc name|gid Oo Fl g Ar newgid Oc | Fl g Ar gid
.Op Fl C Ar config
.Op Fl q
-.Op Fl n Ar name
-.Op Fl g Ar gid
-.Op Fl l Ar name
+.Op Fl l Ar newname
.Op Fl M Ar members
.Op Fl m Ar newmembers
.Op Fl d Ar oldmembers
@@ -173,9 +158,7 @@
.Op Fl R Ar rootdir
.Op Fl V Ar etcdir
.Ar groupshow
-.Op group|gid
-.Op Fl n Ar name
-.Op Fl g Ar gid
+.Oo Fl n Oc name|gid | Fl g Ar gid
.Op Fl F
.Op Fl P
.Op Fl a
@@ -189,14 +172,14 @@
.Op Fl R Ar rootdir
.Op Fl V Ar etcdir
.Ar lock
-.Op name|uid
+.Oo Fl n Oc name|uid | Fl u Ar uid
.Op Fl C Ar config
.Op Fl q
.Nm
.Op Fl R Ar rootdir
.Op Fl V Ar etcdir
.Ar unlock
-.Op name|uid
+.Oo Fl n Oc name|uid | Fl u Ar uid
.Op Fl C Ar config
.Op Fl q
.Sh DESCRIPTION
@@ -250,8 +233,9 @@ all mean the same thing.)
This flexibility is useful for interactive scripts calling
.Nm
for user and group database manipulation.
-Following these keywords, you may optionally specify the user or group name or numeric
-id as an alternative to using the
+Following these keywords,
+the user or group name or numeric id may be optionally specified as an
+alternative to using the
.Fl n Ar name ,
.Fl u Ar uid ,
.Fl g Ar gid
@@ -266,12 +250,13 @@ will operate.
Any paths specified will be relative to
.Va rootdir .
.It Fl V Ar etcdir
-This flag sets an alternate location for the password, group and configuration files,
-and may be used to maintain a user/group database in an alternate location.
+Set an alternate location for the password, group, and configuration files.
+Can be used to maintain a user/group database in an alternate location.
If this switch is specified, the system
.Pa /etc/pw.conf
-will not be sourced for default configuration data, but the file pw.conf in the
-specified directory will be used instead (or none, if it does not exist).
+will not be sourced for default configuration data,
+but the file pw.conf in the specified directory will be used instead
+.Pq or none, if it does not exist .
The
.Fl C
flag may be used to override this behaviour.
@@ -294,7 +279,8 @@ configuration file.
.It Fl q
Use of this option causes
.Nm
-to suppress error messages, which may be useful in interactive environments where it
+to suppress error messages,
+which may be useful in interactive environments where it
is preferable to interpret status codes returned by
.Nm
rather than messing up a carefully formatted display.
@@ -338,27 +324,40 @@ and
.Ar usermod
commands:
.Bl -tag -width "-G grouplist"
-.It Fl n Ar name
+.It Oo Fl n Oc Ar name
+Required unless
+.Fl u Ar uid
+is given.
Specify the user/account name.
+In the case of
+.Ar usermod
+can be a uid.
.It Fl u Ar uid
+Required if
+.Ar name
+is not given.
Specify the user/account numeric id.
+In the case of
+.Ar usermod
+if paired with
+.Ar name ,
+changes the numeric id of the named user/account.
.Pp
-Usually, you only need to provide one or the other of these options, as the account
-name will imply the uid, or vice versa.
-However, there are times when you need to provide both.
+Usually, only one of these options is required,
+as the account name will imply the uid, or vice versa.
+However, there are times when both are needed.
For example, when changing the uid of an existing user with
.Ar usermod ,
-or overriding the default uid when creating a new account.
-If you wish
-.Nm
-to automatically allocate the uid to a new user with
+or overriding the default uid when creating a new account with
+.Ar useradd .
+To automatically allocate the uid to a new user with
.Ar useradd ,
-then you should
+then do
.Em not
use the
.Fl u
option.
-You may also provide either the account or userid immediately after the
+Either the account or userid can also be provided immediately after the
.Ar useradd ,
.Ar userdel ,
.Ar usermod
@@ -372,21 +371,23 @@ options.
.El
.Bl -tag -width "-G grouplist"
.It Fl c Ar comment
-This field sets the contents of the passwd GECOS field, which normally contains up
-to four comma-separated fields containing the user's full name, office or location,
+This field sets the contents of the passwd GECOS field,
+which normally contains up to four comma-separated fields containing the
+user's full name, office or location,
and work and home phone numbers.
These sub-fields are used by convention only, however, and are optional.
-If this field is to contain spaces, you need to quote the comment itself with double
-quotes
+If this field is to contain spaces,
+the comment must be enclosed in double quotes
.Ql \&" .
-Avoid using commas in this field as these are used as sub-field separators, and the
-colon
+Avoid using commas in this field as these are used as sub-field separators,
+and the colon
.Ql \&:
character also cannot be used as this is the field separator for the passwd
file itself.
.It Fl d Ar dir
This option sets the account's home directory.
-Normally, you will only use this if the home directory is to be different from the
+Normally,
+this is only used if the home directory is to be different from the
default determined from
.Pa /etc/pw.conf
- normally
@@ -396,13 +397,15 @@ with the account name as a subdirectory.
Set the account's expiration date.
Format of the date is either a UNIX time in decimal, or a date in
.Ql dd-mmm-yy[yy]
-format, where dd is the day, mmm is the month, either in numeric or alphabetic format
+format, where dd is the day,
+mmm is the month, either in numeric or alphabetic format
('Jan', 'Feb', etc) and year is either a two or four digit year.
This option also accepts a relative date in the form
.Ql \&+n[mhdwoy]
where
.Ql \&n
-is a decimal, octal (leading 0) or hexadecimal (leading 0x) digit followed by the
+is a decimal,
+octal (leading 0) or hexadecimal (leading 0x) digit followed by the
number of Minutes, Hours, Days, Weeks, Months or Years from the current date at
which the expiration date is to be set.
.It Fl p Ar date
@@ -442,8 +445,8 @@ This option instructs
to attempt to create the user's home directory.
While primarily useful when adding a new account with
.Ar useradd ,
-this may also be of use when moving an existing user's home directory elsewhere on
-the file system.
+this may also be of use when moving an existing user's home directory elsewhere
+on the file system.
The new home directory is populated with the contents of the
.Ar skeleton
directory, which typically contains a set of shell configuration files that the
@@ -461,7 +464,8 @@ existing configuration files in the user's home directory are
.Em not
overwritten from the skeleton files.
.Pp
-When a user's home directory is created, it will by default be a subdirectory of the
+When a user's home directory is created,
+it will by default be a subdirectory of the
.Ar basehome
directory as specified by the
.Fl b
@@ -599,10 +603,13 @@ The default value for this is
but it may be set elsewhere as desired.
.It Fl e Ar days
Set the default account expiration period in days.
-Unlike use without
-.Fl D ,
-the argument must be numeric, which specifies the number of days after creation when
-the account is to expire.
+When
+.Fl D
+is used, the
+.Ar days
+argument is interpreted differently.
+It must be numeric and represents the number of days after creation
+that the account expires.
A value of 0 suppresses automatic calculation of the expiry date.
.It Fl p Ar days
Set the default password expiration period in days.
@@ -615,8 +622,8 @@ with the same name as their login name.
If a group is supplied, either its name or uid may be given as an argument.
.It Fl G Ar grouplist
Set the default groups in which new users are granted membership.
-This is a separate set of groups from the primary group, and you should avoid
-nominating the same group as both primary and extra groups.
+This is a separate set of groups from the primary group.
+Avoid nominating the same group as both primary and extra groups.
In other words, these extra groups determine membership in groups
.Em other than
the primary group.
@@ -630,7 +637,8 @@ This option sets the default login class for new users.
.It Fl k Ar dir
Set the default
.Em skeleton
-directory, from which prototype shell and other initialization files are copied when
+directory,
+from which prototype shell and other initialization files are copied when
.Nm
creates a user's home directory.
See description of
@@ -640,22 +648,24 @@ for naming conventions of these files.
.Fl u Ar min , Ns Ar max ,
.Fl i Ar min , Ns Ar max
.Xc
-These options set the minimum and maximum user and group ids allocated for new accounts
-and groups created by
+Set the minimum and maximum user and group ids allocated for new
+accounts and groups created by
.Nm .
The default values for each is 1000 minimum and 32000 maximum.
.Ar min
and
.Ar max
-are both numbers, where max must be greater than min, and both must be between 0
-and 32767.
-In general, user and group ids less than 100 are reserved for use by the system,
-and numbers greater than 32000 may also be reserved for special purposes (used by
-some system daemons).
+are both numbers, where max must be greater than min,
+and both must be between 0 and 32767.
+In general,
+user and group ids less than 100 are reserved for use by the system,
+and numbers greater than 32000 may also be reserved for special purposes
+.Pq used by some system daemons .
.It Fl w Ar method
The
.Fl w
-option sets the default method used to set passwords for newly created user accounts.
+option selects the default method used to set passwords for newly created user
+accounts.
.Ar method
is one of:
.Pp
@@ -676,9 +686,11 @@ or
.Ql \&no
methods are the most secure; in the former case,
.Nm
-generates a password and prints it to stdout, which is suitable where you issue
-users with passwords to access their accounts rather than having the user nominate
-their own (possibly poorly chosen) password.
+generates a password and prints it to stdout,
+which is suitable when users are issued passwords rather than being allowed
+to select their own
+.Pq possibly poorly chosen
+password.
The
.Ql \&no
method requires that the superuser use
@@ -699,7 +711,7 @@ servers.
.Pp
The
.Ar userdel
-command has only three valid options.
+command has three distinct options.
The
.Fl n Ar name
and
@@ -714,7 +726,8 @@ to remove the user's home directory and all of its contents.
The
.Nm
utility errs on the side of caution when removing files from the system.
-Firstly, it will not do so if the uid of the account being removed is also used by
+Firstly,
+it will not do so if the uid of the account being removed is also used by
another account on the system, and the 'home' directory in the password file is
a valid path that commences with the character
.Ql \&/ .
@@ -725,20 +738,20 @@ will be removed.
If any additional cleanup work is required, this is left to the administrator.
.El
.Pp
-Mail spool files and crontabs are always removed when an account is deleted as these
-are unconditionally attached to the user name.
+Mail spool files and crontabs are always removed when an account is deleted as
+these are unconditionally attached to the user name.
Jobs queued for processing by
.Ar at
-are also removed if the user's uid is unique and not also used by another account on the
-system.
+are also removed if the user's uid is unique and not also used by another
+account on the system.
.Pp
The
.Ar usermod
command adds one additional option:
.Bl -tag -width "-G grouplist"
-.It Fl l Ar name
+.It Fl l Ar newname
This option allows changing of an existing account name to
-.Ql \&name .
+.Ql \&newname .
The new name must not already exist, and any attempt to duplicate an
existing account name will be rejected.
.El
@@ -782,10 +795,24 @@ options (explained at the start of the previous section) are available
with the group manipulation commands.
Other common options to all group-related commands are:
.Bl -tag -width "-m newmembers"
-.It Fl n Ar name
+.It Oo Fl n Oc Ar name
+Required unless
+.Fl g Ar gid
+is given.
Specify the group name.
+In the case of
+.Ar groupmod
+can be a gid.
.It Fl g Ar gid
+Required if
+.Ar name
+is not given.
Specify the group numeric id.
+In the case of
+.Ar groupmod
+if paired with
+.Ar name ,
+changes the numeric id of the named group.
.Pp
As with the account name and id fields, you will usually only need
to supply one of these, as the group name implies the uid and vice
@@ -822,18 +849,19 @@ silently eliminated.
also has a
.Fl o
option that allows allocation of an existing group id to a new group.
-The default action is to reject an attempt to add a group, and this option overrides
-the check for duplicate group ids.
+The default action is to reject an attempt to add a group,
+and this option overrides the check for duplicate group ids.
There is rarely any need to duplicate a group id.
.Pp
The
.Ar groupmod
command adds one additional option:
.Bl -tag -width "-m newmembers"
-.It Fl l Ar name
+.It Fl l Ar newname
This option allows changing of an existing group name to
-.Ql \&name .
-The new name must not already exist, and any attempt to duplicate an existing group
+.Ql \&newname .
+The new name must not already exist,
+and any attempt to duplicate an existing group
name will be rejected.
.El
.Pp
diff --git a/usr.sbin/pw/pw.c b/usr.sbin/pw/pw.c
index 5ad2511..1f42101 100644
--- a/usr.sbin/pw/pw.c
+++ b/usr.sbin/pw/pw.c
@@ -32,14 +32,12 @@ static const char rcsid[] =
#include <err.h>
#include <fcntl.h>
#include <locale.h>
-#include <paths.h>
-#include <stdbool.h>
-#include <sys/wait.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
#include "pw.h"
-#if !defined(_PATH_YP)
-#define _PATH_YP "/var/yp/"
-#endif
const char *Modes[] = {
"add", "del", "mod", "show", "next",
NULL};
@@ -85,55 +83,39 @@ struct pwf VPWF =
vgetgrnam,
};
-struct pwconf conf;
-
-static struct cargs arglist;
+static int (*cmdfunc[W_NUM][M_NUM])(int argc, char **argv, char *_name) = {
+ { /* user */
+ pw_user_add,
+ pw_user_del,
+ pw_user_mod,
+ pw_user_show,
+ pw_user_next,
+ pw_user_lock,
+ pw_user_unlock,
+ },
+ { /* group */
+ pw_group_add,
+ pw_group_del,
+ pw_group_mod,
+ pw_group_show,
+ pw_group_next,
+ }
+};
-static int getindex(const char *words[], const char *word);
-static void cmdhelp(int mode, int which);
+struct pwconf conf;
+static int getindex(const char *words[], const char *word);
+static void cmdhelp(int mode, int which);
int
main(int argc, char *argv[])
{
- int ch;
- int mode = -1;
- int which = -1;
- long id = -1;
- char *config = NULL;
+ int mode = -1, which = -1, tmp;
struct stat st;
- const char *errstr;
- char arg, *name;
+ char arg, *arg1;
bool relocated, nis;
- static const char *opts[W_NUM][M_NUM] =
- {
- { /* user */
- "R:V:C:qn:u:c:d:e:p:g:G:mM:k:s:oL:i:w:h:H:Db:NPy:Y",
- "R:V:C:qn:u:rY",
- "R:V:C:qn:u:c:d:e:p:g:G:mM:l:k:s:w:L:h:H:FNPY",
- "R:V:C:qn:u:FPa7",
- "R:V:C:q",
- "R:V:C:q",
- "R:V:C:q"
- },
- { /* grp */
- "R:V:C:qn:g:h:H:M:opNPY",
- "R:V:C:qn:g:Y",
- "R:V:C:qn:d:g:l:h:H:FM:m:NPY",
- "R:V:C:qn:g:FPa",
- "R:V:C:q"
- }
- };
-
- static int (*funcs[W_NUM]) (int _mode, char *_name, long _id,
- struct cargs * _args) =
- { /* Request handlers */
- pw_user,
- pw_group
- };
-
- name = NULL;
+ arg1 = NULL;
relocated = nis = false;
memset(&conf, 0, sizeof(conf));
strlcpy(conf.rootdir, "/", sizeof(conf.rootdir));
@@ -141,17 +123,13 @@ main(int argc, char *argv[])
conf.fd = -1;
conf.checkduplicate = true;
- LIST_INIT(&arglist);
-
- (void)setlocale(LC_ALL, "");
+ setlocale(LC_ALL, "");
/*
* Break off the first couple of words to determine what exactly
* we're being asked to do
*/
while (argc > 1) {
- int tmp;
-
if (*argv[1] == '-') {
/*
* Special case, allow pw -V<dir> <operation> [args] for scripts etc.
@@ -197,15 +175,9 @@ main(int argc, char *argv[])
mode = tmp % M_NUM;
} else if (strcmp(argv[1], "help") == 0 && argv[2] == NULL)
cmdhelp(mode, which);
- else if (which != -1 && mode != -1) {
- if (strspn(argv[1], "0123456789") == strlen(argv[1])) {
- id = strtonum(argv[1], 0, LONG_MAX, &errstr);
- if (errstr != NULL)
- errx(EX_USAGE, "Bad id '%s': %s",
- argv[1], errstr);
- } else
- name = argv[1];
- } else
+ else if (which != -1 && mode != -1)
+ arg1 = argv[1];
+ else
errx(EX_USAGE, "unknown keyword `%s'", argv[1]);
++argv;
--argc;
@@ -220,200 +192,22 @@ main(int argc, char *argv[])
conf.rootfd = open(conf.rootdir, O_DIRECTORY|O_CLOEXEC);
if (conf.rootfd == -1)
errx(EXIT_FAILURE, "Unable to open '%s'", conf.rootdir);
- conf.which = which;
- /*
- * We know which mode we're in and what we're about to do, so now
- * let's dispatch the remaining command line args in a genric way.
- */
- optarg = NULL;
-
- while ((ch = getopt(argc, argv, opts[which][mode])) != -1) {
- switch (ch) {
- case '?':
- errx(EX_USAGE, "unknown switch");
- break;
- case '7':
- conf.v7 = true;
- break;
- case 'C':
- conf.config = optarg;
- config = conf.config;
- break;
- case 'F':
- conf.force = true;
- break;
- case 'N':
- conf.dryrun = true;
- break;
- case 'l':
- if (strlen(optarg) >= MAXLOGNAME)
- errx(EX_USAGE, "new name too long: %s", optarg);
- conf.newname = optarg;
- break;
- case 'P':
- conf.pretty = true;
- break;
- case 'Y':
- nis = true;
- break;
- case 'a':
- conf.all = true;
- break;
- case 'c':
- conf.gecos = pw_checkname(optarg, 1);
- break;
- case 'g':
- if (which == 0) { /* for user* */
- addarg(&arglist, 'g', optarg);
- break;
- }
- if (strspn(optarg, "0123456789") != strlen(optarg))
- errx(EX_USAGE, "-g expects a number");
- id = strtonum(optarg, 0, LONG_MAX, &errstr);
- if (errstr != NULL)
- errx(EX_USAGE, "Bad id '%s': %s", optarg,
- errstr);
- break;
- case 'u':
- if (strspn(optarg, "0123456789,") != strlen(optarg))
- errx(EX_USAGE, "-u expects a number");
- if (strchr(optarg, ',') != NULL) {
- addarg(&arglist, 'u', optarg);
- break;
- }
- id = strtonum(optarg, 0, LONG_MAX, &errstr);
- if (errstr != NULL)
- errx(EX_USAGE, "Bad id '%s': %s", optarg,
- errstr);
- break;
- case 'n':
- if (strspn(optarg, "0123456789") != strlen(optarg)) {
- name = optarg;
- break;
- }
- id = strtonum(optarg, 0, LONG_MAX, &errstr);
- if (errstr != NULL)
- errx(EX_USAGE, "Bad id '%s': %s", optarg,
- errstr);
- break;
- case 'H':
- if (conf.fd != -1)
- errx(EX_USAGE, "'-h' and '-H' are mutually "
- "exclusive options");
- conf.precrypted = true;
- if (strspn(optarg, "0123456789") != strlen(optarg))
- errx(EX_USAGE, "'-H' expects a file descriptor");
-
- conf.fd = strtonum(optarg, 0, INT_MAX, &errstr);
- if (errstr != NULL)
- errx(EX_USAGE, "Bad file descriptor '%s': %s",
- optarg, errstr);
- break;
- case 'h':
- if (conf.fd != -1)
- errx(EX_USAGE, "'-h' and '-H' are mutually "
- "exclusive options");
- if (strcmp(optarg, "-") == 0)
- conf.fd = '-';
- else if (strspn(optarg, "0123456789") == strlen(optarg)) {
- conf.fd = strtonum(optarg, 0, INT_MAX, &errstr);
- if (errstr != NULL)
- errx(EX_USAGE, "'-h' expects a "
- "file descriptor or '-'");
- } else
- errx(EX_USAGE, "'-h' expects a file "
- "descriptor or '-'");
- break;
- case 'o':
- conf.checkduplicate = false;
- break;
- case 'q':
- conf.quiet = true;
- break;
- case 'r':
- conf.deletehome = true;
- break;
- default:
- addarg(&arglist, ch, optarg);
- break;
- }
- optarg = NULL;
- }
-
- if (name != NULL && strlen(name) >= MAXLOGNAME)
- errx(EX_USAGE, "name too long: %s", name);
-
- /*
- * Must be root to attempt an update
- */
- if (geteuid() != 0 && mode != M_PRINT && mode != M_NEXT && !conf.dryrun)
- errx(EX_NOPERM, "you must be root to run this program");
-
- /*
- * We should immediately look for the -q 'quiet' switch so that we
- * don't bother with extraneous errors
- */
- if (conf.quiet)
- freopen(_PATH_DEVNULL, "w", stderr);
-
- /*
- * Set our base working path if not overridden
- */
-
- if (config == NULL) { /* Only override config location if -C not specified */
- asprintf(&config, "%s/pw.conf", conf.etcpath);
- if (config == NULL)
- errx(EX_OSERR, "out of memory");
- }
-
- /*
- * Now, let's do the common initialisation
- */
- conf.userconf = read_userconfig(config);
-
- ch = funcs[which] (mode, name, id, &arglist);
-
- /*
- * If everything went ok, and we've been asked to update
- * the NIS maps, then do it now
- */
- if (ch == EXIT_SUCCESS && nis) {
- pid_t pid;
-
- fflush(NULL);
- if (chdir(_PATH_YP) == -1)
- warn("chdir(" _PATH_YP ")");
- else if ((pid = fork()) == -1)
- warn("fork()");
- else if (pid == 0) {
- /* Is make anywhere else? */
- execlp("/usr/bin/make", "make", (char *)NULL);
- _exit(1);
- } else {
- int i;
- waitpid(pid, &i, 0);
- if ((i = WEXITSTATUS(i)) != 0)
- errx(ch, "make exited with status %d", i);
- else
- pw_log(conf.userconf, mode, which, "NIS maps updated");
- }
- }
- return ch;
+ return (cmdfunc[which][mode](argc, argv, arg1));
}
static int
getindex(const char *words[], const char *word)
{
- int i = 0;
+ int i = 0;
while (words[i]) {
if (strcmp(words[i], word) == 0)
- return i;
+ return (i);
i++;
}
- return -1;
+ return (-1);
}
@@ -463,7 +257,7 @@ cmdhelp(int mode, int which)
" Setting defaults:\n"
"\t-V etcdir alternate /etc location\n"
"\t-R rootir alternate root directory\n"
- "\t-D set user defaults\n"
+ "\t-D set user defaults\n"
"\t-b dir default home root dir\n"
"\t-e period default expiry period\n"
"\t-p period default password change period\n"
@@ -483,6 +277,7 @@ cmdhelp(int mode, int which)
"\t-n name login name\n"
"\t-u uid user id\n"
"\t-Y update NIS maps\n"
+ "\t-y path set NIS passwd file path\n"
"\t-r remove home & contents\n",
"usage: pw usermod [uid|name] [switches]\n"
"\t-V etcdir alternate /etc location\n"
@@ -507,6 +302,7 @@ cmdhelp(int mode, int which)
"\t-h fd read password on fd\n"
"\t-H fd read encrypted password on fd\n"
"\t-Y update NIS maps\n"
+ "\t-y path set NIS passwd file path\n"
"\t-N no update\n",
"usage: pw usershow [uid|name] [switches]\n"
"\t-V etcdir alternate /etc location\n"
@@ -583,31 +379,3 @@ cmdhelp(int mode, int which)
}
exit(EXIT_FAILURE);
}
-
-struct carg *
-getarg(struct cargs * _args, int ch)
-{
- struct carg *c;
-
- if (_args == NULL)
- return (NULL);
-
- c = LIST_FIRST(_args);
-
- while (c != NULL && c->ch != ch)
- c = LIST_NEXT(c, list);
- return c;
-}
-
-struct carg *
-addarg(struct cargs * _args, int ch, char *argstr)
-{
- struct carg *ca = malloc(sizeof(struct carg));
-
- if (ca == NULL)
- errx(EX_OSERR, "out of memory");
- ca->ch = ch;
- ca->val = argstr;
- LIST_INSERT_HEAD(_args, ca, list);
- return ca;
-}
diff --git a/usr.sbin/pw/pw.h b/usr.sbin/pw/pw.h
index ed3b715..b389f12 100644
--- a/usr.sbin/pw/pw.h
+++ b/usr.sbin/pw/pw.h
@@ -26,22 +26,13 @@
* $FreeBSD$
*/
+#include <sys/stat.h>
+
#define _WITH_GETLINE
+#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/queue.h>
-#include <sysexits.h>
-#include "psdate.h"
#include "pwupd.h"
enum _mode
@@ -63,35 +54,44 @@ enum _which
W_NUM
};
-struct carg
-{
- int ch;
- char *val;
- LIST_ENTRY(carg) list;
-};
-
-LIST_HEAD(cargs, carg);
-
#define _DEF_DIRMODE (S_IRWXU | S_IRWXG | S_IRWXO)
#define _PATH_PW_CONF "/etc/pw.conf"
#define _UC_MAXLINE 1024
#define _UC_MAXSHELLS 32
+struct userconf *get_userconfig(const char *cfg);
struct userconf *read_userconfig(char const * file);
-int write_userconfig(char const * file);
-struct carg *addarg(struct cargs * _args, int ch, char *argstr);
-struct carg *getarg(struct cargs * _args, int ch);
+int write_userconfig(struct userconf *cnf, char const * file);
-int pw_user(int mode, char *name, long id, struct cargs * _args);
-int pw_usernext(struct userconf *cnf, bool quiet);
-int pw_group(int mode, char *name, long id, struct cargs * _args);
+int pw_group_add(int argc, char **argv, char *name);
+int pw_group_del(int argc, char **argv, char *name);
+int pw_group_mod(int argc, char **argv, char *name);
+int pw_group_next(int argc, char **argv, char *name);
+int pw_group_show(int argc, char **argv, char *name);
+int pw_user_add(int argc, char **argv, char *name);
+int pw_user_add(int argc, char **argv, char *name);
+int pw_user_add(int argc, char **argv, char *name);
+int pw_user_add(int argc, char **argv, char *name);
+int pw_user_del(int argc, char **argv, char *name);
+int pw_user_lock(int argc, char **argv, char *name);
+int pw_user_mod(int argc, char **argv, char *name);
+int pw_user_next(int argc, char **argv, char *name);
+int pw_user_show(int argc, char **argv, char *name);
+int pw_user_unlock(int argc, char **argv, char *name);
int pw_groupnext(struct userconf *cnf, bool quiet);
char *pw_checkname(char *name, int gecos);
+uintmax_t pw_checkid(char *nptr, uintmax_t maxval);
+int pw_checkfd(char *nptr);
int addnispwent(const char *path, struct passwd *pwd);
int delnispwent(const char *path, const char *login);
int chgnispwent(const char *path, const char *login, struct passwd *pwd);
+int groupadd(struct userconf *, char *name, gid_t id, char *members, int fd,
+ bool dryrun, bool pretty, bool precrypted);
+
+int nis_update(void);
+
int boolean_val(char const * str, int dflt);
char const *boolean_str(int val);
char *newstr(char const * p);
@@ -101,3 +101,6 @@ char *pw_pwcrypt(char *password);
extern const char *Modes[];
extern const char *Which[];
+
+uintmax_t strtounum(const char * __restrict, uintmax_t, uintmax_t,
+ const char ** __restrict);
diff --git a/usr.sbin/pw/pw_conf.c b/usr.sbin/pw/pw_conf.c
index 33bb6b3..e9606b4 100644
--- a/usr.sbin/pw/pw_conf.c
+++ b/usr.sbin/pw/pw_conf.c
@@ -31,10 +31,11 @@ static const char rcsid[] =
#include <sys/types.h>
#include <sys/sbuf.h>
-#include <string.h>
-#include <ctype.h>
-#include <fcntl.h>
+
#include <err.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
#include "pw.h"
@@ -227,15 +228,13 @@ read_userconfig(char const * file)
{
FILE *fp;
char *buf, *p;
+ const char *errstr;
size_t linecap;
ssize_t linelen;
buf = NULL;
linecap = 0;
- config.groups = sl_init();
- if (config.groups == NULL)
- err(1, "sl_init()");
if (file == NULL)
file = _PATH_PW_CONF;
@@ -314,36 +313,69 @@ read_userconfig(char const * file)
? NULL : newstr(q);
break;
case _UC_EXTRAGROUPS:
- for (i = 0; q != NULL; q = strtok(NULL, toks))
+ for (i = 0; q != NULL; q = strtok(NULL, toks)) {
+ if (config.groups == NULL)
+ config.groups = sl_init();
sl_add(config.groups, newstr(q));
+ }
break;
case _UC_DEFAULTCLASS:
config.default_class = (q == NULL || !boolean_val(q, 1))
? NULL : newstr(q);
break;
case _UC_MINUID:
- if ((q = unquote(q)) != NULL && isdigit(*q))
- config.min_uid = (uid_t) atol(q);
+ if ((q = unquote(q)) != NULL) {
+ config.min_uid = strtounum(q, 0,
+ UID_MAX, &errstr);
+ if (errstr)
+ warnx("Invalid min_uid: '%s';"
+ " ignoring", q);
+ }
break;
case _UC_MAXUID:
- if ((q = unquote(q)) != NULL && isdigit(*q))
- config.max_uid = (uid_t) atol(q);
+ if ((q = unquote(q)) != NULL) {
+ config.max_uid = strtounum(q, 0,
+ UID_MAX, &errstr);
+ if (errstr)
+ warnx("Invalid max_uid: '%s';"
+ " ignoring", q);
+ }
break;
case _UC_MINGID:
- if ((q = unquote(q)) != NULL && isdigit(*q))
- config.min_gid = (gid_t) atol(q);
+ if ((q = unquote(q)) != NULL) {
+ config.min_gid = strtounum(q, 0,
+ GID_MAX, &errstr);
+ if (errstr)
+ warnx("Invalid min_gid: '%s';"
+ " ignoring", q);
+ }
break;
case _UC_MAXGID:
- if ((q = unquote(q)) != NULL && isdigit(*q))
- config.max_gid = (gid_t) atol(q);
+ if ((q = unquote(q)) != NULL) {
+ config.max_gid = strtounum(q, 0,
+ GID_MAX, &errstr);
+ if (errstr)
+ warnx("Invalid max_gid: '%s';"
+ " ignoring", q);
+ }
break;
case _UC_EXPIRE:
- if ((q = unquote(q)) != NULL && isdigit(*q))
- config.expire_days = atoi(q);
+ if ((q = unquote(q)) != NULL) {
+ config.expire_days = strtonum(q, 0,
+ INT_MAX, &errstr);
+ if (errstr)
+ warnx("Invalid expire days:"
+ " '%s'; ignoring", q);
+ }
break;
case _UC_PASSWORD:
- if ((q = unquote(q)) != NULL && isdigit(*q))
- config.password_days = atoi(q);
+ if ((q = unquote(q)) != NULL) {
+ config.password_days = strtonum(q, 0,
+ INT_MAX, &errstr);
+ if (errstr)
+ warnx("Invalid password days:"
+ " '%s'; ignoring", q);
+ }
break;
case _UC_FIELDS:
case _UC_NONE:
@@ -359,7 +391,7 @@ read_userconfig(char const * file)
int
-write_userconfig(char const * file)
+write_userconfig(struct userconf *cnf, const char *file)
{
int fd;
int i, j;
@@ -384,40 +416,39 @@ write_userconfig(char const * file)
sbuf_clear(buf);
switch (i) {
case _UC_DEFAULTPWD:
- sbuf_cat(buf, boolean_str(config.default_password));
+ sbuf_cat(buf, boolean_str(cnf->default_password));
break;
case _UC_REUSEUID:
- sbuf_cat(buf, boolean_str(config.reuse_uids));
+ sbuf_cat(buf, boolean_str(cnf->reuse_uids));
break;
case _UC_REUSEGID:
- sbuf_cat(buf, boolean_str(config.reuse_gids));
+ sbuf_cat(buf, boolean_str(cnf->reuse_gids));
break;
case _UC_NISPASSWD:
- sbuf_cat(buf, config.nispasswd ? config.nispasswd :
- "");
+ sbuf_cat(buf, cnf->nispasswd ? cnf->nispasswd : "");
quote = 0;
break;
case _UC_DOTDIR:
- sbuf_cat(buf, config.dotdir ? config.dotdir :
+ sbuf_cat(buf, cnf->dotdir ? cnf->dotdir :
boolean_str(0));
break;
case _UC_NEWMAIL:
- sbuf_cat(buf, config.newmail ? config.newmail :
+ sbuf_cat(buf, cnf->newmail ? cnf->newmail :
boolean_str(0));
break;
case _UC_LOGFILE:
- sbuf_cat(buf, config.logfile ? config.logfile :
+ sbuf_cat(buf, cnf->logfile ? cnf->logfile :
boolean_str(0));
break;
case _UC_HOMEROOT:
- sbuf_cat(buf, config.home);
+ sbuf_cat(buf, cnf->home);
break;
case _UC_HOMEMODE:
- sbuf_printf(buf, "%04o", config.homemode);
+ sbuf_printf(buf, "%04o", cnf->homemode);
quote = 0;
break;
case _UC_SHELLPATH:
- sbuf_cat(buf, config.shelldir);
+ sbuf_cat(buf, cnf->shelldir);
break;
case _UC_SHELLS:
for (j = 0; j < _UC_MAXSHELLS &&
@@ -427,46 +458,46 @@ write_userconfig(char const * file)
quote = 0;
break;
case _UC_DEFAULTSHELL:
- sbuf_cat(buf, config.shell_default ?
- config.shell_default : bourne_shell);
+ sbuf_cat(buf, cnf->shell_default ?
+ cnf->shell_default : bourne_shell);
break;
case _UC_DEFAULTGROUP:
- sbuf_cat(buf, config.default_group ?
- config.default_group : "");
+ sbuf_cat(buf, cnf->default_group ?
+ cnf->default_group : "");
break;
case _UC_EXTRAGROUPS:
- for (j = 0; config.groups != NULL &&
- j < (int)config.groups->sl_cur; j++)
+ for (j = 0; cnf->groups != NULL &&
+ j < (int)cnf->groups->sl_cur; j++)
sbuf_printf(buf, "%s\"%s\"", j ?
- "," : "", config.groups->sl_str[j]);
+ "," : "", cnf->groups->sl_str[j]);
quote = 0;
break;
case _UC_DEFAULTCLASS:
- sbuf_cat(buf, config.default_class ?
- config.default_class : "");
+ sbuf_cat(buf, cnf->default_class ?
+ cnf->default_class : "");
break;
case _UC_MINUID:
- sbuf_printf(buf, "%u", config.min_uid);
+ sbuf_printf(buf, "%ju", (uintmax_t)cnf->min_uid);
quote = 0;
break;
case _UC_MAXUID:
- sbuf_printf(buf, "%u", config.max_uid);
+ sbuf_printf(buf, "%ju", (uintmax_t)cnf->max_uid);
quote = 0;
break;
case _UC_MINGID:
- sbuf_printf(buf, "%u", config.min_gid);
+ sbuf_printf(buf, "%ju", (uintmax_t)cnf->min_gid);
quote = 0;
break;
case _UC_MAXGID:
- sbuf_printf(buf, "%u", config.max_gid);
+ sbuf_printf(buf, "%ju", (uintmax_t)cnf->max_gid);
quote = 0;
break;
case _UC_EXPIRE:
- sbuf_printf(buf, "%d", config.expire_days);
+ sbuf_printf(buf, "%jd", (intmax_t)cnf->expire_days);
quote = 0;
break;
case _UC_PASSWORD:
- sbuf_printf(buf, "%d", config.password_days);
+ sbuf_printf(buf, "%jd", (intmax_t)cnf->password_days);
quote = 0;
break;
case _UC_NONE:
diff --git a/usr.sbin/pw/pw_group.c b/usr.sbin/pw/pw_group.c
index b0db3cf..711ef68 100644
--- a/usr.sbin/pw/pw_group.c
+++ b/usr.sbin/pw/pw_group.c
@@ -31,46 +31,50 @@ static const char rcsid[] =
#include <ctype.h>
#include <err.h>
-#include <termios.h>
-#include <stdbool.h>
-#include <unistd.h>
#include <grp.h>
#include <libutil.h>
+#include <paths.h>
+#include <string.h>
+#include <sysexits.h>
+#include <termios.h>
+#include <unistd.h>
#include "pw.h"
#include "bitmap.h"
-
static struct passwd *lookup_pwent(const char *user);
static void delete_members(struct group *grp, char *list);
-static int print_group(struct group * grp);
-static gid_t gr_gidpolicy(struct userconf * cnf, long id);
+static int print_group(struct group * grp, bool pretty);
+static gid_t gr_gidpolicy(struct userconf * cnf, intmax_t id);
static void
-set_passwd(struct group *grp, bool update)
+grp_set_passwd(struct group *grp, bool update, int fd, bool precrypted)
{
int b;
int istty;
struct termios t, n;
char *p, line[256];
- if (conf.fd == '-') {
+ if (fd == -1)
+ return;
+
+ if (fd == '-') {
grp->gr_passwd = "*"; /* No access */
return;
}
- if ((istty = isatty(conf.fd))) {
+ if ((istty = isatty(fd))) {
n = t;
/* Disable echo */
n.c_lflag &= ~(ECHO);
- tcsetattr(conf.fd, TCSANOW, &n);
+ tcsetattr(fd, TCSANOW, &n);
printf("%sassword for group %s:", update ? "New p" : "P",
grp->gr_name);
fflush(stdout);
}
- b = read(conf.fd, line, sizeof(line) - 1);
+ b = read(fd, line, sizeof(line) - 1);
if (istty) { /* Restore state */
- tcsetattr(conf.fd, TCSANOW, &t);
+ tcsetattr(fd, TCSANOW, &t);
fputc('\n', stdout);
fflush(stdout);
}
@@ -82,7 +86,7 @@ set_passwd(struct group *grp, bool update)
if (!*line)
errx(EX_DATAERR, "empty password read on file descriptor %d",
conf.fd);
- if (conf.precrypted) {
+ if (precrypted) {
if (strchr(line, ':') != 0)
errx(EX_DATAERR, "wrong encrypted passwrd");
grp->gr_passwd = line;
@@ -97,198 +101,29 @@ pw_groupnext(struct userconf *cnf, bool quiet)
if (quiet)
return (next);
- printf("%u\n", next);
+ printf("%ju\n", (uintmax_t)next);
return (EXIT_SUCCESS);
}
-static int
-pw_groupshow(const char *name, long id, struct group *fakegroup)
+static struct group *
+getgroup(char *name, intmax_t id, bool fatal)
{
- struct group *grp = NULL;
-
- if (id < 0 && name == NULL && !conf.all)
- errx(EX_DATAERR, "groupname or id or '-a' required");
-
- if (conf.all) {
- SETGRENT();
- while ((grp = GETGRENT()) != NULL)
- print_group(grp);
- ENDGRENT();
-
- return (EXIT_SUCCESS);
- }
-
- grp = (name != NULL) ? GETGRNAM(name) : GETGRGID(id);
- if (grp == NULL) {
- if (conf.force) {
- grp = fakegroup;
- } else {
- if (name == NULL)
- errx(EX_DATAERR, "unknown gid `%ld'", id);
- errx(EX_DATAERR, "unknown group `%s'", name);
- }
- }
-
- return (print_group(grp));
-}
-
-static int
-pw_groupdel(const char *name, long id)
-{
- struct group *grp = NULL;
- int rc;
+ struct group *grp;
+ if (id < 0 && name == NULL)
+ errx(EX_DATAERR, "groupname or id required");
grp = (name != NULL) ? GETGRNAM(name) : GETGRGID(id);
if (grp == NULL) {
+ if (!fatal)
+ return (NULL);
if (name == NULL)
- errx(EX_DATAERR, "unknown gid `%ld'", id);
+ errx(EX_DATAERR, "unknown gid `%ju'", id);
errx(EX_DATAERR, "unknown group `%s'", name);
}
-
- rc = delgrent(grp);
- if (rc == -1)
- err(EX_IOERR, "group '%s' not available (NIS?)", name);
- else if (rc != 0)
- err(EX_IOERR, "group update");
- pw_log(conf.userconf, M_DELETE, W_GROUP, "%s(%ld) removed", name, id);
-
- return (EXIT_SUCCESS);
-}
-
-int
-pw_group(int mode, char *name, long id, struct cargs * args)
-{
- int rc;
- struct carg *arg;
- struct group *grp = NULL;
- struct userconf *cnf = conf.userconf;
-
- static struct group fakegroup =
- {
- "nogroup",
- "*",
- -1,
- NULL
- };
-
- if (mode == M_NEXT)
- return (pw_groupnext(cnf, conf.quiet));
-
- if (mode == M_PRINT)
- return (pw_groupshow(name, id, &fakegroup));
-
- if (mode == M_DELETE)
- return (pw_groupdel(name, id));
-
- if (mode == M_LOCK || mode == M_UNLOCK)
- errx(EX_USAGE, "'lock' command is not available for groups");
-
- if (id < 0 && name == NULL)
- errx(EX_DATAERR, "group name or id required");
-
- grp = (name != NULL) ? GETGRNAM(name) : GETGRGID(id);
-
- if (mode == M_UPDATE) {
- if (name == NULL && grp == NULL) /* Try harder */
- grp = GETGRGID(id);
-
- if (grp == NULL) {
- if (name == NULL)
- errx(EX_DATAERR, "unknown group `%s'", name);
- else
- errx(EX_DATAERR, "unknown group `%ld'", id);
- }
- if (name == NULL) /* Needed later */
- name = grp->gr_name;
-
- if (id > 0)
- grp->gr_gid = (gid_t) id;
-
- if (conf.newname != NULL)
- grp->gr_name = pw_checkname(conf.newname, 0);
- } else {
- if (name == NULL) /* Required */
- errx(EX_DATAERR, "group name required");
- else if (grp != NULL) /* Exists */
- errx(EX_DATAERR, "group name `%s' already exists", name);
-
- grp = &fakegroup;
- grp->gr_name = pw_checkname(name, 0);
- grp->gr_passwd = "*";
- grp->gr_gid = gr_gidpolicy(cnf, id);
- grp->gr_mem = NULL;
- }
-
- /*
- * This allows us to set a group password Group passwords is an
- * antique idea, rarely used and insecure (no secure database) Should
- * be discouraged, but it is apparently still supported by some
- * software.
- */
-
- if (conf.which == W_GROUP && conf.fd != -1)
- set_passwd(grp, mode == M_UPDATE);
-
- if (((arg = getarg(args, 'M')) != NULL ||
- (arg = getarg(args, 'd')) != NULL ||
- (arg = getarg(args, 'm')) != NULL) && arg->val) {
- char *p;
- struct passwd *pwd;
-
- /* Make sure this is not stay NULL with -M "" */
- if (arg->ch == 'd')
- delete_members(grp, arg->val);
- else if (arg->ch == 'M')
- grp->gr_mem = NULL;
-
- for (p = strtok(arg->val, ", \t"); arg->ch != 'd' && p != NULL;
- p = strtok(NULL, ", \t")) {
- int j;
-
- /*
- * Check for duplicates
- */
- pwd = lookup_pwent(p);
- for (j = 0; grp->gr_mem != NULL && grp->gr_mem[j] != NULL; j++) {
- if (strcmp(grp->gr_mem[j], pwd->pw_name) == 0)
- break;
- }
- if (grp->gr_mem != NULL && grp->gr_mem[j] != NULL)
- continue;
- grp = gr_add(grp, pwd->pw_name);
- }
- }
-
- if (conf.dryrun)
- return print_group(grp);
-
- if (mode == M_ADD && (rc = addgrent(grp)) != 0) {
- if (rc == -1)
- errx(EX_IOERR, "group '%s' already exists",
- grp->gr_name);
- else
- err(EX_IOERR, "group update");
- } else if (mode == M_UPDATE && (rc = chggrent(name, grp)) != 0) {
- if (rc == -1)
- errx(EX_IOERR, "group '%s' not available (NIS?)",
- grp->gr_name);
- else
- err(EX_IOERR, "group update");
- }
-
- if (conf.newname != NULL)
- name = conf.newname;
- /* grp may have been invalidated */
- if ((grp = GETGRNAM(name)) == NULL)
- errx(EX_SOFTWARE, "group disappeared during update");
-
- pw_log(cnf, mode, W_GROUP, "%s(%u)", grp->gr_name, grp->gr_gid);
-
- return EXIT_SUCCESS;
+ return (grp);
}
-
/*
* Lookup a passwd entry using a name or UID.
*/
@@ -331,11 +166,11 @@ delete_members(struct group *grp, char *list)
}
}
-
-static gid_t
-gr_gidpolicy(struct userconf * cnf, long id)
+static gid_t
+gr_gidpolicy(struct userconf * cnf, intmax_t id)
{
struct group *grp;
+ struct bitmap bm;
gid_t gid = (gid_t) - 1;
/*
@@ -345,67 +180,62 @@ gr_gidpolicy(struct userconf * cnf, long id)
gid = (gid_t) id;
if ((grp = GETGRGID(gid)) != NULL && conf.checkduplicate)
- errx(EX_DATAERR, "gid `%u' has already been allocated", grp->gr_gid);
- } else {
- struct bitmap bm;
-
- /*
- * We need to allocate the next available gid under one of
- * two policies a) Grab the first unused gid b) Grab the
- * highest possible unused gid
- */
- if (cnf->min_gid >= cnf->max_gid) { /* Sanity claus^H^H^H^Hheck */
- cnf->min_gid = 1000;
- cnf->max_gid = 32000;
- }
- bm = bm_alloc(cnf->max_gid - cnf->min_gid + 1);
+ errx(EX_DATAERR, "gid `%ju' has already been allocated",
+ (uintmax_t)grp->gr_gid);
+ return (gid);
+ }
- /*
- * Now, let's fill the bitmap from the password file
- */
- SETGRENT();
- while ((grp = GETGRENT()) != NULL)
- if ((gid_t)grp->gr_gid >= (gid_t)cnf->min_gid &&
- (gid_t)grp->gr_gid <= (gid_t)cnf->max_gid)
- bm_setbit(&bm, grp->gr_gid - cnf->min_gid);
- ENDGRENT();
+ /*
+ * We need to allocate the next available gid under one of
+ * two policies a) Grab the first unused gid b) Grab the
+ * highest possible unused gid
+ */
+ if (cnf->min_gid >= cnf->max_gid) { /* Sanity claus^H^H^H^Hheck */
+ cnf->min_gid = 1000;
+ cnf->max_gid = 32000;
+ }
+ bm = bm_alloc(cnf->max_gid - cnf->min_gid + 1);
- /*
- * Then apply the policy, with fallback to reuse if necessary
- */
- if (cnf->reuse_gids)
- gid = (gid_t) (bm_firstunset(&bm) + cnf->min_gid);
- else {
- gid = (gid_t) (bm_lastset(&bm) + 1);
- if (!bm_isset(&bm, gid))
- gid += cnf->min_gid;
- else
- gid = (gid_t) (bm_firstunset(&bm) + cnf->min_gid);
- }
+ /*
+ * Now, let's fill the bitmap from the password file
+ */
+ SETGRENT();
+ while ((grp = GETGRENT()) != NULL)
+ if ((gid_t)grp->gr_gid >= (gid_t)cnf->min_gid &&
+ (gid_t)grp->gr_gid <= (gid_t)cnf->max_gid)
+ bm_setbit(&bm, grp->gr_gid - cnf->min_gid);
+ ENDGRENT();
- /*
- * Another sanity check
- */
- if (gid < cnf->min_gid || gid > cnf->max_gid)
- errx(EX_SOFTWARE, "unable to allocate a new gid - range fully used");
- bm_dealloc(&bm);
+ /*
+ * Then apply the policy, with fallback to reuse if necessary
+ */
+ if (cnf->reuse_gids)
+ gid = (gid_t) (bm_firstunset(&bm) + cnf->min_gid);
+ else {
+ gid = (gid_t) (bm_lastset(&bm) + 1);
+ if (!bm_isset(&bm, gid))
+ gid += cnf->min_gid;
+ else
+ gid = (gid_t) (bm_firstunset(&bm) + cnf->min_gid);
}
- return gid;
-}
+ /*
+ * Another sanity check
+ */
+ if (gid < cnf->min_gid || gid > cnf->max_gid)
+ errx(EX_SOFTWARE, "unable to allocate a new gid - range fully "
+ "used");
+ bm_dealloc(&bm);
+ return (gid);
+}
static int
-print_group(struct group * grp)
+print_group(struct group * grp, bool pretty)
{
- if (!conf.pretty) {
- char *buf = NULL;
-
- buf = gr_make(grp);
- printf("%s\n", buf);
- free(buf);
- } else {
- int i;
+ char *buf = NULL;
+ int i;
+ if (pretty) {
printf("Group Name: %-15s #%lu\n"
" Members: ",
grp->gr_name, (long) grp->gr_gid);
@@ -414,6 +244,446 @@ print_group(struct group * grp)
printf("%s%s", i ? "," : "", grp->gr_mem[i]);
}
fputs("\n\n", stdout);
+ return (EXIT_SUCCESS);
+ }
+
+ buf = gr_make(grp);
+ printf("%s\n", buf);
+ free(buf);
+ return (EXIT_SUCCESS);
+}
+
+int
+pw_group_next(int argc, char **argv, char *arg1 __unused)
+{
+ struct userconf *cnf;
+ const char *cfg = NULL;
+ int ch;
+ bool quiet;
+
+ while ((ch = getopt(argc, argv, "Cq")) != -1) {
+ switch (ch) {
+ case 'C':
+ cfg = optarg;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ }
}
- return EXIT_SUCCESS;
+
+ if (quiet)
+ freopen(_PATH_DEVNULL, "w", stderr);
+ cnf = get_userconfig(cfg);
+ return (pw_groupnext(cnf, quiet));
+}
+
+int
+pw_group_show(int argc, char **argv, char *arg1)
+{
+ struct group *grp = NULL;
+ char *name;
+ intmax_t id = -1;
+ int ch;
+ bool all, force, quiet, pretty;
+
+ all = force = quiet = pretty = false;
+
+ struct group fakegroup = {
+ "nogroup",
+ "*",
+ -1,
+ NULL
+ };
+
+ if (arg1 != NULL) {
+ if (arg1[strspn(arg1, "0123456789")] == '\0')
+ id = pw_checkid(arg1, GID_MAX);
+ else
+ name = arg1;
+ }
+
+ while ((ch = getopt(argc, argv, "C:qn:g:FPa")) != -1) {
+ switch (ch) {
+ case 'C':
+ /* ignore compatibility */
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'n':
+ name = optarg;
+ break;
+ case 'g':
+ id = pw_checkid(optarg, GID_MAX);
+ break;
+ case 'F':
+ force = true;
+ break;
+ case 'P':
+ pretty = true;
+ break;
+ case 'a':
+ all = true;
+ break;
+ }
+ }
+
+ if (quiet)
+ freopen(_PATH_DEVNULL, "w", stderr);
+
+ if (all) {
+ SETGRENT();
+ while ((grp = GETGRENT()) != NULL)
+ print_group(grp, pretty);
+ ENDGRENT();
+ return (EXIT_SUCCESS);
+ }
+
+ grp = getgroup(name, id, !force);
+ if (grp == NULL)
+ grp = &fakegroup;
+
+ return (print_group(grp, pretty));
+}
+
+int
+pw_group_del(int argc, char **argv, char *arg1)
+{
+ struct userconf *cnf = NULL;
+ struct group *grp = NULL;
+ char *name;
+ const char *cfg = NULL;
+ intmax_t id = -1;
+ int ch, rc;
+ bool quiet = false;
+ bool nis = false;
+
+ if (arg1 != NULL) {
+ if (arg1[strspn(arg1, "0123456789")] == '\0')
+ id = pw_checkid(arg1, GID_MAX);
+ else
+ name = arg1;
+ }
+
+ while ((ch = getopt(argc, argv, "C:qn:g:Y")) != -1) {
+ switch (ch) {
+ case 'C':
+ cfg = optarg;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'n':
+ name = optarg;
+ break;
+ case 'g':
+ id = pw_checkid(optarg, GID_MAX);
+ break;
+ case 'Y':
+ nis = true;
+ break;
+ }
+ }
+
+ if (quiet)
+ freopen(_PATH_DEVNULL, "w", stderr);
+ grp = getgroup(name, id, true);
+ cnf = get_userconfig(cfg);
+ rc = delgrent(grp);
+ if (rc == -1)
+ err(EX_IOERR, "group '%s' not available (NIS?)", name);
+ else if (rc != 0)
+ err(EX_IOERR, "group update");
+ pw_log(cnf, M_DELETE, W_GROUP, "%s(%ju) removed", name,
+ (uintmax_t)id);
+
+ if (nis && nis_update() == 0)
+ pw_log(cnf, M_DELETE, W_GROUP, "NIS maps updated");
+
+ return (EXIT_SUCCESS);
+}
+
+static bool
+grp_has_member(struct group *grp, const char *name)
+{
+ int j;
+
+ for (j = 0; grp->gr_mem != NULL && grp->gr_mem[j] != NULL; j++)
+ if (strcmp(grp->gr_mem[j], name) == 0)
+ return (true);
+ return (false);
+}
+
+static void
+grp_add_members(struct group **grp, char *members)
+{
+ struct passwd *pwd;
+ char *p;
+ char tok[] = ", \t";
+
+ if (members == NULL)
+ return;
+ for (p = strtok(members, tok); p != NULL; p = strtok(NULL, tok)) {
+ pwd = lookup_pwent(p);
+ if (grp_has_member(*grp, pwd->pw_name))
+ continue;
+ *grp = gr_add(*grp, pwd->pw_name);
+ }
+}
+
+int
+groupadd(struct userconf *cnf, char *name, gid_t id, char *members, int fd,
+ bool dryrun, bool pretty, bool precrypted)
+{
+ struct group *grp;
+ int rc;
+
+ struct group fakegroup = {
+ "nogroup",
+ "*",
+ -1,
+ NULL
+ };
+
+ grp = &fakegroup;
+ grp->gr_name = pw_checkname(name, 0);
+ grp->gr_passwd = "*";
+ grp->gr_gid = gr_gidpolicy(cnf, id);
+ grp->gr_mem = NULL;
+
+ /*
+ * This allows us to set a group password Group passwords is an
+ * antique idea, rarely used and insecure (no secure database) Should
+ * be discouraged, but it is apparently still supported by some
+ * software.
+ */
+ grp_set_passwd(grp, false, fd, precrypted);
+ grp_add_members(&grp, members);
+ if (dryrun)
+ return (print_group(grp, pretty));
+
+ if ((rc = addgrent(grp)) != 0) {
+ if (rc == -1)
+ errx(EX_IOERR, "group '%s' already exists",
+ grp->gr_name);
+ else
+ err(EX_IOERR, "group update");
+ }
+
+ pw_log(cnf, M_ADD, W_GROUP, "%s(%ju)", grp->gr_name,
+ (uintmax_t)grp->gr_gid);
+
+ return (EXIT_SUCCESS);
+}
+
+int
+pw_group_add(int argc, char **argv, char *arg1)
+{
+ struct userconf *cnf = NULL;
+ char *name = NULL;
+ char *members = NULL;
+ const char *cfg = NULL;
+ intmax_t id = -1;
+ int ch, rc, fd = -1;
+ bool quiet, precrypted, dryrun, pretty, nis;
+
+ quiet = precrypted = dryrun = pretty = nis = false;
+
+ if (arg1 != NULL) {
+ if (arg1[strspn(arg1, "0123456789")] == '\0')
+ id = pw_checkid(arg1, GID_MAX);
+ else
+ name = arg1;
+ }
+
+ while ((ch = getopt(argc, argv, "C:qn:g:h:H:M:oNPY")) != -1) {
+ switch (ch) {
+ case 'C':
+ cfg = optarg;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'n':
+ name = optarg;
+ break;
+ case 'g':
+ id = pw_checkid(optarg, GID_MAX);
+ break;
+ case 'H':
+ if (fd != -1)
+ errx(EX_USAGE, "'-h' and '-H' are mutually "
+ "exclusive options");
+ fd = pw_checkfd(optarg);
+ precrypted = true;
+ if (fd == '-')
+ errx(EX_USAGE, "-H expects a file descriptor");
+ break;
+ case 'h':
+ if (fd != -1)
+ errx(EX_USAGE, "'-h' and '-H' are mutually "
+ "exclusive options");
+ fd = pw_checkfd(optarg);
+ break;
+ case 'M':
+ members = optarg;
+ break;
+ case 'o':
+ conf.checkduplicate = false;
+ break;
+ case 'N':
+ dryrun = true;
+ break;
+ case 'P':
+ pretty = true;
+ break;
+ case 'Y':
+ nis = true;
+ break;
+ }
+ }
+
+ if (quiet)
+ freopen(_PATH_DEVNULL, "w", stderr);
+ if (name == NULL)
+ errx(EX_DATAERR, "group name required");
+ if (GETGRNAM(name) != NULL)
+ errx(EX_DATAERR, "group name `%s' already exists", name);
+ cnf = get_userconfig(cfg);
+ rc = groupadd(cnf, name, gr_gidpolicy(cnf, id), members, fd, dryrun,
+ pretty, precrypted);
+ if (nis && rc == EXIT_SUCCESS && nis_update() == 0)
+ pw_log(cnf, M_ADD, W_GROUP, "NIS maps updated");
+
+ return (rc);
+}
+
+int
+pw_group_mod(int argc, char **argv, char *arg1)
+{
+ struct userconf *cnf;
+ struct group *grp = NULL;
+ const char *cfg = NULL;
+ char *oldmembers = NULL;
+ char *members = NULL;
+ char *newmembers = NULL;
+ char *newname = NULL;
+ char *name = NULL;
+ intmax_t id = -1;
+ int ch, rc, fd = -1;
+ bool quiet, pretty, dryrun, nis, precrypted;
+
+ quiet = pretty = dryrun = nis = precrypted = false;
+
+ if (arg1 != NULL) {
+ if (arg1[strspn(arg1, "0123456789")] == '\0')
+ id = pw_checkid(arg1, GID_MAX);
+ else
+ name = arg1;
+ }
+
+ while ((ch = getopt(argc, argv, "C:qn:d:g:l:h:H:M:m:NPY")) != -1) {
+ switch (ch) {
+ case 'C':
+ cfg = optarg;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'n':
+ name = optarg;
+ break;
+ case 'g':
+ id = pw_checkid(optarg, GID_MAX);
+ break;
+ case 'd':
+ oldmembers = optarg;
+ break;
+ case 'l':
+ newname = optarg;
+ break;
+ case 'H':
+ if (fd != -1)
+ errx(EX_USAGE, "'-h' and '-H' are mutually "
+ "exclusive options");
+ fd = pw_checkfd(optarg);
+ precrypted = true;
+ if (fd == '-')
+ errx(EX_USAGE, "-H expects a file descriptor");
+ break;
+ case 'h':
+ if (fd != -1)
+ errx(EX_USAGE, "'-h' and '-H' are mutually "
+ "exclusive options");
+ fd = pw_checkfd(optarg);
+ break;
+ case 'M':
+ members = optarg;
+ break;
+ case 'm':
+ newmembers = optarg;
+ break;
+ case 'N':
+ dryrun = true;
+ break;
+ case 'P':
+ pretty = true;
+ break;
+ case 'Y':
+ nis = true;
+ break;
+ }
+ }
+ if (quiet)
+ freopen(_PATH_DEVNULL, "w", stderr);
+ cnf = get_userconfig(cfg);
+ grp = getgroup(name, id, true);
+ if (name == NULL)
+ name = grp->gr_name;
+ if (id > 0)
+ grp->gr_gid = id;
+
+ if (newname != NULL)
+ grp->gr_name = pw_checkname(newname, 0);
+
+ grp_set_passwd(grp, true, fd, precrypted);
+ /*
+ * Keep the same logic as old code for now:
+ * if -M is passed, -d and -m are ignored
+ * then id -d, -m is ignored
+ * last is -m
+ */
+
+ if (members) {
+ grp->gr_mem = NULL;
+ grp_add_members(&grp, members);
+ } else if (oldmembers) {
+ delete_members(grp, oldmembers);
+ } else if (newmembers) {
+ grp_add_members(&grp, newmembers);
+ }
+
+ if ((rc = chggrent(name, grp)) != 0) {
+ if (rc == -1)
+ errx(EX_IOERR, "group '%s' not available (NIS?)",
+ grp->gr_name);
+ else
+ err(EX_IOERR, "group update");
+ }
+
+ if (newname)
+ name = newname;
+
+ /* grp may have been invalidated */
+ if ((grp = GETGRNAM(name)) == NULL)
+ errx(EX_SOFTWARE, "group disappeared during update");
+
+ pw_log(cnf, M_UPDATE, W_GROUP, "%s(%ju)", grp->gr_name,
+ (uintmax_t)grp->gr_gid);
+
+ if (nis && nis_update() == 0)
+ pw_log(cnf, M_UPDATE, W_GROUP, "NIS maps updated");
+
+ return (EXIT_SUCCESS);
}
diff --git a/usr.sbin/pw/pw_log.c b/usr.sbin/pw/pw_log.c
index b774423..29038d9 100644
--- a/usr.sbin/pw/pw_log.c
+++ b/usr.sbin/pw/pw_log.c
@@ -30,6 +30,8 @@ static const char rcsid[] =
#endif /* not lint */
#include <fcntl.h>
+#include <string.h>
+#include <stdarg.h>
#include "pw.h"
diff --git a/usr.sbin/pw/pw_nis.c b/usr.sbin/pw/pw_nis.c
index c786cc7..6cc361b 100644
--- a/usr.sbin/pw/pw_nis.c
+++ b/usr.sbin/pw/pw_nis.c
@@ -30,6 +30,7 @@ static const char rcsid[] =
#endif /* not lint */
#include <sys/types.h>
+
#include <err.h>
#include <pwd.h>
#include <libutil.h>
@@ -43,6 +44,7 @@ pw_nisupdate(const char * path, struct passwd * pwd, char const * user)
struct passwd *pw = NULL;
struct passwd *old_pw = NULL;
+ printf("===> %s\n", path);
if (pwd != NULL)
pw = pw_dup(pwd);
diff --git a/usr.sbin/pw/pw_user.c b/usr.sbin/pw/pw_user.c
index d6dad3f..d9bce87 100644
--- a/usr.sbin/pw/pw_user.c
+++ b/usr.sbin/pw/pw_user.c
@@ -30,63 +30,80 @@ static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
+#include <sys/param.h>
+#include <sys/resource.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
#include <ctype.h>
+#include <dirent.h>
#include <err.h>
#include <fcntl.h>
-#include <sys/param.h>
-#include <dirent.h>
-#include <paths.h>
-#include <termios.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <login_cap.h>
-#include <pwd.h>
#include <grp.h>
+#include <pwd.h>
#include <libutil.h>
+#include <login_cap.h>
+#include <paths.h>
+#include <string.h>
+#include <sysexits.h>
+#include <termios.h>
+#include <unistd.h>
+
#include "pw.h"
#include "bitmap.h"
+#include "psdate.h"
#define LOGNAMESIZE (MAXLOGNAME-1)
static char locked_str[] = "*LOCKED*";
-static int pw_userdel(char *name, long id);
-static int print_user(struct passwd * pwd);
-static uid_t pw_uidpolicy(struct userconf * cnf, long id);
-static uid_t pw_gidpolicy(struct cargs * args, char *nam, gid_t prefer);
-static time_t pw_pwdpolicy(struct userconf * cnf, struct cargs * args);
-static time_t pw_exppolicy(struct userconf * cnf, struct cargs * args);
-static char *pw_homepolicy(struct userconf * cnf, struct cargs * args, char const * user);
-static char *pw_shellpolicy(struct userconf * cnf, struct cargs * args, char *newshell);
-static char *pw_password(struct userconf * cnf, char const * user);
-static char *shell_path(char const * path, char *shells[], char *sh);
-static void rmat(uid_t uid);
-static void rmopie(char const * name);
+static struct passwd fakeuser = {
+ "nouser",
+ "*",
+ -1,
+ -1,
+ 0,
+ "",
+ "User &",
+ "/nonexistent",
+ "/bin/sh",
+ 0,
+ 0
+};
+
+static int print_user(struct passwd *pwd, bool pretty, bool v7);
+static uid_t pw_uidpolicy(struct userconf *cnf, intmax_t id);
+static uid_t pw_gidpolicy(struct userconf *cnf, char *grname, char *nam,
+ gid_t prefer, bool dryrun);
+static char *pw_homepolicy(struct userconf * cnf, char *homedir,
+ const char *user);
+static char *pw_shellpolicy(struct userconf * cnf);
+static char *pw_password(struct userconf * cnf, char const * user,
+ bool dryrun);
+static char *shell_path(char const * path, char *shells[], char *sh);
+static void rmat(uid_t uid);
+static void rmopie(char const * name);
static void
-create_and_populate_homedir(struct passwd *pwd)
+create_and_populate_homedir(struct userconf *cnf, struct passwd *pwd,
+ const char *skeldir, mode_t homemode, bool update)
{
- struct userconf *cnf = conf.userconf;
- const char *skeldir;
int skelfd = -1;
- skeldir = cnf->dotdir;
-
if (skeldir != NULL && *skeldir != '\0') {
if (*skeldir == '/')
skeldir++;
skelfd = openat(conf.rootfd, skeldir, O_DIRECTORY|O_CLOEXEC);
}
- copymkdir(conf.rootfd, pwd->pw_dir, skelfd, cnf->homemode, pwd->pw_uid,
+ copymkdir(conf.rootfd, pwd->pw_dir, skelfd, homemode, pwd->pw_uid,
pwd->pw_gid, 0);
- pw_log(cnf, M_ADD, W_USER, "%s(%u) home %s made", pwd->pw_name,
- pwd->pw_uid, pwd->pw_dir);
+ pw_log(cnf, update ? M_UPDATE : M_ADD, W_USER, "%s(%ju) home %s made",
+ pwd->pw_name, (uintmax_t)pwd->pw_uid, pwd->pw_dir);
}
static int
-set_passwd(struct passwd *pwd, bool update)
+pw_set_passwd(struct passwd *pwd, int fd, bool precrypted, bool update)
{
int b, istty;
struct termios t, n;
@@ -94,7 +111,7 @@ set_passwd(struct passwd *pwd, bool update)
char line[_PASSWORD_LEN+1];
char *p;
- if (conf.fd == '-') {
+ if (fd == '-') {
if (!pwd->pw_passwd || *pwd->pw_passwd != '*') {
pwd->pw_passwd = "*"; /* No access */
return (1);
@@ -102,40 +119,40 @@ set_passwd(struct passwd *pwd, bool update)
return (0);
}
- if ((istty = isatty(conf.fd))) {
- if (tcgetattr(conf.fd, &t) == -1)
+ if ((istty = isatty(fd))) {
+ if (tcgetattr(fd, &t) == -1)
istty = 0;
else {
n = t;
n.c_lflag &= ~(ECHO);
- tcsetattr(conf.fd, TCSANOW, &n);
+ tcsetattr(fd, TCSANOW, &n);
printf("%s%spassword for user %s:",
update ? "new " : "",
- conf.precrypted ? "encrypted " : "",
+ precrypted ? "encrypted " : "",
pwd->pw_name);
fflush(stdout);
}
}
- b = read(conf.fd, line, sizeof(line) - 1);
+ b = read(fd, line, sizeof(line) - 1);
if (istty) { /* Restore state */
- tcsetattr(conf.fd, TCSANOW, &t);
+ tcsetattr(fd, TCSANOW, &t);
fputc('\n', stdout);
fflush(stdout);
}
if (b < 0)
err(EX_IOERR, "-%c file descriptor",
- conf.precrypted ? 'H' : 'h');
+ precrypted ? 'H' : 'h');
line[b] = '\0';
if ((p = strpbrk(line, "\r\n")) != NULL)
*p = '\0';
if (!*line)
errx(EX_DATAERR, "empty password read on file descriptor %d",
- conf.fd);
- if (conf.precrypted) {
+ fd);
+ if (precrypted) {
if (strchr(line, ':') != NULL)
errx(EX_DATAERR, "bad encrypted password");
- pwd->pw_passwd = line;
+ pwd->pw_passwd = strdup(line);
} else {
lc = login_getpwclass(pwd);
if (lc == NULL ||
@@ -147,54 +164,15 @@ set_passwd(struct passwd *pwd, bool update)
return (1);
}
-int
-pw_usernext(struct userconf *cnf, bool quiet)
-{
- uid_t next = pw_uidpolicy(cnf, -1);
-
- if (quiet)
- return (next);
-
- printf("%u:", next);
- pw_groupnext(cnf, quiet);
-
- return (EXIT_SUCCESS);
-}
-
-static int
-pw_usershow(char *name, long id, struct passwd *fakeuser)
-{
- struct passwd *pwd = NULL;
-
- if (id < 0 && name == NULL && !conf.all)
- errx(EX_DATAERR, "username or id or '-a' required");
-
- if (conf.all) {
- SETPWENT();
- while ((pwd = GETPWENT()) != NULL)
- print_user(pwd);
- ENDPWENT();
- return (EXIT_SUCCESS);
- }
-
- pwd = (name != NULL) ? GETPWNAM(pw_checkname(name, 0)) : GETPWUID(id);
- if (pwd == NULL) {
- if (conf.force) {
- pwd = fakeuser;
- } else {
- if (name == NULL)
- errx(EX_NOUSER, "no such uid `%ld'", id);
- errx(EX_NOUSER, "no such user `%s'", name);
- }
- }
-
- return (print_user(pwd));
-}
-
static void
-perform_chgpwent(const char *name, struct passwd *pwd)
+perform_chgpwent(const char *name, struct passwd *pwd, char *nispasswd)
{
int rc;
+ struct passwd *nispwd;
+
+ /* duplicate for nis so that chgpwent is not modifying before NIS */
+ if (nispasswd && *nispasswd == '/')
+ nispwd = pw_dup(pwd);
rc = chgpwent(name, pwd);
if (rc == -1)
@@ -202,11 +180,11 @@ perform_chgpwent(const char *name, struct passwd *pwd)
else if (rc != 0)
err(EX_IOERR, "passwd file update");
- if (conf.userconf->nispasswd && *conf.userconf->nispasswd == '/') {
- rc = chgnispwent(conf.userconf->nispasswd, name, pwd);
+ if (nispasswd && *nispasswd == '/') {
+ rc = chgnispwent(nispasswd, name, nispwd);
if (rc == -1)
warn("User '%s' not found in NIS passwd", pwd->pw_name);
- else
+ else if (rc != 0)
warn("NIS passwd update");
/* NOTE: NIS-only update errors are not fatal */
}
@@ -222,19 +200,29 @@ perform_chgpwent(const char *name, struct passwd *pwd)
* that is a known limitation.
*/
static int
-pw_userlock(char *name, long id, int mode)
+pw_userlock(char *arg1, int mode)
{
struct passwd *pwd = NULL;
char *passtmp = NULL;
+ char *name;
bool locked = false;
+ uid_t id;
- if (id < 0 && name == NULL)
+ if (geteuid() != 0)
+ errx(EX_NOPERM, "you must be root");
+
+ if (arg1 == NULL)
errx(EX_DATAERR, "username or id required");
+ if (arg1[strspn(arg1, "0123456789")] == '\0')
+ id = pw_checkid(arg1, UID_MAX);
+ else
+ name = arg1;
+
pwd = (name != NULL) ? GETPWNAM(pw_checkname(name, 0)) : GETPWUID(id);
if (pwd == NULL) {
if (name == NULL)
- errx(EX_NOUSER, "no such uid `%ld'", id);
+ errx(EX_NOUSER, "no such uid `%ju'", (uintmax_t) id);
errx(EX_NOUSER, "no such user `%s'", name);
}
@@ -257,629 +245,87 @@ pw_userlock(char *name, long id, int mode)
pwd->pw_passwd += sizeof(locked_str)-1;
}
- perform_chgpwent(name, pwd);
+ perform_chgpwent(name, pwd, NULL);
free(passtmp);
return (EXIT_SUCCESS);
}
-/*-
- * -C config configuration file
- * -q quiet operation
- * -n name login name
- * -u uid user id
- * -c comment user name/comment
- * -d directory home directory
- * -e date account expiry date
- * -p date password expiry date
- * -g grp primary group
- * -G grp1,grp2 additional groups
- * -m [ -k dir ] create and set up home
- * -s shell name of login shell
- * -o duplicate uid ok
- * -L class user class
- * -l name new login name
- * -h fd password filehandle
- * -H fd encrypted password filehandle
- * -F force print or add
- * Setting defaults:
- * -D set user defaults
- * -b dir default home root dir
- * -e period default expiry period
- * -p period default password change period
- * -g group default group
- * -G grp1,grp2.. default additional groups
- * -L class default login class
- * -k dir default home skeleton
- * -s shell default shell
- * -w method default password method
- */
-
-int
-pw_user(int mode, char *name, long id, struct cargs * args)
+static uid_t
+pw_uidpolicy(struct userconf * cnf, intmax_t id)
{
- int rc, edited = 0;
- char *p = NULL;
- struct carg *arg;
- struct passwd *pwd = NULL;
- struct group *grp;
- struct stat st;
- struct userconf *cnf;
- char line[_PASSWORD_LEN+1];
- char path[MAXPATHLEN];
- FILE *fp;
- char *dmode_c;
- void *set = NULL;
-
- static struct passwd fakeuser =
- {
- "nouser",
- "*",
- -1,
- -1,
- 0,
- "",
- "User &",
- "/nonexistent",
- "/bin/sh",
- 0
-#if defined(__FreeBSD__)
- ,0
-#endif
- };
-
- cnf = conf.userconf;
-
- if (mode == M_NEXT)
- return (pw_usernext(cnf, conf.quiet));
-
- if (mode == M_PRINT)
- return (pw_usershow(name, id, &fakeuser));
-
- if (mode == M_DELETE)
- return (pw_userdel(name, id));
-
- if (mode == M_LOCK || mode == M_UNLOCK)
- return (pw_userlock(name, id, mode));
-
- /*
- * We can do all of the common legwork here
- */
-
- if ((arg = getarg(args, 'b')) != NULL) {
- cnf->home = arg->val;
- }
-
- if ((arg = getarg(args, 'M')) != NULL) {
- dmode_c = arg->val;
- if ((set = setmode(dmode_c)) == NULL)
- errx(EX_DATAERR, "invalid directory creation mode '%s'",
- dmode_c);
- cnf->homemode = getmode(set, _DEF_DIRMODE);
- free(set);
- }
-
- /*
- * If we'll need to use it or we're updating it,
- * then create the base home directory if necessary
- */
- if (arg != NULL || getarg(args, 'm') != NULL) {
- int l = strlen(cnf->home);
-
- if (l > 1 && cnf->home[l-1] == '/') /* Shave off any trailing path delimiter */
- cnf->home[--l] = '\0';
-
- if (l < 2 || *cnf->home != '/') /* Check for absolute path name */
- errx(EX_DATAERR, "invalid base directory for home '%s'", cnf->home);
-
- if (stat(cnf->home, &st) == -1) {
- char dbuf[MAXPATHLEN];
-
- /*
- * This is a kludge especially for Joerg :)
- * If the home directory would be created in the root partition, then
- * we really create it under /usr which is likely to have more space.
- * But we create a symlink from cnf->home -> "/usr" -> cnf->home
- */
- if (strchr(cnf->home+1, '/') == NULL) {
- snprintf(dbuf, MAXPATHLEN, "/usr%s", cnf->home);
- if (mkdir(dbuf, _DEF_DIRMODE) != -1 || errno == EEXIST) {
- chown(dbuf, 0, 0);
- /*
- * Skip first "/" and create symlink:
- * /home -> usr/home
- */
- symlink(dbuf+1, cnf->home);
- }
- /* If this falls, fall back to old method */
- }
- strlcpy(dbuf, cnf->home, sizeof(dbuf));
- p = dbuf;
- if (stat(dbuf, &st) == -1) {
- while ((p = strchr(p + 1, '/')) != NULL) {
- *p = '\0';
- if (stat(dbuf, &st) == -1) {
- if (mkdir(dbuf, _DEF_DIRMODE) == -1)
- err(EX_OSFILE, "mkdir '%s'", dbuf);
- chown(dbuf, 0, 0);
- } else if (!S_ISDIR(st.st_mode))
- errx(EX_OSFILE, "'%s' (root home parent) is not a directory", dbuf);
- *p = '/';
- }
- }
- if (stat(dbuf, &st) == -1) {
- if (mkdir(dbuf, _DEF_DIRMODE) == -1)
- err(EX_OSFILE, "mkdir '%s'", dbuf);
- chown(dbuf, 0, 0);
- }
- } else if (!S_ISDIR(st.st_mode))
- errx(EX_OSFILE, "root home `%s' is not a directory", cnf->home);
- }
-
- if ((arg = getarg(args, 'e')) != NULL)
- cnf->expire_days = atoi(arg->val);
-
- if ((arg = getarg(args, 'y')) != NULL)
- cnf->nispasswd = arg->val;
-
- if ((arg = getarg(args, 'p')) != NULL && arg->val)
- cnf->password_days = atoi(arg->val);
-
- if ((arg = getarg(args, 'g')) != NULL) {
- if (!*(p = arg->val)) /* Handle empty group list specially */
- cnf->default_group = "";
- else {
- if ((grp = GETGRNAM(p)) == NULL) {
- if (!isdigit((unsigned char)*p) || (grp = GETGRGID((gid_t) atoi(p))) == NULL)
- errx(EX_NOUSER, "group `%s' does not exist", p);
- }
- cnf->default_group = newstr(grp->gr_name);
- }
- }
- if ((arg = getarg(args, 'L')) != NULL)
- cnf->default_class = pw_checkname(arg->val, 0);
-
- if ((arg = getarg(args, 'G')) != NULL && arg->val) {
- for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) {
- if ((grp = GETGRNAM(p)) == NULL) {
- if (!isdigit((unsigned char)*p) || (grp = GETGRGID((gid_t) atoi(p))) == NULL)
- errx(EX_NOUSER, "group `%s' does not exist", p);
- }
- sl_add(cnf->groups, newstr(grp->gr_name));
- }
- }
-
- if ((arg = getarg(args, 'k')) != NULL) {
- char *tmp = cnf->dotdir = arg->val;
- if (*tmp == '/')
- tmp++;
- if ((fstatat(conf.rootfd, tmp, &st, 0) == -1) ||
- !S_ISDIR(st.st_mode))
- errx(EX_OSFILE, "skeleton `%s' is not a directory or "
- "does not exist", cnf->dotdir);
- }
-
- if ((arg = getarg(args, 's')) != NULL)
- cnf->shell_default = arg->val;
-
- if ((arg = getarg(args, 'w')) != NULL)
- cnf->default_password = boolean_val(arg->val, cnf->default_password);
- if (mode == M_ADD && getarg(args, 'D')) {
- if (name != NULL)
- errx(EX_DATAERR, "can't combine `-D' with `-n name'");
- if ((arg = getarg(args, 'u')) != NULL && (p = strtok(arg->val, ", \t")) != NULL) {
- if ((cnf->min_uid = (uid_t) atoi(p)) == 0)
- cnf->min_uid = 1000;
- if ((p = strtok(NULL, " ,\t")) == NULL || (cnf->max_uid = (uid_t) atoi(p)) < cnf->min_uid)
- cnf->max_uid = 32000;
- }
- if ((arg = getarg(args, 'i')) != NULL && (p = strtok(arg->val, ", \t")) != NULL) {
- if ((cnf->min_gid = (gid_t) atoi(p)) == 0)
- cnf->min_gid = 1000;
- if ((p = strtok(NULL, " ,\t")) == NULL || (cnf->max_gid = (gid_t) atoi(p)) < cnf->min_gid)
- cnf->max_gid = 32000;
- }
-
- if (write_userconfig(conf.config))
- return (EXIT_SUCCESS);
- err(EX_IOERR, "config udpate");
- }
-
- if (name != NULL)
- pwd = GETPWNAM(pw_checkname(name, 0));
-
- if (id < 0 && name == NULL)
- errx(EX_DATAERR, "user name or id required");
-
- /*
- * Update require that the user exists
- */
- if (mode == M_UPDATE) {
-
- if (name == NULL && pwd == NULL) /* Try harder */
- pwd = GETPWUID(id);
-
- if (pwd == NULL) {
- if (name == NULL)
- errx(EX_NOUSER, "no such uid `%ld'", id);
- errx(EX_NOUSER, "no such user `%s'", name);
- }
-
- if (name == NULL)
- name = pwd->pw_name;
-
- /*
- * The rest is edit code
- */
- if (conf.newname != NULL) {
- if (strcmp(pwd->pw_name, "root") == 0)
- errx(EX_DATAERR, "can't rename `root' account");
- pwd->pw_name = pw_checkname(conf.newname, 0);
- edited = 1;
- }
-
- if (id > 0 && isdigit((unsigned char)*arg->val)) {
- pwd->pw_uid = (uid_t)id;
- edited = 1;
- if (pwd->pw_uid != 0 && strcmp(pwd->pw_name, "root") == 0)
- errx(EX_DATAERR, "can't change uid of `root' account");
- if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0)
- warnx("WARNING: account `%s' will have a uid of 0 (superuser access!)", pwd->pw_name);
- }
-
- if ((arg = getarg(args, 'g')) != NULL && pwd->pw_uid != 0) { /* Already checked this */
- gid_t newgid = (gid_t) GETGRNAM(cnf->default_group)->gr_gid;
- if (newgid != pwd->pw_gid) {
- edited = 1;
- pwd->pw_gid = newgid;
- }
- }
-
- if ((arg = getarg(args, 'p')) != NULL) {
- if (*arg->val == '\0' || strcmp(arg->val, "0") == 0) {
- if (pwd->pw_change != 0) {
- pwd->pw_change = 0;
- edited = 1;
- }
- }
- else {
- time_t now = time(NULL);
- time_t expire = parse_date(now, arg->val);
-
- if (pwd->pw_change != expire) {
- pwd->pw_change = expire;
- edited = 1;
- }
- }
- }
-
- if ((arg = getarg(args, 'e')) != NULL) {
- if (*arg->val == '\0' || strcmp(arg->val, "0") == 0) {
- if (pwd->pw_expire != 0) {
- pwd->pw_expire = 0;
- edited = 1;
- }
- }
- else {
- time_t now = time(NULL);
- time_t expire = parse_date(now, arg->val);
-
- if (pwd->pw_expire != expire) {
- pwd->pw_expire = expire;
- edited = 1;
- }
- }
- }
-
- if ((arg = getarg(args, 's')) != NULL) {
- char *shell = shell_path(cnf->shelldir, cnf->shells, arg->val);
- if (shell == NULL)
- shell = "";
- if (strcmp(shell, pwd->pw_shell) != 0) {
- pwd->pw_shell = shell;
- edited = 1;
- }
- }
-
- if (getarg(args, 'L')) {
- if (cnf->default_class == NULL)
- cnf->default_class = "";
- if (strcmp(pwd->pw_class, cnf->default_class) != 0) {
- pwd->pw_class = cnf->default_class;
- edited = 1;
- }
- }
-
- if ((arg = getarg(args, 'd')) != NULL) {
- if (strcmp(pwd->pw_dir, arg->val))
- edited = 1;
- if (stat(pwd->pw_dir = arg->val, &st) == -1) {
- if (getarg(args, 'm') == NULL && strcmp(pwd->pw_dir, "/nonexistent") != 0)
- warnx("WARNING: home `%s' does not exist", pwd->pw_dir);
- } else if (!S_ISDIR(st.st_mode))
- warnx("WARNING: home `%s' is not a directory", pwd->pw_dir);
- }
-
- if ((arg = getarg(args, 'w')) != NULL && conf.fd == -1) {
- login_cap_t *lc;
-
- lc = login_getpwclass(pwd);
- if (lc == NULL ||
- login_setcryptfmt(lc, "sha512", NULL) == NULL)
- warn("setting crypt(3) format");
- login_close(lc);
- pwd->pw_passwd = pw_password(cnf, pwd->pw_name);
- edited = 1;
- }
-
- } else {
- login_cap_t *lc;
-
- /*
- * Add code
- */
-
- if (name == NULL) /* Required */
- errx(EX_DATAERR, "login name required");
- else if ((pwd = GETPWNAM(name)) != NULL) /* Exists */
- errx(EX_DATAERR, "login name `%s' already exists", name);
-
- /*
- * Now, set up defaults for a new user
- */
- pwd = &fakeuser;
- pwd->pw_name = name;
- pwd->pw_class = cnf->default_class ? cnf->default_class : "";
- pwd->pw_uid = pw_uidpolicy(cnf, id);
- pwd->pw_gid = pw_gidpolicy(args, pwd->pw_name, (gid_t) pwd->pw_uid);
- pwd->pw_change = pw_pwdpolicy(cnf, args);
- pwd->pw_expire = pw_exppolicy(cnf, args);
- pwd->pw_dir = pw_homepolicy(cnf, args, pwd->pw_name);
- pwd->pw_shell = pw_shellpolicy(cnf, args, NULL);
- lc = login_getpwclass(pwd);
- if (lc == NULL || login_setcryptfmt(lc, "sha512", NULL) == NULL)
- warn("setting crypt(3) format");
- login_close(lc);
- pwd->pw_passwd = pw_password(cnf, pwd->pw_name);
- edited = 1;
-
- if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0)
- warnx("WARNING: new account `%s' has a uid of 0 (superuser access!)", pwd->pw_name);
- }
-
- /*
- * Shared add/edit code
- */
- if (conf.gecos != NULL) {
- if (strcmp(pwd->pw_gecos, conf.gecos) != 0) {
- pwd->pw_gecos = conf.gecos;
- edited = 1;
- }
- }
-
- if (conf.fd != -1)
- edited = set_passwd(pwd, mode == M_UPDATE);
-
- /*
- * Special case: -N only displays & exits
- */
- if (conf.dryrun)
- return print_user(pwd);
-
- if (mode == M_ADD) {
- edited = 1; /* Always */
- rc = addpwent(pwd);
- if (rc == -1)
- errx(EX_IOERR, "user '%s' already exists",
- pwd->pw_name);
- else if (rc != 0)
- err(EX_IOERR, "passwd file update");
- if (cnf->nispasswd && *cnf->nispasswd=='/') {
- rc = addnispwent(cnf->nispasswd, pwd);
- if (rc == -1)
- warnx("User '%s' already exists in NIS passwd", pwd->pw_name);
- else
- warn("NIS passwd update");
- /* NOTE: we treat NIS-only update errors as non-fatal */
- }
- } else if (mode == M_UPDATE && edited) /* Only updated this if required */
- perform_chgpwent(name, pwd);
+ struct passwd *pwd;
+ struct bitmap bm;
+ uid_t uid = (uid_t) - 1;
/*
- * Ok, user is created or changed - now edit group file
+ * Check the given uid, if any
*/
+ if (id >= 0) {
+ uid = (uid_t) id;
- if (mode == M_ADD || getarg(args, 'G') != NULL) {
- int j;
- size_t i;
- /* First remove the user from all group */
- SETGRENT();
- while ((grp = GETGRENT()) != NULL) {
- char group[MAXLOGNAME];
- if (grp->gr_mem == NULL)
- continue;
- for (i = 0; grp->gr_mem[i] != NULL; i++) {
- if (strcmp(grp->gr_mem[i] , pwd->pw_name) != 0)
- continue;
- for (j = i; grp->gr_mem[j] != NULL ; j++)
- grp->gr_mem[j] = grp->gr_mem[j+1];
- strlcpy(group, grp->gr_name, MAXLOGNAME);
- chggrent(group, grp);
- }
- }
- ENDGRENT();
-
- /* now add to group where needed */
- for (i = 0; i < cnf->groups->sl_cur; i++) {
- grp = GETGRNAM(cnf->groups->sl_str[i]);
- grp = gr_add(grp, pwd->pw_name);
- /*
- * grp can only be NULL in 2 cases:
- * - the new member is already a member
- * - a problem with memory occurs
- * in both cases we want to skip now.
- */
- if (grp == NULL)
- continue;
- chggrent(grp->gr_name, grp);
- free(grp);
- }
- }
-
-
- /* go get a current version of pwd */
- pwd = GETPWNAM(name);
- if (pwd == NULL) {
- /* This will fail when we rename, so special case that */
- if (mode == M_UPDATE && conf.newname != NULL) {
- name = conf.newname; /* update new name */
- pwd = GETPWNAM(name); /* refetch renamed rec */
- }
+ if ((pwd = GETPWUID(uid)) != NULL && conf.checkduplicate)
+ errx(EX_DATAERR, "uid `%ju' has already been allocated",
+ (uintmax_t)pwd->pw_uid);
+ return (uid);
}
- if (pwd == NULL) /* can't go on without this */
- errx(EX_NOUSER, "user '%s' disappeared during update", name);
-
- grp = GETGRGID(pwd->pw_gid);
- pw_log(cnf, mode, W_USER, "%s(%u):%s(%u):%s:%s:%s",
- pwd->pw_name, pwd->pw_uid,
- grp ? grp->gr_name : "unknown", (grp ? grp->gr_gid : (uid_t)-1),
- pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell);
-
/*
- * If adding, let's touch and chown the user's mail file. This is not
- * strictly necessary under BSD with a 0755 maildir but it also
- * doesn't hurt anything to create the empty mailfile
+ * We need to allocate the next available uid under one of
+ * two policies a) Grab the first unused uid b) Grab the
+ * highest possible unused uid
*/
- if (mode == M_ADD) {
- if (PWALTDIR() != PWF_ALT) {
- snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR,
- pwd->pw_name);
- close(openat(conf.rootfd, path +1, O_RDWR | O_CREAT,
- 0600)); /* Preserve contents & mtime */
- fchownat(conf.rootfd, path + 1, pwd->pw_uid,
- pwd->pw_gid, AT_SYMLINK_NOFOLLOW);
- }
+ if (cnf->min_uid >= cnf->max_uid) { /* Sanity
+ * claus^H^H^H^Hheck */
+ cnf->min_uid = 1000;
+ cnf->max_uid = 32000;
}
+ bm = bm_alloc(cnf->max_uid - cnf->min_uid + 1);
/*
- * Let's create and populate the user's home directory. Note
- * that this also `works' for editing users if -m is used, but
- * existing files will *not* be overwritten.
+ * Now, let's fill the bitmap from the password file
*/
- if (PWALTDIR() != PWF_ALT && getarg(args, 'm') != NULL && pwd->pw_dir &&
- *pwd->pw_dir == '/' && pwd->pw_dir[1])
- create_and_populate_homedir(pwd);
+ SETPWENT();
+ while ((pwd = GETPWENT()) != NULL)
+ if (pwd->pw_uid >= (uid_t) cnf->min_uid && pwd->pw_uid <= (uid_t) cnf->max_uid)
+ bm_setbit(&bm, pwd->pw_uid - cnf->min_uid);
+ ENDPWENT();
/*
- * Finally, send mail to the new user as well, if we are asked to
+ * Then apply the policy, with fallback to reuse if necessary
*/
- if (mode == M_ADD && !PWALTDIR() && cnf->newmail && *cnf->newmail && (fp = fopen(cnf->newmail, "r")) != NULL) {
- FILE *pfp = popen(_PATH_SENDMAIL " -t", "w");
-
- if (pfp == NULL)
- warn("sendmail");
- else {
- fprintf(pfp, "From: root\n" "To: %s\n" "Subject: Welcome!\n\n", pwd->pw_name);
- while (fgets(line, sizeof(line), fp) != NULL) {
- /* Do substitutions? */
- fputs(line, pfp);
- }
- pclose(pfp);
- pw_log(cnf, mode, W_USER, "%s(%u) new user mail sent",
- pwd->pw_name, pwd->pw_uid);
- }
- fclose(fp);
- }
-
- return EXIT_SUCCESS;
-}
-
-
-static uid_t
-pw_uidpolicy(struct userconf * cnf, long id)
-{
- struct passwd *pwd;
- uid_t uid = (uid_t) - 1;
+ if (cnf->reuse_uids || (uid = (uid_t) (bm_lastset(&bm) + cnf->min_uid + 1)) > cnf->max_uid)
+ uid = (uid_t) (bm_firstunset(&bm) + cnf->min_uid);
/*
- * Check the given uid, if any
+ * Another sanity check
*/
- if (id >= 0) {
- uid = (uid_t) id;
-
- if ((pwd = GETPWUID(uid)) != NULL && conf.checkduplicate)
- errx(EX_DATAERR, "uid `%u' has already been allocated", pwd->pw_uid);
- } else {
- struct bitmap bm;
-
- /*
- * We need to allocate the next available uid under one of
- * two policies a) Grab the first unused uid b) Grab the
- * highest possible unused uid
- */
- if (cnf->min_uid >= cnf->max_uid) { /* Sanity
- * claus^H^H^H^Hheck */
- cnf->min_uid = 1000;
- cnf->max_uid = 32000;
- }
- bm = bm_alloc(cnf->max_uid - cnf->min_uid + 1);
-
- /*
- * Now, let's fill the bitmap from the password file
- */
- SETPWENT();
- while ((pwd = GETPWENT()) != NULL)
- if (pwd->pw_uid >= (uid_t) cnf->min_uid && pwd->pw_uid <= (uid_t) cnf->max_uid)
- bm_setbit(&bm, pwd->pw_uid - cnf->min_uid);
- ENDPWENT();
-
- /*
- * Then apply the policy, with fallback to reuse if necessary
- */
- if (cnf->reuse_uids || (uid = (uid_t) (bm_lastset(&bm) + cnf->min_uid + 1)) > cnf->max_uid)
- uid = (uid_t) (bm_firstunset(&bm) + cnf->min_uid);
-
- /*
- * Another sanity check
- */
- if (uid < cnf->min_uid || uid > cnf->max_uid)
- errx(EX_SOFTWARE, "unable to allocate a new uid - range fully used");
- bm_dealloc(&bm);
- }
- return uid;
+ if (uid < cnf->min_uid || uid > cnf->max_uid)
+ errx(EX_SOFTWARE, "unable to allocate a new uid - range fully used");
+ bm_dealloc(&bm);
+ return (uid);
}
-
-static uid_t
-pw_gidpolicy(struct cargs * args, char *nam, gid_t prefer)
+static uid_t
+pw_gidpolicy(struct userconf *cnf, char *grname, char *nam, gid_t prefer, bool dryrun)
{
struct group *grp;
gid_t gid = (uid_t) - 1;
- struct carg *a_gid = getarg(args, 'g');
- struct userconf *cnf = conf.userconf;
-
- /*
- * If no arg given, see if default can help out
- */
- if (a_gid == NULL && cnf->default_group && *cnf->default_group)
- a_gid = addarg(args, 'g', cnf->default_group);
/*
* Check the given gid, if any
*/
SETGRENT();
- if (a_gid != NULL) {
- if ((grp = GETGRNAM(a_gid->val)) == NULL) {
- gid = (gid_t) atol(a_gid->val);
- if ((gid == 0 && !isdigit((unsigned char)*a_gid->val)) || (grp = GETGRGID(gid)) == NULL)
- errx(EX_NOUSER, "group `%s' is not defined", a_gid->val);
+ if (grname) {
+ if ((grp = GETGRNAM(grname)) == NULL) {
+ gid = pw_checkid(grname, GID_MAX);
+ grp = GETGRGID(gid);
}
gid = grp->gr_gid;
} else if ((grp = GETGRNAM(nam)) != NULL &&
(grp->gr_mem == NULL || grp->gr_mem[0] == NULL)) {
gid = grp->gr_gid; /* Already created? Use it anyway... */
} else {
- gid_t grid = -1;
+ intmax_t grid = -1;
/*
* We need to auto-create a group with the user's name. We
@@ -892,59 +338,27 @@ pw_gidpolicy(struct cargs * args, char *nam, gid_t prefer)
*/
if (GETGRGID(prefer) == NULL)
grid = prefer;
- if (conf.dryrun) {
+ if (dryrun) {
gid = pw_groupnext(cnf, true);
} else {
- pw_group(M_ADD, nam, grid, NULL);
+ if (grid == -1)
+ grid = pw_groupnext(cnf, true);
+ groupadd(cnf, nam, grid, NULL, -1, false, false, false);
if ((grp = GETGRNAM(nam)) != NULL)
gid = grp->gr_gid;
}
}
ENDGRENT();
- return gid;
+ return (gid);
}
-
-static time_t
-pw_pwdpolicy(struct userconf * cnf, struct cargs * args)
-{
- time_t result = 0;
- time_t now = time(NULL);
- struct carg *arg = getarg(args, 'p');
-
- if (arg != NULL) {
- if ((result = parse_date(now, arg->val)) == now)
- errx(EX_DATAERR, "invalid date/time `%s'", arg->val);
- } else if (cnf->password_days > 0)
- result = now + ((long) cnf->password_days * 86400L);
- return result;
-}
-
-
-static time_t
-pw_exppolicy(struct userconf * cnf, struct cargs * args)
+static char *
+pw_homepolicy(struct userconf * cnf, char *homedir, const char *user)
{
- time_t result = 0;
- time_t now = time(NULL);
- struct carg *arg = getarg(args, 'e');
-
- if (arg != NULL) {
- if ((result = parse_date(now, arg->val)) == now)
- errx(EX_DATAERR, "invalid date/time `%s'", arg->val);
- } else if (cnf->expire_days > 0)
- result = now + ((long) cnf->expire_days * 86400L);
- return result;
-}
-
-
-static char *
-pw_homepolicy(struct userconf * cnf, struct cargs * args, char const * user)
-{
- struct carg *arg = getarg(args, 'd');
static char home[128];
- if (arg)
- return (arg->val);
+ if (homedir)
+ return (homedir);
if (cnf->home == NULL || *cnf->home == '\0')
errx(EX_CONFIG, "no base home directory set");
@@ -953,7 +367,7 @@ pw_homepolicy(struct userconf * cnf, struct cargs * args, char const * user)
return (home);
}
-static char *
+static char *
shell_path(char const * path, char *shells[], char *sh)
{
if (sh != NULL && (*sh == '/' || *sh == '\0'))
@@ -988,29 +402,23 @@ shell_path(char const * path, char *shells[], char *sh)
}
}
-
-static char *
-pw_shellpolicy(struct userconf * cnf, struct cargs * args, char *newshell)
+static char *
+pw_shellpolicy(struct userconf * cnf)
{
- char *sh = newshell;
- struct carg *arg = getarg(args, 's');
- if (newshell == NULL && arg != NULL)
- sh = arg->val;
- return shell_path(cnf->shelldir, cnf->shells, sh ? sh : cnf->shell_default);
+ return shell_path(cnf->shelldir, cnf->shells, cnf->shell_default);
}
#define SALTSIZE 32
static char const chars[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./";
-char *
+char *
pw_pwcrypt(char *password)
{
int i;
char salt[SALTSIZE + 1];
char *cryptpw;
-
static char buf[256];
/*
@@ -1026,9 +434,8 @@ pw_pwcrypt(char *password)
return strcpy(buf, cryptpw);
}
-
-static char *
-pw_password(struct userconf * cnf, char const * user)
+static char *
+pw_password(struct userconf * cnf, char const * user, bool dryrun)
{
int i, l;
char pwbuf[32];
@@ -1043,7 +450,7 @@ pw_password(struct userconf * cnf, char const * user)
/*
* We give this information back to the user
*/
- if (conf.fd == -1 && !conf.dryrun) {
+ if (conf.fd == -1 && !dryrun) {
if (isatty(STDOUT_FILENO))
printf("Password for '%s' is: ", user);
printf("%s\n", pwbuf);
@@ -1066,201 +473,78 @@ pw_password(struct userconf * cnf, char const * user)
}
static int
-pw_userdel(char *name, long id)
+print_user(struct passwd * pwd, bool pretty, bool v7)
{
- struct passwd *pwd = NULL;
- char file[MAXPATHLEN];
- char home[MAXPATHLEN];
- uid_t uid;
- struct group *gr, *grp;
- char grname[LOGNAMESIZE];
- int rc;
- struct stat st;
-
- if (id < 0 && name == NULL)
- errx(EX_DATAERR, "username or id required");
-
- pwd = (name != NULL) ? GETPWNAM(pw_checkname(name, 0)) : GETPWUID(id);
- if (pwd == NULL) {
- if (name == NULL)
- errx(EX_NOUSER, "no such uid `%ld'", id);
- errx(EX_NOUSER, "no such user `%s'", name);
+ int j;
+ char *p;
+ struct group *grp = GETGRGID(pwd->pw_gid);
+ char uname[60] = "User &", office[60] = "[None]",
+ wphone[60] = "[None]", hphone[60] = "[None]";
+ char acexpire[32] = "[None]", pwexpire[32] = "[None]";
+ struct tm * tptr;
+
+ if (!pretty) {
+ p = v7 ? pw_make_v7(pwd) : pw_make(pwd);
+ printf("%s\n", p);
+ free(p);
+ return (EXIT_SUCCESS);
}
- uid = pwd->pw_uid;
- if (name == NULL)
- name = pwd->pw_name;
-
- if (strcmp(pwd->pw_name, "root") == 0)
- errx(EX_DATAERR, "cannot remove user 'root'");
- /* Remove opie record from /etc/opiekeys */
-
- if (PWALTDIR() != PWF_ALT)
- rmopie(pwd->pw_name);
-
- if (!PWALTDIR()) {
- /* Remove crontabs */
- snprintf(file, sizeof(file), "/var/cron/tabs/%s", pwd->pw_name);
- if (access(file, F_OK) == 0) {
- snprintf(file, sizeof(file), "crontab -u %s -r", pwd->pw_name);
- system(file);
+ if ((p = strtok(pwd->pw_gecos, ",")) != NULL) {
+ strlcpy(uname, p, sizeof(uname));
+ if ((p = strtok(NULL, ",")) != NULL) {
+ strlcpy(office, p, sizeof(office));
+ if ((p = strtok(NULL, ",")) != NULL) {
+ strlcpy(wphone, p, sizeof(wphone));
+ if ((p = strtok(NULL, "")) != NULL) {
+ strlcpy(hphone, p, sizeof(hphone));
+ }
+ }
}
}
/*
- * Save these for later, since contents of pwd may be
- * invalidated by deletion
+ * Handle '&' in gecos field
*/
- snprintf(file, sizeof(file), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
- strlcpy(home, pwd->pw_dir, sizeof(home));
- gr = GETGRGID(pwd->pw_gid);
- if (gr != NULL)
- strlcpy(grname, gr->gr_name, LOGNAMESIZE);
- else
- grname[0] = '\0';
-
- rc = delpwent(pwd);
- if (rc == -1)
- err(EX_IOERR, "user '%s' does not exist", pwd->pw_name);
- else if (rc != 0)
- err(EX_IOERR, "passwd update");
-
- if (conf.userconf->nispasswd && *conf.userconf->nispasswd=='/') {
- rc = delnispwent(conf.userconf->nispasswd, name);
- if (rc == -1)
- warnx("WARNING: user '%s' does not exist in NIS passwd",
- pwd->pw_name);
- else if (rc != 0)
- warn("WARNING: NIS passwd update");
- /* non-fatal */
- }
-
- grp = GETGRNAM(name);
- if (grp != NULL &&
- (grp->gr_mem == NULL || *grp->gr_mem == NULL) &&
- strcmp(name, grname) == 0)
- delgrent(GETGRNAM(name));
- SETGRENT();
- while ((grp = GETGRENT()) != NULL) {
- int i, j;
- char group[MAXLOGNAME];
- if (grp->gr_mem == NULL)
- continue;
-
- for (i = 0; grp->gr_mem[i] != NULL; i++) {
- if (strcmp(grp->gr_mem[i], name) != 0)
- continue;
-
- for (j = i; grp->gr_mem[j] != NULL; j++)
- grp->gr_mem[j] = grp->gr_mem[j+1];
- strlcpy(group, grp->gr_name, MAXLOGNAME);
- chggrent(group, grp);
- }
- }
- ENDGRENT();
-
- pw_log(conf.userconf, M_DELETE, W_USER, "%s(%u) account removed", name,
- uid);
-
- /* Remove mail file */
- if (PWALTDIR() != PWF_ALT)
- unlinkat(conf.rootfd, file + 1, 0);
-
- /* Remove at jobs */
- if (!PWALTDIR() && getpwuid(uid) == NULL)
- rmat(uid);
+ if ((p = strchr(uname, '&')) != NULL) {
+ int l = strlen(pwd->pw_name);
+ int m = strlen(p);
- /* Remove home directory and contents */
- if (PWALTDIR() != PWF_ALT && conf.deletehome && *home == '/' &&
- getpwuid(uid) == NULL &&
- fstatat(conf.rootfd, home + 1, &st, 0) != -1) {
- rm_r(conf.rootfd, home, uid);
- pw_log(conf.userconf, M_DELETE, W_USER, "%s(%u) home '%s' %s"
- "removed", name, uid, home,
- fstatat(conf.rootfd, home + 1, &st, 0) == -1 ? "" : "not "
- "completely ");
+ memmove(p + l, p + 1, m);
+ memmove(p, pwd->pw_name, l);
+ *p = (char) toupper((unsigned char)*p);
}
-
- return (EXIT_SUCCESS);
-}
-
-static int
-print_user(struct passwd * pwd)
-{
- if (!conf.pretty) {
- char *buf;
-
- buf = conf.v7 ? pw_make_v7(pwd) : pw_make(pwd);
- printf("%s\n", buf);
- free(buf);
- } else {
- int j;
- char *p;
- struct group *grp = GETGRGID(pwd->pw_gid);
- char uname[60] = "User &", office[60] = "[None]",
- wphone[60] = "[None]", hphone[60] = "[None]";
- char acexpire[32] = "[None]", pwexpire[32] = "[None]";
- struct tm * tptr;
-
- if ((p = strtok(pwd->pw_gecos, ",")) != NULL) {
- strlcpy(uname, p, sizeof(uname));
- if ((p = strtok(NULL, ",")) != NULL) {
- strlcpy(office, p, sizeof(office));
- if ((p = strtok(NULL, ",")) != NULL) {
- strlcpy(wphone, p, sizeof(wphone));
- if ((p = strtok(NULL, "")) != NULL) {
- strlcpy(hphone, p,
- sizeof(hphone));
- }
- }
- }
- }
- /*
- * Handle '&' in gecos field
- */
- if ((p = strchr(uname, '&')) != NULL) {
- int l = strlen(pwd->pw_name);
- int m = strlen(p);
-
- memmove(p + l, p + 1, m);
- memmove(p, pwd->pw_name, l);
- *p = (char) toupper((unsigned char)*p);
- }
- if (pwd->pw_expire > (time_t)0 && (tptr = localtime(&pwd->pw_expire)) != NULL)
- strftime(acexpire, sizeof acexpire, "%c", tptr);
+ if (pwd->pw_expire > (time_t)0 && (tptr = localtime(&pwd->pw_expire)) != NULL)
+ strftime(acexpire, sizeof acexpire, "%c", tptr);
if (pwd->pw_change > (time_t)0 && (tptr = localtime(&pwd->pw_change)) != NULL)
- strftime(pwexpire, sizeof pwexpire, "%c", tptr);
- printf("Login Name: %-15s #%-12u Group: %-15s #%u\n"
- " Full Name: %s\n"
- " Home: %-26.26s Class: %s\n"
- " Shell: %-26.26s Office: %s\n"
- "Work Phone: %-26.26s Home Phone: %s\n"
- "Acc Expire: %-26.26s Pwd Expire: %s\n",
- pwd->pw_name, pwd->pw_uid,
- grp ? grp->gr_name : "(invalid)", pwd->pw_gid,
- uname, pwd->pw_dir, pwd->pw_class,
- pwd->pw_shell, office, wphone, hphone,
- acexpire, pwexpire);
- SETGRENT();
- j = 0;
- while ((grp=GETGRENT()) != NULL)
- {
- int i = 0;
- if (grp->gr_mem != NULL) {
- while (grp->gr_mem[i] != NULL)
- {
- if (strcmp(grp->gr_mem[i], pwd->pw_name)==0)
- {
- printf(j++ == 0 ? " Groups: %s" : ",%s", grp->gr_name);
- break;
- }
- ++i;
+ strftime(pwexpire, sizeof pwexpire, "%c", tptr);
+ printf("Login Name: %-15s #%-12ju Group: %-15s #%ju\n"
+ " Full Name: %s\n"
+ " Home: %-26.26s Class: %s\n"
+ " Shell: %-26.26s Office: %s\n"
+ "Work Phone: %-26.26s Home Phone: %s\n"
+ "Acc Expire: %-26.26s Pwd Expire: %s\n",
+ pwd->pw_name, (uintmax_t)pwd->pw_uid,
+ grp ? grp->gr_name : "(invalid)", (uintmax_t)pwd->pw_gid,
+ uname, pwd->pw_dir, pwd->pw_class,
+ pwd->pw_shell, office, wphone, hphone,
+ acexpire, pwexpire);
+ SETGRENT();
+ j = 0;
+ while ((grp=GETGRENT()) != NULL) {
+ int i = 0;
+ if (grp->gr_mem != NULL) {
+ while (grp->gr_mem[i] != NULL) {
+ if (strcmp(grp->gr_mem[i], pwd->pw_name)==0) {
+ printf(j++ == 0 ? " Groups: %s" : ",%s", grp->gr_name);
+ break;
}
+ ++i;
}
}
- ENDGRENT();
- printf("%s", j ? "\n" : "");
}
- return EXIT_SUCCESS;
+ ENDGRENT();
+ printf("%s", j ? "\n" : "");
+ return (EXIT_SUCCESS);
}
char *
@@ -1316,13 +600,12 @@ pw_checkname(char *name, int gecos)
showch, (ch - name), showtype);
}
if (!gecos && (ch - name) > LOGNAMESIZE)
- errx(EX_DATAERR, "name too long `%s' (max is %d)", name,
+ errx(EX_USAGE, "name too long `%s' (max is %d)", name,
LOGNAMESIZE);
return (name);
}
-
static void
rmat(uid_t uid)
{
@@ -1340,7 +623,8 @@ rmat(uid_t uid)
st.st_uid == uid) {
char tmp[MAXPATHLEN];
- snprintf(tmp, sizeof(tmp), "/usr/bin/atrm %s", e->d_name);
+ snprintf(tmp, sizeof(tmp), "/usr/bin/atrm %s",
+ e->d_name);
system(tmp);
}
}
@@ -1377,3 +661,1079 @@ rmopie(char const * name)
*/
fclose(fp);
}
+
+int
+pw_user_next(int argc, char **argv, char *name __unused)
+{
+ struct userconf *cnf = NULL;
+ const char *cfg = NULL;
+ int ch;
+ bool quiet = false;
+ uid_t next;
+
+ while ((ch = getopt(argc, argv, "Cq")) != -1) {
+ switch (ch) {
+ case 'C':
+ cfg = optarg;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ }
+ }
+
+ if (quiet)
+ freopen(_PATH_DEVNULL, "w", stderr);
+
+ cnf = get_userconfig(cfg);
+
+ next = pw_uidpolicy(cnf, -1);
+
+ printf("%ju:", (uintmax_t)next);
+ pw_groupnext(cnf, quiet);
+
+ return (EXIT_SUCCESS);
+}
+
+int
+pw_user_show(int argc, char **argv, char *arg1)
+{
+ struct passwd *pwd = NULL;
+ char *name = NULL;
+ intmax_t id = -1;
+ int ch;
+ bool all = false;
+ bool pretty = false;
+ bool force = false;
+ bool v7 = false;
+ bool quiet = false;
+
+ if (arg1 != NULL) {
+ if (arg1[strspn(arg1, "0123456789")] == '\0')
+ id = pw_checkid(arg1, UID_MAX);
+ else
+ name = arg1;
+ }
+
+ while ((ch = getopt(argc, argv, "C:qn:u:FPa7")) != -1) {
+ switch (ch) {
+ case 'C':
+ /* ignore compatibility */
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'n':
+ name = optarg;
+ break;
+ case 'u':
+ id = pw_checkid(optarg, UID_MAX);
+ break;
+ case 'F':
+ force = true;
+ break;
+ case 'P':
+ pretty = true;
+ break;
+ case 'a':
+ all = true;
+ break;
+ case 7:
+ v7 = true;
+ break;
+ }
+ }
+
+ if (quiet)
+ freopen(_PATH_DEVNULL, "w", stderr);
+
+ if (all) {
+ SETPWENT();
+ while ((pwd = GETPWENT()) != NULL)
+ print_user(pwd, pretty, v7);
+ ENDPWENT();
+ return (EXIT_SUCCESS);
+ }
+
+ if (id < 0 && name == NULL)
+ errx(EX_DATAERR, "username or id required");
+
+ pwd = (name != NULL) ? GETPWNAM(pw_checkname(name, 0)) : GETPWUID(id);
+ if (pwd == NULL) {
+ if (force) {
+ pwd = &fakeuser;
+ } else {
+ if (name == NULL)
+ errx(EX_NOUSER, "no such uid `%ju'",
+ (uintmax_t) id);
+ errx(EX_NOUSER, "no such user `%s'", name);
+ }
+ }
+
+ return (print_user(pwd, pretty, v7));
+}
+
+int
+pw_user_del(int argc, char **argv, char *arg1)
+{
+ struct userconf *cnf = NULL;
+ struct passwd *pwd = NULL;
+ struct group *gr, *grp;
+ char *name = NULL;
+ char grname[MAXLOGNAME];
+ char *nispasswd = NULL;
+ char file[MAXPATHLEN];
+ char home[MAXPATHLEN];
+ const char *cfg = NULL;
+ struct stat st;
+ intmax_t id = -1;
+ int ch, rc;
+ bool nis = false;
+ bool deletehome = false;
+ bool quiet = false;
+
+ if (arg1 != NULL) {
+ if (arg1[strspn(arg1, "0123456789")] == '\0')
+ id = pw_checkid(arg1, UID_MAX);
+ else
+ name = arg1;
+ }
+
+ while ((ch = getopt(argc, argv, "C:qn:u:rYy:")) != -1) {
+ switch (ch) {
+ case 'C':
+ cfg = optarg;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'n':
+ name = optarg;
+ break;
+ case 'u':
+ id = pw_checkid(optarg, UID_MAX);
+ break;
+ case 'r':
+ deletehome = true;
+ break;
+ case 'y':
+ nispasswd = optarg;
+ break;
+ case 'Y':
+ nis = true;
+ break;
+ }
+ }
+
+ if (quiet)
+ freopen(_PATH_DEVNULL, "w", stderr);
+
+ if (id < 0 && name == NULL)
+ errx(EX_DATAERR, "username or id required");
+
+ cnf = get_userconfig(cfg);
+
+ if (nispasswd == NULL)
+ nispasswd = cnf->nispasswd;
+
+ pwd = (name != NULL) ? GETPWNAM(pw_checkname(name, 0)) : GETPWUID(id);
+ if (pwd == NULL) {
+ if (name == NULL)
+ errx(EX_NOUSER, "no such uid `%ju'", (uintmax_t) id);
+ errx(EX_NOUSER, "no such user `%s'", name);
+ }
+
+ if (PWF._altdir == PWF_REGULAR &&
+ ((pwd->pw_fields & _PWF_SOURCE) != _PWF_FILES)) {
+ if ((pwd->pw_fields & _PWF_SOURCE) == _PWF_NIS) {
+ if (!nis && nispasswd && *nispasswd != '/')
+ errx(EX_NOUSER, "Cannot remove NIS user `%s'",
+ name);
+ } else {
+ errx(EX_NOUSER, "Cannot remove non local user `%s'",
+ name);
+ }
+ }
+
+ id = pwd->pw_uid;
+ if (name == NULL)
+ name = pwd->pw_name;
+
+ if (strcmp(pwd->pw_name, "root") == 0)
+ errx(EX_DATAERR, "cannot remove user 'root'");
+
+ /* Remove opie record from /etc/opiekeys */
+ if (PWALTDIR() != PWF_ALT)
+ rmopie(pwd->pw_name);
+
+ if (!PWALTDIR()) {
+ /* Remove crontabs */
+ snprintf(file, sizeof(file), "/var/cron/tabs/%s", pwd->pw_name);
+ if (access(file, F_OK) == 0) {
+ snprintf(file, sizeof(file), "crontab -u %s -r",
+ pwd->pw_name);
+ system(file);
+ }
+ }
+
+ /*
+ * Save these for later, since contents of pwd may be
+ * invalidated by deletion
+ */
+ snprintf(file, sizeof(file), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
+ strlcpy(home, pwd->pw_dir, sizeof(home));
+ gr = GETGRGID(pwd->pw_gid);
+ if (gr != NULL)
+ strlcpy(grname, gr->gr_name, LOGNAMESIZE);
+ else
+ grname[0] = '\0';
+
+ rc = delpwent(pwd);
+ if (rc == -1)
+ err(EX_IOERR, "user '%s' does not exist", pwd->pw_name);
+ else if (rc != 0)
+ err(EX_IOERR, "passwd update");
+
+ if (nis && nispasswd && *nispasswd=='/') {
+ rc = delnispwent(nispasswd, name);
+ if (rc == -1)
+ warnx("WARNING: user '%s' does not exist in NIS passwd",
+ pwd->pw_name);
+ else if (rc != 0)
+ warn("WARNING: NIS passwd update");
+ }
+
+ grp = GETGRNAM(name);
+ if (grp != NULL &&
+ (grp->gr_mem == NULL || *grp->gr_mem == NULL) &&
+ strcmp(name, grname) == 0)
+ delgrent(GETGRNAM(name));
+ SETGRENT();
+ while ((grp = GETGRENT()) != NULL) {
+ int i, j;
+ char group[MAXLOGNAME];
+ if (grp->gr_mem == NULL)
+ continue;
+
+ for (i = 0; grp->gr_mem[i] != NULL; i++) {
+ if (strcmp(grp->gr_mem[i], name) != 0)
+ continue;
+
+ for (j = i; grp->gr_mem[j] != NULL; j++)
+ grp->gr_mem[j] = grp->gr_mem[j+1];
+ strlcpy(group, grp->gr_name, MAXLOGNAME);
+ chggrent(group, grp);
+ }
+ }
+ ENDGRENT();
+
+ pw_log(cnf, M_DELETE, W_USER, "%s(%ju) account removed", name,
+ (uintmax_t)id);
+
+ /* Remove mail file */
+ if (PWALTDIR() != PWF_ALT)
+ unlinkat(conf.rootfd, file + 1, 0);
+
+ /* Remove at jobs */
+ if (!PWALTDIR() && getpwuid(id) == NULL)
+ rmat(id);
+
+ /* Remove home directory and contents */
+ if (PWALTDIR() != PWF_ALT && deletehome && *home == '/' &&
+ GETPWUID(id) == NULL &&
+ fstatat(conf.rootfd, home + 1, &st, 0) != -1) {
+ rm_r(conf.rootfd, home, id);
+ pw_log(cnf, M_DELETE, W_USER, "%s(%ju) home '%s' %s"
+ "removed", name, (uintmax_t)id, home,
+ fstatat(conf.rootfd, home + 1, &st, 0) == -1 ? "" : "not "
+ "completely ");
+ }
+
+ return (EXIT_SUCCESS);
+}
+
+int
+pw_user_lock(int argc, char **argv, char *arg1)
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "Cq")) != -1) {
+ switch (ch) {
+ case 'C':
+ case 'q':
+ /* compatibility */
+ break;
+ }
+ }
+
+ return (pw_userlock(arg1, M_LOCK));
+}
+
+int
+pw_user_unlock(int argc, char **argv, char *arg1)
+{
+ int ch;
+
+ while ((ch = getopt(argc, argv, "Cq")) != -1) {
+ switch (ch) {
+ case 'C':
+ case 'q':
+ /* compatibility */
+ break;
+ }
+ }
+
+ return (pw_userlock(arg1, M_UNLOCK));
+}
+
+static struct group *
+group_from_name_or_id(char *name)
+{
+ const char *errstr = NULL;
+ struct group *grp;
+ uintmax_t id;
+
+ if ((grp = GETGRNAM(name)) == NULL) {
+ id = strtounum(name, 0, GID_MAX, &errstr);
+ if (errstr)
+ errx(EX_NOUSER, "group `%s' does not exist", name);
+ grp = GETGRGID(id);
+ if (grp == NULL)
+ errx(EX_NOUSER, "group `%s' does not exist", name);
+ }
+
+ return (grp);
+}
+
+static void
+split_groups(StringList **groups, char *groupsstr)
+{
+ struct group *grp;
+ char *p;
+ char tok[] = ", \t";
+
+ for (p = strtok(groupsstr, tok); p != NULL; p = strtok(NULL, tok)) {
+ grp = group_from_name_or_id(p);
+ if (*groups == NULL)
+ *groups = sl_init();
+ sl_add(*groups, newstr(grp->gr_name));
+ }
+}
+
+static void
+validate_grname(struct userconf *cnf, char *group)
+{
+ struct group *grp;
+
+ if (group == NULL || *group == '\0') {
+ cnf->default_group = "";
+ return;
+ }
+ grp = group_from_name_or_id(group);
+ cnf->default_group = newstr(grp->gr_name);
+}
+
+static mode_t
+validate_mode(char *mode)
+{
+ mode_t m;
+ void *set;
+
+ if ((set = setmode(mode)) == NULL)
+ errx(EX_DATAERR, "invalid directory creation mode '%s'", mode);
+
+ m = getmode(set, _DEF_DIRMODE);
+ free(set);
+ return (m);
+}
+
+static void
+mix_config(struct userconf *cmdcnf, struct userconf *cfg)
+{
+
+ if (cmdcnf->default_password == 0)
+ cmdcnf->default_password = cfg->default_password;
+ if (cmdcnf->reuse_uids == 0)
+ cmdcnf->reuse_uids = cfg->reuse_uids;
+ if (cmdcnf->reuse_gids == 0)
+ cmdcnf->reuse_gids = cfg->reuse_gids;
+ if (cmdcnf->nispasswd == NULL)
+ cmdcnf->nispasswd = cfg->nispasswd;
+ if (cmdcnf->dotdir == NULL)
+ cmdcnf->dotdir = cfg->dotdir;
+ if (cmdcnf->newmail == NULL)
+ cmdcnf->newmail = cfg->newmail;
+ if (cmdcnf->logfile == NULL)
+ cmdcnf->logfile = cfg->logfile;
+ if (cmdcnf->home == NULL)
+ cmdcnf->home = cfg->home;
+ if (cmdcnf->homemode == 0)
+ cmdcnf->homemode = cfg->homemode;
+ if (cmdcnf->shelldir == NULL)
+ cmdcnf->shelldir = cfg->shelldir;
+ if (cmdcnf->shells == NULL)
+ cmdcnf->shells = cfg->shells;
+ if (cmdcnf->shell_default == NULL)
+ cmdcnf->shell_default = cfg->shell_default;
+ if (cmdcnf->default_group == NULL)
+ cmdcnf->default_group = cfg->default_group;
+ if (cmdcnf->groups == NULL)
+ cmdcnf->groups = cfg->groups;
+ if (cmdcnf->default_class == NULL)
+ cmdcnf->default_class = cfg->default_class;
+ if (cmdcnf->min_uid == 0)
+ cmdcnf->min_uid = cfg->min_uid;
+ if (cmdcnf->max_uid == 0)
+ cmdcnf->max_uid = cfg->max_uid;
+ if (cmdcnf->min_gid == 0)
+ cmdcnf->min_gid = cfg->min_gid;
+ if (cmdcnf->max_gid == 0)
+ cmdcnf->max_gid = cfg->max_gid;
+ if (cmdcnf->expire_days == 0)
+ cmdcnf->expire_days = cfg->expire_days;
+ if (cmdcnf->password_days == 0)
+ cmdcnf->password_days = cfg->password_days;
+}
+
+int
+pw_user_add(int argc, char **argv, char *arg1)
+{
+ struct userconf *cnf, *cmdcnf;
+ struct passwd *pwd;
+ struct group *grp;
+ struct stat st;
+ char args[] = "C:qn:u:c:d:e:p:g:G:mM:k:s:oL:i:w:h:H:Db:NPy:Y";
+ char line[_PASSWORD_LEN+1], path[MAXPATHLEN];
+ char *gecos, *homedir, *skel, *walk, *userid, *groupid, *grname;
+ char *default_passwd, *name, *p;
+ const char *cfg;
+ login_cap_t *lc;
+ FILE *pfp, *fp;
+ intmax_t id = -1;
+ time_t now;
+ int rc, ch, fd = -1;
+ size_t i;
+ bool dryrun, nis, pretty, quiet, createhome, precrypted, genconf;
+
+ dryrun = nis = pretty = quiet = createhome = precrypted = false;
+ genconf = false;
+ gecos = homedir = skel = userid = groupid = default_passwd = NULL;
+ grname = name = NULL;
+
+ if ((cmdcnf = calloc(1, sizeof(struct userconf))) == NULL)
+ err(EXIT_FAILURE, "calloc()");
+
+ if (arg1 != NULL) {
+ if (arg1[strspn(arg1, "0123456789")] == '\0')
+ id = pw_checkid(arg1, UID_MAX);
+ else
+ name = arg1;
+ }
+
+ while ((ch = getopt(argc, argv, args)) != -1) {
+ switch (ch) {
+ case 'C':
+ cfg = optarg;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'n':
+ name = optarg;
+ break;
+ case 'u':
+ userid = optarg;
+ break;
+ case 'c':
+ gecos = pw_checkname(optarg, 1);
+ break;
+ case 'd':
+ homedir = optarg;
+ break;
+ case 'e':
+ now = time(NULL);
+ cmdcnf->expire_days = parse_date(now, optarg);
+ break;
+ case 'p':
+ now = time(NULL);
+ cmdcnf->password_days = parse_date(now, optarg);
+ break;
+ case 'g':
+ validate_grname(cmdcnf, optarg);
+ grname = optarg;
+ break;
+ case 'G':
+ split_groups(&cmdcnf->groups, optarg);
+ break;
+ case 'm':
+ createhome = true;
+ break;
+ case 'M':
+ cmdcnf->homemode = validate_mode(optarg);
+ break;
+ case 'k':
+ walk = skel = optarg;
+ if (*walk == '/')
+ walk++;
+ if (fstatat(conf.rootfd, walk, &st, 0) == -1)
+ errx(EX_OSFILE, "skeleton `%s' does not "
+ "exists", skel);
+ if (!S_ISDIR(st.st_mode))
+ errx(EX_OSFILE, "skeleton `%s' is not a "
+ "directory", skel);
+ cmdcnf->dotdir = skel;
+ break;
+ case 's':
+ cmdcnf->shell_default = optarg;
+ break;
+ case 'o':
+ conf.checkduplicate = false;
+ break;
+ case 'L':
+ cmdcnf->default_class = pw_checkname(optarg, 0);
+ break;
+ case 'i':
+ groupid = optarg;
+ break;
+ case 'w':
+ default_passwd = optarg;
+ break;
+ case 'H':
+ if (fd != -1)
+ errx(EX_USAGE, "'-h' and '-H' are mutually "
+ "exclusive options");
+ fd = pw_checkfd(optarg);
+ precrypted = true;
+ if (fd == '-')
+ errx(EX_USAGE, "-H expects a file descriptor");
+ break;
+ case 'h':
+ if (fd != -1)
+ errx(EX_USAGE, "'-h' and '-H' are mutually "
+ "exclusive options");
+ fd = pw_checkfd(optarg);
+ break;
+ case 'D':
+ genconf = true;
+ break;
+ case 'b':
+ cmdcnf->home = optarg;
+ break;
+ case 'N':
+ dryrun = true;
+ break;
+ case 'P':
+ pretty = true;
+ break;
+ case 'y':
+ cmdcnf->nispasswd = optarg;
+ break;
+ case 'Y':
+ nis = true;
+ break;
+ }
+ }
+
+ if (geteuid() != 0 && ! dryrun)
+ errx(EX_NOPERM, "you must be root");
+
+ if (quiet)
+ freopen(_PATH_DEVNULL, "w", stderr);
+
+ cnf = get_userconfig(cfg);
+
+ mix_config(cmdcnf, cnf);
+ if (default_passwd)
+ cmdcnf->default_password = boolean_val(default_passwd,
+ cnf->default_password);
+ if (genconf) {
+ if (name != NULL)
+ errx(EX_DATAERR, "can't combine `-D' with `-n name'");
+ if (userid != NULL) {
+ if ((p = strtok(userid, ", \t")) != NULL)
+ cmdcnf->min_uid = pw_checkid(p, UID_MAX);
+ if (cmdcnf->min_uid == 0)
+ cmdcnf->min_uid = 1000;
+ if ((p = strtok(NULL, " ,\t")) != NULL)
+ cmdcnf->max_uid = pw_checkid(p, UID_MAX);
+ if (cmdcnf->max_uid == 0)
+ cmdcnf->max_uid = 32000;
+ }
+ if (groupid != NULL) {
+ if ((p = strtok(groupid, ", \t")) != NULL)
+ cmdcnf->min_gid = pw_checkid(p, GID_MAX);
+ if (cmdcnf->min_gid == 0)
+ cmdcnf->min_gid = 1000;
+ if ((p = strtok(NULL, " ,\t")) != NULL)
+ cmdcnf->max_gid = pw_checkid(p, GID_MAX);
+ if (cmdcnf->max_gid == 0)
+ cmdcnf->max_gid = 32000;
+ }
+ if (write_userconfig(cmdcnf, cfg))
+ return (EXIT_SUCCESS);
+ err(EX_IOERR, "config update");
+ }
+
+ if (userid)
+ id = pw_checkid(userid, UID_MAX);
+ if (id < 0 && name == NULL)
+ errx(EX_DATAERR, "user name or id required");
+
+ if (name == NULL)
+ errx(EX_DATAERR, "login name required");
+
+ if (GETPWNAM(name) != NULL)
+ errx(EX_DATAERR, "login name `%s' already exists", name);
+
+ pwd = &fakeuser;
+ pwd->pw_name = name;
+ pwd->pw_class = cmdcnf->default_class ? cmdcnf->default_class : "";
+ pwd->pw_uid = pw_uidpolicy(cmdcnf, id);
+ pwd->pw_gid = pw_gidpolicy(cnf, grname, pwd->pw_name,
+ (gid_t) pwd->pw_uid, dryrun);
+ pwd->pw_change = cmdcnf->password_days;
+ pwd->pw_expire = cmdcnf->expire_days;
+ pwd->pw_dir = pw_homepolicy(cmdcnf, homedir, pwd->pw_name);
+ pwd->pw_shell = pw_shellpolicy(cmdcnf);
+ lc = login_getpwclass(pwd);
+ if (lc == NULL || login_setcryptfmt(lc, "sha512", NULL) == NULL)
+ warn("setting crypt(3) format");
+ login_close(lc);
+ pwd->pw_passwd = pw_password(cmdcnf, pwd->pw_name, dryrun);
+ if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0)
+ warnx("WARNING: new account `%s' has a uid of 0 "
+ "(superuser access!)", pwd->pw_name);
+ if (gecos)
+ pwd->pw_gecos = gecos;
+
+ if (fd != -1)
+ pw_set_passwd(pwd, fd, precrypted, false);
+
+ if (dryrun)
+ return (print_user(pwd, pretty, false));
+
+ if ((rc = addpwent(pwd)) != 0) {
+ if (rc == -1)
+ errx(EX_IOERR, "user '%s' already exists",
+ pwd->pw_name);
+ else if (rc != 0)
+ err(EX_IOERR, "passwd file update");
+ }
+ if (nis && cmdcnf->nispasswd && *cmdcnf->nispasswd == '/') {
+ printf("%s\n", cmdcnf->nispasswd);
+ rc = addnispwent(cmdcnf->nispasswd, pwd);
+ if (rc == -1)
+ warnx("User '%s' already exists in NIS passwd",
+ pwd->pw_name);
+ else if (rc != 0)
+ warn("NIS passwd update");
+ /* NOTE: we treat NIS-only update errors as non-fatal */
+ }
+
+ if (cmdcnf->groups != NULL) {
+ for (i = 0; i < cmdcnf->groups->sl_cur; i++) {
+ grp = GETGRNAM(cmdcnf->groups->sl_str[i]);
+ grp = gr_add(grp, pwd->pw_name);
+ /*
+ * grp can only be NULL in 2 cases:
+ * - the new member is already a member
+ * - a problem with memory occurs
+ * in both cases we want to skip now.
+ */
+ if (grp == NULL)
+ continue;
+ chggrent(grp->gr_name, grp);
+ free(grp);
+ }
+ }
+
+ pwd = GETPWNAM(name);
+ if (pwd == NULL)
+ errx(EX_NOUSER, "user '%s' disappeared during update", name);
+
+ grp = GETGRGID(pwd->pw_gid);
+ pw_log(cnf, M_ADD, W_USER, "%s(%ju):%s(%ju):%s:%s:%s",
+ pwd->pw_name, (uintmax_t)pwd->pw_uid,
+ grp ? grp->gr_name : "unknown",
+ (uintmax_t)(grp ? grp->gr_gid : (uid_t)-1),
+ pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell);
+
+ /*
+ * let's touch and chown the user's mail file. This is not
+ * strictly necessary under BSD with a 0755 maildir but it also
+ * doesn't hurt anything to create the empty mailfile
+ */
+ if (PWALTDIR() != PWF_ALT) {
+ snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR,
+ pwd->pw_name);
+ /* Preserve contents & mtime */
+ close(openat(conf.rootfd, path +1, O_RDWR | O_CREAT, 0600));
+ fchownat(conf.rootfd, path + 1, pwd->pw_uid, pwd->pw_gid,
+ AT_SYMLINK_NOFOLLOW);
+ }
+
+ /*
+ * Let's create and populate the user's home directory. Note
+ * that this also `works' for editing users if -m is used, but
+ * existing files will *not* be overwritten.
+ */
+ if (PWALTDIR() != PWF_ALT && createhome && pwd->pw_dir &&
+ *pwd->pw_dir == '/' && pwd->pw_dir[1])
+ create_and_populate_homedir(cmdcnf, pwd, cmdcnf->dotdir,
+ cmdcnf->homemode, false);
+
+ if (!PWALTDIR() && cmdcnf->newmail && *cmdcnf->newmail &&
+ (fp = fopen(cnf->newmail, "r")) != NULL) {
+ if ((pfp = popen(_PATH_SENDMAIL " -t", "w")) == NULL)
+ warn("sendmail");
+ else {
+ fprintf(pfp, "From: root\n" "To: %s\n"
+ "Subject: Welcome!\n\n", pwd->pw_name);
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ /* Do substitutions? */
+ fputs(line, pfp);
+ }
+ pclose(pfp);
+ pw_log(cnf, M_ADD, W_USER, "%s(%ju) new user mail sent",
+ pwd->pw_name, (uintmax_t)pwd->pw_uid);
+ }
+ fclose(fp);
+ }
+
+ if (nis && nis_update() == 0)
+ pw_log(cnf, M_ADD, W_USER, "NIS maps updated");
+
+ return (EXIT_SUCCESS);
+}
+
+int
+pw_user_mod(int argc, char **argv, char *arg1)
+{
+ struct userconf *cnf;
+ struct passwd *pwd;
+ struct group *grp;
+ StringList *groups = NULL;
+ char args[] = "C:qn:u:c:d:e:p:g:G:mM:l:k:s:w:L:h:H:NPYy:";
+ const char *cfg;
+ char *gecos, *homedir, *grname, *name, *newname, *walk, *skel, *shell;
+ char *passwd, *class, *nispasswd;
+ login_cap_t *lc;
+ struct stat st;
+ intmax_t id = -1;
+ int ch, fd = -1;
+ size_t i, j;
+ bool quiet, createhome, pretty, dryrun, nis, edited, docreatehome;
+ bool precrypted;
+ mode_t homemode = 0;
+ time_t expire_days, password_days, now;
+
+ expire_days = password_days = -1;
+ gecos = homedir = grname = name = newname = skel = shell =NULL;
+ passwd = NULL;
+ class = nispasswd = NULL;
+ quiet = createhome = pretty = dryrun = nis = precrypted = false;
+ edited = docreatehome = false;
+
+ if (arg1 != NULL) {
+ if (arg1[strspn(arg1, "0123456789")] == '\0')
+ id = pw_checkid(arg1, UID_MAX);
+ else
+ name = arg1;
+ }
+
+ while ((ch = getopt(argc, argv, args)) != -1) {
+ switch (ch) {
+ case 'C':
+ cfg = optarg;
+ break;
+ case 'q':
+ quiet = true;
+ break;
+ case 'n':
+ name = optarg;
+ break;
+ case 'u':
+ id = pw_checkid(optarg, UID_MAX);
+ break;
+ case 'c':
+ gecos = pw_checkname(optarg, 1);
+ break;
+ case 'd':
+ homedir = optarg;
+ break;
+ case 'e':
+ now = time(NULL);
+ expire_days = parse_date(now, optarg);
+ break;
+ case 'p':
+ now = time(NULL);
+ password_days = parse_date(now, optarg);
+ break;
+ case 'g':
+ group_from_name_or_id(optarg);
+ grname = optarg;
+ break;
+ case 'G':
+ split_groups(&groups, optarg);
+ break;
+ case 'm':
+ createhome = true;
+ break;
+ case 'M':
+ homemode = validate_mode(optarg);
+ break;
+ case 'l':
+ newname = optarg;
+ break;
+ case 'k':
+ walk = skel = optarg;
+ if (*walk == '/')
+ walk++;
+ if (fstatat(conf.rootfd, walk, &st, 0) == -1)
+ errx(EX_OSFILE, "skeleton `%s' does not "
+ "exists", skel);
+ if (!S_ISDIR(st.st_mode))
+ errx(EX_OSFILE, "skeleton `%s' is not a "
+ "directory", skel);
+ break;
+ case 's':
+ shell = optarg;
+ break;
+ case 'w':
+ passwd = optarg;
+ break;
+ case 'L':
+ class = pw_checkname(optarg, 0);
+ break;
+ case 'H':
+ if (fd != -1)
+ errx(EX_USAGE, "'-h' and '-H' are mutually "
+ "exclusive options");
+ fd = pw_checkfd(optarg);
+ precrypted = true;
+ if (fd == '-')
+ errx(EX_USAGE, "-H expects a file descriptor");
+ break;
+ case 'h':
+ if (fd != -1)
+ errx(EX_USAGE, "'-h' and '-H' are mutually "
+ "exclusive options");
+ fd = pw_checkfd(optarg);
+ break;
+ case 'N':
+ dryrun = true;
+ break;
+ case 'P':
+ pretty = true;
+ break;
+ case 'y':
+ nispasswd = optarg;
+ break;
+ case 'Y':
+ nis = true;
+ break;
+ }
+ }
+
+ if (geteuid() != 0 && ! dryrun)
+ errx(EX_NOPERM, "you must be root");
+
+ if (quiet)
+ freopen(_PATH_DEVNULL, "w", stderr);
+
+ cnf = get_userconfig(cfg);
+
+ if (id < 0 && name == NULL)
+ errx(EX_DATAERR, "username or id required");
+
+ pwd = (name != NULL) ? GETPWNAM(pw_checkname(name, 0)) : GETPWUID(id);
+ if (pwd == NULL) {
+ if (name == NULL)
+ errx(EX_NOUSER, "no such uid `%ju'",
+ (uintmax_t) id);
+ errx(EX_NOUSER, "no such user `%s'", name);
+ }
+
+ if (name == NULL)
+ name = pwd->pw_name;
+
+ if (nis && nispasswd == NULL)
+ nispasswd = cnf->nispasswd;
+
+ if (PWF._altdir == PWF_REGULAR &&
+ ((pwd->pw_fields & _PWF_SOURCE) != _PWF_FILES)) {
+ if ((pwd->pw_fields & _PWF_SOURCE) == _PWF_NIS) {
+ if (!nis && nispasswd && *nispasswd != '/')
+ errx(EX_NOUSER, "Cannot modify NIS user `%s'",
+ name);
+ } else {
+ errx(EX_NOUSER, "Cannot modify non local user `%s'",
+ name);
+ }
+ }
+
+ if (newname) {
+ if (strcmp(pwd->pw_name, "root") == 0)
+ errx(EX_DATAERR, "can't rename `root' account");
+ if (strcmp(pwd->pw_name, newname) != 0) {
+ pwd->pw_name = pw_checkname(newname, 0);
+ edited = true;
+ }
+ }
+
+ if (id > 0 && pwd->pw_uid != id) {
+ pwd->pw_uid = id;
+ edited = true;
+ if (pwd->pw_uid != 0 && strcmp(pwd->pw_name, "root") == 0)
+ errx(EX_DATAERR, "can't change uid of `root' account");
+ if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0)
+ warnx("WARNING: account `%s' will have a uid of 0 "
+ "(superuser access!)", pwd->pw_name);
+ }
+
+ if (grname && pwd->pw_uid != 0) {
+ grp = GETGRNAM(grname);
+ if (grp == NULL)
+ grp = GETGRGID(pw_checkid(grname, GID_MAX));
+ if (grp->gr_gid != pwd->pw_gid) {
+ pwd->pw_gid = grp->gr_gid;
+ edited = true;
+ }
+ }
+
+ if (password_days >= 0 && pwd->pw_change != password_days) {
+ pwd->pw_change = password_days;
+ edited = true;
+ }
+
+ if (expire_days >= 0 && pwd->pw_expire != expire_days) {
+ pwd->pw_expire = expire_days;
+ edited = true;
+ }
+
+ if (shell) {
+ shell = shell_path(cnf->shelldir, cnf->shells, shell);
+ if (shell == NULL)
+ shell = "";
+ if (strcmp(shell, pwd->pw_shell) != 0) {
+ pwd->pw_shell = shell;
+ edited = true;
+ }
+ }
+
+ if (class && strcmp(pwd->pw_class, class) != 0) {
+ pwd->pw_class = class;
+ edited = true;
+ }
+
+ if (homedir && strcmp(pwd->pw_dir, homedir) != 0) {
+ pwd->pw_dir = homedir;
+ if (fstatat(conf.rootfd, pwd->pw_dir, &st, 0) == -1) {
+ if (!createhome)
+ warnx("WARNING: home `%s' does not exist",
+ pwd->pw_dir);
+ else
+ docreatehome = true;
+ } else if (!S_ISDIR(st.st_mode)) {
+ warnx("WARNING: home `%s' is not a directory",
+ pwd->pw_dir);
+ }
+ }
+
+ if (passwd && conf.fd == -1) {
+ lc = login_getpwclass(pwd);
+ if (lc == NULL || login_setcryptfmt(lc, "sha512", NULL) == NULL)
+ warn("setting crypt(3) format");
+ login_close(lc);
+ pwd->pw_passwd = pw_password(cnf, pwd->pw_name, dryrun);
+ edited = true;
+ }
+
+ if (gecos && strcmp(pwd->pw_gecos, gecos) != 0) {
+ pwd->pw_gecos = gecos;
+ edited = true;
+ }
+
+ if (fd != -1)
+ edited = pw_set_passwd(pwd, fd, precrypted, true);
+
+ if (dryrun)
+ return (print_user(pwd, pretty, false));
+
+ if (edited) /* Only updated this if required */
+ perform_chgpwent(name, pwd, nis ? nispasswd : NULL);
+ /* Now perform the needed changes concern groups */
+ if (groups != NULL) {
+ /* Delete User from groups using old name */
+ SETGRENT();
+ while ((grp = GETGRENT()) != NULL) {
+ if (grp->gr_mem == NULL)
+ continue;
+ for (i = 0; grp->gr_mem[i] != NULL; i++) {
+ if (strcmp(grp->gr_mem[i] , name) != 0)
+ continue;
+ for (j = i; grp->gr_mem[j] != NULL ; j++)
+ grp->gr_mem[j] = grp->gr_mem[j+1];
+ chggrent(grp->gr_name, grp);
+ break;
+ }
+ }
+ ENDGRENT();
+ /* Add the user to the needed groups */
+ for (i = 0; i < groups->sl_cur; i++) {
+ grp = GETGRNAM(groups->sl_str[i]);
+ grp = gr_add(grp, pwd->pw_name);
+ if (grp == NULL)
+ continue;
+ chggrent(grp->gr_name, grp);
+ free(grp);
+ }
+ }
+ /* In case of rename we need to walk over the different groups */
+ if (newname) {
+ SETGRENT();
+ while ((grp = GETGRENT()) != NULL) {
+ if (grp->gr_mem == NULL)
+ continue;
+ for (i = 0; grp->gr_mem[i] != NULL; i++) {
+ if (strcmp(grp->gr_mem[i], name) != 0)
+ continue;
+ grp->gr_mem[i] = newname;
+ chggrent(grp->gr_name, grp);
+ break;
+ }
+ }
+ }
+
+ /* go get a current version of pwd */
+ if (newname)
+ name = newname;
+ pwd = GETPWNAM(name);
+ if (pwd == NULL)
+ errx(EX_NOUSER, "user '%s' disappeared during update", name);
+ grp = GETGRGID(pwd->pw_gid);
+ pw_log(cnf, M_UPDATE, W_USER, "%s(%ju):%s(%ju):%s:%s:%s",
+ pwd->pw_name, (uintmax_t)pwd->pw_uid,
+ grp ? grp->gr_name : "unknown",
+ (uintmax_t)(grp ? grp->gr_gid : (uid_t)-1),
+ pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell);
+
+ /*
+ * Let's create and populate the user's home directory. Note
+ * that this also `works' for editing users if -m is used, but
+ * existing files will *not* be overwritten.
+ */
+ if (PWALTDIR() != PWF_ALT && docreatehome && pwd->pw_dir &&
+ *pwd->pw_dir == '/' && pwd->pw_dir[1]) {
+ if (!skel)
+ skel = cnf->dotdir;
+ if (homemode == 0)
+ homemode = cnf->homemode;
+ create_and_populate_homedir(cnf, pwd, skel, homemode, true);
+ }
+
+ if (nis && nis_update() == 0)
+ pw_log(cnf, M_UPDATE, W_USER, "NIS maps updated");
+
+ return (EXIT_SUCCESS);
+}
diff --git a/usr.sbin/pw/pw_utils.c b/usr.sbin/pw/pw_utils.c
new file mode 100644
index 0000000..1a4f812
--- /dev/null
+++ b/usr.sbin/pw/pw_utils.c
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (C) 2015 Baptiste Daroussin <bapt@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
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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/types.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <inttypes.h>
+#include <sysexits.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pw.h"
+
+int
+pw_checkfd(char *nptr)
+{
+ const char *errstr;
+ int fd = -1;
+
+ if (strcmp(nptr, "-") == 0)
+ return '-';
+ fd = strtonum(nptr, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ errx(EX_USAGE, "Bad file descriptor '%s': %s",
+ nptr, errstr);
+ return (fd);
+}
+
+uintmax_t
+pw_checkid(char *nptr, uintmax_t maxval)
+{
+ const char *errstr = NULL;
+ uintmax_t id;
+
+ id = strtounum(nptr, 0, maxval, &errstr);
+ if (errstr)
+ errx(EX_USAGE, "Bad id '%s': %s", nptr, errstr);
+ return (id);
+}
+
+struct userconf *
+get_userconfig(const char *config)
+{
+ char defaultcfg[MAXPATHLEN];
+
+ if (config != NULL)
+ return (read_userconfig(config));
+ snprintf(defaultcfg, sizeof(defaultcfg), "%s/pw.conf", conf.etcpath);
+ return (read_userconfig(defaultcfg));
+}
+
+int
+nis_update(void) {
+ pid_t pid;
+ int i;
+
+ fflush(NULL);
+ if ((pid = fork()) == -1) {
+ warn("fork()");
+ return (1);
+ }
+ if (pid == 0) {
+ execlp("/usr/bin/make", "make", "-C", "/var/yp/", (char*) NULL);
+ _exit(1);
+ }
+ waitpid(pid, &i, 0);
+ if ((i = WEXITSTATUS(i)) != 0)
+ errx(i, "make exited with status %d", i);
+ return (i);
+}
diff --git a/usr.sbin/pw/pwupd.c b/usr.sbin/pw/pwupd.c
index f9e1959..ee23952 100644
--- a/usr.sbin/pw/pwupd.c
+++ b/usr.sbin/pw/pwupd.c
@@ -29,18 +29,16 @@ static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <pwd.h>
+#include <libutil.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <pwd.h>
-#include <libutil.h>
-#include <errno.h>
-#include <err.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <sys/wait.h>
#include "pwupd.h"
diff --git a/usr.sbin/pw/pwupd.h b/usr.sbin/pw/pwupd.h
index 054c5a5..7fecffb 100644
--- a/usr.sbin/pw/pwupd.h
+++ b/usr.sbin/pw/pwupd.h
@@ -76,29 +76,16 @@ struct userconf {
char *default_class; /* Default user class */
uid_t min_uid, max_uid; /* Allowed range of uids */
gid_t min_gid, max_gid; /* Allowed range of gids */
- int expire_days; /* Days to expiry */
- int password_days; /* Days to password expiry */
+ time_t expire_days; /* Days to expiry */
+ time_t password_days; /* Days to password expiry */
};
struct pwconf {
char rootdir[MAXPATHLEN];
char etcpath[MAXPATHLEN];
- char *newname;
- char *config;
- char *gecos;
int fd;
int rootfd;
- int which;
- bool quiet;
- bool force;
- bool all;
- bool dryrun;
- bool pretty;
- bool v7;
bool checkduplicate;
- bool deletehome;
- bool precrypted;
- struct userconf *userconf;
};
extern struct pwf PWF;
diff --git a/usr.sbin/pw/rm_r.c b/usr.sbin/pw/rm_r.c
index 65a63e6..172c7b0 100644
--- a/usr.sbin/pw/rm_r.c
+++ b/usr.sbin/pw/rm_r.c
@@ -29,15 +29,12 @@ static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/param.h>
-#include <unistd.h>
+
#include <dirent.h>
#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
#include "pwupd.h"
diff --git a/usr.sbin/pw/strtounum.c b/usr.sbin/pw/strtounum.c
new file mode 100644
index 0000000..be57276
--- /dev/null
+++ b/usr.sbin/pw/strtounum.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (C) 2015 Baptiste Daroussin <bapt@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
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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(S) 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 <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include "pw.h"
+
+uintmax_t
+strtounum(const char * __restrict np, uintmax_t minval, uintmax_t maxval,
+ const char ** __restrict errpp)
+{
+ char *endp;
+ uintmax_t ret;
+
+ if (minval > maxval) {
+ errno = EINVAL;
+ if (errpp != NULL)
+ *errpp = "invalid";
+ return (0);
+ }
+ errno = 0;
+ ret = strtoumax(np, &endp, 10);
+ if (endp == np || *endp != '\0') {
+ errno = EINVAL;
+ if (errpp != NULL)
+ *errpp = "invalid";
+ return (0);
+ }
+ if (ret < minval) {
+ errno = ERANGE;
+ if (errpp != NULL)
+ *errpp = "too small";
+ return (0);
+ }
+ if (errno == ERANGE || ret > maxval) {
+ errno = ERANGE;
+ if (errpp != NULL)
+ *errpp = "too large";
+ return (0);
+ }
+ return (ret);
+}
diff --git a/usr.sbin/pw/tests/Makefile b/usr.sbin/pw/tests/Makefile
index 193b8ab..a1605aa 100644
--- a/usr.sbin/pw/tests/Makefile
+++ b/usr.sbin/pw/tests/Makefile
@@ -1,13 +1,11 @@
# $FreeBSD$
-TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.sbin/useradd
-.PATH: ${TESTSRC}
-
TESTSDIR= ${TESTSBASE}/usr.sbin/pw
ATF_TESTS_SH= pw_etcdir \
pw_lock \
pw_config \
+ pw_groupadd \
pw_groupdel \
pw_groupmod \
pw_useradd \
@@ -23,12 +21,4 @@ FILES= group helper_functions.shin master.passwd pw.conf \
pw-modified.conf
FILESDIR= ${TESTSDIR}
-ATF_TESTS_SH+= pw_test
-# - user{add,del} does not exist on FreeBSD; use pw user{add,del} instead
-# - The command passes on FreeBSD
-ATF_TESTS_SH_SED_pw_test= -e 's/useradd /pw useradd /'
-ATF_TESTS_SH_SED_pw_test+= -e 's/userdel /pw userdel /'
-ATF_TESTS_SH_SED_pw_test+= -e '/atf_expect_fail "PR bin\/39546"/d'
-ATF_TESTS_SH_SRC_pw_test= t_useradd.sh
-
.include <bsd.test.mk>
diff --git a/usr.sbin/pw/tests/pw_groupadd.sh b/usr.sbin/pw/tests/pw_groupadd.sh
new file mode 100755
index 0000000..5fa7bef
--- /dev/null
+++ b/usr.sbin/pw/tests/pw_groupadd.sh
@@ -0,0 +1,26 @@
+# $FreeBSD$
+
+# Import helper functions
+. $(atf_get_srcdir)/helper_functions.shin
+
+atf_test_case group_add_gid_too_large
+group_add_gid_too_large_body() {
+ populate_etc_skel
+ atf_check -s exit:64 -e inline:"pw: Bad id '9999999999999': too large\n" \
+ ${PW} groupadd -n test1 -g 9999999999999
+}
+
+atf_test_case group_add_already_exists
+group_add_already_exists_body() {
+ populate_etc_skel
+
+ atf_check -s exit:0 ${PW} groupadd foo
+ atf_check -s exit:65 \
+ -e inline:"pw: group name \`foo' already exists\n" \
+ ${PW} groupadd foo
+}
+
+atf_init_test_cases() {
+ atf_add_test_case group_add_gid_too_large
+ atf_add_test_case group_add_already_exists
+}
diff --git a/usr.sbin/pw/tests/pw_groupdel.sh b/usr.sbin/pw/tests/pw_groupdel.sh
index 75b063a..88cc0e0 100755
--- a/usr.sbin/pw/tests/pw_groupdel.sh
+++ b/usr.sbin/pw/tests/pw_groupdel.sh
@@ -13,7 +13,7 @@ group_do_not_delete_wheel_if_group_unknown_head() {
group_do_not_delete_wheel_if_group_unknown_body() {
populate_etc_skel
atf_check -s exit:0 -o inline:"wheel:*:0:root\n" -x ${PW} groupshow wheel
- atf_check -e inline:"pw: -g expects a number\n" -s exit:64 -x \
+ atf_check -e inline:"pw: Bad id 'I_do_not_exist': invalid\n" -s exit:64 -x \
${PW} groupdel -g I_do_not_exist
atf_check -s exit:0 -o inline:"wheel:*:0:root\n" -x ${PW} groupshow wheel
}
diff --git a/usr.sbin/pw/tests/pw_useradd.sh b/usr.sbin/pw/tests/pw_useradd.sh
index 880dab5..2ac31c9 100755
--- a/usr.sbin/pw/tests/pw_useradd.sh
+++ b/usr.sbin/pw/tests/pw_useradd.sh
@@ -181,29 +181,29 @@ user_add_expiration_body() {
populate_etc_skel
atf_check -s exit:0 \
- ${PW} useradd foo -e 20-03-2043
- atf_check -o inline:"foo:*:1001:1001::0:2310422400:User &:/home/foo:/bin/sh\n" \
+ ${PW} useradd foo -e 20-03-2037
+ atf_check -o inline:"foo:*:1001:1001::0:2121120000:User &:/home/foo:/bin/sh\n" \
-s exit:0 grep "^foo" ${HOME}/master.passwd
atf_check -s exit:0 ${PW} userdel foo
atf_check -s exit:0 \
- ${PW} useradd foo -e 20-03-43
- atf_check -o inline:"foo:*:1001:1001::0:2310422400:User &:/home/foo:/bin/sh\n" \
+ ${PW} useradd foo -e 20-03-37
+ atf_check -o inline:"foo:*:1001:1001::0:2121120000:User &:/home/foo:/bin/sh\n" \
-s exit:0 grep "^foo" ${HOME}/master.passwd
atf_check -s exit:0 ${PW} userdel foo
atf_check -s exit:0 \
- ${PW} useradd foo -e 20-Mar-2043
- atf_check -o inline:"foo:*:1001:1001::0:2310422400:User &:/home/foo:/bin/sh\n" \
+ ${PW} useradd foo -e 20-Mar-2037
+ atf_check -o inline:"foo:*:1001:1001::0:2121120000:User &:/home/foo:/bin/sh\n" \
-s exit:0 grep "^foo" ${HOME}/master.passwd
atf_check -s exit:0 ${PW} userdel foo
atf_check -e inline:"pw: Invalid date\n" -s exit:1 \
- ${PW} useradd foo -e 20-Foo-2043
+ ${PW} useradd foo -e 20-Foo-2037
atf_check -e inline:"pw: Invalid date\n" -s exit:1 \
- ${PW} useradd foo -e 20-13-2043
- atf_check -s exit:0 ${PW} useradd foo -e "12:00 20-03-2043"
+ ${PW} useradd foo -e 20-13-2037
+ atf_check -s exit:0 ${PW} useradd foo -e "12:00 20-03-2037"
atf_check -s exit:0 ${PW} userdel foo
atf_check -e inline:"pw: Invalid date\n" -s exit:1 \
- ${PW} useradd foo -e "12 20-03-2043"
- atf_check -s exit:0 ${PW} useradd foo -e "20-03-2043 12:00"
+ ${PW} useradd foo -e "12 20-03-2037"
+ atf_check -s exit:0 ${PW} useradd foo -e "20-03-2037 12:00"
atf_check -s exit:0 ${PW} userdel foo
}
@@ -250,9 +250,9 @@ user_add_R_body() {
test -d ${HOME}/home/bar || atf_fail "Directory not created"
atf_check -s exit:0 ${RPW} userdel bar
test -d ${HOME}/home/bar || atf_fail "Directory removed"
-# atf_check -s exit:0 ${RPW} useradd bar
-# atf_check -s exit:0 ${RPW} userdel bar -r
-# test -d ${HOME}/home/bar && atf_fail "Directory not removed"
+ atf_check -s exit:0 ${RPW} useradd bar
+ atf_check -s exit:0 ${RPW} userdel bar -r
+ [ ! -d ${HOME}/home/bar ] || atf_fail "Directory not removed"
}
atf_test_case user_add_skel
@@ -289,6 +289,31 @@ user_add_uid0_body() {
-s exit:0 ${PW} usershow foo
}
+atf_test_case user_add_uid_too_large
+user_add_uid_too_large_body() {
+ populate_etc_skel
+ atf_check -s exit:64 -e inline:"pw: Bad id '9999999999999': too large\n" \
+ ${PW} useradd -n test1 -u 9999999999999
+}
+
+atf_test_case user_add_bad_shell
+user_add_bad_shell_body() {
+ populate_etc_skel
+
+ atf_check -s exit:0 ${PW} useradd foo -s sh
+ atf_check -s exit:78 -e ignore ${PW} useradd bar -s badshell
+}
+
+atf_test_case user_add_already_exists
+user_add_already_exists_body() {
+ populate_etc_skel
+
+ atf_check -s exit:0 ${PW} useradd foo
+ atf_check -s exit:65 \
+ -e inline:"pw: login name \`foo' already exists\n" \
+ ${PW} useradd foo
+}
+
atf_init_test_cases() {
atf_add_test_case user_add
atf_add_test_case user_add_noupdate
@@ -313,4 +338,7 @@ atf_init_test_cases() {
atf_add_test_case user_add_R
atf_add_test_case user_add_skel
atf_add_test_case user_add_uid0
+ atf_add_test_case user_add_uid_too_large
+ atf_add_test_case user_add_bad_shell
+ atf_add_test_case user_add_already_exists
}
diff --git a/usr.sbin/pw/tests/pw_userdel.sh b/usr.sbin/pw/tests/pw_userdel.sh
index 5ba87c2..f608029 100755
--- a/usr.sbin/pw/tests/pw_userdel.sh
+++ b/usr.sbin/pw/tests/pw_userdel.sh
@@ -27,7 +27,7 @@ user_do_not_try_to_delete_root_if_user_unknown_head() {
}
user_do_not_try_to_delete_root_if_user_unknown_body() {
populate_etc_skel
- atf_check -e inline:"pw: -u expects a number\n" -s exit:64 -x \
+ atf_check -e inline:"pw: Bad id 'plop': invalid\n" -s exit:64 -x \
${PW} userdel -u plop
}
@@ -50,8 +50,18 @@ delete_files_body() {
fi
}
+atf_test_case delete_numeric_name
+delete_numeric_name_body() {
+ populate_etc_skel
+
+ atf_check ${PW} useradd -n foo -u 4001
+ atf_check -e inline:"pw: no such user \`4001'\n" -s exit:67 \
+ ${PW} userdel -n 4001
+}
+
atf_init_test_cases() {
atf_add_test_case rmuser_seperate_group
atf_add_test_case user_do_not_try_to_delete_root_if_user_unknown
atf_add_test_case delete_files
+ atf_add_test_case delete_numeric_name
}
diff --git a/usr.sbin/pw/tests/pw_usermod.sh b/usr.sbin/pw/tests/pw_usermod.sh
index 006bb2c..236fd27 100755
--- a/usr.sbin/pw/tests/pw_usermod.sh
+++ b/usr.sbin/pw/tests/pw_usermod.sh
@@ -100,6 +100,36 @@ user_mod_name_noupdate_body() {
grep "^foo:.*" $HOME/master.passwd
}
+atf_test_case user_mod_rename_multigroups
+user_mod_rename_multigroups_body() {
+ populate_etc_skel
+
+ atf_check -s exit:0 ${PW} groupadd test1
+ atf_check -s exit:0 ${PW} groupadd test2
+ atf_check -s exit:0 ${PW} useradd foo -G test1,test2
+ atf_check -o match:"foo" -s exit:0 ${PW} groupshow test1
+ atf_check -o match:"foo" -s exit:0 ${PW} groupshow test2
+ atf_check -s exit:0 ${PW} usermod foo -l bar
+ atf_check -o match:"bar" -s exit:0 ${PW} groupshow test1
+ atf_check -o match:"bar" -s exit:0 ${PW} groupshow test2
+}
+
+atf_test_case user_mod_nogroups
+user_mod_nogroups_body() {
+ populate_etc_skel
+
+ atf_check -s exit:0 ${PW} groupadd test1
+ atf_check -s exit:0 ${PW} groupadd test2
+ atf_check -s exit:0 ${PW} groupadd test3
+ atf_check -s exit:0 ${PW} groupadd test4
+ atf_check -s exit:0 ${PW} useradd foo -G test1,test2
+ atf_check -o match:"foo" -s exit:0 ${PW} groupshow test1
+ atf_check -o match:"foo" -s exit:0 ${PW} groupshow test2
+ atf_check -s exit:0 ${PW} usermod foo -G test3,test4
+ atf_check -s exit:0 -o inline:"test3\ntest4\n" \
+ awk -F\: '$4 == "foo" { print $1 }' ${HOME}/group
+}
+
atf_test_case user_mod_rename
user_mod_rename_body() {
populate_etc_skel
@@ -134,7 +164,7 @@ user_mod_h_body() {
EOF
atf_check -s exit:0 -o match:"^foo:\*:.*" \
grep "^foo" ${HOME}/master.passwd
- atf_check -e inline:"pw: '-h' expects a file descriptor or '-'\n" \
+ atf_check -e inline:"pw: Bad file descriptor 'a': invalid\n" \
-s exit:64 ${PW} usermod foo -h a <<- EOF
$(echo a)
EOF
@@ -150,10 +180,29 @@ user_mod_H_body() {
EOF
atf_check -s exit:0 -o match:"^foo:a:.*" \
grep "^foo" ${HOME}/master.passwd
- atf_check -s exit:64 -e inline:"pw: '-H' expects a file descriptor\n" \
+ atf_check -s exit:64 -e inline:"pw: -H expects a file descriptor\n" \
${PW} usermod foo -H -
}
+atf_test_case user_mod_renamehome
+user_mod_renamehome_body() {
+ populate_root_etc_skel
+
+ mkdir -p ${HOME}/home
+ atf_check -s exit:0 ${RPW} useradd foo -m
+ test -d ${HOME}/home/foo || atf_fail "Directory not created"
+ atf_check -s exit:0 ${RPW} usermod foo -l bar -d /home/bar -m
+ test -d ${HOME}/home/bar || atf_fail "Directory not created"
+}
+
+atf_test_case user_mod_uid
+user_mod_uid_body() {
+ populate_etc_skel
+
+ atf_check -s exit:0 ${PW} useradd foo
+ atf_check -s exit:0 ${PW} usermod foo -u 5000
+}
+
atf_init_test_cases() {
atf_add_test_case user_mod
atf_add_test_case user_mod_noupdate
@@ -161,10 +210,13 @@ atf_init_test_cases() {
atf_add_test_case user_mod_comments_noupdate
atf_add_test_case user_mod_comments_invalid
atf_add_test_case user_mod_comments_invalid_noupdate
+ atf_add_test_case user_mod_nogroups
atf_add_test_case user_mod_rename
atf_add_test_case user_mod_name_noupdate
- atf_add_test_case user_mod_rename
atf_add_test_case user_mod_rename_too_long
+ atf_add_test_case user_mod_rename_multigroups
atf_add_test_case user_mod_h
atf_add_test_case user_mod_H
+ atf_add_test_case user_mod_renamehome
+ atf_add_test_case user_mod_uid
}
diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
index ff3e524..fa55e9d 100644
--- a/usr.sbin/syslogd/syslogd.c
+++ b/usr.sbin/syslogd/syslogd.c
@@ -349,6 +349,18 @@ static int waitdaemon(int, int, int);
static void timedout(int);
static void increase_rcvbuf(int);
+static void
+close_filed(struct filed *f)
+{
+
+ if (f == NULL || f->f_file == -1)
+ return;
+
+ (void)close(f->f_file);
+ f->f_file = -1;
+ f->f_type = F_UNUSED;
+}
+
int
main(int argc, char *argv[])
{
@@ -1024,7 +1036,8 @@ logmsg(int pri, const char *msg, const char *from, int flags)
(void)strlcpy(f->f_lasttime, timestamp,
sizeof(f->f_lasttime));
fprintlog(f, flags, msg);
- (void)close(f->f_file);
+ close(f->f_file);
+ f->f_file = -1;
}
(void)sigsetmask(omask);
return;
@@ -1313,8 +1326,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
*/
if (errno != ENOSPC) {
int e = errno;
- (void)close(f->f_file);
- f->f_type = F_UNUSED;
+ close_filed(f);
errno = e;
logerror(f->f_un.f_fname);
}
@@ -1338,7 +1350,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
}
if (writev(f->f_file, iov, IOV_SIZE) < 0) {
int e = errno;
- (void)close(f->f_file);
+ close_filed(f);
if (f->f_un.f_pipe.f_pid > 0)
deadq_enter(f->f_un.f_pipe.f_pid,
f->f_un.f_pipe.f_pname);
@@ -1446,7 +1458,7 @@ reapchild(int signo __unused)
for (f = Files; f; f = f->f_next)
if (f->f_type == F_PIPE &&
f->f_un.f_pipe.f_pid == pid) {
- (void)close(f->f_file);
+ close_filed(f);
f->f_un.f_pipe.f_pid = 0;
log_deadchild(pid, status,
f->f_un.f_pipe.f_pname);
@@ -1550,7 +1562,7 @@ die(int signo)
if (f->f_prevcount)
fprintlog(f, 0, (char *)NULL);
if (f->f_type == F_PIPE && f->f_un.f_pipe.f_pid > 0) {
- (void)close(f->f_file);
+ close_filed(f);
f->f_un.f_pipe.f_pid = 0;
}
}
@@ -1634,11 +1646,11 @@ init(int signo)
case F_FORW:
case F_CONSOLE:
case F_TTY:
- (void)close(f->f_file);
+ close_filed(f);
break;
case F_PIPE:
if (f->f_un.f_pipe.f_pid > 0) {
- (void)close(f->f_file);
+ close_filed(f);
deadq_enter(f->f_un.f_pipe.f_pid,
f->f_un.f_pipe.f_pname);
}
diff --git a/usr.sbin/yp_mkdb/yp_mkdb.c b/usr.sbin/yp_mkdb/yp_mkdb.c
index f1f629a..290e405 100644
--- a/usr.sbin/yp_mkdb/yp_mkdb.c
+++ b/usr.sbin/yp_mkdb/yp_mkdb.c
@@ -51,7 +51,6 @@ __FBSDID("$FreeBSD$");
#include "ypxfr_extern.h"
char *yp_dir = ""; /* No particular default needed. */
-int _rpcpmstart = 0;
int debug = 1;
static void
@@ -66,7 +65,6 @@ usage(void)
}
#define PERM_SECURE (S_IRUSR|S_IWUSR)
-
static DB *
open_db(char *path, int flags)
{
@@ -185,7 +183,6 @@ main(int argc, char *argv[])
* write to stdout; the db library doesn't let you
* write to a file stream like that.
*/
-
if (!strcmp(infile, "-")) {
ifp = stdin;
} else {
@@ -327,7 +324,6 @@ main(int argc, char *argv[])
(void)(dbp->close)(dbp);
doclear:
-
if (clear) {
char in = 0;
char *out = NULL;
diff --git a/usr.sbin/yppush/yppush_main.c b/usr.sbin/yppush/yppush_main.c
index 6c66515..5a712e5 100644
--- a/usr.sbin/yppush/yppush_main.c
+++ b/usr.sbin/yppush/yppush_main.c
@@ -58,15 +58,15 @@ int debug = 1;
int _rpcpmstart = 0;
char *yp_dir = _PATH_YP;
-char *yppush_mapname = NULL; /* Map to transfer. */
-char *yppush_domain = NULL; /* Domain in which map resides. */
-char *yppush_master = NULL; /* Master NIS server for said domain. */
-int skip_master = 0; /* Do not attempt to push map to master. */
-int verbose = 0; /* Toggle verbose mode. */
-unsigned long yppush_transid = 0;
-int yppush_timeout = 80; /* Default timeout. */
-int yppush_jobs = 1; /* Number of allowed concurrent jobs. */
-int yppush_running_jobs = 0; /* Number of currently running jobs. */
+static char *yppush_mapname = NULL; /* Map to transfer. */
+static char *yppush_domain = NULL; /* Domain in which map resides. */
+static char *yppush_master = NULL; /* Master NIS server for said domain. */
+static int skip_master = 0; /* Do not attempt to push map to master. */
+static int verbose = 0; /* Toggle verbose mode. */
+static unsigned long yppush_transid = 0;
+static int yppush_timeout = 80; /* Default timeout. */
+static int yppush_jobs = 1; /* Number of allowed concurrent jobs. */
+static int yppush_running_jobs = 0; /* Number of currently running jobs. */
/* Structure for holding information about a running job. */
struct jobs {
@@ -80,8 +80,7 @@ struct jobs {
struct jobs *next;
};
-struct jobs *yppush_joblist; /* Linked list of running jobs. */
-
+static struct jobs *yppush_joblist; /* Linked list of running jobs. */
static int yppush_svc_run(int);
/*
@@ -464,7 +463,8 @@ yppush_foreach(int status, char *key, int keylen, char *val, int vallen,
return (0);
}
-static void usage()
+static void
+usage()
{
fprintf (stderr, "%s\n%s\n",
"usage: yppush [-d domain] [-t timeout] [-j #parallel jobs] [-h host]",
diff --git a/usr.sbin/ypserv/yp_access.c b/usr.sbin/ypserv/yp_access.c
index c82f8c7..a4ba504 100644
--- a/usr.sbin/ypserv/yp_access.c
+++ b/usr.sbin/ypserv/yp_access.c
@@ -57,8 +57,8 @@ __FBSDID("$FreeBSD$");
extern int debug;
- /* NIS v1 */
-const char *yp_procs[] = {
+static const char *yp_procs[] = {
+ /* NIS v1 */
"ypoldproc_null",
"ypoldproc_domain",
"ypoldproc_domain_nonack",
@@ -71,7 +71,7 @@ const char *yp_procs[] = {
"badproc1", /* placeholder */
"badproc2", /* placeholder */
"badproc3", /* placeholder */
-
+
/* NIS v2 */
"ypproc_null",
"ypproc_domain",
@@ -93,7 +93,7 @@ struct securenet {
struct securenet *next;
};
-struct securenet *securenets;
+static struct securenet *securenets;
#define LINEBUFSZ 1024
diff --git a/usr.sbin/ypserv/yp_dblookup.c b/usr.sbin/ypserv/yp_dblookup.c
index 61944dc..6a3bf1c 100644
--- a/usr.sbin/ypserv/yp_dblookup.c
+++ b/usr.sbin/ypserv/yp_dblookup.c
@@ -405,7 +405,7 @@ yp_open_db(const char *domain, const char *map)
#ifdef DB_CACHE
again:
#endif
- dbp = dbopen(buf,O_RDONLY, PERM_SECURE, DB_HASH, NULL);
+ dbp = dbopen(buf, O_RDONLY, PERM_SECURE, DB_HASH, NULL);
if (dbp == NULL) {
switch (errno) {
diff --git a/usr.sbin/ypserv/yp_error.c b/usr.sbin/ypserv/yp_error.c
index 8d488f3..a5b1290 100644
--- a/usr.sbin/ypserv/yp_error.c
+++ b/usr.sbin/ypserv/yp_error.c
@@ -46,13 +46,13 @@ __FBSDID("$FreeBSD$");
#include "yp_extern.h"
int debug;
-extern int _rpcpmstart;
+extern int _rpcpmstart;
extern char *progname;
-
static void __verr(const char *fmt, va_list ap) __printflike(1, 0);
-static void __verr(const char *fmt, va_list ap)
+static void
+__verr(const char *fmt, va_list ap)
{
if (debug && !_rpcpmstart) {
fprintf(stderr,"%s: ",progname);
diff --git a/usr.sbin/ypserv/yp_main.c b/usr.sbin/ypserv/yp_main.c
index 958d3a6..8c538ca 100644
--- a/usr.sbin/ypserv/yp_main.c
+++ b/usr.sbin/ypserv/yp_main.c
@@ -72,13 +72,11 @@ __FBSDID("$FreeBSD$");
#define _RPCSVC_CLOSEDOWN 120
int _rpcpmstart; /* Started by a port monitor ? */
-static int _rpcfdtype;
- /* Whether Stream or Datagram ? */
+static int _rpcfdtype; /* Whether Stream or Datagram? */
static int _rpcaf;
static int _rpcfd;
- /* States a server can be in wrt request */
-
+/* States a server can be in wrt request */
#define _IDLE 0
#define _SERVED 1
#define _SERVING 2
OpenPOWER on IntegriCloud