diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 16f8d2f93352..e1c4d838e490 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 86c58088211e..3d1058b59894 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 @@ -574,6 +592,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW: or # 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__*" rc.conf(5) variables @@ -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 cf4dd5e0e550..823a98d4dd3e 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 6cc4be03fa30..37637c052b20 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 61d967a5b470..2d299d4b7312 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 f2c3178e31c6..42ae0168644a 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 dbb10c3fd598..0784eda4d775 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 ac43e790b7b3..f953d2407374 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 ccc247dec514..5f58eb8e0ca8 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 35bea8e58fa1..fbfcdfdab35f 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 2e3ffec52ba6..1d2a99237068 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 < test.pl <<-EOPERL sleep(2); EOPERL -$dtrace -c '/usr/bin/perl test.pl' -qs /dev/stdin < test.pl <<-EOPERL sleep(2); EOPERL -$dtrace -c '/usr/bin/perl test.pl' -qs /dev/stdin < test.pl <<-EOPERL sleep(2); EOPERL -$dtrace -c '/usr/bin/perl test.pl' -qs /dev/stdin < .\" Copyright (c) 2014 Nexenta Systems, Inc. All Rights Reserved. .\" Copyright (c) 2014, Xin LI -.\" 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 ae26d55ba8be..d408aed45199 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 18a54afdb937..41f7aa1533b8 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 a1a2996362fd..33fb007e6fff 100644 --- a/cddl/lib/libdtrace/ip.d +++ b/cddl/lib/libdtrace/ip.d @@ -25,6 +25,7 @@ * Copyright (c) 2013 Mark Johnston */ +#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 be342286f1b5..ae864ed363d2 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 68ac08b58cde..37842f7963a1 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 c2219f70a35d..1b13863df0e3 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 7dce19717642..03528a6423d3 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 d91d3c5318f0..104fd571e4c0 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 a6ff844901dc..37bc30ff3e06 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 4b826f175572..8398cd3ec6ad 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 21538eb0ef3c..eeba58c8752f 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 8c5e3abe5a07..551f6cf80031 100644 --- a/cddl/usr.sbin/dtrace/Makefile +++ b/cddl/usr.sbin/dtrace/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + .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 diff --git a/contrib/bsnmp/snmp_mibII/mibII_ip.c b/contrib/bsnmp/snmp_mibII/mibII_ip.c index 11efe8274dd8..1e33dc974903 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 000000000000..ddd811338d92 --- /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 000000000000..6b50fb3b19dd --- /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 +#include +#include +#include + +#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 000000000000..84f08e2393af --- /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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 FNAME +%type 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 000000000000..2bfa908d6edb --- /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 000000000000..45961e05cf61 --- /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 "!" +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 000000000000..ceecbd93920b --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 [options] archive file...\n\ + Manage archives.\n\n\ + Where 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 000000000000..a75b9a9eb856 --- /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 + +#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 000000000000..11be68bf401e --- /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 000000000000..daed864eee9e --- /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 000000000000..89ab4ab49cab --- /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 000000000000..08b3224db17e --- /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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 000000000000..f22542e67db2 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 000000000000..90be5da11937 --- /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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 000000000000..28ba3e0df01c --- /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 000000000000..1c2e485e44e1 --- /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 000000000000..5f5e6317b7b6 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 000000000000..b78d4652664e --- /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 000000000000..eae7262900a8 --- /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 000000000000..e4e565bdd5c5 --- /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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_LIBARCHIVE_AR +#include +#include +#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 6b65cdf55571..511104f2f954 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 b688917cc72b..ccb534f0e18c 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 7dd3909aa5b9..c185d1f6a45a 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 7c21c56e4c2a..26bc6b70080c 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 1879d76955cc..8afd6aa317f6 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 4779bbd1f765..2bf48c3cb8aa 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 5ed3a82727f3..91e750add240 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 fde339a638c7..c2003e78acb6 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 000000000000..20567c7bc0f1 --- /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 000000000000..dc0daae9e1e2 --- /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#)DRBD:;,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[=$V +M9]RY=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 0d94dcbe6a78..57b0931385fe 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 64adce45b37f..451a2a0c9daf 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 980250a91c3e..791be5ca3c9f 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 fd8ad1dd3348..25ced5735dc6 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 125d59e17aa9..fbe18db386af 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 73ed57536317..5087a93d18fc 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 d30826024355..f6c18de45d6b 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 0915b28e29ed..c7b84b9b449a 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 567436be9da6..93b200d475e9 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 7b1e38737c10..c23c8fd3e32e 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 1c863dfa7a33..d8ebdb1637e1 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 diff --git a/gnu/usr.bin/binutils/addr2line/Makefile b/gnu/usr.bin/binutils/addr2line/Makefile deleted file mode 100644 index 2380738fa638..000000000000 --- 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 diff --git a/gnu/usr.bin/binutils/addr2line/Makefile.depend b/gnu/usr.bin/binutils/addr2line/Makefile.depend deleted file mode 100644 index b58c9bda263a..000000000000 --- 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 - -.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 4f76544fa352..000000000000 --- 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 9a5a4f99aa50..000000000000 --- 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 - -.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 4ef2b8fdf65a..000000000000 --- 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 diff --git a/gnu/usr.bin/binutils/nm/Makefile.depend b/gnu/usr.bin/binutils/nm/Makefile.depend deleted file mode 100644 index b58c9bda263a..000000000000 --- 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 - -.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 e94e472f21aa..000000000000 --- 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 9a5a4f99aa50..000000000000 --- 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 - -.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 d90c3bcc9cc9..000000000000 --- 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 diff --git a/gnu/usr.bin/binutils/readelf/Makefile.depend b/gnu/usr.bin/binutils/readelf/Makefile.depend deleted file mode 100644 index b58c9bda263a..000000000000 --- 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 - -.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 e246d2ce2884..000000000000 --- 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 |\fB\-\-hex\-dump=\fR] - [\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 \fR" 4 -.IX Item "-x " -.PD 0 -.IP "\fB\-\-hex\-dump=\fR" 4 -.IX Item "--hex-dump=" -.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 c5c19c1908e9..000000000000 --- 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 diff --git a/gnu/usr.bin/binutils/size/Makefile.depend b/gnu/usr.bin/binutils/size/Makefile.depend deleted file mode 100644 index b58c9bda263a..000000000000 --- 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 - -.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 7064762186ff..000000000000 --- 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 a432d51ddf65..000000000000 --- 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 diff --git a/gnu/usr.bin/binutils/strings/Makefile.depend b/gnu/usr.bin/binutils/strings/Makefile.depend deleted file mode 100644 index b58c9bda263a..000000000000 --- 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 - -.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 075e3a5d8a58..000000000000 --- 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 d3cf8c454cdc..000000000000 --- 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 diff --git a/gnu/usr.bin/binutils/strip/Makefile.depend b/gnu/usr.bin/binutils/strip/Makefile.depend deleted file mode 100644 index b58c9bda263a..000000000000 --- 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 - -.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 3f0d7a3e3db8..000000000000 --- 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." 4 -.IX Item "1." -\&\f(CW\*(C`foo\*(C'\fR then... -.ie n .IP "1." 4 -.el .IP "1." 4 -.IX Item "1." -create a file containing the debugging info. -.ie n .IP "1." 4 -.el .IP "1." 4 -.IX Item "1." -stripped executable. -.ie n .IP "1." 4 -.el .IP "1." 4 -.IX Item "1." -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." 4 -.IX Item "1." -.PD 0 -.ie n .IP "1." 4 -.el .IP "1." 4 -.IX Item "1." -.ie n .IP "1." 4 -.el .IP "1." 4 -.IX Item "1." -.ie n .IP "1." 4 -.el .IP "1." 4 -.IX Item "1." -.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 65dc0871f3ee..41349cfa1b9b 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 b9daaf0f1287..000000000000 --- a/gnu/usr.bin/cc/c++filt/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# $FreeBSD$ - -MAN= -.include - -.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 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 0f7485ddb163..000000000000 --- 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 - -.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 80d6dd4a03ff..e57c5ff29e69 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 c6f2dfb3556a..1899b213e2f6 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 c6f2dfb3556a..1454f16699d2 100644 --- a/lib/libc/i386/sys/__vdso_gettc.c +++ b/lib/libc/i386/sys/__vdso_gettc.c @@ -31,24 +31,78 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #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 e01952bc4941..1a0cb0753aba 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 a305173b3ed8..b3527fa4de53 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 c5e8cafd5579..ca94852cba29 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 406c77c24752..e59ecf8b2a93 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 797618d4183a..43f6e839ff10 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 bdab0bc90fe6..23a95498f443 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 7528dbe1e670..a09db6f60956 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 7528dbe1e670..a09db6f60956 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 4b8794f317e7..458971f893c5 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 03a30f6307c8..03ebbe12fcaf 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 b1424ac552fc..a5ac92da578d 100644 --- a/libexec/ypxfr/ypxfrd_getmap.c +++ b/libexec/ypxfr/ypxfrd_getmap.c @@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$"); #include #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 f00a2686fc07..fbf35b59ecab 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 @@ The &man.alc.4; driver has been updated to support AR816x and AR817x ethernet controllers. - The &man.pfil.9; interface default hash + The &man.pf.4; packet filter default hash has been changed from Jenkins to Murmur3, providing a 3-percent performance increase in packets-per-second. @@ -1405,7 +1405,7 @@ &os;. - Network Procols + Network Protocols 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 9472ec59d89f..557e60260dbf 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 687d707195e6..5dea97470c11 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 04d3391c0b16..264532721531 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 -.Dl mdconfig -d -u md4 +Show detailed information on current memory disks: +.Bd -literal -offset indent +mdconfig -lv +.Ed .Pp -Create a 128MByte swap backed disk, initialize an +Resize the +.Dq Li md3 +memory disk to 2 gigabytes: +.Bd -literal -offset indent +mdconfig -rs 2g -u md3 +.Ed +.Pp +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 +Create a memory disk out of an ISO 9660 CD image file, +using the first available .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 -.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 895ef507db7e..bc030283e15f 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 c551c356e737..60e779d47c2d 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 prefix protocol_spec upper_spec %type ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD ALG_ENC_NOKEY +%type ALG_ENC_SALT %type ALG_AUTH ALG_AUTH_NOKEY %type ALG_COMP %type 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 b9c616066599..62fb2e1d2ba4 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 1b667190fe39..7f30859e3861 100644 --- a/sbin/setkey/token.l +++ b/sbin/setkey/token.l @@ -166,9 +166,9 @@ tcp { yylval.num = 0; return(PR_TCP); } des-deriv { yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC_DESDERIV); } des-32iv { yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC_DES32IV); } rijndael-cbc { yylval.num = SADB_X_EALG_RIJNDAELCBC; BEGIN INITIAL; return(ALG_ENC); } -aes-ctr { yylval.num = SADB_X_EALG_AESCTR; BEGIN INITIAL; return(ALG_ENC); } +aes-ctr { yylval.num = SADB_X_EALG_AESCTR; BEGIN INITIAL; return(ALG_ENC_SALT); } camellia-cbc { yylval.num = SADB_X_EALG_CAMELLIACBC; BEGIN INITIAL; return(ALG_ENC); } -aes-gcm-16 { yylval.num = SADB_X_EALG_AESGCM16; BEGIN INITIAL; return(ALG_ENC); } +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 f32112013610..d740778cf0c8 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 fc7370494c2c..5cb8c2308c63 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 fe1ea65b4e68..7ee9e859229b 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 000000000000..050e8c0eb63d --- /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 7684051213c5..05dd7bc09634 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 29aaa8ca6453..7ca2699a84a6 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 1045169b7a2d..687d44318f8b 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 90885e76a6af..b1ac39482ca1 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 6211c2e5095a..39f25d6dbe82 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 695fa23cd2f3..521a710a2861 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 5d317805fe04..f7edc33b1513 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 000000000000..2089dd98a932 --- /dev/null +++ b/share/man/man9/pmap_quick_enter_page.9 @@ -0,0 +1,103 @@ +.\" +.\" Copyright (c) 2015 Jason A. Harmening +.\" 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 cdf05921d269..51ab5d7ab747 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 b007609f3789..aac0ade02b8e 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 cdf8bab71d59..53628b33e295 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 6ba87cc3486e..7d776bce5637 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 3331f6f47966..ba8f48f8eabf 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 e91e6d546558..a2ca9e271f60 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 6a3de60af982..780d0e37959e 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 diff --git a/sys/amd64/cloudabi64/cloudabi64_sysvec.c b/sys/amd64/cloudabi64/cloudabi64_sysvec.c index 428d9f7602da..36edfc5acc68 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 016aa70e04b0..33d79b2cdfb6 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 156035e8918b..d76b48a8863f 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 954df3ec9c06..0657deee1283 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 110a351bac62..000000000000 --- 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 - -#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 13a97dea5186..b18648f072e7 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 a9421aa00e57..50172f253f54 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 dfd5bcb39ef0..daaa0ee906e5 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 bee9427a19d5..a0ca1b61dad1 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 644b5ff773a1..358a611bd4f7 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 73400c59fefa..d98d6390c144 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 8e28adc07944..2818babe5ed7 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 5702e7f0670e..08a297bbec7e 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 5dc2c0bea2ae..022a6c207f0f 100644 --- a/sys/arm64/arm64/gic_v3.c +++ b/sys/arm64/arm64/gic_v3.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #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 274a6aa2c230..fb4b8681483e 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 1621c0cfdffe..8bfce9b1ed13 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 f67211f2ec12..d63ee7aa5214 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 70c0f574450a..481ef8842e92 100644 --- a/sys/arm64/arm64/mem.c +++ b/sys/arm64/arm64/mem.c @@ -33,15 +33,84 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include + +#include +#include +#include +#include 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; - panic("memrw"); + 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; + } + } + + return (error); } diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index 7e4182052bd6..c2bccb84173e 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 @@ pmap_ts_referenced(vm_page_t m) * 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 a640077b75fb..72a9ab9e92b6 100644 --- a/sys/arm64/arm64/stack_machdep.c +++ b/sys/arm64/arm64/stack_machdep.c @@ -40,21 +40,49 @@ __FBSDID("$FreeBSD$"); #include #include +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 a987134bc3b3..fbffaed437a6 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 89c104f214a1..22d49b179d45 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 e6f6d39f02be..11ed239fa9dd 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 similarity index 53% rename from sys/amd64/include/xen/xenfunc.h rename to sys/arm64/arm64/uma_machdep.c index d8a6b5c5c99b..b17a2533875e 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 * 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 +__FBSDID("$FreeBSD$"); -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#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; +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; -extern pteinfo_t *pteinfo_list; -#ifdef XENDEBUG_LOW -#define __PRINTK(x) printk x -#else -#define __PRINTK(x) -#endif + *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); +} -char *xen_setbootenv(char *cmd_line); +void +uma_small_free(void *mem, vm_size_t size, u_int8_t flags) +{ + vm_page_t m; + vm_paddr_t pa; -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 - -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_ */ + 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 a98724202607..8278f87bacd8 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 bd6d980145ee..edcdeca1f742 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 c4ef49d180b3..e3b0c77245d9 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 4c9d7188e735..12ce4a1dcb86 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 15cdd80d4e26..ec351ad03b68 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 2bb86bd8472b..0829f6f52aa9 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 40524e4d145e..522ba005a0e4 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 ccb853c8f3ed..39adf4fb742b 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 8ad602994e48..3c14af8d101a 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 b48b4938801b..163814b94b9b 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 caafcc65ba90..e2338abe4c05 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 b4a6d51c4c4a..0bc66579cd0f 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 e65084803123..7ffeef40aced 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 ade605439ff6..bcbe0b86c627 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 a134f3d48eb8..7223492068b1 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 9333f3c3756d..319600fd5515 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 4601f29ed16c..a47275c9c89d 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 diff --git a/sys/boot/powerpc/ofw/Makefile b/sys/boot/powerpc/ofw/Makefile index 6a2fc700b1ca..ab5720fb1f40 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 diff --git a/sys/boot/powerpc/ps3/Makefile b/sys/boot/powerpc/ps3/Makefile index 861872f3852c..baf2507a6b51 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 diff --git a/sys/boot/sparc64/loader/Makefile b/sys/boot/sparc64/loader/Makefile index 5c9bfbb262ef..05d23ff19265 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 diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 3d562d02c8f2..1b6c14928732 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 2693419414ea..b1d9118c64b0 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 8ea52aa323df..5bb3121688a3 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; @@ -1166,6 +1161,26 @@ ctl_be_block_getattr_dev(struct ctl_be_block_lun *be_lun, const char *attrname) return (arg.value.off); } +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) { @@ -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 b07ea9355708..08ff88adefa9 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 8a00b5cae909..a038552e3c4b 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 ee2d019b528a..8d5d6bce81ba 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 490cddd510b7..662ee3d064a0 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 4da94445e3ca..a3a0bba9d26f 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 e3b6581c862d..7bf9de2a3659 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 #include @@ -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 94de1e85904c..627fdf9c30c3 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 83c28b89edc5..c02c1eccf3b7 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 643858317cd5..ea245cb0b8e8 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 0e131bf629e9..d55d553d9cd1 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 160c9b3c6976..4514b34d512a 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 8b72c19cdf6f..f16d66855ad4 100644 --- a/sys/compat/cloudabi/cloudabi_fd.c +++ b/sys/compat/cloudabi/cloudabi_fd.c @@ -27,13 +27,65 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include +#include +#include #include #include +#include #include +#include #include +#include +#include + +/* 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; - /* Not implemented. */ - return (ENOSYS); + /* 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); + } + + 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 b5085173811a..893825265eae 100644 --- a/sys/compat/cloudabi/cloudabi_file.c +++ b/sys/compat/cloudabi/cloudabi_file.c @@ -27,14 +27,23 @@ __FBSDID("$FreeBSD$"); #include +#include +#include #include #include #include #include +#include +#include #include +#include +#include #include #include +#include + +#include 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; - /* Not implemented. */ - return (ENOSYS); + error = copyin_path(uap->path, uap->pathlen, &path); + if (error != 0) + return (error); + + /* + * 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; - /* Not implemented. */ - return (ENOSYS); + 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); + + /* 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; - /* Not implemented. */ - return (ENOSYS); + /* 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); + } + + /* + * 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; - /* Not implemented. */ - return (ENOSYS); + /* 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; + } + + 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; - /* Not implemented. */ - return (ENOSYS); + error = copyin(uap->buf, &fs, sizeof(fs)); + if (error != 0) + return (error); + + /* + * 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; - /* Not implemented. */ - return (ENOSYS); + 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); + + /* 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; - /* Not implemented. */ - return (ENOSYS); + /* + * 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); + + 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 802509062e67..aec2f3318f34 100644 --- a/sys/compat/cloudabi/cloudabi_futex.c +++ b/sys/compat/cloudabi/cloudabi_futex.c @@ -35,13 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include - -#include -#include -#include -#include -#include -#include +#include #include #include @@ -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 1f4418f0b589..22f199df14f7 100644 --- a/sys/compat/cloudabi/cloudabi_proc.c +++ b/sys/compat/cloudabi/cloudabi_proc.c @@ -27,8 +27,11 @@ __FBSDID("$FreeBSD$"); #include +#include +#include #include #include +#include #include #include #include @@ -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 877571c144c0..1cfff92449a3 100644 --- a/sys/compat/cloudabi/cloudabi_sock.c +++ b/sys/compat/cloudabi/cloudabi_sock.c @@ -27,14 +27,62 @@ __FBSDID("$FreeBSD$"); #include +#include +#include +#include +#include +#include #include +#include #include #include #include #include +#include + +#include + #include #include +#include + +/* 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; - /* Not implemented. */ - return (ENOSYS); + 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; + + 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 5350d24c082c..10da229a2104 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 + #include +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 544886dc33b4..0a18838033d3 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 dd86bc982cc1..8c65fe3c7364 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 176519053e7b..40c017a41900 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 e44e6eaecb3f..5c0732b34636 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 1048e4e7d136..2ed5042b8107 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 @@ -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 311a14c20b1d..b3176aa3018e 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 21deffb24ee4..5fd6f7eb3dfb 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 fcb57533bdc8..b1ceadfde50e 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 1e5e37a2db76..489dc1e458dc 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 6b3749009bcf..a8bf72091393 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 99cef6dab2c2..fecb8b189675 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 92a422d4a1bf..6a8c9661a6a4 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 1dfcbec11ffe..4965940d222d 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_common.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_iofic.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_iofic_regs.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_nb_regs.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_pbs_regs.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_pcie.c rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_pcie.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_pcie_axi_reg.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_pcie_interrupts.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_pcie_regs.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_pcie_w_reg.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_plat_services.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_plat_types.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_reg_utils.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_types.h rename to 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 similarity index 100% rename from sys/arm/annapurna/alpine/hal/al_hal_unit_adapter_regs.h rename to 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 a7045c2d7e6b..f2e37058846f 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 151a3dcc59b9..adce208cb1d6 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 5bdd74f31ca5..6118b8292293 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 e9caa4325ebe..6972200d68f0 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 0594176a4522..3d5adec79eed 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 f7be6c089754..54c8815ce01f 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 19d6eb2cdb53..6e3f5fec65b6 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 459f98ccac5e..6b825c05e0d2 100644 --- a/sys/dev/ata/ata-lowlevel.c +++ b/sys/dev/ata/ata-lowlevel.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -44,6 +45,12 @@ __FBSDID("$FreeBSD$"); #include #include +#include +#include + +#include +#include + /* 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); - 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)))) { + 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--; + } + + /* 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]; + 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; } - } 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); - } + 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)); -#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); - 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)))) { + 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 - 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++]; - ATA_IDX_OUTW_STRM(ch, ATA_DATA, *(uint16_t *)&buf); - } - } else + 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 / - sizeof(int16_t)); - if (size & 1) { - buf[0] = (addr + (size & ~1))[0]; - ATA_IDX_OUTW_STRM(ch, ATA_DATA, *(uint16_t *)&buf); + 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; } - } 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); - } + /* 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); + } + + 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 3606e14c28c3..815c68b7a245 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 1c57dee88c45..5495141c60be 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 4aac93bb0f5b..f40f4fa77eac 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 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) 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 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) 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 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m) 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; + 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)); + /* 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<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 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) 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 @@ ath_calibrate(void *arg) 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 @@ ath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad) } #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 a672c71336f5..41267b31f885 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 40c0b9a5ac74..05d3cf5b12ed 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 fe99f106ac50..b8a77e89343a 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 711e69e87ba5..ff9a4db0eb7d 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 2779b7a59053..600d0a58d1da 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 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status, /* 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 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status, 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 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status, 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 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status, rs->rs_antenna |= 0x4; } - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); sc->sc_stats.ast_ant_rx[rs->rs_antenna]++; /* @@ -841,9 +833,9 @@ ath_rx_pkt(struct ath_softc *sc, struct ath_rx_status *rs, HAL_STATUS status, * 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 @@ ath_rx_proc(struct ath_softc *sc, int resched) 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 @@ ath_rx_proc(struct ath_softc *sc, int resched) 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 7aa818fe02aa..c3e8d3ab9492 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 eeb8d4b8400a..d8c6bac78e92 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 fd23db1977da..d4c9ccd20aad 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 c15b1583761a..bee632001480 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 @@ ath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, 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 7d149203d3ed..fdc2b4beb3c8 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 5c5e6cd3d287..2e71ff6374d4 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 f39ef44d4174..baad7fef550f 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 1057a83dcb9a..60d6bf569baf 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 cd0723a6a3d8..615e6dff6902 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 ad41bc675447..741f5f1d922b 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 @@ bwi_attach(struct bwi_softc *sc) 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 @@ bwi_init_statechg(struct bwi_softc *sc, int statechg) bwi_stop_locked(sc, 1); } -static int -bwi_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 bwi_softc *sc = ifp->if_softc; - struct ieee80211com *ic = ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0, 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; - } - - if (promisc >= 0) - bwi_mac_set_promisc(mac, promisc); - } - - 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); - } - 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; - } - return error; -#undef IS_RUNNING -} - static void -bwi_start(struct ifnet *ifp) +bwi_parent(struct ieee80211com *ic) { - struct bwi_softc *sc = ifp->if_softc; + struct bwi_softc *sc = ic->ic_softc; + int startall = 0; BWI_LOCK(sc); - bwi_start_locked(ifp); + if (ic->ic_nrunning > 0) { + 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 (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; + } + + if (promisc >= 0) + bwi_mac_set_promisc(mac, promisc); + } + 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 int +bwi_transmit(struct ieee80211com *ic, struct mbuf *m) +{ + struct bwi_softc *sc = ic->ic_softc; + int error; + + BWI_LOCK(sc); + 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; - } - } - 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) - ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + 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; + } + if (bwi_encap(sc, idx, m, ni) != 0) { + /* 'm' is freed in bwi_encap() if we reach here */ + if (ni != NULL) { + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); + ieee80211_free_node(ni); + } 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 d5f09da6eb2f..07c20fef2b0c 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 39bd06fadae4..15f6f27a0a5a 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; - } - } 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); -} - static void -bwn_start(struct ifnet *ifp) +bwn_parent(struct ieee80211com *ic) { - struct bwn_softc *sc = ifp->if_softc; + struct bwn_softc *sc = ic->ic_softc; + int startall = 0; BWN_LOCK(sc); - bwn_start_locked(ifp); + if (ic->ic_nrunning > 0) { + if ((sc->sc_flags & BWN_FLAG_RUNNING) == 0) { + bwn_init(sc); + startall = 1; + } else + 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 int +bwn_transmit(struct ieee80211com *ic, struct mbuf *m) +{ + struct bwn_softc *sc = ic->ic_softc; + int error; + + BWN_LOCK(sc); + 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 @@ bwn_pio_rxeof(struct bwn_pio_rxqueue *prq) } } - 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 f6647b0f4f5f..b8295ece9b1c 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 f3e59640fb84..274cc5b4ca3e 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 5fb31a32ba87..980a91fc759c 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 bdd746fcb44f..985306c3c6e8 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 @@ do_close_con_rpl(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); @@ -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 e11bb2583373..933a83c2aaa7 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 @@ do_pass_establish(struct sge_qset *qs, struct rsp_desc *r, struct mbuf *m) 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 similarity index 77% rename from sys/dev/cxgbe/firmware/t4fw-1.14.2.0.bin.uu rename to sys/dev/cxgbe/firmware/t4fw-1.14.4.0.bin.uu index c868045fb05d..e3f3f779d8af 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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 @@ -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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 @@ -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,1921 +7307,1922 @@ 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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 +0CALkpAf/5sIH/+bAB//mwQf/6kYH/+pFB//gqAf/6qsH/+boB//m5wf/5uUH/+CwB//qqggAwgA +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 +AAAAACADDmAMwAAGIAasPCADDmQIwAAMIAasPCADDmggwAAQIAarxCADDmwGwAA4IAatoCADDnAI +wAA8IAasPCADDnQCwABAIAatoCADDngIwABEIAasPCADDnwIgABIIAaszCADDoAYgABcIAaszCAD +DoQYgABsIAaszCADDogYgAB8IAaszCADDowYgACMIAaszCADDpAYgADcIAaszCADDpQYgADoIAas +zCADDpgYgAD0IAaszCADDpwYgAEAIAaszCADDqAIgAE8IAaszGh3X2JjbTg0MzRfY2hlY2tyYW06 +IFN0YXJ0CgAAAAAAUEhZIHByb2Nlc3NvciBub3QgcnVubmluZywgc3RpbGwgaW4gcmVzZXQgZm9y +IDVtcywgcG9ydF9iaXRfbWFwPSV1IAoAAAAAAAAAAAAAAABQSFkgRlcgaGFzIGJhZCBDUkMsIG9r +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 @@ -9231,23 +9232,31 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAACCAAABIAAAAAAAAACCAAABAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAGgIAAAAAAAAAAAAAAAACAAAAAAAAAAAACgAAAAAAAAAAAAAIAAwAAAAABYAgAAAAAAwAA -AAAAAAAAAAAAAwAAAAAAAAAAAAAAAgAAAAAAAAAAACAAAAAAAAAAAAAAAAEAA4AAAAAAAAAAAAAA -AgAAAAAAAAAAACADgAAAAAAAAAAAABACgACAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA -AAAAAoAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAoAAAAAAAAAAAAEAAwAAAAAAAAAAAAACgwAAAAAA -AAAAABACgAAAAAAAAAAAADAAAwAAAAAAAAgAADAAAwAAAAAAAAAAADAFgwAAAAAAAAgAADAFgwAA -AAAAAAAAADAEgwAAAAAAAAgAADAEgwAAAAAAAAAAADADAwAAAAAAAAgAADADAwAAAAAAAAAAADgD -AwAAAAAAAAAAADgFgwAAAAAAAAAAADgEgwAAAAAAAAAAADgAAwAAAAAAAAAAADQGggAAAAAAAAAA -ADwDggAAAAAAAAAAADwAAwAAAAAAAAgAADwAAwAAAAAAAAAAADwEgwAAAAAAAAAAADwFAwAAAAAA -AAAAAD0EAwAAAAAAAAAAADwDgwAAAAAAAAAAACwAAgAAAAAAAAAAACwFggAAAAAAAAAAACwFAgAA -AAAAAAAAABAGgAAAAAAAAAAAABAGgsAAAAAAAAAAABAGgoAAAAAAAAAAAAAOggAAAAAAAAAAABAH -goAAAAAgAAAAAAAHggAAAAAgAAAAABAHAoAAAAAAAAAAABAHAoAAAAAAAAAAABAHAoAAAAAAAAAA -AAAHAgAAAAAgAAAAABAXgwAAAAAAAAgAABAXgwAAAAAAAAgAABAAAAAAAAAAAAAAABAGA4AAAAAA -AAAAAAAOAwAAAAAAAAAAABAGA0AAAAAAAAAAABAGAwAAAAAAAAAAABAGAAAAAAAAAAAAAAAGA4AA -AAAAAAAAAAAGAwAAAAAAAAAAAAAOAgAAAAAAAAAAAAAOAgAAAAAAAAAAABAGAgAAAAAAAAAAABAG -AgAAAAAAAAAAABAGAoAAAAAAAAAAABAGAoAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAgAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAQAwAAAAAAAAgAAAAAAAAAAAAAAAAAAP////////// +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,36 +9293,36 @@ AAIAAAAAAAAAABAAAAAAAAAAAAAAAACAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////wAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAACACSAAAAAAAAAANmACAAQAAAAAAIAJIAAAAAAAAAA3IBJQRAAAAA -AAAAAAAAAAAAAAADlgAgAEAAAAAACAAAAAIAiAOHAABWACAAQAAAAAAAAAAAAAAAAAAAA5YAIABA -AAAAAAAAAAAAAAAAAAADlgAgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAAAAAAAAAAA5YA -IABAAAAAAAgAAAACAIgDhQAAlgEgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAAAAAAAAAA -A5YAIABAAAAAAAgAAAACAIgDhQAAlgEgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAAAAAA -AAAAA5YAIABAAAAAAAgAAAACAIgDhQAAlgEgAEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAAAAAA -AAAAAAIAA5YAJgRAAAAAAAhHIAEEAAACsgAC0gUgJEAAAAAAAAAAAAAAAAAAAAOWACAAQAAAAAAA -RyABBgyhgrBAAZIEICRAAAAAAABHIAEEDKBCs4ACEgUgJEAAAAAACAAAAAIAiAOFAACWASAAQAAA -AAAIAAAAAgCIA4UAAJYBIABAAAAAAAgAAAACAIgDhQAAlgEgAEAAAAAAAAAAAAAAAAAAAAOWACAA -QAAAAAANxRK6ArCA0xRUi+JKRiRAAAAAAAXFEroCt4DTFFSLYkmmJEAAAAAABcUSogawgNMUVIvi -SkYkQAAAAAANxRKiBreA0xRUi2JJpiRAAAAAAAXFEqIGsIDTFFSL4kpGJEAAAAAADcUSoga3gNMU -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 @@ -9330,29 +9339,29 @@ 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,63 +9374,63 @@ 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 @@ -9437,50 +9446,50 @@ 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 +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 -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= ==== diff --git a/sys/dev/cxgbe/firmware/t4fw_interface.h b/sys/dev/cxgbe/firmware/t4fw_interface.h index bd436681641c..2ee58bab22f5 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 similarity index 58% rename from sys/dev/cxgbe/firmware/t5fw-1.14.2.0.bin.uu rename to sys/dev/cxgbe/firmware/t5fw-1.14.4.0.bin.uu index ed9375b3f97e..dc35d5aa8ae7 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 @@ 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 @@ -713,18 +713,18 @@ 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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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 @@ -816,60 +816,60 @@ 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 @@ -877,24 +877,24 @@ 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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 @@ 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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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 @@ -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 @@ Do4ULjQ+Do4ULjQ9Do4ULjQ8/lIOIAAQUDD6NCUgABBgMCw0Ivw0JiAAEFgwKzQjKzQn/jQzIAAQ SDApNCQOjhQuNDIOjhQuNDEOjhQuNDDwDRcAkAJI8AAJiixyESpSEgyNFC00Og2NFCw0Oy00OQ2N FC00OIumnF8rNDcLixQrNDYLixQrNDULixQrNDSKpyo0QwqKFCo0QgqKFCo0QQqKFCo0QCkgBwkJ QQyZEaiZL5Y5KyAWJgr/drEK+iAHIDAQYDBYPlXJU4hYyI+PWcDgnluY8IlYn5GeWC5WCRykoY0g -L3IULnIRKHITmBD2Ug4gBRBQMPYWASAwEFgwWZK+KfqZ+VQFIAAQEDDRDwCNN/wyBiIAAFCw+1wA -D/8QcDBZkdL9rAANRAA2oCoKBfykjhAwEFgwWZKwwdbaIPtcAAIAAGDwWD3owCDRD9ogWD6A+KNd +L3IULnIRKHITmBD2Ug4gBRBQMPYWASAwEFgwWZLCKfqZ+VQFIAAQEDDRDwCNN/wyBiIAAFCw+1wA +D/8QcDBZkdb9rAANRAA2oCoKBfykjhAwEFgwWZK0wdbaIPtcAAIAAGDwWD3owCDRD9ogWD6A+KNd HbcANqBgABSLFPosAAABEGAw+7wYIAUQaDBYPrWMWGXP0Y8vGKR9+FYLIEACaXD99gAgcAJwsJ5Y n1n9Jg8gABAQMNEPiDcpiRT1PAAApgA2YIOJ8/y/YEACIPDz++RgABBYMPP/f2COEGgwwLCbq/P8 RGIAABpwAAAAAPP8c2//EEAw/LoMADcANOAKSxT+vAgiAABA8P5ONgIAAEsw0w9t6QUGCIYASWeJ Fao4+04MAIACSnBt6QUICIYASWmLFQr+DK67K7xAm9Bj++ePFS/8QJ/QY/vdixT6LAAAARBgMPu8 EiAAEGgwWD6BY/8sAAAAAPP/XGAAEBgwbBAEKiAE+6cHYBgQQDBrpAZ4oRvAINEP+iwAAgAAWPD8 TAACAABpcFj//MAg0Q8A+iwAAgAAWPD8TAACAABpcFv+l8Ag0Q8AbBAIBQZH9NUaAAUQUDD8pDIQ -MBBYMFmSUvciECICLxmgFaODJVKLKlIVKKECZIRnWDFkHKN1LVIWG6N9LMJuK7KF/dwBLAAgUzD9 +MBBYMFmSVvciECICLxmgFaODJVKLKlIVKKECZIRnWDFkHKN1LVIWG6N9LMJuK7KF/dwBLAAgUzD9 VhYtkAQ7IPkgByoAIGbwKLAH+gr7KAIBTDD+mREIAEBSMP0gDCgJAEowKLQH+SAHL5gQYDD9tAwg /BBQMPy0BSgAQFIw8rYKIAAQUDD6tggoIAFMMPq2CSgJAEowKLQH9bwAA/EANuCKt/yiCCfABDkg +6EVL8AQcDD5ogsgQAJqsP+pFC4AQHNw/hYFKgAgdvD7vEAmAePmUKb//6UUKgAgYbD/AgAKAebW 0Mk1+cwAABMANSBtSQUAA4YASWEq0gAGqgj/AgAGAftekJrQ08CJUA8CAA8CAPqjQx2ABDpg+zEI LAkAYTCcMStVCCqic/qZDABgAiDw+WgUAJACYXD5DUUMAbQSICpwcLaqAKEEAIgaCNgCLFYTLFYS -mF4rMDH5PDgqwAFcMPtUUCQBO4bg2pBZkQYco9YtQAD+QAEgMBBYMP9QUCIAADKw9hYAIAUQUDBZ -ke8tMQgco87+UQggBRBQMP9SDCAwEFgwWZHpiCL6IAcikQC2IBiimgoKQQypEfyimRgAIEZwK5I6 +mF4rMDH5PDgqwAFcMPtUUCQBO4bg2pBZkQoco9YtQAD+QAEgMBBYMP9QUCIAADKw9hYAIAUQUDBZ +kfMtMQgco87+UQggBRBQMP9SDCAwEFgwWZHtiCL6IAcikQC2IBiimgoKQQypEfyimRgAIEZwK5I6 mhQMrAr8wpckAS3G4CuSOfyzAQ4BKGbQJiISLiIJGaLX/SIKJggBMDAmFgYJZgomYoD+3QwAYAJZ sP8CAAoBC19QKyAWKQr/ebES+iAHIAAQYDBYPYH4ooAS4AA2oC0hBx6iiA0NSgzdEfqiiBwJAHdw nTCLIP0SBiBAEGAw/DYDIAUQSDD6NgIvgAQ+4Pminx4JAE/wnzEfotIuIhL9nzgOSgFwMPrdEQ9g @@ -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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 @@ -2018,21 +2018,21 @@ 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 @@ -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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 @@ -2125,23 +2125,23 @@ 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 @@ -2150,29 +2150,29 @@ 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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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 @@ -2311,30 +2311,30 @@ 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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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 @@ -2411,35 +2411,35 @@ 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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 @@ 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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 @@ O3ZnNihABYNDJ0EDCDMMA3MK/ncRAZ4CGPAHMy3zwwwAYAJ6cAP/KK8i0Q8AKjADDaoR+iIMAZoA AAAAsap7oRwJ6jAN6jCsmQ2dDGrR7G0ICA3qMA2dDGrR4GP/8BT7hQIPR/v/EQAeEEAwCP8CL0bB HvuBLkbCGvuA+/uAEDIQaDD+CgEgABBgMPxGwyAAEHgwW64K9qBGYgAAErAa+3cb+3f8CgAgMhBo MP4KASADEEAw+EbDIAAQeDBbrgD2oC1iAAASsClCwikVAPYgC2IAAFCwKhEAmjDRD9Kg0Q/ApPz7 -aBAUEFgwWQfFY//cwKT8+2UQFBBYMFkHwWP/zAAAbBAG+vthFAAQYDD4+2AQABAoMPRcAADAEFgw +aBAUEFgwWQfJY//cwKT8+2UQFBBYMFkHxWP/zAAAbBAG+vthFAAQYDD4+2AQABAoMPRcAADAEFgw +VwACgBAXPD7iTkADgBk8AqZAv77WBwAQFZw/cQ5AA4AQnAORAImICHz+0sQEBA4MPtmEQAHEEAw CGYCJjbBJzbCG/tH/AoAIDIQaDD6+0QQARBwMPU2wyAAEHgwW63Q96BRYgAAErAqCgT8+z4QFBBY -MFkHnGYgdiY2wSc2whv7OPwKACAyEGgw+vs0EAEQcDD1NsMgABB4MFutwfegXGIAABKwwKH8+zQQ -FBBYMFkHjdEPAPv7KxAAEGAw/QoyIAEQcDD6+yYQAxBAMPg2wyAAEHgwW62y96AWYgAAErDApPz7 -IRAUEFgwWQd+Zy+I0Q8pMsIpFQBj/3oAABv7ICoRAAuqAQpKAgoKTyo2whv7FPwKACAyEGgw+vsQ -EAEQcDD+NsMgABB4MFutnfegEWIAABKwwKH8+xIQFBBYMFkHadEPAGwQBAIqAlgCe2agjyogIRz7 -DPsKASAYEGgwWNusZqB7KiAhHPsI/QqAIAEQWDBY26dmoGcqICEc+wT7CgEgPxBoMFjbomagUyog -IRz7AP0K/yABEFgwWNudZqA/KiAhHPr8Hfr8/vr7EAEQWDBYaudmoCgqICEc+vj7CgEgBhBoMFjb -kmagFCogIRz69PsKASAAEGgwWNuN0qDRD9Kg0Q9sEAYjIR3Apfz67hAYEFgw/SAiIgAAcPBZBzn6 +MFkHoGYgdiY2wSc2whv7OPwKACAyEGgw+vs0EAEQcDD1NsMgABB4MFutwfegXGIAABKwwKH8+zQQ +FBBYMFkHkdEPAPv7KxAAEGAw/QoyIAEQcDD6+yYQAxBAMPg2wyAAEHgwW62y96AWYgAAErDApPz7 +IRAUEFgwWQeCZy+I0Q8pMsIpFQBj/3oAABv7ICoRAAuqAQpKAgoKTyo2whv7FPwKACAyEGgw+vsQ +EAEQcDD+NsMgABB4MFutnfegEWIAABKwwKH8+xIQFBBYMFkHbdEPAGwQBAIqAlgCe2agjyogIRz7 +DPsKASAYEGgwWNuwZqB7KiAhHPsI/QqAIAEQWDBY26tmoGcqICEc+wT7CgEgPxBoMFjbpmagUyog +IRz7AP0K/yABEFgwWNuhZqA/KiAhHPr8Hfr8/vr7EAEQWDBYaudmoCgqICEc+vj7CgEgBhBoMFjb +lmagFCogIRz69PsKASAAEGgwWNuR0qDRD9Kg0Q9sEAYjIR3Apfz67hAYEFgw/SAiIgAAcPBZBz36 +tsUABBgMPj62hAAECgw9FwAAMAQWDD5XAAKAEBc8PuJOQAOAGTwCpkC/vrSHABAVnD9xDkADgBC cA5EAiYgIfP6xRAQEDgw+2YRAAcQQDAIZgImNsEnNsIb+sH8CgAgMhBoMPr6vhABEHAw9TbDIAAQ -eDBbrUr3oFFiAAASsCoKBPz6uBAUEFgwWQcWZiB2JjbBJzbCG/qy/AoAIDIQaDD6+q4QARBwMPU2 -wyAAEHgwW60796BcYgAAErDAofz6rhAUEFgwWQcH0Q8A+/qlEAAQYDD9CjIgARBwMPr6oBADEEAw -+DbDIAAQeDBbrSz3oBZiAAASsMCk/PqbEBQQWDBZBvhnL4jRDykywikVAGP/egAAG/qaKhEAC6oB +eDBbrUr3oFFiAAASsCoKBPz6uBAUEFgwWQcaZiB2JjbBJzbCG/qy/AoAIDIQaDD6+q4QARBwMPU2 +wyAAEHgwW60796BcYgAAErDAofz6rhAUEFgwWQcL0Q8A+/qlEAAQYDD9CjIgARBwMPr6oBADEEAw ++DbDIAAQeDBbrSz3oBZiAAASsMCk/PqbEBQQWDBZBvxnL4jRDykywikVAGP/egAAG/qaKhEAC6oB CkoCCgpPKjbCG/qO/AoAIDIQaDD6+ooQARBwMP42wyAAEHgwW60X96ARYgAAErDAofz6jBAUEFgw -WQbj0Q8AbBAEGfp7IgoA9vrnIKcQODDzChQiAAAqcG06DyRRcAZEAfdBCnAEAilwsSLHK9EPZiC8 +WQbn0Q8AbBAEGfp7IgoA9vrnIKcQODDzChQiAAAqcG06DyRRcAZEAfdBCnAEAilwsSLHK9EPZiC8 9fqGEBMQUDD4CgEgABBYMP8rJG//EDgwJlKEACEEALwaACEEAI0aB90DDWYBDGYCJlaEYAAfAAAu UsACpAwAQQQAvxoAQQQAgxoHMwMD7gEP7gIuVsAG6jAkkjErkjELRAoGRAoG6jAGRgxqYQ5tCAgM 6jAMTAxqwQJj//BvKxwuUoQAIQQAjRoH3wMP7gEO3QL9VoQgABAQMNEPACNSwAKpDACRBACCGgck -AwQzAQMiAvJWwCAAEBAw0Q8A0Q8AAGwQBvMWAiIAAHDw/PpUEAQQUDD9ICIgFBBYMFkGnhj6PhT6 +AwQzAQMiAvJWwCAAEBAw0Q8A0Q8AAGwQBvMWAiIAAHDw/PpUEAQQUDD9ICIgFBBYMFkGohj6PhT6 OPf6TxAAEDAw+BYAIaACQjD4FgEgABAoMPAADmAAEBgwsWb/AgAIAFuFoCwgIfvMEQAeEGgwDcwC LEbBJ0bCGvoq+/oqEAAQYDD9CjIgARBwMPNGwyAAEHgwW6y0ZqCWGvoiG/oi/AoAIDIQaDD+CgEg AxBAMPhGwyAAEHgwW6yrZqCCJULCBQVPflcsCuowGfoSKZIxqpkI6jAImAz/AgAB/7+mIG0IDQrq MAqaDP8CAAH/tyagY//rjBIqICH9CoAggBBYMPz6HhIFAGbw+woeIgAAcPBYagHAINEP3lD9ICIg -BBBQMPz6FxAUEFgwWQZgxyvRD8Ck/BIBIBQQWDBZBltj/4LApPwSACAUEFgwWQZXY/9yAABsEAQq +BBBQMPz6FxAUEFgwWQZkxyvRD8Ck/BIBIBQQWDBZBl9j/4LApPwSACAUEFgwWQZbY/9yAABsEAQq ICEd+gr7CgcgABAoMP5cAAgDARgw+N45ACAQYDBYaej2oFViAAAisBz6AvoKAiIAEEgw+joBAgAA cXD6ICEuBQBScP0qACAHEFgwWGnd9qAnYgAAIrD6ICEhABBoMPMMQAEAEFgw+woHJAUAZvD8ChAi AABxcFhp0tJA0Q8AAABsEAT8CiggJhBYMPg8HWAlEFAw/wIABgBI1ND/AgAGAFFc0HwxUMYq0Q8A @@ -3108,131 +3108,131 @@ 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 @@ -3247,32 +3247,32 @@ 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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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 @@ -3373,22 +3373,22 @@ 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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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 @@ -3456,38 +3456,38 @@ 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 @@ -3502,21 +3502,21 @@ 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 @@ -3540,113 +3540,113 @@ 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 @@ -3658,73 +3658,73 @@ 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 @@ -3732,28 +3732,28 @@ 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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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 @@ -3845,51 +3845,51 @@ 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 @@ -3899,59 +3899,59 @@ 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 @@ -3960,25 +3960,25 @@ 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 @@ -3988,39 +3988,39 @@ D90CDt0CnRQM6jD8FgUgABBYMPsWByBAAkhwBgOIAMmKBAOIAImKAgOIAEmKAAOIAAmK2xD8CgQg AhBoMFt0ZdEPAABsEAQTyXYlMoooUhQogQIqCob2MoQgIAIg8PSBVmDAAjlwKSIFKDJ1qYgJiBEI ZggpYAUPAgB6kQUq+oYqZAUqUhRbdBckQnAjMoSqRAlEEaQzhDcfyJ6ETv82DiABEHAwLjYT/jYS IAAQaDAtNhQtNhGMKPzsUQIAAFqw/DRuIgAAUTBbGcYcydAuYRn9YRgv/xBQMJo/iSX5Ng0gMBBY -MPY2CyAAEEAw+DU1IAUQUDBY1OL2CgAiAABYsPpNAiFQEGAwWMvhKkKI0w/TD/SmEnACEGAwKzBv +MPY2CyAAEEAw+DU1IAUQUDBY1Ob2CgAiAABYsPpNAiFQEGAwWMvlKkKI0w/TD/SmEnACEGAwKzBv 0w8PAgAMuwIrNG/zpg1wBBBwMC0wbw7dAi00b/KmE3AIEEAwLzBvDwIADwIACP8CLzRv/AoDLPgB VDD1pg1wARBYMCkwbwuZAik0b/kyAC4AB+8QLjBvwfAP7gIuNG8sTQEtwZItNTQswZMsNhYrQosr NhgqQowqNhcpRoYocDgoNHAiUheWOPY2CSACAhCw8lYXIgAAEPDRDwDAINEPbBAGKCAhFMhL+4gR AAcQSDAJiAIoRsHA4S5GwvvISRAyEGgw+shGEAAQYDD8RsMgABB4MFt60vagRGIAABKw+8hAEAAQ YDD9CjIgARBwMPrIOxADEEgw+UbDIAAQeDBbesj2oCxiAAASsCpCwioVAGYgCSsRAAsrQJsw0Q/R -D8Ck/MgwEBQQWDBY1I5nL+Nj/+rApPzILRAUEFgwWNSJY//NAABsEAYkICHzyCIQABAoMA8CAPtE +D8Ck/MgwEBQQWDBY1JJnL+Nj/+rApPzILRAUEFgwWNSNY//NAABsEAYkICHzyCIQABAoMA8CAPtE EQAHEEAwCEQCJDbBJTbCG8ge/FwAADIQaDD6yBoQARBwMPU2wyAAEHgwW3qn96BUYgAAErDApPzI -FRAUEFgwWNRzZiB6JDbBJTbCG8gP/AoAIDIQaDD6yAsQARBwMPU2wyAAEHgwW3qY96BhYgAAErDA -ofzICxAUEFgwWNRk0Q8AAAAAAPvIARAAEGAw/QoyIAEQcDD6x/wQAxBAMPg2wyAAEHgwW3qI96AW -YgAAErDApPzH9xAUEFgwWNRUZy+E0Q8pMsIpFQBj/3YAAAAqGQArKgALqgIqNsIbx+v8CgAgMhBo -MPrH6BABEHAw/jbDIAAQeDBbenT3oBFiAAASsMCh/MfpEBQQWDBY1EDRDwAAbBAGjjP+5RNv6hBg -MPpcAAIAAFjwWNJUwCDRD/zJHBAFEFAw/TICIAAQWDBY1DOIMIYyGckX9DIDIABZKhB2mwrz/8hv +FRAUEFgwWNR3ZiB6JDbBJTbCG8gP/AoAIDIQaDD6yAsQARBwMPU2wyAAEHgwW3qY96BhYgAAErDA +ofzICxAUEFgwWNRo0Q8AAAAAAPvIARAAEGAw/QoyIAEQcDD6x/wQAxBAMPg2wyAAEHgwW3qI96AW +YgAAErDApPzH9xAUEFgwWNRYZy+E0Q8pMsIpFQBj/3YAAAAqGQArKgALqgIqNsIbx+v8CgAgMhBo +MPrH6BABEHAw/jbDIAAQeDBbenT3oBFiAAASsMCh/MfpEBQQWDBY1ETRDwAAbBAGjjP+5RNv6hBg +MPpcAAIAAFjwWNJYwCDRD/zJHBAFEFAw/TICIAAQWDBY1DeIMIYyGckX9DIDIABZKhB2mwrz/8hv 6hBgMAAAAP8CAAIAiIUgiycAQAT6IHcgDRBgMAwMG/uyDiABEEgw/8cNcgAAOrAtIA0PAgBl38MA QQQAnBr8FgAgbQA1oAtPC/zJARgJAFMw+CR3IgAAaTD//QUgAgJxsP716CAEEFAw/vXpIAAQWDBY -1BEbyPcLSworsn/Is9ogC7AAZHBv3UD+bAAABRBQMPzI8RAAEFgwWNQH8/8oYAAQYDAAAADz/x1g -ABBgMN1A+goFIgAAMzD8yOgQABBYMFjT/Sogd8e/C2sDC6oBCgpH+iR3L8YANeBlr77ApfzI4BAA -EFgwWNPziicqrBBbeaRj/6YAACsgd2S/icCl/MjZEAAQWDBY0+sbx938yNYSAABQsFjQSmP/awBb -eWRlruzAovzI0RAAEFgwWNPiY/7JAGwQBoQnFcjNKSB39EIOIAAQGDAAMAT5ChsAABAwMPRNBSAF +1BUbyPcLSworsn/Is9ogC7AAZHBv3UD+bAAABRBQMPzI8RAAEFgwWNQL8/8oYAAQYDAAAADz/x1g +ABBgMN1A+goFIgAAMzD8yOgQABBYMFjUASogd8e/C2sDC6oBCgpH+iR3L8YANeBlr77ApfzI4BAA +EFgwWNP3iicqrBBbeaRj/6YAACsgd2S/icCl/MjZEAAQWDBY0+8bx938yNYSAABQsFjQTmP/awBb +eWRlruzAovzI0RAAEFgwWNPmY/7JAGwQBoQnFcjNKSB39EIOIAAQGDAAMAT5ChsAABAwMPRNBSAF EDgwf6dyK0HoDwIAsLsLC0/7ReggZAC24PkWAiKIADzgLCAN+iAMIHQAtyD5FgIrgAQ6oBjIuvqK FAjgAVQwCJgKKIJ/+hYAKeAEPmApFgELgAAKCUH4kV9iAABasGiTWihSf9ogC4AAKkHo0w8PAgD5 EgIgfAA2oPVcBCAQAjGw9EwIIAICGPDwMAQB/gI58PkKGw9uALXgYABzG8hYiiArsn+ZEguqDPiq EQABEFgw8/9/agkAWrB8pxmNJ43e+RICLAAgN3D93QYgARBgMCzVaGP/ohnIkogRqYgogn/HnPoS ACoAQE7wC4AAY/9wACogd/AxBAABEFgw8LsaD/8QYDAMuwMLqgEqJHdj/2gbx4b8yH8SAABQsFjP -88Ag0Q8AAABsEARj//wAAGwQBMCi/Mh8EAAQWDBY04nAplt50sAg0Q8AAABsEASJJ4meKZ0GKJI9 +98Ag0Q8AAABsEARj//wAAGwQBMCi/Mh8EAAQWDBY043Aplt50sAg0Q8AAABsEASJJ4meKZ0GKJI9 ZIAEwCDRDwAVyHLAsSuWPSpSIvbHYxAAEBgw9woAL+QANqAkUtwoYnssUtOLIKg4CYgR/LsMBAAg -QTAqQh1bduXIqClAb8mRsZoqRG8rUiKxM3szzWP/qgAAAPoKAiAAEFgw/MhdEgAAaPBY02cnRHAr +QTAqQh1bduXIqClAb8mRsZoqRG8rUiKxM3szzWP/qgAAAPoKAiAAEFgw/MhdEgAAaPBY02snRHAr QF/8QC0iAABRMFg53ilAb2P/wgAAbBAEiSeJnimdBiiSPWiBBcAg0Q8AABTITcAwI5Y9KkIiFsc9 9/r/L+gANqAlQtwoYnssQtOLIKg4CYgR/LsMBAAgRXAqUh1bdsHJrylQb7CZCQlH+VRvIBUAtmAn -VHArUF/8UC0iAABRcFg5wSpCIrEzejO2Y/+XbBAEwKT8yDUQABBYMFjTPxrG2SigwXuHQx7G7cCw +VHArUF/8UC0iAABRcFg5wSpCIrEzejO2Y/+XbBAEwKT8yDUQABBYMFjTQxrG2SigwXuHQx7G7cCw /PrnIeAQaDD+4oQgFBBIMG2aDy+hcAz/Af3xCXAEAlKwsbsr+vsAsAT+CBkAAhBQMPgIQAABEFgw -CLo5WI/TwCDRDwAAAGwQBMCk/MgdEAAQWDBY0ybAINEPbBAEHsa+HcgZLuKEH8gZ/dJ/LjgBcDAP -7gou4n//CmQsAAtrkIIngi4iLQb/JXQgABAQMNEPAMCh/MgOEAAQWDBY0xTApVt5XYIngi7yLQYg +CLo5WI/TwCDRDwAAAGwQBMCk/MgdEAAQWDBY0yrAINEPbBAEHsa+HcgZLuKEH8gZ/dJ/LjgBcDAP +7gou4n//CmQsAAtrkIIngi4iLQb/JXQgABAQMNEPAMCh/MgOEAAQWDBY0xjApVt5XYIngi7yLQYg ZBB4MP8ldCAAEBAw0Q8AbBAEGsgF+qJ/IgAAWLD8PAAAARBoMFt2VdKg0Q8AAABsEAQax/0qon/b IFt2dNKg0Q8AAGwQBBTH+MAx9EJ/IAAQEDAoQQMkQQIIRAwEMjjRDwAAbBAIlBGSEPvH8BIAAHjw /lwAAgAAabAsGkAsthArshFksiAXxpL3twEAARAoMPcWAyIBC0LQwJD6CgAgABBgMPAAlGAAEBgw @@ -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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 @@ -4076,49 +4076,49 @@ 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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 @@ wXsQ/gJgcPoWaCCIAlhw+xZfIKgCUnD6FmAgCgJjMCwWZfvBshB0AjOw9hZaIGACO7D3FlkgUAJD sPgWWCB6Anuw/xZbIKgCQHD4FmEgcAJ6cP8WZCCAAjpwJxZi+xZeILgCMHD2FmMgiAJzsP4WXCDI AnJwLhZm9rywIGACYvD8FmchoAJa8CsWV/AADmA/EDgwjjjz7AADpwA3oC0wBYQ3w4b0Qg4mAiS/ UP8CAAYCIMdQK0B++7z/ID4QYDD6Cv4o4AFcMPtEfiGQCFJwLTAFfNkH/wIABgM+v1AsEmctIAcu -ME4vME/4MFAgBBBQMPgWACAyEFgwWMxrHMBRKDAMJTIWKzEZFMF6+cBMEBoQUDAqNFQqEmgpknck +ME4vME/4MFAgBBBQMPgWACAyEFgwWMxvHMBRKDAMJTIWKzEZFMF6+cBMEBoQUDAqNFQqEmgpknck Qon7Fl0lkAQ9YPAKFwgAIEow+YgRBAAgLTD4HH8kACBBMPiMQSAQEEgw0w9tmgIACIorQSnTD/8C -AAYBOGbQjTAuMAX8ElcgBRBQMP8wVCAyEFgwWMxNGsA0+TIAIOEQWDArFNj6FjIgCBBQMPvALxmA +AAYBOGbQjTAuMAX8ElcgBRBQMP8wVCAyEFgwWMxRGsA0+TIAIOEQWDArFNj6FjIgCBBQMPvALxmA BD5g+xYwKAkAVnApFjEsMAcqQSn7wCocIAFgMADMEQyqAguqAioWNAjqMCkWOSgWNR/BTf8WOCBA EHAwLhVvLTBULRTxLDAFLBTyKzAw+xTzIAEQeDAvFPD6MhYg/gJIcPoWPSDCAkpwjpSMkouRjZMq HQGIlZilnaOboZyinqQsHQEuHQGJkJmgKh0BiDAoFkYtMFQoHQEt5B0uHQErMAUrxCD5MDAgABBo -MC3kHi+EHPmkISBoAljw+hJYIAgQYDBYwxkqEln8CgggeAJY8FjDFitccvoSWiAGEGAwWMMSKhJb -/AoDIJwCWPBYww8qElz8CggguAJY8FjDCyQRoigRoyoSXSgVkSgyDPqMQAwJAVQw+hUUCAUBJDD0 +MC3kHi+EHPmkISBoAljw+hJYIAgQYDBYwx0qEln8CgggeAJY8FjDGitccvoSWiAGEGAwWMMWKhJb +/AoDIJwCWPBYwxMqElz8CggguAJY8FjDDyQRoigRoyoSXSgVkSgyDPqMQAwJAVQw+hUUCAUBJDD0 30AECQAusPr/EQQAASww+5kRBZAEPWD4OFQECQBNcPgdASQJAEVw9YQkLbAEP2D5MGgtwAQ7IP4w aSQOASAw+UQRDAkAazD6bUAOCQAn8P5kQAgDAUww/nVACdAEPmD+VREF8AQ5IPVEAg4JAE/w/l5A DgkAJ/D/CjAuCQB7sP/uAg4LAVQw/t0RD5AEP+D+hCUuCgFQMPsyDC+gBDug/+4CDgcBVDD+zAIO BQFQMPpKQA/QBD/g/+4RDAkAf3D7FVAIEAFcMPuZEQWgBD1g/cwCChIBXDD+qgILkAQ+4PyqAgQJ AF1w+QoIJAkATXD6hCckCQBNcCWEJikyBySZFCqcIPuSCSQwADUgZLQoKxx/+7xBIAgQYDBbcukV wMooMhYlUon5iBECAABQ8PhVCACHEFgwW/v5ijcqrBBbcWKEOctGJRZphUv9QgAiAABhsP4yACAF -EFAw/0AFIDIQWDBYy6b7CociAABRMFv7cvRcAA/UALVghDklEmmJO2RAU/wKACAzALZglDtgAD4A +EFAw/0AFIDIQWDBYy6r7CociAABRMFv7cvRcAA/UALVghDklEmmJO2RAU/wKACAzALZglDtgAD4A AAAAAAD6LAAABRBYMPwKACACEGgwWxQNZauZwrUrJAUbwKdj+4kAAACNm8jb/dILIgAAS3DTD2Xf 8pSbmUz8NgkgABAgMI1ac9kKhDmNOJ1aYAAgAADJ0I7Yc+EM/ewAAAkAN6CO6HPp8sjXJDIJLjII LtYI/TAFIAAQcDD9NDAgABB4MP82CCKYADUgxIIoNAUqElaKp4quKaBwK6BxCJkRC5kCsZkppHEJ -iRQppHBj+6YAAAAsEl4tIAcuME4vME/4MFAgBBBQMPgWACAyEFgwWMtm+RJoLgAQWDD7FlQgABBQ +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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 @@ -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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 @@ -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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 @@ -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 @@ EIoniq76iAsAIAJI8PRvgmHwAkIwbWkFAAiIAAmKY/9xAAAHCEWobA3MESzM+P8CAAv/hGbQA4gL aQUACIgACYpj/xUHCEWobA3MESzM+P8CAAv/V2bQiicqog76iAsAIAJI8PRu8mHwAkIwbWkFAAiI AAmKY/7hAAAAbBAKG7Lx8iAiIAAQMDAmNB8mNB4mNB0mNBwmNBsmNBomNBkmNBgmNBcmNBYmNBUm NBQmNBMmNBImNBEmNBDyCwcCAABQcABKY/ALBwAoAkhwAElhiDD6FgQgIAJQ8PkWCSAuAKYwBVoC -+zwAAAAQYDBYvR/AINEPABSynAIoCQyIEahE9E0fIAYQYDD0TFogLhBAMPg0DyIAAFkwWLX9jDQA ++zwAAAAQYDBYvSPAINEPABSynAIoCQyIEahE9E0fIAYQYDD0TFogLhBAMPg0DyIAAFkwWLYBjDQA RASNNQxOFP42BCBQEDgw9zQQIgAAWTD9zBgAMAJQ8Pw2BSjoAWQw9jQXKAkAFnD5NBYgBhBgMFi1 -7h60RBqyjBu0QYk2AEQEjDcJTRSdNic0GPyZGA+AEEAw+TYHLugBTDD4NB8uCQAX8P80HiAoAkBw +8h60RBqyjBu0QYk2AEQEjDcJTRSdNic0GPyZGA+AEEAw+TYHLugBTDD4NB8uCQAX8P80HiAoAkBw loCWgZaCloOWEJYR9hYCJ9AQeDCfE/sVAyAfEEgwKRUF+hUCIAoQYDAsFQH+FQogARBoMP0UISD/ EGAwLBUELBUO+xUNIgAAUHD2ChYAQAJI8ABJZ/QIFgBgAnjwAE9lY/7uAGwQBIgw/wIAAABULhCJ MWeQnhSz0CpCjCuhAmSxZVtd1B2zL4zescz81g4gAKwCoBiynCiCaSRCif2yhRgAIFIwCYgRqETw DQcAQAJJMABJYQBJYQBJYQBJYQBJYQBJYS8gDC4gDS0hBywgBysgFikgfPoiCiAEEEAwKEQEL0QM LkQNLUUHLEQHKURV+0QWID8QWDD7RAUg9AA2oCmiCMmfbQgJ+ZIIIgAAUnDJkmP/78HG+lwAAgAA -WPBYvK/AINEPlKj7RDAgABAwMJZJ9kYIICACWPD1CxYAaAJRMPKaHgAwAkjw8wkWAHgCQTDyWB4A +WPBYvLPAINEPlKj7RDAgABAwMJZJ9kYIICACWPD1CxYAaAJRMPKaHgAwAkjw8wkWAHgCQTDyWB4A QAJ48PEPFgC4AnEwAA6KjTv9RhkgYAJg8PAMFgDQAlkw8AugAJwCUTD5IgAgAxBgMPlGFiAaAljw -WLV8KkxR/AoDIJACWLBYtXgYs4GOQCshKSoiEykgUIxHKURM+kYSL8AQeDD7RSIgQAJrMPjuAQwA +WLWAKkxR/AoDIJACWLBYtXwYs4GOQCshKSoiEykgUIxHKURM+kYSL8AQeDD7RSIgQAJrMPjuAQwA QH9w/jYKIIACa3CdyZ3IJsUU8/85YAAQYDAAAAAAAADz/ytgDBBgMJQqY/8yAAAAbBAMFLNqG7O3 iTD3stAQKxBQMPwyASAcEGgw+5sBAA4ALnBmwX78s7AQnAAqcIgyL8LpBIQBCUQR/SIAJAAgI/D+ -Qh4gQAJY8Pk8KCBwAnjw/Ew4IIACUTD4TFQmAI93UMHG+lwAAgAAWPBYvF7AINEPAAAAAAAA/sLT -IOoAJnCLMgS7Af3CFioABPLQrt17084kwukJuBH4RAgAJAJQ8PtMbCAGEGAwWLU3KEw49QgWADAC +Qh4gQAJY8Pk8KCBwAnjw/Ew4IIACUTD4TFQmAI93UMHG+lwAAgAAWPBYvGLAINEPAAAAAAAA/sLT +IOoAJnCLMgS7Af3CFioABPLQrt17084kwukJuBH4RAgAJAJQ8PtMbCAGEGAwWLU7KEw49QgWADAC ePDynx4AgAJxMPMOFgBAAmjw8l0eAKgCYTDwDBYAUAJY8PALoADIAlEw8QoWAHACSPAACYrz/3Zg ABBgMGS/bIkxizIuwtP/AgAB/7EGUPTC6SoAQCbw+bkRCgAI8tAvwhau//8CAAv/ot/QiCqpRP8C AAf/nKYQK0AF/wIABgIC1tAsIAT/AgAOAStrEIZKyGjaYFhOoYZoZW/1+kwAAAAQWDBYSKnaQFhI @@ -4403,29 +4403,29 @@ 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 @@ -4433,47 +4433,47 @@ IgAAYPBbaA7SoNEPAAAAbBAEjjLAi/mxtBoAD8OQCekKiZAKkAD6LAACAABbsP1cAAAYAmDwW0Lv wCDRD/osAAIAAFjw/EwAAgAAaXBYQAzSoNEP+iwAAgAAWPD8TAACAABpcFg9t9Kg0Q/6LAACAABY 8PxMAAIAAGlwWAHd0qDRD/osAAIAAFjw/EwAAgAAaXBYBFHSoNEP+iwAAgAAW7D9XAAAABBgMFtC 0sAg0Q8AAABsEC4XsJWGLS5yhAlmEabmjGeMzo8uK8AwLcAx+f8RC4AEPuD9uwICACB7sPoiByAC -AlrwK8QxC4sU+8QwICACUrBbYdCDKcszFbF7hDv9MgAgBRBQMP4iACAyEFgw/zAFIgAAYXBYvBT7 +AlrwK8QxC4sU+8QwICACUrBbYdCDKcszFbF7hDv9MgAgBRBQMP4iACAyEFgw/zAFIgAAYXBYvBj7 CooiAABQ8Fvr4PNMAA/UALUggynAQPsiCyAVADTgZbPXkytgAAYAAACTu5s8lCkpIAwqIhYbr+sY sNb4FlAgGhBgMCwkVCVyhCuydwAIjfmqEQIAAEBw+loICAAgXnD6Fk8pkAQ+YPkhGSQAIE1w+RZO -IBAQSDBtmgIACIoer9otUSnAcfMsTiYBJHdQHLFRLSIA/iAFIAUQUDD/IFQgMhBYMFi76h6v0f0i +IBAQSDBtmgIACIoer9otUSnAcfMsTiYBJHdQHLFRLSIA/iAFIAUQUDD/IFQgMhBYMFi77h6v0f0i ACDhEHgwLxQY/hYCIAgQYDD+r8wdgAQ/YP4WACwJAGdwnREoIAcuUSn/r8cYIAFAMACIEQjuAg/u Ap4UC+owmxWdGfqw6xBAEEgwKRUPmhgoIFQoFDEvIAUvFDIuIDAnFDAuFDMtIhb9Fg0gQAJocIvV itSJ04jS/9IBIIACcHCf4ZjimeOa5JvljdCd4IsgKxYWKiBUKhRdKSAFKRRgKCAwJxRc9BReIGgC -WLD4FGEg0AJQcFiyvyoccPwKCCB4AliwWLK7KxJPKhx6+7xyIAYQYDBYsrcqHH37PAAAAxBgMFiy -tCUKCPssXCD+AlBw+qwFIAgQYDBYsq4qEUMqFTEqEk4KTUD6XkAKCwFUMPpoQAgHAVQw/ZkRCeAE +WLD4FGEg0AJQcFiywyoccPwKCCB4AliwWLK/KxJPKhx6+7xyIAYQYDBYsrsqHH37PAAAAxBgMFiy +uCUKCPssXCD+AlBw+qwFIAgQYDBYsrIqEUMqFTEqEk4KTUD6XkAKCwFUMPpoQAgHAVQw/ZkRCeAE OiD5iAIICgFUMPm7EQmgBD5g+xFCKAkAXnD6HBQP8AQ7oPysAgwJAHdw/AxADgUBWDD5zBEPsAQ7 oP4iDCwJAHMwCo9A/P8RCgkBUDD7qhEOkwFwMPr/AgwJAHMw/BRkLgkAT/D+IGgqDQFYMPkgaSoO AVww+qoRC5AEPuALqgL5a0AOAwFwMPl8QA/QBDug/swRC/AEPuD8uwIKCQBysPlZQAoJAFqw+gow KAkAVnAKmQIpFGX4IgwuCQBH8AgOUPgcUAgSAUAw+swRCZAEOiD77hEMCQBDMP/dAgwJAHMw/RRn LAkAKzAsFGaOJyvpFPSxWWBAAlOwi+lksU/7HAAACBBgMFtikBuwwSoiEywgBSQlGfuqAQA5ECgw +iYTIBQEKzALrAEsJhMpElAoHH8ojBHwCRcAFRBIMG2aAgAIih6wZv4WJCCiAliw/SIAIAMQYDD6 -HH8j/xB4MPQUoyALEHAw9xSoLYAEP2D/FVAsCQB3cP0WJSBUAlKwWLJG+hx/IgAAWPD6rC4gAxBg -MFiyQSQUwSQUwiQUw/wKECADEFgw+xTAIP4CUHD6rEUgqAJZsFiyOPtsQCD+AlBw+qxVIAgQYDBY -sjP7bDgg/gJQcPqsXSAIEGAwWLIu+h0BIMgCWbD6rAQgCBBgMFiyKicViCQU5CQU9PosAAALEGAw +HH8j/xB4MPQUoyALEHAw9xSoLYAEP2D/FVAsCQB3cP0WJSBUAlKwWLJK+hx/IgAAWPD6rC4gAxBg +MFiyRSQUwSQUwiQUw/wKECADEFgw+xTAIP4CUHD6rEUgqAJZsFiyPPtsQCD+AlBw+qxVIAgQYDBY +sjf7bDgg/gJQcPqsXSAIEGAwWLIy+h0BIMgCWbD6rAQgCBBgMFiyLicViCQU5CQU9PosAAALEGAw /x0BIAIQaDD09BQg/xBwMP4VhiAgEEAw+BTEIP4CWHD4FMUgIgJa8FhBISUkBdEPibvTDw8CAGSc JW0ICvmSCyIAAFpwZJwXY//uAAD6LAACAABYcPwKCCACEGgwW1peY/6kAABsEDYTsD+LLS0yf/yv MRABECgw+iAFK5AEPuD+sGQaACBfcPuyByAAECAw9zr/IXYCUrD+rgoAEhBAMPuyDioABMKQjuAK -4ADaIFtbp8Ag0Q8AABywV40g/iE2IAUQUDD/ITcgMhBYMFi67YYuIzJ/CWYRpjP2PE4gCgJQcPwK -AyIAAFmwWLHqGK+3G7BK/AoDIBUQSDDwCBcAMAJAcG2aAgAIipsWiiD8FCsgCxBYMPUUMCuABDqg -9xUUKgkAWrAqFgcpMAT6HDEkAN0GYCs8UVix19tg/AoDIGoCUHBYsdQlFEgkFEkkFEokFEskFE77 +4ADaIFtbp8Ag0Q8AABywV40g/iE2IAUQUDD/ITcgMhBYMFi68YYuIzJ/CWYRpjP2PE4gCgJQcPwK +AyIAAFmwWLHuGK+3G7BK/AoDIBUQSDDwCBcAMAJAcG2aAgAIipsWiiD8FCsgCxBYMPUUMCuABDqg +9xUUKgkAWrAqFgcpMAT6HDEkAN0GYCs8UVix29tg/AoDIGoCUHBYsdglFEgkFEkkFEokFEskFE77 HBgiAABQsP0KAiAJEGAw/BRNIAsQYDBYQM/aIFtbdsAg0Q/aIFtbdMAg0Q+KJyqsEFtgcoguGa+P IzJ/8AkXCZAEOiD4HH8iACBE8PiMQSAVEEgwbZoCAAiKG7Ab+xYwIAMQYDD9Ig4gogIw8PocfyAL -EHAw9RTYILQCUrD3FWgtgAQ/YPQU0ywJAHdw/RYxIgAAWbBYsar7PE4g/gJQcPqsXiADEGAwWLGl -JBTxJBTyJBTz+2wAABIQYDD8FPAg/gJQcPwKAyDsAlKwWLGc2jD+IgAgCxBgMP4VfCACEGgw/iE3 +EHAw9RTYILQCUrD3FWgtgAQ/YPQU0ywJAHdw/RYxIgAAWbBYsa77PE4g/gJQcPqsXiADEGAwWLGp +JBTxJBTyJBTz+2wAABIQYDD8FPAg/gJQcPwKAyDsAlKwWLGg2jD+IgAgCxBgMP4VfCACEGgw/iE3 IP4CWHD+FX0gggJa8FhAmcAg0Q+JLgmZEanZiZeJniiQO7GIKJQ7L7Bfsf//tF8iAABQsFv+V8Ag 0Q8AAIknKpkUyKCEmSjCRPosAAAAEGgw/EAHIgAAWTALgADAINEPLx0B+q/hENACW/CUsJSxlLKU s5S0lLWUtpS3KhZaiSD4wkQgAhBwMP1MAAIAAGOw9fR8KYAEPmD09HsoCQB2cPkWWyIAAFCwC4AA -wCDRDys8SFixarUbLbAB/rAAIGoCYHAuxAAtxAErsAIrxAJj/joAAGwQCi0hKSsgFiYgBxyvc/Ui +wCDRDys8SFixbrUbLbAB/rAAIGoCYHAuxAAtxAErsAIrxAJj/joAAGwQCi0hKSsgFiYgBxyvc/Ui CCIAAHFwKiB8iScnUgcKrwn5kg4g/xBAMPkWBi/ABD/g93IOLAAgezD8wn8mIAEwMPwWCCAuBELw LRYHAM6OW2X+jBj9EgcinQA2oBiuQAxkEQ8CAPquQRQAIEEwK0I6CmoK+qKXJgEIQuApQjkbrg/6 kwEOAQFWUPALBwIAAEjwAElhAElhAElhAElhAElhAElhKCEHGa40+AhKAEgQeDD8C0YJwAQ6IPmI AghIAWQw+DYAKYAEPmD5rnoaCQBO8PoiAC4HAWAw/zYDL1AEO6D/riQQBhBgMP82AiuABDqg/d8U CgkAYrD6NgErQAQ7YP2vhR9ABD/g+CB8LgkAe7D+uwIAABB4MP81CiA0EHAwLjUL/aoCCQAEOiD6 -NgYoCQBaMPo8ICgJAEow+DYEIOQCWLBYsRD6PCYg2AIwsPwKBiIAAFmwWLELHK2qH69v/zQtIIkQ +NgYoCQBaMPo8ICgJAEow+DYEIOQCWLBYsRT6PCYg2AIwsPwKBiIAAFmwWLEPHK2qH69v/zQtIIkQ cDD+NCwgEBBoMP00LiACEEAw+DQ4ILACWXD4NDkgBxBIMPw0NyABEFAw+jQzIAYQYDD5NDUgAxBQ -MPo0MSAAEEgw+TQ0IAAQUDD6NDAggBBIMPk0NiB0AlDwWLDxBmsC/AoFIIQCUPD8NEEgCxBoMP00 -QCAGEGAwWLDqKjxJ/AoDIJACWLBYsOb6PEwgBhAoMPwKCCCAAliwWLDhjBYrwCAtwCH+wCIrgAQ+ +MPo0MSAAEEgw+TQ0IAAQUDD6NDAggBBIMPk0NiB0AlDwWLD1BmsC/AoFIIQCUPD8NEEgCxBoMP00 +QCAGEGAwWLDuKjxJ/AoDIJACWLBYsOr6PEwgBhAoMPwKCCCAAliwWLDljBYrwCAtwCH+wCIrgAQ+ 4A27Av3AIyuABD7gDrsCCLsRDbsCsbsrxCMLixQrxCILixQrxCELixQrxCCKcIlxKqw4+nYAIAIC SnCZcYgnwJD/+sAgQAJCMPVGOS4AQH4w+YUEIIACe/CfgJ+BKyAWLgr/frFf+iB8IDQQYDBbZUXA INEPAIwiZMBSjiD4ryQQCRB4MJ8S+O4RAAEQeDD4FgAuCQB7sJ4Rjif9+sAgQAJTsP2tAQAAEHgw @@ -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 @@ 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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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 @@ -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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 @@ -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 @@ ARBQMPoWICABEHAw/hYhKAAgQTD4gIAv/xBwMP6ULCAIEFAwKpQEjhUqEh8qlA3+lQggABBQMCoW IiqUBSqUBvqUFCngBDog+pQVKAkAQTAolAeIl46QLhYvKIkUKBYd+pYCIAEQUDD6FjAknQC2IMCI KJQFY/v6AAAAKyISKbECZJTs2rBbTWccojMuIhH6o1USAABqsCvCdfqiXC4AIGuwrrv+IA0rkAQ+ 4PsKEioAIFqw/aYKJgD43dD6Fi4iCgA3oB6jSI0gLuJUDt0MHqHWDV8UDv8RD+4MLu0H/uIlKIAB -aDDwgQQAARB4MPD/GgAFEFAw/+4BAAEQWDD8o8YeBQBy8P4WFyAAEFgwWK4sKRIuLxIXL5R5GKMy +aDDwgQQAARB4MPD/GgAFEFAw/+4BAAEQWDD8o8YeBQBy8P4WFyAAEFgwWK4wKRIuLxIXL5R5GKMy KIJACGgKmYBj/fQAAAAAAC8WMos4GKMshC8tFjP4gkAoHgFcMPkWGiwfAVww/RYZK3ABXDD7Fhgk -ACA5MPhECgIAAFCw9EIAIAEQYDBYhIwtEjMvEjIrEjH0FhAiLwA2oIQ0KSBcBARRAEAECQkb/qAm +ACA5MPhECgIAAFCw9EIAIAEQYDBYhJAtEjMvEjIrEjH0FhAiLwA2oIQ0KSBcBARRAEAECQkb/qAm IAEM/lAqIQcoEhApIA0sIAwshAwqhQf5hA0gABBQMJqCKoQVKRIYKoQUKoQG+oQFLEgBSDD4zBEK BwFIMPkJRgtQBDqg/KJBGgkAYrD6ofUYCQBWcCmFFykSHPmFCCwAIGEwLMCA+qCAIAgQSDAphAT5 Eh4t4AQ7IPpqFAwJAGEwLIQHjDcKmQwKmRH6MgYsACBicPaFCSoAA0sQsaopEhCamPyWCSABEFAw KhYhKCAN/pQsIAAQcDAuFiD+kgAoBQBCsCgWIoiXKiB2KpQWKIkU/hYvIAEQUDAqFjD4FhYjHAC2 ICyQBygSGiiUdSgSGSiUdPSAdmwgAWAwKJIaZIC4GKGy+JYcIAgQYDAslAWMNfP5zm3gAWAw+hYu IB0AN6AowngdosyPIC3SXQj/DAr/Ea/dnaxj/fIAHqNULSAMLuCAANAE/g4bAAUQUDD8o1AeAAFw -MP4WEiAAEFgwWK20KRIuLxISL5R5Y/4cKBIaZY+HKJIa+BYRL4cANiAokhsiFjQjFjYMwgoTo0Is +MP4WEiAAEFgwWK24KRIuLxISL5R5Y/4cKBIaZY+HKJIa+BYRL4cANiAokhsiFjQjFjYMwgoTo0Is EhGcgAMiCiOSGiwh3vg2ASAAEBgwI5Yb85YaIf4CYzAsJd4jEjYiEjRj/0YjFjYTozYiFjQMwgoD IwooMd/0FjcgARAgMPShMRgRACIw9CIKCeABQDACiAsojRgojKCCgSScaJQgKJYaIpYblIEiMd70 EjcgAgIQsCI13iISNCMSNmP+7QAAAAAAAPP6C2/qEDAw+iwAABwQWDD8CgAgIBBoMFtZkownKMkU 9IDsYEACUzArwglksOEpsAAsCip8mQgeosgtsgJ+0Uf7CgAgAhBgMFtYiRuiwykSGx+jCxyicJyg -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 +iCCTpZWmL6YEKaQc+6YCIAIQSDD4iBEP/xBYMPukHSgJAEow+KYBIgAAUXBYq6vAINEPAAAAAPyi +/RASEFgw/SAMIgAAefD6FgAgAhBQMFitX/P2vW/qEFAwAAAAAAD8ovQQAhBQMP0gDCASEFgw/iAN +IgAAefBYrVVj/9QAACggXA4EUQBABAgIG/8CAAH/jH4QwJD5FiIgABBAMPgWISABEEgw+RYgIAAQ +UDDz98BgABBwMAAA+woAIAIQYDBbVHBj/yyMLPosAAAAEFgw98wIAAEQaDBYqmXz+PxiAAAysIws ++iwAAAAQWDD3zAgAABBoMFiqXvP432IAADKw8/oaYgAAMzAcosspEh3+IA0iAAB58P0gDCAAEEAw ++BYBIAUQUDD5FgAgEhBYMFitKCkSECsSMY6XKhIw/DIFL8AQQDD/7CAgABBoMP3lFC4AQEfw/RIz IIACe/Cf6Z/oLxIyLhIv8/sFbeABYDAAAPwKACIAAFqw+iINIAEQaDBbUF3z+Zdv9BAwMByiq/4g -DSIAAHnw/SAMIAAQSDD5FgEgBRBQMPgWACASEFgwWK0EKRIQjpcrEjH6EjAvwBBAMP/sICAAEGgw +DSIAAHnw/SAMIAAQSDD5FgEgBRBQMPgWACASEFgwWK0IKRIQjpcrEjH6EjAvwBBAMP/sICAAEGgw /eUULgBAR/D9EjMggAJ78J/pn+gvEjIuEi9j/IwAAGwQCBWhBw4tEaXULkKEDg5LCe4R/wIADgDA B6AfoeEs8iJkwWobogrAkPuwgCAAEFAwbckRAJAECwwb/8cGcAICSnCxqtMP/wIAAACipqAXooH2 -CgAgABBYMPxylyAIEEAwbYoQALAEDAkZCQlD+dEUcAgCWvD3fAQgAgIxsPpp2HAAEFgwZmD/G6C4 -K7J7KvLcq2sJuxGrqiqhNCqtLyqs4BiibQInCQh3CSt9AS+wPgP2HMDaDWYt+bBAJgEAUbD25gwA -gBBgMPkWBCAAea2gKvqcCpodqmr5FgQgAHGuoC+wPw8/HA3/LQ+qNv/6gCD+AlKw/6oBAYAQeDD2 -eRIKAQB6sPp6EgkABD5g+pkCC8AEOKClryn26bStpd0p1um4q6W7KbbpvKiliCmG6RigRCiAwPui -SRJEATogKTx/C5kBCekMZpC2HaBCKp0BKqyACnoSDaoCKkaSLUKIDQ1LCd0Ry9guPH8L7gH+3gwE -ABB4MPrt/CwAPXuQCn8S/0aXIAAQEDDRDxqiNWP/EgDz/vVgABAwMMAg0Q8AAAAA+goEIBgQWDD8 -oi8SAABosFisiQZyEvJGlyAAEBAw0Q8coir5fQEiAABosPgSBCEAAkpw+ZC/IgAAcPD5FgAgAhBQ -MPgWASAYEFgwWKx7xyTRD6x0L0C+JEDAlBRj/8AArHQvQL4kQMCUFGP/sgAAAGwQBhagVg8CAChi +CgAgABBYMPxylyAIEEAwbYoQALAEDAkZCQlD+dEUcAgCWvD3fAQgAgIxsPpp2HAAEFgwZmD+G6C4 +K7J7KvLcq2sJuxGrqiqhNCqtLyqs4BiibQZnCah3K30BL7A8A/YcwNoNZi35sD4mAQBRsPbmDACA +EGAw+RYEIAB6LaAq+pwKmh2qavkWBCAAci6gL7A9Dz8cDf8tD6o2//qAIP4CUrD/qgEBgBB4MPZ5 +EgoBAHqw+noSCQAEPmD6mQILwAQ4oKWvKfbptK2l3SnW6birpbsptum8qKWIKYbpGKBEKIDA+6JK +EkQBOiApPH8LmQEJ6QxmkLcdoEMqnQEqrIAKehINqgIqRpItQogNDUsJ3RHL2S48fwvuAf7eDAQA +EHgw+u38LAA9+5AKfxL/RpcgABAQMNEPGqI2Y/8TAADz/vVgABAwMMAg0Q8AAAAA+goEIBgQWDD8 +oi8SAABosFisjQZyEvJGlyAAEBAw0Q8coir5fQEiAABosPgSBCEAAkpw+ZC9IgAAcPD5FgAgAhBQ +MPgWASAYEFgwWKx/xyTRD6x0L0C8JEC+lBRj/8AArHQvQLwkQL6UFGP/sgAAAGwQBhagVg8CAChi fSZigKKICYgRCGYIKmIHKqIO+woBIAAQYDD6rQIgYAIxsPqgFyEAAhqwWGBC+GwoIgAAKbD4FgAg KAI5sPcWASB4AjmwKVAFy5H6EgEgpAQxcPsSACB0BFFwe1kfLDCV+sEZYAAQIDDaIPQMRwAEEFgw WGAwLTCVsUR9QuolXBR3WcEpMJbLk2iRAmiSS9EP2iD7CgMgABBgMFhgJmP/3Nog+woCIAAQYDBY @@ -4728,26 +4728,26 @@ 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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 +AABsEAQclL39ICIgBRBQMP4hHSAYEFgwWJ7mKCAhE5J9wHoLiBEoNsEaknz7knwQABBgMP0KMiAB EHAw9zbDIAAQeDBbRQb2kncSAAAisPUaACAAxi6gLjLCKSEd/5KHHgkAK7D+Dk8AFABecA/uAg4O T/ogISAAEFgw/AoAIAAQaDBYAmJmoDEqICH7CgAgBBBgMP4KACPgEGgwWAJcZqAYKiAh+woAIAkQ -YDD+CgAhABBoMFgCVmegA9Kg0Q8kIR3ApfySfRAYEFgw/SAiIgAAcTBYnrP6ICEgABBYMPwKBCAA +YDD+CgAhABBoMFgCVmegA9Kg0Q8kIR3ApfySfRAYEFgw/SAiIgAAcTBYnrf6ICEgABBYMPwKBCAA EDAw/mwACAABIDD9GgAuBQBBcFgCRWavvcCw/SoAIAkQYDD6CgIiABBIMPpKAQIAAHGw+iAhLgUA -UnBYAjtmr5UlIR3ApfySYxAYEFgw/SAiIgAAcXBYnpkF7ED0bAAEABBYMPy0OQAUAEFwHZI4DUQC +UnBYAjtmr5UlIR3ApfySYxAYEFgw/SAiIgAAcXBYnp0F7ED0bAAEABBYMPy0OQAUAEFwHZI4DUQC JSAh0w8PAgD7VREABBBAMAhVAiU2wRuSLPwKACAyEGgw+pIoEAEQcDD3NsMgABB4MFtEtfagYmIA ADqwKTLCJTbBGpIoCpkBCUkCCQlPKTbC+5IdEAAQYDD9CjIgARBwMPqSGBAJEEAw+DbDIAAQeDBb -RKX2oD9iAAAasGagL/YkQiIAABKw0Q/ApPsKFCIAAGGwWJ5u0kDRD8Ck/JINEBQQWDBYnmn3f9Ri -AABR8NKg0Q8AAAAAwKH8kgsQFBBYMFieYvP/tGIAAFDwbBAEKyAhGZH60w8LuxErlsEakf4qlsIa +RKX2oD9iAAAasGagL/YkQiIAABKw0Q/ApPsKFCIAAGGwWJ5y0kDRD8Ck/JINEBQQWDBYnm33f9Ri +AABR8NKg0Q8AAAAAwKH8kgsQFBBYMFieZvP/tGIAAFDwbBAEKyAhGZH60w8LuxErlsEakf4qlsIa kfgbkfj8CgAgMhBoMP4KASAJEEAw+JbDIAAQeDBbRIH2oCpiAAASsArqMBmR6SmSMQqZCgzqMAyc -DGrBDm0ICArqMAqaDGqhAmP/8NEPwKH8ke0QFBBYMFieQ9EPAAAAbBAE2iBb/+BnoATSoNEPAPog -ISAAEFgw/AofIAEQaDBYcoQTkdUWkdn2r95gChAoMCggIfuIEQATEEgwCYgCKDbBG5HQ/AoAIDIQ -aDD6kcwQARBwMPU2wyAAEHgwW0RZ96EZYgAAIrDApPsKFCIAAGGwWJ4l2kBmr5D6ICEgABBYMP2T -+BAfEGAwWHJqZq96KSAhJwoYDwIAC5kRB5kCKTbBG5G4/AoAIDIQaDD6kbQQARBwMPU2wyAAEHgw -W0RB96D2YgAAIrDApPsKFCIAAGGwWJ4N2kBmrzD6ICEgABBYMP2T4BAfEGAwWHJSZq8aKiAh0w8L -qhEqNsEbkaL8CgAgMhBoMPqRnhABEHAw9TbDIAAQeDBbRCv3oSBiAAAisNxg+goEIBQQWDBYnffa +DGrBDm0ICArqMAqaDGqhAmP/8NEPwKH8ke0QFBBYMFieR9EPAAAAbBAE2iBb/+BnoATSoNEPAPog +ISAAEFgw/AofIAEQaDBYcogTkdUWkdn2r95gChAoMCggIfuIEQATEEgwCYgCKDbBG5HQ/AoAIDIQ +aDD6kcwQARBwMPU2wyAAEHgwW0RZ96EZYgAAIrDApPsKFCIAAGGwWJ4p2kBmr5D6ICEgABBYMP2T ++BAfEGAwWHJuZq96KSAhJwoYDwIAC5kRB5kCKTbBG5G4/AoAIDIQaDD6kbQQARBwMPU2wyAAEHgw +W0RB96D2YgAAIrDApPsKFCIAAGGwWJ4R2kBmrzD6ICEgABBYMP2T4BAfEGAwWHJWZq8aKiAh0w8L +qhEqNsEbkaL8CgAgMhBoMPqRnhABEHAw9TbDIAAQeDBbRCv3oSBiAAAisNxg+goEIBQQWDBYnfva QGau1yogIfsKACAeEGAw/QoDIAAQcDBYAYtmrr4qICH7CgAgEhBgMP4KACCAEGgwWAGFZq6l2iBb -/wD2rp1gABBYMPskICIAABKw0Q8ALTLCHpGGwLD9DU8AExBgMPogISwJAHdwWHInZq5v+iAhIAAQ -WDD8Ch8gABBoMFhyImauWdogW/91Y/69AB+RjS0ywsCw/90BAAMQcDD+3QIAGBBgMPogIS3gAWww -WHIWZq4q+iAhIAAQWDD8Ch8gABBoMFhyEGauFCggIQuIEQeIAig2wRqRX/uRXxAAEGAw/QoyIAEQ -cDD1NsMgABB4MFtD6feheWIAACKwwKT7ChQiAABhsFidtfP+nmIAAFEwH5OKLTLCKwoADwIA/gpg -LABAf3D+3QIAABBgMPogIS3gAWwwWHH0Zq2j+iAhIAAQWDD9k38QHxBgMFhx72atjfogISAAEFgw -/AoSIBIQaDBYcelmrXf6ICEgABBYMP2TdRAREGAwWHHkZq1h+iAhIAAQWDD9k3AQEBBgMFhx3mat -S/ogISAAEFgw/AoSIAAQaDBYcdlmrTX6ICEgABBYMP1KIiAREGAwWHHTZq0f+iAhIAAQWDD9k2EQ -EBBgMFhxzmatCfogISAAEFgw/AoSIDwQaDBYcchmrPP6ICEgABBYMP2TVxAREGAwWHHDZqzd+iAh -IAAQWDD9k1IQEBBgMFhxvWasx/ogISAAEFgw/AoSIAgQaDBYcbhmrLH6ICEgABBYMP2TSBAREGAw -WHGyZqyb+iAhIAAQWDD9k0QQEBBgMFhxrWashfogISAAEFgw/AofIAAQaDBYcadj/ZQAAB+TOy0y -wsCw/90BAAQQcDD+3QIAGBBgMPogIS3gAWwwWHGdY/0TAGwQBCkgIROQ6/uZEQAdEFAwCpICIjbB -GpDpG5Dp/AoAIDIQaDD+CgEgChBAMPg2wyAAEHgwW0NyZ6AYwKT8kOIQFBBYMFidP/agVmAAEBAw +/wD2rp1gABBYMPskICIAABKw0Q8ALTLCHpGGwLD9DU8AExBgMPogISwJAHdwWHIrZq5v+iAhIAAQ +WDD8Ch8gABBoMFhyJmauWdogW/91Y/69AB+RjS0ywsCw/90BAAMQcDD+3QIAGBBgMPogIS3gAWww +WHIaZq4q+iAhIAAQWDD8Ch8gABBoMFhyFGauFCggIQuIEQeIAig2wRqRX/uRXxAAEGAw/QoyIAEQ +cDD1NsMgABB4MFtD6feheWIAACKwwKT7ChQiAABhsFidufP+nmIAAFEwH5OKLTLCKwoADwIA/gpg +LABAf3D+3QIAABBgMPogIS3gAWwwWHH4Zq2j+iAhIAAQWDD9k38QHxBgMFhx82atjfogISAAEFgw +/AoSIBIQaDBYce1mrXf6ICEgABBYMP2TdRAREGAwWHHoZq1h+iAhIAAQWDD9k3AQEBBgMFhx4mat +S/ogISAAEFgw/AoSIAAQaDBYcd1mrTX6ICEgABBYMP1KIiAREGAwWHHXZq0f+iAhIAAQWDD9k2EQ +EBBgMFhx0matCfogISAAEFgw/AoSIDwQaDBYccxmrPP6ICEgABBYMP2TVxAREGAwWHHHZqzd+iAh +IAAQWDD9k1IQEBBgMFhxwWasx/ogISAAEFgw/AoSIAgQaDBYcbxmrLH6ICEgABBYMP2TSBAREGAw +WHG2Zqyb+iAhIAAQWDD9k0QQEBBgMFhxsWashfogISAAEFgw/AofIAAQaDBYcatj/ZQAAB+TOy0y +wsCw/90BAAQQcDD+3QIAGBBgMPogIS3gAWwwWHGhY/0TAGwQBCkgIROQ6/uZEQAdEFAwCpICIjbB +GpDpG5Dp/AoAIDIQaDD+CgEgChBAMPg2wyAAEHgwW0NyZ6AYwKT8kOIQFBBYMFidQ/agVmAAEBAw 0Q8AACkywiI2wSv6APuZAQAhEFAwCpkCCQlPKTbCGpDTG5DT/AoAIDIQaDD+CgEgCRBAMPg2wyAA -EHgwW0NcZ6+1wKH8kNMQFBBYMFidKWP/pdEPbBAEKSAhE5DC+5kRAB0QUDAKmQIpNsEakMAbkMD8 +EHgwW0NcZ6+1wKH8kNMQFBBYMFidLWP/pdEPbBAEKSAhE5DC+5kRAB0QUDAKmQIpNsEakMAbkMD8 CgAgMhBoMP4KASAKEEAw+DbDIAAQeDBbQ0lmoDwpMsL6ICEgPAB+cPsKACAdEGAw/Qr/IO4QcDBY -AK3SoNEPAAAA+woAIB0QYDD9Cv8g7xBwMFgAptKg0Q8AwKT8kKoQFBBYMFidB2P/tWwQBCJ6w9EP -bBAEKgoF/JLkEBgQWDD9ICIiAABw8Fic/iQgIRWQmQtEESRWwfuQmRAAEGAw/QoyIAEQcDD6kJQQ -ChBAMPhWwyAAEHgwW0Mh96AWYgAAErDApPyQkBAUEFgwWJzt0Q8AAAApUsIkVsEbkYsakswdkswD +AK3SoNEPAAAA+woAIB0QYDD9Cv8g7xBwMFgAptKg0Q8AwKT8kKoQFBBYMFidC2P/tWwQBCJ6w9EP +bBAEKgoF/JLkEBgQWDD9ICIiAABw8FidAiQgIRWQmQtEESRWwfuQmRAAEGAw/QoyIAEQcDD6kJQQ +ChBAMPhWwyAAEHgwW0Mh96AWYgAAErDApPyQkBAUEFgwWJzx0Q8AAAApUsIkVsEbkYsakswdkswD DED9mQEKBQBi8AqZAgkJTylWwvuQgRAAEGAw/QoyIAEQcDD6kHwQCRBAMPhWwyAAEHgwW0MJ96AU -YgAAErDAofyQfhAUEFgwWJzV0Q8A0Q8AAGwQBCkgIRSQbfuZEQABEHAwDpkCKUbBG5Bs/AoAIDIQ -aDD6kGgQChBAMPhGwyAAEHgwW0L19qAOYgAAErAqQsIKKkCaMNEPwKT8kGEQFBBYMFicvtEPAABs +YgAAErDAofyQfhAUEFgwWJzZ0Q8A0Q8AAGwQBCkgIRSQbfuZEQABEHAwDpkCKUbBG5Bs/AoAIDIQ +aDD6kGgQChBAMPhGwyAAEHgwW0L19qAOYgAAErAqQsIKKkCaMNEPwKT8kGEQFBBYMFicwtEPAABs EAQoICHzkFcQChAoMNMP+4gRABoQSDAJiAIoNsEakFP7kFMQABBgMP0KMiABEHAw9TbDIAAQeDBb Qt30kE8QACQuoCkywnSXA8Ai0Q8qICH7qhEABRBYMAuqAio2wRqQQ/uQQxAAEGAw/QoyIAEQcDD1 -NsMgABB4MFtCzWagGCIywgLSQNEPwKT7ChQiAABhMFicmMAl0Q/cQPoKBCAUEFgwWJyUwCXRDwAA -bBAEHJJ2/SAiIAUQUDD+IR0gGBBYMFicjCMgIRSQJwszESNGwfuQJxAAEGAw/QoyIAEQcDD6kCIQ +NsMgABB4MFtCzWagGCIywgLSQNEPwKT7ChQiAABhMFicnMAl0Q/cQPoKBCAUEFgwWJyYwCXRDwAA +bBAEHJJ2/SAiIAUQUDD+IR0gGBBYMFickCMgIRSQJwszESNGwfuQJxAAEGAw/QoyIAEQcDD6kCIQ ChBAMPhGwyAAEHgwW0Kv9qBHYgAAErApQsIjRsEakmIImTIPAgAKmQIpRsL7kBcQABBgMP0KMiAB -EHAw+pASEAkQQDD4RsMgABB4MFtCn/agF2IAABKw0Q8AwKT8kA0QFBBYMFicatEPAMCh/JAPEBQQ -WDBYnGbRDwAAbBAGF5AA+SwAAgAAETD0MExlsAQ6YJIRA0kCKXbBInbCGo/6G4/7/QoyIAEQcDD/ -CgAgABBAMPh2wyIAAGIwW0KE96DAYgAAErDApPyP8hAUEFgwWJxPYABLAAAAAAJLAit2wcCqKnbD -G4/p/AoAIDIQaDD6j+YQARBwMPIWASAAEHgwW0Jy96AVYgAAErDApPyP4RAUEFgwWJw+YAAGACxy +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 -ofyPuBAUEFgwWJwP0Q8ABWgCKHbCwPEvdsNj/74AAGwQBMCl/JHvEBgQWDD9ICIiAABw8FicBPog +ofyPuBAUEFgwWJwT0Q8ABWgCKHbCwPEvdsNj/74AAGwQBMCl/JHvEBgQWDD9ICIiAABw8FicCPog ISAcADTg/Y+mEAAQWDD+j6QQABBgMFv/mNKg0Q8A/Y+gEAAQWDD8CgAgABBwMFv/kvagRGIAABqw JiAhFI+QwFr3j5QXsAQ5oCZGwRqPjvuPjhAAEGAw/QoyIAEQcDD1RsMgABB4MFtCGGaghihCwnSP -1S4hHXfvBNIw0Q8A/JHJEAUQUDD9ICIgGBBYMFib3yIgIQsiESJGwRqPe/uPexAAEGAw/QoyIAEQ +1S4hHXfvBNIw0Q8A/JHJEAUQUDD9ICIgGBBYMFib4yIgIQsiESJGwRqPe/uPexAAEGAw/QoyIAEQ cDD1RsMgABB4MFtCBWagSilCwiJGwRqRuQiZMgqZAilGwhqPbhuPbvwKACAyEGgw/goBIAkQQDD4 -RsMgABB4MFtB92evh2AAIsCk+woUIgAAYfBYm8Mi+rnRD8Ck+woUIgAAYfBYm7/SMNEPwKH8j2QQ -FBBYMFibu9Iw0Q8AAGwQBhqPnSktAiuQFyyifSqigKvMCcwRrKoqohrykNcQgBB4MPmQFiA9ADag +RsMgABB4MFtB92evh2AAIsCk+woUIgAAYfBYm8ci+rnRD8Ck+woUIgAAYfBYm8PSMNEPwKH8j2QQ +FBBYMFibv9Iw0Q8AAGwQBhqPnSktAiuQFyyifSqigKvMCcwRrKoqohrykNcQgBB4MPmQFiA9ADag jaEsogL6ogAgEwA2YGiRGMqZaJECaJI3xirRD68urr4u4MBo4wJp5+ZoRjloRzj4SEVv6hAQMNEP wCDRD68urr4u4MBo49Bo581o4gJp58doRiz/AgAGAFyFIPhIWW/qEBAw0Q8A3cDyCgAgXAC3YNEP AAAAAAAA8//sYgAAarBkwD8FWQkMmQnLliyRAf2RACADEFgw/pECIAAQUDD+NAQsKAFgMP01AyoF -AGLw+jQFIAAQEDDRD8inBVkJCpkJZZ/HwCDRDwD1WwkCAABQcPvbCAACEGAw8rABIAQCWvBYknny +AGLw+jQFIAAQEDDRD8inBVkJCpkJZZ/HwCDRDwD1WwkCAABQcPvbCAACEGAw8rABIAQCWvBYkn3y DkIORQEUMPDxBAH+AnOw/jQFIAEQaDAA3RotNAQsEQD8NQMgABAQMNEPAABk368FWQkNmQlj/2xs EAQWj0siLQInIBcoYn0mYoCniAmIEahm9mIVIAgQeDD8kIMQBBBwMPsKgCACEGgw8iAWIEEANaCJ YYhi9mIAIBMANKBoIRjKLmghAmgiQ8Yq0Q+ryqp6KqDAaKMCaafmaEZJ/wIABgBchSDy+uooAJAB @@ -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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 @@ -5134,45 +5134,45 @@ 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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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 @@ -5289,26 +5289,26 @@ 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 @@ -5321,41 +5321,41 @@ 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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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 @@ -5509,63 +5509,63 @@ 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 @@ -5573,40 +5573,40 @@ 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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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 @@ -5708,43 +5708,43 @@ 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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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 @@ -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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 @@ -5946,47 +5946,47 @@ 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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 @@ 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 @@ -6108,43 +6108,43 @@ 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 @@ -6169,42 +6169,42 @@ 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 @@ -6212,19 +6212,19 @@ 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 @@ -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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 @@ -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 @@ 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 @@ -6355,38 +6355,38 @@ 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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 @@ Ggk9Aw1VAQUzAiOGhGP/BWwQCBtEXvIqCw8AEGAw/kSgERgQODD3JygCAABJsPOqCQfABDjg+O32 K8AEOqD7qggGACBF8PSQeWYAIDmwH0SVAigL+X0EKbAEOiD7RJMYACBaMPuGxSACEGgwnZArfQQZ QYmZsSvxfyd9BCuGwZtyL/F+KV0BD0cuD08s+EGOEAICa/D3RIUeBQA/cLCZ+hYEKABAZnD1lzkK AD7+EAeJFACbEQv7AiumySlmvy9mwNEPLeI9LH0EiMKMwQ3dEQjdLA3MKJoU/BYFKgBLpxAkZr4q -fQT6ogEiAABZMFhPlv0SBSAAEGAwWE4L9FCYbwAQQDAlXQGwVfSwk2QAQEVwjRQFihQArBEMvAIs +fQT6ogEiAABZMFhPmv0SBSAAEGAwWE4P9FCYbwAQQDAlXQGwVfSwk2QAQEVwjRQFihQArBEMvAIs 1skqZr8rZsDRDwCUERlBZ5kQKOI93SD8RF8QAxBQMPcWAynQBDogC4gs+YgoAgAAcPD4FgIgIBBY -MFhNahlBW4wUB4oUAKsRC5sCK8bJKma/KWbA0Q/fQPoKAyAgEFgw/BYAIgAAaLD8REsSAABw8FhN -XIQVY/9KAAAA9URFH3UAtuApfQQYRD/0FgEgARBQMPoWACIAAGiw+II9IgAAcPD5kgIiAAB68PxE -PBAgEFgw9RYDKdAEOiAJiCz4FgIgAxBQMFhNR8CxjhQFjBQAzRENvQIt5sksZr8rZsDRD2wQBvZA -2hEYEDgwByco0w/3Q94WACA5sCNm/yNm/idyf/tD2hIAAFHwWE9I9bwAAgAAIrD7CmQiAABQ8FhP -Q/wKACBkEGgwWE252kD8CgAiAAAa8PtcAAIAAGjwWE2z/7FXYgAAcvAYQRktbQQaQ8gCKQv+Q8gZ +MFhNbhlBW4wUB4oUAKsRC5sCK8bJKma/KWbA0Q/fQPoKAyAgEFgw/BYAIgAAaLD8REsSAABw8FhN +YIQVY/9KAAAA9URFH3UAtuApfQQYRD/0FgEgARBQMPoWACIAAGiw+II9IgAAcPD5kgIiAAB68PxE +PBAgEFgw9RYDKdAEOiAJiCz4FgIgAxBQMFhNS8CxjhQFjBQAzRENvQIt5sksZr8rZsDRD2wQBvZA +2hEYEDgwByco0w/3Q94WACA5sCNm/yNm/idyf/tD2hIAAFHwWE9M9bwAAgAAIrD7CmQiAABQ8FhP +R/wKACBkEGgwWE292kD8CgAiAAAa8PtcAAIAAGjwWE23/7FXYgAAcvAYQRktbQQaQ8gCKQv+Q8gZ sAQ+YPptBCgAIFZw/pbFIAIQYDCc0JihL20EK5bBm/IsksAeQacdQQ8OzAENzAIslsAoksAaQLUK iAIolsAjZv/RD5MQHEO3mxMfQPYbQPb5QQEQAxBQMPkWAinQBDngC4gs+YgoAgAAaLD4FgEgIBBY -MFhNBhtA62P/cwBsEAoWQOgVQwcPAgAtYm0rUuMPAgCi3QndEfxD7BIAIGrwLiA5KiA4/SIAIAEQ +MFhNChtA62P/cwBsEAoWQOgVQwcPAgAtYm0rUuMPAgCi3QndEfxD7BIAIGrwLiA5KiA4/SIAIAEQ eDD5IRsgABBAMPcgByH0AlKwCvg4lxD7IBYoBQBP8PkWAyAAEDgw9xYCIAUQUDD7FgEiAAB48PgW -BCAwEFgwWEzo/wIAAgCAgOAuIDjTD2nmWGQxRGgxOWkyQS9S6S/yF8v4K1IWy7PAQPpDzhCSEDgw +BCAwEFgwWEzs/wIAAgCAgOAuIDjTD2nmWGQxRGgxOWkyQS9S6S/yF8v4K1IWy7PAQPpDzhCSEDgw +hYJLwgQcDAoYnAvUuMJiBGo/67/KvB9YAAlAAAAAAD6LAAAARBYMFqUUSlS6SmSK/8CAAIASf5Q 0Q8AsUR7S+l3qfct8ihk3/GM2XLJ7GTf2I/Y/xYIL9MAN+ApIAf/8AciAABD8PoK+ygCAUww+v8B CeAEPmD8IBYuCQBP8C+EBykgB/4K/CAwEFgw/YIALgBAd/D8hBYoIAFMMPwSCS4JAE/w/4QHIAUQ -UDD/DkEOAgF8MFhMritSFrFE/voIK/+j3RBj/2L6LAACAABY8Ft7YNEPHEOXLUAA/kACIAUQUDD/ -QAEgMBBYMFhMoSkhGytAACskFipAAfokByAKADZgCQlMKSUbLUACHkGWjCsD3RENnQL9JRssCQBz +UDD/DkEOAgF8MFhMsitSFrFE/voIK/+j3RBj/2L6LAACAABY8Ft7YNEPHEOXLUAA/kACIAUQUDD/ +QAEgMBBYMFhMpSkhGytAACskFipAAfokByAKADZgCQlMKSUbLUACHkGWjCsD3RENnQL9JRssCQBz MJwrY/60AAAAAAD6LAAAABBYMFqUD2P+9AAAbBAG9UHhEOUANOD/AgACAGUU4GQwwi1AIg3ZCQyZ -EfggDCgAIE1wKZCA/wIADgBeShD6CgQgMhBYMPxDcRIAAHDwWEx9JUAiFEGUBVgJDIgRqEQrQn9k -sJAaQFwtIAwuoncqooCu3QndEf2qCAABEGAwWCLo1qD5GoAiAFUU4PpNAiCiADTgKqyAKaB5wML8 +EfggDCgAIE1wKZCA/wIADgBeShD6CgQgMhBYMPxDcRIAAHDwWEyBJUAiFEGUBVgJDIgRqEQrQn9k +sJAaQFwtIAwuoncqooCu3QndEf2qCAABEGAwWCLs1qD5GoAiAFUU4PpNAiCiADTgKqyAKaB5wML8 mwIAZAD6cCJCg8E8+6R5IBgANKArIARosQJzsR6CKQ8CAA8CAGUv6/psAAAAEFgwW8vnyqPaUFuH 39EP2iBbf52CKWUvzWP/3mgzD2g0aWg1Cf8CAAf/mADg0Q8tQCIN3wkM/xH+IAwuACB9cC/wgH/p -5voKBCAyEFgw/EM+EgAAcPBYTEnaIPtMAAIAAGDwW4Ga0Q9pNpypSimgef+flHABEGAw+wr9KAkA -YnALiAEopHlj/34AAAAcQy8vQAEuQAItICL4QAAgBBBQMPgWACAyEFgwWEw0KiAiCqsJDLsRq1ss +5voKBCAyEFgw/EM+EgAAcPBYTE3aIPtMAAIAAGDwW4Ga0Q9pNpypSimgef+flHABEGAw+wr9KAkA +YnALiAEopHlj/34AAAAcQy8vQAEuQAItICL4QAAgBBBQMPgWACAyEFgwWEw4KiAiCqsJDLsRq1ss sHnA1PmweiwJAGswLLR5LkAALEAC/UABICoIcnAvsHt8+QoosHj/AgAH/6ZuEC60eiy0ey20eFuH ptEPbBASG0AG87J7IgAAYPAqsoAvsn2iMwkzEfL/CAIAIB6w+DIeL5AEP+CvqoqnKYEDKIECBE4C 8hYZIgAAILD6og4mAI9OEBk/4Rs/9hJASB0/9i0WBCIWCvsWBiBgAlhw8AkHAgAASvAASWEASWEs FhUuFhYfQvoqFhQYQvn4Fg0uCQB9MP8WDCIAAGuwW4OC+jIeIAAQWDBa730XP+EqFhgYP94VQGEc Qu8sFhfwAFxiAAAysMLIWu16ZaCl+xwQIgAAUXD8CgQgAhBoMFrrQywSFy4SFf8SFiAEEFAw+FIA -ICQQWDD4FgAiAABpMFhL5voyHiACAlmwWu9lKRIYGD/HFUBJ+pFXcgAAMrAognclUoSmiAmIEahV +ICQQWDD4FgAiAABpMFhL6voyHiACAlmwWu9lKRIYGD/HFUBJ+pFXcgAAMrAognclUoSmiAmIEahV K1Ep97HQcAQQaDCPUAj/EQ3/Ap8VLlAHiVcODkH8mRQvAAQ7oPqcIC4JAHLw+5IJLgkAE7D+Fggv YgC3IPP/WmAAEFgwANEPAIuo+4hXABsQSDB5gSyOVy3hFfz6wCBAAnOwDOwBrNz7rEAoAC1mkPrs AAAoEGAwWu1DZK8kY//HAAALD0N/ScyIqQgIX2mFxCmgKMieaJEcaZO5KRIVaZOzYAAnACsSFWmy @@ -6460,32 +6460,32 @@ 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 @@ -6496,41 +6496,41 @@ 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 @@ -6538,37 +6538,37 @@ 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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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 -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//// -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 -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 -BEvUAARB2AAES9gABEHcAARL3AAEcDgABHAAIAtxgAAEcAQAAMAAIAtxwAAEYMgAAIAkAARAHAAE -ShwAABcsIAtyACALcjA7msoAAARg5AAEYNAgC3JgAARAAAAEQAQABEAMAARACCADCtQABEoEAARw -NAAEcAgABFAAAARUAAAEYMwAAH8AAARB0AAES9AABHBQAARQaAAEUEAABFRoIAgH8AAEUFAABFRQ -AARSJAAAQEAABFIoAARSLAAEQBAABEgQAARAFAAESBQgCAgQAARB4AAES+AgCAg0AARB6AAES+gA -BEHkAARL5AAEQewABEvsAARAGAAEShgAAO7wAARQYAAEVGAAABEAAAARMAAAEDAgCAPoIAgDPCAI -BUggCAScIAgGqCAIBfwABBMEAAQTJAD///8AgQIg4QHiQOEAEgD/wAwAH/+URB//lbAgC3UgAf// -/wPf0kACFg7A4QNGAB//mngABFSwAADj7wAEULAABGDgAADB8x//rIgf/4QQ//x//wAAfuiAAAcA -gAAFAIAABgCAAAQAgAABAIAAAgAgCT9gIAt1cB//lIAgCUDgIAMIwCALdaAAD///IAdT+B//rTAf -/6wAH/+u4B//rwAf/5SzH/+sMABUAAAgDAAA4QT+AOEFBgAAJAAA4QHeAOEAWgD4AAP/3//+AAAA -gGAAAEAJAAAJxCALu0AgC7uQIAu7wCALvIAgC7xQIAu7EN6tvu8gCAxEIAgOVAAJiWggCA5EIAgM -BCAIDpQgAw+gIAu8sCALddAf/6uQIAoAAAAKAAAgC3YA4v/+AB//q9Af/63UH/+ZDCAKoAAgCuBA -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 -KzLSHfZKHPZKDbsBDLsCKzbSKzLSGvXGKqDACbsB+zbSIjgBOqAsMtMe9kId9kMOzAENzAIsNtMl -NvQlNvXA9C4y3g/uAi423iwywR32PP3MAQCAEGgwDcwCLDbBKjLCG/Y4C6oCKjbCLyItGfY2GPY2 -+vY2HgBAT/D89jUeCQBH8P8mLSAFEFgwW5ciGvYv/PYwEAYQWDBblx4a9iz89iwQBxBYMFuXGxr2 -KPz2KRAIEFgwW5cXGvYl/PYlEAkQWDBblxQa9iH89iIQChBYMFuXEBr2Hvz2HhALEFgwW5cNGvYc -HPYeGPYc+CYOICAQWDAPAgBblwf69hcRQRBYMP0KACD/EGAwW5ko+vYSEUEQWDD9CgAg/xBgMFuZ -JBr2Dfz2DxDkEEgw+SYKICMQWDBblvga9gj89goQJBBYMFuW9Rr2BPz2BhAlEFgwW5bxG/YFmyyb -K5stKXBAmRAtMtwtFgEsMtgPAgAPAgAMTFP8FgIk8gA2YPkWACACjIZg+RYAIgLXgmD/AgACAueG -YMYq9PWIEAIhLKApCszyCoAgABBQMPJOCAAAECgwLuDA+0JRIpAAN6D1XAEkACBJMPlS6W4AIBEw -9qQMYgAAErAU9eYvQtQZ9eUY9eUJ/wH4/wIALhBQMP9G1CAHEFgwW3DAKmF9/wIAAAHz6pD7CgIg -rxBQMFtwq/oKKyABEFgwW3Co+gorICkQWDBbcLX6CjIgARBYMFtwo/oKMiApEFgwW3Cv+govIAEQ -WDBbcJ36Ci8gLBBYMFtwqvoKJiABEFgwW3CY+gomICkQWDBbcKT6CjogRxBYMFtwofsKASCpEFAw -W3CQ+wotIKkQUDBbcJz6CjYgAxBYMFtwivoKNiAuEFgwW3CW+go3IAEQWDBbcIX6CjcgPBBYMFtw -kfoKJSACEFgwW3B/+golIAMQWDBbcIv6CjsgAhBYMFtwevoKOyAGEFgwW3CG+woBILMQUDBbcHQr -YYEiChgPAgD/AgAIAYfYkPsKViCzEFAwW3B8+gpHIAEQWDBbcGosYYH/AgAIAX9gkPoKRyA6EFgw -W3B0+gpGIAEQWDBbcGItYYEPAgAPAgD/AgAIAXPokPoKRiA5EFgwW3Bq+gpAIEwQWDBbcGf6CjMg -TRBYMFtwZfoKOSBOEFgwW3Bi+gqyIGIQWDBbcF/6CkkgTxBYMFtwXPoKTSABEFgwW3BL+wphIE0Q -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 -VBnp4Q17OCtWJCxSJSpSJKyq+5bbIf4CUrAoUictUiYqltwIfTgtViYvUicsUiavzP2W1yH+AmMw -K1IpKFIoLJbYC3g4KFYoKlIpL1Ioqv/45vUh/gJ78CxSKC/m9i1SKStSKK27/JbfIf4CWvAqUisv -UiorluAKfzgvViooUistUiqo3f/m9yH+AmtwK1IqLeb4LFIrKlIqrKr7luMh/gJSsChSLS5SLCqW -5Ah+OC5WLC9SLS1SLK/d/pbhIf4Ca3AsUi8qUi4tluIMejgqVi4rUi8oUi6riPqW6SH+AkIwKJbq -LkLwH+obD+4CLkbwLULCLVY3LELYLFY4K0LZK1Y5KkLbKlY6KULwKVY7KELsKFY80Q/AICdGxidG -yCJGzSJGzidGyiJGyyJGzCJmGyJGxydGxSdmGCdmGSdmGmP+tQAAAAAAAPrpixFBEFgwW4p0AqwC -+umHEUEQWDBbinVj/OgnRsZj/SEf6Pku8MHAhAjuAi70wWP87cCh/On2EAYQWDBbtWjGKtEPwKH8 -6fMQBhBYMFu1ZMYq0Q/Aofzp8BAGEFgwW7Vg0Q9sEAQb6Q79CgEiAAB4sNMPKrJ2DwIAf6cSLLJw -/MwQAAAQcDD8LwwKAD4TEP6nEHACEHAwLLJxDMwQf8t4DP8MfacoLLJyDMwQf8t1/P8MAD4A7rD6 -CgEgABBYMPzo+RIAAGiwW7VFxirRDwB7p+QtsoIM3RD/09twBhBwMJ9A/jYAIAYQcDD9LAAABRBQ -MPzo7RAAEFgwW7U5wCDRDwAAAAAAAPJGACAAEHgwnzDz/9ViAAB4sJ0wn0Dz/8lgARBwMJ9AnjDz -/71gAhBwMAAAbBAEJlpA+gqAIgAAQTD9+sAgQAJYsPMmACBgAmCw/CYMIAAQSDD8Jg0iHwEkMPkl -FCoAQG7w9aU6AIACWvD7JgkgcAJQsPsmCCgFABmw+CUVIgAAWXBbZo4DZDn7XAACAABRMFt8/Qpu -FC4lAtEPAGwQBBrpnQMLBvKihiIAAGiwKKKBKaKFDSIM9IATYgBAEvAoooIJmDl4IwUipoZgAAHA -IM8hIqJ8LKJ9oyL5onoh/gIQsPTAM2IAQBLwK6J7C5sMC8s2LKJ4yMmtLHyzBSymfGAAAcAgyCDR -D8Cg/OjXEAYQWDBbtPHRDwDz/9ZiAABacGwQBhPpQCgyIxXpKPIKACBFADYgJlJ6JDLfDwIApiYJ -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 -8/5LYgAAWnAZ4Kgqku0rku7HwPmS6yAeAlKw9LCJagBAYrAc4KEswuwMnAwMuzYe4J4u4unI7are -frMJH+CbLvbtYAACAMCg9KwADqEAtqDAoPzfzRAGEFgwW6vnY/6MAAAb4JH7sgoiAABQ8Ftdax3g -jh/glPzgnhAyEFgw/dIKIgAAcrD+9oMgBRBQMFur2h/gjC/yg/769CAAEBAwD+I4yCvRDwAA8/+D -YgAAWnAAFd/pIlLb9VLcIgAAUPBbXVQY4ID6hkkiAABQ8FtdSxzgfcCQKcZNLcJJKsZKLcZLDasM -At0MC2sUm8cNbRT9xkwiAABQ8FtdSRzgcvrGBiAIALagxyTRDx7gbhzgev3iSSIAAHiw/uJKIAUQ -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 -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 +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 +/gDhBQYAACQAAOEB3gDhAFoA+AAD/9///gAAAIBgAABACQAACcQgC7tAIAu7kCALu8AgC7yAIAu8 +UCALuxDerb7vIAgMRCAIDlQACYloIAgORCAIDAQgCA6UIAMPoCALvLAgC3XQH/+rkCAKAAAACgAA +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 +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 +cHj6CkcgARBYMFtwZixhgf8CAAgBf2CQ+gpHIDoQWDBbcHD6CkYgARBYMFtwXi1hgQ8CAA8CAP8C +AAgBc+iQ+gpGIDkQWDBbcGb6CkAgTBBYMFtwY/oKMyBNEFgwW3Bh+go5IE4QWDBbcF76CrIgYhBY +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 +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 +ooEpooUNIgz0gBNiAEAS8CiiggmYOXgjBSKmhmAAAcAgzyEionwson2jIvmieiH+AhCw9MAzYgBA +EvAronsLmwwLyzYsonjIya0sfLMFLKZ8YAABwCDIINEPwKD86NMQBhBYMFu08dEPAPP/1mIAAFpw +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 +8/ow9SgAIG+w+hYCKAAgfnD7FgEoACBmcPwWACgAIF5w/NlzGAAgVnD5FjIgBhBYMPkWAyAFEFAw +W6TXKhIyzKktEj3wADVgABB4MMCx+xY0IAgQWDBbpuIuMO0tEjL+3QgAABBgMFulVigSNPgIBg4B +AEbw/RI9LgBAR/AuQCn8MXwgCBBYMA+7DPvaKABAEEAw/MwQDgkAQ7D+RCkqAwBisBzZsSoWGf/Y +KA90AVAw/bwAAAYQWDD4Fj4pdAFAMPgWACAFEFAwW6SzKRIZ0w/+Ej4l4wA2YBrY9ik2Kvo2KSgA +IFZwLRI2/9krEAoAN6ApNi0uNi4r8nYq8ncLqgwqFjwNOxQrFjNaUu0uMOwpMXv8EjwgCBBoMArd +DPTlnGjABD5gLhIz0w8N7igJ7jYvQCkoCoAI/wIvRCnA8PoWASAAEEgw/hYYK3QBZDD82YcfdAFw +MPsWAiAFEFAw+RYAIAYQWDBbpIwpEhjInBzY0fk2KCwAIGHwLDYnLTInZNDhLTIpZNDbLRYdHNl8 +/jIqIAUQUDD+Fi8gBhBYMFukficyGStCiiww7ygyJCpCjv9CkiwAICswLMCALhIv+vkICAAgWjD3 +zCgIACBKMAjuDPwWEioCk2OQLhIdp+73CAYB/gJzsPw2Ki4AQEOw/jYpIgAAazAc2WL9MicoACBz +cC4yKC4WOy0WMChGifsKBigAIFow+EaNKAAgUjD4RpEuACB+MP82IyAFEFAwW6RaLzDu9zIaLgAg +L/Av8IAuEjsH/yj/AgAKAnH7kCgSMKeI9wkGAf4CQjD/NigoAEBKMCg2JyoyLdMPyKQrMi5b8/8v +QpD1EhEgGQA34K9V/wgGAf4CKXAIVQH1Ro8kACB9cChCiSVcP/SENGQAQDVwKEKNKUKMJUaL9IQz +ZAAgLnAvQpLI9CpCkWSkM4gzKzInLDJm9TYCJAAgLjAlNmX0sIVkACAvMCkyKWSQei8w7xrYsScy +GikyGS4yKi0yKCgw7gnuLAfdLKqI+ICALgAgV/Av8ICu16h39woYLgAgP/AH2CwH6Sz82MMYACB+ +cPmICAAGEFgwB/cs/jYbJgAgRfD9NhwnoAQ94PcWACAFEFAwW6QVJVw/9zYsJABANXD1NiskACA9 +cCky4igyJtMP9TbhKAAgLnD1+oAg/gJKcAWVAfU2JSQAIC4w2lBba7ovMilk+6snMhn/AgAL/ZOr +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 -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 +cBL2oFpiAAASsC4KAS4WBRrNQ44UKqJ/DqsoLDroDLsse2Mb+c4TE/+E/RDz/wRrAAQ+4AAAAADz +/3Zv6hAQMB/ODfzODRABEFgwCv8s/UwAAAQQUDBbmMobzCtj/8QA0Q/RD2wQDhvOBfocAABIEGAw +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 +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 8c96715c0bd6..442643eeebbf 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 425c56358e7e..fae7979db9a8 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 147802d927bf..eb972d074612 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 @@ do_close_con_rpl(struct sge_iq *iq, const struct rss_header *rss, } 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 fc5f9350db79..127abe0c1217 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 @@ do_pass_establish(struct sge_iq *iq, const struct rss_header *rss, */ 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 @@ do_pass_establish(struct sge_iq *iq, const struct rss_header *rss, 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 @@ do_pass_establish(struct sge_iq *iq, const struct rss_header *rss, * 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 a980fba80a77..d0a248892e4f 100644 --- a/sys/dev/cxgbe/tom/t4_tom.c +++ b/sys/dev/cxgbe/tom/t4_tom.c @@ -36,9 +36,11 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include +#include #include #include #include @@ -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 @@ update_clip_table(struct adapter *sc, struct tom_data *td) 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 0a79d3b5c467..fd1aa146e021 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 356ccc5d80da..1b4591722165 100644 --- a/sys/dev/drm2/i915/i915_gem.c +++ b/sys/dev/drm2/i915/i915_gem.c @@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$"); #include #include #include + #include #include #include @@ -69,38 +70,40 @@ __FBSDID("$FreeBSD$"); #include -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); + ret = -sx_xlock_sig(&dev->dev_struct_lock); + if (ret) + return ret; - return (0); + 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) +static bool +i915_gem_object_is_inactive(struct drm_i915_gem_object *obj) { - 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) -{ - 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 @@ i915_gem_shmem_pwrite(struct drm_device *dev, 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 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, 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 @@ i915_gem_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot, * 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 @@ i915_gem_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot, 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,19 +1576,145 @@ 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) +/** + * 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_release_mmap(struct drm_i915_gem_object *obj) { - struct drm_i915_private *dev_priv; + vm_object_t devobj; + vm_page_t page; + int i, page_count; + + if (!obj->fault_mappable) + 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); + + 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); + } + VM_OBJECT_WUNLOCK(devobj); + vm_object_deallocate(devobj); + } + + obj->fault_mappable = false; +} + +static uint32_t +i915_gem_get_gtt_size(struct drm_device *dev, uint32_t size, int tiling_mode) +{ + uint32_t gtt_size; + + if (INTEL_INFO(dev)->gen >= 4 || + tiling_mode == I915_TILING_NONE) + return size; + + /* Previous chips need a power-of-two fence region when tiling */ + if (INTEL_INFO(dev)->gen == 3) + gtt_size = 1024*1024; + else + gtt_size = 512*1024; + + while (gtt_size < size) + gtt_size <<= 1; + + return gtt_size; +} + +/** + * i915_gem_get_gtt_alignment - return required GTT alignment for an object + * @obj: object to check + * + * Return the required GTT alignment for an object, taking into account + * potential fence register mapping. + */ +static uint32_t +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; + + /* + * 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); +} + +/** + * 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) +{ + if (tiling_mode == I915_TILING_NONE) + return 4096; + + /* + * Minimum alignment is 4k (GTT page size) for sane hw. + */ + if (INTEL_INFO(dev)->gen >= 4 || IS_G33(dev)) + return 4096; + + /* 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); +} + +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 = dev->dev_private; struct drm_i915_gem_object *obj; int ret; - dev_priv = dev->dev_private; - 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, handle)); if (&obj->base == NULL) { @@ -2131,694 +1734,61 @@ i915_gem_mmap_gtt(struct drm_file *file, struct drm_device *dev, } ret = drm_gem_create_mmap_offset(&obj->base); - if (ret != 0) + if (ret) 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); -} - -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) -{ - uint32_t old_write_domain; - - if (obj->base.write_domain != I915_GEM_DOMAIN_GTT) - 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); - - /* 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); - } - - 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; - } - - CTR3(KTR_DRM, "object_change_domain set_to_cpu %p %x %x", obj, - old_read_domains, old_write_domain); - return (0); -} - -static uint32_t -i915_gem_get_gtt_size(struct drm_device *dev, uint32_t size, int tiling_mode) -{ - uint32_t gtt_size; - - if (INTEL_INFO(dev)->gen >= 4 || - tiling_mode == I915_TILING_NONE) - return (size); - - /* Previous chips need a power-of-two fence region when tiling */ - if (INTEL_INFO(dev)->gen == 3) - gtt_size = 1024*1024; - else - gtt_size = 512*1024; - - while (gtt_size < size) - gtt_size <<= 1; - - return (gtt_size); -} - /** - * i915_gem_get_gtt_alignment - return required GTT alignment for an object - * @obj: object to check + * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing + * @dev: DRM device + * @data: GTT mapping ioctl data + * @file: GEM object info * - * Return the required GTT alignment for an object, taking into account - * potential fence register mapping. + * 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. */ -static uint32_t -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); - - /* - * 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)); -} - -uint32_t -i915_gem_get_unfenced_gtt_alignment(struct drm_device *dev, uint32_t size, - int tiling_mode) -{ - - if (tiling_mode == I915_TILING_NONE) - return (4096); - - /* - * Minimum alignment is 4k (GTT page size) for sane hw. - */ - if (INTEL_INFO(dev)->gen >= 4 || IS_G33(dev)) - return (4096); - - /* - * 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); -} - int -i915_gem_object_sync(struct drm_i915_gem_object *obj, - struct intel_ring_buffer *to) +i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) { - struct intel_ring_buffer *from = obj->ring; - u32 seqno; - int ret, idx; + struct drm_i915_gem_mmap_gtt *args = data; - 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; + return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset); } -static void i915_gem_object_finish_gtt(struct drm_i915_gem_object *obj) +/* Immediately discard the backing storage */ +static void +i915_gem_object_truncate(struct drm_i915_gem_object *obj) { - u32 old_write_domain, old_read_domains; + vm_object_t vm_obj; - /* 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); + 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; } -int -i915_gem_object_unbind(struct drm_i915_gem_object *obj) +static inline int +i915_gem_object_is_purgeable(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); - } - - 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; - } - - 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); + return obj->madv == I915_MADV_DONTNEED; } static void @@ -2826,98 +1796,23 @@ i915_gem_object_put_pages_range_locked(struct drm_i915_gem_object *obj, vm_pindex_t si, vm_pindex_t ei) { vm_object_t vm_obj; - vm_page_t m; + vm_page_t page; vm_pindex_t i; 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) + 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(m); + vm_page_unlock(page); } } -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 int -i915_gem_object_get_pages_range(struct drm_i915_gem_object *obj, - off_t start, off_t end) -{ - 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); -} - -static int -i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj, - int flags) -{ - struct drm_device *dev; - vm_object_t vm_obj; - vm_page_t m; - vm_pindex_t i, page_count; - int res; - - 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_WUNLOCK(vm_obj); - return (0); -} - #define GEM_PARANOID_CHECK_GTT 0 #if GEM_PARANOID_CHECK_GTT static void @@ -2945,10 +1840,23 @@ 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; - - 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); - - 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); - } - - obj->fault_mappable = false; + return (!list_empty(&dev_priv->mm.flushing_list) || + !list_empty(&dev_priv->mm.active_list)); } -int -i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj) +static void +i915_gem_lowmem(void *arg) { - int ret; + struct drm_device *dev; + struct drm_i915_private *dev_priv; + struct drm_i915_gem_object *obj, *next; + int cnt, cnt_fail, cnt_total; - KASSERT((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0, - ("In GPU write domain")); + dev = arg; + dev_priv = dev->dev_private; - 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); + if (!sx_try_xlock(&dev->dev_struct_lock)) + return; + + CTR0(KTR_DRM, "gem_lowmem"); + +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++; } + + /* 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); +} + +static int +i915_gem_object_get_pages_range(struct drm_i915_gem_object *obj, + off_t start, off_t end) +{ + vm_object_t vm_obj; + vm_page_t page; + 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++) { + 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); +} + +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) { + if (request->file_priv) { 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) +static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, + struct intel_ring_buffer *ring) { - 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); - 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) -{ - 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; + + 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; +} + +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); +} + +/** Flushes the GTT write domain for the object if it's dirty. */ +static void +i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj) +{ + uint32_t old_write_domain; + + if (obj->base.write_domain != I915_GEM_DOMAIN_GTT) + return; + + /* 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); + } + + i915_gem_object_flush_cpu_write_domain(obj); + + old_write_domain = obj->base.write_domain; + old_read_domains = obj->base.read_domains; + + /* 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_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; + } + + CTR3(KTR_DRM, "object_change_domain set_to_gtt %p %x %x", obj, + old_read_domains, old_write_domain); + + /* 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; + } + + 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) + 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, 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); + + 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 -i915_gem_object_is_inactive(struct drm_i915_gem_object *obj) +intel_enable_ppgtt(struct drm_device *dev) { + if (i915_enable_ppgtt >= 0) + return i915_enable_ppgtt; - return !obj->active; + /* Disable ppgtt on SNB if VT-d is on. */ + if (INTEL_INFO(dev)->gen == 6 && intel_iommu_enabled) + return false; + + return true; } -static void -i915_gem_retire_task_handler(void *arg, int pending) +int i915_gem_init(struct drm_device *dev) { - drm_i915_private_t *dev_priv; - 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; - bool idle; int i; - dev_priv = arg; - dev = dev_priv->dev; + for_each_ring(ring, dev_priv, i) + intel_cleanup_ring_buffer(ring); +} - /* 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; +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); } - CTR0(KTR_DRM, "retire_task"); + DRM_LOCK(dev); + dev_priv->mm.suspended = 0; - 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); + ret = i915_gem_init_hw(dev); + if (ret != 0) { + DRM_UNLOCK(dev); + return ret; } - if (!dev_priv->mm.suspended && !idle) - taskqueue_enqueue_timeout(dev_priv->tq, - &dev_priv->mm.retire_task, hz); - + 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) +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) { - drm_i915_private_t *dev_priv; + void *vaddr = (char *)obj->phys_obj->handle->vaddr + args->offset; + char __user *user_data = to_user_ptr(args->data_ptr); - dev_priv = dev->dev_private; - return (!list_empty(&dev_priv->mm.flushing_list) || - !list_empty(&dev_priv->mm.active_list)); -} + if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) { + unsigned long unwritten; -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; - - CTR0(KTR_DRM, "gem_lowmem"); - -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++; - } - - /* 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. + /* 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. */ - if (i915_gpu_idle(dev) == 0) - goto rescan; + DRM_UNLOCK(dev); + unwritten = copy_from_user(vaddr, user_data, args->size); + DRM_LOCK(dev); + if (unwritten) + return -EFAULT; } - DRM_UNLOCK(dev); + + i915_gem_chipset_flush(dev); + return 0; } -void -i915_gem_unload(struct drm_device *dev) +void i915_gem_release(struct drm_device *dev, struct drm_file *file) { - struct drm_i915_private *dev_priv; + struct drm_i915_file_private *file_priv = file->driver_priv; - dev_priv = dev->dev_private; - EVENTHANDLER_DEREGISTER(vm_lowmem, dev_priv->mm.i915_lowmem); + /* 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; + + 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; + } + mtx_unlock(&file_priv->mm.lck); } + +static vm_page_t +i915_gem_wire_page(vm_object_t object, vm_pindex_t pindex, bool *fresh) +{ + vm_page_t page; + int rv; + + 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 89c8060fd3cb..117c07cc3f7c 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 528ad149ae89..830325b2ef95 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -2029,9 +2029,6 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp) /* 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 384a46bc223d..9eacc78a1cf4 100644 --- a/sys/dev/e1000/if_igb.c +++ b/sys/dev/e1000/if_igb.c @@ -1908,9 +1908,6 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp) 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 000000000000..3ff74f1e8969 --- /dev/null +++ b/sys/dev/gpio/gpiobacklight.c @@ -0,0 +1,211 @@ +/*- + * Copyright (c) 2015 Oleksandr Tymoshenko + * 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 +__FBSDID("$FreeBSD$"); + +#include "opt_platform.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#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 9c57aedd3a55..c30f31c4807c 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -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); @@ -634,16 +636,9 @@ ndis_attach(dev) goto fail; } - /* - * 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; + return (error); +} - callout_init(&sc->ndis_scan_callout, 1); +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; - 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; - } + callout_init(&sc->ndis_scan_callout, 1); - 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]); - } + 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 @@ ndis_attach(dev) #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; + 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; + 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; + /* + * Get station address from the driver. + */ + len = sizeof(ic->ic_macaddr); + ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &ic->ic_macaddr, &len); - if (bootverbose) - ieee80211_announce(ic); + 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; - } 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); - } + if (bootverbose) + ieee80211_announce(ic); -fail: - if (error) { - ndis_detach(dev); - return (error); - } + return (0); +} - if (sc->ndis_iftype == PNPBus && ndisusb_halt == 0) - return (error); +static int +ndis_ifattach(struct ndis_softc *sc) +{ + struct ifnet *ifp; + u_char eaddr[ETHER_ADDR_LEN]; + int len; - DPRINTF(("attach done.\n")); - /* We're done talking to the NIC for now; halt it. */ - ndis_halt_nic(sc); - DPRINTF(("halting done.\n")); + ifp = if_alloc(IFT_ETHER); + if (ifp == NULL) + return (ENOSPC); + sc->ifp = ifp; + ifp->if_softc = sc; - return (error); + /* 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; - 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; + if ((error = priv_check(curthread, PRIV_DRIVER)) != 0) + return (error); + + 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 @@ ndis_scan_results(struct ndis_softc *sc) 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 f98db0a203cd..e3b1a39c35c5 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 d3eb85e8f188..1ffd24c5243d 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 @@ ipw_scan(struct ipw_softc *sc) 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 @@ ipw_assoc(struct ieee80211com *ic, struct ieee80211vap *vap) 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 cca050f3e469..aa3ba5bb4944 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 5188ac827664..10430f6f1512 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 fecbe89c4562..73631eaa1e5f 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 void -iwi_start_locked(struct ifnet *ifp) +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(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 int -iwi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +static void +iwi_parent(struct ieee80211com *ic) { - 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 iwi_softc *sc = ic->ic_softc; + int startall = 0; IWI_LOCK_DECL; - 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_LOCK(sc); + if (ic->ic_nrunning > 0) { + if (!sc->sc_running) { + iwi_init_locked(sc); + startall = 1; } - 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; + } else if (sc->sc_running) + iwi_stop_locked(sc); + IWI_UNLOCK(sc); + if (startall) + ieee80211_start_all(ic); +} + +static int +iwi_ioctl(struct ieee80211com *ic, u_long cmd, void *data) +{ + struct ifreq *ifr = data; + struct iwi_softc *sc = ic->ic_softc; + int error; + IWI_LOCK_DECL; + + IWI_LOCK(sc); + switch (cmd) { 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 @@ iwi_init_fw_dma(struct iwi_softc *sc, int size) 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 b38bbd91d2c0..47848e16c822 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 3cd5d7b066dd..cfed420ce8dd 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 9366fc2bf7fb..ed275bf7c4f4 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 3787db390771..7742eeae9f0b 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 741837949909..2790fdc8400c 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 @@ malo_attach(uint16_t devid, struct malo_softc *sc) 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 @@ malo_desc_setup(struct malo_softc *sc, const char *name, 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 void -malo_start(struct ifnet *ifp) +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 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; + 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++; } - IEEE80211_ADDR_COPY(mp, - LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); - - 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 @@ malo_setmcastfilter(struct malo_softc *sc) 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 @@ malo_rx_proc(void *arg, int npending) 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 bac290c6330b..681e7501aa67 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 32914a386484..373b7097eaf4 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 2d3a5bef613e..04452f2fbe8a 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 81e3083a33cf..162cd94f396b 100644 --- a/sys/dev/mmc/host/dwmmc.c +++ b/sys/dev/mmc/host/dwmmc.c @@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include @@ -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 09975005eec2..be80e465cd39 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 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc) mwl_hal_detach(mh); bad: MWL_RXFREE_DESTROY(sc); - if_free(ifp); sc->sc_invalid = 1; return error; } @@ -545,13 +523,11 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc) int mwl_detach(struct mwl_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - struct ieee80211com *ic = ifp->if_l2com; + struct ieee80211com *ic = &sc->sc_ic; - 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); /* * 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 void -mwl_start(struct ifnet *ifp) +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 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 @@ mwl_rx_proc(void *arg, int npending) 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<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 ef7009c785d1..d9da128af70e 100644 --- a/sys/dev/mwl/if_mwl_pci.c +++ b/sys/dev/mwl/if_mwl_pci.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/dev/mwl/if_mwlvar.h b/sys/dev/mwl/if_mwlvar.h index 7071ba03562b..4a4b338239e5 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 20a4026304e8..38b28445add1 100644 --- a/sys/dev/nand/nfc_rb.c +++ b/sys/dev/nand/nfc_rb.c @@ -31,16 +31,11 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include -#include #include #include #include #include -#include -#include -#include #include diff --git a/sys/dev/nvme/nvme.c b/sys/dev/nvme/nvme.c index 329c5e56e82d..cc14d34afbc4 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 59e49eea6485..4b89b53b9966 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 4cc16c150792..365ba5ae4116 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 47922db9d863..0a500cb23bb6 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 @@ agtiapi_probe() 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 52f1146ffdd0..6f6bf7b08916 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 519b4ca30d78..42ec03424bdf 100644 --- a/sys/dev/ral/if_ral_pci.c +++ b/sys/dev/ral/if_ral_pci.c @@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c index 29ce8cbf8014..ea9c4162b8f8 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); + rt2560_get_macaddr(sc, ic->ic_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; 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 void -rt2560_start_locked(struct ifnet *ifp) +static int +rt2560_transmit(struct ieee80211com *ic, struct mbuf *m) { - struct rt2560_softc *sc = ifp->if_softc; - struct mbuf *m; - struct ieee80211_node *ni; + struct rt2560_softc *sc = ic->ic_softc; + int error; - 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; - } - ni = (struct ieee80211_node *) m->m_pkthdr.rcvif; - if (rt2560_tx_data(sc, m, ni) != 0) { - ieee80211_free_node(ni); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - break; - } - - sc->sc_tx_timer = 5; + 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(struct ifnet *ifp) +rt2560_start(struct rt2560_softc *sc) { - struct rt2560_softc *sc = ifp->if_softc; + struct ieee80211_node *ni; + struct mbuf *m; - RAL_LOCK(sc); - rt2560_start_locked(ifp); - RAL_UNLOCK(sc); + RAL_LOCK_ASSERT(sc); + + 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); + break; + } + sc->sc_tx_timer = 5; + } } 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 b6a8d68e9236..3a5fef981080 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 15a2364a2c74..c77d4f88df76 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 void -rt2661_start_locked(struct ifnet *ifp) +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(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 9927d138fa71..7ea16f623d57 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 782fa1f9780b..b3c737d67c66 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 28a3d59b8263..3779e5beb1d1 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 17d792a5db54..bd3e51b91a20 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 @@ dwc_otg_host_setup_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)) { @@ -789,7 +793,7 @@ dwc_otg_host_setup_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)) { @@ -801,7 +805,7 @@ dwc_otg_host_setup_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) { @@ -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 1ba0a5e4ce7e..39c9529757c7 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 c0dc79f18b11..b33df36d9276 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)); } @@ -1790,6 +1798,82 @@ uftdi_set_error_char(struct ucom_softc *ucom, int echar) return (usbd_do_request(sc->sc_udev, &sc->sc_mtx, &req, NULL)); } +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 a2d6e3876ae0..a1ea325b89a2 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 0db2f3808756..b6244831de32 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 89b8c0007723..463a9bdc9a08 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 @@ rsu_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) } 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 @@ rsu_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) } - 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 @@ rsu_bulk_tx_callback_sub(struct usb_xfer *xfer, usb_error_t error, 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; + struct rsu_softc *sc = ic->ic_softc; + int 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); + 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 @@ rsu_init_locked(struct rsu_softc *sc) } static void -rsu_stop(struct ifnet *ifp, int disable) +rsu_stop(struct rsu_softc *sc) { - 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) -{ - 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 db0751dfcd09..4e6cd884fab8 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 d5142ea8315e..6a558f66395f 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 @@ rum_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 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 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) (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 void -rum_start(struct ifnet *ifp) +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 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; @@ -2073,30 +2018,14 @@ fail: rum_stop(sc); #undef N } -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 17944aaf3b41..35da6d38a0e9 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 ac14178a3c7e..193b9adcb213 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 @@ run_wme_update_cb(void *arg) 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 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) } 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 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) 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 @@ run_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) 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 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index) 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 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index) 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 @@ run_bulk_tx_callbackN(struct usb_xfer *xfer, usb_error_t error, u_int index) 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 @@ run_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, return (error); } -static void -run_start(struct ifnet *ifp) +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 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) { + if ((sc->sc_flags & RUN_RUNNING) == 0) + return; + + while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { + ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; + if (run_tx(sc, m, ni) != 0) { + mbufq_prepend(&sc->sc_snd, m); + break; + } + } +} + +static void +run_parent(struct ieee80211com *ic) +{ + struct run_softc *sc = ic->ic_softc; + int startall = 0; + + RUN_LOCK(sc); + if (sc->sc_detached) { RUN_UNLOCK(sc); return; } - for (;;) { - /* send data frames */ - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - - 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; - break; - } - } - + 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); -} - -static int -run_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct run_softc *sc = ifp->if_softc; - struct ieee80211com *ic = sc->sc_ifp->if_l2com; - struct ifreq *ifr = (struct ifreq *) data; - 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); - } - } - 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 (error); + 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++) @@ -6184,36 +6111,20 @@ run_init_locked(struct run_softc *sc) run_stop(sc); } -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 ad0fc30fe599..b8cb12f5e1b6 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 fca9e39a6a27..04e092040c14 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) +uath_stop(struct uath_softc *sc) { - struct uath_softc *sc = arg; - - UATH_LOCK(sc); - (void)uath_init_locked(sc); - UATH_UNLOCK(sc); -} - -static void -uath_stop_locked(struct ifnet *ifp) -{ - 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 @@ uath_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) 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 @@ uath_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) } 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 @@ uath_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error) 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 fae360460bbb..56b5ba35a2b6 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 a2e493ed64fa..b882fe36164e 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; - } - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - upgt_stop(sc); - } - 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; + if (sc->sc_flags & UPGT_FLAG_DETACHED) { + UPGT_UNLOCK(sc); + return; } - return error; -} - -static void -upgt_stop_locked(struct upgt_softc *sc) -{ - struct ifnet *ifp = sc->sc_ifp; - - UPGT_ASSERT_LOCKED(sc); - - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - upgt_set_macfilter(sc, IEEE80211_S_INIT); - upgt_abort_xfers_locked(sc); + 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 { + upgt_init(sc); + startall = 1; + } + } else if (sc->sc_flags & UPGT_FLAG_INITDONE) + upgt_stop(sc); + UPGT_UNLOCK(sc); + if (startall) + ieee80211_start_all(ic); } static void upgt_stop(struct upgt_softc *sc) { - struct ifnet *ifp = sc->sc_ifp; - UPGT_LOCK(sc); - upgt_stop_locked(sc); - UPGT_UNLOCK(sc); + UPGT_ASSERT_LOCKED(sc); + if (sc->sc_flags & UPGT_FLAG_INITDONE) + upgt_set_macfilter(sc, IEEE80211_S_INIT); + upgt_abort_xfers_locked(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) +upgt_init(struct upgt_softc *sc) { - 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) -{ - 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) + UPGT_ASSERT_LOCKED(sc); + + if ((sc->sc_flags & UPGT_FLAG_INITDONE) == 0) return; - UPGT_LOCK(sc); - for (;;) { - IFQ_DRV_DEQUEUE(&ifp->if_snd, m); - if (m == NULL) - break; - + 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 @@ upgt_tx_start(struct upgt_softc *sc, struct mbuf *m, struct ieee80211_node *ni, * 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 @@ upgt_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) (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 @@ upgt_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) } 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 @@ upgt_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error) 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 c50276be9cb4..3dcd335aa248 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 79a5be0a63f7..e8224ba3f149 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 @@ ural_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 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 @@ ural_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) } 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 void -ural_start(struct ifnet *ifp) +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 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; @@ -2143,29 +2092,13 @@ fail: ural_stop(sc); #undef N } -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 c62b0e449680..f40f71d9de08 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 f8b77d427521..f0d2674e56e7 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 @@ urtw_adapter_start_b(struct urtw_softc *sc) 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) @@ -1376,16 +1345,6 @@ urtw_stop_locked(struct ifnet *ifp) urtw_abort_xfers(sc); } -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) { @@ -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); - - 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; - } - } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) - urtw_stop(ifp); - } - 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; + if (sc->sc_flags & URTW_DETACHED) { + URTW_UNLOCK(sc); + return; } - return (error); + + 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 { + urtw_init(sc); + startall = 1; + } + } 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); + } + 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 @@ urtw_8225_isv2(struct urtw_softc *sc, int *ret) 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 @@ urtw_tx_enable(struct urtw_softc *sc) 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 @@ urtw_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) } 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 @@ urtw_bulk_tx_status_callback(struct usb_xfer *xfer, usb_error_t error) 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 @@ urtw_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error) 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 6b712b3dbcb6..457a88526516 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 @@ urtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) } 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 @@ urtwn_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error) 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; - 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; + if (sc->sc_flags & URTWN_DETACHED) { + URTWN_UNLOCK(sc); + return; } - return (error); + 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 (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,38 +3410,15 @@ urtwn_init_locked(void *arg) } static void -urtwn_init(void *arg) +urtwn_stop(struct urtwn_softc *sc) { - struct urtwn_softc *sc = arg; - - URTWN_LOCK(sc); - urtwn_init_locked(arg); - URTWN_UNLOCK(sc); -} - -static void -urtwn_stop_locked(struct ifnet *ifp) -{ - 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) { @@ -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 2bbec7a10647..0ca9db7bd230 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 e99cbf4e30a7..a423214de87b 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 8f9035eaeb0e..a86ab8a3f061 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 @@ zyd_set_led(struct zyd_softc *sc, int which, int on) 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 @@ zyd_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) } 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 @@ zyd_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 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 void -zyd_start(struct ifnet *ifp) +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 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]); @@ -2810,30 +2762,14 @@ fail: zyd_stop(sc); return; } -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 05d94e399709..ec61d06434f5 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 b316d46dae74..f8af23138340 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) +wi_stop(struct wi_softc *sc, int disable) { - 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) -{ - 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 void -wi_start_locked(struct ifnet *ifp) +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(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 @@ wi_info_intr(struct wi_softc *sc) 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 @@ wi_write_multi(struct wi_softc *sc) } 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 fd70e77074a7..414dc20dba1b 100644 --- a/sys/dev/wi/if_wi_pccard.c +++ b/sys/dev/wi/if_wi_pccard.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include diff --git a/sys/dev/wi/if_wi_pci.c b/sys/dev/wi/if_wi_pci.c index 198c599ef54a..b218c2479a69 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 f163744ef834..9b668cc0e114 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 34406059b437..01ce3e467695 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); - m_freem(m); - return ENETDOWN; - } + ac = M_WME_GETAC(m); WPI_TX_LOCK(sc); + + if (sc->sc_running == 0 || wpi_tx_ring_is_full(sc, ac)) { + m_freem(m); + error = sc->sc_running ? ENOBUFS : ENETDOWN; + goto unlock; + } + 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); + +unlock: 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); - + 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__); + +unlock: WPI_TX_UNLOCK(sc); + + return (error); +} + +/** + * Process data waiting to be sent on the output queue + */ +static void +wpi_start(void *arg0, int pending) +{ + struct wpi_softc *sc = arg0; + struct ieee80211_node *ni; + struct mbuf *m; + uint8_t i; + + WPI_TX_LOCK(sc); + if (sc->sc_running == 0) + goto unlock; + + 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__); - WPI_TX_UNLOCK(sc); -} - -static void -wpi_start_task(void *arg0, int pending) -{ - struct wpi_softc *sc = arg0; - struct ifnet *ifp = sc->sc_ifp; - - wpi_start(ifp); +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 b7835281fb39..4e1baa5fdc50 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 7e2eca783e97..526ce54928d4 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; + struct wtap_softc *sc = ic->ic_softc; - 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){ - - 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 3bdc8980b387..04a1818d5c41 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 a6036d84961a..773644fda27c 100644 --- a/sys/dev/xen/balloon/balloon.c +++ b/sys/dev/xen/balloon/balloon.c @@ -49,8 +49,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - 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 0610732bfb98..5ff9d38a68dc 100644 --- a/sys/dev/xen/blkfront/blkfront.c +++ b/sys/dev/xen/blkfront/blkfront.c @@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include @@ -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 8dcd322b12b3..28c6ff2b48de 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_REQUEST_SIZE \ - MIN(MAXPHYS, XBD_SEGS_TO_SIZE(BLKIF_MAX_SEGMENTS_PER_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_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 2a0d459ee621..219a3953a24e 100644 --- a/sys/dev/xen/control/control.c +++ b/sys/dev/xen/control/control.c @@ -145,9 +145,6 @@ __FBSDID("$FreeBSD$"); #include -#include -#include - /*--------------------------- 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 2233084edb42..c58b324abbfb 100644 --- a/sys/dev/xen/netback/netback.c +++ b/sys/dev/xen/netback/netback.c @@ -87,8 +87,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - /*--------------------------- 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 3eac25dccd35..2f972b847e39 100644 --- a/sys/dev/xen/netfront/netfront.c +++ b/sys/dev/xen/netfront/netfront.c @@ -86,8 +86,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include - #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 @@ network_alloc_rx_buffers(struct netfront_info *sc) 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 1613e0ae0ca0..1730bf8fc09f 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 fe8e9ef3f03f..806843769a11 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 6b9041d6e4a8..1c5c3bb9b8c9 100644 --- a/sys/fs/ext2fs/ext2_subr.c +++ b/sys/fs/ext2fs/ext2_subr.c @@ -54,10 +54,6 @@ #include #include -#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 @@ ext2_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp) 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 d3bac30bdc74..a6a216727133 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 #include +#include #include #include #include @@ -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 15f5243717cf..d1ade4aaf153 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 f7bf1fdad713..f68800197eda 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 a60efe8f1445..d636e1fb0ba0 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 2539e1b1d8b8..0d34ef5a51d5 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 0b8e118a6944..e72e709a25ae 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 732de9d5e8d0..8363d06ebaec 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 7a00740a998c..6a00d2361539 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 5bf7944568e9..4d8e22fc3002 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 2be5dbc5070e..76790f0d5c31 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 083aa4af0ec9..09425230eb41 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 a642d10088f7..f8ae6d957729 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -118,11 +118,7 @@ __FBSDID("$FreeBSD$"); #include #include #include -#ifdef SMP #include -#else -#include -#endif #include #include @@ -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 f67b279e4393..62e99aa7f2c9 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 adc86cac623a..3242d76dce80 100644 --- a/sys/i386/include/atomic.h +++ b/sys/i386/include/atomic.h @@ -37,9 +37,31 @@ #include #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(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 34d85be25a1f..8816f3c8ddea 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 e6102405d4e3..13655eea7735 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 b3fd85f45344..f7968f830800 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 231f80f6a303..cfd8d03c2e6d 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 5eb54c224f9a..000000000000 --- 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 f48b1f14719d..000000000000 --- 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 -#include - -#include - -#include - -#include -#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 484c279c0ff1..000000000000 --- 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 - -#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 a362d00fbfdf..efb7317c0e09 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 933e4cc5cc81..dc0ee49c3851 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 f8c6cf099fe5..06cb763b33c0 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 517b68978338..56207a00c98c 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -562,6 +562,10 @@ do_execve(td, args, mac_p) 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 a031435455aa..85dbd944325c 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 68903ba079e5..2072dc726b08 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 bb92e18db790..a4fde06198f4 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 36a8470d2971..aa671804afd6 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 97e198584ddb..bec8f6b0669b 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 945608da2834..2667e6e3482c 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 370d0d6fca4b..6541724f5aef 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 fd619cd32e08..6ad2ed8bde4b 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 4d57fd3f3fcf..3a91673bab11 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 1ba1ab2aff53..96e117b429b5 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 52075e47045d..b32198f18493 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include @@ -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 8ff8f764dedb..a40aa5a358c8 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 59bd38737118..da77c4be105f 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 74ae85f5efcf..708478f27558 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 cba656aa1884..5043a57bfefb 100644 --- a/sys/kern/subr_param.c +++ b/sys/kern/subr_param.c @@ -138,13 +138,6 @@ SYSCTL_PROC(_kern, OID_AUTO, vm_guest, CTLFLAG_RD | CTLTYPE_STRING, NULL, 0, sysctl_kern_vm_guest, "A", "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 70e76ad39952..a81c9dee055f 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 cb88034b06fa..66109604ad57 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 fb8433027b81..21cbe49e5cb6 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -68,6 +68,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -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 d29c308d825b..5f68bde8cd1c 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -64,9 +64,11 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include +#include #include #include #include @@ -76,6 +78,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #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) { + /* + * If we're not defragging or low on bufspace attempt to make a new + * buf from a header. + */ + 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 or we need to start recycling. + */ 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 (nbp == NULL && defrag == 0 && (bufspace + maxsize < hibufspace || - metadata)) { - nqindex = QUEUE_EMPTY; - nbp = TAILQ_FIRST(&bufqueues[QUEUE_EMPTY]); - } - - /* - * All available buffers might be clean, retry ignoring the - * lobufspace as the last resort. - */ - if (nbp == NULL && !TAILQ_EMPTY(&bufqueues[QUEUE_CLEAN])) { nqindex = QUEUE_CLEAN; nbp = TAILQ_FIRST(&bufqueues[QUEUE_CLEAN]); } @@ -2332,28 +2417,21 @@ getnewbuf_scan(int maxsize, int defrag, int unmapped, int metadata) /* * 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 @@ getnewbuf_scan(int maxsize, int defrag, int unmapped, int metadata) 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 @@ getnewbuf_scan(int maxsize, int defrag, int unmapped, int metadata) */ if (defrag) { bp->b_flags |= B_INVAL; - bufkvafree(bp); brelse(bp); defrag = 0; goto restart; @@ -2424,7 +2501,6 @@ getnewbuf_scan(int maxsize, int defrag, int unmapped, int metadata) */ if (qindex == QUEUE_CLEAN && BUF_LOCKWAITERS(bp)) { bp->b_flags |= B_INVAL; - bufkvafree(bp); brelse(bp); goto restart; } @@ -2437,16 +2513,11 @@ getnewbuf_scan(int maxsize, int defrag, int unmapped, int metadata) * 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 9ac193a9ebd5..f935954fcef2 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 b24a6aeb761a..3c189d1a2df5 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -2850,7 +2850,7 @@ vfs_notify_upper(struct vnode *vp, int event) /* * 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 c8c49810b503..ecc93e13346e 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 d1e0da0efa95..0133fada2343 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 1db8d857bf67..c8b1dfbb433c 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 c23b4515bdd4..e2f44687d411 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 2aa661a7ffcd..86efd02b975c 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 633efa1ff21d..72edfba91041 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 7ab4244d9685..0d126e4b4962 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 0c0b8236b170..000000000000 --- 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 -__FBSDID("$FreeBSD$"); -/* - * RTC chip sitting on the I2C bus. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#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 0827ca7ce84b..ed85a1b9c47a 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 96f982066702..2605887d6048 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 508488414136..7b0e286c9fea 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 16be94005f55..391632c3ec72 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 eba2faa20b43..c74e3c1a00e9 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 709c2555132b..4eb2f01df560 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 diff --git a/sys/modules/zfs/Makefile b/sys/modules/zfs/Makefile index 05d226c1fb13..ffbd9ba6ce9e 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 9fc5e9f7433c..985208b1975a 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 df326e69b8b6..a74b521e5fef 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 74e1ae488ab9..64bb982aab22 100644 --- a/sys/net/bpf_buffer.c +++ b/sys/net/bpf_buffer.c @@ -79,8 +79,6 @@ __FBSDID("$FreeBSD$"); #include #include -#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 48a842a9dd93..78b4d9da4430 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 6743981c9009..841a0f20741e 100644 --- a/sys/net/if_spppsubr.c +++ b/sys/net/if_spppsubr.c @@ -28,7 +28,9 @@ #include #include +#include #include +#include #include #include #include diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c index aed2a37379d6..cbcee141ea62 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 #include #include @@ -84,10 +81,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -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 98ffd4aecc7b..bab26fe9411e 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 d16c92490729..d6db35ea3a94 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 @@ rn_delete(void *v_arg, void *netmask_arg, struct radix_node_head *head) 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 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 cc262fa745eb..d4bb58a47ed4 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 992cf8e72b0f..a88742267ccf 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 3902227e8c43..39e03eaff93f 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include @@ -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) @@ -1394,15 +1356,6 @@ media2mode(const struct ifmedia_entry *ime, uint32_t flags, uint16_t *mode) return 1; } -/* - * 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. */ @@ -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 e646cf2b7417..ae4910c6ee0d 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 3af75dfc78c0..9a8e94172030 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 54ab39072ecc..1c7ddb9e15e4 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 d11628df04ac..eb333da139cb 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 91668cc7c0d2..2d216c2ac7c8 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 01c60e1614e5..7adf0445d7fd 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 a8123931588f..b5918b44a1cd 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 9dfef2c5f168..efbe1a81fbc8 100644 --- a/sys/net80211/ieee80211_regdomain.c +++ b/sys/net80211/ieee80211_regdomain.c @@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$"); #include #include #include - #include #include @@ -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 c0cbb7d2de4f..709710c1e9e4 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 26238b88e4f1..a4507010f7fa 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 aa370d6f904d..1012e93c2863 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -42,12 +42,14 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include #include #include +#include #include #include @@ -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 a094a499f7bf..185f5c2b5a04 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -58,6 +58,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include #include @@ -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 @@ igmp_intr(struct mbuf *m) 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 f47492ddaf1a..c2c7ce089c22 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -44,7 +44,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include #include @@ -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 e634987cf4c9..0afdea278c39 100644 --- a/sys/netinet/in_gif.c +++ b/sys/netinet/in_gif.c @@ -67,8 +67,6 @@ __FBSDID("$FreeBSD$"); #include -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 93557f8f335b..c168780c7283 100644 --- a/sys/netinet/in_mcast.c +++ b/sys/netinet/in_mcast.c @@ -38,9 +38,11 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include +#include #include #include #include @@ -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 bc48e105f69b..c721c6dd950c 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -47,11 +47,13 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -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 606795a69bb0..2b7932538615 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) * - * ipi_lock (before) inpcb locks (before) {ipi_hash_lock, pcbgroup locks} + * The lock order is: + * + * 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 0318fb2ff9a2..f9e98128bc1c 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 0886cc8277fe..c5c1c4ebf57f 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 b6b967f6d59c..57553f547f75 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include @@ -647,6 +649,7 @@ icmp_input(struct mbuf **mp, int *offp, int proto) 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 4140edac5460..e1cbb43c87f7 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -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 588bc0542a31..086a8c94a604 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -44,11 +44,13 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -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 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, * 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 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, 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 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, 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 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, /* 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 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, #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; - - ip = mtod(m, struct ip *); - needfiblookup = 0; - - /* 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); + if (PFIL_HOOKED(&V_inet_pfil_hook)) { + switch (ip_output_pfil(&m, ifp, inp, dst, &fibnum, &error)) { + case 1: /* Finished */ goto done; - } else { + + case 0: /* Continue normally */ + ip = mtod(m, struct ip *); + break; + + 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. */ + ro->ro_lle = NULL; + rte = NULL; + gw = dst; + ip = mtod(m, struct ip *); + goto again; + } } - /* 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; - /* 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 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, 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 a71d8ec86f71..4e9fedaac817 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -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 a64e7f95f730..540cc65ff08c 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 f8bf05ff7d24..7d92655cc745 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -2312,11 +2312,8 @@ sctp_service_queues(struct sctp_tcb *stcb, struct sctp_association *asoc) 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 79a86e2a6ff0..94cd49c6f51b 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 aa7c30c6bf51..9071bf6708ee 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 1beab07adbda..1c56f9ad9d4a 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -5524,7 +5524,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 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 @@ sctp_lower_sosend(struct socket *so, 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 541d4ca3b6c2..07119f15d9ff 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 257d18845b23..6c8589eea1df 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 b613992fb5ae..069ed34c346a 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 9454a6565b03..e7ef6dbb80d8 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 @@ tcp_input(struct mbuf **mp, int *offp, int proto) 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 @@ tcp_input(struct mbuf **mp, int *offp, int proto) */ 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 @@ tcp_input(struct mbuf **mp, int *offp, int proto) */ #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 @@ tcp_input(struct mbuf **mp, int *offp, int proto) } 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 @@ tcp_input(struct mbuf **mp, int *offp, int proto) */ 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 @@ tcp_input(struct mbuf **mp, int *offp, int proto) */ 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 @@ tcp_input(struct mbuf **mp, int *offp, int proto) * 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 @@ tcp_input(struct mbuf **mp, int *offp, int proto) 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 @@ tcp_input(struct mbuf **mp, int *offp, int proto) 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 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, */ 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 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, */ 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 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, * 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 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, * 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 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, 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 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, 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 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so, 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 17d9a79eb50d..77d8940a0d92 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -71,33 +71,80 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef TCPDEBUG +#include +#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); @@ -144,14 +189,47 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m) return (0); } + /* + * 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 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m) */ 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 757bcf2e43db..808eb9736f7c 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 7d97ae081a6b..2c853b3b55e2 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -652,6 +652,8 @@ syncache_unreach(struct in_conninfo *inc, struct tcphdr *th) /* * 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 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m) * 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 d992492cddc7..e0073346a548 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 @@ tcp_timer_keep(void *xtp) #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 @@ tcp_timer_persist(void *xtp) #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 @@ tcp_timer_rexmt(void * xtp) 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 1ba74d86ae68..4685fe734f5e 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 4ea39e300cff..36d5312aec26 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 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m, ((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 df01735c5e5d..d16f27b0f379 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 1021475f9319..5ca460483537 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 4340150a7f14..754a5f334231 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -80,6 +80,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include @@ -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 126890f73077..d714f236384e 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 8c25e982cdeb..d8a32d504aa4 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -39,7 +39,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include +#include #include #include diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 10cd3f2b1bf0..9f876a4cbb92 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 227f234206a8..020c5cfe9370 100644 --- a/sys/netinet6/in6_src.c +++ b/sys/netinet6/in6_src.c @@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -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 (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; + } } - - /* - * 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 - */ - - + /* 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) { - /* XXX-BZ WT.? */ - if (ron->ro_rt) { - RTFREE(ron->ro_rt); - ron->ro_rt = NULL; - } - error = EHOSTUNREACH; - 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 { + /* + * 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; - } -#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; - } - if (ron->ro_rt == NULL) { - 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. - */ goto done; } diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h index a486ce188287..81ca8396da6e 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 78e8ef3b6b39..e4e388f3712c 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -82,6 +82,8 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include @@ -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 ae360700b629..a6611a7e7fcb 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 34e8c413f274..9927509a4524 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 97ac0616a11d..b5bdb0ed42ca 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 15dbc9cf502c..3fe28eb6c155 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 132717fa839e..fee457be8794 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 0710578a0345..350a735a89b3 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 e0dc2b2728e6..a48c0386b9af 100644 --- a/sys/netipsec/xform_esp.c +++ b/sys/netipsec/xform_esp.c @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include #include @@ -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)) - crde->crd_flags |= CRD_F_IV_EXPLICIT; + if (SAV_ISCTRORGCM(sav)) { + ivp = &crde->crd_iv[0]; - /* XXX Rounds ? */ + /* 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; + } + + 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 afa3944244a6..e32c7cc7a26c 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 int -search_ip6_addr_net (struct in6_addr * ip6_addr) -{ - struct ifnet *mdc; - struct ifaddr *mdc2; - struct in6_ifaddr *fdm; - struct in6_addr copia; +static const struct in6_addr lla_mask = {{{ + 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}}}; - 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; - } - } +static int +ipfw_localip6(struct in6_addr *in6) +{ + 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 81d010fb17fd..fba04328237e 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -3681,7 +3681,7 @@ pf_create_state(struct pf_rule *r, struct pf_rule *nr, struct pf_rule *a, 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 @@ pf_test(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) !((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 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp) !((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 384f5653bdec..497f0ed41fc7 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 11b3ba372186..3eedca1d6b6a 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 2d7e8a8c3530..2565f514e9b1 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 d3e8add794ea..102563f2abb5 100644 --- a/sys/ofed/include/linux/in.h +++ b/sys/ofed/include/linux/in.h @@ -37,7 +37,7 @@ #include #include -#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 5aa450f6a44b..d14fb3a81376 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 77ab5076be26..052916b8b683 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 9e8a1c1afec8..cb44bfad029a 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 5db57c3230e9..000000000000 --- a/sys/pc98/include/privatespace.h +++ /dev/null @@ -1,6 +0,0 @@ -/*- - * This file is in the public domain. - */ -/* $FreeBSD$ */ - -#include diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c index 6d4ddebb77d5..473473846026 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 9471c24fb839..44caec686d72 100644 --- a/sys/powerpc/aim/mmu_oea64.c +++ b/sys/powerpc/aim/mmu_oea64.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include @@ -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 656b7a336fb3..275ae8dee895 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 50da262b8013..4eea0bda5870 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 4fe1b4023f7b..37bfb20034ae 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 79b2d96709fd..2c79cd696e72 100644 --- a/sys/powerpc/include/pcpu.h +++ b/sys/powerpc/include/pcpu.h @@ -35,6 +35,7 @@ #include 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 0089d76a5413..6c41c74a5dc5 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 a27eb82400a0..a0718994dd07 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 1d3d04190a3d..6056345b6eb7 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 dcc626f801a8..270336922f6d 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 d5d167f54a02..b13882e0820e 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 dbcc59c6cd4b..df43810ef0b5 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 f10678eb79dc..e0dca86e69b2 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 2ffa4f5b27fb..d5ce0e51d87a 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 089c9b3874f0..0f132318c827 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 b557706bb04e..f75927b86b72 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 3d5a7c1c4428..39a41d3a40d7 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 f4193c8257df..8f56c9482257 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 40893ed34477..62c4b05c0061 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 0ea259bd9ab8..abfb7cdcd4d8 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 799bbf5fd8eb..f685df3fbe76 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 #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 d22c349bb678..ce68ba80a085 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -35,6 +35,7 @@ #include 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 4c66431e55f4..988dbae94087 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 980c79667fbc..db929815ca49 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 07794dfe038b..145950710a10 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 e2460a36be2d..67f7e5ceebc2 100644 --- a/sys/ufs/ffs/ffs_subr.c +++ b/sys/ufs/ffs/ffs_subr.c @@ -55,10 +55,6 @@ __FBSDID("$FreeBSD$"); #include #include -#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 d73babc83ccd..1d18823a6a19 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 7391465cc3d2..50983ca389f3 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) @@ -243,15 +243,6 @@ vm_fault_dirty(vm_map_entry_t entry, vm_page_t m, vm_prot_t prot, vm_pager_page_unswapped(m); } -/* - * 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: * @@ -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 @@ RetryFault:; } /* - * 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 @@ RetryFault:; * * 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 @@ RetryFault:; 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 @@ RetryFault:; */ 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 @@ RetryFault:; * 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 f8172bda702a..65c3e2c4217e 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 3bf7a6719ad8..2c0a4ad50859 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 a42061c0417b..40d7d4e43ac7 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 2cfc630026de..34e69e11b832 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, @@ -234,6 +239,33 @@ static boolean_t vm_reserv_has_pindex(vm_reserv_t rv, 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. */ diff --git a/sys/x86/include/_types.h b/sys/x86/include/_types.h index 816a30123270..b130be3d040d 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 8af3039d0856..32e338efb2c0 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 6c849ffea72f..e88a4d7915fb 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 548da4a0e10a..4fe3e3cbe99d 100644 --- a/sys/x86/x86/identcpu.c +++ b/sys/x86/x86/identcpu.c @@ -1294,6 +1294,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. */ @@ -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 b4c66a58faa5..c23108cc7ad6 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 3bc4b4399f5c..a728ddb22e62 100644 --- a/sys/x86/xen/xen_intr.c +++ b/sys/x86/xen/xen_intr.c @@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include diff --git a/sys/xen/interface/io/blkif.h b/sys/xen/interface/io/blkif.h index 160547a27502..9c73ae7e863c 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: * 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: * - * 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: + * + * The physical sector size, in bytes, of the backend device. * * sectors * Values: * - * 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. */ /* @@ -403,6 +508,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. @@ -410,12 +539,18 @@ */ #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 a64262a7b1da..c10c097b37b6 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 ccbacafbd7a1..986b70eeb459 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 1795eefa6a52..08fbb2159c63 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 diff --git a/tests/sys/vm/mmap_test.c b/tests/sys/vm/mmap_test.c index 7591a0996971..00abeb628b6f 100644 --- a/tests/sys/vm/mmap_test.c +++ b/tests/sys/vm/mmap_test.c @@ -29,16 +29,18 @@ #include #include #include -#include +#include #include +#include +#include #include -#include +#include 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); } } - - return (error != 0); +} + +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 (atf_no_error()); } diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index dbbe28329c45..532db1eef02b 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 dd95162591e5..b68aa52c049e 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 000000000000..f06a60692344 --- /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 e4780582c860..e30f48d3762e 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 000000000000..dc85e2b5defd --- /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 000000000000..eabaac375142 --- /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 f9b404b1b26c..3ef454466f9d 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 0fae9879d2ce..1f0c3f176516 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 48a112ba0c30..0fde8fc1bb62 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 3f948b72f983..04a9da8b2ef4 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 cf9d4f27542f..ec4890dd201f 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 000000000000..bcea31b32460 --- /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 590c17854c13..89582aa995ed 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 02e99f1a92c9..6998c04e0d9c 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 3d5e2b87667b..4dee029b96aa 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 6b8477773c6a..309f467ccc82 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 41e8ea6cff9e..4d473c9c34cd 100644 --- a/usr.bin/calendar/calendars/calendar.freebsd +++ b/usr.bin/calendar/calendars/calendar.freebsd @@ -122,6 +122,7 @@ 04/03 Hellmuth Michaelis born in Kiel, Schleswig-Holstein, Germany, 1958 04/03 Tong Liu born in Beijing, People's Republic of China, 1981 04/03 Gabor Pali born in Kunhegyes, Hungary, 1982 +04/04 Jason Unovitch born in Scranton, Pennsylvania, United States, 1986 04/05 Stacey Son born in Burley, Idaho, United States, 1967 04/06 Peter Jeremy born in Sydney, New South Wales, Australia, 1961 04/07 Edward Tomasz Napierala born in Wolsztyn, Poland, 1981 diff --git a/usr.bin/elfcopy/Makefile b/usr.bin/elfcopy/Makefile index 8e7f31d2b9bd..dc6dd47be719 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 diff --git a/usr.bin/find/extern.h b/usr.bin/find/extern.h index 3afe6e4f7d15..b2e344acd7a8 100644 --- a/usr.bin/find/extern.h +++ b/usr.bin/find/extern.h @@ -32,7 +32,7 @@ #include -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 11a26beccf9c..df2e5025457c 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 d8271372a922..781b6e0b4406 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 32887e058ab5..98c45554384c 100644 --- a/usr.bin/ipcrm/ipcrm.c +++ b/usr.bin/ipcrm/ipcrm.c @@ -34,6 +34,9 @@ __FBSDID("$FreeBSD$"); #include +#define _WANT_MSG_PROTOTYPES +#define _WANT_SEM_PROTOTYPES +#define _WANT_SHM_PROTOTYPES #define _KERNEL #include #include @@ -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 be1c2e9fcbb2..a3bec6350e82 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 ce195d9b41ee..0405c5b37c27 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 3b1d63e94136..b982791396d8 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 9b2f1227bf7c..a2be9b15555b 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[@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,:/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'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?[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<N>@*10,QSKL/$Z3)H. +ME??MIGG=JA$_E@D5^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[!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-65KF1EK#$M-#`Y-BUB9LCS$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("`#$M-#`Y-BUB@4]`YT!3KCME&@[\'D`-1I"S:UM(]0EQ_O57G.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#$M-#`Y-BUE8G(N=FAD+F]U=`"METUSI"`0AN_S -M*SJUMQPL:*&=7+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?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^#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>``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`OSR_QGCIVL3JE3YMZ&^+^!SYM090ET]=?25!A9<*OK_[ +MO38=;6+U[H^?ATN7^*_MZ"LI]AGT]^7*?\F*[ +A]O7DRGVF?3WY#$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';-D,< -M5L.FRN/I5_WG9!;Z>")5U*B/K>:*M+OY]%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%/.\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'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`#$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;">@(*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&)@"?1W,;2A<&@5-"7L% +MJWGO+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 a3ebac582f05..eee43f3e43bd 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`">#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&POTA9V7F -MVNOKE9V?9V!JE73`:J_)>$"77UCTW<0R,'!W1Q_$[C8:5X7SN8?#3]R%$-?N -MYG9?W56LKLNL -CV*%]/9EVGVE?3[;=Y]G7:US6?3VI?VR,G?X#`*JO#$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./7X\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<+'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&>&)$'ZD(( +MU^[Z=I_=3O)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 3445c958ed66..dbaca2298497 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@]Z`ITQOU<@=Y`O@:@0=.PN4IS"W7Y]5F5I\,Y,4>]:&%2N%:^.=MC -M"HI>D@,6_!*]XS[4%I/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>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?!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-U=6) +M)^,P71E7KER&A"NWQV':0J"ZRDP9R#4R:I<[VL#$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]`LWI?,E=:"FG.6XA57X4/0KMM!^X((BR -MG\#6_3!Z(PJF^DB*"S%/+T92GV%]FGA%N0J4H!%*MUDU*'(33 -MT^\P?B:QNM^.GUD'=I_LCC6(#5>-9+J8S6BU^?EF,R:7NQVNOA;'Y:N!QH*U -M,]QV@MME7HPZGK<*.[.#'!`!<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^EN8;=\>[7+K\UVYJ[=I(%)T;4* +MS=D>,U#TD@+0\$MTQ6/8>7#=6U5O0M*A`*I.P\D7EUA)E]A\XJLEJMZE:`L'5\?`MN@HG6 +MV5[LAIGSU<2.I\J_HZ=!.N0$% +M0>1^`FOWP^BU*.CJTU(4=X&<"R.G8E604?Q4%7/XYL/: +MR_LK=1O&ST16]\_Q,_/`[DAU4$4O>->(IHM9M%:+_Q>;,:G<;7#EJ3@JB%^CS.)DV5#$M-3$R+6%P;2YV:&0N;W5T`*U6R6[;,!"]^RL& -MZ"U`!7)$CMIC@R:W`D&#HL=$D:E`R&;$!IJ#/[XNEG\*^>GLUU:[YR/RS7[5@4O2MAN9L -MCSDH^Y$"L.2/T)K'L`\PV:>KQXOFY3'`H8=##Z0+MLH1Z&'R'1('=HSTN\$G -M!WG?L495,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\;)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[#+]O$APF&`PP"D2[8J$.C'Y#W*_GKIV3'2 +M]Q9_.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,%`R'\,E0N6_U*.AG0H# +M*X+0<0'=]H?J=5#0YT=2+&@^[XQ9?A7SLZFIL#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 9949cd1d1c15..04627e2b7de4 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?TGOM0M9CH97UW6Q -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-:>.0 -M!Y![$)F5U1:P6U_H]:U\&>BX.Z,/?'=SQJ7N?&GA\(Z[X.)VLVL[KT[XZHK` -MB[$?5L:#E62@#:9;?3@]4;Y%[-T`T6U6PO0_;K2J40F6` -MP102L`RL$,O99'LV"[51&.@@R;B`!TG&!3Q(,B[@09)Q`0^2C`MXD&1#$M-3$R+6)S9"YV:&0N;W5T`*V736_#(`R&[_T5 +MGG;KI`@<`MEU4N\[K>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!C?MA +M],XH\/5I*69B/CT9D_H*UD>+010C]71'_9"$=P]#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 7bbe238939ff..d8b38b080122 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+65BSF&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&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\+O3UVLKHN].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.:<#SWLI7>X_LZ\GK]P7V->3*_#$M-3$R+65B +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=@`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^>SBQQCF*^/"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&?3WY3*?: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 9e6e5ae96966..81f18cb6736b 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>WEXS-H5:^UF*?-M!#`!>;[X1^&UNYETG'#"2/6]'244#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-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&#$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$K:K7&Q2;Z!6QO0\01.;4D->\E_Q+;':19+ +M%5.I0D-AMY`:FC*)^Q;AJ.MRB].5@;S&+5QSJ-U>WACY']>N[U:[G/B+61GDAYKQ5;&8%*_<-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 831f819746a0..6aa2b8a05bd3 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+6UBS^O/;=^_FC,*_Q-,,X\ZU"^["1'E?XS9*Y5O1H]!.F`L5!";M`$[N -MA]%;4.#K(\YV8IY.1E)?H_4)M`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+6UB2Q!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=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&FG+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 73e06370351b..fd654d67bab3 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-`L7I/.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#P@KO@X[:S:VAQ-H3+`:`J5J#$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!6MR8N?/,PC* +MX1I$Z54%#SC,+XSZ=K$,#-Q=T0>QNQ7C3#A>>CC\QET(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 a1c781c1c93c..d9a0c6e6aa5f 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'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,^&E\R5UH*:$6Y"I2@$4JW634H/=[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)1GXC*<^ -: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[MCW=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='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>[KR9>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]$.IC7,)3'^,2GOH8E_34I^O!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@>@<-F$E"`0I#G(!.#.$)>T9N83P*L7K2]NOG[\<743 -MZZ=%7GZ'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 +M3]]\\Y`8H,R@V`6?0#[V17C-E%*^=@TT#1)%\4@=V[G;^GS@IC9;ZG(>&NM/J$T7OI +M+41G!]I)-K!*:$Z)RJ*S4W!JR>HC<"3-D&'T3"I +M\K;?52][/>"',ZFBDF`,U\2\N^A3!+Q[!ZKW20[F3FV +M^LC8;I(Z8:/80N"G<^>>MN%0)#R=D!($@C0'F0#<&N*2ULS["/#J1>L?-S]/ +M_US=I/IID9PN<.\<_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)DEP.^ -M#M7IL;K>JG6PJD!78H:6ZJ)H+7&&K&@^/Q:V21.?[O%>O`&)\]0E:F`E9$X% -M53@[A;-+5M?@;E4XQ$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[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!`.GA(5+S0%R-9_Q/T(=^W^`:>6U''- +MM%,#L\Z6F8NYJ09V<9ZA:*&0(*JHJB/@=WZAUW)!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 e6addcc9e9d9..9c75099584f2 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:"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:'"[RKX'<,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>&=_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/ +M=J$/-U)%3_KR:*S:=A==JN`46*M`=?8- +M/;^JX)K1K`YO.JL3)8JJ%G1]GR%O("R[&=@Q#X!1?F/7=QC(P<'=' +M'\3N&L:5X?S'.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 f47328c7e60f..0e9500f82aa5 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.HT[3\`F`&V@!I0T7V1`^Z@*`',I!O27H7["5WS\ZB;A\-CXC[= -M10\FTKF5;T[V,H/3>RR-;O)JO_3MI"ULR>R@=V=O;Z=.YL;*_,\#80&(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`+C3ABZE6]>F&12+W0TAUWM21YXV_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&VM2#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,)FJPJ!&EF[U%L5$>D -MIQ.^3M55.^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?>/^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&!%`@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\SH#C#MU +M1'H\X^^ENBI5-UNY]W0=5%WP1!6J*XI3B./6RCY/IP`C!_^,9W03382X2)U@ +M"ZM`YII3V;S8-9S6RX,E-%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:!-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?,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?4T+QP_-KI#[%6I=6*&>%-H5V2[H4H'&CRI\ -M?OJV,H.U*982A\-;N"`X7N]3W"G"<3?A9DI4;-#5P'O_$KK -M0K_6L>FL+%PL1B_LXCQ#W4/-@6G?ARGPFE^8]1US&9BXNZ,/\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[/`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]#^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 995a75abbac5..4b1226c22247 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(V36TF:*PV)0JKP^ -M/[JG9S_3AQNI8L_Z\L5*KA(E7=&SZ9V)@U2 -M_#"NH.BH8MM=>XD>3D&C0:I5N;<9V>"O6N!0[5CMX3;<=>RNL9P@7%0*,`@% -MG7W#AQYGA&N%-Z-9N.N'_%=#^;W:W69R5U\6C^>* -M*OL&+JK+MW-"!<[%?4P:JZ[HQK6C`ZM=IU]M,:SHNF2M._%=9K^RI5;N6Y/G+YEZ7<$FJ!0S&4"RBJT -M`2BFT%(3*:JP[&H4W>4J*!3JFQDGV#;]<-S[Y[1S +ML$R$5K$YVZ,$11\I``U_1+?R"%7)0YUR]#)U59$7KN>50YWU\AA8- +MHHG1V4GL`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/#T'KFY`R=AJT]GK)9Q-FBIU]UE<:Z"F +M/,F@VZC*S::(&]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 da8f61af68f6..5aa8ba1f995c 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;<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@(.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(@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^DM +M1&<'VDDVL$IH3HG*HK-3<&K)ZB-P)RL?"Y>@2""2^Z"1=D/X292Y4OJJ;Z=\`]& +M!";#`EKW^^I%*$CY*]`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,!L#$6LX5P,N5H,YD>CK'!C7:#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_'?IL>9Y;4<)!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!A!I6$KB:`WHW7,%BJWCL4][O'9 +M(D^].CE6UULY!W<[D+MHA@SJ3K:]B9U59$7S^2UA8VQ\PIM\)`.]LX/8E6)@ +M%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<_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 5865a83838f7..bf1b6b684a1b 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:&#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!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\?BX2^>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&%U3O&ZIK$P:B7.^.+.Y%!@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 438b398df848..b496241a9260 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 -MG4OYXB0OOV4U2PT_;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("NY_X]PA8U^EIL1021>D1=\.&XZ[(NR7J*S7I[&RRA -M$5^(6J\:K!ZXJR7)"Q^NYK5>UK>/)C],_5[/\87N*O'O`5#8;8AM -M7Q.VD+(QE!:0C:&T^<9:!KA-+)@,\XR\!P(_34 -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 +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*'KNY9MI:(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 16d286a648bd..27e7455f2046 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?O3-G]/GX7_]3L'*UEL -ME9J3/5;`[4MJ0$TOD<_4ASY@BKO'E_WI]TO`H<>A!XF:K"H$:6;O46Q41Z2G -M$[Y.U55S=1C*UX[YC%X&),("#^^GJ -M75`0ZY,EVUCS]CD@^D]1MF\;^F*:32'WP&P*+;#-K%#G_7Y(KS#3 -K08%P&0\*A,MX4"!%`B7\:!`N*P'!6F/@(SM_@$'<*)G70X````` +M'XL(""DUQ%4``VEM9RTV,W@R-34M-3$R+6UB +M+V3&W`]`5B`[D"U(0=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(:`_^9I\SQ-=UU0"%`ZP3X:]37[,JX7I]2 +MF>.KAH2Q_=BVFSK(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!^]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*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[U/<*<)Q-^%F2E1LT-7`>_\2MR/'P -MAKN0XEJ_\X:120IO1.\Q5]<53D:[G!D?G+D$26>NPV'9AQ10*#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&\A +M56Q.]EB",!^I`#5]1#U2&P:/*7[H(\1%ZB1; +M6`4RUX+*9F?7<&K/ZAK3OGK;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'#_>^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%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 a38fd79a5827..03552762de0b 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'+_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$:X4WHUFXZX?\5T/YO=K=9G)77Q:/YXHJ -M^P8NJLNWJ5YFO[*E5NY;D^QMI97VL->2A%2CJ@^U/.27\/^-`CCZ,Z.5476O%80M>![((5NYY5#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-&=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_-C$MX;V9FQF7\-[, +2N*3W9@+2^=W]`WD,N"QL#0`` ` end diff --git a/usr.bin/mkimg/vhd.c b/usr.bin/mkimg/vhd.c index 054f82facd81..c4c1d1d45b8b 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 8963c8343a10..f33abcfd79e2 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 826f85b40e9b..e7fa3515f66d 100644 --- a/usr.bin/patch/inp.c +++ b/usr.bin/patch/inp.c @@ -31,8 +31,10 @@ #include #include #include +#include #include +#include #include #include #include @@ -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 d31300ea843a..79d8faea6285 100644 --- a/usr.bin/patch/pathnames.h +++ b/usr.bin/patch/pathnames.h @@ -9,4 +9,4 @@ #include -#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 e731ca1f9e8f..5fadf6292f67 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 a57361188c57..a2fa826333c7 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 efd27e91fff0..7ecb38b2ce22 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 3c310a9b84fc..000000000000 --- 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 - -__FBSDID("$FreeBSD$"); - -#define BUFSIZ 1024 -#define MAXHOP 32 /* max number of tc= indirections */ - -#include -#include -#include -#include - -/* - * 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 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 37b09e9e95d6..1317a4b0cb60 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 934d6ed4dd0d..607b966af451 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 b95c7d47bb60..c69a23a8b441 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 __FBSDID("$FreeBSD$"); -#include +#include #include - +#include +#include +#include #include #include #include @@ -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 3484bc9c1f4c..aad07cc21db9 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 + * Copyright (c) 1992, 1993, 1996 Theo de Raadt * 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 #include -#include -#include -#include -#include - #include #include #include @@ -47,7 +41,12 @@ __FBSDID("$FreeBSD$"); #include #include -struct ypalias { +#include +#include +#include +#include + +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 + * Copyright (c) 1992, 1993, 1996 Theo de Raadt * 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 #include -#include -#include -#include -#include - #include #include #include @@ -47,7 +42,12 @@ __FBSDID("$FreeBSD$"); #include #include -struct ypalias { +#include +#include +#include +#include + +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 #include #include +#include #include #include #include @@ -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 79b240f39704..8ace15add1f8 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 c265399730c7..f26c9de540e9 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 e84d0f34a6bc..334f789bb75e 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 #include #include #include -#include #include -#include #include -#include -#include -#include -#include #include "pw.h" #include "pwupd.h" diff --git a/usr.sbin/pw/grupd.c b/usr.sbin/pw/grupd.c index d52a345b48fb..9cbe0cb0b345 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 #include #include -#include #include #include -#include -#include #include "pwupd.h" diff --git a/usr.sbin/pw/psdate.c b/usr.sbin/pw/psdate.c index 8e3a951ef85b..bd2aa152b437 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 +#include +#include #include #include -#include #include -#include #include "psdate.h" diff --git a/usr.sbin/pw/pw.8 b/usr.sbin/pw/pw.8 index c29a8a9f40d1..3a9c0b0b87b9 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 5ad2511aeb10..1f42101a9add 100644 --- a/usr.sbin/pw/pw.c +++ b/usr.sbin/pw/pw.c @@ -32,14 +32,12 @@ static const char rcsid[] = #include #include #include -#include -#include -#include +#include +#include +#include + #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, }; +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, + } +}; + struct pwconf conf; -static struct cargs arglist; - -static int getindex(const char *words[], const char *word); -static void cmdhelp(int mode, int which); - +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 [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 ed3b7158e907..b389f1248dd1 100644 --- a/usr.sbin/pw/pw.h +++ b/usr.sbin/pw/pw.h @@ -26,22 +26,13 @@ * $FreeBSD$ */ +#include + #define _WITH_GETLINE +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 33bb6b3105e7..e9606b4e6a2f 100644 --- a/usr.sbin/pw/pw_conf.c +++ b/usr.sbin/pw/pw_conf.c @@ -31,10 +31,11 @@ static const char rcsid[] = #include #include -#include -#include -#include + #include +#include +#include +#include #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 b0db3cffbc45..711ef68b0cca 100644 --- a/usr.sbin/pw/pw_group.c +++ b/usr.sbin/pw/pw_group.c @@ -31,46 +31,50 @@ static const char rcsid[] = #include #include -#include -#include -#include #include #include +#include +#include +#include +#include +#include #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; - - grp = (name != NULL) ? GETGRNAM(name) : GETGRGID(id); - if (grp == NULL) { - if (name == NULL) - errx(EX_DATAERR, "unknown gid `%ld'", 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"); + struct group *grp; if (id < 0 && name == NULL) - errx(EX_DATAERR, "group name or id required"); - + errx(EX_DATAERR, "groupname 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; + if (grp == NULL) { + if (!fatal) + return (NULL); + if (name == NULL) + errx(EX_DATAERR, "unknown gid `%ju'", id); + errx(EX_DATAERR, "unknown group `%s'", name); } - - /* - * 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); - - /* - * 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(); - - /* - * 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); - } - - /* - * 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); + errx(EX_DATAERR, "gid `%ju' has already been allocated", + (uintmax_t)grp->gr_gid); + return (gid); } - return gid; + + /* + * 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); + + /* + * 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(); + + /* + * 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); + } + + /* + * 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); } - 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; + } + } + + 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 b7744234c336..29038d903747 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 +#include +#include #include "pw.h" diff --git a/usr.sbin/pw/pw_nis.c b/usr.sbin/pw/pw_nis.c index c786cc7ba4dc..6cc361b7a25c 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 + #include #include #include @@ -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 d6dad3f3c52b..d9bce87f619f 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 +#include +#include +#include + #include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include #include +#include +#include +#include +#include +#include +#include + #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,548 +245,17 @@ 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) -{ - 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); - - /* - * Ok, user is created or changed - now edit group file - */ - - 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 == 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 - */ - 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); - } - } - - /* - * 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 && getarg(args, 'm') != NULL && pwd->pw_dir && - *pwd->pw_dir == '/' && pwd->pw_dir[1]) - create_and_populate_homedir(pwd); - - /* - * Finally, send mail to the new user as well, if we are asked to - */ - 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) +static uid_t +pw_uidpolicy(struct userconf * cnf, intmax_t id) { struct passwd *pwd; + struct bitmap bm; uid_t uid = (uid_t) - 1; /* @@ -808,78 +265,67 @@ pw_uidpolicy(struct userconf * cnf, long id) 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); + errx(EX_DATAERR, "uid `%ju' has already been allocated", + (uintmax_t)pwd->pw_uid); + return (uid); } - return uid; + /* + * 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); } - -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) +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, '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) -{ - 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,203 +473,80 @@ 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; + 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 (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); + 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'; + if ((p = strchr(uname, '&')) != NULL) { + int l = strlen(pwd->pw_name); + int m = strlen(p); - 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 */ + memmove(p + l, p + 1, m); + memmove(p, pwd->pw_name, l); + *p = (char) toupper((unsigned char)*p); } - - 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); + 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 #%-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(); - - 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); - - /* 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 "); - } - + printf("%s", j ? "\n" : ""); 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_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; - } - } - } - ENDGRENT(); - printf("%s", j ? "\n" : ""); - } - return EXIT_SUCCESS; -} - char * pw_checkname(char *name, int gecos) { @@ -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 000000000000..1a4f8127de14 --- /dev/null +++ b/usr.sbin/pw/pw_utils.c @@ -0,0 +1,99 @@ +/*- + * Copyright (C) 2015 Baptiste Daroussin + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 f9e1959f44a7..ee23952e090f 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 + +#include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include "pwupd.h" diff --git a/usr.sbin/pw/pwupd.h b/usr.sbin/pw/pwupd.h index 054c5a55293b..7fecffb7da4b 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 65a63e6e0cbe..172c7b02e1db 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 -#include -#include -#include #include -#include -#include + #include #include +#include +#include #include "pwupd.h" diff --git a/usr.sbin/pw/strtounum.c b/usr.sbin/pw/strtounum.c new file mode 100644 index 000000000000..be572764b60c --- /dev/null +++ b/usr.sbin/pw/strtounum.c @@ -0,0 +1,71 @@ +/*- + * Copyright (C) 2015 Baptiste Daroussin + * 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#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 193b8ab58530..a1605aadaf57 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 diff --git a/usr.sbin/pw/tests/pw_groupadd.sh b/usr.sbin/pw/tests/pw_groupadd.sh new file mode 100755 index 000000000000..5fa7bef0fdf1 --- /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 75b063a34b32..88cc0e08b8bf 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 880dab5ca7bb..2ac31c96ac2f 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 5ba87c258dea..f608029bef45 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 006bb2c17328..236fd27661eb 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 ff3e5249fd4c..fa55e9d025c7 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 f1f629a42b5b..290e40500de6 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 6c665158c4ad..5a712e5a41b0 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 c82f8c7bbbee..a4ba5049f20c 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 61944dc44bbe..6a3bf1c462a0 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 8d488f3bdb6a..a5b12902d0d1 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 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 958d3a62d18c..8c538ca8ca46 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