Merge ^/head r293850 through r294089.
This commit is contained in:
commit
7f38eb34e2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/clang380-import/; revision=294096
@ -283,7 +283,6 @@ static int
|
|||||||
equiv_su(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
|
equiv_su(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
|
||||||
{
|
{
|
||||||
mlist_t *ml1 = stdp->t_members, *ml2 = ttdp->t_members;
|
mlist_t *ml1 = stdp->t_members, *ml2 = ttdp->t_members;
|
||||||
mlist_t *olm1 = NULL;
|
|
||||||
|
|
||||||
while (ml1 && ml2) {
|
while (ml1 && ml2) {
|
||||||
if (ml1->ml_offset != ml2->ml_offset ||
|
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))
|
!equiv_node(ml1->ml_type, ml2->ml_type, ed))
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
olm1 = ml1;
|
|
||||||
ml1 = ml1->ml_next;
|
ml1 = ml1->ml_next;
|
||||||
ml2 = ml2->ml_next;
|
ml2 = ml2->ml_next;
|
||||||
}
|
}
|
||||||
|
@ -1610,7 +1610,7 @@ initialize_options(Options * options)
|
|||||||
options->tun_remote = -1;
|
options->tun_remote = -1;
|
||||||
options->local_command = NULL;
|
options->local_command = NULL;
|
||||||
options->permit_local_command = -1;
|
options->permit_local_command = -1;
|
||||||
options->use_roaming = -1;
|
options->use_roaming = 0;
|
||||||
options->visual_host_key = -1;
|
options->visual_host_key = -1;
|
||||||
options->ip_qos_interactive = -1;
|
options->ip_qos_interactive = -1;
|
||||||
options->ip_qos_bulk = -1;
|
options->ip_qos_bulk = -1;
|
||||||
@ -1788,8 +1788,7 @@ fill_default_options(Options * options)
|
|||||||
options->tun_remote = SSH_TUNID_ANY;
|
options->tun_remote = SSH_TUNID_ANY;
|
||||||
if (options->permit_local_command == -1)
|
if (options->permit_local_command == -1)
|
||||||
options->permit_local_command = 0;
|
options->permit_local_command = 0;
|
||||||
if (options->use_roaming == -1)
|
options->use_roaming = 0;
|
||||||
options->use_roaming = 1;
|
|
||||||
if (options->visual_host_key == -1)
|
if (options->visual_host_key == -1)
|
||||||
options->visual_host_key = 0;
|
options->visual_host_key = 0;
|
||||||
if (options->ip_qos_interactive == -1)
|
if (options->ip_qos_interactive == -1)
|
||||||
|
@ -82,10 +82,6 @@ BIN1+= apmd.conf
|
|||||||
BIN1+= auto_master
|
BIN1+= auto_master
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
.if ${MK_BSNMP} != "no"
|
|
||||||
BIN1+= snmpd.config
|
|
||||||
.endif
|
|
||||||
|
|
||||||
.if ${MK_FREEBSD_UPDATE} != "no"
|
.if ${MK_FREEBSD_UPDATE} != "no"
|
||||||
BIN1+= freebsd-update.conf
|
BIN1+= freebsd-update.conf
|
||||||
.endif
|
.endif
|
||||||
@ -219,6 +215,11 @@ distribution:
|
|||||||
${BIN2} ${DESTDIR}/etc; \
|
${BIN2} ${DESTDIR}/etc; \
|
||||||
${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 600 \
|
${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 600 \
|
||||||
master.passwd nsmb.conf opieaccess ${DESTDIR}/etc;
|
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"
|
.if ${MK_AT} == "no"
|
||||||
sed -i "" -e 's;.*/usr/libexec/atrun;#&;' ${DESTDIR}/etc/crontab
|
sed -i "" -e 's;.*/usr/libexec/atrun;#&;' ${DESTDIR}/etc/crontab
|
||||||
.endif
|
.endif
|
||||||
|
@ -36,15 +36,15 @@ mountcritlocal_start()
|
|||||||
done
|
done
|
||||||
mount_excludes=${mount_excludes%,}
|
mount_excludes=${mount_excludes%,}
|
||||||
|
|
||||||
# Originally, root mount hold had to be released before mounting the root
|
# Originally, root mount hold had to be released before mounting
|
||||||
# filesystem. This delayed the boot, so it was changed to only wait if
|
# the root filesystem. This delayed the boot, so it was changed
|
||||||
# the root device isn't readily available. This can result in this script
|
# to only wait if the root device isn't readily available. This
|
||||||
# executing before all the devices - such as graid(8) - are available.
|
# can result in this script executing before all the devices - such
|
||||||
# Thus, should the mount fail, we will wait for the root mount hold release
|
# as graid(8) - are available. Thus, should the mount fail,
|
||||||
# and retry.
|
# we will wait for the root mount hold release and retry.
|
||||||
mount -a -t ${mount_excludes}
|
mount -a -t ${mount_excludes}
|
||||||
err=$?
|
err=$?
|
||||||
if [ $? -ne 0 ]; then
|
if [ ${err} -ne 0 ]; then
|
||||||
echo
|
echo
|
||||||
echo 'Mounting /etc/fstab filesystems failed,' \
|
echo 'Mounting /etc/fstab filesystems failed,' \
|
||||||
'will retry after root mount hold release'
|
'will retry after root mount hold release'
|
||||||
|
@ -6,4 +6,8 @@ LLVM_SRCS= ${.CURDIR}/../../../contrib/llvm
|
|||||||
|
|
||||||
INTERNALLIB=
|
INTERNALLIB=
|
||||||
|
|
||||||
|
.if ${MACHINE_CPUARCH} == "arm"
|
||||||
|
STATIC_CXXFLAGS+= -mlong-calls
|
||||||
|
.endif
|
||||||
|
|
||||||
.include <bsd.lib.mk>
|
.include <bsd.lib.mk>
|
||||||
|
@ -6,6 +6,9 @@ _LIBCXXRTDIR= ${.CURDIR}/../../contrib/libcxxrt
|
|||||||
HDRDIR= ${.CURDIR}/../../contrib/libc++/include
|
HDRDIR= ${.CURDIR}/../../contrib/libc++/include
|
||||||
SRCDIR= ${.CURDIR}/../../contrib/libc++/src
|
SRCDIR= ${.CURDIR}/../../contrib/libc++/src
|
||||||
CXXINCLUDEDIR= ${INCLUDEDIR}/c++/v${SHLIB_MAJOR}
|
CXXINCLUDEDIR= ${INCLUDEDIR}/c++/v${SHLIB_MAJOR}
|
||||||
|
.if ${MACHINE_CPUARCH} == "arm"
|
||||||
|
STATIC_CXXFLAGS+= -mlong-calls
|
||||||
|
.endif
|
||||||
|
|
||||||
.PATH: ${SRCDIR}
|
.PATH: ${SRCDIR}
|
||||||
|
|
||||||
|
@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
base = leaf; \
|
base = leaf; \
|
||||||
path_init(&path); \
|
path_init(&path); \
|
||||||
} \
|
} \
|
||||||
result = &(*leaf)->key; \
|
|
||||||
path_taking_right(&path); \
|
path_taking_right(&path); \
|
||||||
leaf = &(*leaf)->rlink; \
|
leaf = &(*leaf)->rlink; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -54,7 +54,7 @@ wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
|
|||||||
size_t dlen;
|
size_t dlen;
|
||||||
|
|
||||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
/* 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++;
|
d++;
|
||||||
dlen = d - dst;
|
dlen = d - dst;
|
||||||
n = siz - dlen;
|
n = siz - dlen;
|
||||||
|
@ -48,7 +48,7 @@ wcsncat(wchar_t * __restrict s1, const wchar_t * __restrict s2, size_t n)
|
|||||||
p++;
|
p++;
|
||||||
q = p;
|
q = p;
|
||||||
r = s2;
|
r = s2;
|
||||||
while (*r && n) {
|
while (n && *r) {
|
||||||
*q++ = *r++;
|
*q++ = *r++;
|
||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
.\" @(#)stat.2 8.4 (Berkeley) 5/1/95
|
.\" @(#)stat.2 8.4 (Berkeley) 5/1/95
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd June 2, 2012
|
.Dd January 14, 2016
|
||||||
.Dt STAT 2
|
.Dt STAT 2
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -40,12 +40,11 @@
|
|||||||
.Sh LIBRARY
|
.Sh LIBRARY
|
||||||
.Lb libc
|
.Lb libc
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.In sys/types.h
|
|
||||||
.In sys/stat.h
|
.In sys/stat.h
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn stat "const char *path" "struct stat *sb"
|
.Fn stat "const char * restrict path" "struct stat * restrict sb"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn lstat "const char *path" "struct stat *sb"
|
.Fn lstat "const char * restrict path" "struct stat * restrict sb"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn fstat "int fd" "struct stat *sb"
|
.Fn fstat "int fd" "struct stat *sb"
|
||||||
.Ft int
|
.Ft int
|
||||||
|
@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <dialog.h>
|
#include <dialog.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <locale.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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 */
|
/* Reads: label_size pbar_size pprompt aprompt dpv_nfiles */
|
||||||
/* Inits: dheight and dwidth */
|
/* 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) {
|
if (!debug) {
|
||||||
/* Internally create the initial `--gauge' prompt text */
|
/* Internally create the initial `--gauge' prompt text */
|
||||||
dprompt_recreate(file_list, (struct dpv_file_node *)NULL, 0);
|
dprompt_recreate(file_list, (struct dpv_file_node *)NULL, 0);
|
||||||
|
@ -38,6 +38,9 @@
|
|||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* localeconv(3) */
|
||||||
|
#define LC_NUMERIC_DEFAULT "en_US.ISO8859-1"
|
||||||
|
|
||||||
/* Data to process */
|
/* Data to process */
|
||||||
extern long long dpv_overall_read;
|
extern long long dpv_overall_read;
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ _Static_assert(NBPDR == I386_NBPDR, "NBPDR mismatch");
|
|||||||
|
|
||||||
_Static_assert(PG_V == I386_PG_V, "PG_V mismatch");
|
_Static_assert(PG_V == I386_PG_V, "PG_V mismatch");
|
||||||
_Static_assert(PG_PS == I386_PG_PS, "PG_PS 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");
|
_Static_assert(PG_PS_FRAME == I386_PG_PS_FRAME, "PG_PS_FRAME mismatch");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* mdXhl.c * ----------------------------------------------------------------------------
|
/* mdXhl.c
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
* <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
|
* <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
|
* 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];
|
unsigned char buffer[16*1024];
|
||||||
MDX_CTX ctx;
|
MDX_CTX ctx;
|
||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
int f, i, e;
|
int fd, readrv, e;
|
||||||
off_t n;
|
off_t remain;
|
||||||
|
|
||||||
|
if (len < 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
MDXInit(&ctx);
|
MDXInit(&ctx);
|
||||||
f = open(filename, O_RDONLY);
|
fd = open(filename, O_RDONLY);
|
||||||
if (f < 0)
|
if (fd < 0)
|
||||||
return 0;
|
return NULL;
|
||||||
if (fstat(f, &stbuf) < 0) {
|
if (ofs != 0) {
|
||||||
i = -1;
|
errno = 0;
|
||||||
goto error;
|
if (lseek(fd, ofs, SEEK_SET) != ofs ||
|
||||||
|
(ofs == -1 && errno != 0)) {
|
||||||
|
readrv = -1;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ofs > stbuf.st_size)
|
remain = len;
|
||||||
ofs = stbuf.st_size;
|
readrv = 0;
|
||||||
if ((len == 0) || (len > stbuf.st_size - ofs))
|
while (len == 0 || remain > 0) {
|
||||||
len = stbuf.st_size - ofs;
|
if (len == 0 || remain > sizeof(buffer))
|
||||||
if (lseek(f, ofs, SEEK_SET) < 0) {
|
readrv = read(fd, buffer, sizeof(buffer));
|
||||||
i = -1;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
n = len;
|
|
||||||
i = 0;
|
|
||||||
while (n > 0) {
|
|
||||||
if (n > sizeof(buffer))
|
|
||||||
i = read(f, buffer, sizeof(buffer));
|
|
||||||
else
|
else
|
||||||
i = read(f, buffer, n);
|
readrv = read(fd, buffer, remain);
|
||||||
if (i <= 0)
|
if (readrv <= 0)
|
||||||
break;
|
break;
|
||||||
MDXUpdate(&ctx, buffer, i);
|
MDXUpdate(&ctx, buffer, readrv);
|
||||||
n -= i;
|
remain -= readrv;
|
||||||
}
|
}
|
||||||
error:
|
error:
|
||||||
e = errno;
|
e = errno;
|
||||||
close(f);
|
close(fd);
|
||||||
errno = e;
|
errno = e;
|
||||||
if (i < 0)
|
if (readrv < 0)
|
||||||
return 0;
|
return NULL;
|
||||||
return (MDXEnd(&ctx, buf));
|
return (MDXEnd(&ctx, buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ int _umtx_op_err(void *obj, int op, u_long val, void *uaddr, void *uaddr2)
|
|||||||
void
|
void
|
||||||
_thr_umutex_init(struct umutex *mtx)
|
_thr_umutex_init(struct umutex *mtx)
|
||||||
{
|
{
|
||||||
static struct umutex default_mtx = DEFAULT_UMUTEX;
|
static const struct umutex default_mtx = DEFAULT_UMUTEX;
|
||||||
|
|
||||||
*mtx = default_mtx;
|
*mtx = default_mtx;
|
||||||
}
|
}
|
||||||
@ -50,7 +50,8 @@ _thr_umutex_init(struct umutex *mtx)
|
|||||||
void
|
void
|
||||||
_thr_urwlock_init(struct urwlock *rwl)
|
_thr_urwlock_init(struct urwlock *rwl)
|
||||||
{
|
{
|
||||||
static struct urwlock default_rwl = DEFAULT_URWLOCK;
|
static const struct urwlock default_rwl = DEFAULT_URWLOCK;
|
||||||
|
|
||||||
*rwl = default_rwl;
|
*rwl = default_rwl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
# $OpenBSD: pf.conf,v 1.34 2007/02/24 19:30:59 millert Exp $
|
# $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.
|
# 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
|
# Remember to set gateway_enable="YES" and/or ipv6_gateway_enable="YES"
|
||||||
# in /etc/sysctl.conf if packets are to be forwarded between interfaces.
|
# in /etc/rc.conf if packets are to be forwarded between interfaces.
|
||||||
|
|
||||||
#ext_if="ext0"
|
#ext_if="ext0"
|
||||||
#int_if="int0"
|
#int_if="int0"
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd November 5, 2015
|
.Dd January 14, 2016
|
||||||
.Dt DDB 4
|
.Dt DDB 4
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -1435,6 +1435,47 @@ The NMI allows one to break into the debugger on a wedged machine to
|
|||||||
diagnose problems.
|
diagnose problems.
|
||||||
Other bus' bridge chipsets may be able to generate NMI using bus specific
|
Other bus' bridge chipsets may be able to generate NMI using bus specific
|
||||||
methods.
|
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
|
.Sh FILES
|
||||||
Header files mentioned in this manual page can be found below
|
Header files mentioned in this manual page can be found below
|
||||||
.Pa /usr/include
|
.Pa /usr/include
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd January 7, 2016
|
.Dd January 14, 2016
|
||||||
.Dt IOAT 4
|
.Dt IOAT 4
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -134,7 +134,7 @@ Null operations do nothing, but may be used to test the interrupt and callback
|
|||||||
mechanism.
|
mechanism.
|
||||||
.Pp
|
.Pp
|
||||||
All operations can optionally trigger an interrupt at completion with the
|
All operations can optionally trigger an interrupt at completion with the
|
||||||
.Ar DMA_EN_INT
|
.Ar DMA_INT_EN
|
||||||
flag.
|
flag.
|
||||||
For example, a user might submit multiple operations to the same channel and
|
For example, a user might submit multiple operations to the same channel and
|
||||||
only enable an interrupt and callback for the last operation.
|
only enable an interrupt and callback for the last operation.
|
||||||
@ -160,6 +160,17 @@ flag.
|
|||||||
.Ar DMA_NO_WAIT
|
.Ar DMA_NO_WAIT
|
||||||
may return NULL.)
|
may return NULL.)
|
||||||
.Pp
|
.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
|
All operations, as well as
|
||||||
.Fn ioat_get_dmaengine ,
|
.Fn ioat_get_dmaengine ,
|
||||||
can return NULL in special circumstances.
|
can return NULL in special circumstances.
|
||||||
|
@ -121,8 +121,10 @@ If a packet is dropped, the
|
|||||||
counter is incremented and the local sender receives ENOBUFS.
|
counter is incremented and the local sender receives ENOBUFS.
|
||||||
The value must be greater than or equal to 0.
|
The value must be greater than or equal to 0.
|
||||||
.It Va hw.sfxge.tso_fw_assisted
|
.It Va hw.sfxge.tso_fw_assisted
|
||||||
Enable/disable usage of FW-assisted TSO if supported by NIC firmware.
|
Bitmask to enable/disable usage of FW-assisted TSO version if supported
|
||||||
Enabled by default.
|
by NIC firmware.
|
||||||
|
FATSOv1 (bit 0) and FATSOv2 (bit 1) are supported.
|
||||||
|
All enabled by default.
|
||||||
.It Va hw.sfxge.N.max_rss_channels
|
.It Va hw.sfxge.N.max_rss_channels
|
||||||
The maximum number of allocated RSS channels for the Nth adapter.
|
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
|
If set to 0 or unset, the number of channels is determined by the number
|
||||||
|
@ -164,10 +164,11 @@ SSP_CFLAGS?= -fstack-protector
|
|||||||
CFLAGS+= ${SSP_CFLAGS}
|
CFLAGS+= ${SSP_CFLAGS}
|
||||||
.endif # SSP && !ARM && !MIPS
|
.endif # SSP && !ARM && !MIPS
|
||||||
|
|
||||||
# Allow user-specified additional warning flags, plus compiler specific flag overrides.
|
# Allow user-specified additional warning flags, plus compiler and file
|
||||||
# Unless we've overriden this...
|
# specific flag overrides, unless we've overriden this...
|
||||||
.if ${MK_WARNS} != "no"
|
.if ${MK_WARNS} != "no"
|
||||||
CFLAGS+= ${CWARNFLAGS} ${CWARNFLAGS.${COMPILER_TYPE}}
|
CFLAGS+= ${CWARNFLAGS} ${CWARNFLAGS.${COMPILER_TYPE}}
|
||||||
|
CFLAGS+= ${CWARNFLAGS.${.IMPSRC:T}}
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
CFLAGS+= ${CFLAGS.${COMPILER_TYPE}}
|
CFLAGS+= ${CFLAGS.${COMPILER_TYPE}}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* DO NOT EDIT-- this file is automatically generated.
|
* DO NOT EDIT-- this file is automatically generated.
|
||||||
* $FreeBSD$
|
* $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_
|
#ifndef _LINUX_SYSPROTO_H_
|
||||||
@ -966,7 +966,7 @@ struct linux_set_robust_list_args {
|
|||||||
};
|
};
|
||||||
struct linux_get_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 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 *)];
|
char len_l_[PADL_(l_size_t *)]; l_size_t * len; char len_r_[PADR_(l_size_t *)];
|
||||||
};
|
};
|
||||||
struct linux_splice_args {
|
struct linux_splice_args {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* DO NOT EDIT-- this file is automatically generated.
|
* DO NOT EDIT-- this file is automatically generated.
|
||||||
* $FreeBSD$
|
* $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
|
#define LINUX_SYS_read 0
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* DO NOT EDIT-- this file is automatically generated.
|
* DO NOT EDIT-- this file is automatically generated.
|
||||||
* $FreeBSD$
|
* $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[] = {
|
const char *linux_syscallnames[] = {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* DO NOT EDIT-- this file is automatically generated.
|
* DO NOT EDIT-- this file is automatically generated.
|
||||||
* $FreeBSD$
|
* $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>
|
#include <sys/param.h>
|
||||||
|
@ -2020,7 +2020,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
|||||||
case 274: {
|
case 274: {
|
||||||
struct linux_get_robust_list_args *p = params;
|
struct linux_get_robust_list_args *p = params;
|
||||||
iarg[0] = p->pid; /* l_int */
|
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 * */
|
uarg[2] = (intptr_t) p->len; /* l_size_t * */
|
||||||
*n_args = 3;
|
*n_args = 3;
|
||||||
break;
|
break;
|
||||||
@ -5347,7 +5347,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
|||||||
p = "l_int";
|
p = "l_int";
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
p = "struct linux_robust_list_head *";
|
p = "struct linux_robust_list_head **";
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
p = "l_size_t *";
|
p = "l_size_t *";
|
||||||
|
@ -461,8 +461,8 @@
|
|||||||
272 AUE_NULL STD { int linux_unshare(void); }
|
272 AUE_NULL STD { int linux_unshare(void); }
|
||||||
273 AUE_NULL STD { int linux_set_robust_list(struct linux_robust_list_head *head, \
|
273 AUE_NULL STD { int linux_set_robust_list(struct linux_robust_list_head *head, \
|
||||||
l_size_t len); }
|
l_size_t len); }
|
||||||
274 AUE_NULL STD { int linux_get_robust_list(l_int pid, struct linux_robust_list_head *head, \
|
274 AUE_NULL STD { int linux_get_robust_list(l_int pid, \
|
||||||
l_size_t *len); }
|
struct linux_robust_list_head **head, l_size_t *len); }
|
||||||
275 AUE_NULL STD { int linux_splice(void); }
|
275 AUE_NULL STD { int linux_splice(void); }
|
||||||
276 AUE_NULL STD { int linux_tee(void); }
|
276 AUE_NULL STD { int linux_tee(void); }
|
||||||
277 AUE_NULL STD { int linux_sync_file_range(void); }
|
277 AUE_NULL STD { int linux_sync_file_range(void); }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* DO NOT EDIT-- this file is automatically generated.
|
* DO NOT EDIT-- this file is automatically generated.
|
||||||
* $FreeBSD$
|
* $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_
|
#ifndef _LINUX32_SYSPROTO_H_
|
||||||
@ -1023,7 +1023,7 @@ struct linux_set_robust_list_args {
|
|||||||
};
|
};
|
||||||
struct linux_get_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 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 *)];
|
char len_l_[PADL_(l_size_t *)]; l_size_t * len; char len_r_[PADR_(l_size_t *)];
|
||||||
};
|
};
|
||||||
struct linux_splice_args {
|
struct linux_splice_args {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* DO NOT EDIT-- this file is automatically generated.
|
* DO NOT EDIT-- this file is automatically generated.
|
||||||
* $FreeBSD$
|
* $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
|
#define LINUX32_SYS_linux_exit 1
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* DO NOT EDIT-- this file is automatically generated.
|
* DO NOT EDIT-- this file is automatically generated.
|
||||||
* $FreeBSD$
|
* $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[] = {
|
const char *linux32_syscallnames[] = {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* DO NOT EDIT-- this file is automatically generated.
|
* DO NOT EDIT-- this file is automatically generated.
|
||||||
* $FreeBSD$
|
* $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"
|
#include "opt_compat.h"
|
||||||
|
@ -2122,7 +2122,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
|||||||
case 312: {
|
case 312: {
|
||||||
struct linux_get_robust_list_args *p = params;
|
struct linux_get_robust_list_args *p = params;
|
||||||
iarg[0] = p->pid; /* l_int */
|
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 * */
|
uarg[2] = (intptr_t) p->len; /* l_size_t * */
|
||||||
*n_args = 3;
|
*n_args = 3;
|
||||||
break;
|
break;
|
||||||
@ -5551,7 +5551,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
|||||||
p = "l_int";
|
p = "l_int";
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
p = "struct linux_robust_list_head *";
|
p = "struct linux_robust_list_head **";
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
p = "l_size_t *";
|
p = "l_size_t *";
|
||||||
|
@ -520,8 +520,8 @@
|
|||||||
; linux 2.6.17:
|
; linux 2.6.17:
|
||||||
311 AUE_NULL STD { int linux_set_robust_list(struct linux_robust_list_head *head, \
|
311 AUE_NULL STD { int linux_set_robust_list(struct linux_robust_list_head *head, \
|
||||||
l_size_t len); }
|
l_size_t len); }
|
||||||
312 AUE_NULL STD { int linux_get_robust_list(l_int pid, struct linux_robust_list_head *head, \
|
312 AUE_NULL STD { int linux_get_robust_list(l_int pid, \
|
||||||
l_size_t *len); }
|
struct linux_robust_list_head **head, l_size_t *len); }
|
||||||
313 AUE_NULL STD { int linux_splice(void); }
|
313 AUE_NULL STD { int linux_splice(void); }
|
||||||
314 AUE_NULL STD { int linux_sync_file_range(void); }
|
314 AUE_NULL STD { int linux_sync_file_range(void); }
|
||||||
315 AUE_NULL STD { int linux_tee(void); }
|
315 AUE_NULL STD { int linux_tee(void); }
|
||||||
|
@ -446,6 +446,9 @@ at91_mci_attach(device_t dev)
|
|||||||
CTLFLAG_RW, &sc->allow_overclock, 0,
|
CTLFLAG_RW, &sc->allow_overclock, 0,
|
||||||
"Allow up to 30MHz clock for 25MHz request when next highest speed 15MHz or less.");
|
"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
|
* 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
|
* 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);
|
WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN);
|
||||||
} else {
|
} else {
|
||||||
len = min(BBSIZE, remaining);
|
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);
|
at91_bswap_buf(sc, sc->bbuf_vaddr[0], data->data, len);
|
||||||
err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0],
|
err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0],
|
||||||
sc->bbuf_vaddr[0], len, at91_mci_getaddr,
|
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");
|
panic("IO write dmamap_load failed\n");
|
||||||
bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0],
|
bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0],
|
||||||
BUS_DMASYNC_PREWRITE);
|
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_TPR,paddr);
|
||||||
WR4(sc, PDC_TCR, len / 4);
|
WR4(sc, PDC_TCR, (len < 12) ? 3 : len / 4);
|
||||||
sc->bbuf_len[0] = len;
|
sc->bbuf_len[0] = len;
|
||||||
remaining -= len;
|
remaining -= len;
|
||||||
if (remaining == 0) {
|
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_dmamap_sync(sc->dmatag, sc->bbuf_map[1],
|
||||||
BUS_DMASYNC_PREWRITE);
|
BUS_DMASYNC_PREWRITE);
|
||||||
WR4(sc, PDC_TNPR, paddr);
|
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;
|
sc->bbuf_len[1] = len;
|
||||||
remaining -= len;
|
remaining -= len;
|
||||||
}
|
}
|
||||||
|
@ -136,11 +136,3 @@ device wlan_amrr # AMRR transmit rate control algorithm
|
|||||||
|
|
||||||
# Flattened Device Tree
|
# Flattened Device Tree
|
||||||
options FDT # Configure using FDT/DTB data
|
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
|
|
||||||
|
@ -125,14 +125,6 @@ device u3g # USB modems
|
|||||||
#device wlan_tkip # 802.11 TKIP support
|
#device wlan_tkip # 802.11 TKIP support
|
||||||
#device wlan_amrr # AMRR transmit rate control algorithm
|
#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 vt
|
||||||
device kbdmux
|
device kbdmux
|
||||||
device ukbd
|
device ukbd
|
||||||
|
@ -237,7 +237,7 @@ void unload(void);
|
|||||||
struct preloaded_file *file_alloc(void);
|
struct preloaded_file *file_alloc(void);
|
||||||
struct preloaded_file *file_findfile(const char *name, const char *type);
|
struct preloaded_file *file_findfile(const char *name, const char *type);
|
||||||
struct file_metadata *file_findmetadata(struct preloaded_file *fp, int 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_discard(struct preloaded_file *fp);
|
||||||
void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p);
|
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,
|
int file_addmodule(struct preloaded_file *fp, char *modname, int version,
|
||||||
|
@ -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.
|
* no arguments or anything.
|
||||||
*/
|
*/
|
||||||
struct preloaded_file *
|
struct preloaded_file *
|
||||||
file_loadraw(char *name, char *type, int insert)
|
file_loadraw(const char *fname, char *type, int insert)
|
||||||
{
|
{
|
||||||
struct preloaded_file *fp;
|
struct preloaded_file *fp;
|
||||||
char *cp;
|
char *name;
|
||||||
int fd, got;
|
int fd, got;
|
||||||
vm_offset_t laddr;
|
vm_offset_t laddr;
|
||||||
|
|
||||||
@ -406,12 +406,11 @@ file_loadraw(char *name, char *type, int insert)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* locate the file on the load path */
|
/* locate the file on the load path */
|
||||||
cp = file_search(name, NULL);
|
name = file_search(fname, NULL);
|
||||||
if (cp == NULL) {
|
if (name == NULL) {
|
||||||
sprintf(command_errbuf, "can't find '%s'", name);
|
sprintf(command_errbuf, "can't find '%s'", fname);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
name = cp;
|
|
||||||
|
|
||||||
if ((fd = open(name, O_RDONLY)) < 0) {
|
if ((fd = open(name, O_RDONLY)) < 0) {
|
||||||
sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno));
|
sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno));
|
||||||
|
@ -187,8 +187,15 @@ fsread(ufs_ino_t inode, void *buf, size_t nbyte)
|
|||||||
|
|
||||||
blkbuf = dmadat->blkbuf;
|
blkbuf = dmadat->blkbuf;
|
||||||
indbuf = dmadat->indbuf;
|
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;
|
inomap = 0;
|
||||||
|
dsk_meta = 0;
|
||||||
for (n = 0; sblock_try[n] != -1; n++) {
|
for (n = 0; sblock_try[n] != -1; n++) {
|
||||||
if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
|
if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
|
||||||
SBLOCKSIZE / DEV_BSIZE))
|
SBLOCKSIZE / DEV_BSIZE))
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
.include <src.opts.mk>
|
.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 ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm"
|
||||||
.if ${MK_FDT} != "no"
|
.if ${MK_FDT} != "no"
|
||||||
@ -13,7 +14,10 @@ SUBDIR+= fdt
|
|||||||
.if ${MACHINE_CPUARCH} == "aarch64" || \
|
.if ${MACHINE_CPUARCH} == "aarch64" || \
|
||||||
${MACHINE_CPUARCH} == "amd64" || \
|
${MACHINE_CPUARCH} == "amd64" || \
|
||||||
${MACHINE_CPUARCH} == "arm"
|
${MACHINE_CPUARCH} == "arm"
|
||||||
SUBDIR+= loader boot1
|
SUBDIR+= libefi loader boot1
|
||||||
.endif
|
.endif
|
||||||
|
|
||||||
|
.endif # ${COMPILER_TYPE} != "gcc"
|
||||||
|
|
||||||
.include <bsd.subdir.mk>
|
.include <bsd.subdir.mk>
|
||||||
|
|
||||||
|
@ -2,10 +2,7 @@
|
|||||||
|
|
||||||
MAN=
|
MAN=
|
||||||
|
|
||||||
.include <bsd.own.mk>
|
.include <src.opts.mk>
|
||||||
|
|
||||||
# In-tree GCC does not support __attribute__((ms_abi)).
|
|
||||||
.if ${COMPILER_TYPE} != "gcc"
|
|
||||||
|
|
||||||
MK_SSP= no
|
MK_SSP= no
|
||||||
|
|
||||||
@ -13,14 +10,35 @@ PROG= boot1.sym
|
|||||||
INTERNALPROG=
|
INTERNALPROG=
|
||||||
WARNS?= 6
|
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
|
# 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.
|
||||||
CFLAGS+= -I${.CURDIR}/../include
|
CFLAGS+= -I${.CURDIR}/../include
|
||||||
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
|
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
|
||||||
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
|
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
|
||||||
CFLAGS+= -I${.CURDIR}/../../..
|
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
|
# Always add MI sources and REGULAR efi loader bits
|
||||||
.PATH: ${.CURDIR}/../loader/arch/${MACHINE}
|
.PATH: ${.CURDIR}/../loader/arch/${MACHINE}
|
||||||
@ -96,8 +114,6 @@ boot1.efifat: boot1.efi
|
|||||||
|
|
||||||
CLEANFILES= boot1.efi boot1.efifat
|
CLEANFILES= boot1.efi boot1.efifat
|
||||||
|
|
||||||
.endif # ${COMPILER_TYPE} != "gcc"
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
|
||||||
beforedepend ${OBJS}: machine
|
beforedepend ${OBJS}: machine
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
* Copyright (c) 2014 Nathan Whitehorn
|
* Copyright (c) 2014 Nathan Whitehorn
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
|
* Copyright (c) 2015 Eric McCorkle
|
||||||
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms are freely
|
* Redistribution and use in source and binary forms are freely
|
||||||
* permitted provided that the above copyright notice and this
|
* permitted provided that the above copyright notice and this
|
||||||
@ -21,7 +23,6 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/dirent.h>
|
|
||||||
#include <machine/elf.h>
|
#include <machine/elf.h>
|
||||||
#include <machine/stdarg.h>
|
#include <machine/stdarg.h>
|
||||||
#include <stand.h>
|
#include <stand.h>
|
||||||
@ -29,19 +30,32 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <efi.h>
|
#include <efi.h>
|
||||||
#include <eficonsctl.h>
|
#include <eficonsctl.h>
|
||||||
|
|
||||||
|
#include "boot_module.h"
|
||||||
|
|
||||||
#define _PATH_LOADER "/boot/loader.efi"
|
#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);
|
void putchar(int c);
|
||||||
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
|
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 try_load(const boot_module_t* mod);
|
||||||
static void load(const char *fname);
|
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_HANDLE *image;
|
||||||
|
|
||||||
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
|
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 LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
|
||||||
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
|
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
|
||||||
|
|
||||||
static EFI_BLOCK_IO *bootdev;
|
/*
|
||||||
static EFI_DEVICE_PATH *bootdevpath;
|
* Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
|
||||||
static EFI_HANDLE *bootdevhandle;
|
* memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
|
||||||
|
* EFI methods.
|
||||||
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
|
*/
|
||||||
|
void *
|
||||||
|
Malloc(size_t len, const char *file __unused, int line __unused)
|
||||||
{
|
{
|
||||||
EFI_HANDLE handles[128];
|
void *out;
|
||||||
EFI_BLOCK_IO *blkio;
|
|
||||||
UINTN i, nparts = sizeof(handles), cols, rows, max_dim, best_mode;
|
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_STATUS status;
|
||||||
EFI_DEVICE_PATH *devpath;
|
|
||||||
EFI_BOOT_SERVICES *BS;
|
|
||||||
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
|
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
|
||||||
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = 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;
|
systab = Xsystab;
|
||||||
image = Ximage;
|
image = Ximage;
|
||||||
|
bs = Xsystab->BootServices;
|
||||||
|
|
||||||
BS = systab->BootServices;
|
/* Set up the console, so printf works. */
|
||||||
status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
|
status = bs->LocateProtocol(&ConsoleControlGUID, NULL,
|
||||||
(VOID **)&ConsoleControl);
|
(VOID **)&ConsoleControl);
|
||||||
if (status == EFI_SUCCESS)
|
if (status == EFI_SUCCESS)
|
||||||
(void)ConsoleControl->SetMode(ConsoleControl,
|
(void)ConsoleControl->SetMode(ConsoleControl,
|
||||||
@ -94,200 +173,162 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
|
|||||||
conout->EnableCursor(conout, TRUE);
|
conout->EnableCursor(conout, TRUE);
|
||||||
conout->ClearScreen(conout);
|
conout->ClearScreen(conout);
|
||||||
|
|
||||||
printf("\n"
|
printf("\n>> FreeBSD EFI boot block\n");
|
||||||
">> FreeBSD EFI boot block\n");
|
printf(" Loader path: %s\n\n", _PATH_LOADER);
|
||||||
printf(" Loader path: %s\n", path);
|
printf(" Initializing modules:");
|
||||||
|
for (i = 0; i < NUM_BOOT_MODULES; i++) {
|
||||||
status = systab->BootServices->LocateHandle(ByProtocol,
|
if (boot_modules[i] == NULL)
|
||||||
&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))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
|
printf(" %s", boot_modules[i]->name);
|
||||||
devpath = NextDevicePathNode(devpath);
|
if (boot_modules[i]->init != NULL)
|
||||||
|
boot_modules[i]->init();
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
|
||||||
status = systab->BootServices->HandleProtocol(handles[i],
|
/* Get all the device handles */
|
||||||
&BlockIoProtocolGUID, (void **)&blkio);
|
hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
|
||||||
if (EFI_ERROR(status))
|
if ((status = bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles))
|
||||||
continue;
|
!= EFI_SUCCESS)
|
||||||
|
panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT,
|
||||||
|
EFI_ERROR_CODE(status));
|
||||||
|
|
||||||
if (!blkio->Media->LogicalPartition)
|
status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
|
||||||
continue;
|
&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;
|
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;
|
/* Select a partition to boot by trying each module in order. */
|
||||||
return (n);
|
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 EFI_STATUS
|
||||||
|
probe_handle(EFI_HANDLE h)
|
||||||
static int
|
|
||||||
domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
|
|
||||||
{
|
{
|
||||||
|
dev_info_t *devinfo;
|
||||||
dmadat = &__dmadat;
|
EFI_BLOCK_IO *blkio;
|
||||||
bootdev = blkio;
|
EFI_DEVICE_PATH *devpath;
|
||||||
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;
|
|
||||||
EFI_STATUS status;
|
EFI_STATUS status;
|
||||||
EFI_HANDLE loaderhandle;
|
UINTN i;
|
||||||
EFI_LOADED_IMAGE *loaded_image;
|
|
||||||
void *buffer;
|
|
||||||
size_t bufsize;
|
|
||||||
|
|
||||||
if ((ino = lookup(fname)) == 0) {
|
/* Figure out if we're dealing with an actual partition. */
|
||||||
printf("File %s not found\n", fname);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bufsize = fsstat(ino);
|
for (dev = *devinfop; dev->next != NULL; dev = dev->next)
|
||||||
status = systab->BootServices->AllocatePool(EfiLoaderData,
|
;
|
||||||
bufsize, &buffer);
|
|
||||||
fsread(ino, buffer, bufsize);
|
|
||||||
|
|
||||||
/* XXX: For secure boot, we need our own loader here */
|
dev->next = devinfo;
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
113
sys/boot/efi/boot1/boot_module.h
Normal file
113
sys/boot/efi/boot1/boot_module.h
Normal 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
|
253
sys/boot/efi/boot1/ufs_module.c
Normal file
253
sys/boot/efi/boot1/ufs_module.c
Normal 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
|
||||||
|
};
|
199
sys/boot/efi/boot1/zfs_module.c
Normal file
199
sys/boot/efi/boot1/zfs_module.c
Normal 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
|
||||||
|
};
|
@ -39,11 +39,11 @@ extern struct devsw efinet_dev;
|
|||||||
extern struct netif_driver efinetif;
|
extern struct netif_driver efinetif;
|
||||||
|
|
||||||
void *efi_get_table(EFI_GUID *tbl);
|
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);
|
int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int);
|
||||||
EFI_HANDLE efi_find_handle(struct devsw *, 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);
|
int efi_status_to_errno(EFI_STATUS);
|
||||||
time_t efi_time(EFI_TIME *);
|
time_t efi_time(EFI_TIME *);
|
||||||
|
@ -35,6 +35,7 @@ struct entry {
|
|||||||
EFI_HANDLE alias;
|
EFI_HANDLE alias;
|
||||||
struct devsw *dev;
|
struct devsw *dev;
|
||||||
int unit;
|
int unit;
|
||||||
|
uint64_t extra;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct entry *entry;
|
struct entry *entry;
|
||||||
@ -79,7 +80,7 @@ efi_find_handle(struct devsw *dev, int unit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
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;
|
int idx;
|
||||||
|
|
||||||
@ -90,7 +91,28 @@ efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit)
|
|||||||
*dev = entry[idx].dev;
|
*dev = entry[idx].dev;
|
||||||
if (unit != NULL)
|
if (unit != NULL)
|
||||||
*unit = entry[idx].unit;
|
*unit = entry[idx].unit;
|
||||||
|
if (extra != NULL)
|
||||||
|
*extra = entry[idx].extra;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
return (ENOENT);
|
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);
|
||||||
|
}
|
||||||
|
@ -4,9 +4,6 @@ MAN=
|
|||||||
|
|
||||||
.include <src.opts.mk>
|
.include <src.opts.mk>
|
||||||
|
|
||||||
# In-tree GCC does not support __attribute__((ms_abi)).
|
|
||||||
.if ${COMPILER_TYPE} != "gcc"
|
|
||||||
|
|
||||||
MK_SSP= no
|
MK_SSP= no
|
||||||
|
|
||||||
PROG= loader.sym
|
PROG= loader.sym
|
||||||
@ -24,6 +21,16 @@ SRCS= autoload.c \
|
|||||||
smbios.c \
|
smbios.c \
|
||||||
vers.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}
|
.PATH: ${.CURDIR}/arch/${MACHINE}
|
||||||
# For smbios.c
|
# For smbios.c
|
||||||
.PATH: ${.CURDIR}/../../i386/libi386
|
.PATH: ${.CURDIR}/../../i386/libi386
|
||||||
@ -36,6 +43,11 @@ CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
|
|||||||
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
|
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
|
||||||
CFLAGS+= -I${.CURDIR}/../../..
|
CFLAGS+= -I${.CURDIR}/../../..
|
||||||
CFLAGS+= -I${.CURDIR}/../../i386/libi386
|
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
|
CFLAGS+= -DNO_PCI -DEFI
|
||||||
|
|
||||||
# make buildenv doesn't set DESTDIR, this means LIBSTAND
|
# make buildenv doesn't set DESTDIR, this means LIBSTAND
|
||||||
@ -113,8 +125,6 @@ DPADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND} \
|
|||||||
${LDSCRIPT}
|
${LDSCRIPT}
|
||||||
LDADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND}
|
LDADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND}
|
||||||
|
|
||||||
.endif # ${COMPILER_TYPE} != "gcc"
|
|
||||||
|
|
||||||
.include <bsd.prog.mk>
|
.include <bsd.prog.mk>
|
||||||
|
|
||||||
beforedepend ${OBJS}: machine
|
beforedepend ${OBJS}: machine
|
||||||
|
@ -31,14 +31,23 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <bootstrap.h>
|
#include <bootstrap.h>
|
||||||
#include <efi.h>
|
#include <efi.h>
|
||||||
#include <efilib.h>
|
#include <efilib.h>
|
||||||
|
#ifdef EFI_ZFS_BOOT
|
||||||
|
#include <libzfs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
struct devsw *devsw[] = {
|
struct devsw *devsw[] = {
|
||||||
&efipart_dev,
|
&efipart_dev,
|
||||||
&efinet_dev,
|
&efinet_dev,
|
||||||
|
#ifdef EFI_ZFS_BOOT
|
||||||
|
&zfs_dev,
|
||||||
|
#endif
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fs_ops *file_system[] = {
|
struct fs_ops *file_system[] = {
|
||||||
|
#ifdef EFI_ZFS_BOOT
|
||||||
|
&zfs_fsops,
|
||||||
|
#endif
|
||||||
&dosfs_fsops,
|
&dosfs_fsops,
|
||||||
&ufs_fsops,
|
&ufs_fsops,
|
||||||
&cd9660_fsops,
|
&cd9660_fsops,
|
||||||
|
@ -31,7 +31,11 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <stand.h>
|
#include <stand.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/disklabel.h>
|
#include <sys/disklabel.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <bootstrap.h>
|
#include <bootstrap.h>
|
||||||
|
#ifdef EFI_ZFS_BOOT
|
||||||
|
#include <libzfs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <efi.h>
|
#include <efi.h>
|
||||||
#include <efilib.h>
|
#include <efilib.h>
|
||||||
@ -86,7 +90,7 @@ efi_parsedev(struct devdesc **dev, const char *devspec, const char **path)
|
|||||||
struct devsw *dv;
|
struct devsw *dv;
|
||||||
char *cp;
|
char *cp;
|
||||||
const char *np;
|
const char *np;
|
||||||
int i, err;
|
int i;
|
||||||
|
|
||||||
/* minimum length check */
|
/* minimum length check */
|
||||||
if (strlen(devspec) < 2)
|
if (strlen(devspec) < 2)
|
||||||
@ -101,24 +105,43 @@ efi_parsedev(struct devdesc **dev, const char *devspec, const char **path)
|
|||||||
if (devsw[i] == NULL)
|
if (devsw[i] == NULL)
|
||||||
return (ENOENT);
|
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);
|
np = devspec + strlen(dv->dv_name);
|
||||||
if (*np != '\0' && *np != ':') {
|
|
||||||
idev->d_unit = strtol(np, &cp, 0);
|
#ifdef EFI_ZFS_BOOT
|
||||||
if (cp == np) {
|
if (dv->dv_type == DEVT_ZFS) {
|
||||||
idev->d_unit = -1;
|
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);
|
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 != ':') {
|
if (*cp != '\0' && *cp != ':') {
|
||||||
free(idev);
|
free(idev);
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
@ -137,9 +160,13 @@ char *
|
|||||||
efi_fmtdev(void *vdev)
|
efi_fmtdev(void *vdev)
|
||||||
{
|
{
|
||||||
struct devdesc *dev = (struct devdesc *)vdev;
|
struct devdesc *dev = (struct devdesc *)vdev;
|
||||||
static char buf[32]; /* XXX device length constant? */
|
static char buf[SPECNAMELEN + 1];
|
||||||
|
|
||||||
switch(dev->d_type) {
|
switch(dev->d_type) {
|
||||||
|
#ifdef EFI_ZFS_BOOT
|
||||||
|
case DEVT_ZFS:
|
||||||
|
return (zfs_fmtdev(dev));
|
||||||
|
#endif
|
||||||
case DEVT_NONE:
|
case DEVT_NONE:
|
||||||
strcpy(buf, "(no device)");
|
strcpy(buf, "(no device)");
|
||||||
break;
|
break;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
#include <stand.h>
|
#include <stand.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
@ -38,6 +39,10 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <bootstrap.h>
|
#include <bootstrap.h>
|
||||||
#include <smbios.h>
|
#include <smbios.h>
|
||||||
|
|
||||||
|
#ifdef EFI_ZFS_BOOT
|
||||||
|
#include <libzfs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "loader_efi.h"
|
#include "loader_efi.h"
|
||||||
|
|
||||||
extern char bootprog_name[];
|
extern char bootprog_name[];
|
||||||
@ -45,7 +50,6 @@ extern char bootprog_rev[];
|
|||||||
extern char bootprog_date[];
|
extern char bootprog_date[];
|
||||||
extern char bootprog_maker[];
|
extern char bootprog_maker[];
|
||||||
|
|
||||||
struct devdesc currdev; /* our current device */
|
|
||||||
struct arch_switch archsw; /* MI/MD interface boundary */
|
struct arch_switch archsw; /* MI/MD interface boundary */
|
||||||
|
|
||||||
EFI_GUID acpi = ACPI_TABLE_GUID;
|
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 debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
|
||||||
EFI_GUID fdtdtb = FDT_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
|
EFI_STATUS
|
||||||
main(int argc, CHAR16 *argv[])
|
main(int argc, CHAR16 *argv[])
|
||||||
{
|
{
|
||||||
char var[128];
|
char var[128];
|
||||||
EFI_LOADED_IMAGE *img;
|
EFI_LOADED_IMAGE *img;
|
||||||
EFI_GUID *guid;
|
EFI_GUID *guid;
|
||||||
int i, j, vargood;
|
int i, j, vargood, unit;
|
||||||
|
struct devsw *dev;
|
||||||
|
uint64_t pool_guid;
|
||||||
UINTN k;
|
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
|
* XXX Chicken-and-egg problem; we want to have console output
|
||||||
* early, but some console attributes may depend on reading from
|
* 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. */
|
/* Get our loaded image protocol interface structure. */
|
||||||
BS->HandleProtocol(IH, &imgid, (VOID**)&img);
|
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("Image base: 0x%lx\n", (u_long)img->ImageBase);
|
||||||
printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16,
|
printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16,
|
||||||
ST->Hdr.Revision & 0xffff);
|
ST->Hdr.Revision & 0xffff);
|
||||||
@ -129,9 +170,6 @@ main(int argc, CHAR16 *argv[])
|
|||||||
printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
|
printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
|
||||||
printf("(%s, %s)\n", bootprog_maker, bootprog_date);
|
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
|
* Disable the watchdog timer. By default the boot manager sets
|
||||||
* the timer to 5 minutes before invoking a boot option. If we
|
* 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);
|
BS->SetWatchdogTimer(0, 0, 0, NULL);
|
||||||
|
|
||||||
env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
|
if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &pool_guid) != 0)
|
||||||
efi_setcurrdev, env_nounset);
|
return (EFI_NOT_FOUND);
|
||||||
env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
|
|
||||||
env_nounset);
|
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 */
|
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++) {
|
for (k = 0; k < ST->NumberOfTableEntries; k++) {
|
||||||
guid = &ST->ConfigurationTable[k].VendorGuid;
|
guid = &ST->ConfigurationTable[k].VendorGuid;
|
||||||
if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) {
|
if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) {
|
||||||
@ -423,6 +487,61 @@ command_nvram(int argc, char *argv[])
|
|||||||
return (CMD_OK);
|
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
|
#ifdef LOADER_FDT_SUPPORT
|
||||||
extern int command_fdt_internal(int argc, char *argv[]);
|
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);
|
COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt);
|
||||||
#endif
|
#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
|
||||||
|
@ -464,7 +464,7 @@ fdt_fixup_memory(struct fdt_mem_region *region, size_t num)
|
|||||||
{
|
{
|
||||||
struct fdt_mem_region *curmr;
|
struct fdt_mem_region *curmr;
|
||||||
uint32_t addr_cells, size_cells;
|
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;
|
int err, i, len, memory, root;
|
||||||
size_t realmrno;
|
size_t realmrno;
|
||||||
uint8_t *buf, *sb;
|
uint8_t *buf, *sb;
|
||||||
|
@ -69,7 +69,6 @@ static int isa_inb(int port);
|
|||||||
static void isa_outb(int port, int value);
|
static void isa_outb(int port, int value);
|
||||||
void exit(int code);
|
void exit(int code);
|
||||||
#ifdef LOADER_ZFS_SUPPORT
|
#ifdef LOADER_ZFS_SUPPORT
|
||||||
static void init_zfs_bootenv(char *currdev);
|
|
||||||
static void i386_zfs_probe(void);
|
static void i386_zfs_probe(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -306,34 +305,6 @@ extract_currdev(void)
|
|||||||
env_nounset);
|
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);
|
COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -414,7 +414,7 @@ void
|
|||||||
usage()
|
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);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,9 +425,14 @@ main(int argc, char** argv)
|
|||||||
void (*func)(struct loader_callbacks *, void *, int, int);
|
void (*func)(struct loader_callbacks *, void *, int, int);
|
||||||
int opt;
|
int opt;
|
||||||
char *disk_image = NULL;
|
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) {
|
switch (opt) {
|
||||||
|
case 'b':
|
||||||
|
userboot_obj = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
disk_image = optarg;
|
disk_image = optarg;
|
||||||
break;
|
break;
|
||||||
@ -441,8 +446,7 @@ main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h = dlopen("/boot/userboot.so",
|
h = dlopen(userboot_obj, RTLD_LOCAL);
|
||||||
RTLD_LOCAL);
|
|
||||||
if (!h) {
|
if (!h) {
|
||||||
printf("%s\n", dlerror());
|
printf("%s\n", dlerror());
|
||||||
return (1);
|
return (1);
|
||||||
|
@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
static void userboot_zfs_probe(void);
|
static void userboot_zfs_probe(void);
|
||||||
static int userboot_zfs_found;
|
static int userboot_zfs_found;
|
||||||
static void init_zfs_bootenv(char *currdev);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define USERBOOT_VERSION USERBOOT_VERSION_3
|
#define USERBOOT_VERSION USERBOOT_VERSION_3
|
||||||
@ -199,32 +198,6 @@ extract_currdev(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USERBOOT_ZFS_SUPPORT)
|
#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
|
static void
|
||||||
userboot_zfs_probe(void)
|
userboot_zfs_probe(void)
|
||||||
{
|
{
|
||||||
|
@ -62,6 +62,7 @@ int zfs_parsedev(struct zfs_devdesc *dev, const char *devspec,
|
|||||||
char *zfs_fmtdev(void *vdev);
|
char *zfs_fmtdev(void *vdev);
|
||||||
int zfs_probe_dev(const char *devname, uint64_t *pool_guid);
|
int zfs_probe_dev(const char *devname, uint64_t *pool_guid);
|
||||||
int zfs_list(const char *name);
|
int zfs_list(const char *name);
|
||||||
|
void init_zfs_bootenv(char *currdev);
|
||||||
int zfs_bootenv(const char *name);
|
int zfs_bootenv(const char *name);
|
||||||
int zfs_belist_add(const char *name);
|
int zfs_belist_add(const char *name);
|
||||||
int zfs_set_env(void);
|
int zfs_set_env(void);
|
||||||
|
@ -709,6 +709,32 @@ zfs_list(const char *name)
|
|||||||
return (zfs_list_dataset(spa, objid));
|
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
|
int
|
||||||
zfs_bootenv(const char *name)
|
zfs_bootenv(const char *name)
|
||||||
{
|
{
|
||||||
@ -779,8 +805,15 @@ int
|
|||||||
zfs_belist_add(const char *name)
|
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 */
|
/* Add the boot environment to the head of the SLIST */
|
||||||
zfs_be = malloc(sizeof(struct zfs_be_entry));
|
zfs_be = malloc(sizeof(struct zfs_be_entry));
|
||||||
|
if (zfs_be == NULL) {
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
zfs_be->name = name;
|
zfs_be->name = name;
|
||||||
SLIST_INSERT_HEAD(&zfs_be_head, zfs_be, entries);
|
SLIST_INSERT_HEAD(&zfs_be_head, zfs_be, entries);
|
||||||
zfs_env_count++;
|
zfs_env_count++;
|
||||||
|
@ -2165,7 +2165,13 @@ zfs_lookup(const struct zfsmount *mount, const char *upath, dnode_phys_t *dnode)
|
|||||||
strcpy(&path[sb.st_size], p);
|
strcpy(&path[sb.st_size], p);
|
||||||
else
|
else
|
||||||
path[sb.st_size] = 0;
|
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)],
|
memcpy(path, &dn.dn_bonus[sizeof(znode_phys_t)],
|
||||||
sb.st_size);
|
sb.st_size);
|
||||||
} else {
|
} else {
|
||||||
|
@ -610,7 +610,6 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
|
|||||||
error = SET_ERROR(EINVAL);
|
error = SET_ERROR(EINVAL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
check++;
|
|
||||||
}
|
}
|
||||||
if (strlen(strval) > ZPROP_MAX_COMMENT)
|
if (strlen(strval) > ZPROP_MAX_COMMENT)
|
||||||
error = E2BIG;
|
error = E2BIG;
|
||||||
@ -5952,6 +5951,8 @@ spa_async_remove(spa_t *spa, vdev_t *vd)
|
|||||||
vd->vdev_stat.vs_checksum_errors = 0;
|
vd->vdev_stat.vs_checksum_errors = 0;
|
||||||
|
|
||||||
vdev_state_dirty(vd->vdev_top);
|
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++)
|
for (int c = 0; c < vd->vdev_children; c++)
|
||||||
|
@ -160,7 +160,6 @@ vdev_geom_orphan(struct g_consumer *cp)
|
|||||||
* async removal support to invoke a close on this
|
* async removal support to invoke a close on this
|
||||||
* vdev once it is safe to do so.
|
* vdev once it is safe to do so.
|
||||||
*/
|
*/
|
||||||
zfs_post_remove(vd->vdev_spa, vd);
|
|
||||||
vd->vdev_remove_wanted = B_TRUE;
|
vd->vdev_remove_wanted = B_TRUE;
|
||||||
spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE);
|
spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE);
|
||||||
}
|
}
|
||||||
|
@ -1131,7 +1131,7 @@ linux_get_robust_list(struct thread *td, struct linux_get_robust_list_args *args
|
|||||||
return (EFAULT);
|
return (EFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = copyout(head, args->head, sizeof(struct linux_robust_list_head));
|
error = copyout(&head, args->head, sizeof(head));
|
||||||
if (error) {
|
if (error) {
|
||||||
LIN_SDT_PROBE1(futex, linux_get_robust_list, copyout_error,
|
LIN_SDT_PROBE1(futex, linux_get_robust_list, copyout_error,
|
||||||
error);
|
error);
|
||||||
|
@ -1304,9 +1304,11 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args)
|
|||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
newcred = crget();
|
newcred = crget();
|
||||||
|
crextend(newcred, ngrp + 1);
|
||||||
p = td->td_proc;
|
p = td->td_proc;
|
||||||
PROC_LOCK(p);
|
PROC_LOCK(p);
|
||||||
oldcred = crcopysafe(p, newcred);
|
oldcred = p->p_ucred;
|
||||||
|
crcopy(newcred, oldcred);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cr_groups[0] holds egid. Setting the whole set from
|
* cr_groups[0] holds egid. Setting the whole set from
|
||||||
|
@ -129,8 +129,9 @@ struct pci_driver {
|
|||||||
const struct pci_device_id *id_table;
|
const struct pci_device_id *id_table;
|
||||||
int (*probe)(struct pci_dev *dev, const struct pci_device_id *id);
|
int (*probe)(struct pci_dev *dev, const struct pci_device_id *id);
|
||||||
void (*remove)(struct pci_dev *dev);
|
void (*remove)(struct pci_dev *dev);
|
||||||
int (*suspend) (struct pci_dev *dev, pm_message_t state); /* Device suspended */
|
int (*suspend) (struct pci_dev *dev, pm_message_t state); /* Device suspended */
|
||||||
int (*resume) (struct pci_dev *dev); /* Device woken up */
|
int (*resume) (struct pci_dev *dev); /* Device woken up */
|
||||||
|
void (*shutdown) (struct pci_dev *dev); /* Device shutdown */
|
||||||
driver_t driver;
|
driver_t driver;
|
||||||
devclass_t bsdclass;
|
devclass_t bsdclass;
|
||||||
const struct pci_error_handlers *err_handler;
|
const struct pci_error_handlers *err_handler;
|
||||||
|
@ -61,11 +61,17 @@ __FBSDID("$FreeBSD$");
|
|||||||
static device_probe_t linux_pci_probe;
|
static device_probe_t linux_pci_probe;
|
||||||
static device_attach_t linux_pci_attach;
|
static device_attach_t linux_pci_attach;
|
||||||
static device_detach_t linux_pci_detach;
|
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[] = {
|
static device_method_t pci_methods[] = {
|
||||||
DEVMETHOD(device_probe, linux_pci_probe),
|
DEVMETHOD(device_probe, linux_pci_probe),
|
||||||
DEVMETHOD(device_attach, linux_pci_attach),
|
DEVMETHOD(device_attach, linux_pci_attach),
|
||||||
DEVMETHOD(device_detach, linux_pci_detach),
|
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
|
DEVMETHOD_END
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -169,6 +175,46 @@ linux_pci_detach(device_t dev)
|
|||||||
return (0);
|
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
|
int
|
||||||
pci_register_driver(struct pci_driver *pdrv)
|
pci_register_driver(struct pci_driver *pdrv)
|
||||||
{
|
{
|
||||||
|
@ -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_channel_mgmt.c optional hyperv
|
||||||
dev/hyperv/vmbus/hv_connection.c optional hyperv
|
dev/hyperv/vmbus/hv_connection.c optional hyperv
|
||||||
dev/hyperv/vmbus/hv_hv.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_ring_buffer.c optional hyperv
|
||||||
dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
|
dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
|
||||||
dev/nfe/if_nfe.c optional nfe pci
|
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_filter.c optional sfxge pci
|
||||||
dev/sfxge/common/efx_hash.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_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_mac.c optional sfxge pci
|
||||||
dev/sfxge/common/efx_mcdi.c optional sfxge pci
|
dev/sfxge/common/efx_mcdi.c optional sfxge pci
|
||||||
dev/sfxge/common/efx_mon.c optional sfxge pci
|
dev/sfxge/common/efx_mon.c optional sfxge pci
|
||||||
|
@ -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_channel_mgmt.c optional hyperv
|
||||||
dev/hyperv/vmbus/hv_connection.c optional hyperv
|
dev/hyperv/vmbus/hv_connection.c optional hyperv
|
||||||
dev/hyperv/vmbus/hv_hv.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_ring_buffer.c optional hyperv
|
||||||
dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
|
dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
|
||||||
dev/ichwd/ichwd.c optional ichwd
|
dev/ichwd/ichwd.c optional ichwd
|
||||||
|
@ -173,7 +173,7 @@ bcm_vchiq_attach(device_t dev)
|
|||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
mtx_init(&sc->lock, "vchiq", MTX_DEF, 0);
|
mtx_init(&sc->lock, "vchiq", 0, MTX_DEF);
|
||||||
bcm_vchiq_sc = sc;
|
bcm_vchiq_sc = sc;
|
||||||
|
|
||||||
vchiq_init();
|
vchiq_init();
|
||||||
|
@ -663,7 +663,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
|
|||||||
plane->dev = dev;
|
plane->dev = dev;
|
||||||
plane->funcs = funcs;
|
plane->funcs = funcs;
|
||||||
plane->format_types = malloc(sizeof(uint32_t) * format_count,
|
plane->format_types = malloc(sizeof(uint32_t) * format_count,
|
||||||
DRM_MEM_KMS, M_NOWAIT);
|
DRM_MEM_KMS, M_WAITOK);
|
||||||
if (!plane->format_types) {
|
if (!plane->format_types) {
|
||||||
DRM_DEBUG_KMS("out of memory when allocating plane\n");
|
DRM_DEBUG_KMS("out of memory when allocating plane\n");
|
||||||
drm_mode_object_put(dev, &plane->base);
|
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;
|
total_objects += dev->mode_config.num_encoder;
|
||||||
|
|
||||||
group->id_list = malloc(total_objects * sizeof(uint32_t),
|
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)
|
if (!group->id_list)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -1998,7 +1998,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
|||||||
|
|
||||||
connector_set = malloc(crtc_req->count_connectors *
|
connector_set = malloc(crtc_req->count_connectors *
|
||||||
sizeof(struct drm_connector *),
|
sizeof(struct drm_connector *),
|
||||||
DRM_MEM_KMS, M_NOWAIT);
|
DRM_MEM_KMS, M_WAITOK);
|
||||||
if (!connector_set) {
|
if (!connector_set) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
@ -2523,7 +2523,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
|
|||||||
goto out_err1;
|
goto out_err1;
|
||||||
}
|
}
|
||||||
clips = malloc(num_clips * sizeof(*clips), DRM_MEM_KMS,
|
clips = malloc(num_clips * sizeof(*clips), DRM_MEM_KMS,
|
||||||
M_NOWAIT | M_ZERO);
|
M_WAITOK | M_ZERO);
|
||||||
if (!clips) {
|
if (!clips) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out_err1;
|
goto out_err1;
|
||||||
@ -2774,13 +2774,13 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
property = malloc(sizeof(struct drm_property), DRM_MEM_KMS,
|
property = malloc(sizeof(struct drm_property), DRM_MEM_KMS,
|
||||||
M_NOWAIT | M_ZERO);
|
M_WAITOK | M_ZERO);
|
||||||
if (!property)
|
if (!property)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (num_values) {
|
if (num_values) {
|
||||||
property->values = malloc(sizeof(uint64_t)*num_values, DRM_MEM_KMS,
|
property->values = malloc(sizeof(uint64_t)*num_values, DRM_MEM_KMS,
|
||||||
M_NOWAIT | M_ZERO);
|
M_WAITOK | M_ZERO);
|
||||||
if (!property->values)
|
if (!property->values)
|
||||||
goto fail;
|
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,
|
prop_enum = malloc(sizeof(struct drm_property_enum), DRM_MEM_KMS,
|
||||||
M_NOWAIT | M_ZERO);
|
M_WAITOK | M_ZERO);
|
||||||
if (!prop_enum)
|
if (!prop_enum)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -3104,7 +3104,7 @@ static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
blob = malloc(sizeof(struct drm_property_blob)+length, DRM_MEM_KMS,
|
blob = malloc(sizeof(struct drm_property_blob)+length, DRM_MEM_KMS,
|
||||||
M_NOWAIT | M_ZERO);
|
M_WAITOK | M_ZERO);
|
||||||
if (!blob)
|
if (!blob)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -3434,7 +3434,7 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
|
|||||||
crtc->gamma_size = gamma_size;
|
crtc->gamma_size = gamma_size;
|
||||||
|
|
||||||
crtc->gamma_store = malloc(gamma_size * sizeof(uint16_t) * 3,
|
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) {
|
if (!crtc->gamma_store) {
|
||||||
crtc->gamma_size = 0;
|
crtc->gamma_size = 0;
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -3632,7 +3632,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
|||||||
file_priv->event_space -= sizeof e->event;
|
file_priv->event_space -= sizeof e->event;
|
||||||
mtx_unlock(&dev->event_lock);
|
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) {
|
if (e == NULL) {
|
||||||
mtx_lock(&dev->event_lock);
|
mtx_lock(&dev->event_lock);
|
||||||
file_priv->event_space += sizeof e->event;
|
file_priv->event_space += sizeof e->event;
|
||||||
|
@ -225,7 +225,7 @@ int drm_pci_set_unique(struct drm_device *dev,
|
|||||||
|
|
||||||
master->unique_len = u->unique_len;
|
master->unique_len = u->unique_len;
|
||||||
master->unique_size = u->unique_len + 1;
|
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) {
|
if (!master->unique) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -2035,9 +2035,9 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp)
|
|||||||
if (error == EFBIG && remap) {
|
if (error == EFBIG && remap) {
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
|
|
||||||
m = m_defrag(*m_headp, M_NOWAIT);
|
m = m_collapse(*m_headp, M_NOWAIT, EM_MAX_SCATTER);
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
adapter->mbuf_alloc_failed++;
|
adapter->mbuf_defrag_failed++;
|
||||||
m_freem(*m_headp);
|
m_freem(*m_headp);
|
||||||
*m_headp = NULL;
|
*m_headp = NULL;
|
||||||
return (ENOBUFS);
|
return (ENOBUFS);
|
||||||
@ -5493,18 +5493,15 @@ em_add_hw_stats(struct adapter *adapter)
|
|||||||
char namebuf[QUEUE_NAME_LEN];
|
char namebuf[QUEUE_NAME_LEN];
|
||||||
|
|
||||||
/* Driver Statistics */
|
/* 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",
|
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
|
||||||
CTLFLAG_RD, &adapter->dropped_pkts,
|
CTLFLAG_RD, &adapter->dropped_pkts,
|
||||||
"Driver dropped packets");
|
"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",
|
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail",
|
||||||
CTLFLAG_RD, &adapter->no_tx_dma_setup,
|
CTLFLAG_RD, &adapter->no_tx_dma_setup,
|
||||||
"Driver tx dma failure in xmit");
|
"Driver tx dma failure in xmit");
|
||||||
|
@ -473,13 +473,12 @@ struct adapter {
|
|||||||
|
|
||||||
/* Misc stats maintained by the driver */
|
/* Misc stats maintained by the driver */
|
||||||
unsigned long dropped_pkts;
|
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_dma_setup;
|
||||||
unsigned long no_tx_map_avail;
|
unsigned long no_tx_map_avail;
|
||||||
unsigned long no_tx_dma_setup;
|
|
||||||
unsigned long rx_overruns;
|
unsigned long rx_overruns;
|
||||||
unsigned long watchdog_events;
|
unsigned long watchdog_events;
|
||||||
unsigned long link_irq;
|
|
||||||
|
|
||||||
struct e1000_hw_stats stats;
|
struct e1000_hw_stats stats;
|
||||||
};
|
};
|
||||||
|
@ -1835,7 +1835,8 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
|
|||||||
/* Try it again? - one try */
|
/* Try it again? - one try */
|
||||||
if (remap == TRUE) {
|
if (remap == TRUE) {
|
||||||
remap = FALSE;
|
remap = FALSE;
|
||||||
m = m_defrag(*m_headp, M_NOWAIT);
|
m = m_collapse(*m_headp, M_NOWAIT,
|
||||||
|
IGB_MAX_SCATTER);
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
adapter->mbuf_defrag_failed++;
|
adapter->mbuf_defrag_failed++;
|
||||||
m_freem(*m_headp);
|
m_freem(*m_headp);
|
||||||
@ -5826,12 +5827,15 @@ igb_add_hw_stats(struct adapter *adapter)
|
|||||||
char namebuf[QUEUE_NAME_LEN];
|
char namebuf[QUEUE_NAME_LEN];
|
||||||
|
|
||||||
/* Driver Statistics */
|
/* 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",
|
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
|
||||||
CTLFLAG_RD, &adapter->dropped_pkts,
|
CTLFLAG_RD, &adapter->dropped_pkts,
|
||||||
"Driver dropped packets");
|
"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",
|
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail",
|
||||||
CTLFLAG_RD, &adapter->no_tx_dma_setup,
|
CTLFLAG_RD, &adapter->no_tx_dma_setup,
|
||||||
"Driver tx dma failure in xmit");
|
"Driver tx dma failure in xmit");
|
||||||
|
@ -512,20 +512,19 @@ struct adapter {
|
|||||||
u8 *mta;
|
u8 *mta;
|
||||||
|
|
||||||
/* Misc stats maintained by the driver */
|
/* 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 device_control;
|
||||||
unsigned long rx_control;
|
unsigned long dropped_pkts;
|
||||||
unsigned long int_mask;
|
|
||||||
unsigned long eint_mask;
|
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_rx;
|
||||||
unsigned long packet_buf_alloc_tx;
|
unsigned long packet_buf_alloc_tx;
|
||||||
|
unsigned long rx_control;
|
||||||
|
unsigned long rx_overruns;
|
||||||
|
unsigned long watchdog_events;
|
||||||
|
|
||||||
/* Used in pf and vf */
|
/* Used in pf and vf */
|
||||||
void *stats;
|
void *stats;
|
||||||
|
|
||||||
|
@ -1675,9 +1675,9 @@ lem_xmit(struct adapter *adapter, struct mbuf **m_headp)
|
|||||||
if (error == EFBIG) {
|
if (error == EFBIG) {
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
|
|
||||||
m = m_defrag(*m_headp, M_NOWAIT);
|
m = m_collapse(*m_headp, M_NOWAIT, EM_MAX_SCATTER);
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
adapter->mbuf_alloc_failed++;
|
adapter->mbuf_defrag_failed++;
|
||||||
m_freem(*m_headp);
|
m_freem(*m_headp);
|
||||||
*m_headp = NULL;
|
*m_headp = NULL;
|
||||||
return (ENOBUFS);
|
return (ENOBUFS);
|
||||||
@ -4526,12 +4526,12 @@ lem_add_hw_stats(struct adapter *adapter)
|
|||||||
struct sysctl_oid_list *stat_list;
|
struct sysctl_oid_list *stat_list;
|
||||||
|
|
||||||
/* Driver Statistics */
|
/* 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",
|
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "cluster_alloc_fail",
|
||||||
CTLFLAG_RD, &adapter->mbuf_cluster_failed,
|
CTLFLAG_RD, &adapter->mbuf_cluster_failed,
|
||||||
"Std 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",
|
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
|
||||||
CTLFLAG_RD, &adapter->dropped_pkts,
|
CTLFLAG_RD, &adapter->dropped_pkts,
|
||||||
"Driver dropped packets");
|
"Driver dropped packets");
|
||||||
|
@ -417,17 +417,17 @@ struct adapter {
|
|||||||
|
|
||||||
/* Misc stats maintained by the driver */
|
/* Misc stats maintained by the driver */
|
||||||
unsigned long dropped_pkts;
|
unsigned long dropped_pkts;
|
||||||
unsigned long mbuf_alloc_failed;
|
unsigned long link_irq;
|
||||||
unsigned long mbuf_cluster_failed;
|
unsigned long mbuf_cluster_failed;
|
||||||
|
unsigned long mbuf_defrag_failed;
|
||||||
unsigned long no_tx_desc_avail1;
|
unsigned long no_tx_desc_avail1;
|
||||||
unsigned long no_tx_desc_avail2;
|
unsigned long no_tx_desc_avail2;
|
||||||
|
unsigned long no_tx_dma_setup;
|
||||||
unsigned long no_tx_map_avail;
|
unsigned long no_tx_map_avail;
|
||||||
unsigned long no_tx_dma_setup;
|
|
||||||
unsigned long watchdog_events;
|
unsigned long watchdog_events;
|
||||||
unsigned long rx_overruns;
|
|
||||||
unsigned long rx_irq;
|
unsigned long rx_irq;
|
||||||
|
unsigned long rx_overruns;
|
||||||
unsigned long tx_irq;
|
unsigned long tx_irq;
|
||||||
unsigned long link_irq;
|
|
||||||
|
|
||||||
/* 82547 workaround */
|
/* 82547 workaround */
|
||||||
uint32_t tx_fifo_size;
|
uint32_t tx_fifo_size;
|
||||||
|
@ -184,7 +184,7 @@ gpiobus_init_softc(device_t dev)
|
|||||||
if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0)
|
if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0)
|
||||||
return (ENXIO);
|
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 */
|
/* Pins = GPIO_PIN_MAX() + 1 */
|
||||||
sc->sc_npins++;
|
sc->sc_npins++;
|
||||||
|
@ -335,11 +335,6 @@ typedef enum {
|
|||||||
HV_CHANNEL_MESSAGE_INITIATED_CONTACT = 14,
|
HV_CHANNEL_MESSAGE_INITIATED_CONTACT = 14,
|
||||||
HV_CHANNEL_MESSAGE_VERSION_RESPONSE = 15,
|
HV_CHANNEL_MESSAGE_VERSION_RESPONSE = 15,
|
||||||
HV_CHANNEL_MESSAGE_UNLOAD = 16,
|
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_CHANNEL_MESSAGE_COUNT
|
||||||
} hv_vmbus_channel_msg_type;
|
} hv_vmbus_channel_msg_type;
|
||||||
|
|
||||||
|
@ -642,6 +642,12 @@ hv_nv_connect_to_vsp(struct hv_device *device)
|
|||||||
/* sema_wait(&NetVscChannel->channel_init_sema); */
|
/* sema_wait(&NetVscChannel->channel_init_sema); */
|
||||||
|
|
||||||
/* Post the big receive buffer to NetVSP */
|
/* 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);
|
ret = hv_nv_init_rx_buffer_with_net_vsp(device);
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = hv_nv_init_send_buffer_with_net_vsp(device);
|
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;
|
goto cleanup;
|
||||||
|
|
||||||
/* Initialize the NetVSC channel extension */
|
/* 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");
|
sema_init(&net_dev->channel_init_sema, 0, "netdev_sema");
|
||||||
|
|
||||||
|
@ -857,7 +857,7 @@ typedef struct nvsp_msg_ {
|
|||||||
#define NETVSC_SEND_BUFFER_SIZE (1024*1024*15) /* 15M */
|
#define NETVSC_SEND_BUFFER_SIZE (1024*1024*15) /* 15M */
|
||||||
#define NETVSC_SEND_BUFFER_ID 0xface
|
#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_SIZE (1024*1024*16) /* 16MB */
|
||||||
|
|
||||||
#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
|
#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
|
||||||
|
@ -391,12 +391,14 @@ netvsc_attach(device_t dev)
|
|||||||
sc->hn_carrier = 1;
|
sc->hn_carrier = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(INET) || defined(INET6)
|
||||||
tcp_lro_init(&sc->hn_lro);
|
tcp_lro_init(&sc->hn_lro);
|
||||||
/* Driver private LRO settings */
|
/* Driver private LRO settings */
|
||||||
sc->hn_lro.ifp = ifp;
|
sc->hn_lro.ifp = ifp;
|
||||||
#ifdef HN_LRO_HIWAT
|
#ifdef HN_LRO_HIWAT
|
||||||
sc->hn_lro.lro_hiwat = sc->hn_lro_hiwat;
|
sc->hn_lro.lro_hiwat = sc->hn_lro_hiwat;
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* INET || INET6 */
|
||||||
|
|
||||||
ether_ifattach(ifp, device_info.mac_addr);
|
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);
|
hv_rf_on_device_remove(hv_device, HV_RF_NV_DESTROY_CHANNEL);
|
||||||
|
|
||||||
ifmedia_removeall(&sc->hn_media);
|
ifmedia_removeall(&sc->hn_media);
|
||||||
|
#if defined(INET) || defined(INET6)
|
||||||
tcp_lro_free(&sc->hn_lro);
|
tcp_lro_free(&sc->hn_lro);
|
||||||
|
#endif
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@ -1083,6 +1087,7 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet,
|
|||||||
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
|
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
|
||||||
|
|
||||||
if ((ifp->if_capenable & IFCAP_LRO) && do_lro) {
|
if ((ifp->if_capenable & IFCAP_LRO) && do_lro) {
|
||||||
|
#if defined(INET) || defined(INET6)
|
||||||
struct lro_ctrl *lro = &sc->hn_lro;
|
struct lro_ctrl *lro = &sc->hn_lro;
|
||||||
|
|
||||||
if (lro->lro_cnt) {
|
if (lro->lro_cnt) {
|
||||||
@ -1092,6 +1097,7 @@ netvsc_recv(struct hv_device *device_ctx, netvsc_packet *packet,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We're not holding the lock here, so don't release it */
|
/* 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
|
void
|
||||||
netvsc_recv_rollup(struct hv_device *device_ctx)
|
netvsc_recv_rollup(struct hv_device *device_ctx)
|
||||||
{
|
{
|
||||||
|
#if defined(INET) || defined(INET6)
|
||||||
hn_softc_t *sc = device_get_softc(device_ctx->device);
|
hn_softc_t *sc = device_get_softc(device_ctx->device);
|
||||||
struct lro_ctrl *lro = &sc->hn_lro;
|
struct lro_ctrl *lro = &sc->hn_lro;
|
||||||
struct lro_entry *queued;
|
struct lro_entry *queued;
|
||||||
@ -1111,6 +1118,7 @@ netvsc_recv_rollup(struct hv_device *device_ctx)
|
|||||||
SLIST_REMOVE_HEAD(&lro->lro_active, next);
|
SLIST_REMOVE_HEAD(&lro->lro_active, next);
|
||||||
tcp_lro_flush(lro, queued);
|
tcp_lro_flush(lro, queued);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -251,7 +251,7 @@ hv_vmbus_connect(void) {
|
|||||||
|
|
||||||
hv_vmbus_protocal_version = version;
|
hv_vmbus_protocal_version = version;
|
||||||
if (bootverbose)
|
if (bootverbose)
|
||||||
printf("VMBUS: Portocal Version: %d.%d\n",
|
printf("VMBUS: Protocol Version: %d.%d\n",
|
||||||
version >> 16, version & 0xFFFF);
|
version >> 16, version & 0xFFFF);
|
||||||
|
|
||||||
sema_destroy(&msg_info->wait_sema);
|
sema_destroy(&msg_info->wait_sema);
|
||||||
@ -423,12 +423,6 @@ VmbusProcessChannelEvent(uint32_t relid)
|
|||||||
// mtx_unlock(&channel->inbound_lock);
|
// 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
|
* Handler for events
|
||||||
*/
|
*/
|
||||||
@ -449,17 +443,6 @@ hv_vmbus_on_events(void *arg)
|
|||||||
KASSERT(cpu <= mp_maxid, ("VMBUS: hv_vmbus_on_events: "
|
KASSERT(cpu <= mp_maxid, ("VMBUS: hv_vmbus_on_events: "
|
||||||
"cpu out of range!"));
|
"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) ||
|
if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) ||
|
||||||
(hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)) {
|
(hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)) {
|
||||||
maxdword = HV_MAX_NUM_CHANNELS_SUPPORTED >> 5;
|
maxdword = HV_MAX_NUM_CHANNELS_SUPPORTED >> 5;
|
||||||
|
131
sys/dev/hyperv/vmbus/hv_et.c
Normal file
131
sys/dev/hyperv/vmbus/hv_et.c
Normal 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);
|
||||||
|
}
|
||||||
|
|
@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/pcpu.h>
|
#include <sys/pcpu.h>
|
||||||
#include <sys/timetc.h>
|
#include <sys/timetc.h>
|
||||||
#include <machine/bus.h>
|
#include <machine/bus.h>
|
||||||
|
#include <machine/md_var.h>
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
#include <vm/vm_param.h>
|
#include <vm/vm_param.h>
|
||||||
#include <vm/pmap.h>
|
#include <vm/pmap.h>
|
||||||
@ -44,23 +45,11 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include "hv_vmbus_priv.h"
|
#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
|
#define HV_NANOSECONDS_PER_SEC 1000000000L
|
||||||
|
|
||||||
|
|
||||||
static u_int hv_get_timecount(struct timecounter *tc);
|
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
|
* Globals
|
||||||
*/
|
*/
|
||||||
@ -86,27 +75,10 @@ hv_get_timecount(struct timecounter *tc)
|
|||||||
int
|
int
|
||||||
hv_vmbus_query_hypervisor_presence(void)
|
hv_vmbus_query_hypervisor_presence(void)
|
||||||
{
|
{
|
||||||
u_int regs[4];
|
if (vm_guest != VM_GUEST_HV)
|
||||||
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)
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
do_cpuid(1, regs);
|
return (hv_high >= HV_X64_CPUID_MIN && hv_high <= HV_X64_CPUID_MAX);
|
||||||
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", ®s[1], 12);
|
|
||||||
}
|
|
||||||
return (hyper_v_detected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,10 +87,7 @@ hv_vmbus_query_hypervisor_presence(void)
|
|||||||
static int
|
static int
|
||||||
hv_vmbus_get_hypervisor_version(void)
|
hv_vmbus_get_hypervisor_version(void)
|
||||||
{
|
{
|
||||||
unsigned int eax;
|
u_int regs[4];
|
||||||
unsigned int ebx;
|
|
||||||
unsigned int ecx;
|
|
||||||
unsigned int edx;
|
|
||||||
unsigned int maxLeaf;
|
unsigned int maxLeaf;
|
||||||
unsigned int op;
|
unsigned int op;
|
||||||
|
|
||||||
@ -127,28 +96,16 @@ hv_vmbus_get_hypervisor_version(void)
|
|||||||
* Viridian is present
|
* Viridian is present
|
||||||
* Query id and revision.
|
* Query id and revision.
|
||||||
*/
|
*/
|
||||||
eax = 0;
|
|
||||||
ebx = 0;
|
|
||||||
ecx = 0;
|
|
||||||
edx = 0;
|
|
||||||
op = HV_CPU_ID_FUNCTION_HV_VENDOR_AND_MAX_FUNCTION;
|
op = HV_CPU_ID_FUNCTION_HV_VENDOR_AND_MAX_FUNCTION;
|
||||||
do_cpuid_inline(op, &eax, &ebx, &ecx, &edx);
|
do_cpuid(op, regs);
|
||||||
|
|
||||||
maxLeaf = eax;
|
maxLeaf = regs[0];
|
||||||
eax = 0;
|
|
||||||
ebx = 0;
|
|
||||||
ecx = 0;
|
|
||||||
edx = 0;
|
|
||||||
op = HV_CPU_ID_FUNCTION_HV_INTERFACE;
|
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) {
|
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;
|
op = HV_CPU_ID_FUNCTION_MS_HV_VERSION;
|
||||||
do_cpuid_inline(op, &eax, &ebx, &ecx, &edx);
|
do_cpuid(op, regs);
|
||||||
}
|
}
|
||||||
return (maxLeaf);
|
return (maxLeaf);
|
||||||
}
|
}
|
||||||
@ -255,6 +212,8 @@ hv_vmbus_init(void)
|
|||||||
hv_vmbus_g_context.hypercall_page = virt_addr;
|
hv_vmbus_g_context.hypercall_page = virt_addr;
|
||||||
|
|
||||||
tc_init(&hv_timecounter); /* register virtual timecount */
|
tc_init(&hv_timecounter); /* register virtual timecount */
|
||||||
|
|
||||||
|
hv_et_init();
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
#include <sys/module.h>
|
#include <sys/module.h>
|
||||||
|
#include <sys/proc.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <sys/syslog.h>
|
#include <sys/syslog.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
@ -60,13 +61,15 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include "hv_vmbus_priv.h"
|
#include "hv_vmbus_priv.h"
|
||||||
|
|
||||||
|
#include <contrib/dev/acpica/include/acpi.h>
|
||||||
#define VMBUS_IRQ 0x5
|
#include "acpi_if.h"
|
||||||
|
|
||||||
static device_t vmbus_devp;
|
static device_t vmbus_devp;
|
||||||
static int vmbus_inited;
|
static int vmbus_inited;
|
||||||
static hv_setup_args setup_args; /* only CPU 0 supported at this time */
|
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
|
* @brief Software interrupt thread routine to handle channel messages from
|
||||||
* the hypervisor.
|
* the hypervisor.
|
||||||
@ -151,7 +154,7 @@ vmbus_msg_swintr(void *arg)
|
|||||||
* message to process - an event or a channel message.
|
* message to process - an event or a channel message.
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline int
|
||||||
hv_vmbus_isr(void *unused)
|
hv_vmbus_isr(struct trapframe *frame)
|
||||||
{
|
{
|
||||||
int cpu;
|
int cpu;
|
||||||
hv_vmbus_message* msg;
|
hv_vmbus_message* msg;
|
||||||
@ -191,41 +194,57 @@ hv_vmbus_isr(void *unused)
|
|||||||
page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu];
|
page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu];
|
||||||
msg = (hv_vmbus_message*) page_addr + HV_VMBUS_MESSAGE_SINT;
|
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) {
|
if (msg->header.message_type != HV_MESSAGE_TYPE_NONE) {
|
||||||
swi_sched(hv_vmbus_g_context.msg_swintr[cpu], 0);
|
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_swintr_event_cpu[MAXCPU];
|
||||||
uint32_t hv_vmbus_intr_cpu[MAXCPU];
|
u_long *hv_vmbus_intr_cpu[MAXCPU];
|
||||||
|
|
||||||
void
|
void
|
||||||
hv_vector_handler(struct trapframe *trap_frame)
|
hv_vector_handler(struct trapframe *trap_frame)
|
||||||
{
|
{
|
||||||
#ifdef HV_DEBUG_INTR
|
|
||||||
int cpu;
|
int cpu;
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable preemption.
|
* Disable preemption.
|
||||||
*/
|
*/
|
||||||
critical_enter();
|
critical_enter();
|
||||||
|
|
||||||
#ifdef HV_DEBUG_INTR
|
|
||||||
/*
|
/*
|
||||||
* Do a little interrupt counting.
|
* Do a little interrupt counting.
|
||||||
*/
|
*/
|
||||||
cpu = PCPU_GET(cpuid);
|
cpu = PCPU_GET(cpuid);
|
||||||
hv_vmbus_intr_cpu[cpu]++;
|
(*hv_vmbus_intr_cpu[cpu])++;
|
||||||
hv_intr_count++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
hv_vmbus_isr(NULL);
|
hv_vmbus_isr(trap_frame);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable preemption.
|
* Enable preemption.
|
||||||
@ -350,25 +369,15 @@ hv_vmbus_child_device_unregister(struct hv_device *child_dev)
|
|||||||
return(ret);
|
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
|
static int
|
||||||
vmbus_probe(device_t dev) {
|
vmbus_probe(device_t dev) {
|
||||||
if(bootverbose)
|
if (ACPI_ID_PROBE(device_get_parent(dev), dev, vmbus_ids) == NULL ||
|
||||||
device_printf(dev, "VMBUS: probe\n");
|
device_get_unit(dev) != 0)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
device_set_desc(dev, "Vmbus Devices");
|
device_set_desc(dev, "Vmbus Devices");
|
||||||
|
|
||||||
return (BUS_PROBE_NOWILDCARD);
|
return (BUS_PROBE_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HYPERV
|
#ifdef HYPERV
|
||||||
@ -462,6 +471,7 @@ static int
|
|||||||
vmbus_bus_init(void)
|
vmbus_bus_init(void)
|
||||||
{
|
{
|
||||||
int i, j, n, ret;
|
int i, j, n, ret;
|
||||||
|
char buf[MAXCOMLEN + 1];
|
||||||
|
|
||||||
if (vmbus_inited)
|
if (vmbus_inited)
|
||||||
return (0);
|
return (0);
|
||||||
@ -498,13 +508,15 @@ vmbus_bus_init(void)
|
|||||||
setup_args.vector = hv_vmbus_g_context.hv_cb_vector;
|
setup_args.vector = hv_vmbus_g_context.hv_cb_vector;
|
||||||
|
|
||||||
CPU_FOREACH(j) {
|
CPU_FOREACH(j) {
|
||||||
hv_vmbus_intr_cpu[j] = 0;
|
|
||||||
hv_vmbus_swintr_event_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_event_intr_event[j] = NULL;
|
||||||
hv_vmbus_g_context.hv_msg_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.event_swintr[j] = NULL;
|
||||||
hv_vmbus_g_context.msg_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++)
|
for (i = 0; i < 2; i++)
|
||||||
setup_args.page_buffers[2 * j + i] = NULL;
|
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[] = {
|
static device_method_t vmbus_methods[] = {
|
||||||
/** Device interface */
|
/** Device interface */
|
||||||
DEVMETHOD(device_identify, vmbus_identify),
|
|
||||||
DEVMETHOD(device_probe, vmbus_probe),
|
DEVMETHOD(device_probe, vmbus_probe),
|
||||||
DEVMETHOD(device_attach, vmbus_attach),
|
DEVMETHOD(device_attach, vmbus_attach),
|
||||||
DEVMETHOD(device_detach, vmbus_detach),
|
DEVMETHOD(device_detach, vmbus_detach),
|
||||||
@ -745,8 +756,9 @@ static driver_t vmbus_driver = { driver_name, vmbus_methods,0, };
|
|||||||
|
|
||||||
devclass_t vmbus_devclass;
|
devclass_t vmbus_devclass;
|
||||||
|
|
||||||
DRIVER_MODULE(vmbus, nexus, vmbus_driver, vmbus_devclass, vmbus_modevent, 0);
|
DRIVER_MODULE(vmbus, acpi, vmbus_driver, vmbus_devclass, vmbus_modevent, 0);
|
||||||
MODULE_VERSION(vmbus,1);
|
MODULE_DEPEND(vmbus, acpi, 1, 1, 1);
|
||||||
|
MODULE_VERSION(vmbus, 1);
|
||||||
|
|
||||||
/* We want to be started after SMP is initialized */
|
/* We want to be started after SMP is initialized */
|
||||||
SYSINIT(vmb_init, SI_SUB_SMP + 1, SI_ORDER_FIRST, vmbus_init, NULL);
|
SYSINIT(vmb_init, SI_SUB_SMP + 1, SI_ORDER_FIRST, vmbus_init, NULL);
|
||||||
|
@ -359,11 +359,6 @@ typedef struct {
|
|||||||
struct sema control_sema;
|
struct sema control_sema;
|
||||||
} hv_vmbus_connection;
|
} hv_vmbus_connection;
|
||||||
|
|
||||||
/*
|
|
||||||
* Declare the MSR used to identify the guest OS
|
|
||||||
*/
|
|
||||||
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
|
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
uint64_t as_uint64_t;
|
uint64_t as_uint64_t;
|
||||||
struct {
|
struct {
|
||||||
@ -380,10 +375,6 @@ typedef union {
|
|||||||
} u;
|
} u;
|
||||||
} hv_vmbus_x64_msr_guest_os_id_contents;
|
} 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 {
|
typedef union {
|
||||||
uint64_t as_uint64_t;
|
uint64_t as_uint64_t;
|
||||||
@ -512,6 +503,22 @@ typedef union {
|
|||||||
} u;
|
} u;
|
||||||
} hv_vmbus_synic_sint;
|
} 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
|
* Define syn_ic control register
|
||||||
*/
|
*/
|
||||||
@ -542,8 +549,21 @@ typedef union {
|
|||||||
uint32_t flags32[HV_EVENT_FLAGS_DWORD_COUNT];
|
uint32_t flags32[HV_EVENT_FLAGS_DWORD_COUNT];
|
||||||
} hv_vmbus_synic_event_flags;
|
} 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 */
|
/* 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
|
* Define synthetic interrupt controller model specific registers
|
||||||
@ -571,6 +591,18 @@ typedef union {
|
|||||||
#define HV_X64_MSR_SINT14 (0x4000009E)
|
#define HV_X64_MSR_SINT14 (0x4000009E)
|
||||||
#define HV_X64_MSR_SINT15 (0x4000009F)
|
#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
|
* 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);
|
int hv_vmbus_set_event(hv_vmbus_channel *channel);
|
||||||
void hv_vmbus_on_events(void *);
|
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.
|
* The guest OS needs to register the guest ID with the hypervisor.
|
||||||
|
@ -852,6 +852,8 @@ ioat_op_generic(struct ioat_softc *ioat, uint8_t op,
|
|||||||
|
|
||||||
if ((flags & DMA_INT_EN) != 0)
|
if ((flags & DMA_INT_EN) != 0)
|
||||||
hw_desc->u.control_generic.int_enable = 1;
|
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->size = size;
|
||||||
hw_desc->src_addr = src;
|
hw_desc->src_addr = src;
|
||||||
|
@ -46,7 +46,13 @@ __FBSDID("$FreeBSD$");
|
|||||||
* descriptor without blocking.
|
* descriptor without blocking.
|
||||||
*/
|
*/
|
||||||
#define DMA_NO_WAIT 0x2
|
#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
|
* Hardware revision number. Different hardware revisions support different
|
||||||
|
@ -45,6 +45,52 @@ extern "C" {
|
|||||||
#define EF10_MAX_PIOBUF_NBUFS MEDFORD_PIOBUF_NBUFS
|
#define EF10_MAX_PIOBUF_NBUFS MEDFORD_PIOBUF_NBUFS
|
||||||
#endif
|
#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
|
#ifdef __cplusplus
|
||||||
|
@ -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_DECODE_INTR_FATAL 1
|
||||||
|
|
||||||
|
#define EFSYS_OPT_LICENSING 0
|
||||||
|
|
||||||
/* ID */
|
/* ID */
|
||||||
|
|
||||||
typedef struct __efsys_identifier_s efsys_identifier_t;
|
typedef struct __efsys_identifier_s efsys_identifier_t;
|
||||||
|
@ -1071,6 +1071,7 @@ efx_bist_stop(
|
|||||||
#define EFX_FEATURE_TX_SRC_FILTERS 0x00000400
|
#define EFX_FEATURE_TX_SRC_FILTERS 0x00000400
|
||||||
#define EFX_FEATURE_PIO_BUFFERS 0x00000800
|
#define EFX_FEATURE_PIO_BUFFERS 0x00000800
|
||||||
#define EFX_FEATURE_FW_ASSISTED_TSO 0x00001000
|
#define EFX_FEATURE_FW_ASSISTED_TSO 0x00001000
|
||||||
|
#define EFX_FEATURE_FW_ASSISTED_TSO_V2 0x00002000
|
||||||
|
|
||||||
typedef struct efx_nic_cfg_s {
|
typedef struct efx_nic_cfg_s {
|
||||||
uint32_t enc_board_type;
|
uint32_t enc_board_type;
|
||||||
@ -1152,6 +1153,7 @@ typedef struct efx_nic_cfg_s {
|
|||||||
*/
|
*/
|
||||||
uint32_t enc_tx_tso_tcp_header_offset_limit;
|
uint32_t enc_tx_tso_tcp_header_offset_limit;
|
||||||
boolean_t enc_fw_assisted_tso_enabled;
|
boolean_t enc_fw_assisted_tso_enabled;
|
||||||
|
boolean_t enc_fw_assisted_tso_v2_enabled;
|
||||||
boolean_t enc_hw_tx_insert_vlan_enabled;
|
boolean_t enc_hw_tx_insert_vlan_enabled;
|
||||||
/* Datapath firmware vadapter/vport/vswitch support */
|
/* Datapath firmware vadapter/vport/vswitch support */
|
||||||
boolean_t enc_datapath_cap_evb;
|
boolean_t enc_datapath_cap_evb;
|
||||||
@ -1160,6 +1162,8 @@ typedef struct efx_nic_cfg_s {
|
|||||||
/* External port identifier */
|
/* External port identifier */
|
||||||
uint8_t enc_external_port;
|
uint8_t enc_external_port;
|
||||||
uint32_t enc_mcdi_max_payload_length;
|
uint32_t enc_mcdi_max_payload_length;
|
||||||
|
/* VPD may be per-PF or global */
|
||||||
|
boolean_t enc_vpd_is_global;
|
||||||
} efx_nic_cfg_t;
|
} efx_nic_cfg_t;
|
||||||
|
|
||||||
#define EFX_PCI_FUNCTION_IS_PF(_encp) ((_encp)->enc_vf == 0xffff)
|
#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_CPLD,
|
||||||
EFX_NVRAM_FPGA_BACKUP,
|
EFX_NVRAM_FPGA_BACKUP,
|
||||||
EFX_NVRAM_DYNAMIC_CFG,
|
EFX_NVRAM_DYNAMIC_CFG,
|
||||||
|
EFX_NVRAM_LICENSE,
|
||||||
EFX_NVRAM_NTYPES,
|
EFX_NVRAM_NTYPES,
|
||||||
} efx_nvram_type_t;
|
} efx_nvram_type_t;
|
||||||
|
|
||||||
@ -2002,6 +2007,7 @@ efx_tx_fini(
|
|||||||
|
|
||||||
#define EFX_TXQ_CKSUM_IPV4 0x0001
|
#define EFX_TXQ_CKSUM_IPV4 0x0001
|
||||||
#define EFX_TXQ_CKSUM_TCPUDP 0x0002
|
#define EFX_TXQ_CKSUM_TCPUDP 0x0002
|
||||||
|
#define EFX_TXQ_FATSOV2 0x0004
|
||||||
|
|
||||||
extern __checkReturn efx_rc_t
|
extern __checkReturn efx_rc_t
|
||||||
efx_tx_qcreate(
|
efx_tx_qcreate(
|
||||||
@ -2089,6 +2095,21 @@ efx_tx_qdesc_tso_create(
|
|||||||
__in uint8_t tcp_flags,
|
__in uint8_t tcp_flags,
|
||||||
__out efx_desc_t *edp);
|
__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
|
extern void
|
||||||
efx_tx_qdesc_vlantci_create(
|
efx_tx_qdesc_vlantci_create(
|
||||||
__in efx_txq_t *etp,
|
__in efx_txq_t *etp,
|
||||||
@ -2291,6 +2312,57 @@ efx_hash_bytes(
|
|||||||
__in size_t length,
|
__in size_t length,
|
||||||
__in uint32_t init);
|
__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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -401,4 +401,15 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif /* EFSYS_OPT_BIST */
|
#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 */
|
#endif /* _SYS_EFX_CHECK_H */
|
||||||
|
@ -84,6 +84,7 @@ extern "C" {
|
|||||||
#define EFX_MOD_WOL 0x00000800
|
#define EFX_MOD_WOL 0x00000800
|
||||||
#define EFX_MOD_FILTER 0x00001000
|
#define EFX_MOD_FILTER 0x00001000
|
||||||
#define EFX_MOD_PKTFILTER 0x00002000
|
#define EFX_MOD_PKTFILTER 0x00002000
|
||||||
|
#define EFX_MOD_LIC 0x00004000
|
||||||
|
|
||||||
#define EFX_RESET_MAC 0x00000001
|
#define EFX_RESET_MAC 0x00000001
|
||||||
#define EFX_RESET_PHY 0x00000002
|
#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,
|
void (*etxo_qdesc_tso_create)(efx_txq_t *, uint16_t,
|
||||||
uint32_t, uint8_t,
|
uint32_t, uint8_t,
|
||||||
efx_desc_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,
|
void (*etxo_qdesc_vlantci_create)(efx_txq_t *, uint16_t,
|
||||||
efx_desc_t *);
|
efx_desc_t *);
|
||||||
#if EFSYS_OPT_QSTATS
|
#if EFSYS_OPT_QSTATS
|
||||||
@ -358,6 +362,7 @@ typedef struct efx_intr_s {
|
|||||||
|
|
||||||
typedef struct efx_nic_ops_s {
|
typedef struct efx_nic_ops_s {
|
||||||
efx_rc_t (*eno_probe)(efx_nic_t *);
|
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_set_drv_limits)(efx_nic_t *, efx_drv_limits_t*);
|
||||||
efx_rc_t (*eno_reset)(efx_nic_t *);
|
efx_rc_t (*eno_reset)(efx_nic_t *);
|
||||||
efx_rc_t (*eno_init)(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 {
|
typedef struct efx_mcdi_ops_s {
|
||||||
efx_rc_t (*emco_init)(efx_nic_t *, const efx_mcdi_transport_t *);
|
efx_rc_t (*emco_init)(efx_nic_t *, const efx_mcdi_transport_t *);
|
||||||
void (*emco_request_copyin)(efx_nic_t *, efx_mcdi_req_t *,
|
void (*emco_send_request)(efx_nic_t *, void *, size_t,
|
||||||
unsigned int, boolean_t, boolean_t);
|
void *, size_t);
|
||||||
void (*emco_request_copyout)(efx_nic_t *, efx_mcdi_req_t *);
|
|
||||||
efx_rc_t (*emco_poll_reboot)(efx_nic_t *);
|
efx_rc_t (*emco_poll_reboot)(efx_nic_t *);
|
||||||
boolean_t (*emco_poll_response)(efx_nic_t *);
|
boolean_t (*emco_poll_response)(efx_nic_t *);
|
||||||
void (*emco_read_response)(efx_nic_t *, void *, size_t, size_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
|
#if EFSYS_OPT_DIAG
|
||||||
efx_rc_t (*envo_test)(efx_nic_t *);
|
efx_rc_t (*envo_test)(efx_nic_t *);
|
||||||
#endif /* EFSYS_OPT_DIAG */
|
#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,
|
efx_rc_t (*envo_get_version)(efx_nic_t *, efx_nvram_type_t,
|
||||||
uint32_t *, uint16_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,
|
efx_rc_t (*envo_read_chunk)(efx_nic_t *, efx_nvram_type_t,
|
||||||
unsigned int, caddr_t, size_t);
|
unsigned int, caddr_t, size_t);
|
||||||
efx_rc_t (*envo_erase)(efx_nic_t *, efx_nvram_type_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,
|
efx_rc_t (*envo_type_to_partn)(efx_nic_t *, efx_nvram_type_t,
|
||||||
uint32_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;
|
} efx_nvram_ops_t;
|
||||||
#endif /* EFSYS_OPT_NVRAM */
|
#endif /* EFSYS_OPT_NVRAM */
|
||||||
|
|
||||||
@ -587,6 +591,18 @@ efx_mcdi_nvram_test(
|
|||||||
|
|
||||||
#endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */
|
#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 {
|
typedef struct efx_drv_cfg_s {
|
||||||
uint32_t edc_min_vi_count;
|
uint32_t edc_min_vi_count;
|
||||||
uint32_t edc_max_vi_count;
|
uint32_t edc_max_vi_count;
|
||||||
@ -636,6 +652,9 @@ struct efx_nic_s {
|
|||||||
uint32_t en_rss_context;
|
uint32_t en_rss_context;
|
||||||
#endif /* EFSYS_OPT_RX_SCALE */
|
#endif /* EFSYS_OPT_RX_SCALE */
|
||||||
uint32_t en_vport_id;
|
uint32_t en_vport_id;
|
||||||
|
#if EFSYS_OPT_LICENSING
|
||||||
|
efx_lic_ops_t *en_elop;
|
||||||
|
#endif
|
||||||
union {
|
union {
|
||||||
#if EFSYS_OPT_FALCON
|
#if EFSYS_OPT_FALCON
|
||||||
struct {
|
struct {
|
||||||
|
792
sys/dev/sfxge/common/efx_lic.c
Normal file
792
sys/dev/sfxge/common/efx_lic.c
Normal 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 */
|
@ -36,13 +36,32 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#if EFSYS_OPT_MCDI
|
#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
|
#if EFSYS_OPT_SIENA
|
||||||
|
|
||||||
static efx_mcdi_ops_t __efx_mcdi_siena_ops = {
|
static efx_mcdi_ops_t __efx_mcdi_siena_ops = {
|
||||||
siena_mcdi_init, /* emco_init */
|
siena_mcdi_init, /* emco_init */
|
||||||
siena_mcdi_request_copyin, /* emco_request_copyin */
|
siena_mcdi_send_request, /* emco_send_request */
|
||||||
siena_mcdi_request_copyout, /* emco_request_copyout */
|
|
||||||
siena_mcdi_poll_reboot, /* emco_poll_reboot */
|
siena_mcdi_poll_reboot, /* emco_poll_reboot */
|
||||||
siena_mcdi_poll_response, /* emco_poll_response */
|
siena_mcdi_poll_response, /* emco_poll_response */
|
||||||
siena_mcdi_read_response, /* emco_read_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 = {
|
static efx_mcdi_ops_t __efx_mcdi_ef10_ops = {
|
||||||
ef10_mcdi_init, /* emco_init */
|
ef10_mcdi_init, /* emco_init */
|
||||||
ef10_mcdi_request_copyin, /* emco_request_copyin */
|
ef10_mcdi_send_request, /* emco_send_request */
|
||||||
ef10_mcdi_request_copyout, /* emco_request_copyout */
|
|
||||||
ef10_mcdi_poll_reboot, /* emco_poll_reboot */
|
ef10_mcdi_poll_reboot, /* emco_poll_reboot */
|
||||||
ef10_mcdi_poll_response, /* emco_poll_response */
|
ef10_mcdi_poll_response, /* emco_poll_response */
|
||||||
ef10_mcdi_read_response, /* emco_read_response */
|
ef10_mcdi_read_response, /* emco_read_response */
|
||||||
@ -179,26 +197,16 @@ efx_mcdi_new_epoch(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
efx_mcdi_request_copyin(
|
efx_mcdi_send_request(
|
||||||
__in efx_nic_t *enp,
|
__in efx_nic_t *enp,
|
||||||
__in efx_mcdi_req_t *emrp,
|
__in void *hdrp,
|
||||||
__in unsigned int seq,
|
__in size_t hdr_len,
|
||||||
__in boolean_t ev_cpl,
|
__in void *sdup,
|
||||||
__in boolean_t new_epoch)
|
__in size_t sdu_len)
|
||||||
{
|
{
|
||||||
efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop;
|
efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop;
|
||||||
|
|
||||||
emcop->emco_request_copyin(enp, emrp, seq, ev_cpl, new_epoch);
|
emcop->emco_send_request(enp, hdrp, hdr_len, sdup, sdu_len);
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static efx_rc_t
|
static efx_rc_t
|
||||||
@ -241,8 +249,15 @@ efx_mcdi_request_start(
|
|||||||
__in efx_mcdi_req_t *emrp,
|
__in efx_mcdi_req_t *emrp,
|
||||||
__in boolean_t ev_cpl)
|
__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_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 seq;
|
||||||
|
unsigned int xflags;
|
||||||
boolean_t new_epoch;
|
boolean_t new_epoch;
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
@ -269,13 +284,64 @@ efx_mcdi_request_start(
|
|||||||
emip->emi_poll_cnt = 0;
|
emip->emi_poll_cnt = 0;
|
||||||
seq = emip->emi_seq++ & EFX_MASK32(MCDI_HEADER_SEQ);
|
seq = emip->emi_seq++ & EFX_MASK32(MCDI_HEADER_SEQ);
|
||||||
new_epoch = emip->emi_new_epoch;
|
new_epoch = emip->emi_new_epoch;
|
||||||
|
max_version = emip->emi_max_version;
|
||||||
EFSYS_UNLOCK(enp->en_eslp, state);
|
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(
|
efx_mcdi_read_response_header(
|
||||||
__in efx_nic_t *enp,
|
__in efx_nic_t *enp,
|
||||||
__inout efx_mcdi_req_t *emrp)
|
__inout efx_mcdi_req_t *emrp)
|
||||||
@ -384,19 +450,56 @@ efx_mcdi_read_response_header(
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
fail3:
|
fail3:
|
||||||
if (!emrp->emr_quiet)
|
|
||||||
EFSYS_PROBE(fail3);
|
|
||||||
fail2:
|
fail2:
|
||||||
if (!emrp->emr_quiet)
|
|
||||||
EFSYS_PROBE(fail2);
|
|
||||||
fail1:
|
fail1:
|
||||||
if (!emrp->emr_quiet)
|
|
||||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
|
||||||
|
|
||||||
emrp->emr_rc = rc;
|
emrp->emr_rc = rc;
|
||||||
emrp->emr_out_length_used = 0;
|
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
|
__checkReturn boolean_t
|
||||||
efx_mcdi_request_poll(
|
efx_mcdi_request_poll(
|
||||||
@ -444,7 +547,7 @@ efx_mcdi_request_poll(
|
|||||||
if ((rc = emrp->emr_rc) != 0)
|
if ((rc = emrp->emr_rc) != 0)
|
||||||
goto fail2;
|
goto fail2;
|
||||||
|
|
||||||
efx_mcdi_request_copyout(enp, emrp);
|
efx_mcdi_finish_response(enp, emrp);
|
||||||
return (B_TRUE);
|
return (B_TRUE);
|
||||||
|
|
||||||
fail2:
|
fail2:
|
||||||
@ -638,7 +741,6 @@ efx_mcdi_ev_cpl(
|
|||||||
{
|
{
|
||||||
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
|
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
|
||||||
const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
|
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;
|
efx_mcdi_req_t *emrp;
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
@ -680,7 +782,7 @@ efx_mcdi_ev_cpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (errcode == 0) {
|
if (errcode == 0) {
|
||||||
emcop->emco_request_copyout(enp, emrp);
|
efx_mcdi_finish_response(enp, emrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
emtp->emt_ev_cpl(emtp->emt_context);
|
emtp->emt_ev_cpl(emtp->emt_context);
|
||||||
|
@ -88,11 +88,6 @@ efx_mcdi_execute_quiet(
|
|||||||
__in efx_nic_t *enp,
|
__in efx_nic_t *enp,
|
||||||
__inout efx_mcdi_req_t *emrp);
|
__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
|
extern void
|
||||||
efx_mcdi_ev_cpl(
|
efx_mcdi_ev_cpl(
|
||||||
__in efx_nic_t *enp,
|
__in efx_nic_t *enp,
|
||||||
|
@ -244,6 +244,7 @@ efx_nic_biu_test(
|
|||||||
|
|
||||||
static efx_nic_ops_t __efx_nic_falcon_ops = {
|
static efx_nic_ops_t __efx_nic_falcon_ops = {
|
||||||
falcon_nic_probe, /* eno_probe */
|
falcon_nic_probe, /* eno_probe */
|
||||||
|
NULL, /* eno_board_cfg */
|
||||||
NULL, /* eno_set_drv_limits */
|
NULL, /* eno_set_drv_limits */
|
||||||
falcon_nic_reset, /* eno_reset */
|
falcon_nic_reset, /* eno_reset */
|
||||||
falcon_nic_init, /* eno_init */
|
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 = {
|
static efx_nic_ops_t __efx_nic_siena_ops = {
|
||||||
siena_nic_probe, /* eno_probe */
|
siena_nic_probe, /* eno_probe */
|
||||||
|
NULL, /* eno_board_cfg */
|
||||||
NULL, /* eno_set_drv_limits */
|
NULL, /* eno_set_drv_limits */
|
||||||
siena_nic_reset, /* eno_reset */
|
siena_nic_reset, /* eno_reset */
|
||||||
siena_nic_init, /* eno_init */
|
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 = {
|
static efx_nic_ops_t __efx_nic_hunt_ops = {
|
||||||
ef10_nic_probe, /* eno_probe */
|
ef10_nic_probe, /* eno_probe */
|
||||||
|
hunt_board_cfg, /* eno_board_cfg */
|
||||||
ef10_nic_set_drv_limits, /* eno_set_drv_limits */
|
ef10_nic_set_drv_limits, /* eno_set_drv_limits */
|
||||||
ef10_nic_reset, /* eno_reset */
|
ef10_nic_reset, /* eno_reset */
|
||||||
ef10_nic_init, /* eno_init */
|
ef10_nic_init, /* eno_init */
|
||||||
@ -297,6 +300,27 @@ static efx_nic_ops_t __efx_nic_hunt_ops = {
|
|||||||
|
|
||||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
#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
|
__checkReturn efx_rc_t
|
||||||
efx_nic_create(
|
efx_nic_create(
|
||||||
__in efx_family_t family,
|
__in efx_family_t family,
|
||||||
@ -357,10 +381,29 @@ efx_nic_create(
|
|||||||
EFX_FEATURE_MAC_HEADER_FILTERS |
|
EFX_FEATURE_MAC_HEADER_FILTERS |
|
||||||
EFX_FEATURE_MCDI_DMA |
|
EFX_FEATURE_MCDI_DMA |
|
||||||
EFX_FEATURE_PIO_BUFFERS |
|
EFX_FEATURE_PIO_BUFFERS |
|
||||||
EFX_FEATURE_FW_ASSISTED_TSO;
|
EFX_FEATURE_FW_ASSISTED_TSO |
|
||||||
|
EFX_FEATURE_FW_ASSISTED_TSO_V2;
|
||||||
break;
|
break;
|
||||||
#endif /* EFSYS_OPT_HUNTINGTON */
|
#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:
|
default:
|
||||||
rc = ENOTSUP;
|
rc = ENOTSUP;
|
||||||
goto fail2;
|
goto fail2;
|
||||||
@ -665,8 +708,9 @@ efx_nic_reset(
|
|||||||
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
|
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
|
||||||
EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
|
EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
|
||||||
/*
|
/*
|
||||||
* All modules except the MCDI, PROBE, NVRAM, VPD, MON (which we
|
* All modules except the MCDI, PROBE, NVRAM, VPD, MON, LIC
|
||||||
* do not reset here) must have been shut down or never initialized.
|
* (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*
|
* 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
|
* 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 = enp->en_mod_flags;
|
||||||
mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
|
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);
|
EFSYS_ASSERT3U(mod_flags, ==, 0);
|
||||||
if (mod_flags != 0) {
|
if (mod_flags != 0) {
|
||||||
rc = EINVAL;
|
rc = EINVAL;
|
||||||
|
@ -42,15 +42,15 @@ static efx_nvram_ops_t __efx_nvram_falcon_ops = {
|
|||||||
#if EFSYS_OPT_DIAG
|
#if EFSYS_OPT_DIAG
|
||||||
falcon_nvram_test, /* envo_test */
|
falcon_nvram_test, /* envo_test */
|
||||||
#endif /* EFSYS_OPT_DIAG */
|
#endif /* EFSYS_OPT_DIAG */
|
||||||
falcon_nvram_size, /* envo_size */
|
|
||||||
falcon_nvram_get_version, /* envo_get_version */
|
falcon_nvram_get_version, /* envo_get_version */
|
||||||
falcon_nvram_rw_start, /* envo_rw_start */
|
|
||||||
falcon_nvram_read_chunk, /* envo_read_chunk */
|
falcon_nvram_read_chunk, /* envo_read_chunk */
|
||||||
falcon_nvram_erase, /* envo_erase */
|
falcon_nvram_erase, /* envo_erase */
|
||||||
falcon_nvram_write_chunk, /* envo_write_chunk */
|
falcon_nvram_write_chunk, /* envo_write_chunk */
|
||||||
falcon_nvram_rw_finish, /* envo_rw_finish */
|
falcon_nvram_rw_finish, /* envo_rw_finish */
|
||||||
falcon_nvram_set_version, /* envo_set_version */
|
falcon_nvram_set_version, /* envo_set_version */
|
||||||
falcon_nvram_type_to_partn, /* envo_type_to_partn */
|
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 */
|
#endif /* EFSYS_OPT_FALCON */
|
||||||
@ -61,15 +61,15 @@ static efx_nvram_ops_t __efx_nvram_siena_ops = {
|
|||||||
#if EFSYS_OPT_DIAG
|
#if EFSYS_OPT_DIAG
|
||||||
siena_nvram_test, /* envo_test */
|
siena_nvram_test, /* envo_test */
|
||||||
#endif /* EFSYS_OPT_DIAG */
|
#endif /* EFSYS_OPT_DIAG */
|
||||||
siena_nvram_size, /* envo_size */
|
|
||||||
siena_nvram_get_version, /* envo_get_version */
|
siena_nvram_get_version, /* envo_get_version */
|
||||||
siena_nvram_rw_start, /* envo_rw_start */
|
|
||||||
siena_nvram_read_chunk, /* envo_read_chunk */
|
siena_nvram_read_chunk, /* envo_read_chunk */
|
||||||
siena_nvram_erase, /* envo_erase */
|
siena_nvram_erase, /* envo_erase */
|
||||||
siena_nvram_write_chunk, /* envo_write_chunk */
|
siena_nvram_write_chunk, /* envo_write_chunk */
|
||||||
siena_nvram_rw_finish, /* envo_rw_finish */
|
siena_nvram_rw_finish, /* envo_rw_finish */
|
||||||
siena_nvram_set_version, /* envo_set_version */
|
siena_nvram_set_version, /* envo_set_version */
|
||||||
siena_nvram_type_to_partn, /* envo_type_to_partn */
|
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 */
|
#endif /* EFSYS_OPT_SIENA */
|
||||||
@ -80,15 +80,15 @@ static efx_nvram_ops_t __efx_nvram_ef10_ops = {
|
|||||||
#if EFSYS_OPT_DIAG
|
#if EFSYS_OPT_DIAG
|
||||||
ef10_nvram_test, /* envo_test */
|
ef10_nvram_test, /* envo_test */
|
||||||
#endif /* EFSYS_OPT_DIAG */
|
#endif /* EFSYS_OPT_DIAG */
|
||||||
ef10_nvram_size, /* envo_size */
|
|
||||||
ef10_nvram_get_version, /* envo_get_version */
|
ef10_nvram_get_version, /* envo_get_version */
|
||||||
ef10_nvram_rw_start, /* envo_rw_start */
|
|
||||||
ef10_nvram_read_chunk, /* envo_read_chunk */
|
ef10_nvram_read_chunk, /* envo_read_chunk */
|
||||||
ef10_nvram_erase, /* envo_erase */
|
ef10_nvram_erase, /* envo_erase */
|
||||||
ef10_nvram_write_chunk, /* envo_write_chunk */
|
ef10_nvram_write_chunk, /* envo_write_chunk */
|
||||||
ef10_nvram_rw_finish, /* envo_rw_finish */
|
ef10_nvram_rw_finish, /* envo_rw_finish */
|
||||||
ef10_nvram_set_version, /* envo_set_version */
|
ef10_nvram_set_version, /* envo_set_version */
|
||||||
ef10_nvram_type_to_partn, /* envo_type_to_partn */
|
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 */
|
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
|
||||||
@ -178,6 +178,7 @@ efx_nvram_size(
|
|||||||
__out size_t *sizep)
|
__out size_t *sizep)
|
||||||
{
|
{
|
||||||
efx_nvram_ops_t *envop = enp->en_envop;
|
efx_nvram_ops_t *envop = enp->en_envop;
|
||||||
|
uint32_t partn;
|
||||||
efx_rc_t rc;
|
efx_rc_t rc;
|
||||||
|
|
||||||
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
|
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
|
||||||
@ -185,13 +186,19 @@ efx_nvram_size(
|
|||||||
|
|
||||||
EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
|
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;
|
goto fail1;
|
||||||
|
|
||||||
|
if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
|
||||||
|
goto fail2;
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
fail2:
|
||||||
|
EFSYS_PROBE(fail2);
|
||||||
fail1:
|
fail1:
|
||||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||||
|
*sizep = 0;
|
||||||
|
|
||||||
return (rc);
|
return (rc);
|
||||||
}
|
}
|
||||||
@ -230,6 +237,7 @@ efx_nvram_rw_start(
|
|||||||
__out_opt size_t *chunk_sizep)
|
__out_opt size_t *chunk_sizep)
|
||||||
{
|
{
|
||||||
efx_nvram_ops_t *envop = enp->en_envop;
|
efx_nvram_ops_t *envop = enp->en_envop;
|
||||||
|
uint32_t partn;
|
||||||
efx_rc_t rc;
|
efx_rc_t rc;
|
||||||
|
|
||||||
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
|
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);
|
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;
|
goto fail1;
|
||||||
|
|
||||||
|
if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
|
||||||
|
goto fail2;
|
||||||
|
|
||||||
enp->en_nvram_locked = type;
|
enp->en_nvram_locked = type;
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
fail2:
|
||||||
|
EFSYS_PROBE(fail2);
|
||||||
fail1:
|
fail1:
|
||||||
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
EFSYS_PROBE1(fail1, efx_rc_t, rc);
|
||||||
|
|
||||||
|
@ -78,14 +78,14 @@ falconsiena_rx_prefix_hash(
|
|||||||
__in efx_rx_hash_alg_t func,
|
__in efx_rx_hash_alg_t func,
|
||||||
__in uint8_t *buffer);
|
__in uint8_t *buffer);
|
||||||
|
|
||||||
|
#endif /* EFSYS_OPT_RX_SCALE */
|
||||||
|
|
||||||
static __checkReturn efx_rc_t
|
static __checkReturn efx_rc_t
|
||||||
falconsiena_rx_prefix_pktlen(
|
falconsiena_rx_prefix_pktlen(
|
||||||
__in efx_nic_t *enp,
|
__in efx_nic_t *enp,
|
||||||
__in uint8_t *buffer,
|
__in uint8_t *buffer,
|
||||||
__out uint16_t *lengthp);
|
__out uint16_t *lengthp);
|
||||||
|
|
||||||
#endif /* EFSYS_OPT_RX_SCALE */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
falconsiena_rx_qpost(
|
falconsiena_rx_qpost(
|
||||||
__in efx_rxq_t *erp,
|
__in efx_rxq_t *erp,
|
||||||
|
@ -142,6 +142,7 @@ static efx_tx_ops_t __efx_tx_falcon_ops = {
|
|||||||
falconsiena_tx_qdesc_post, /* etxo_qdesc_post */
|
falconsiena_tx_qdesc_post, /* etxo_qdesc_post */
|
||||||
falconsiena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
|
falconsiena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
|
||||||
NULL, /* etxo_qdesc_tso_create */
|
NULL, /* etxo_qdesc_tso_create */
|
||||||
|
NULL, /* etxo_qdesc_tso2_create */
|
||||||
NULL, /* etxo_qdesc_vlantci_create */
|
NULL, /* etxo_qdesc_vlantci_create */
|
||||||
#if EFSYS_OPT_QSTATS
|
#if EFSYS_OPT_QSTATS
|
||||||
falconsiena_tx_qstats_update, /* etxo_qstats_update */
|
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_post, /* etxo_qdesc_post */
|
||||||
falconsiena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
|
falconsiena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
|
||||||
NULL, /* etxo_qdesc_tso_create */
|
NULL, /* etxo_qdesc_tso_create */
|
||||||
|
NULL, /* etxo_qdesc_tso2_create */
|
||||||
NULL, /* etxo_qdesc_vlantci_create */
|
NULL, /* etxo_qdesc_vlantci_create */
|
||||||
#if EFSYS_OPT_QSTATS
|
#if EFSYS_OPT_QSTATS
|
||||||
falconsiena_tx_qstats_update, /* etxo_qstats_update */
|
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_post, /* etxo_qdesc_post */
|
||||||
ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
|
ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
|
||||||
hunt_tx_qdesc_tso_create, /* etxo_qdesc_tso_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 */
|
ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
|
||||||
#if EFSYS_OPT_QSTATS
|
#if EFSYS_OPT_QSTATS
|
||||||
ef10_tx_qstats_update, /* etxo_qstats_update */
|
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_post, /* etxo_qdesc_post */
|
||||||
ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
|
ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
|
||||||
NULL, /* etxo_qdesc_tso_create */
|
NULL, /* etxo_qdesc_tso_create */
|
||||||
|
ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
|
||||||
ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
|
ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
|
||||||
#if EFSYS_OPT_QSTATS
|
#if EFSYS_OPT_QSTATS
|
||||||
ef10_tx_qstats_update, /* etxo_qstats_update */
|
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);
|
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
|
void
|
||||||
efx_tx_qdesc_vlantci_create(
|
efx_tx_qdesc_vlantci_create(
|
||||||
__in efx_txq_t *etp,
|
__in efx_txq_t *etp,
|
||||||
|
@ -669,7 +669,7 @@ efx_vpd_hunk_next(
|
|||||||
__in size_t size,
|
__in size_t size,
|
||||||
__out efx_vpd_tag_t *tagp,
|
__out efx_vpd_tag_t *tagp,
|
||||||
__out efx_vpd_keyword_t *keywordp,
|
__out efx_vpd_keyword_t *keywordp,
|
||||||
__out_bcount_opt(*paylenp) unsigned int *payloadp,
|
__out_opt unsigned int *payloadp,
|
||||||
__out_opt uint8_t *paylenp,
|
__out_opt uint8_t *paylenp,
|
||||||
__inout unsigned int *contp)
|
__inout unsigned int *contp)
|
||||||
{
|
{
|
||||||
@ -689,12 +689,18 @@ efx_vpd_hunk_next(
|
|||||||
if ((rc = efx_vpd_next_tag(data, size, &offset,
|
if ((rc = efx_vpd_next_tag(data, size, &offset,
|
||||||
&tag, &taglen)) != 0)
|
&tag, &taglen)) != 0)
|
||||||
goto fail1;
|
goto fail1;
|
||||||
if (tag == EFX_VPD_END)
|
|
||||||
|
if (tag == EFX_VPD_END) {
|
||||||
|
keyword = 0;
|
||||||
|
paylen = 0;
|
||||||
|
index = 0;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (tag == EFX_VPD_ID) {
|
if (tag == EFX_VPD_ID) {
|
||||||
if (index == *contp) {
|
if (index++ == *contp) {
|
||||||
EFSYS_ASSERT3U(taglen, <, 0x100);
|
EFSYS_ASSERT3U(taglen, <, 0x100);
|
||||||
|
keyword = 0;
|
||||||
paylen = (uint8_t)MIN(taglen, 0xff);
|
paylen = (uint8_t)MIN(taglen, 0xff);
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
@ -705,7 +711,7 @@ efx_vpd_hunk_next(
|
|||||||
taglen, pos, &keyword, &keylen)) != 0)
|
taglen, pos, &keyword, &keylen)) != 0)
|
||||||
goto fail2;
|
goto fail2;
|
||||||
|
|
||||||
if (index == *contp) {
|
if (index++ == *contp) {
|
||||||
offset += pos + 3;
|
offset += pos + 3;
|
||||||
paylen = keylen;
|
paylen = keylen;
|
||||||
|
|
||||||
@ -717,9 +723,6 @@ efx_vpd_hunk_next(
|
|||||||
offset += taglen;
|
offset += taglen;
|
||||||
}
|
}
|
||||||
|
|
||||||
*contp = 0;
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
*tagp = tag;
|
*tagp = tag;
|
||||||
*keywordp = keyword;
|
*keywordp = keyword;
|
||||||
@ -728,7 +731,7 @@ efx_vpd_hunk_next(
|
|||||||
if (paylenp != NULL)
|
if (paylenp != NULL)
|
||||||
*paylenp = paylen;
|
*paylenp = paylen;
|
||||||
|
|
||||||
++(*contp);
|
*contp = index;
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
fail2:
|
fail2:
|
||||||
|
@ -444,9 +444,9 @@ ef10_ev_qmoderate(
|
|||||||
eep->ee_index, &dword, 0);
|
eep->ee_index, &dword, 0);
|
||||||
} else {
|
} else {
|
||||||
EFX_POPULATE_DWORD_2(dword,
|
EFX_POPULATE_DWORD_2(dword,
|
||||||
FRF_CZ_TC_TIMER_MODE, mode,
|
ERF_DZ_TC_TIMER_MODE, mode,
|
||||||
FRF_CZ_TC_TIMER_VAL, timer_val);
|
ERF_DZ_TC_TIMER_VAL, timer_val);
|
||||||
EFX_BAR_TBL_WRITED(enp, FR_BZ_TIMER_COMMAND_REGP0,
|
EFX_BAR_TBL_WRITED(enp, ER_DZ_EVQ_TMR_REG,
|
||||||
eep->ee_index, &dword, 0);
|
eep->ee_index, &dword, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user