Merge ^/head r293850 through r294089.

This commit is contained in:
Dimitry Andric 2016-01-15 17:55:00 +00:00
commit 7f38eb34e2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang380-import/; revision=294096
155 changed files with 3839 additions and 1456 deletions

View File

@ -283,7 +283,6 @@ static int
equiv_su(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
{
mlist_t *ml1 = stdp->t_members, *ml2 = ttdp->t_members;
mlist_t *olm1 = NULL;
while (ml1 && ml2) {
if (ml1->ml_offset != ml2->ml_offset ||
@ -292,7 +291,6 @@ equiv_su(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
!equiv_node(ml1->ml_type, ml2->ml_type, ed))
return (0);
olm1 = ml1;
ml1 = ml1->ml_next;
ml2 = ml2->ml_next;
}

View File

@ -1610,7 +1610,7 @@ initialize_options(Options * options)
options->tun_remote = -1;
options->local_command = NULL;
options->permit_local_command = -1;
options->use_roaming = -1;
options->use_roaming = 0;
options->visual_host_key = -1;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
@ -1788,8 +1788,7 @@ fill_default_options(Options * options)
options->tun_remote = SSH_TUNID_ANY;
if (options->permit_local_command == -1)
options->permit_local_command = 0;
if (options->use_roaming == -1)
options->use_roaming = 1;
options->use_roaming = 0;
if (options->visual_host_key == -1)
options->visual_host_key = 0;
if (options->ip_qos_interactive == -1)

View File

@ -82,10 +82,6 @@ BIN1+= apmd.conf
BIN1+= auto_master
.endif
.if ${MK_BSNMP} != "no"
BIN1+= snmpd.config
.endif
.if ${MK_FREEBSD_UPDATE} != "no"
BIN1+= freebsd-update.conf
.endif
@ -219,6 +215,11 @@ distribution:
${BIN2} ${DESTDIR}/etc; \
${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 600 \
master.passwd nsmb.conf opieaccess ${DESTDIR}/etc;
.if ${MK_BSNMP} != "no"
cd ${.CURDIR}; \
${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 600 \
snmpd.config ${DESTDIR}/etc;
.endif
.if ${MK_AT} == "no"
sed -i "" -e 's;.*/usr/libexec/atrun;#&;' ${DESTDIR}/etc/crontab
.endif

View File

@ -36,15 +36,15 @@ mountcritlocal_start()
done
mount_excludes=${mount_excludes%,}
# Originally, root mount hold had to be released before mounting the root
# filesystem. This delayed the boot, so it was changed to only wait if
# the root device isn't readily available. This can result in this script
# executing before all the devices - such as graid(8) - are available.
# Thus, should the mount fail, we will wait for the root mount hold release
# and retry.
# Originally, root mount hold had to be released before mounting
# the root filesystem. This delayed the boot, so it was changed
# to only wait if the root device isn't readily available. This
# can result in this script executing before all the devices - such
# as graid(8) - are available. Thus, should the mount fail,
# we will wait for the root mount hold release and retry.
mount -a -t ${mount_excludes}
err=$?
if [ $? -ne 0 ]; then
if [ ${err} -ne 0 ]; then
echo
echo 'Mounting /etc/fstab filesystems failed,' \
'will retry after root mount hold release'

View File

@ -6,4 +6,8 @@ LLVM_SRCS= ${.CURDIR}/../../../contrib/llvm
INTERNALLIB=
.if ${MACHINE_CPUARCH} == "arm"
STATIC_CXXFLAGS+= -mlong-calls
.endif
.include <bsd.lib.mk>

View File

@ -6,6 +6,9 @@ _LIBCXXRTDIR= ${.CURDIR}/../../contrib/libcxxrt
HDRDIR= ${.CURDIR}/../../contrib/libc++/include
SRCDIR= ${.CURDIR}/../../contrib/libc++/src
CXXINCLUDEDIR= ${INCLUDEDIR}/c++/v${SHLIB_MAJOR}
.if ${MACHINE_CPUARCH} == "arm"
STATIC_CXXFLAGS+= -mlong-calls
.endif
.PATH: ${SRCDIR}

View File

@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$");
base = leaf; \
path_init(&path); \
} \
result = &(*leaf)->key; \
path_taking_right(&path); \
leaf = &(*leaf)->rlink; \
} while (0)

View File

@ -54,7 +54,7 @@ wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (*d != '\0' && n-- != 0)
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;

View File

@ -48,7 +48,7 @@ wcsncat(wchar_t * __restrict s1, const wchar_t * __restrict s2, size_t n)
p++;
q = p;
r = s2;
while (*r && n) {
while (n && *r) {
*q++ = *r++;
n--;
}

View File

@ -28,7 +28,7 @@
.\" @(#)stat.2 8.4 (Berkeley) 5/1/95
.\" $FreeBSD$
.\"
.Dd June 2, 2012
.Dd January 14, 2016
.Dt STAT 2
.Os
.Sh NAME
@ -40,12 +40,11 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In sys/types.h
.In sys/stat.h
.Ft int
.Fn stat "const char *path" "struct stat *sb"
.Fn stat "const char * restrict path" "struct stat * restrict sb"
.Ft int
.Fn lstat "const char *path" "struct stat *sb"
.Fn lstat "const char * restrict path" "struct stat * restrict sb"
.Ft int
.Fn fstat "int fd" "struct stat *sb"
.Ft int

View File

@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <dialog.h>
#include <err.h>
#include <limits.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -482,6 +483,11 @@ dpv(struct dpv_config *config, struct dpv_file_node *file_list)
/* Reads: label_size pbar_size pprompt aprompt dpv_nfiles */
/* Inits: dheight and dwidth */
/* Default localeconv(3) settings for dialog(3) status */
setlocale(LC_NUMERIC,
getenv("LC_ALL") == NULL && getenv("LC_NUMERIC") == NULL ?
LC_NUMERIC_DEFAULT : "");
if (!debug) {
/* Internally create the initial `--gauge' prompt text */
dprompt_recreate(file_list, (struct dpv_file_node *)NULL, 0);

View File

@ -38,6 +38,9 @@
#define FALSE 0
#endif
/* localeconv(3) */
#define LC_NUMERIC_DEFAULT "en_US.ISO8859-1"
/* Data to process */
extern long long dpv_overall_read;

View File

@ -70,7 +70,7 @@ _Static_assert(NBPDR == I386_NBPDR, "NBPDR mismatch");
_Static_assert(PG_V == I386_PG_V, "PG_V mismatch");
_Static_assert(PG_PS == I386_PG_PS, "PG_PS mismatch");
_Static_assert(PG_FRAME == I386_PG_FRAME, "PG_FRAME mismatch");
_Static_assert((u_int)PG_FRAME == I386_PG_FRAME, "PG_FRAME mismatch");
_Static_assert(PG_PS_FRAME == I386_PG_PS_FRAME, "PG_PS_FRAME mismatch");
#endif

View File

@ -1,4 +1,5 @@
/* mdXhl.c * ----------------------------------------------------------------------------
/* mdXhl.c
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
@ -52,43 +53,44 @@ MDXFileChunk(const char *filename, char *buf, off_t ofs, off_t len)
unsigned char buffer[16*1024];
MDX_CTX ctx;
struct stat stbuf;
int f, i, e;
off_t n;
int fd, readrv, e;
off_t remain;
if (len < 0) {
errno = EINVAL;
return NULL;
}
MDXInit(&ctx);
f = open(filename, O_RDONLY);
if (f < 0)
return 0;
if (fstat(f, &stbuf) < 0) {
i = -1;
goto error;
fd = open(filename, O_RDONLY);
if (fd < 0)
return NULL;
if (ofs != 0) {
errno = 0;
if (lseek(fd, ofs, SEEK_SET) != ofs ||
(ofs == -1 && errno != 0)) {
readrv = -1;
goto error;
}
}
if (ofs > stbuf.st_size)
ofs = stbuf.st_size;
if ((len == 0) || (len > stbuf.st_size - ofs))
len = stbuf.st_size - ofs;
if (lseek(f, ofs, SEEK_SET) < 0) {
i = -1;
goto error;
}
n = len;
i = 0;
while (n > 0) {
if (n > sizeof(buffer))
i = read(f, buffer, sizeof(buffer));
remain = len;
readrv = 0;
while (len == 0 || remain > 0) {
if (len == 0 || remain > sizeof(buffer))
readrv = read(fd, buffer, sizeof(buffer));
else
i = read(f, buffer, n);
if (i <= 0)
readrv = read(fd, buffer, remain);
if (readrv <= 0)
break;
MDXUpdate(&ctx, buffer, i);
n -= i;
MDXUpdate(&ctx, buffer, readrv);
remain -= readrv;
}
error:
e = errno;
close(f);
close(fd);
errno = e;
if (i < 0)
return 0;
if (readrv < 0)
return NULL;
return (MDXEnd(&ctx, buf));
}

View File

@ -42,7 +42,7 @@ int _umtx_op_err(void *obj, int op, u_long val, void *uaddr, void *uaddr2)
void
_thr_umutex_init(struct umutex *mtx)
{
static struct umutex default_mtx = DEFAULT_UMUTEX;
static const struct umutex default_mtx = DEFAULT_UMUTEX;
*mtx = default_mtx;
}
@ -50,7 +50,8 @@ _thr_umutex_init(struct umutex *mtx)
void
_thr_urwlock_init(struct urwlock *rwl)
{
static struct urwlock default_rwl = DEFAULT_URWLOCK;
static const struct urwlock default_rwl = DEFAULT_URWLOCK;
*rwl = default_rwl;
}

View File

@ -2,8 +2,8 @@
# $OpenBSD: pf.conf,v 1.34 2007/02/24 19:30:59 millert Exp $
#
# See pf.conf(5) and /usr/share/examples/pf for syntax and examples.
# Remember to set net.inet.ip.forwarding=1 and/or net.inet6.ip6.forwarding=1
# in /etc/sysctl.conf if packets are to be forwarded between interfaces.
# Remember to set gateway_enable="YES" and/or ipv6_gateway_enable="YES"
# in /etc/rc.conf if packets are to be forwarded between interfaces.
#ext_if="ext0"
#int_if="int0"

View File

@ -60,7 +60,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd November 5, 2015
.Dd January 14, 2016
.Dt DDB 4
.Os
.Sh NAME
@ -1435,6 +1435,47 @@ The NMI allows one to break into the debugger on a wedged machine to
diagnose problems.
Other bus' bridge chipsets may be able to generate NMI using bus specific
methods.
There are many PCI and PCIe add-in cards which can generate NMI for
debugging.
Modern systems typically use IPMI to generate signals to enter the
debugger.
The
.Dv devel/ipmitool
port can be used to send the
.Cd chassis power diag
command which delivers an NMI to the processor.
.Pp
For serial consoles, you can break to the debugger by sending a BREAK
condition on the serial line if
.Cd options BREAK_TO_DEBUGGER
is specified in the kernel.
Most terminal emulation programs can send a break sequence with a
special key sequence or via a menu item.
However, in some setups, sending the break can be difficult to arrange
or happens spuriously, so if the kernel contains
.Cd options ALT_BREAK_TO_DEBUGGER
then the sequence of CR TILDE CTRL-B enters the debugger;
CR TILDE CTRL-P causes a panic instead of entering the
debugger; and
CR TILDE CTRL-R causes an immediate reboot.
In all the above sequences, CR is a Carriage Return and is usually
sent by hitting the Enter or Return key.
TILDE is the ASCII tilde character (~).
CTRL-x is Control x created by hitting the control key and then x
and then releasing both.
.Pp
The break to debugger behavior may also be enabled by setting the
.Xr sysctl 8
.Dv debug.kdb.break_to_debugger
to 1.
The alt break to debugger behavior may also be enabled by setting the
.Xr sysctl 8
.Dv debug.kdb.alt_break_to_debugger
to 1.
The debugger may be entered by setting the
.Xr sysctl 8
.Dv debug.kdb.enter
to 1.
.Sh FILES
Header files mentioned in this manual page can be found below
.Pa /usr/include

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd January 7, 2016
.Dd January 14, 2016
.Dt IOAT 4
.Os
.Sh NAME
@ -134,7 +134,7 @@ Null operations do nothing, but may be used to test the interrupt and callback
mechanism.
.Pp
All operations can optionally trigger an interrupt at completion with the
.Ar DMA_EN_INT
.Ar DMA_INT_EN
flag.
For example, a user might submit multiple operations to the same channel and
only enable an interrupt and callback for the last operation.
@ -160,6 +160,17 @@ flag.
.Ar DMA_NO_WAIT
may return NULL.)
.Pp
Operations that depend on the result of prior operations should use
.Ar DMA_FENCE .
For example, such a scenario can happen when two related DMA operations are
queued.
First, a DMA copy to one location (A), followed directly by a DMA copy
from A to B.
In this scenario, some classes of I/OAT hardware may prefetch A for the second
operation before it is written by the first operation.
To avoid reading a stale value in sequences of dependent operations, use
.Ar DMA_FENCE .
.Pp
All operations, as well as
.Fn ioat_get_dmaengine ,
can return NULL in special circumstances.

View File

@ -121,8 +121,10 @@ If a packet is dropped, the
counter is incremented and the local sender receives ENOBUFS.
The value must be greater than or equal to 0.
.It Va hw.sfxge.tso_fw_assisted
Enable/disable usage of FW-assisted TSO if supported by NIC firmware.
Enabled by default.
Bitmask to enable/disable usage of FW-assisted TSO version if supported
by NIC firmware.
FATSOv1 (bit 0) and FATSOv2 (bit 1) are supported.
All enabled by default.
.It Va hw.sfxge.N.max_rss_channels
The maximum number of allocated RSS channels for the Nth adapter.
If set to 0 or unset, the number of channels is determined by the number

View File

@ -164,10 +164,11 @@ SSP_CFLAGS?= -fstack-protector
CFLAGS+= ${SSP_CFLAGS}
.endif # SSP && !ARM && !MIPS
# Allow user-specified additional warning flags, plus compiler specific flag overrides.
# Unless we've overriden this...
# Allow user-specified additional warning flags, plus compiler and file
# specific flag overrides, unless we've overriden this...
.if ${MK_WARNS} != "no"
CFLAGS+= ${CWARNFLAGS} ${CWARNFLAGS.${COMPILER_TYPE}}
CFLAGS+= ${CWARNFLAGS.${.IMPSRC:T}}
.endif
CFLAGS+= ${CFLAGS.${COMPILER_TYPE}}

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: head/sys/amd64/linux/syscalls.master 289769 2015-10-22 21:28:20Z jhb
* created from FreeBSD: head/sys/amd64/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#ifndef _LINUX_SYSPROTO_H_
@ -966,7 +966,7 @@ struct linux_set_robust_list_args {
};
struct linux_get_robust_list_args {
char pid_l_[PADL_(l_int)]; l_int pid; char pid_r_[PADR_(l_int)];
char head_l_[PADL_(struct linux_robust_list_head *)]; struct linux_robust_list_head * head; char head_r_[PADR_(struct linux_robust_list_head *)];
char head_l_[PADL_(struct linux_robust_list_head **)]; struct linux_robust_list_head ** head; char head_r_[PADR_(struct linux_robust_list_head **)];
char len_l_[PADL_(l_size_t *)]; l_size_t * len; char len_r_[PADR_(l_size_t *)];
};
struct linux_splice_args {

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: head/sys/amd64/linux/syscalls.master 289769 2015-10-22 21:28:20Z jhb
* created from FreeBSD: head/sys/amd64/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#define LINUX_SYS_read 0

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: head/sys/amd64/linux/syscalls.master 289769 2015-10-22 21:28:20Z jhb
* created from FreeBSD: head/sys/amd64/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
const char *linux_syscallnames[] = {

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: head/sys/amd64/linux/syscalls.master 289769 2015-10-22 21:28:20Z jhb
* created from FreeBSD: head/sys/amd64/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#include <sys/param.h>

View File

@ -2020,7 +2020,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 274: {
struct linux_get_robust_list_args *p = params;
iarg[0] = p->pid; /* l_int */
uarg[1] = (intptr_t) p->head; /* struct linux_robust_list_head * */
uarg[1] = (intptr_t) p->head; /* struct linux_robust_list_head ** */
uarg[2] = (intptr_t) p->len; /* l_size_t * */
*n_args = 3;
break;
@ -5347,7 +5347,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "l_int";
break;
case 1:
p = "struct linux_robust_list_head *";
p = "struct linux_robust_list_head **";
break;
case 2:
p = "l_size_t *";

View File

@ -461,8 +461,8 @@
272 AUE_NULL STD { int linux_unshare(void); }
273 AUE_NULL STD { int linux_set_robust_list(struct linux_robust_list_head *head, \
l_size_t len); }
274 AUE_NULL STD { int linux_get_robust_list(l_int pid, struct linux_robust_list_head *head, \
l_size_t *len); }
274 AUE_NULL STD { int linux_get_robust_list(l_int pid, \
struct linux_robust_list_head **head, l_size_t *len); }
275 AUE_NULL STD { int linux_splice(void); }
276 AUE_NULL STD { int linux_tee(void); }
277 AUE_NULL STD { int linux_sync_file_range(void); }

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: head/sys/amd64/linux32/syscalls.master 289769 2015-10-22 21:28:20Z jhb
* created from FreeBSD: head/sys/amd64/linux32/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#ifndef _LINUX32_SYSPROTO_H_
@ -1023,7 +1023,7 @@ struct linux_set_robust_list_args {
};
struct linux_get_robust_list_args {
char pid_l_[PADL_(l_int)]; l_int pid; char pid_r_[PADR_(l_int)];
char head_l_[PADL_(struct linux_robust_list_head *)]; struct linux_robust_list_head * head; char head_r_[PADR_(struct linux_robust_list_head *)];
char head_l_[PADL_(struct linux_robust_list_head **)]; struct linux_robust_list_head ** head; char head_r_[PADR_(struct linux_robust_list_head **)];
char len_l_[PADL_(l_size_t *)]; l_size_t * len; char len_r_[PADR_(l_size_t *)];
};
struct linux_splice_args {

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: head/sys/amd64/linux32/syscalls.master 289769 2015-10-22 21:28:20Z jhb
* created from FreeBSD: head/sys/amd64/linux32/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#define LINUX32_SYS_linux_exit 1

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: head/sys/amd64/linux32/syscalls.master 289769 2015-10-22 21:28:20Z jhb
* created from FreeBSD: head/sys/amd64/linux32/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
const char *linux32_syscallnames[] = {

View File

@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
* created from FreeBSD: head/sys/amd64/linux32/syscalls.master 289769 2015-10-22 21:28:20Z jhb
* created from FreeBSD: head/sys/amd64/linux32/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#include "opt_compat.h"

View File

@ -2122,7 +2122,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 312: {
struct linux_get_robust_list_args *p = params;
iarg[0] = p->pid; /* l_int */
uarg[1] = (intptr_t) p->head; /* struct linux_robust_list_head * */
uarg[1] = (intptr_t) p->head; /* struct linux_robust_list_head ** */
uarg[2] = (intptr_t) p->len; /* l_size_t * */
*n_args = 3;
break;
@ -5551,7 +5551,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "l_int";
break;
case 1:
p = "struct linux_robust_list_head *";
p = "struct linux_robust_list_head **";
break;
case 2:
p = "l_size_t *";

View File

@ -520,8 +520,8 @@
; linux 2.6.17:
311 AUE_NULL STD { int linux_set_robust_list(struct linux_robust_list_head *head, \
l_size_t len); }
312 AUE_NULL STD { int linux_get_robust_list(l_int pid, struct linux_robust_list_head *head, \
l_size_t *len); }
312 AUE_NULL STD { int linux_get_robust_list(l_int pid, \
struct linux_robust_list_head **head, l_size_t *len); }
313 AUE_NULL STD { int linux_splice(void); }
314 AUE_NULL STD { int linux_sync_file_range(void); }
315 AUE_NULL STD { int linux_tee(void); }

View File

@ -446,6 +446,9 @@ at91_mci_attach(device_t dev)
CTLFLAG_RW, &sc->allow_overclock, 0,
"Allow up to 30MHz clock for 25MHz request when next highest speed 15MHz or less.");
SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug",
CTLFLAG_RWTUN, &mci_debug, 0, "enable debug output");
/*
* Our real min freq is master_clock/512, but upper driver layers are
* going to set the min speed during card discovery, and the right speed
@ -783,15 +786,6 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd)
WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN);
} else {
len = min(BBSIZE, remaining);
/*
* If this is MCI1 revision 2xx controller, apply
* a work-around for the "Data Write Operation and
* number of bytes" erratum.
*/
if ((sc->sc_cap & CAP_MCI1_REV2XX) && len < 12) {
len = 12;
memset(sc->bbuf_vaddr[0], 0, 12);
}
at91_bswap_buf(sc, sc->bbuf_vaddr[0], data->data, len);
err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0],
sc->bbuf_vaddr[0], len, at91_mci_getaddr,
@ -800,8 +794,13 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd)
panic("IO write dmamap_load failed\n");
bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0],
BUS_DMASYNC_PREWRITE);
/*
* Erratum workaround: PDC transfer length on a write
* must not be smaller than 12 bytes (3 words); only
* blklen bytes (set above) are actually transferred.
*/
WR4(sc, PDC_TPR,paddr);
WR4(sc, PDC_TCR, len / 4);
WR4(sc, PDC_TCR, (len < 12) ? 3 : len / 4);
sc->bbuf_len[0] = len;
remaining -= len;
if (remaining == 0) {
@ -818,7 +817,7 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd)
bus_dmamap_sync(sc->dmatag, sc->bbuf_map[1],
BUS_DMASYNC_PREWRITE);
WR4(sc, PDC_TNPR, paddr);
WR4(sc, PDC_TNCR, len / 4);
WR4(sc, PDC_TNCR, (len < 12) ? 3 : len / 4);
sc->bbuf_len[1] = len;
remaining -= len;
}

View File

@ -136,11 +136,3 @@ device wlan_amrr # AMRR transmit rate control algorithm
# Flattened Device Tree
options FDT # Configure using FDT/DTB data
# NOTE: serial console will be disabled if syscons enabled
# Uncomment following lines for framebuffer/syscons support
#device sc
#device vt
#device kbdmux
#options SC_DFLT_FONT # compile font in
#makeoptions SC_DFLT_FONT=cp437

View File

@ -125,14 +125,6 @@ device u3g # USB modems
#device wlan_tkip # 802.11 TKIP support
#device wlan_amrr # AMRR transmit rate control algorithm
# NOTE: serial console will be disabled if syscons enabled
# Uncomment following lines for framebuffer/syscons support
# Wandboard has no video console support yet.
#device sc
#device kbdmux
#options SC_DFLT_FONT # compile font in
#makeoptions SC_DFLT_FONT=cp437
device vt
device kbdmux
device ukbd

View File

@ -237,7 +237,7 @@ void unload(void);
struct preloaded_file *file_alloc(void);
struct preloaded_file *file_findfile(const char *name, const char *type);
struct file_metadata *file_findmetadata(struct preloaded_file *fp, int type);
struct preloaded_file *file_loadraw(char *name, char *type, int insert);
struct preloaded_file *file_loadraw(const char *name, char *type, int insert);
void file_discard(struct preloaded_file *fp);
void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p);
int file_addmodule(struct preloaded_file *fp, char *modname, int version,

View File

@ -388,14 +388,14 @@ file_load_dependencies(struct preloaded_file *base_file)
}
/*
* We've been asked to load (name) as (type), so just suck it in,
* We've been asked to load (fname) as (type), so just suck it in,
* no arguments or anything.
*/
struct preloaded_file *
file_loadraw(char *name, char *type, int insert)
file_loadraw(const char *fname, char *type, int insert)
{
struct preloaded_file *fp;
char *cp;
char *name;
int fd, got;
vm_offset_t laddr;
@ -406,12 +406,11 @@ file_loadraw(char *name, char *type, int insert)
}
/* locate the file on the load path */
cp = file_search(name, NULL);
if (cp == NULL) {
sprintf(command_errbuf, "can't find '%s'", name);
name = file_search(fname, NULL);
if (name == NULL) {
sprintf(command_errbuf, "can't find '%s'", fname);
return(NULL);
}
name = cp;
if ((fd = open(name, O_RDONLY)) < 0) {
sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno));

View File

@ -187,8 +187,15 @@ fsread(ufs_ino_t inode, void *buf, size_t nbyte)
blkbuf = dmadat->blkbuf;
indbuf = dmadat->indbuf;
if (!dsk_meta) {
/*
* Force probe if inode is zero to ensure we have a valid fs, otherwise
* when probing multiple paritions, reads from subsequent parititions
* will incorrectly succeed.
*/
if (!dsk_meta || inode == 0) {
inomap = 0;
dsk_meta = 0;
for (n = 0; sblock_try[n] != -1; n++) {
if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
SBLOCKSIZE / DEV_BSIZE))

View File

@ -2,7 +2,8 @@
.include <src.opts.mk>
SUBDIR= libefi
# In-tree GCC does not support __attribute__((ms_abi)).
.if ${COMPILER_TYPE} != "gcc"
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm"
.if ${MK_FDT} != "no"
@ -13,7 +14,10 @@ SUBDIR+= fdt
.if ${MACHINE_CPUARCH} == "aarch64" || \
${MACHINE_CPUARCH} == "amd64" || \
${MACHINE_CPUARCH} == "arm"
SUBDIR+= loader boot1
SUBDIR+= libefi loader boot1
.endif
.endif # ${COMPILER_TYPE} != "gcc"
.include <bsd.subdir.mk>

View File

@ -2,10 +2,7 @@
MAN=
.include <bsd.own.mk>
# In-tree GCC does not support __attribute__((ms_abi)).
.if ${COMPILER_TYPE} != "gcc"
.include <src.opts.mk>
MK_SSP= no
@ -13,14 +10,35 @@ PROG= boot1.sym
INTERNALPROG=
WARNS?= 6
.if ${MK_ZFS} != "no"
# Disable warnings that are currently incompatible with the zfs boot code
CWARNFLAGS.zfs_module.c += -Wno-array-bounds
CWARNFLAGS.zfs_module.c += -Wno-cast-align
CWARNFLAGS.zfs_module.c += -Wno-cast-qual
CWARNFLAGS.zfs_module.c += -Wno-missing-prototypes
CWARNFLAGS.zfs_module.c += -Wno-sign-compare
CWARNFLAGS.zfs_module.c += -Wno-unused-parameter
CWARNFLAGS.zfs_module.c += -Wno-unused-function
.endif
# architecture-specific loader code
SRCS= boot1.c self_reloc.c start.S
SRCS= boot1.c self_reloc.c start.S ufs_module.c
.if ${MK_ZFS} != "no"
SRCS+= zfs_module.c
.endif
CFLAGS+= -I.
CFLAGS+= -I${.CURDIR}/../include
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
CFLAGS+= -DEFI_UFS_BOOT
.if ${MK_ZFS} != "no"
CFLAGS+= -I${.CURDIR}/../../zfs/
CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs/
CFLAGS+= -DEFI_ZFS_BOOT
.endif
# Always add MI sources and REGULAR efi loader bits
.PATH: ${.CURDIR}/../loader/arch/${MACHINE}
@ -96,8 +114,6 @@ boot1.efifat: boot1.efi
CLEANFILES= boot1.efi boot1.efifat
.endif # ${COMPILER_TYPE} != "gcc"
.include <bsd.prog.mk>
beforedepend ${OBJS}: machine

View File

@ -5,6 +5,8 @@
* All rights reserved.
* Copyright (c) 2014 Nathan Whitehorn
* All rights reserved.
* Copyright (c) 2015 Eric McCorkle
* All rights reserved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
@ -21,7 +23,6 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/dirent.h>
#include <machine/elf.h>
#include <machine/stdarg.h>
#include <stand.h>
@ -29,19 +30,32 @@ __FBSDID("$FreeBSD$");
#include <efi.h>
#include <eficonsctl.h>
#include "boot_module.h"
#define _PATH_LOADER "/boot/loader.efi"
#define _PATH_KERNEL "/boot/kernel/kernel"
#define BSIZEMAX 16384
static const boot_module_t *boot_modules[] =
{
#ifdef EFI_ZFS_BOOT
&zfs_module,
#endif
#ifdef EFI_UFS_BOOT
&ufs_module
#endif
};
#define NUM_BOOT_MODULES (sizeof(boot_modules) / sizeof(boot_module_t*))
/* The initial number of handles used to query EFI for partitions. */
#define NUM_HANDLES_INIT 24
void panic(const char *fmt, ...) __dead2;
void putchar(int c);
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
static int domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet);
static void load(const char *fname);
static void try_load(const boot_module_t* mod);
static EFI_STATUS probe_handle(EFI_HANDLE h);
static EFI_SYSTEM_TABLE *systab;
EFI_SYSTEM_TABLE *systab;
EFI_BOOT_SERVICES *bs;
static EFI_HANDLE *image;
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
@ -49,27 +63,92 @@ static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
static EFI_BLOCK_IO *bootdev;
static EFI_DEVICE_PATH *bootdevpath;
static EFI_HANDLE *bootdevhandle;
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
/*
* Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
* memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
* EFI methods.
*/
void *
Malloc(size_t len, const char *file __unused, int line __unused)
{
EFI_HANDLE handles[128];
EFI_BLOCK_IO *blkio;
UINTN i, nparts = sizeof(handles), cols, rows, max_dim, best_mode;
void *out;
if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
return (out);
return (NULL);
}
void
Free(void *buf, const char *file __unused, int line __unused)
{
(void)bs->FreePool(buf);
}
/*
* This function only returns if it fails to load the kernel. If it
* succeeds, it simply boots the kernel.
*/
void
try_load(const boot_module_t *mod)
{
size_t bufsize;
void *buf;
dev_info_t *dev;
EFI_HANDLE loaderhandle;
EFI_LOADED_IMAGE *loaded_image;
EFI_STATUS status;
status = mod->load(_PATH_LOADER, &dev, &buf, &bufsize);
if (status == EFI_NOT_FOUND)
return;
if (status != EFI_SUCCESS) {
printf("%s failed to load %s (%lu)\n", mod->name, _PATH_LOADER,
EFI_ERROR_CODE(status));
return;
}
if ((status = bs->LoadImage(TRUE, image, dev->devpath, buf, bufsize,
&loaderhandle)) != EFI_SUCCESS) {
printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
mod->name, bufsize, EFI_ERROR_CODE(status));
return;
}
if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID,
(VOID**)&loaded_image)) != EFI_SUCCESS) {
printf("Failed to query LoadedImage provided by %s (%lu)\n",
mod->name, EFI_ERROR_CODE(status));
return;
}
loaded_image->DeviceHandle = dev->devhandle;
if ((status = bs->StartImage(loaderhandle, NULL, NULL)) !=
EFI_SUCCESS) {
printf("Failed start image provided by %s (%lu)\n", mod->name,
EFI_ERROR_CODE(status));
return;
}
}
EFI_STATUS
efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
{
EFI_HANDLE *handles;
EFI_STATUS status;
EFI_DEVICE_PATH *devpath;
EFI_BOOT_SERVICES *BS;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
const char *path = _PATH_LOADER;
UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
/* Basic initialization*/
systab = Xsystab;
image = Ximage;
bs = Xsystab->BootServices;
BS = systab->BootServices;
status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
/* Set up the console, so printf works. */
status = bs->LocateProtocol(&ConsoleControlGUID, NULL,
(VOID **)&ConsoleControl);
if (status == EFI_SUCCESS)
(void)ConsoleControl->SetMode(ConsoleControl,
@ -94,200 +173,162 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
conout->EnableCursor(conout, TRUE);
conout->ClearScreen(conout);
printf("\n"
">> FreeBSD EFI boot block\n");
printf(" Loader path: %s\n", path);
status = systab->BootServices->LocateHandle(ByProtocol,
&BlockIoProtocolGUID, NULL, &nparts, handles);
nparts /= sizeof(handles[0]);
for (i = 0; i < nparts; i++) {
status = systab->BootServices->HandleProtocol(handles[i],
&DevicePathGUID, (void **)&devpath);
if (EFI_ERROR(status))
printf("\n>> FreeBSD EFI boot block\n");
printf(" Loader path: %s\n\n", _PATH_LOADER);
printf(" Initializing modules:");
for (i = 0; i < NUM_BOOT_MODULES; i++) {
if (boot_modules[i] == NULL)
continue;
while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
devpath = NextDevicePathNode(devpath);
printf(" %s", boot_modules[i]->name);
if (boot_modules[i]->init != NULL)
boot_modules[i]->init();
}
putchar('\n');
status = systab->BootServices->HandleProtocol(handles[i],
&BlockIoProtocolGUID, (void **)&blkio);
if (EFI_ERROR(status))
continue;
/* Get all the device handles */
hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
if ((status = bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles))
!= EFI_SUCCESS)
panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT,
EFI_ERROR_CODE(status));
if (!blkio->Media->LogicalPartition)
continue;
status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
&hsize, handles);
switch (status) {
case EFI_SUCCESS:
break;
case EFI_BUFFER_TOO_SMALL:
(void)bs->FreePool(handles);
if ((status = bs->AllocatePool(EfiLoaderData, hsize,
(void **)&handles) != EFI_SUCCESS)) {
panic("Failed to allocate %zu handles (%lu)", hsize /
sizeof(*handles), EFI_ERROR_CODE(status));
}
status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
NULL, &hsize, handles);
if (status != EFI_SUCCESS)
panic("Failed to get device handles (%lu)\n",
EFI_ERROR_CODE(status));
break;
default:
panic("Failed to get device handles (%lu)",
EFI_ERROR_CODE(status));
}
if (domount(devpath, blkio, 1) >= 0)
/* Scan all partitions, probing with all modules. */
nhandles = hsize / sizeof(*handles);
printf(" Probing %zu block devices...", nhandles);
for (i = 0; i < nhandles; i++) {
status = probe_handle(handles[i]);
switch (status) {
case EFI_UNSUPPORTED:
printf(".");
break;
case EFI_SUCCESS:
printf("+");
break;
default:
printf("x");
break;
}
if (i == nparts)
panic("No bootable partition found");
bootdevhandle = handles[i];
load(path);
panic("Load failed");
return EFI_SUCCESS;
}
static int
dskread(void *buf, u_int64_t lba, int nblk)
{
EFI_STATUS status;
int size;
lba = lba / (bootdev->Media->BlockSize / DEV_BSIZE);
size = nblk * DEV_BSIZE;
status = bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba,
size, buf);
if (EFI_ERROR(status))
return (-1);
return (0);
}
#include "ufsread.c"
static ssize_t
fsstat(ufs_ino_t inode)
{
#ifndef UFS2_ONLY
static struct ufs1_dinode dp1;
#endif
#ifndef UFS1_ONLY
static struct ufs2_dinode dp2;
#endif
static struct fs fs;
static ufs_ino_t inomap;
char *blkbuf;
void *indbuf;
size_t n, size;
static ufs2_daddr_t blkmap, indmap;
blkbuf = dmadat->blkbuf;
indbuf = dmadat->indbuf;
if (!dsk_meta) {
inomap = 0;
for (n = 0; sblock_try[n] != -1; n++) {
if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
SBLOCKSIZE / DEV_BSIZE))
return -1;
memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
if ((
#if defined(UFS1_ONLY)
fs.fs_magic == FS_UFS1_MAGIC
#elif defined(UFS2_ONLY)
(fs.fs_magic == FS_UFS2_MAGIC &&
fs.fs_sblockloc == sblock_try[n])
#else
fs.fs_magic == FS_UFS1_MAGIC ||
(fs.fs_magic == FS_UFS2_MAGIC &&
fs.fs_sblockloc == sblock_try[n])
#endif
) &&
fs.fs_bsize <= MAXBSIZE &&
fs.fs_bsize >= (int32_t)sizeof(struct fs))
break;
}
if (sblock_try[n] == -1) {
return -1;
}
printf(" done\n");
/* Status summary. */
for (i = 0; i < NUM_BOOT_MODULES; i++) {
if (boot_modules[i] != NULL) {
printf(" ");
boot_modules[i]->status();
}
dsk_meta++;
} else
memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
if (!inode)
return 0;
if (inomap != inode) {
n = IPERVBLK(&fs);
if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK))
return -1;
n = INO_TO_VBO(n, inode);
#if defined(UFS1_ONLY)
memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
sizeof(struct ufs1_dinode));
#elif defined(UFS2_ONLY)
memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
sizeof(struct ufs2_dinode));
#else
if (fs.fs_magic == FS_UFS1_MAGIC)
memcpy(&dp1, (struct ufs1_dinode *)(void *)blkbuf + n,
sizeof(struct ufs1_dinode));
else
memcpy(&dp2, (struct ufs2_dinode *)(void *)blkbuf + n,
sizeof(struct ufs2_dinode));
#endif
inomap = inode;
fs_off = 0;
blkmap = indmap = 0;
}
size = DIP(di_size);
n = size - fs_off;
return (n);
/* Select a partition to boot by trying each module in order. */
for (i = 0; i < NUM_BOOT_MODULES; i++)
if (boot_modules[i] != NULL)
try_load(boot_modules[i]);
/* If we get here, we're out of luck... */
panic("No bootable partitions found!");
}
static struct dmadat __dmadat;
static int
domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
static EFI_STATUS
probe_handle(EFI_HANDLE h)
{
dmadat = &__dmadat;
bootdev = blkio;
bootdevpath = device;
if (fsread(0, NULL, 0)) {
if (!quiet)
printf("domount: can't read superblock\n");
return (-1);
}
if (!quiet)
printf("Succesfully mounted UFS filesystem\n");
return (0);
}
static void
load(const char *fname)
{
ufs_ino_t ino;
dev_info_t *devinfo;
EFI_BLOCK_IO *blkio;
EFI_DEVICE_PATH *devpath;
EFI_STATUS status;
EFI_HANDLE loaderhandle;
EFI_LOADED_IMAGE *loaded_image;
void *buffer;
size_t bufsize;
UINTN i;
if ((ino = lookup(fname)) == 0) {
printf("File %s not found\n", fname);
/* Figure out if we're dealing with an actual partition. */
status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
if (status == EFI_UNSUPPORTED)
return (status);
if (status != EFI_SUCCESS) {
DPRINTF("\nFailed to query DevicePath (%lu)\n",
EFI_ERROR_CODE(status));
return (status);
}
while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
devpath = NextDevicePathNode(devpath);
status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
if (status == EFI_UNSUPPORTED)
return (status);
if (status != EFI_SUCCESS) {
DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
EFI_ERROR_CODE(status));
return (status);
}
if (!blkio->Media->LogicalPartition)
return (EFI_UNSUPPORTED);
/* Run through each module, see if it can load this partition */
for (i = 0; i < NUM_BOOT_MODULES; i++) {
if (boot_modules[i] == NULL)
continue;
if ((status = bs->AllocatePool(EfiLoaderData,
sizeof(*devinfo), (void **)&devinfo)) !=
EFI_SUCCESS) {
DPRINTF("\nFailed to allocate devinfo (%lu)\n",
EFI_ERROR_CODE(status));
continue;
}
devinfo->dev = blkio;
devinfo->devpath = devpath;
devinfo->devhandle = h;
devinfo->devdata = NULL;
devinfo->next = NULL;
status = boot_modules[i]->probe(devinfo);
if (status == EFI_SUCCESS)
return (EFI_SUCCESS);
(void)bs->FreePool(devinfo);
}
return (EFI_UNSUPPORTED);
}
void
add_device(dev_info_t **devinfop, dev_info_t *devinfo)
{
dev_info_t *dev;
if (*devinfop == NULL) {
*devinfop = devinfo;
return;
}
bufsize = fsstat(ino);
status = systab->BootServices->AllocatePool(EfiLoaderData,
bufsize, &buffer);
fsread(ino, buffer, bufsize);
for (dev = *devinfop; dev->next != NULL; dev = dev->next)
;
/* XXX: For secure boot, we need our own loader here */
status = systab->BootServices->LoadImage(TRUE, image, bootdevpath,
buffer, bufsize, &loaderhandle);
if (EFI_ERROR(status))
printf("LoadImage failed with error %lu\n",
EFI_ERROR_CODE(status));
status = systab->BootServices->HandleProtocol(loaderhandle,
&LoadedImageGUID, (VOID**)&loaded_image);
if (EFI_ERROR(status))
printf("HandleProtocol failed with error %lu\n",
EFI_ERROR_CODE(status));
loaded_image->DeviceHandle = bootdevhandle;
status = systab->BootServices->StartImage(loaderhandle, NULL, NULL);
if (EFI_ERROR(status))
printf("StartImage failed with error %lu\n",
EFI_ERROR_CODE(status));
dev->next = devinfo;
}
void

View File

@ -0,0 +1,113 @@
/*-
* Copyright (c) 2015 Eric McCorkle
* 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 _BOOT_MODULE_H_
#define _BOOT_MODULE_H_
#include <stdbool.h>
#include <efi.h>
#include <efilib.h>
#include <eficonsctl.h>
#ifdef EFI_DEBUG
#define DPRINTF(fmt, args...) \
do { \
printf(fmt, ##args) \
} while (0)
#else
#define DPRINTF(fmt, args...) {}
#endif
/* EFI device info */
typedef struct dev_info
{
EFI_BLOCK_IO *dev;
EFI_DEVICE_PATH *devpath;
EFI_HANDLE *devhandle;
void *devdata;
struct dev_info *next;
} dev_info_t;
/*
* A boot loader module.
*
* This is a standard interface for filesystem modules in the EFI system.
*/
typedef struct boot_module_t
{
const char *name;
/* init is the optional initialiser for the module. */
void (*init)();
/*
* probe checks to see if the module can handle dev.
*
* Return codes:
* EFI_SUCCESS = The module can handle the device.
* EFI_NOT_FOUND = The module can not handle the device.
* Other = The module encountered an error.
*/
EFI_STATUS (*probe)(dev_info_t* dev);
/*
* load should select the best out of a set of devices that probe
* indicated were loadable and load it.
*
* Return codes:
* EFI_SUCCESS = The module can handle the device.
* EFI_NOT_FOUND = The module can not handle the device.
* Other = The module encountered an error.
*/
EFI_STATUS (*load)(const char *loader_path, dev_info_t **devinfo,
void **buf, size_t *bufsize);
/* status outputs information about the probed devices. */
void (*status)();
} boot_module_t;
/* Standard boot modules. */
#ifdef EFI_UFS_BOOT
extern const boot_module_t ufs_module;
#endif
#ifdef EFI_ZFS_BOOT
extern const boot_module_t zfs_module;
#endif
/* Functions available to modules. */
extern void add_device(dev_info_t **devinfop, dev_info_t *devinfo);
extern void panic(const char *fmt, ...) __dead2;
extern int printf(const char *fmt, ...);
extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
extern EFI_SYSTEM_TABLE *systab;
extern EFI_BOOT_SERVICES *bs;
#endif

View File

@ -0,0 +1,253 @@
/*-
* Copyright (c) 1998 Robert Nordier
* All rights reserved.
* Copyright (c) 2001 Robert Drehmel
* All rights reserved.
* Copyright (c) 2014 Nathan Whitehorn
* All rights reserved.
* Copyright (c) 2015 Eric McCorkle
* All rights reverved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <stdarg.h>
#include <stdbool.h>
#include <sys/cdefs.h>
#include <sys/param.h>
#include <efi.h>
#include "boot_module.h"
static dev_info_t *devinfo;
static dev_info_t *devices;
static int
dskread(void *buf, u_int64_t lba, int nblk)
{
int size;
EFI_STATUS status;
lba = lba / (devinfo->dev->Media->BlockSize / DEV_BSIZE);
size = nblk * DEV_BSIZE;
status = devinfo->dev->ReadBlocks(devinfo->dev,
devinfo->dev->Media->MediaId, lba, size, buf);
if (status != EFI_SUCCESS) {
DPRINTF("dskread: failed dev: %p, id: %u, lba: %lu, size: %d, "
"status: %lu\n", devinfo->dev,
devinfo->dev->Media->MediaId, lba, size,
EFI_ERROR_CODE(status));
return (-1);
}
return (0);
}
#include "ufsread.c"
static ssize_t
fsstat(ufs_ino_t inode)
{
#ifndef UFS2_ONLY
static struct ufs1_dinode dp1;
#endif
#ifndef UFS1_ONLY
static struct ufs2_dinode dp2;
#endif
static struct fs fs;
static ufs_ino_t inomap;
char *blkbuf;
void *indbuf;
size_t n, size;
static ufs2_daddr_t blkmap, indmap;
blkbuf = dmadat->blkbuf;
indbuf = dmadat->indbuf;
if (!dsk_meta) {
inomap = 0;
for (n = 0; sblock_try[n] != -1; n++) {
if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
SBLOCKSIZE / DEV_BSIZE))
return (-1);
memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
if ((
#if defined(UFS1_ONLY)
fs.fs_magic == FS_UFS1_MAGIC
#elif defined(UFS2_ONLY)
(fs.fs_magic == FS_UFS2_MAGIC &&
fs.fs_sblockloc == sblock_try[n])
#else
fs.fs_magic == FS_UFS1_MAGIC ||
(fs.fs_magic == FS_UFS2_MAGIC &&
fs.fs_sblockloc == sblock_try[n])
#endif
) &&
fs.fs_bsize <= MAXBSIZE &&
fs.fs_bsize >= (int32_t)sizeof(struct fs))
break;
}
if (sblock_try[n] == -1) {
return (-1);
}
dsk_meta++;
} else
memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
if (!inode)
return (0);
if (inomap != inode) {
n = IPERVBLK(&fs);
if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK))
return (-1);
n = INO_TO_VBO(n, inode);
#if defined(UFS1_ONLY)
memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
sizeof(struct ufs1_dinode));
#elif defined(UFS2_ONLY)
memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
sizeof(struct ufs2_dinode));
#else
if (fs.fs_magic == FS_UFS1_MAGIC)
memcpy(&dp1, (struct ufs1_dinode *)(void *)blkbuf + n,
sizeof(struct ufs1_dinode));
else
memcpy(&dp2, (struct ufs2_dinode *)(void *)blkbuf + n,
sizeof(struct ufs2_dinode));
#endif
inomap = inode;
fs_off = 0;
blkmap = indmap = 0;
}
size = DIP(di_size);
n = size - fs_off;
return (n);
}
static struct dmadat __dmadat;
static EFI_STATUS
probe(dev_info_t* dev)
{
devinfo = dev;
dmadat = &__dmadat;
if (fsread(0, NULL, 0) < 0)
return (EFI_UNSUPPORTED);
add_device(&devices, dev);
return (EFI_SUCCESS);
}
static EFI_STATUS
try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize)
{
ufs_ino_t ino;
EFI_STATUS status;
size_t size;
ssize_t read;
void *buf;
devinfo = dev;
if ((ino = lookup(loader_path)) == 0)
return (EFI_NOT_FOUND);
size = fsstat(ino);
if (size <= 0) {
printf("Failed to fsstat %s ino: %d\n", loader_path, ino);
return (EFI_INVALID_PARAMETER);
}
if ((status = bs->AllocatePool(EfiLoaderData, size, &buf)) !=
EFI_SUCCESS) {
printf("Failed to allocate read buffer (%lu)\n",
EFI_ERROR_CODE(status));
return (status);
}
read = fsread(ino, buf, size);
if ((size_t)read != size) {
printf("Failed to read %s (%zd != %zu)\n", loader_path, read,
size);
(void)bs->FreePool(buf);
return (EFI_INVALID_PARAMETER);
}
*bufp = buf;
*bufsize = size;
return (EFI_SUCCESS);
}
static EFI_STATUS
load(const char *loader_path, dev_info_t **devinfop, void **buf,
size_t *bufsize)
{
dev_info_t *dev;
EFI_STATUS status;
for (dev = devices; dev != NULL; dev = dev->next) {
status = try_load(dev, loader_path, buf, bufsize);
if (status == EFI_SUCCESS) {
*devinfop = dev;
return (EFI_SUCCESS);
} else if (status != EFI_NOT_FOUND) {
return (status);
}
}
return (EFI_NOT_FOUND);
}
static void
status()
{
int i;
dev_info_t *dev;
for (dev = devices, i = 0; dev != NULL; dev = dev->next, i++)
;
printf("%s found ", ufs_module.name);
switch (i) {
case 0:
printf("no partitions\n");
break;
case 1:
printf("%d partition\n", i);
break;
default:
printf("%d partitions\n", i);
}
}
const boot_module_t ufs_module =
{
.name = "UFS",
.probe = probe,
.load = load,
.status = status
};

View File

@ -0,0 +1,199 @@
/*-
* Copyright (c) 2015 Eric McCorkle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <stddef.h>
#include <stdarg.h>
#include <stdbool.h>
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/queue.h>
#include <efi.h>
#include "boot_module.h"
#include "libzfs.h"
#include "zfsimpl.c"
static dev_info_t *devices;
static int
vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
{
dev_info_t *devinfo;
off_t lba;
EFI_STATUS status;
devinfo = (dev_info_t *)priv;
lba = off / devinfo->dev->Media->BlockSize;
status = devinfo->dev->ReadBlocks(devinfo->dev,
devinfo->dev->Media->MediaId, lba, bytes, buf);
if (status != EFI_SUCCESS) {
DPRINTF("vdev_read: failed dev: %p, id: %u, lba: %lu, size: %d,"
" status: %lu\n", devinfo->dev,
devinfo->dev->Media->MediaId, lba, size,
EFI_ERROR_CODE(status));
return (-1);
}
return (0);
}
static EFI_STATUS
probe(dev_info_t *dev)
{
spa_t *spa;
dev_info_t *tdev;
EFI_STATUS status;
/* ZFS consumes the dev on success so we need a copy. */
if ((status = bs->AllocatePool(EfiLoaderData, sizeof(*dev),
(void**)&tdev)) != EFI_SUCCESS) {
DPRINTF("Failed to allocate tdev (%lu)\n",
EFI_ERROR_CODE(status));
return (status);
}
memcpy(tdev, dev, sizeof(*dev));
if (vdev_probe(vdev_read, tdev, &spa) != 0) {
(void)bs->FreePool(tdev);
return (EFI_UNSUPPORTED);
}
dev->devdata = spa;
add_device(&devices, dev);
return (EFI_SUCCESS);
}
static EFI_STATUS
try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufsize)
{
spa_t *spa;
struct zfsmount zfsmount;
dnode_phys_t dn;
struct stat st;
int err;
void *buf;
EFI_STATUS status;
spa = devinfo->devdata;
if (zfs_spa_init(spa) != 0) {
/* Init failed, don't report this loudly. */
return (EFI_NOT_FOUND);
}
if (zfs_mount(spa, 0, &zfsmount) != 0) {
/* Mount failed, don't report this loudly. */
return (EFI_NOT_FOUND);
}
if ((err = zfs_lookup(&zfsmount, loader_path, &dn)) != 0) {
printf("Failed to lookup %s on pool %s (%d)\n", loader_path,
spa->spa_name, err);
return (EFI_INVALID_PARAMETER);
}
if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) {
printf("Failed to lookup %s on pool %s (%d)\n", loader_path,
spa->spa_name, err);
return (EFI_INVALID_PARAMETER);
}
if ((status = bs->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf))
!= EFI_SUCCESS) {
printf("Failed to allocate load buffer for pool %s (%lu)\n",
spa->spa_name, EFI_ERROR_CODE(status));
return (EFI_INVALID_PARAMETER);
}
if ((err = dnode_read(spa, &dn, 0, buf, st.st_size)) != 0) {
printf("Failed to read node from %s (%d)\n", spa->spa_name,
err);
(void)bs->FreePool(buf);
return (EFI_INVALID_PARAMETER);
}
*bufsize = st.st_size;
*bufp = buf;
return (EFI_SUCCESS);
}
static EFI_STATUS
load(const char *loader_path, dev_info_t **devinfop, void **bufp,
size_t *bufsize)
{
dev_info_t *devinfo;
EFI_STATUS status;
for (devinfo = devices; devinfo != NULL; devinfo = devinfo->next) {
status = try_load(devinfo, loader_path, bufp, bufsize);
if (status == EFI_SUCCESS) {
*devinfop = devinfo;
return (EFI_SUCCESS);
} else if (status != EFI_NOT_FOUND) {
return (status);
}
}
return (EFI_NOT_FOUND);
}
static void
status()
{
spa_t *spa;
spa = STAILQ_FIRST(&zfs_pools);
if (spa == NULL) {
printf("%s found no pools\n", zfs_module.name);
return;
}
printf("%s found the following pools:", zfs_module.name);
STAILQ_FOREACH(spa, &zfs_pools, spa_link)
printf(" %s", spa->spa_name);
printf("\n");
}
static void
init()
{
zfs_init();
}
const boot_module_t zfs_module =
{
.name = "ZFS",
.init = init,
.probe = probe,
.load = load,
.status = status
};

View File

@ -39,11 +39,11 @@ extern struct devsw efinet_dev;
extern struct netif_driver efinetif;
void *efi_get_table(EFI_GUID *tbl);
void efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int);
EFI_HANDLE efi_find_handle(struct devsw *, int);
int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *);
int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *, uint64_t *);
int efi_handle_update_dev(EFI_HANDLE, struct devsw *, int, uint64_t);
int efi_status_to_errno(EFI_STATUS);
time_t efi_time(EFI_TIME *);

View File

@ -35,6 +35,7 @@ struct entry {
EFI_HANDLE alias;
struct devsw *dev;
int unit;
uint64_t extra;
};
struct entry *entry;
@ -79,7 +80,7 @@ efi_find_handle(struct devsw *dev, int unit)
}
int
efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit)
efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit, uint64_t *extra)
{
int idx;
@ -90,7 +91,28 @@ efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit)
*dev = entry[idx].dev;
if (unit != NULL)
*unit = entry[idx].unit;
if (extra != NULL)
*extra = entry[idx].extra;
return (0);
}
return (ENOENT);
}
int
efi_handle_update_dev(EFI_HANDLE h, struct devsw *dev, int unit,
uint64_t guid)
{
int idx;
for (idx = 0; idx < nentries; idx++) {
if (entry[idx].handle != h)
continue;
entry[idx].dev = dev;
entry[idx].unit = unit;
entry[idx].alias = NULL;
entry[idx].extra = guid;
return (0);
}
return (ENOENT);
}

View File

@ -4,9 +4,6 @@ MAN=
.include <src.opts.mk>
# In-tree GCC does not support __attribute__((ms_abi)).
.if ${COMPILER_TYPE} != "gcc"
MK_SSP= no
PROG= loader.sym
@ -24,6 +21,16 @@ SRCS= autoload.c \
smbios.c \
vers.c
.if ${MK_ZFS} != "no"
SRCS+= zfs.c
.PATH: ${.CURDIR}/../../zfs
# Disable warnings that are currently incompatible with the zfs boot code
CWARNFLAGS.zfs.c+= -Wno-sign-compare
CWARNFLAGS.zfs.c+= -Wno-array-bounds
CWARNFLAGS.zfs.c+= -Wno-missing-prototypes
.endif
.PATH: ${.CURDIR}/arch/${MACHINE}
# For smbios.c
.PATH: ${.CURDIR}/../../i386/libi386
@ -36,6 +43,11 @@ CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
CFLAGS+= -I${.CURDIR}/../../i386/libi386
.if ${MK_ZFS} != "no"
CFLAGS+= -I${.CURDIR}/../../zfs
CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs
CFLAGS+= -DEFI_ZFS_BOOT
.endif
CFLAGS+= -DNO_PCI -DEFI
# make buildenv doesn't set DESTDIR, this means LIBSTAND
@ -113,8 +125,6 @@ DPADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND} \
${LDSCRIPT}
LDADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND}
.endif # ${COMPILER_TYPE} != "gcc"
.include <bsd.prog.mk>
beforedepend ${OBJS}: machine

View File

@ -31,14 +31,23 @@ __FBSDID("$FreeBSD$");
#include <bootstrap.h>
#include <efi.h>
#include <efilib.h>
#ifdef EFI_ZFS_BOOT
#include <libzfs.h>
#endif
struct devsw *devsw[] = {
&efipart_dev,
&efinet_dev,
#ifdef EFI_ZFS_BOOT
&zfs_dev,
#endif
NULL
};
struct fs_ops *file_system[] = {
#ifdef EFI_ZFS_BOOT
&zfs_fsops,
#endif
&dosfs_fsops,
&ufs_fsops,
&cd9660_fsops,

View File

@ -31,7 +31,11 @@ __FBSDID("$FreeBSD$");
#include <stand.h>
#include <string.h>
#include <sys/disklabel.h>
#include <sys/param.h>
#include <bootstrap.h>
#ifdef EFI_ZFS_BOOT
#include <libzfs.h>
#endif
#include <efi.h>
#include <efilib.h>
@ -86,7 +90,7 @@ efi_parsedev(struct devdesc **dev, const char *devspec, const char **path)
struct devsw *dv;
char *cp;
const char *np;
int i, err;
int i;
/* minimum length check */
if (strlen(devspec) < 2)
@ -101,24 +105,43 @@ efi_parsedev(struct devdesc **dev, const char *devspec, const char **path)
if (devsw[i] == NULL)
return (ENOENT);
idev = malloc(sizeof(struct devdesc));
if (idev == NULL)
return (ENOMEM);
idev->d_dev = dv;
idev->d_type = dv->dv_type;
idev->d_unit = -1;
err = 0;
np = devspec + strlen(dv->dv_name);
if (*np != '\0' && *np != ':') {
idev->d_unit = strtol(np, &cp, 0);
if (cp == np) {
idev->d_unit = -1;
#ifdef EFI_ZFS_BOOT
if (dv->dv_type == DEVT_ZFS) {
int err;
idev = malloc(sizeof(struct zfs_devdesc));
if (idev == NULL)
return (ENOMEM);
err = zfs_parsedev((struct zfs_devdesc*)idev, np, path);
if (err != 0) {
free(idev);
return (EUNIT);
return (err);
}
*dev = idev;
cp = strchr(np + 1, ':');
} else
#endif
{
idev = malloc(sizeof(struct devdesc));
if (idev == NULL)
return (ENOMEM);
idev->d_dev = dv;
idev->d_type = dv->dv_type;
idev->d_unit = -1;
if (*np != '\0' && *np != ':') {
idev->d_unit = strtol(np, &cp, 0);
if (cp == np) {
idev->d_unit = -1;
free(idev);
return (EUNIT);
}
}
}
if (*cp != '\0' && *cp != ':') {
free(idev);
return (EINVAL);
@ -137,9 +160,13 @@ char *
efi_fmtdev(void *vdev)
{
struct devdesc *dev = (struct devdesc *)vdev;
static char buf[32]; /* XXX device length constant? */
static char buf[SPECNAMELEN + 1];
switch(dev->d_type) {
#ifdef EFI_ZFS_BOOT
case DEVT_ZFS:
return (zfs_fmtdev(dev));
#endif
case DEVT_NONE:
strcpy(buf, "(no device)");
break;

View File

@ -28,6 +28,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <stand.h>
#include <string.h>
#include <setjmp.h>
@ -38,6 +39,10 @@ __FBSDID("$FreeBSD$");
#include <bootstrap.h>
#include <smbios.h>
#ifdef EFI_ZFS_BOOT
#include <libzfs.h>
#endif
#include "loader_efi.h"
extern char bootprog_name[];
@ -45,7 +50,6 @@ extern char bootprog_rev[];
extern char bootprog_date[];
extern char bootprog_maker[];
struct devdesc currdev; /* our current device */
struct arch_switch archsw; /* MI/MD interface boundary */
EFI_GUID acpi = ACPI_TABLE_GUID;
@ -61,15 +65,45 @@ EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_GUID;
EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
EFI_GUID fdtdtb = FDT_TABLE_GUID;
#ifdef EFI_ZFS_BOOT
static void efi_zfs_probe(void);
#endif
/*
* Need this because EFI uses UTF-16 unicode string constants, but we
* use UTF-8. We can't use printf due to the possiblity of \0 and we
* don't support support wide characters either.
*/
static void
print_str16(const CHAR16 *str)
{
int i;
for (i = 0; str[i]; i++)
printf("%c", (char)str[i]);
}
EFI_STATUS
main(int argc, CHAR16 *argv[])
{
char var[128];
EFI_LOADED_IMAGE *img;
EFI_GUID *guid;
int i, j, vargood;
int i, j, vargood, unit;
struct devsw *dev;
uint64_t pool_guid;
UINTN k;
archsw.arch_autoload = efi_autoload;
archsw.arch_getdev = efi_getdev;
archsw.arch_copyin = efi_copyin;
archsw.arch_copyout = efi_copyout;
archsw.arch_readin = efi_readin;
#ifdef EFI_ZFS_BOOT
/* Note this needs to be set before ZFS init. */
archsw.arch_zfs_probe = efi_zfs_probe;
#endif
/*
* XXX Chicken-and-egg problem; we want to have console output
* early, but some console attributes may depend on reading from
@ -116,6 +150,13 @@ main(int argc, CHAR16 *argv[])
/* Get our loaded image protocol interface structure. */
BS->HandleProtocol(IH, &imgid, (VOID**)&img);
printf("Command line arguments:");
for (i = 0; i < argc; i++) {
printf(" ");
print_str16(argv[i]);
}
printf("\n");
printf("Image base: 0x%lx\n", (u_long)img->ImageBase);
printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16,
ST->Hdr.Revision & 0xffff);
@ -129,9 +170,6 @@ main(int argc, CHAR16 *argv[])
printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
printf("(%s, %s)\n", bootprog_maker, bootprog_date);
efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit);
currdev.d_type = currdev.d_dev->dv_type;
/*
* Disable the watchdog timer. By default the boot manager sets
* the timer to 5 minutes before invoking a boot option. If we
@ -143,19 +181,45 @@ main(int argc, CHAR16 *argv[])
*/
BS->SetWatchdogTimer(0, 0, 0, NULL);
env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
efi_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
env_nounset);
if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &pool_guid) != 0)
return (EFI_NOT_FOUND);
switch (dev->dv_type) {
#ifdef EFI_ZFS_BOOT
case DEVT_ZFS: {
struct zfs_devdesc currdev;
currdev.d_dev = dev;
currdev.d_unit = unit;
currdev.d_type = currdev.d_dev->dv_type;
currdev.d_opendata = NULL;
currdev.pool_guid = pool_guid;
currdev.root_guid = 0;
env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
efi_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
env_nounset);
init_zfs_bootenv(zfs_fmtdev(&currdev));
break;
}
#endif
default: {
struct devdesc currdev;
currdev.d_dev = dev;
currdev.d_unit = unit;
currdev.d_opendata = NULL;
currdev.d_type = currdev.d_dev->dv_type;
env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
efi_setcurrdev, env_nounset);
env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
env_nounset);
break;
}
}
setenv("LINES", "24", 1); /* optional */
archsw.arch_autoload = efi_autoload;
archsw.arch_getdev = efi_getdev;
archsw.arch_copyin = efi_copyin;
archsw.arch_copyout = efi_copyout;
archsw.arch_readin = efi_readin;
for (k = 0; k < ST->NumberOfTableEntries; k++) {
guid = &ST->ConfigurationTable[k].VendorGuid;
if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) {
@ -423,6 +487,61 @@ command_nvram(int argc, char *argv[])
return (CMD_OK);
}
#ifdef EFI_ZFS_BOOT
COMMAND_SET(lszfs, "lszfs", "list child datasets of a zfs dataset",
command_lszfs);
static int
command_lszfs(int argc, char *argv[])
{
int err;
if (argc != 2) {
command_errmsg = "wrong number of arguments";
return (CMD_ERROR);
}
err = zfs_list(argv[1]);
if (err != 0) {
command_errmsg = strerror(err);
return (CMD_ERROR);
}
return (CMD_OK);
}
COMMAND_SET(reloadbe, "reloadbe", "refresh the list of ZFS Boot Environments",
command_reloadbe);
static int
command_reloadbe(int argc, char *argv[])
{
int err;
char *root;
if (argc > 2) {
command_errmsg = "wrong number of arguments";
return (CMD_ERROR);
}
if (argc == 2) {
err = zfs_bootenv(argv[1]);
} else {
root = getenv("zfs_be_root");
if (root == NULL) {
return (CMD_OK);
}
err = zfs_bootenv(root);
}
if (err != 0) {
command_errmsg = strerror(err);
return (CMD_ERROR);
}
return (CMD_OK);
}
#endif
#ifdef LOADER_FDT_SUPPORT
extern int command_fdt_internal(int argc, char *argv[]);
@ -441,3 +560,23 @@ command_fdt(int argc, char *argv[])
COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt);
#endif
#ifdef EFI_ZFS_BOOT
static void
efi_zfs_probe(void)
{
EFI_HANDLE h;
u_int unit;
int i;
char dname[SPECNAMELEN + 1];
uint64_t guid;
unit = 0;
h = efi_find_handle(&efipart_dev, 0);
for (i = 0; h != NULL; h = efi_find_handle(&efipart_dev, ++i)) {
snprintf(dname, sizeof(dname), "%s%d:", efipart_dev.dv_name, i);
if (zfs_probe_dev(dname, &guid) == 0)
(void)efi_handle_update_dev(h, &zfs_dev, unit++, guid);
}
}
#endif

View File

@ -464,7 +464,7 @@ fdt_fixup_memory(struct fdt_mem_region *region, size_t num)
{
struct fdt_mem_region *curmr;
uint32_t addr_cells, size_cells;
uint32_t *addr_cellsp, *reg, *size_cellsp;
uint32_t *addr_cellsp, *size_cellsp;
int err, i, len, memory, root;
size_t realmrno;
uint8_t *buf, *sb;

View File

@ -69,7 +69,6 @@ static int isa_inb(int port);
static void isa_outb(int port, int value);
void exit(int code);
#ifdef LOADER_ZFS_SUPPORT
static void init_zfs_bootenv(char *currdev);
static void i386_zfs_probe(void);
#endif
@ -306,34 +305,6 @@ extract_currdev(void)
env_nounset);
}
#ifdef LOADER_ZFS_SUPPORT
static void
init_zfs_bootenv(char *currdev)
{
char *beroot;
if (strlen(currdev) == 0)
return;
if(strncmp(currdev, "zfs:", 4) != 0)
return;
/* Remove the trailing : */
currdev[strlen(currdev) - 1] = '\0';
setenv("zfs_be_active", currdev, 1);
setenv("zfs_be_currpage", "1", 1);
/* Do not overwrite if already set */
setenv("vfs.root.mountfrom", currdev, 0);
/* Forward past zfs: */
currdev = strchr(currdev, ':');
currdev++;
/* Remove the last element (current bootenv) */
beroot = strrchr(currdev, '/');
if (beroot != NULL)
beroot[0] = '\0';
beroot = currdev;
setenv("zfs_be_root", beroot, 1);
}
#endif
COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
static int

View File

@ -414,7 +414,7 @@ void
usage()
{
printf("usage: [-d <disk image path>] [-h <host filesystem path>\n");
printf("usage: [-b <userboot shared object>] [-d <disk image path>] [-h <host filesystem path>\n");
exit(1);
}
@ -425,9 +425,14 @@ main(int argc, char** argv)
void (*func)(struct loader_callbacks *, void *, int, int);
int opt;
char *disk_image = NULL;
const char *userboot_obj = "/boot/userboot.so";
while ((opt = getopt(argc, argv, "d:h:")) != -1) {
while ((opt = getopt(argc, argv, "b:d:h:")) != -1) {
switch (opt) {
case 'b':
userboot_obj = optarg;
break;
case 'd':
disk_image = optarg;
break;
@ -441,8 +446,7 @@ main(int argc, char** argv)
}
}
h = dlopen("/boot/userboot.so",
RTLD_LOCAL);
h = dlopen(userboot_obj, RTLD_LOCAL);
if (!h) {
printf("%s\n", dlerror());
return (1);

View File

@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
static void userboot_zfs_probe(void);
static int userboot_zfs_found;
static void init_zfs_bootenv(char *currdev);
#endif
#define USERBOOT_VERSION USERBOOT_VERSION_3
@ -199,32 +198,6 @@ extract_currdev(void)
}
#if defined(USERBOOT_ZFS_SUPPORT)
static void
init_zfs_bootenv(char *currdev)
{
char *beroot;
if (strlen(currdev) == 0)
return;
if(strncmp(currdev, "zfs:", 4) != 0)
return;
/* Remove the trailing : */
currdev[strlen(currdev) - 1] = '\0';
setenv("zfs_be_active", currdev, 1);
setenv("zfs_be_currpage", "1", 1);
/* Do not overwrite if already set */
setenv("vfs.root.mountfrom", currdev, 0);
/* Forward past zfs: */
currdev = strchr(currdev, ':');
currdev++;
/* Remove the last element (current bootenv) */
beroot = strrchr(currdev, '/');
if (beroot != NULL)
beroot[0] = '\0';
beroot = currdev;
setenv("zfs_be_root", beroot, 1);
}
static void
userboot_zfs_probe(void)
{

View File

@ -62,6 +62,7 @@ int zfs_parsedev(struct zfs_devdesc *dev, const char *devspec,
char *zfs_fmtdev(void *vdev);
int zfs_probe_dev(const char *devname, uint64_t *pool_guid);
int zfs_list(const char *name);
void init_zfs_bootenv(char *currdev);
int zfs_bootenv(const char *name);
int zfs_belist_add(const char *name);
int zfs_set_env(void);

View File

@ -709,6 +709,32 @@ zfs_list(const char *name)
return (zfs_list_dataset(spa, objid));
}
void
init_zfs_bootenv(char *currdev)
{
char *beroot;
if (strlen(currdev) == 0)
return;
if(strncmp(currdev, "zfs:", 4) != 0)
return;
/* Remove the trailing : */
currdev[strlen(currdev) - 1] = '\0';
setenv("zfs_be_active", currdev, 1);
setenv("zfs_be_currpage", "1", 1);
/* Do not overwrite if already set */
setenv("vfs.root.mountfrom", currdev, 0);
/* Forward past zfs: */
currdev = strchr(currdev, ':');
currdev++;
/* Remove the last element (current bootenv) */
beroot = strrchr(currdev, '/');
if (beroot != NULL)
beroot[0] = '\0';
beroot = currdev;
setenv("zfs_be_root", beroot, 1);
}
int
zfs_bootenv(const char *name)
{
@ -779,8 +805,15 @@ int
zfs_belist_add(const char *name)
{
/* Skip special datasets that start with a $ character */
if (strncmp(name, "$", 1) == 0) {
return (0);
}
/* Add the boot environment to the head of the SLIST */
zfs_be = malloc(sizeof(struct zfs_be_entry));
if (zfs_be == NULL) {
return (ENOMEM);
}
zfs_be->name = name;
SLIST_INSERT_HEAD(&zfs_be_head, zfs_be, entries);
zfs_env_count++;

View File

@ -2165,7 +2165,13 @@ zfs_lookup(const struct zfsmount *mount, const char *upath, dnode_phys_t *dnode)
strcpy(&path[sb.st_size], p);
else
path[sb.st_size] = 0;
if (sb.st_size + sizeof(znode_phys_t) <= dn.dn_bonuslen) {
/*
* Second test is purely to silence bogus compiler
* warning about accessing past the end of dn_bonus.
*/
if (sb.st_size + sizeof(znode_phys_t) <=
dn.dn_bonuslen && sizeof(znode_phys_t) <=
sizeof(dn.dn_bonus)) {
memcpy(path, &dn.dn_bonus[sizeof(znode_phys_t)],
sb.st_size);
} else {

View File

@ -610,7 +610,6 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
error = SET_ERROR(EINVAL);
break;
}
check++;
}
if (strlen(strval) > ZPROP_MAX_COMMENT)
error = E2BIG;
@ -5952,6 +5951,8 @@ spa_async_remove(spa_t *spa, vdev_t *vd)
vd->vdev_stat.vs_checksum_errors = 0;
vdev_state_dirty(vd->vdev_top);
/* Tell userspace that the vdev is gone. */
zfs_post_remove(spa, vd);
}
for (int c = 0; c < vd->vdev_children; c++)

View File

@ -160,7 +160,6 @@ vdev_geom_orphan(struct g_consumer *cp)
* async removal support to invoke a close on this
* vdev once it is safe to do so.
*/
zfs_post_remove(vd->vdev_spa, vd);
vd->vdev_remove_wanted = B_TRUE;
spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE);
}

View File

@ -1131,7 +1131,7 @@ linux_get_robust_list(struct thread *td, struct linux_get_robust_list_args *args
return (EFAULT);
}
error = copyout(head, args->head, sizeof(struct linux_robust_list_head));
error = copyout(&head, args->head, sizeof(head));
if (error) {
LIN_SDT_PROBE1(futex, linux_get_robust_list, copyout_error,
error);

View File

@ -1304,9 +1304,11 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args)
if (error)
goto out;
newcred = crget();
crextend(newcred, ngrp + 1);
p = td->td_proc;
PROC_LOCK(p);
oldcred = crcopysafe(p, newcred);
oldcred = p->p_ucred;
crcopy(newcred, oldcred);
/*
* cr_groups[0] holds egid. Setting the whole set from

View File

@ -129,8 +129,9 @@ struct pci_driver {
const struct pci_device_id *id_table;
int (*probe)(struct pci_dev *dev, const struct pci_device_id *id);
void (*remove)(struct pci_dev *dev);
int (*suspend) (struct pci_dev *dev, pm_message_t state); /* Device suspended */
int (*resume) (struct pci_dev *dev); /* Device woken up */
int (*suspend) (struct pci_dev *dev, pm_message_t state); /* Device suspended */
int (*resume) (struct pci_dev *dev); /* Device woken up */
void (*shutdown) (struct pci_dev *dev); /* Device shutdown */
driver_t driver;
devclass_t bsdclass;
const struct pci_error_handlers *err_handler;

View File

@ -61,11 +61,17 @@ __FBSDID("$FreeBSD$");
static device_probe_t linux_pci_probe;
static device_attach_t linux_pci_attach;
static device_detach_t linux_pci_detach;
static device_suspend_t linux_pci_suspend;
static device_resume_t linux_pci_resume;
static device_shutdown_t linux_pci_shutdown;
static device_method_t pci_methods[] = {
DEVMETHOD(device_probe, linux_pci_probe),
DEVMETHOD(device_attach, linux_pci_attach),
DEVMETHOD(device_detach, linux_pci_detach),
DEVMETHOD(device_suspend, linux_pci_suspend),
DEVMETHOD(device_resume, linux_pci_resume),
DEVMETHOD(device_shutdown, linux_pci_shutdown),
DEVMETHOD_END
};
@ -169,6 +175,46 @@ linux_pci_detach(device_t dev)
return (0);
}
static int
linux_pci_suspend(device_t dev)
{
struct pm_message pm = { };
struct pci_dev *pdev;
int err;
pdev = device_get_softc(dev);
if (pdev->pdrv->suspend != NULL)
err = -pdev->pdrv->suspend(pdev, pm);
else
err = 0;
return (err);
}
static int
linux_pci_resume(device_t dev)
{
struct pci_dev *pdev;
int err;
pdev = device_get_softc(dev);
if (pdev->pdrv->resume != NULL)
err = -pdev->pdrv->resume(pdev);
else
err = 0;
return (err);
}
static int
linux_pci_shutdown(device_t dev)
{
struct pci_dev *pdev;
pdev = device_get_softc(dev);
if (pdev->pdrv->shutdown != NULL)
pdev->pdrv->shutdown(pdev);
return (0);
}
int
pci_register_driver(struct pci_driver *pdrv)
{

View File

@ -273,6 +273,7 @@ dev/hyperv/vmbus/hv_channel.c optional hyperv
dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv
dev/hyperv/vmbus/hv_connection.c optional hyperv
dev/hyperv/vmbus/hv_hv.c optional hyperv
dev/hyperv/vmbus/hv_et.c optional hyperv
dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv
dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
dev/nfe/if_nfe.c optional nfe pci
@ -316,6 +317,7 @@ dev/sfxge/common/efx_ev.c optional sfxge pci
dev/sfxge/common/efx_filter.c optional sfxge pci
dev/sfxge/common/efx_hash.c optional sfxge pci
dev/sfxge/common/efx_intr.c optional sfxge pci
dev/sfxge/common/efx_lic.c optional sfxge pci
dev/sfxge/common/efx_mac.c optional sfxge pci
dev/sfxge/common/efx_mcdi.c optional sfxge pci
dev/sfxge/common/efx_mon.c optional sfxge pci

View File

@ -247,6 +247,7 @@ dev/hyperv/vmbus/hv_channel.c optional hyperv
dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv
dev/hyperv/vmbus/hv_connection.c optional hyperv
dev/hyperv/vmbus/hv_hv.c optional hyperv
dev/hyperv/vmbus/hv_et.c optional hyperv
dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv
dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
dev/ichwd/ichwd.c optional ichwd

View File

@ -173,7 +173,7 @@ bcm_vchiq_attach(device_t dev)
return (ENXIO);
}
mtx_init(&sc->lock, "vchiq", MTX_DEF, 0);
mtx_init(&sc->lock, "vchiq", 0, MTX_DEF);
bcm_vchiq_sc = sc;
vchiq_init();

View File

@ -663,7 +663,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
plane->dev = dev;
plane->funcs = funcs;
plane->format_types = malloc(sizeof(uint32_t) * format_count,
DRM_MEM_KMS, M_NOWAIT);
DRM_MEM_KMS, M_WAITOK);
if (!plane->format_types) {
DRM_DEBUG_KMS("out of memory when allocating plane\n");
drm_mode_object_put(dev, &plane->base);
@ -1010,7 +1010,7 @@ int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
total_objects += dev->mode_config.num_encoder;
group->id_list = malloc(total_objects * sizeof(uint32_t),
DRM_MEM_KMS, M_NOWAIT | M_ZERO);
DRM_MEM_KMS, M_WAITOK | M_ZERO);
if (!group->id_list)
return -ENOMEM;
@ -1998,7 +1998,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
connector_set = malloc(crtc_req->count_connectors *
sizeof(struct drm_connector *),
DRM_MEM_KMS, M_NOWAIT);
DRM_MEM_KMS, M_WAITOK);
if (!connector_set) {
ret = -ENOMEM;
goto out;
@ -2523,7 +2523,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
goto out_err1;
}
clips = malloc(num_clips * sizeof(*clips), DRM_MEM_KMS,
M_NOWAIT | M_ZERO);
M_WAITOK | M_ZERO);
if (!clips) {
ret = -ENOMEM;
goto out_err1;
@ -2774,13 +2774,13 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
int ret;
property = malloc(sizeof(struct drm_property), DRM_MEM_KMS,
M_NOWAIT | M_ZERO);
M_WAITOK | M_ZERO);
if (!property)
return NULL;
if (num_values) {
property->values = malloc(sizeof(uint64_t)*num_values, DRM_MEM_KMS,
M_NOWAIT | M_ZERO);
M_WAITOK | M_ZERO);
if (!property->values)
goto fail;
}
@ -2908,7 +2908,7 @@ int drm_property_add_enum(struct drm_property *property, int index,
}
prop_enum = malloc(sizeof(struct drm_property_enum), DRM_MEM_KMS,
M_NOWAIT | M_ZERO);
M_WAITOK | M_ZERO);
if (!prop_enum)
return -ENOMEM;
@ -3104,7 +3104,7 @@ static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev
return NULL;
blob = malloc(sizeof(struct drm_property_blob)+length, DRM_MEM_KMS,
M_NOWAIT | M_ZERO);
M_WAITOK | M_ZERO);
if (!blob)
return NULL;
@ -3434,7 +3434,7 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
crtc->gamma_size = gamma_size;
crtc->gamma_store = malloc(gamma_size * sizeof(uint16_t) * 3,
DRM_MEM_KMS, M_NOWAIT | M_ZERO);
DRM_MEM_KMS, M_WAITOK | M_ZERO);
if (!crtc->gamma_store) {
crtc->gamma_size = 0;
return -ENOMEM;
@ -3632,7 +3632,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
file_priv->event_space -= sizeof e->event;
mtx_unlock(&dev->event_lock);
e = malloc(sizeof *e, DRM_MEM_KMS, M_NOWAIT | M_ZERO);
e = malloc(sizeof *e, DRM_MEM_KMS, M_WAITOK | M_ZERO);
if (e == NULL) {
mtx_lock(&dev->event_lock);
file_priv->event_space += sizeof e->event;

View File

@ -225,7 +225,7 @@ int drm_pci_set_unique(struct drm_device *dev,
master->unique_len = u->unique_len;
master->unique_size = u->unique_len + 1;
master->unique = malloc(master->unique_size, DRM_MEM_DRIVER, M_NOWAIT);
master->unique = malloc(master->unique_size, DRM_MEM_DRIVER, M_WAITOK);
if (!master->unique) {
ret = -ENOMEM;
goto err;

View File

@ -2035,9 +2035,9 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp)
if (error == EFBIG && remap) {
struct mbuf *m;
m = m_defrag(*m_headp, M_NOWAIT);
m = m_collapse(*m_headp, M_NOWAIT, EM_MAX_SCATTER);
if (m == NULL) {
adapter->mbuf_alloc_failed++;
adapter->mbuf_defrag_failed++;
m_freem(*m_headp);
*m_headp = NULL;
return (ENOBUFS);
@ -5493,18 +5493,15 @@ em_add_hw_stats(struct adapter *adapter)
char namebuf[QUEUE_NAME_LEN];
/* Driver Statistics */
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
CTLFLAG_RD, &adapter->link_irq,
"Link MSIX IRQ Handled");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_alloc_fail",
CTLFLAG_RD, &adapter->mbuf_alloc_failed,
"Std mbuf failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "cluster_alloc_fail",
CTLFLAG_RD, &adapter->mbuf_cluster_failed,
"Std mbuf cluster failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
CTLFLAG_RD, &adapter->dropped_pkts,
"Driver dropped packets");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
CTLFLAG_RD, &adapter->link_irq,
"Link MSIX IRQ Handled");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_fail",
CTLFLAG_RD, &adapter->mbuf_defrag_failed,
"Defragmenting mbuf chain failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail",
CTLFLAG_RD, &adapter->no_tx_dma_setup,
"Driver tx dma failure in xmit");

View File

@ -473,13 +473,12 @@ struct adapter {
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
unsigned long mbuf_alloc_failed;
unsigned long mbuf_cluster_failed;
unsigned long link_irq;
unsigned long mbuf_defrag_failed;
unsigned long no_tx_dma_setup;
unsigned long no_tx_map_avail;
unsigned long no_tx_dma_setup;
unsigned long rx_overruns;
unsigned long watchdog_events;
unsigned long link_irq;
struct e1000_hw_stats stats;
};

View File

@ -1835,7 +1835,8 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
/* Try it again? - one try */
if (remap == TRUE) {
remap = FALSE;
m = m_defrag(*m_headp, M_NOWAIT);
m = m_collapse(*m_headp, M_NOWAIT,
IGB_MAX_SCATTER);
if (m == NULL) {
adapter->mbuf_defrag_failed++;
m_freem(*m_headp);
@ -5826,12 +5827,15 @@ igb_add_hw_stats(struct adapter *adapter)
char namebuf[QUEUE_NAME_LEN];
/* Driver Statistics */
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
CTLFLAG_RD, &adapter->link_irq,
"Link MSIX IRQ Handled");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
CTLFLAG_RD, &adapter->dropped_pkts,
"Driver dropped packets");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
CTLFLAG_RD, &adapter->link_irq,
"Link MSIX IRQ Handled");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_fail",
CTLFLAG_RD, &adapter->mbuf_defrag_failed,
"Defragmenting mbuf chain failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail",
CTLFLAG_RD, &adapter->no_tx_dma_setup,
"Driver tx dma failure in xmit");

View File

@ -512,20 +512,19 @@ struct adapter {
u8 *mta;
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
unsigned long mbuf_defrag_failed;
unsigned long mbuf_header_failed;
unsigned long mbuf_packet_failed;
unsigned long no_tx_dma_setup;
unsigned long watchdog_events;
unsigned long link_irq;
unsigned long rx_overruns;
unsigned long device_control;
unsigned long rx_control;
unsigned long int_mask;
unsigned long dropped_pkts;
unsigned long eint_mask;
unsigned long int_mask;
unsigned long link_irq;
unsigned long mbuf_defrag_failed;
unsigned long no_tx_dma_setup;
unsigned long packet_buf_alloc_rx;
unsigned long packet_buf_alloc_tx;
unsigned long rx_control;
unsigned long rx_overruns;
unsigned long watchdog_events;
/* Used in pf and vf */
void *stats;

View File

@ -1675,9 +1675,9 @@ lem_xmit(struct adapter *adapter, struct mbuf **m_headp)
if (error == EFBIG) {
struct mbuf *m;
m = m_defrag(*m_headp, M_NOWAIT);
m = m_collapse(*m_headp, M_NOWAIT, EM_MAX_SCATTER);
if (m == NULL) {
adapter->mbuf_alloc_failed++;
adapter->mbuf_defrag_failed++;
m_freem(*m_headp);
*m_headp = NULL;
return (ENOBUFS);
@ -4526,12 +4526,12 @@ lem_add_hw_stats(struct adapter *adapter)
struct sysctl_oid_list *stat_list;
/* Driver Statistics */
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_alloc_fail",
CTLFLAG_RD, &adapter->mbuf_alloc_failed,
"Std mbuf failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "cluster_alloc_fail",
CTLFLAG_RD, &adapter->mbuf_cluster_failed,
"Std mbuf cluster failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_fail",
CTLFLAG_RD, &adapter->mbuf_defrag_failed,
"Defragmenting mbuf chain failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
CTLFLAG_RD, &adapter->dropped_pkts,
"Driver dropped packets");

View File

@ -417,17 +417,17 @@ struct adapter {
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
unsigned long mbuf_alloc_failed;
unsigned long link_irq;
unsigned long mbuf_cluster_failed;
unsigned long mbuf_defrag_failed;
unsigned long no_tx_desc_avail1;
unsigned long no_tx_desc_avail2;
unsigned long no_tx_dma_setup;
unsigned long no_tx_map_avail;
unsigned long no_tx_dma_setup;
unsigned long watchdog_events;
unsigned long rx_overruns;
unsigned long rx_irq;
unsigned long rx_overruns;
unsigned long tx_irq;
unsigned long link_irq;
/* 82547 workaround */
uint32_t tx_fifo_size;

View File

@ -184,7 +184,7 @@ gpiobus_init_softc(device_t dev)
if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0)
return (ENXIO);
KASSERT(sc->sc_npins != 0, ("GPIO device with no pins"));
KASSERT(sc->sc_npins >= 0, ("GPIO device with no pins"));
/* Pins = GPIO_PIN_MAX() + 1 */
sc->sc_npins++;

View File

@ -335,11 +335,6 @@ typedef enum {
HV_CHANNEL_MESSAGE_INITIATED_CONTACT = 14,
HV_CHANNEL_MESSAGE_VERSION_RESPONSE = 15,
HV_CHANNEL_MESSAGE_UNLOAD = 16,
#ifdef HV_VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD
HV_CHANNEL_MESSAGE_VIEW_RANGE_ADD = 17,
HV_CHANNEL_MESSAGE_VIEW_RANGE_REMOVE = 18,
#endif
HV_CHANNEL_MESSAGE_COUNT
} hv_vmbus_channel_msg_type;

View File

@ -642,6 +642,12 @@ hv_nv_connect_to_vsp(struct hv_device *device)
/* sema_wait(&NetVscChannel->channel_init_sema); */
/* Post the big receive buffer to NetVSP */
if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_2)
net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY;
else
net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
net_dev->send_buf_size = NETVSC_SEND_BUFFER_SIZE;
ret = hv_nv_init_rx_buffer_with_net_vsp(device);
if (ret == 0)
ret = hv_nv_init_send_buffer_with_net_vsp(device);
@ -676,9 +682,6 @@ hv_nv_on_device_add(struct hv_device *device, void *additional_info)
goto cleanup;
/* Initialize the NetVSC channel extension */
net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
net_dev->send_buf_size = NETVSC_SEND_BUFFER_SIZE;
sema_init(&net_dev->channel_init_sema, 0, "netdev_sema");

View File

@ -857,7 +857,7 @@ typedef struct nvsp_msg_ {
#define NETVSC_SEND_BUFFER_SIZE (1024*1024*15) /* 15M */
#define NETVSC_SEND_BUFFER_ID 0xface
#define NETVSC_RECEIVE_BUFFER_SIZE_LEGACY (1024*1024*15) /* 15MB */
#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*16) /* 16MB */
#define NETVSC_RECEIVE_BUFFER_ID 0xcafe

View File

@ -391,12 +391,14 @@ netvsc_attach(device_t dev)
sc->hn_carrier = 1;
}
#if defined(INET) || defined(INET6)
tcp_lro_init(&sc->hn_lro);
/* Driver private LRO settings */
sc->hn_lro.ifp = ifp;
#ifdef HN_LRO_HIWAT
sc->hn_lro.lro_hiwat = sc->hn_lro_hiwat;
#endif
#endif /* INET || INET6 */
ether_ifattach(ifp, device_info.mac_addr);
@ -475,7 +477,9 @@ netvsc_detach(device_t dev)
hv_rf_on_device_remove(hv_device, HV_RF_NV_DESTROY_CHANNEL);
ifmedia_removeall(&sc->hn_media);
#if defined(INET) || defined(INET6)
tcp_lro_free(&sc->hn_lro);
#endif
return (0);
}
@ -1083,6 +1087,7 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet,
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
if ((ifp->if_capenable & IFCAP_LRO) && do_lro) {
#if defined(INET) || defined(INET6)
struct lro_ctrl *lro = &sc->hn_lro;
if (lro->lro_cnt) {
@ -1092,6 +1097,7 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet,
return 0;
}
}
#endif
}
/* We're not holding the lock here, so don't release it */
@ -1103,6 +1109,7 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet,
void
netvsc_recv_rollup(struct hv_device *device_ctx)
{
#if defined(INET) || defined(INET6)
hn_softc_t *sc = device_get_softc(device_ctx->device);
struct lro_ctrl *lro = &sc->hn_lro;
struct lro_entry *queued;
@ -1111,6 +1118,7 @@ netvsc_recv_rollup(struct hv_device *device_ctx)
SLIST_REMOVE_HEAD(&lro->lro_active, next);
tcp_lro_flush(lro, queued);
}
#endif
}
/*

View File

@ -251,7 +251,7 @@ hv_vmbus_connect(void) {
hv_vmbus_protocal_version = version;
if (bootverbose)
printf("VMBUS: Portocal Version: %d.%d\n",
printf("VMBUS: Protocol Version: %d.%d\n",
version >> 16, version & 0xFFFF);
sema_destroy(&msg_info->wait_sema);
@ -423,12 +423,6 @@ VmbusProcessChannelEvent(uint32_t relid)
// mtx_unlock(&channel->inbound_lock);
}
#ifdef HV_DEBUG_INTR
extern uint32_t hv_intr_count;
extern uint32_t hv_vmbus_swintr_event_cpu[MAXCPU];
extern uint32_t hv_vmbus_intr_cpu[MAXCPU];
#endif
/**
* Handler for events
*/
@ -449,17 +443,6 @@ hv_vmbus_on_events(void *arg)
KASSERT(cpu <= mp_maxid, ("VMBUS: hv_vmbus_on_events: "
"cpu out of range!"));
#ifdef HV_DEBUG_INTR
int i;
hv_vmbus_swintr_event_cpu[cpu]++;
if (hv_intr_count % 10000 == 0) {
printf("VMBUS: Total interrupt %d\n", hv_intr_count);
for (i = 0; i < mp_ncpus; i++)
printf("VMBUS: hw cpu[%d]: %d, event sw intr cpu[%d]: %d\n",
i, hv_vmbus_intr_cpu[i], i, hv_vmbus_swintr_event_cpu[i]);
}
#endif
if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) ||
(hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)) {
maxdword = HV_MAX_NUM_CHANNELS_SUPPORTED >> 5;

View File

@ -0,0 +1,131 @@
/*-
* Copyright (c) 2015 Microsoft Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/smp.h>
#include <sys/time.h>
#include <sys/timeet.h>
#include "hv_vmbus_priv.h"
#define HV_TIMER_FREQUENCY (10 * 1000 * 1000LL) /* 100ns period */
#define HV_MAX_DELTA_TICKS 0xffffffffLL
#define HV_MIN_DELTA_TICKS 1LL
static struct eventtimer et;
static uint64_t periodticks[MAXCPU];
static inline uint64_t
sbintime2tick(sbintime_t time)
{
struct timespec val;
val = sbttots(time);
return val.tv_sec * HV_TIMER_FREQUENCY + val.tv_nsec / 100;
}
static int
hv_et_start(struct eventtimer *et, sbintime_t firsttime, sbintime_t periodtime)
{
union hv_timer_config timer_cfg;
uint64_t current;
timer_cfg.as_uint64 = 0;
timer_cfg.auto_enable = 1;
timer_cfg.sintx = HV_VMBUS_MESSAGE_SINT;
periodticks[curcpu] = sbintime2tick(periodtime);
if (firsttime == 0)
firsttime = periodtime;
current = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
current += sbintime2tick(firsttime);
wrmsr(HV_X64_MSR_STIMER0_CONFIG, timer_cfg.as_uint64);
wrmsr(HV_X64_MSR_STIMER0_COUNT, current);
return (0);
}
static int
hv_et_stop(struct eventtimer *et)
{
wrmsr(HV_X64_MSR_STIMER0_CONFIG, 0);
wrmsr(HV_X64_MSR_STIMER0_COUNT, 0);
return (0);
}
void
hv_et_intr(struct trapframe *frame)
{
union hv_timer_config timer_cfg;
struct trapframe *oldframe;
struct thread *td;
if (periodticks[curcpu] != 0) {
uint64_t tick = sbintime2tick(periodticks[curcpu]);
timer_cfg.as_uint64 = rdmsr(HV_X64_MSR_STIMER0_CONFIG);
timer_cfg.enable = 0;
timer_cfg.auto_enable = 1;
timer_cfg.periodic = 1;
periodticks[curcpu] = 0;
wrmsr(HV_X64_MSR_STIMER0_CONFIG, timer_cfg.as_uint64);
wrmsr(HV_X64_MSR_STIMER0_COUNT, tick);
}
if (et.et_active) {
td = curthread;
td->td_intr_nesting_level++;
oldframe = td->td_intr_frame;
td->td_intr_frame = frame;
et.et_event_cb(&et, et.et_arg);
td->td_intr_frame = oldframe;
td->td_intr_nesting_level--;
}
}
void
hv_et_init(void)
{
et.et_name = "HyperV";
et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU | ET_FLAGS_PERIODIC;
et.et_quality = 1000;
et.et_frequency = HV_TIMER_FREQUENCY;
et.et_min_period = (1LL << 32) / HV_TIMER_FREQUENCY;
et.et_max_period = HV_MAX_DELTA_TICKS * ((1LL << 32) / HV_TIMER_FREQUENCY);
et.et_start = hv_et_start;
et.et_stop = hv_et_stop;
et.et_priv = &et;
et_register(&et);
}

View File

@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/pcpu.h>
#include <sys/timetc.h>
#include <machine/bus.h>
#include <machine/md_var.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
@ -44,23 +45,11 @@ __FBSDID("$FreeBSD$");
#include "hv_vmbus_priv.h"
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
#define HV_X64_CPUID_MIN 0x40000005
#define HV_X64_CPUID_MAX 0x4000ffff
#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
#define HV_NANOSECONDS_PER_SEC 1000000000L
static u_int hv_get_timecount(struct timecounter *tc);
static inline void do_cpuid_inline(unsigned int op, unsigned int *eax,
unsigned int *ebx, unsigned int *ecx, unsigned int *edx) {
__asm__ __volatile__("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx),
"=d" (*edx) : "0" (op), "c" (ecx));
}
/**
* Globals
*/
@ -86,27 +75,10 @@ hv_get_timecount(struct timecounter *tc)
int
hv_vmbus_query_hypervisor_presence(void)
{
u_int regs[4];
int hyper_v_detected = 0;
/*
* When Xen is detected and native Xen PV support is enabled,
* ignore Xen's HyperV emulation.
*/
if (vm_guest == VM_GUEST_XEN)
if (vm_guest != VM_GUEST_HV)
return (0);
do_cpuid(1, regs);
if (regs[2] & 0x80000000) { /* if(a hypervisor is detected) */
/* make sure this really is Hyper-V */
/* we look at the CPUID info */
do_cpuid(HV_X64_MSR_GUEST_OS_ID, regs);
hyper_v_detected =
regs[0] >= HV_X64_CPUID_MIN &&
regs[0] <= HV_X64_CPUID_MAX &&
!memcmp("Microsoft Hv", &regs[1], 12);
}
return (hyper_v_detected);
return (hv_high >= HV_X64_CPUID_MIN && hv_high <= HV_X64_CPUID_MAX);
}
/**
@ -115,10 +87,7 @@ hv_vmbus_query_hypervisor_presence(void)
static int
hv_vmbus_get_hypervisor_version(void)
{
unsigned int eax;
unsigned int ebx;
unsigned int ecx;
unsigned int edx;
u_int regs[4];
unsigned int maxLeaf;
unsigned int op;
@ -127,28 +96,16 @@ hv_vmbus_get_hypervisor_version(void)
* Viridian is present
* Query id and revision.
*/
eax = 0;
ebx = 0;
ecx = 0;
edx = 0;
op = HV_CPU_ID_FUNCTION_HV_VENDOR_AND_MAX_FUNCTION;
do_cpuid_inline(op, &eax, &ebx, &ecx, &edx);
do_cpuid(op, regs);
maxLeaf = eax;
eax = 0;
ebx = 0;
ecx = 0;
edx = 0;
maxLeaf = regs[0];
op = HV_CPU_ID_FUNCTION_HV_INTERFACE;
do_cpuid_inline(op, &eax, &ebx, &ecx, &edx);
do_cpuid(op, regs);
if (maxLeaf >= HV_CPU_ID_FUNCTION_MS_HV_VERSION) {
eax = 0;
ebx = 0;
ecx = 0;
edx = 0;
op = HV_CPU_ID_FUNCTION_MS_HV_VERSION;
do_cpuid_inline(op, &eax, &ebx, &ecx, &edx);
do_cpuid(op, regs);
}
return (maxLeaf);
}
@ -255,6 +212,8 @@ hv_vmbus_init(void)
hv_vmbus_g_context.hypercall_page = virt_addr;
tc_init(&hv_timecounter); /* register virtual timecount */
hv_et_init();
return (0);

View File

@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/systm.h>
@ -60,13 +61,15 @@ __FBSDID("$FreeBSD$");
#include "hv_vmbus_priv.h"
#define VMBUS_IRQ 0x5
#include <contrib/dev/acpica/include/acpi.h>
#include "acpi_if.h"
static device_t vmbus_devp;
static int vmbus_inited;
static hv_setup_args setup_args; /* only CPU 0 supported at this time */
static char *vmbus_ids[] = { "VMBUS", NULL };
/**
* @brief Software interrupt thread routine to handle channel messages from
* the hypervisor.
@ -151,7 +154,7 @@ vmbus_msg_swintr(void *arg)
* message to process - an event or a channel message.
*/
static inline int
hv_vmbus_isr(void *unused)
hv_vmbus_isr(struct trapframe *frame)
{
int cpu;
hv_vmbus_message* msg;
@ -191,41 +194,57 @@ hv_vmbus_isr(void *unused)
page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu];
msg = (hv_vmbus_message*) page_addr + HV_VMBUS_MESSAGE_SINT;
/* we call eventtimer process the message */
if (msg->header.message_type == HV_MESSAGE_TIMER_EXPIRED) {
msg->header.message_type = HV_MESSAGE_TYPE_NONE;
/*
* Make sure the write to message_type (ie set to
* HV_MESSAGE_TYPE_NONE) happens before we read the
* message_pending and EOMing. Otherwise, the EOMing will
* not deliver any more messages
* since there is no empty slot
*/
wmb();
if (msg->header.message_flags.u.message_pending) {
/*
* This will cause message queue rescan to possibly
* deliver another msg from the hypervisor
*/
wrmsr(HV_X64_MSR_EOM, 0);
}
hv_et_intr(frame);
return (FILTER_HANDLED);
}
if (msg->header.message_type != HV_MESSAGE_TYPE_NONE) {
swi_sched(hv_vmbus_g_context.msg_swintr[cpu], 0);
}
return FILTER_HANDLED;
return (FILTER_HANDLED);
}
#ifdef HV_DEBUG_INTR
uint32_t hv_intr_count = 0;
#endif
uint32_t hv_vmbus_swintr_event_cpu[MAXCPU];
uint32_t hv_vmbus_intr_cpu[MAXCPU];
u_long *hv_vmbus_intr_cpu[MAXCPU];
void
hv_vector_handler(struct trapframe *trap_frame)
{
#ifdef HV_DEBUG_INTR
int cpu;
#endif
/*
* Disable preemption.
*/
critical_enter();
#ifdef HV_DEBUG_INTR
/*
* Do a little interrupt counting.
*/
cpu = PCPU_GET(cpuid);
hv_vmbus_intr_cpu[cpu]++;
hv_intr_count++;
#endif
(*hv_vmbus_intr_cpu[cpu])++;
hv_vmbus_isr(NULL);
hv_vmbus_isr(trap_frame);
/*
* Enable preemption.
@ -350,25 +369,15 @@ hv_vmbus_child_device_unregister(struct hv_device *child_dev)
return(ret);
}
static void
vmbus_identify(driver_t *driver, device_t parent)
{
if (!hv_vmbus_query_hypervisor_presence())
return;
vm_guest = VM_GUEST_HV;
BUS_ADD_CHILD(parent, 0, "vmbus", 0);
}
static int
vmbus_probe(device_t dev) {
if(bootverbose)
device_printf(dev, "VMBUS: probe\n");
if (ACPI_ID_PROBE(device_get_parent(dev), dev, vmbus_ids) == NULL ||
device_get_unit(dev) != 0)
return (ENXIO);
device_set_desc(dev, "Vmbus Devices");
return (BUS_PROBE_NOWILDCARD);
return (BUS_PROBE_DEFAULT);
}
#ifdef HYPERV
@ -462,6 +471,7 @@ static int
vmbus_bus_init(void)
{
int i, j, n, ret;
char buf[MAXCOMLEN + 1];
if (vmbus_inited)
return (0);
@ -498,13 +508,15 @@ vmbus_bus_init(void)
setup_args.vector = hv_vmbus_g_context.hv_cb_vector;
CPU_FOREACH(j) {
hv_vmbus_intr_cpu[j] = 0;
hv_vmbus_swintr_event_cpu[j] = 0;
hv_vmbus_g_context.hv_event_intr_event[j] = NULL;
hv_vmbus_g_context.hv_msg_intr_event[j] = NULL;
hv_vmbus_g_context.event_swintr[j] = NULL;
hv_vmbus_g_context.msg_swintr[j] = NULL;
snprintf(buf, sizeof(buf), "cpu%d:hyperv", j);
intrcnt_add(buf, &hv_vmbus_intr_cpu[j]);
for (i = 0; i < 2; i++)
setup_args.page_buffers[2 * j + i] = NULL;
}
@ -723,7 +735,6 @@ vmbus_modevent(module_t mod, int what, void *arg)
static device_method_t vmbus_methods[] = {
/** Device interface */
DEVMETHOD(device_identify, vmbus_identify),
DEVMETHOD(device_probe, vmbus_probe),
DEVMETHOD(device_attach, vmbus_attach),
DEVMETHOD(device_detach, vmbus_detach),
@ -745,8 +756,9 @@ static driver_t vmbus_driver = { driver_name, vmbus_methods,0, };
devclass_t vmbus_devclass;
DRIVER_MODULE(vmbus, nexus, vmbus_driver, vmbus_devclass, vmbus_modevent, 0);
MODULE_VERSION(vmbus,1);
DRIVER_MODULE(vmbus, acpi, vmbus_driver, vmbus_devclass, vmbus_modevent, 0);
MODULE_DEPEND(vmbus, acpi, 1, 1, 1);
MODULE_VERSION(vmbus, 1);
/* We want to be started after SMP is initialized */
SYSINIT(vmb_init, SI_SUB_SMP + 1, SI_ORDER_FIRST, vmbus_init, NULL);

View File

@ -359,11 +359,6 @@ typedef struct {
struct sema control_sema;
} hv_vmbus_connection;
/*
* Declare the MSR used to identify the guest OS
*/
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
typedef union {
uint64_t as_uint64_t;
struct {
@ -380,10 +375,6 @@ typedef union {
} u;
} hv_vmbus_x64_msr_guest_os_id_contents;
/*
* Declare the MSR used to setup pages used to communicate with the hypervisor
*/
#define HV_X64_MSR_HYPERCALL 0x40000001
typedef union {
uint64_t as_uint64_t;
@ -512,6 +503,22 @@ typedef union {
} u;
} hv_vmbus_synic_sint;
/*
* Timer configuration register.
*/
union hv_timer_config {
uint64_t as_uint64;
struct {
uint64_t enable:1;
uint64_t periodic:1;
uint64_t lazy:1;
uint64_t auto_enable:1;
uint64_t reserved_z0:12;
uint64_t sintx:4;
uint64_t reserved_z1:44;
};
};
/*
* Define syn_ic control register
*/
@ -542,8 +549,21 @@ typedef union {
uint32_t flags32[HV_EVENT_FLAGS_DWORD_COUNT];
} hv_vmbus_synic_event_flags;
#define HV_X64_CPUID_MIN (0x40000005)
#define HV_X64_CPUID_MAX (0x4000ffff)
/*
* Declare the MSR used to identify the guest OS
*/
#define HV_X64_MSR_GUEST_OS_ID (0x40000000)
/*
* Declare the MSR used to setup pages used to communicate with the hypervisor
*/
#define HV_X64_MSR_HYPERCALL (0x40000001)
/* MSR used to provide vcpu index */
#define HV_X64_MSR_VP_INDEX (0x40000002)
#define HV_X64_MSR_VP_INDEX (0x40000002)
#define HV_X64_MSR_TIME_REF_COUNT (0x40000020)
/*
* Define synthetic interrupt controller model specific registers
@ -571,6 +591,18 @@ typedef union {
#define HV_X64_MSR_SINT14 (0x4000009E)
#define HV_X64_MSR_SINT15 (0x4000009F)
/*
* Synthetic Timer MSRs. Four timers per vcpu.
*/
#define HV_X64_MSR_STIMER0_CONFIG 0x400000B0
#define HV_X64_MSR_STIMER0_COUNT 0x400000B1
#define HV_X64_MSR_STIMER1_CONFIG 0x400000B2
#define HV_X64_MSR_STIMER1_COUNT 0x400000B3
#define HV_X64_MSR_STIMER2_CONFIG 0x400000B4
#define HV_X64_MSR_STIMER2_COUNT 0x400000B5
#define HV_X64_MSR_STIMER3_CONFIG 0x400000B6
#define HV_X64_MSR_STIMER3_COUNT 0x400000B7
/*
* Declare the various hypercall operations
*/
@ -678,6 +710,11 @@ int hv_vmbus_post_message(void *buffer, size_t buf_size);
int hv_vmbus_set_event(hv_vmbus_channel *channel);
void hv_vmbus_on_events(void *);
/**
* Event Timer interfaces
*/
void hv_et_init(void);
void hv_et_intr(struct trapframe*);
/*
* The guest OS needs to register the guest ID with the hypervisor.

View File

@ -852,6 +852,8 @@ ioat_op_generic(struct ioat_softc *ioat, uint8_t op,
if ((flags & DMA_INT_EN) != 0)
hw_desc->u.control_generic.int_enable = 1;
if ((flags & DMA_FENCE) != 0)
hw_desc->u.control_generic.fence = 1;
hw_desc->size = size;
hw_desc->src_addr = src;

View File

@ -46,7 +46,13 @@ __FBSDID("$FreeBSD$");
* descriptor without blocking.
*/
#define DMA_NO_WAIT 0x2
#define DMA_ALL_FLAGS (DMA_INT_EN | DMA_NO_WAIT)
/*
* Disallow prefetching the source of the following operation. Ordinarily, DMA
* operations can be pipelined on some hardware. E.g., operation 2's source
* may be prefetched before operation 1 completes.
*/
#define DMA_FENCE 0x4
#define DMA_ALL_FLAGS (DMA_INT_EN | DMA_NO_WAIT | DMA_FENCE)
/*
* Hardware revision number. Different hardware revisions support different

View File

@ -45,6 +45,52 @@ extern "C" {
#define EF10_MAX_PIOBUF_NBUFS MEDFORD_PIOBUF_NBUFS
#endif
extern __checkReturn efx_rc_t
efx_mcdi_get_port_assignment(
__in efx_nic_t *enp,
__out uint32_t *portp);
extern __checkReturn efx_rc_t
efx_mcdi_get_port_modes(
__in efx_nic_t *enp,
__out uint32_t *modesp);
extern __checkReturn efx_rc_t
efx_mcdi_get_mac_address_pf(
__in efx_nic_t *enp,
__out_ecount_opt(6) uint8_t mac_addrp[6]);
extern __checkReturn efx_rc_t
efx_mcdi_get_mac_address_vf(
__in efx_nic_t *enp,
__out_ecount_opt(6) uint8_t mac_addrp[6]);
extern __checkReturn efx_rc_t
efx_mcdi_get_clock(
__in efx_nic_t *enp,
__out uint32_t *sys_freqp);
extern __checkReturn efx_rc_t
efx_mcdi_get_vector_cfg(
__in efx_nic_t *enp,
__out_opt uint32_t *vec_basep,
__out_opt uint32_t *pf_nvecp,
__out_opt uint32_t *vf_nvecp);
extern __checkReturn efx_rc_t
ef10_get_datapath_caps(
__in efx_nic_t *enp);
extern __checkReturn efx_rc_t
ef10_get_privilege_mask(
__in efx_nic_t *enp,
__out uint32_t *maskp);
extern __checkReturn efx_rc_t
ef10_external_port_mapping(
__in efx_nic_t *enp,
__in uint32_t port,
__out uint8_t *external_portp);
#ifdef __cplusplus

View File

@ -293,6 +293,8 @@ sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map,
#define EFSYS_OPT_DECODE_INTR_FATAL 1
#define EFSYS_OPT_LICENSING 0
/* ID */
typedef struct __efsys_identifier_s efsys_identifier_t;

View File

@ -1071,6 +1071,7 @@ efx_bist_stop(
#define EFX_FEATURE_TX_SRC_FILTERS 0x00000400
#define EFX_FEATURE_PIO_BUFFERS 0x00000800
#define EFX_FEATURE_FW_ASSISTED_TSO 0x00001000
#define EFX_FEATURE_FW_ASSISTED_TSO_V2 0x00002000
typedef struct efx_nic_cfg_s {
uint32_t enc_board_type;
@ -1152,6 +1153,7 @@ typedef struct efx_nic_cfg_s {
*/
uint32_t enc_tx_tso_tcp_header_offset_limit;
boolean_t enc_fw_assisted_tso_enabled;
boolean_t enc_fw_assisted_tso_v2_enabled;
boolean_t enc_hw_tx_insert_vlan_enabled;
/* Datapath firmware vadapter/vport/vswitch support */
boolean_t enc_datapath_cap_evb;
@ -1160,6 +1162,8 @@ typedef struct efx_nic_cfg_s {
/* External port identifier */
uint8_t enc_external_port;
uint32_t enc_mcdi_max_payload_length;
/* VPD may be per-PF or global */
boolean_t enc_vpd_is_global;
} efx_nic_cfg_t;
#define EFX_PCI_FUNCTION_IS_PF(_encp) ((_encp)->enc_vf == 0xffff)
@ -1315,6 +1319,7 @@ typedef enum efx_nvram_type_e {
EFX_NVRAM_CPLD,
EFX_NVRAM_FPGA_BACKUP,
EFX_NVRAM_DYNAMIC_CFG,
EFX_NVRAM_LICENSE,
EFX_NVRAM_NTYPES,
} efx_nvram_type_t;
@ -2002,6 +2007,7 @@ efx_tx_fini(
#define EFX_TXQ_CKSUM_IPV4 0x0001
#define EFX_TXQ_CKSUM_TCPUDP 0x0002
#define EFX_TXQ_FATSOV2 0x0004
extern __checkReturn efx_rc_t
efx_tx_qcreate(
@ -2089,6 +2095,21 @@ efx_tx_qdesc_tso_create(
__in uint8_t tcp_flags,
__out efx_desc_t *edp);
/* Number of FATSOv2 option descriptors */
#define EFX_TX_FATSOV2_OPT_NDESCS 2
/* Maximum number of DMA segments per TSO packet (not superframe) */
#define EFX_TX_FATSOV2_DMA_SEGS_PER_PKT_MAX 24
extern void
efx_tx_qdesc_tso2_create(
__in efx_txq_t *etp,
__in uint16_t ipv4_id,
__in uint32_t tcp_seq,
__in uint16_t tcp_mss,
__out_ecount(count) efx_desc_t *edp,
__in int count);
extern void
efx_tx_qdesc_vlantci_create(
__in efx_txq_t *etp,
@ -2291,6 +2312,57 @@ efx_hash_bytes(
__in size_t length,
__in uint32_t init);
#if EFSYS_OPT_LICENSING
/* LICENSING */
typedef struct efx_key_stats_s {
uint32_t eks_valid;
uint32_t eks_invalid;
uint32_t eks_blacklisted;
uint32_t eks_unverifiable;
uint32_t eks_wrong_node;
uint32_t eks_licensed_apps_lo;
uint32_t eks_licensed_apps_hi;
uint32_t eks_licensed_features_lo;
uint32_t eks_licensed_features_hi;
} efx_key_stats_t;
extern __checkReturn efx_rc_t
efx_lic_init(
__in efx_nic_t *enp);
extern void
efx_lic_fini(
__in efx_nic_t *enp);
extern __checkReturn efx_rc_t
efx_lic_update_licenses(
__in efx_nic_t *enp);
extern __checkReturn efx_rc_t
efx_lic_get_key_stats(
__in efx_nic_t *enp,
__out efx_key_stats_t *ksp);
extern __checkReturn efx_rc_t
efx_lic_app_state(
__in efx_nic_t *enp,
__in uint64_t app_id,
__out boolean_t *licensedp);
extern __checkReturn efx_rc_t
efx_lic_get_id(
__in efx_nic_t *enp,
__in size_t buffer_size,
__out uint32_t *typep,
__out size_t *lengthp,
__out_opt uint8_t *bufferp);
#endif /* EFSYS_OPT_LICENSING */
#ifdef __cplusplus
}

View File

@ -401,4 +401,15 @@
# endif
#endif /* EFSYS_OPT_BIST */
/* Support MCDI licensing API */
#if EFSYS_OPT_LICENSING
# if !EFSYS_OPT_MCDI
# error "LICENSING requires MCDI"
# endif
# if !EFSYS_HAS_UINT64
# error "LICENSING requires UINT64"
# endif
#endif /* EFSYS_OPT_LICENSING */
#endif /* _SYS_EFX_CHECK_H */

View File

@ -84,6 +84,7 @@ extern "C" {
#define EFX_MOD_WOL 0x00000800
#define EFX_MOD_FILTER 0x00001000
#define EFX_MOD_PKTFILTER 0x00002000
#define EFX_MOD_LIC 0x00004000
#define EFX_RESET_MAC 0x00000001
#define EFX_RESET_PHY 0x00000002
@ -146,6 +147,9 @@ typedef struct efx_tx_ops_s {
void (*etxo_qdesc_tso_create)(efx_txq_t *, uint16_t,
uint32_t, uint8_t,
efx_desc_t *);
void (*etxo_qdesc_tso2_create)(efx_txq_t *, uint16_t,
uint32_t, uint16_t,
efx_desc_t *, int);
void (*etxo_qdesc_vlantci_create)(efx_txq_t *, uint16_t,
efx_desc_t *);
#if EFSYS_OPT_QSTATS
@ -358,6 +362,7 @@ typedef struct efx_intr_s {
typedef struct efx_nic_ops_s {
efx_rc_t (*eno_probe)(efx_nic_t *);
efx_rc_t (*eno_board_cfg)(efx_nic_t *);
efx_rc_t (*eno_set_drv_limits)(efx_nic_t *, efx_drv_limits_t*);
efx_rc_t (*eno_reset)(efx_nic_t *);
efx_rc_t (*eno_init)(efx_nic_t *);
@ -456,9 +461,8 @@ falconsiena_filter_tbl_clear(
typedef struct efx_mcdi_ops_s {
efx_rc_t (*emco_init)(efx_nic_t *, const efx_mcdi_transport_t *);
void (*emco_request_copyin)(efx_nic_t *, efx_mcdi_req_t *,
unsigned int, boolean_t, boolean_t);
void (*emco_request_copyout)(efx_nic_t *, efx_mcdi_req_t *);
void (*emco_send_request)(efx_nic_t *, void *, size_t,
void *, size_t);
efx_rc_t (*emco_poll_reboot)(efx_nic_t *);
boolean_t (*emco_poll_response)(efx_nic_t *);
void (*emco_read_response)(efx_nic_t *, void *, size_t, size_t);
@ -479,10 +483,8 @@ typedef struct efx_nvram_ops_s {
#if EFSYS_OPT_DIAG
efx_rc_t (*envo_test)(efx_nic_t *);
#endif /* EFSYS_OPT_DIAG */
efx_rc_t (*envo_size)(efx_nic_t *, efx_nvram_type_t, size_t *);
efx_rc_t (*envo_get_version)(efx_nic_t *, efx_nvram_type_t,
uint32_t *, uint16_t *);
efx_rc_t (*envo_rw_start)(efx_nic_t *, efx_nvram_type_t, size_t *);
efx_rc_t (*envo_read_chunk)(efx_nic_t *, efx_nvram_type_t,
unsigned int, caddr_t, size_t);
efx_rc_t (*envo_erase)(efx_nic_t *, efx_nvram_type_t);
@ -494,6 +496,8 @@ typedef struct efx_nvram_ops_s {
efx_rc_t (*envo_type_to_partn)(efx_nic_t *, efx_nvram_type_t,
uint32_t *);
efx_rc_t (*envo_partn_size)(efx_nic_t *, uint32_t, size_t *);
efx_rc_t (*envo_partn_rw_start)(efx_nic_t *, uint32_t, size_t *);
} efx_nvram_ops_t;
#endif /* EFSYS_OPT_NVRAM */
@ -587,6 +591,18 @@ efx_mcdi_nvram_test(
#endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */
#if EFSYS_OPT_LICENSING
typedef struct efx_lic_ops_s {
efx_rc_t (*elo_update_licenses)(efx_nic_t *);
efx_rc_t (*elo_get_key_stats)(efx_nic_t *, efx_key_stats_t *);
efx_rc_t (*elo_app_state)(efx_nic_t *, uint64_t, boolean_t *);
efx_rc_t (*elo_get_id)(efx_nic_t *, size_t, uint32_t *,
size_t *, uint8_t *);
} efx_lic_ops_t;
#endif
typedef struct efx_drv_cfg_s {
uint32_t edc_min_vi_count;
uint32_t edc_max_vi_count;
@ -636,6 +652,9 @@ struct efx_nic_s {
uint32_t en_rss_context;
#endif /* EFSYS_OPT_RX_SCALE */
uint32_t en_vport_id;
#if EFSYS_OPT_LICENSING
efx_lic_ops_t *en_elop;
#endif
union {
#if EFSYS_OPT_FALCON
struct {

View File

@ -0,0 +1,792 @@
/*-
* Copyright (c) 2009-2015 Solarflare Communications Inc.
* 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of the FreeBSD Project.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "efx.h"
#include "efx_impl.h"
#if EFSYS_OPT_LICENSING
#if EFSYS_OPT_SIENA
static __checkReturn efx_rc_t
efx_mcdi_fc_license_update_license(
__in efx_nic_t *enp);
static __checkReturn efx_rc_t
efx_mcdi_fc_license_get_key_stats(
__in efx_nic_t *enp,
__out efx_key_stats_t *eksp);
static efx_lic_ops_t __efx_lic_v1_ops = {
efx_mcdi_fc_license_update_license, /* elo_update_licenses */
efx_mcdi_fc_license_get_key_stats, /* elo_get_key_stats */
NULL, /* elo_app_state */
NULL, /* elo_get_id */
};
#endif /* EFSYS_OPT_SIENA */
#if EFSYS_OPT_HUNTINGTON
static __checkReturn efx_rc_t
efx_mcdi_licensing_update_licenses(
__in efx_nic_t *enp);
static __checkReturn efx_rc_t
efx_mcdi_licensing_get_key_stats(
__in efx_nic_t *enp,
__out efx_key_stats_t *eksp);
static __checkReturn efx_rc_t
efx_mcdi_licensed_app_state(
__in efx_nic_t *enp,
__in uint64_t app_id,
__out boolean_t *licensedp);
static efx_lic_ops_t __efx_lic_v2_ops = {
efx_mcdi_licensing_update_licenses, /* elo_update_licenses */
efx_mcdi_licensing_get_key_stats, /* elo_get_key_stats */
efx_mcdi_licensed_app_state, /* elo_app_state */
NULL, /* elo_get_id */
};
#endif /* EFSYS_OPT_HUNTINGTON */
#if EFSYS_OPT_MEDFORD
static __checkReturn efx_rc_t
efx_mcdi_licensing_v3_update_licenses(
__in efx_nic_t *enp);
static __checkReturn efx_rc_t
efx_mcdi_licensing_v3_report_license(
__in efx_nic_t *enp,
__out efx_key_stats_t *eksp);
static __checkReturn efx_rc_t
efx_mcdi_licensing_v3_app_state(
__in efx_nic_t *enp,
__in uint64_t app_id,
__out boolean_t *licensedp);
static __checkReturn efx_rc_t
efx_mcdi_licensing_v3_get_id(
__in efx_nic_t *enp,
__in size_t buffer_size,
__out uint32_t *typep,
__out size_t *lengthp,
__out_bcount_part_opt(buffer_size, *lengthp)
uint8_t *bufferp);
static efx_lic_ops_t __efx_lic_v3_ops = {
efx_mcdi_licensing_v3_update_licenses, /* elo_update_licenses */
efx_mcdi_licensing_v3_report_license, /* elo_get_key_stats */
efx_mcdi_licensing_v3_app_state, /* elo_app_state */
efx_mcdi_licensing_v3_get_id, /* elo_get_id */
};
#endif /* EFSYS_OPT_MEDFORD */
/* V1 Licensing - used in Siena Modena only */
#if EFSYS_OPT_SIENA
static __checkReturn efx_rc_t
efx_mcdi_fc_license_update_license(
__in efx_nic_t *enp)
{
efx_mcdi_req_t req;
uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
efx_rc_t rc;
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
(void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_FC_OP_LICENSE;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
req.emr_out_buf = payload;
req.emr_out_length = 0;
MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
efx_mcdi_execute(enp, &req);
if (req.emr_rc != 0) {
rc = req.emr_rc;
goto fail1;
}
if (req.emr_out_length_used != 0) {
rc = EIO;
goto fail2;
}
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
static __checkReturn efx_rc_t
efx_mcdi_fc_license_get_key_stats(
__in efx_nic_t *enp,
__out efx_key_stats_t *eksp)
{
efx_mcdi_req_t req;
uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
MC_CMD_FC_OUT_LICENSE_LEN)];
efx_rc_t rc;
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
(void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_FC_OP_LICENSE;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
req.emr_out_buf = payload;
req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
efx_mcdi_execute(enp, &req);
if (req.emr_rc != 0) {
rc = req.emr_rc;
goto fail1;
}
if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
rc = EMSGSIZE;
goto fail2;
}
eksp->eks_valid =
MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
eksp->eks_invalid =
MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
eksp->eks_blacklisted =
MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
eksp->eks_unverifiable = 0;
eksp->eks_wrong_node = 0;
eksp->eks_licensed_apps_lo = 0;
eksp->eks_licensed_apps_hi = 0;
eksp->eks_licensed_features_lo = 0;
eksp->eks_licensed_features_hi = 0;
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
#endif /* EFSYS_OPT_SIENA */
/* V2 Licensing - used by Huntington family only. See SF-113611-TC */
#if EFSYS_OPT_HUNTINGTON
static __checkReturn efx_rc_t
efx_mcdi_licensed_app_state(
__in efx_nic_t *enp,
__in uint64_t app_id,
__out boolean_t *licensedp)
{
efx_mcdi_req_t req;
uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
uint32_t app_state;
efx_rc_t rc;
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
/* V2 licensing supports 32bit app id only */
if ((app_id >> 32) != 0) {
rc = EINVAL;
goto fail1;
}
(void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
req.emr_out_buf = payload;
req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
app_id & 0xffffffff);
efx_mcdi_execute(enp, &req);
if (req.emr_rc != 0) {
rc = req.emr_rc;
goto fail2;
}
if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
rc = EMSGSIZE;
goto fail3;
}
app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
*licensedp = B_TRUE;
} else {
*licensedp = B_FALSE;
}
return (0);
fail3:
EFSYS_PROBE(fail3);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
static __checkReturn efx_rc_t
efx_mcdi_licensing_update_licenses(
__in efx_nic_t *enp)
{
efx_mcdi_req_t req;
uint8_t payload[MC_CMD_LICENSING_IN_LEN];
efx_rc_t rc;
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
(void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_LICENSING;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
req.emr_out_buf = payload;
req.emr_out_length = 0;
MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
efx_mcdi_execute(enp, &req);
if (req.emr_rc != 0) {
rc = req.emr_rc;
goto fail1;
}
if (req.emr_out_length_used != 0) {
rc = EIO;
goto fail2;
}
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
static __checkReturn efx_rc_t
efx_mcdi_licensing_get_key_stats(
__in efx_nic_t *enp,
__out efx_key_stats_t *eksp)
{
efx_mcdi_req_t req;
uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
MC_CMD_LICENSING_OUT_LEN)];
efx_rc_t rc;
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
(void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_LICENSING;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
req.emr_out_buf = payload;
req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
efx_mcdi_execute(enp, &req);
if (req.emr_rc != 0) {
rc = req.emr_rc;
goto fail1;
}
if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
rc = EMSGSIZE;
goto fail2;
}
eksp->eks_valid =
MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
eksp->eks_invalid =
MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
eksp->eks_blacklisted =
MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
eksp->eks_unverifiable =
MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
eksp->eks_wrong_node =
MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
eksp->eks_licensed_apps_lo = 0;
eksp->eks_licensed_apps_hi = 0;
eksp->eks_licensed_features_lo = 0;
eksp->eks_licensed_features_hi = 0;
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
#endif /* EFSYS_OPT_HUNTINGTON */
/* V3 Licensing - used starting from Medford family. See SF-114884-SW */
#if EFSYS_OPT_MEDFORD
static __checkReturn efx_rc_t
efx_mcdi_licensing_v3_update_licenses(
__in efx_nic_t *enp)
{
efx_mcdi_req_t req;
uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
efx_rc_t rc;
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
(void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_LICENSING_V3;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
req.emr_out_buf = NULL;
req.emr_out_length = 0;
MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
efx_mcdi_execute(enp, &req);
if (req.emr_rc != 0) {
rc = req.emr_rc;
goto fail1;
}
return (0);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
static __checkReturn efx_rc_t
efx_mcdi_licensing_v3_report_license(
__in efx_nic_t *enp,
__out efx_key_stats_t *eksp)
{
efx_mcdi_req_t req;
uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
MC_CMD_LICENSING_V3_OUT_LEN)];
efx_rc_t rc;
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
(void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_LICENSING_V3;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
req.emr_out_buf = payload;
req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
efx_mcdi_execute(enp, &req);
if (req.emr_rc != 0) {
rc = req.emr_rc;
goto fail1;
}
if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
rc = EMSGSIZE;
goto fail2;
}
eksp->eks_valid =
MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
eksp->eks_invalid =
MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
eksp->eks_blacklisted = 0;
eksp->eks_unverifiable =
MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
eksp->eks_wrong_node =
MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
eksp->eks_licensed_apps_lo =
MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
eksp->eks_licensed_apps_hi =
MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
eksp->eks_licensed_features_lo =
MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
eksp->eks_licensed_features_hi =
MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
static __checkReturn efx_rc_t
efx_mcdi_licensing_v3_app_state(
__in efx_nic_t *enp,
__in uint64_t app_id,
__out boolean_t *licensedp)
{
efx_mcdi_req_t req;
uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
uint32_t app_state;
efx_rc_t rc;
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
(void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
req.emr_in_buf = payload;
req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
req.emr_out_buf = payload;
req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
app_id & 0xffffffff);
MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
app_id >> 32);
efx_mcdi_execute(enp, &req);
if (req.emr_rc != 0) {
rc = req.emr_rc;
goto fail1;
}
if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
rc = EMSGSIZE;
goto fail2;
}
app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
*licensedp = B_TRUE;
} else {
*licensedp = B_FALSE;
}
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
static __checkReturn efx_rc_t
efx_mcdi_licensing_v3_get_id(
__in efx_nic_t *enp,
__in size_t buffer_size,
__out uint32_t *typep,
__out size_t *lengthp,
__out_bcount_part_opt(buffer_size, *lengthp)
uint8_t *bufferp)
{
efx_mcdi_req_t req;
uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
efx_rc_t rc;
req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
if (bufferp == NULL) {
/* Request id type and length only */
req.emr_in_buf = bufferp;
req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
req.emr_out_buf = bufferp;
req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
(void) memset(payload, 0, sizeof (payload));
} else {
/* Request full buffer */
req.emr_in_buf = bufferp;
req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
req.emr_out_buf = bufferp;
req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN);
(void) memset(bufferp, 0, req.emr_out_length);
}
efx_mcdi_execute(enp, &req);
if (req.emr_rc != 0) {
rc = req.emr_rc;
goto fail1;
}
if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
rc = EMSGSIZE;
goto fail2;
}
*typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
*lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
if (bufferp == NULL) {
/* modify length requirements to indicate to caller the extra buffering
** needed to read the complete output.
*/
*lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
} else {
/* Shift ID down to start of buffer */
memmove(bufferp,
bufferp+MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
*lengthp);
memset(bufferp+(*lengthp), 0, MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
}
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
#endif /* EFSYS_OPT_MEDFORD */
__checkReturn efx_rc_t
efx_lic_init(
__in efx_nic_t *enp)
{
efx_lic_ops_t *elop;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
switch (enp->en_family) {
#if EFSYS_OPT_SIENA
case EFX_FAMILY_SIENA:
elop = (efx_lic_ops_t *)&__efx_lic_v1_ops;
break;
#endif /* EFSYS_OPT_SIENA */
#if EFSYS_OPT_HUNTINGTON
case EFX_FAMILY_HUNTINGTON:
elop = (efx_lic_ops_t *)&__efx_lic_v2_ops;
break;
#endif /* EFSYS_OPT_HUNTINGTON */
#if EFSYS_OPT_MEDFORD
case EFX_FAMILY_MEDFORD:
elop = (efx_lic_ops_t *)&__efx_lic_v3_ops;
break;
#endif /* EFSYS_OPT_MEDFORD */
default:
EFSYS_ASSERT(0);
rc = ENOTSUP;
goto fail1;
}
enp->en_elop = elop;
enp->en_mod_flags |= EFX_MOD_LIC;
return (0);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
void
efx_lic_fini(
__in efx_nic_t *enp)
{
efx_lic_ops_t *elop = enp->en_elop;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
enp->en_elop = NULL;
enp->en_mod_flags &= ~EFX_MOD_LIC;
}
__checkReturn efx_rc_t
efx_lic_update_licenses(
__in efx_nic_t *enp)
{
efx_lic_ops_t *elop = enp->en_elop;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
if ((rc = elop->elo_update_licenses(enp)) != 0)
goto fail1;
return (0);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
__checkReturn efx_rc_t
efx_lic_get_key_stats(
__in efx_nic_t *enp,
__out efx_key_stats_t *eksp)
{
efx_lic_ops_t *elop = enp->en_elop;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
goto fail1;
return (0);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
__checkReturn efx_rc_t
efx_lic_app_state(
__in efx_nic_t *enp,
__in uint64_t app_id,
__out boolean_t *licensedp)
{
efx_lic_ops_t *elop = enp->en_elop;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
if (elop->elo_app_state == NULL) {
rc = ENOTSUP;
goto fail1;
}
if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
goto fail2;
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
__checkReturn efx_rc_t
efx_lic_get_id(
__in efx_nic_t *enp,
__in size_t buffer_size,
__out uint32_t *typep,
__out size_t *lengthp,
__out_opt uint8_t *bufferp
)
{
efx_lic_ops_t *elop = enp->en_elop;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
if (elop->elo_get_id == NULL) {
rc = ENOTSUP;
goto fail1;
}
if ((rc = elop->elo_get_id(enp, buffer_size, typep,
lengthp, bufferp)) != 0)
goto fail2;
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
return (rc);
}
#endif /* EFSYS_OPT_LICENSING */

View File

@ -36,13 +36,32 @@ __FBSDID("$FreeBSD$");
#if EFSYS_OPT_MCDI
/*
* There are three versions of the MCDI interface:
* - MCDIv0: Siena BootROM. Transport uses MCDIv1 headers.
* - MCDIv1: Siena firmware and Huntington BootROM.
* - MCDIv2: EF10 firmware (Huntington/Medford) and Medford BootROM.
* Transport uses MCDIv2 headers.
*
* MCDIv2 Header NOT_EPOCH flag
* ----------------------------
* A new epoch begins at initial startup or after an MC reboot, and defines when
* the MC should reject stale MCDI requests.
*
* The first MCDI request sent by the host should contain NOT_EPOCH=0, and all
* subsequent requests (until the next MC reboot) should contain NOT_EPOCH=1.
*
* After rebooting the MC will fail all requests with NOT_EPOCH=1 by writing a
* response with ERROR=1 and DATALEN=0 until a request is seen with NOT_EPOCH=0.
*/
#if EFSYS_OPT_SIENA
static efx_mcdi_ops_t __efx_mcdi_siena_ops = {
siena_mcdi_init, /* emco_init */
siena_mcdi_request_copyin, /* emco_request_copyin */
siena_mcdi_request_copyout, /* emco_request_copyout */
siena_mcdi_send_request, /* emco_send_request */
siena_mcdi_poll_reboot, /* emco_poll_reboot */
siena_mcdi_poll_response, /* emco_poll_response */
siena_mcdi_read_response, /* emco_read_response */
@ -56,8 +75,7 @@ static efx_mcdi_ops_t __efx_mcdi_siena_ops = {
static efx_mcdi_ops_t __efx_mcdi_ef10_ops = {
ef10_mcdi_init, /* emco_init */
ef10_mcdi_request_copyin, /* emco_request_copyin */
ef10_mcdi_request_copyout, /* emco_request_copyout */
ef10_mcdi_send_request, /* emco_send_request */
ef10_mcdi_poll_reboot, /* emco_poll_reboot */
ef10_mcdi_poll_response, /* emco_poll_response */
ef10_mcdi_read_response, /* emco_read_response */
@ -179,26 +197,16 @@ efx_mcdi_new_epoch(
}
static void
efx_mcdi_request_copyin(
efx_mcdi_send_request(
__in efx_nic_t *enp,
__in efx_mcdi_req_t *emrp,
__in unsigned int seq,
__in boolean_t ev_cpl,
__in boolean_t new_epoch)
__in void *hdrp,
__in size_t hdr_len,
__in void *sdup,
__in size_t sdu_len)
{
efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop;
emcop->emco_request_copyin(enp, emrp, seq, ev_cpl, new_epoch);
}
static void
efx_mcdi_request_copyout(
__in efx_nic_t *enp,
__in efx_mcdi_req_t *emrp)
{
efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop;
emcop->emco_request_copyout(enp, emrp);
emcop->emco_send_request(enp, hdrp, hdr_len, sdup, sdu_len);
}
static efx_rc_t
@ -241,8 +249,15 @@ efx_mcdi_request_start(
__in efx_mcdi_req_t *emrp,
__in boolean_t ev_cpl)
{
#if EFSYS_OPT_MCDI_LOGGING
const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
#endif
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
efx_dword_t hdr[2];
size_t hdr_len;
unsigned int max_version;
unsigned int seq;
unsigned int xflags;
boolean_t new_epoch;
int state;
@ -269,13 +284,64 @@ efx_mcdi_request_start(
emip->emi_poll_cnt = 0;
seq = emip->emi_seq++ & EFX_MASK32(MCDI_HEADER_SEQ);
new_epoch = emip->emi_new_epoch;
max_version = emip->emi_max_version;
EFSYS_UNLOCK(enp->en_eslp, state);
efx_mcdi_request_copyin(enp, emrp, seq, ev_cpl, new_epoch);
xflags = 0;
if (ev_cpl)
xflags |= MCDI_HEADER_XFLAGS_EVREQ;
/*
* Huntington firmware supports MCDIv2, but the Huntington BootROM only
* supports MCDIv1. Use MCDIv1 headers for MCDIv1 commands where
* possible to support this.
*/
if ((max_version >= 2) &&
((emrp->emr_cmd > MC_CMD_CMD_SPACE_ESCAPE_7) ||
(emrp->emr_in_length > MCDI_CTL_SDU_LEN_MAX_V1))) {
/* Construct MCDI v2 header */
hdr_len = sizeof (hdr);
EFX_POPULATE_DWORD_8(hdr[0],
MCDI_HEADER_CODE, MC_CMD_V2_EXTN,
MCDI_HEADER_RESYNC, 1,
MCDI_HEADER_DATALEN, 0,
MCDI_HEADER_SEQ, seq,
MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1,
MCDI_HEADER_ERROR, 0,
MCDI_HEADER_RESPONSE, 0,
MCDI_HEADER_XFLAGS, xflags);
EFX_POPULATE_DWORD_2(hdr[1],
MC_CMD_V2_EXTN_IN_EXTENDED_CMD, emrp->emr_cmd,
MC_CMD_V2_EXTN_IN_ACTUAL_LEN, emrp->emr_in_length);
} else {
/* Construct MCDI v1 header */
hdr_len = sizeof (hdr[0]);
EFX_POPULATE_DWORD_8(hdr[0],
MCDI_HEADER_CODE, emrp->emr_cmd,
MCDI_HEADER_RESYNC, 1,
MCDI_HEADER_DATALEN, emrp->emr_in_length,
MCDI_HEADER_SEQ, seq,
MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1,
MCDI_HEADER_ERROR, 0,
MCDI_HEADER_RESPONSE, 0,
MCDI_HEADER_XFLAGS, xflags);
}
#if EFSYS_OPT_MCDI_LOGGING
if (emtp->emt_logger != NULL) {
emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_REQUEST,
&hdr, hdr_len,
emrp->emr_in_buf, emrp->emr_in_length);
}
#endif /* EFSYS_OPT_MCDI_LOGGING */
efx_mcdi_send_request(enp, &hdr[0], hdr_len,
emrp->emr_in_buf, emrp->emr_in_length);
}
void
static void
efx_mcdi_read_response_header(
__in efx_nic_t *enp,
__inout efx_mcdi_req_t *emrp)
@ -384,19 +450,56 @@ efx_mcdi_read_response_header(
return;
fail3:
if (!emrp->emr_quiet)
EFSYS_PROBE(fail3);
fail2:
if (!emrp->emr_quiet)
EFSYS_PROBE(fail2);
fail1:
if (!emrp->emr_quiet)
EFSYS_PROBE1(fail1, efx_rc_t, rc);
emrp->emr_rc = rc;
emrp->emr_out_length_used = 0;
}
static void
efx_mcdi_finish_response(
__in efx_nic_t *enp,
__in efx_mcdi_req_t *emrp)
{
#if EFSYS_OPT_MCDI_LOGGING
const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
#endif /* EFSYS_OPT_MCDI_LOGGING */
efx_dword_t hdr[2];
unsigned int hdr_len;
size_t bytes;
if (emrp->emr_out_buf == NULL)
return;
/* Read the command header to detect MCDI response format */
hdr_len = sizeof (hdr[0]);
efx_mcdi_read_response(enp, &hdr[0], 0, hdr_len);
if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE) == MC_CMD_V2_EXTN) {
/*
* Read the actual payload length. The length given in the event
* is only correct for responses with the V1 format.
*/
efx_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1]));
hdr_len += sizeof (hdr[1]);
emrp->emr_out_length_used = EFX_DWORD_FIELD(hdr[1],
MC_CMD_V2_EXTN_IN_ACTUAL_LEN);
}
/* Copy payload out into caller supplied buffer */
bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length);
efx_mcdi_read_response(enp, emrp->emr_out_buf, hdr_len, bytes);
#if EFSYS_OPT_MCDI_LOGGING
if (emtp->emt_logger != NULL) {
emtp->emt_logger(emtp->emt_context,
EFX_LOG_MCDI_RESPONSE,
&hdr, hdr_len,
emrp->emr_out_buf, bytes);
}
#endif /* EFSYS_OPT_MCDI_LOGGING */
}
__checkReturn boolean_t
efx_mcdi_request_poll(
@ -444,7 +547,7 @@ efx_mcdi_request_poll(
if ((rc = emrp->emr_rc) != 0)
goto fail2;
efx_mcdi_request_copyout(enp, emrp);
efx_mcdi_finish_response(enp, emrp);
return (B_TRUE);
fail2:
@ -638,7 +741,6 @@ efx_mcdi_ev_cpl(
{
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop;
efx_mcdi_req_t *emrp;
int state;
@ -680,7 +782,7 @@ efx_mcdi_ev_cpl(
}
}
if (errcode == 0) {
emcop->emco_request_copyout(enp, emrp);
efx_mcdi_finish_response(enp, emrp);
}
emtp->emt_ev_cpl(emtp->emt_context);

View File

@ -88,11 +88,6 @@ efx_mcdi_execute_quiet(
__in efx_nic_t *enp,
__inout efx_mcdi_req_t *emrp);
extern void
efx_mcdi_read_response_header(
__in efx_nic_t *enp,
__inout efx_mcdi_req_t *emrp);
extern void
efx_mcdi_ev_cpl(
__in efx_nic_t *enp,

View File

@ -244,6 +244,7 @@ efx_nic_biu_test(
static efx_nic_ops_t __efx_nic_falcon_ops = {
falcon_nic_probe, /* eno_probe */
NULL, /* eno_board_cfg */
NULL, /* eno_set_drv_limits */
falcon_nic_reset, /* eno_reset */
falcon_nic_init, /* eno_init */
@ -263,6 +264,7 @@ static efx_nic_ops_t __efx_nic_falcon_ops = {
static efx_nic_ops_t __efx_nic_siena_ops = {
siena_nic_probe, /* eno_probe */
NULL, /* eno_board_cfg */
NULL, /* eno_set_drv_limits */
siena_nic_reset, /* eno_reset */
siena_nic_init, /* eno_init */
@ -282,6 +284,7 @@ static efx_nic_ops_t __efx_nic_siena_ops = {
static efx_nic_ops_t __efx_nic_hunt_ops = {
ef10_nic_probe, /* eno_probe */
hunt_board_cfg, /* eno_board_cfg */
ef10_nic_set_drv_limits, /* eno_set_drv_limits */
ef10_nic_reset, /* eno_reset */
ef10_nic_init, /* eno_init */
@ -297,6 +300,27 @@ static efx_nic_ops_t __efx_nic_hunt_ops = {
#endif /* EFSYS_OPT_HUNTINGTON */
#if EFSYS_OPT_MEDFORD
static efx_nic_ops_t __efx_nic_medford_ops = {
ef10_nic_probe, /* eno_probe */
medford_board_cfg, /* eno_board_cfg */
ef10_nic_set_drv_limits, /* eno_set_drv_limits */
ef10_nic_reset, /* eno_reset */
ef10_nic_init, /* eno_init */
ef10_nic_get_vi_pool, /* eno_get_vi_pool */
ef10_nic_get_bar_region, /* eno_get_bar_region */
#if EFSYS_OPT_DIAG
ef10_sram_test, /* eno_sram_test */
ef10_nic_register_test, /* eno_register_test */
#endif /* EFSYS_OPT_DIAG */
ef10_nic_fini, /* eno_fini */
ef10_nic_unprobe, /* eno_unprobe */
};
#endif /* EFSYS_OPT_MEDFORD */
__checkReturn efx_rc_t
efx_nic_create(
__in efx_family_t family,
@ -357,10 +381,29 @@ efx_nic_create(
EFX_FEATURE_MAC_HEADER_FILTERS |
EFX_FEATURE_MCDI_DMA |
EFX_FEATURE_PIO_BUFFERS |
EFX_FEATURE_FW_ASSISTED_TSO;
EFX_FEATURE_FW_ASSISTED_TSO |
EFX_FEATURE_FW_ASSISTED_TSO_V2;
break;
#endif /* EFSYS_OPT_HUNTINGTON */
#if EFSYS_OPT_MEDFORD
case EFX_FAMILY_MEDFORD:
enp->en_enop = (efx_nic_ops_t *)&__efx_nic_medford_ops;
/*
* FW_ASSISTED_TSO ommitted as Medford only supports firmware
* assisted TSO version 2, not the v1 scheme used on Huntington.
*/
enp->en_features =
EFX_FEATURE_IPV6 |
EFX_FEATURE_LINK_EVENTS |
EFX_FEATURE_PERIODIC_MAC_STATS |
EFX_FEATURE_MCDI |
EFX_FEATURE_MAC_HEADER_FILTERS |
EFX_FEATURE_MCDI_DMA |
EFX_FEATURE_PIO_BUFFERS;
break;
#endif /* EFSYS_OPT_MEDFORD */
default:
rc = ENOTSUP;
goto fail2;
@ -665,8 +708,9 @@ efx_nic_reset(
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
/*
* All modules except the MCDI, PROBE, NVRAM, VPD, MON (which we
* do not reset here) must have been shut down or never initialized.
* All modules except the MCDI, PROBE, NVRAM, VPD, MON, LIC
* (which we do not reset here) must have been shut down or never
* initialized.
*
* A rule of thumb here is: If the controller or MC reboots, is *any*
* state lost. If it's lost and needs reapplying, then the module
@ -674,7 +718,7 @@ efx_nic_reset(
*/
mod_flags = enp->en_mod_flags;
mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
EFX_MOD_VPD | EFX_MOD_MON);
EFX_MOD_VPD | EFX_MOD_MON | EFX_MOD_LIC);
EFSYS_ASSERT3U(mod_flags, ==, 0);
if (mod_flags != 0) {
rc = EINVAL;

View File

@ -42,15 +42,15 @@ static efx_nvram_ops_t __efx_nvram_falcon_ops = {
#if EFSYS_OPT_DIAG
falcon_nvram_test, /* envo_test */
#endif /* EFSYS_OPT_DIAG */
falcon_nvram_size, /* envo_size */
falcon_nvram_get_version, /* envo_get_version */
falcon_nvram_rw_start, /* envo_rw_start */
falcon_nvram_read_chunk, /* envo_read_chunk */
falcon_nvram_erase, /* envo_erase */
falcon_nvram_write_chunk, /* envo_write_chunk */
falcon_nvram_rw_finish, /* envo_rw_finish */
falcon_nvram_set_version, /* envo_set_version */
falcon_nvram_type_to_partn, /* envo_type_to_partn */
falcon_nvram_partn_size, /* envo_partn_size */
falcon_nvram_partn_rw_start, /* envo_partn_rw_start */
};
#endif /* EFSYS_OPT_FALCON */
@ -61,15 +61,15 @@ static efx_nvram_ops_t __efx_nvram_siena_ops = {
#if EFSYS_OPT_DIAG
siena_nvram_test, /* envo_test */
#endif /* EFSYS_OPT_DIAG */
siena_nvram_size, /* envo_size */
siena_nvram_get_version, /* envo_get_version */
siena_nvram_rw_start, /* envo_rw_start */
siena_nvram_read_chunk, /* envo_read_chunk */
siena_nvram_erase, /* envo_erase */
siena_nvram_write_chunk, /* envo_write_chunk */
siena_nvram_rw_finish, /* envo_rw_finish */
siena_nvram_set_version, /* envo_set_version */
siena_nvram_type_to_partn, /* envo_type_to_partn */
siena_nvram_partn_size, /* envo_partn_size */
siena_nvram_partn_rw_start, /* envo_partn_rw_start */
};
#endif /* EFSYS_OPT_SIENA */
@ -80,15 +80,15 @@ static efx_nvram_ops_t __efx_nvram_ef10_ops = {
#if EFSYS_OPT_DIAG
ef10_nvram_test, /* envo_test */
#endif /* EFSYS_OPT_DIAG */
ef10_nvram_size, /* envo_size */
ef10_nvram_get_version, /* envo_get_version */
ef10_nvram_rw_start, /* envo_rw_start */
ef10_nvram_read_chunk, /* envo_read_chunk */
ef10_nvram_erase, /* envo_erase */
ef10_nvram_write_chunk, /* envo_write_chunk */
ef10_nvram_rw_finish, /* envo_rw_finish */
ef10_nvram_set_version, /* envo_set_version */
ef10_nvram_type_to_partn, /* envo_type_to_partn */
ef10_nvram_partn_size, /* envo_partn_size */
ef10_nvram_partn_rw_start, /* envo_partn_rw_start */
};
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
@ -178,6 +178,7 @@ efx_nvram_size(
__out size_t *sizep)
{
efx_nvram_ops_t *envop = enp->en_envop;
uint32_t partn;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
@ -185,13 +186,19 @@ efx_nvram_size(
EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
if ((rc = envop->envo_size(enp, type, sizep)) != 0)
if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
goto fail1;
if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
goto fail2;
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
*sizep = 0;
return (rc);
}
@ -230,6 +237,7 @@ efx_nvram_rw_start(
__out_opt size_t *chunk_sizep)
{
efx_nvram_ops_t *envop = enp->en_envop;
uint32_t partn;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
@ -240,13 +248,18 @@ efx_nvram_rw_start(
EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0)
if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
goto fail1;
if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
goto fail2;
enp->en_nvram_locked = type;
return (0);
fail2:
EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);

View File

@ -78,14 +78,14 @@ falconsiena_rx_prefix_hash(
__in efx_rx_hash_alg_t func,
__in uint8_t *buffer);
#endif /* EFSYS_OPT_RX_SCALE */
static __checkReturn efx_rc_t
falconsiena_rx_prefix_pktlen(
__in efx_nic_t *enp,
__in uint8_t *buffer,
__out uint16_t *lengthp);
#endif /* EFSYS_OPT_RX_SCALE */
static void
falconsiena_rx_qpost(
__in efx_rxq_t *erp,

View File

@ -142,6 +142,7 @@ static efx_tx_ops_t __efx_tx_falcon_ops = {
falconsiena_tx_qdesc_post, /* etxo_qdesc_post */
falconsiena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
NULL, /* etxo_qdesc_tso_create */
NULL, /* etxo_qdesc_tso2_create */
NULL, /* etxo_qdesc_vlantci_create */
#if EFSYS_OPT_QSTATS
falconsiena_tx_qstats_update, /* etxo_qstats_update */
@ -167,6 +168,7 @@ static efx_tx_ops_t __efx_tx_siena_ops = {
falconsiena_tx_qdesc_post, /* etxo_qdesc_post */
falconsiena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
NULL, /* etxo_qdesc_tso_create */
NULL, /* etxo_qdesc_tso2_create */
NULL, /* etxo_qdesc_vlantci_create */
#if EFSYS_OPT_QSTATS
falconsiena_tx_qstats_update, /* etxo_qstats_update */
@ -192,6 +194,7 @@ static efx_tx_ops_t __efx_tx_hunt_ops = {
ef10_tx_qdesc_post, /* etxo_qdesc_post */
ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
hunt_tx_qdesc_tso_create, /* etxo_qdesc_tso_create */
ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
#if EFSYS_OPT_QSTATS
ef10_tx_qstats_update, /* etxo_qstats_update */
@ -217,6 +220,7 @@ static efx_tx_ops_t __efx_tx_medford_ops = {
ef10_tx_qdesc_post, /* etxo_qdesc_post */
ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
NULL, /* etxo_qdesc_tso_create */
ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
#if EFSYS_OPT_QSTATS
ef10_tx_qstats_update, /* etxo_qstats_update */
@ -640,6 +644,24 @@ efx_tx_qdesc_tso_create(
etxop->etxo_qdesc_tso_create(etp, ipv4_id, tcp_seq, tcp_flags, edp);
}
void
efx_tx_qdesc_tso2_create(
__in efx_txq_t *etp,
__in uint16_t ipv4_id,
__in uint32_t tcp_seq,
__in uint16_t mss,
__out_ecount(count) efx_desc_t *edp,
__in int count)
{
efx_nic_t *enp = etp->et_enp;
efx_tx_ops_t *etxop = enp->en_etxop;
EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
EFSYS_ASSERT(etxop->etxo_qdesc_tso2_create != NULL);
etxop->etxo_qdesc_tso2_create(etp, ipv4_id, tcp_seq, mss, edp, count);
}
void
efx_tx_qdesc_vlantci_create(
__in efx_txq_t *etp,

View File

@ -669,7 +669,7 @@ efx_vpd_hunk_next(
__in size_t size,
__out efx_vpd_tag_t *tagp,
__out efx_vpd_keyword_t *keywordp,
__out_bcount_opt(*paylenp) unsigned int *payloadp,
__out_opt unsigned int *payloadp,
__out_opt uint8_t *paylenp,
__inout unsigned int *contp)
{
@ -689,12 +689,18 @@ efx_vpd_hunk_next(
if ((rc = efx_vpd_next_tag(data, size, &offset,
&tag, &taglen)) != 0)
goto fail1;
if (tag == EFX_VPD_END)
if (tag == EFX_VPD_END) {
keyword = 0;
paylen = 0;
index = 0;
break;
}
if (tag == EFX_VPD_ID) {
if (index == *contp) {
if (index++ == *contp) {
EFSYS_ASSERT3U(taglen, <, 0x100);
keyword = 0;
paylen = (uint8_t)MIN(taglen, 0xff);
goto done;
@ -705,7 +711,7 @@ efx_vpd_hunk_next(
taglen, pos, &keyword, &keylen)) != 0)
goto fail2;
if (index == *contp) {
if (index++ == *contp) {
offset += pos + 3;
paylen = keylen;
@ -717,9 +723,6 @@ efx_vpd_hunk_next(
offset += taglen;
}
*contp = 0;
return (0);
done:
*tagp = tag;
*keywordp = keyword;
@ -728,7 +731,7 @@ efx_vpd_hunk_next(
if (paylenp != NULL)
*paylenp = paylen;
++(*contp);
*contp = index;
return (0);
fail2:

View File

@ -444,9 +444,9 @@ ef10_ev_qmoderate(
eep->ee_index, &dword, 0);
} else {
EFX_POPULATE_DWORD_2(dword,
FRF_CZ_TC_TIMER_MODE, mode,
FRF_CZ_TC_TIMER_VAL, timer_val);
EFX_BAR_TBL_WRITED(enp, FR_BZ_TIMER_COMMAND_REGP0,
ERF_DZ_TC_TIMER_MODE, mode,
ERF_DZ_TC_TIMER_VAL, timer_val);
EFX_BAR_TBL_WRITED(enp, ER_DZ_EVQ_TMR_REG,
eep->ee_index, &dword, 0);
}

Some files were not shown because too many files have changed in this diff Show More