Merge ^/head r274961 through r275684.

This commit is contained in:
Dimitry Andric 2014-12-10 19:24:42 +00:00
commit 377af4f123
67 changed files with 2717 additions and 271 deletions

View File

@ -5,8 +5,7 @@ MAN = freebsd-version.1
CLEANFILES = freebsd-version.sh
NEWVERS = ${.CURDIR}/../../sys/conf/newvers.sh
freebsd-version.sh.in: ${NEWVERS}
freebsd-version.sh: ${.CURDIR}/freebsd-version.sh.in
freebsd-version.sh: ${.CURDIR}/freebsd-version.sh.in ${NEWVERS}
eval $$(egrep '^(TYPE|REVISION|BRANCH)=' ${NEWVERS}) ; \
if ! sed -e "\
s/@@TYPE@@/$${TYPE}/g; \

View File

@ -1,5 +1,5 @@
.\" $File: file.man,v 1.106 2014/03/07 23:11:51 christos Exp $
.Dd January 30, 2014
.Dd December 3, 2014
.Dt FILE __CSECTION__
.Os
.Sh NAME
@ -385,6 +385,7 @@ options.
.Xr hexdump 1 ,
.Xr od 1 ,
.Xr strings 1 ,
.Xr fstyp 8
.Sh STANDARDS CONFORMANCE
This program is believed to exceed the System V Interface Definition
of FILE(CMD), as near as one can determine from the vague language

View File

@ -35,10 +35,12 @@
switch (type) {
#ifdef ELFCORE
case ET_CORE:
phnum = elf_getu16(swap, elfhdr.e_phnum);
if (phnum > MAX_PHNUM)
return toomany(ms, "program", phnum);
flags |= FLAGS_IS_CORE;
if (dophn_core(ms, clazz, swap, fd,
(off_t)elf_getu(swap, elfhdr.e_phoff),
elf_getu16(swap, elfhdr.e_phnum),
(off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
(size_t)elf_getu16(swap, elfhdr.e_phentsize),
fsize, &flags) == -1)
return -1;
@ -46,18 +48,24 @@
#endif
case ET_EXEC:
case ET_DYN:
phnum = elf_getu16(swap, elfhdr.e_phnum);
if (phnum > MAX_PHNUM)
return toomany(ms, "program", phnum);
shnum = elf_getu16(swap, elfhdr.e_shnum);
if (shnum > MAX_SHNUM)
return toomany(ms, "section", shnum);
if (dophn_exec(ms, clazz, swap, fd,
(off_t)elf_getu(swap, elfhdr.e_phoff),
elf_getu16(swap, elfhdr.e_phnum),
(off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
(size_t)elf_getu16(swap, elfhdr.e_phentsize),
fsize, &flags, elf_getu16(swap, elfhdr.e_shnum))
== -1)
fsize, &flags, shnum) == -1)
return -1;
/*FALLTHROUGH*/
case ET_REL:
shnum = elf_getu16(swap, elfhdr.e_shnum);
if (shnum > MAX_SHNUM)
return toomany(ms, "section", shnum);
if (doshn(ms, clazz, swap, fd,
(off_t)elf_getu(swap, elfhdr.e_shoff),
elf_getu16(swap, elfhdr.e_shnum),
(off_t)elf_getu(swap, elfhdr.e_shoff), shnum,
(size_t)elf_getu16(swap, elfhdr.e_shentsize),
fsize, &flags, elf_getu16(swap, elfhdr.e_machine),
(int)elf_getu16(swap, elfhdr.e_shstrndx)) == -1)

View File

@ -482,6 +482,14 @@ protected int file_regexec(file_regex_t *, const char *, size_t, regmatch_t *,
protected void file_regfree(file_regex_t *);
protected void file_regerror(file_regex_t *, int, struct magic_set *);
typedef struct {
char *buf;
uint32_t offset;
} file_pushbuf_t;
protected file_pushbuf_t *file_push_buffer(struct magic_set *);
protected char *file_pop_buffer(struct magic_set *, file_pushbuf_t *);
#ifndef COMPILE_ONLY
extern const char *file_names[];
extern const size_t file_nnames;

View File

@ -491,3 +491,43 @@ file_regerror(file_regex_t *rx, int rc, struct magic_set *ms)
file_magerror(ms, "regex error %d for `%s', (%s)", rc, rx->pat,
errmsg);
}
protected file_pushbuf_t *
file_push_buffer(struct magic_set *ms)
{
file_pushbuf_t *pb;
if (ms->event_flags & EVENT_HAD_ERR)
return NULL;
if ((pb = (CAST(file_pushbuf_t *, malloc(sizeof(*pb))))) == NULL)
return NULL;
pb->buf = ms->o.buf;
pb->offset = ms->offset;
ms->o.buf = NULL;
ms->offset = 0;
return pb;
}
protected char *
file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb)
{
char *rbuf;
if (ms->event_flags & EVENT_HAD_ERR) {
free(pb->buf);
free(pb);
return NULL;
}
rbuf = ms->o.buf;
ms->o.buf = pb->buf;
ms->offset = pb->offset;
free(pb);
return rbuf;
}

View File

@ -60,6 +60,18 @@ private uint16_t getu16(int, uint16_t);
private uint32_t getu32(int, uint32_t);
private uint64_t getu64(int, uint64_t);
#define MAX_PHNUM 256
#define MAX_SHNUM 1024
private int
toomany(struct magic_set *ms, const char *name, uint16_t num)
{
if (file_printf(ms, ", too many %s header sections (%u)", name, num
) == -1)
return -1;
return 0;
}
private uint16_t
getu16(int swap, uint16_t value)
{
@ -477,6 +489,13 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
uint32_t namesz, descsz;
unsigned char *nbuf = CAST(unsigned char *, vbuf);
if (xnh_sizeof + offset > size) {
/*
* We're out of note headers.
*/
return xnh_sizeof + offset;
}
(void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
offset += xnh_sizeof;
@ -492,13 +511,13 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
if (namesz & 0x80000000) {
(void)file_printf(ms, ", bad note name size 0x%lx",
(unsigned long)namesz);
return offset;
return 0;
}
if (descsz & 0x80000000) {
(void)file_printf(ms, ", bad note description size 0x%lx",
(unsigned long)descsz);
return offset;
return 0;
}
@ -900,6 +919,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
Elf32_Shdr sh32;
Elf64_Shdr sh64;
int stripped = 1;
size_t nbadcap = 0;
void *nbuf;
off_t noff, coff, name_off;
uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */
@ -988,6 +1008,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
goto skip;
}
if (nbadcap > 5)
break;
if (lseek(fd, xsh_offset, SEEK_SET) == (off_t)-1) {
file_badseek(ms);
return -1;
@ -1053,6 +1075,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
(unsigned long long)xcap_tag,
(unsigned long long)xcap_val) == -1)
return -1;
if (nbadcap++ > 2)
coff = xsh_size;
break;
}
}
@ -1233,7 +1257,7 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
int flags = 0;
Elf32_Ehdr elf32hdr;
Elf64_Ehdr elf64hdr;
uint16_t type;
uint16_t type, phnum, shnum;
if (ms->flags & (MAGIC_MIME|MAGIC_APPLE))
return 0;

View File

@ -67,6 +67,9 @@ private void cvt_32(union VALUETYPE *, const struct magic *);
private void cvt_64(union VALUETYPE *, const struct magic *);
#define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o)))
#define MAX_RECURSION_LEVEL 10
/*
* softmagic - lookup one file in parsed, in-memory copy of database
* Passed the name and FILE * of one file to be typed.
@ -1193,14 +1196,15 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
int flip, int recursion_level, int *printed_something,
int *need_separator, int *returnval)
{
uint32_t soffset, offset = ms->offset;
uint32_t offset = ms->offset;
uint32_t lhs;
file_pushbuf_t *pb;
int rv, oneed_separator, in_type;
char *sbuf, *rbuf;
char *rbuf;
union VALUETYPE *p = &ms->ms_value;
struct mlist ml;
if (recursion_level >= 20) {
if (recursion_level >= MAX_RECURSION_LEVEL) {
file_error(ms, 0, "recursion nesting exceeded");
return -1;
}
@ -1644,19 +1648,23 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
case FILE_INDIRECT:
if (offset == 0)
return 0;
if (nbytes < offset)
return 0;
sbuf = ms->o.buf;
soffset = ms->offset;
ms->o.buf = NULL;
ms->offset = 0;
if ((pb = file_push_buffer(ms)) == NULL)
return -1;
rv = file_softmagic(ms, s + offset, nbytes - offset,
recursion_level, BINTEST, text);
if ((ms->flags & MAGIC_DEBUG) != 0)
fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv);
rbuf = ms->o.buf;
ms->o.buf = sbuf;
ms->offset = soffset;
rbuf = file_pop_buffer(ms, pb);
if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR)
return -1;
if (rv == 1) {
if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 &&
file_printf(ms, F(ms, m, "%u"), offset) == -1) {
@ -1674,13 +1682,13 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
case FILE_USE:
if (nbytes < offset)
return 0;
sbuf = m->value.s;
if (*sbuf == '^') {
sbuf++;
rbuf = m->value.s;
if (*rbuf == '^') {
rbuf++;
flip = !flip;
}
if (file_magicfind(ms, sbuf, &ml) == -1) {
file_error(ms, 0, "cannot find entry `%s'", sbuf);
if (file_magicfind(ms, rbuf, &ml) == -1) {
file_error(ms, 0, "cannot find entry `%s'", rbuf);
return -1;
}

View File

@ -3,3 +3,6 @@
# Automounter master map, see auto_master(5) for details.
#
/net -hosts -nobrowse,nosuid
# When using the -media special map, make sure to edit devd.conf(5)
# to move the call to "automount -c" out of the comments section.
#/media -media -nosuid

View File

@ -1,6 +1,6 @@
# $FreeBSD$
FILES= include_ldap special_hosts special_null
FILES= include_ldap special_hosts special_media special_null
NO_OBJ=
FILESDIR= /etc/autofs

93
etc/autofs/special_media Executable file
View File

@ -0,0 +1,93 @@
#!/bin/sh
#
# $FreeBSD$
#
# Print newline-separated list of devices available for mounting.
# If there is a filesystem label - use it, otherwise use device name.
print_available() {
local _fstype _fstype_and_label _label _p
for _p in ${providers}; do
_fstype_and_label="$(fstyp -l "/dev/${_p}" 2> /dev/null)"
if [ $? -ne 0 ]; then
# Ignore devices for which we were unable
# to determine filesystem type.
continue
fi
_fstype="${_fstype_and_label%% *}"
if [ "${_fstype}" != "${_fstype_and_label}" ]; then
_label="${_fstype_and_label#* }"
echo "${_label}"
continue
fi
echo "${_p}"
done
}
# Print a single map entry.
print_one() {
local _fstype _fstype_and_label _label _key _p
_key="$1"
_fstype="$(fstyp "/dev/${_key}" 2> /dev/null)"
if [ $? -eq 0 ]; then
echo "-fstype=${_fstype},nosuid :/dev/${_key}"
return
fi
for _p in ${providers}; do
_fstype_and_label="$(fstyp -l "/dev/${_p}" 2> /dev/null)"
if [ $? -ne 0 ]; then
# Ignore devices for which we were unable
# to determine filesystem type.
continue
fi
_fstype="${_fstype_and_label%% *}"
if [ "${_fstype}" = "${_fstype_and_label}" ]; then
# No label, try another device.
continue
fi
_label="${_fstype_and_label#* }"
if [ "${_label}" != "${_key}" ]; then
# Labels don't match, try another device.
continue
fi
echo "-fstype=${_fstype},nosuid :/dev/${_p}"
done
# No matching device - don't print anything, autofs will handle it.
}
# Obtain a list of (geom-provider-name, access-count) pairs, turning this:
#
# z0xfffff80005085d00 [shape=hexagon,label="ada0\nr2w2e3\nerr#0\nsector=512\nstripe=0"];
#
# Into this:
#
# ada0 r2w2e3
#
# XXX: It would be easier to use kern.geom.conftxt instead, but it lacks
# access counts.
pairs=$(sysctl kern.geom.confdot | sed -n 's/^.*hexagon,label="\([^\]*\)\\n\([^\]*\).*/\1 \2/p')
# Obtain a list of GEOM providers that are not already open - not mounted,
# and without other GEOM class, such as gpart, attached. In other words,
# grep for "r0w0e0". Skip providers with names containing slashes; we're
# not interested in geom_label(4) creations.
providers=$(echo "$pairs" | awk '$2 == "r0w0e0" && $1 !~ /\// { print $1 }')
if [ $# -eq 0 ]; then
print_available
exit 0
fi
print_one "$1"
exit 0

View File

@ -318,4 +318,16 @@ notify 0 {
action "/usr/local/etc/rc.d/postgresql restart";
};
# Discard autofs caches, useful for the -media special map. The one
# second delay is for GEOM to finish tasting.
#
# XXX: We should probably have a devctl(4) event that fires after GEOM
# tasting.
#
notify 100 {
match "system" "DEVFS";
match "cdev" "(da|mmcsd)[0-9]+";
action "sleep 1 && /usr/sbin/automount -c";
};
*/

View File

@ -96,7 +96,7 @@ kgdb_thr_add_procs(uintptr_t paddr)
kt->kaddr = addr;
if (td.td_tid == dumptid)
kt->pcb = dumppcb;
else if (td.td_state == TDS_RUNNING &&
else if (td.td_oncpu != NOCPU &&
CPU_ISSET(td.td_oncpu, &stopped_cpus))
kt->pcb = kgdb_trgt_core_pcb(td.td_oncpu);
else

View File

@ -886,7 +886,7 @@ sctp_recvv(int sd,
struct sctp_rcvinfo *rcvinfo;
struct sctp_nxtinfo *nxtinfo;
if (((info != NULL) && (infolen == NULL)) |
if (((info != NULL) && (infolen == NULL)) ||
((info == NULL) && (infolen != NULL) && (*infolen != 0)) ||
((info != NULL) && (infotype == NULL))) {
errno = EINVAL;

View File

@ -124,11 +124,13 @@ __sflush(FILE *fp)
t = _swrite(fp, (char *)p, n);
if (t <= 0) {
/* Reset _p and _w. */
if (p > fp->_p) /* Some was written. */
if (p > fp->_p) {
/* Some was written. */
memmove(fp->_p, p, n);
fp->_p += n;
if ((fp->_flags & (__SLBF | __SNBF)) == 0)
fp->_w -= n;
fp->_p += n;
if ((fp->_flags & (__SLBF | __SNBF)) == 0)
fp->_w -= n;
}
fp->_flags |= __SERR;
return (EOF);
}

View File

@ -28,7 +28,7 @@
.\" @(#)mount.8 8.8 (Berkeley) 6/16/94
.\" $FreeBSD$
.\"
.Dd November 22, 2014
.Dd December 3, 2014
.Dt MOUNT 8
.Os
.Sh NAME
@ -549,6 +549,7 @@ support for a particular file system might be provided either on a static
.Xr fstab 5 ,
.Xr procfs 5 ,
.Xr automount 8 ,
.Xr fstyp 8 ,
.Xr kldload 8 ,
.Xr mount_cd9660 8 ,
.Xr mount_msdosfs 8 ,

View File

@ -26,5 +26,6 @@ dev/mmc/host/dwmmc.c optional dwmmc
# BERI specific
dev/beri/beri_ring.c optional beri_ring
dev/beri/beri_mem.c optional beri_mem
dev/beri/virtio/virtio.c optional beri_vtblk
dev/beri/virtio/virtio.c optional beri_vtblk | vtbe
dev/beri/virtio/virtio_block.c optional beri_vtblk
dev/beri/virtio/network/if_vtbe.c optional vtbe

View File

@ -84,6 +84,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>

View File

@ -142,14 +142,13 @@ bcmwd_watchdog_fn(void *private, u_int cmd, int *error)
if (cmd > 0) {
sec = ((uint64_t)1 << (cmd & WD_INTERVAL)) / 1000000000;
ticks = (sec << 16) & BCM2835_WDOG_TIME_MASK;
if (ticks == 0) {
if (sec == 0 || sec > 15) {
/*
* Can't arm
* disable watchdog as watchdog(9) requires
*/
device_printf(sc->dev,
"Can't arm, timeout is less than 1 second\n");
"Can't arm, timeout must be between 1-15 seconds\n");
WRITE(sc, BCM2835_RSTC_REG,
(BCM2835_PASWORD << BCM2835_PASSWORD_SHIFT) |
BCM2835_RSTC_RESET);
@ -157,6 +156,7 @@ bcmwd_watchdog_fn(void *private, u_int cmd, int *error)
return;
}
ticks = (sec << 16) & BCM2835_WDOG_TIME_MASK;
reg = (BCM2835_PASWORD << BCM2835_PASSWORD_SHIFT) | ticks;
WRITE(sc, BCM2835_WDOG_REG, reg);

View File

@ -123,6 +123,7 @@ device spibus
device beri_ring
device beri_mem
device beri_vtblk
device vtbe
device altera_pio
# Ethernet

View File

@ -39,7 +39,8 @@
compatible = "altr,socfpga-cyclone5", "altr,socfpga";
memreserve = < 0x00000000 0x1000 >, /* SMP trampoline */
< 0x00001000 0x1000 >; /* virtio block */
< 0x00001000 0x1000 >, /* virtio block */
< 0x00002000 0x1000 >; /* virtio net */
memory {
device_type = "memory";
@ -111,6 +112,15 @@
pio-recv = <&pio0>;
pio-send = <&pio1>;
beri-mem = <&beri_mem0>;
status = "disabled";
};
beri_vtnet: vtnet@00002000 {
compatible = "sri-cambridge,beri-vtnet";
reg = <0x00002000 0x1000>;
pio-recv = <&pio0>;
pio-send = <&pio1>;
beri-mem = <&beri_mem0>;
status = "okay";
};

View File

@ -2651,6 +2651,7 @@ dev/xen/blkback/blkback.c optional xen | xenhvm
dev/xen/console/console.c optional xen | xenhvm
dev/xen/console/xencons_ring.c optional xen | xenhvm
dev/xen/control/control.c optional xen | xenhvm
dev/xen/grant_table/grant_table.c optional xen | xenhvm
dev/xen/netback/netback.c optional xen | xenhvm
dev/xen/netfront/netfront.c optional xen | xenhvm
dev/xen/xenpci/xenpci.c optional xenpci
@ -4000,7 +4001,6 @@ vm/vm_reserv.c standard
vm/vm_unix.c standard
vm/vm_zeroidle.c standard
vm/vnode_pager.c standard
xen/gnttab.c optional xen | xenhvm
xen/features.c optional xen | xenhvm
xen/xenbus/xenbus_if.m optional xen | xenhvm
xen/xenbus/xenbus.c optional xen | xenhvm

View File

@ -336,6 +336,8 @@ dev/viawd/viawd.c optional viawd
dev/vmware/vmxnet3/if_vmx.c optional vmx
dev/wbwd/wbwd.c optional wbwd
dev/wpi/if_wpi.c optional wpi
dev/xen/pci/xen_acpi_pci.c optional xenhvm
dev/xen/pci/xen_pci.c optional xenhvm
dev/isci/isci.c optional isci
dev/isci/isci_controller.c optional isci
dev/isci/isci_domain.c optional isci
@ -572,4 +574,4 @@ x86/xen/xen_apic.c optional xenhvm
x86/xen/xenpv.c optional xenhvm
x86/xen/xen_nexus.c optional xenhvm
x86/xen/xen_msi.c optional xenhvm
x86/xen/xen_pci.c optional xenhvm
x86/xen/xen_pci_bus.c optional xenhvm

View File

@ -0,0 +1,655 @@
/*-
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* 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.
*/
/*
* BERI Virtio Networking Frontend
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/rman.h>
#include <sys/timeet.h>
#include <sys/timetc.h>
#include <sys/endian.h>
#include <sys/lock.h>
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/mdioctl.h>
#include <sys/conf.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/if_types.h>
#include <net/if_var.h>
#include <net/if_vlan_var.h>
#include <machine/bus.h>
#include <machine/fdt.h>
#include <machine/cpu.h>
#include <machine/intr.h>
#include <dev/beri/virtio/virtio.h>
#include <dev/beri/virtio/virtio_mmio_platform.h>
#include <dev/altera/pio/pio.h>
#include <dev/virtio/mmio/virtio_mmio.h>
#include <dev/virtio/network/virtio_net.h>
#include <dev/virtio/virtio.h>
#include <dev/virtio/virtio_ring.h>
#include "pio_if.h"
#define DPRINTF(fmt, args...) printf(fmt, ##args)
#define READ4(_sc, _reg) \
bus_read_4((_sc)->res[0], _reg)
#define WRITE4(_sc, _reg, _val) \
bus_write_4((_sc)->res[0], _reg, _val)
#define VTBE_LOCK(sc) mtx_lock(&(sc)->mtx)
#define VTBE_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
#define VTBE_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mtx, MA_OWNED);
#define VTBE_ASSERT_UNLOCKED(sc) mtx_assert(&(sc)->mtx, MA_NOTOWNED);
/*
* Driver data and defines.
*/
#define DESC_COUNT 256
struct vtbe_softc {
struct resource *res[2];
bus_space_tag_t bst;
bus_space_handle_t bsh;
device_t dev;
struct ifnet *ifp;
int if_flags;
struct mtx mtx;
boolean_t is_attached;
int beri_mem_offset;
device_t pio_send;
device_t pio_recv;
int opened;
struct vqueue_info vs_queues[2];
int vs_curq;
int hdrsize;
};
static struct resource_spec vtbe_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ -1, 0 }
};
static void vtbe_txfinish_locked(struct vtbe_softc *sc);
static void vtbe_rxfinish_locked(struct vtbe_softc *sc);
static void vtbe_stop_locked(struct vtbe_softc *sc);
static int pio_enable_irq(struct vtbe_softc *sc, int enable);
static void
vtbe_txstart_locked(struct vtbe_softc *sc)
{
struct virtio_net_hdr_mrg_rxbuf *vnh;
struct iovec iov[DESC_COUNT];
struct vqueue_info *vq;
struct iovec *riov;
struct ifnet *ifp;
struct mbuf *m;
struct uio uio;
int enqueued;
int iolen;
int error;
int *addr;
int reg;
int len;
int n;
VTBE_ASSERT_LOCKED(sc);
/* RX queue */
vq = &sc->vs_queues[0];
if (!vq_has_descs(vq)) {
return;
}
ifp = sc->ifp;
if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
return;
}
enqueued = 0;
if (!vq_ring_ready(vq))
return;
vq->vq_save_used = be16toh(vq->vq_used->idx);
for (;;) {
if (!vq_has_descs(vq)) {
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL) {
break;
}
n = vq_getchain(sc->beri_mem_offset, vq, iov,
DESC_COUNT, NULL);
KASSERT(n >= 1 && n <= DESC_COUNT,
("wrong descriptors num %d", n));
addr = iov[0].iov_base;
len = iov[0].iov_len;
vnh = iov[0].iov_base;
memset(vnh, 0, sc->hdrsize);
vnh->num_buffers = htobe16(1);
iov[0].iov_len -= sc->hdrsize;
iov[0].iov_base = (void *)((uintptr_t)iov[0].iov_base +
sc->hdrsize);
riov = &iov[0];
uio.uio_resid = iov[0].iov_len;
uio.uio_iov = riov;
uio.uio_segflg = UIO_SYSSPACE;
uio.uio_iovcnt = 1;
uio.uio_offset = 0;
uio.uio_rw = UIO_READ;
error = m_mbuftouio(&uio, m, 0);
if (error)
panic("m_mbuftouio failed\n");
iolen = (len - iov[0].iov_len - sc->hdrsize);
vq_relchain(vq, iov, 0, iolen + sc->hdrsize);
paddr_unmap((void *)addr, len);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
BPF_MTAP(ifp, m);
m_freem(m);
++enqueued;
}
if (enqueued != 0) {
reg = htobe32(VIRTIO_MMIO_INT_VRING);
WRITE4(sc, VIRTIO_MMIO_INTERRUPT_STATUS, reg);
PIO_SET(sc->pio_send, Q_INTR, 1);
}
}
static void
vtbe_txstart(struct ifnet *ifp)
{
struct vtbe_softc *sc = ifp->if_softc;
VTBE_LOCK(sc);
vtbe_txstart_locked(sc);
VTBE_UNLOCK(sc);
}
static void
vtbe_stop_locked(struct vtbe_softc *sc)
{
struct ifnet *ifp;
VTBE_ASSERT_LOCKED(sc);
ifp = sc->ifp;
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
}
static void
vtbe_init_locked(struct vtbe_softc *sc)
{
struct ifnet *ifp = sc->ifp;
VTBE_ASSERT_LOCKED(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
return;
ifp->if_drv_flags |= IFF_DRV_RUNNING;
}
static void
vtbe_init(void *if_softc)
{
struct vtbe_softc *sc = if_softc;
VTBE_LOCK(sc);
vtbe_init_locked(sc);
VTBE_UNLOCK(sc);
}
static int
vtbe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct ifmediareq *ifmr;
struct vtbe_softc *sc;
struct ifreq *ifr;
int mask, error;
sc = ifp->if_softc;
ifr = (struct ifreq *)data;
error = 0;
switch (cmd) {
case SIOCSIFFLAGS:
VTBE_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
pio_enable_irq(sc, 1);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
vtbe_init_locked(sc);
}
} else {
pio_enable_irq(sc, 0);
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
vtbe_stop_locked(sc);
}
}
sc->if_flags = ifp->if_flags;
VTBE_UNLOCK(sc);
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
ifmr = (struct ifmediareq *)data;
ifmr->ifm_count = 1;
ifmr->ifm_status = (IFM_AVALID | IFM_ACTIVE);
ifmr->ifm_active = (IFM_ETHER | IFM_10G_T | IFM_FDX);
ifmr->ifm_current = ifmr->ifm_active;
break;
case SIOCSIFCAP:
mask = ifp->if_capenable ^ ifr->ifr_reqcap;
if (mask & IFCAP_VLAN_MTU) {
ifp->if_capenable ^= IFCAP_VLAN_MTU;
}
break;
case SIOCSIFADDR:
pio_enable_irq(sc, 1);
default:
error = ether_ioctl(ifp, cmd, data);
break;
}
return (error);
}
static void
vtbe_txfinish_locked(struct vtbe_softc *sc)
{
struct ifnet *ifp;
VTBE_ASSERT_LOCKED(sc);
ifp = sc->ifp;
}
static int
vq_init(struct vtbe_softc *sc)
{
struct vqueue_info *vq;
uint8_t *base;
int size;
int reg;
int pfn;
vq = &sc->vs_queues[sc->vs_curq];
vq->vq_qsize = DESC_COUNT;
reg = READ4(sc, VIRTIO_MMIO_QUEUE_PFN);
pfn = be32toh(reg);
vq->vq_pfn = pfn;
size = vring_size(vq->vq_qsize, VRING_ALIGN);
base = paddr_map(sc->beri_mem_offset,
(pfn << PAGE_SHIFT), size);
/* First pages are descriptors */
vq->vq_desc = (struct vring_desc *)base;
base += vq->vq_qsize * sizeof(struct vring_desc);
/* Then avail ring */
vq->vq_avail = (struct vring_avail *)base;
base += (2 + vq->vq_qsize + 1) * sizeof(uint16_t);
/* Then it's rounded up to the next page */
base = (uint8_t *)roundup2((uintptr_t)base, VRING_ALIGN);
/* And the last pages are the used ring */
vq->vq_used = (struct vring_used *)base;
/* Mark queue as allocated, and start at 0 when we use it. */
vq->vq_flags = VQ_ALLOC;
vq->vq_last_avail = 0;
return (0);
}
static void
vtbe_proc_rx(struct vtbe_softc *sc, struct vqueue_info *vq)
{
struct iovec iov[DESC_COUNT];
struct ifnet *ifp;
struct uio uio;
struct mbuf *m;
int iolen;
int i;
int n;
ifp = sc->ifp;
n = vq_getchain(sc->beri_mem_offset, vq, iov,
DESC_COUNT, NULL);
KASSERT(n >= 1 && n <= DESC_COUNT,
("wrong n %d", n));
iolen = 0;
for (i = 1; i < n; i++) {
iolen += iov[i].iov_len;
}
uio.uio_resid = iolen;
uio.uio_iov = &iov[1];
uio.uio_segflg = UIO_SYSSPACE;
uio.uio_iovcnt = (n - 1);
uio.uio_rw = UIO_WRITE;
if ((m = m_uiotombuf(&uio, M_NOWAIT, 0, ETHER_ALIGN,
M_PKTHDR)) == NULL) {
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
goto done;
}
m->m_pkthdr.rcvif = ifp;
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
CURVNET_SET(ifp->if_vnet);
VTBE_UNLOCK(sc);
(*ifp->if_input)(ifp, m);
VTBE_LOCK(sc);
CURVNET_RESTORE();
done:
vq_relchain(vq, iov, n, iolen + sc->hdrsize);
}
static void
vtbe_rxfinish_locked(struct vtbe_softc *sc)
{
struct vqueue_info *vq;
int reg;
/* TX queue */
vq = &sc->vs_queues[1];
if (!vq_ring_ready(vq))
return;
/* Process new descriptors */
vq->vq_save_used = be16toh(vq->vq_used->idx);
while (vq_has_descs(vq)) {
vtbe_proc_rx(sc, vq);
}
/* Interrupt the other side */
reg = htobe32(VIRTIO_MMIO_INT_VRING);
WRITE4(sc, VIRTIO_MMIO_INTERRUPT_STATUS, reg);
PIO_SET(sc->pio_send, Q_INTR, 1);
}
static void
vtbe_intr(void *arg)
{
struct vtbe_softc *sc;
int pending;
uint32_t reg;
sc = arg;
VTBE_LOCK(sc);
reg = PIO_READ(sc->pio_recv);
/* Ack */
PIO_SET(sc->pio_recv, reg, 0);
pending = htobe32(reg);
if (pending & Q_SEL) {
reg = READ4(sc, VIRTIO_MMIO_QUEUE_SEL);
sc->vs_curq = be32toh(reg);
}
if (pending & Q_PFN) {
vq_init(sc);
}
if (pending & Q_NOTIFY) {
/* beri rx / arm tx notify */
vtbe_txfinish_locked(sc);
}
if (pending & Q_NOTIFY1) {
vtbe_rxfinish_locked(sc);
}
VTBE_UNLOCK(sc);
}
static int
vtbe_get_hwaddr(struct vtbe_softc *sc, uint8_t *hwaddr)
{
int rnd;
/*
* Generate MAC address, use 'bsd' + random 24 low-order bits.
*/
rnd = arc4random() & 0x00ffffff;
hwaddr[0] = 'b';
hwaddr[1] = 's';
hwaddr[2] = 'd';
hwaddr[3] = rnd >> 16;
hwaddr[4] = rnd >> 8;
hwaddr[5] = rnd >> 0;
return (0);
}
static int
pio_enable_irq(struct vtbe_softc *sc, int enable)
{
/*
* IRQ lines should be disabled while reprogram FPGA core.
*/
if (enable) {
if (sc->opened == 0) {
sc->opened = 1;
PIO_SETUP_IRQ(sc->pio_recv, vtbe_intr, sc);
}
} else {
if (sc->opened == 1) {
PIO_TEARDOWN_IRQ(sc->pio_recv);
sc->opened = 0;
}
}
return (0);
}
static int
vtbe_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "sri-cambridge,beri-vtnet"))
return (ENXIO);
device_set_desc(dev, "Virtio BERI Ethernet Controller");
return (BUS_PROBE_DEFAULT);
}
static int
vtbe_attach(device_t dev)
{
uint8_t macaddr[ETHER_ADDR_LEN];
struct vtbe_softc *sc;
struct ifnet *ifp;
int reg;
sc = device_get_softc(dev);
sc->dev = dev;
sc->hdrsize = sizeof(struct virtio_net_hdr_mrg_rxbuf);
if (bus_alloc_resources(dev, vtbe_spec, sc->res)) {
device_printf(dev, "could not allocate resources\n");
return (ENXIO);
}
/* Memory interface */
sc->bst = rman_get_bustag(sc->res[0]);
sc->bsh = rman_get_bushandle(sc->res[0]);
mtx_init(&sc->mtx, device_get_nameunit(sc->dev),
MTX_NETWORK_LOCK, MTX_DEF);
if (setup_offset(dev, &sc->beri_mem_offset) != 0)
return (ENXIO);
if (setup_pio(dev, "pio-send", &sc->pio_send) != 0)
return (ENXIO);
if (setup_pio(dev, "pio-recv", &sc->pio_recv) != 0)
return (ENXIO);
/* Setup MMIO */
/* Specify that we provide network device */
reg = htobe32(VIRTIO_ID_NETWORK);
WRITE4(sc, VIRTIO_MMIO_DEVICE_ID, reg);
/* The number of desc we support */
reg = htobe32(DESC_COUNT);
WRITE4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX, reg);
/* Our features */
reg = htobe32(VIRTIO_NET_F_MAC |
VIRTIO_NET_F_MRG_RXBUF |
VIRTIO_F_NOTIFY_ON_EMPTY);
WRITE4(sc, VIRTIO_MMIO_HOST_FEATURES, reg);
/* Get MAC */
if (vtbe_get_hwaddr(sc, macaddr)) {
device_printf(sc->dev, "can't get mac\n");
return (ENXIO);
}
/* Set up the ethernet interface. */
sc->ifp = ifp = if_alloc(IFT_ETHER);
ifp->if_baudrate = IF_Gbps(10);
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX |
IFF_MULTICAST | IFF_PROMISC);
ifp->if_capabilities = IFCAP_VLAN_MTU;
ifp->if_capenable = ifp->if_capabilities;
ifp->if_start = vtbe_txstart;
ifp->if_ioctl = vtbe_ioctl;
ifp->if_init = vtbe_init;
IFQ_SET_MAXLEN(&ifp->if_snd, DESC_COUNT - 1);
ifp->if_snd.ifq_drv_maxlen = DESC_COUNT - 1;
IFQ_SET_READY(&ifp->if_snd);
ifp->if_hdrlen = sizeof(struct ether_vlan_header);
/* All ready to run, attach the ethernet interface. */
ether_ifattach(ifp, macaddr);
sc->is_attached = true;
return (0);
}
static device_method_t vtbe_methods[] = {
DEVMETHOD(device_probe, vtbe_probe),
DEVMETHOD(device_attach, vtbe_attach),
{ 0, 0 }
};
static driver_t vtbe_driver = {
"vtbe",
vtbe_methods,
sizeof(struct vtbe_softc),
};
static devclass_t vtbe_devclass;
DRIVER_MODULE(vtbe, simplebus, vtbe_driver, vtbe_devclass, 0, 0);
MODULE_DEPEND(vtbe, ether, 1, 1, 1);

View File

@ -58,10 +58,18 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/intr.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/beri/virtio/virtio.h>
#include <dev/virtio/virtio.h>
#include <dev/virtio/virtqueue.h>
#include <dev/virtio/virtio_ring.h>
#include <dev/altera/pio/pio.h>
#include "pio_if.h"
int
vq_ring_ready(struct vqueue_info *vq)
@ -167,12 +175,13 @@ vq_relchain(struct vqueue_info *vq, struct iovec *iov, int n, uint32_t iolen)
int i;
mask = vq->vq_qsize - 1;
vu = vq->vq_used;
head = be16toh(vq->vq_avail->ring[vq->vq_last_avail++ & mask]);
vu = vq->vq_used;
uidx = be16toh(vu->idx);
vue = &vu->ring[uidx++ & mask];
vue->id = htobe16(head);
vue->id = htobe32(head);
vue->len = htobe32(iolen);
vu->idx = htobe16(uidx);
@ -181,3 +190,59 @@ vq_relchain(struct vqueue_info *vq, struct iovec *iov, int n, uint32_t iolen)
paddr_unmap((void *)iov[i].iov_base, iov[i].iov_len);
}
}
int
setup_pio(device_t dev, char *name, device_t *pio_dev)
{
phandle_t pio_node;
struct fdt_ic *ic;
phandle_t xref;
phandle_t node;
if ((node = ofw_bus_get_node(dev)) == -1)
return (ENXIO);
if (OF_searchencprop(node, name, &xref,
sizeof(xref)) == -1) {
return (ENXIO);
}
pio_node = OF_node_from_xref(xref);
SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) {
if (ic->iph == pio_node) {
*pio_dev = ic->dev;
PIO_CONFIGURE(*pio_dev, PIO_OUT_ALL,
PIO_UNMASK_ALL);
return (0);
}
}
return (ENXIO);
}
int
setup_offset(device_t dev, uint32_t *offset)
{
pcell_t dts_value[2];
phandle_t mem_node;
phandle_t xref;
phandle_t node;
int len;
if ((node = ofw_bus_get_node(dev)) == -1)
return (ENXIO);
if (OF_searchencprop(node, "beri-mem", &xref,
sizeof(xref)) == -1) {
return (ENXIO);
}
mem_node = OF_node_from_xref(xref);
if ((len = OF_getproplen(mem_node, "reg")) <= 0)
return (ENXIO);
OF_getencprop(mem_node, "reg", dts_value, len);
*offset = dts_value[0];
return (0);
}

View File

@ -41,14 +41,10 @@
#define PAGE_SHIFT 12
#define VRING_ALIGN 4096
#define NUM_QUEUES 1
#define VQ_ALLOC 0x01 /* set once we have a pfn */
#define VQ_MAX_DESCRIPTORS 512
#define VTBLK_BLK_ID_BYTES 20
#define VTBLK_MAXSEGS 256
struct vqueue_info {
uint16_t vq_qsize; /* size of this queue (a power of 2) */
uint16_t vq_num;
@ -70,3 +66,5 @@ int vq_getchain(uint32_t beri_mem_offset, struct vqueue_info *vq,
struct iovec *iov, int n_iov, uint16_t *flags);
void vq_relchain(struct vqueue_info *vq, struct iovec *iov, int n, uint32_t iolen);
int setup_pio(device_t dev, char *name, device_t *pio_dev);
int setup_offset(device_t dev, uint32_t *offset);

View File

@ -74,6 +74,13 @@ __FBSDID("$FreeBSD$");
#define DPRINTF(fmt, ...)
/* We use indirect descriptors */
#define NUM_DESCS 1
#define NUM_QUEUES 1
#define VTBLK_BLK_ID_BYTES 20
#define VTBLK_MAXSEGS 256
struct beri_vtblk_softc {
struct resource *res[1];
bus_space_tag_t bst;
@ -286,8 +293,12 @@ vtblk_notify(struct beri_vtblk_softc *sc)
while (vq_has_descs(vq))
vtblk_proc(sc, vq);
/* Interrupt other side */
PIO_SET(sc->pio_send, Q_INTR, 1);
/* Interrupt the other side */
if ((be16toh(vq->vq_avail->flags) & VRING_AVAIL_F_NO_INTERRUPT) == 0) {
reg = htobe32(VIRTIO_MMIO_INT_VRING);
WRITE4(sc, VIRTIO_MMIO_INTERRUPT_STATUS, reg);
PIO_SET(sc->pio_send, Q_INTR, 1);
}
return (0);
}
@ -302,7 +313,7 @@ vq_init(struct beri_vtblk_softc *sc)
int pfn;
vq = &sc->vs_queues[0];
vq->vq_qsize = NUM_QUEUES;
vq->vq_qsize = NUM_DESCS;
reg = READ4(sc, VIRTIO_MMIO_QUEUE_PFN);
pfn = be32toh(reg);
@ -352,61 +363,6 @@ vtblk_thread(void *arg)
kthread_exit();
}
static int
setup_pio(struct beri_vtblk_softc *sc, char *name, device_t *dev)
{
phandle_t pio_node;
struct fdt_ic *ic;
phandle_t xref;
phandle_t node;
if ((node = ofw_bus_get_node(sc->dev)) == -1)
return (ENXIO);
if (OF_searchencprop(node, name, &xref,
sizeof(xref)) == -1) {
return (ENXIO);
}
pio_node = OF_node_from_xref(xref);
SLIST_FOREACH(ic, &fdt_ic_list_head, fdt_ics) {
if (ic->iph == pio_node) {
*dev = ic->dev;
PIO_CONFIGURE(*dev, PIO_OUT_ALL,
PIO_UNMASK_ALL);
return (0);
}
}
return (ENXIO);
}
static int
setup_offset(struct beri_vtblk_softc *sc)
{
pcell_t dts_value[2];
phandle_t mem_node;
phandle_t xref;
phandle_t node;
int len;
if ((node = ofw_bus_get_node(sc->dev)) == -1)
return (ENXIO);
if (OF_searchencprop(node, "beri-mem", &xref,
sizeof(xref)) == -1) {
return (ENXIO);
}
mem_node = OF_node_from_xref(xref);
if ((len = OF_getproplen(mem_node, "reg")) <= 0)
return (ENXIO);
OF_getencprop(mem_node, "reg", dts_value, len);
sc->beri_mem_offset = dts_value[0];
return (0);
}
static int
backend_info(struct beri_vtblk_softc *sc)
{
@ -419,9 +375,9 @@ backend_info(struct beri_vtblk_softc *sc)
reg = htobe32(VIRTIO_ID_BLOCK);
WRITE4(sc, VIRTIO_MMIO_DEVICE_ID, reg);
/* The number of queues we support */
reg = htobe16(NUM_QUEUES);
WRITE2(sc, VIRTIO_MMIO_QUEUE_NUM, reg);
/* Queue size */
reg = htobe32(NUM_DESCS);
WRITE4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX, reg);
/* Our features */
reg = htobe32(VIRTIO_RING_F_INDIRECT_DESC
@ -566,11 +522,11 @@ beri_vtblk_attach(device_t dev)
return (ENXIO);
}
if (setup_offset(sc) != 0)
if (setup_offset(dev, &sc->beri_mem_offset) != 0)
return (ENXIO);
if (setup_pio(sc, "pio-send", &sc->pio_send) != 0)
if (setup_pio(dev, "pio-send", &sc->pio_send) != 0)
return (ENXIO);
if (setup_pio(sc, "pio-recv", &sc->pio_recv) != 0)
if (setup_pio(dev, "pio-recv", &sc->pio_recv) != 0)
return (ENXIO);
sc->cdev = make_dev(&beri_cdevsw, 0, UID_ROOT, GID_WHEEL,

View File

@ -149,20 +149,49 @@ virtio_mmio_platform_attach(device_t dev)
}
static int
platform_note(device_t dev, size_t offset)
platform_note(device_t dev, size_t offset, int val)
{
struct virtio_mmio_platform_softc *sc;
int note;
int i;
sc = device_get_softc(dev);
if (offset == VIRTIO_MMIO_QUEUE_NOTIFY) {
mips_dcache_wbinv_all();
PIO_SET(sc->pio_send, Q_NOTIFY, 1);
switch (offset) {
case (VIRTIO_MMIO_QUEUE_NOTIFY):
if (val == 0)
note = Q_NOTIFY;
else if (val == 1)
note = Q_NOTIFY1;
break;
case (VIRTIO_MMIO_QUEUE_PFN):
note = Q_PFN;
break;
case (VIRTIO_MMIO_QUEUE_SEL):
note = Q_SEL;
break;
default:
note = 0;
}
if (offset == VIRTIO_MMIO_QUEUE_PFN) {
if (note) {
mips_dcache_wbinv_all();
PIO_SET(sc->pio_send, Q_PFN, 1);
PIO_SET(sc->pio_send, note, 1);
/*
* Wait until host ack the request.
* Usually done within few cycles.
* TODO: bad
*/
for (i = 100; i > 0; i--) {
if (PIO_READ(sc->pio_send) == 0)
break;
}
if (i == 0)
device_printf(sc->dev, "Warning: host busy\n");
}
return (0);

View File

@ -30,6 +30,8 @@
* $FreeBSD$
*/
#define Q_NOTIFY 0x1
#define Q_PFN 0x2
#define Q_INTR 0x4
#define Q_NOTIFY 0x01
#define Q_PFN 0x02
#define Q_INTR 0x04
#define Q_SEL 0x08
#define Q_NOTIFY1 0x10

View File

@ -68,7 +68,7 @@ __FBSDID("$FreeBSD$");
#define MII_KSZPHY_RX_DATA_PAD_SKEW 0x105
#define MII_KSZPHY_TX_DATA_PAD_SKEW 0x106
#define PS_TO_REG(p) (p / 200)
#define PS_TO_REG(p) ((p) / 200)
static int micphy_probe(device_t);
static int micphy_attach(device_t);
@ -104,7 +104,8 @@ static const struct mii_phy_funcs micphy_funcs = {
mii_phy_reset
};
static void micphy_write(struct mii_softc *sc, uint32_t reg, uint32_t val)
static void
micphy_write(struct mii_softc *sc, uint32_t reg, uint32_t val)
{
PHY_WRITE(sc, MII_KSZPHY_EXTREG, KSZPHY_EXTREG_WRITE | reg);

View File

@ -3195,7 +3195,7 @@ product NETGEAR EA101X 0x1002 Ethernet
product NETGEAR FA101 0x1020 Ethernet 10/100, USB1.1
product NETGEAR FA120 0x1040 USB 2.0 Ethernet
product NETGEAR M4100 0x1100 M4100/M5300/M7100 series switch
product NETGEAR WG111V2_2 0x4240 PrismGT USB 2.0 WLAN
product NETGEAR WG111V1_2 0x4240 PrismGT USB 2.0 WLAN
product NETGEAR WG111V3 0x4260 WG111v3
product NETGEAR WG111U 0x4300 WG111U
product NETGEAR WG111U_NF 0x4301 WG111U (no firmware)

View File

@ -182,7 +182,7 @@ static const STRUCT_USB_HOST_ID upgt_devs[] = {
UPGT_DEV(FSC, E5400),
UPGT_DEV(GLOBESPAN, PRISM_GT_1),
UPGT_DEV(GLOBESPAN, PRISM_GT_2),
UPGT_DEV(NETGEAR, WG111V2_2),
UPGT_DEV(NETGEAR, WG111V1_2),
UPGT_DEV(INTERSIL, PRISM_GT),
UPGT_DEV(SMC, 2862WG),
UPGT_DEV(USR, USR5422),

View File

@ -1,11 +1,15 @@
/*-
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Portions of this software were developed by Andrew Turner
* under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@ -131,15 +135,24 @@ static void vtmmio_vq_intr(void *);
/*
* I/O port read/write wrappers.
*/
#define vtmmio_write_config_1(sc, o, v) \
bus_write_1((sc)->res[0], (o), (v)); \
VIRTIO_MMIO_NOTE(sc->platform, (o))
#define vtmmio_write_config_2(sc, o, v) \
bus_write_2((sc)->res[0], (o), (v)); \
VIRTIO_MMIO_NOTE(sc->platform, (o))
#define vtmmio_write_config_4(sc, o, v) \
bus_write_4((sc)->res[0], (o), (v)); \
VIRTIO_MMIO_NOTE(sc->platform, (o))
#define vtmmio_write_config_1(sc, o, v) \
do { \
bus_write_1((sc)->res[0], (o), (v)); \
if (sc->platform != NULL) \
VIRTIO_MMIO_NOTE(sc->platform, (o), (v)); \
} while (0)
#define vtmmio_write_config_2(sc, o, v) \
do { \
bus_write_2((sc)->res[0], (o), (v)); \
if (sc->platform != NULL) \
VIRTIO_MMIO_NOTE(sc->platform, (o), (v)); \
} while (0)
#define vtmmio_write_config_4(sc, o, v) \
do { \
bus_write_4((sc)->res[0], (o), (v)); \
if (sc->platform != NULL) \
VIRTIO_MMIO_NOTE(sc->platform, (o), (v)); \
} while (0)
#define vtmmio_read_config_1(sc, o) \
bus_read_1((sc)->res[0], (o))
@ -200,11 +213,13 @@ vtmmio_setup_intr(device_t dev, enum intr_type type)
sc = device_get_softc(dev);
err = VIRTIO_MMIO_SETUP_INTR(sc->platform, sc->dev,
vtmmio_vq_intr, sc);
if (err == 0) {
/* Okay we have backend-specific interrupts */
return (0);
if (sc->platform != NULL) {
err = VIRTIO_MMIO_SETUP_INTR(sc->platform, sc->dev,
vtmmio_vq_intr, sc);
if (err == 0) {
/* Okay we have backend-specific interrupts */
return (0);
}
}
rid = 0;
@ -473,8 +488,8 @@ vtmmio_alloc_virtqueues(device_t dev, int flags, int nvqs,
struct vq_alloc_info *info;
struct vtmmio_softc *sc;
struct virtqueue *vq;
uint32_t size;
int idx, error;
uint16_t size;
sc = device_get_softc(dev);
@ -492,8 +507,10 @@ vtmmio_alloc_virtqueues(device_t dev, int flags, int nvqs,
vqx = &sc->vtmmio_vqs[idx];
info = &vq_info[idx];
vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_SEL, idx);
vtmmio_select_virtqueue(sc, idx);
size = vtmmio_read_config_2(sc, VIRTIO_MMIO_QUEUE_NUM);
size = vtmmio_read_config_4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX);
error = virtqueue_alloc(dev, idx, size,
VIRTIO_MMIO_VRING_ALIGN, 0xFFFFFFFFUL, info, &vq);
@ -503,6 +520,10 @@ vtmmio_alloc_virtqueues(device_t dev, int flags, int nvqs,
idx, error);
break;
}
vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_NUM, size);
vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_ALIGN,
VIRTIO_MMIO_VRING_ALIGN);
#if 0
device_printf(dev, "virtqueue paddr 0x%08lx\n",
(uint64_t)virtqueue_paddr(vq));
@ -572,7 +593,7 @@ vtmmio_notify_virtqueue(device_t dev, uint16_t queue)
sc = device_get_softc(dev);
vtmmio_write_config_2(sc, VIRTIO_MMIO_QUEUE_NOTIFY, queue);
vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_NOTIFY, queue);
}
static uint8_t
@ -582,7 +603,7 @@ vtmmio_get_status(device_t dev)
sc = device_get_softc(dev);
return (vtmmio_read_config_1(sc, VIRTIO_MMIO_STATUS));
return (vtmmio_read_config_4(sc, VIRTIO_MMIO_STATUS));
}
static void
@ -595,7 +616,7 @@ vtmmio_set_status(device_t dev, uint8_t status)
if (status != VIRTIO_CONFIG_STATUS_RESET)
status |= vtmmio_get_status(dev);
vtmmio_write_config_1(sc, VIRTIO_MMIO_STATUS, status);
vtmmio_write_config_4(sc, VIRTIO_MMIO_STATUS, status);
}
static void
@ -611,13 +632,16 @@ vtmmio_read_dev_config(device_t dev, bus_size_t offset,
off = VIRTIO_MMIO_CONFIG + offset;
for (d = dst; length > 0; d += size, off += size, length -= size) {
#ifdef ALLOW_WORD_ALIGNED_ACCESS
if (length >= 4) {
size = 4;
*(uint32_t *)d = vtmmio_read_config_4(sc, off);
} else if (length >= 2) {
size = 2;
*(uint16_t *)d = vtmmio_read_config_2(sc, off);
} else {
} else
#endif
{
size = 1;
*d = vtmmio_read_config_1(sc, off);
}
@ -637,13 +661,16 @@ vtmmio_write_dev_config(device_t dev, bus_size_t offset,
off = VIRTIO_MMIO_CONFIG + offset;
for (s = src; length > 0; s += size, off += size, length -= size) {
#ifdef ALLOW_WORD_ALIGNED_ACCESS
if (length >= 4) {
size = 4;
vtmmio_write_config_4(sc, off, *(uint32_t *)s);
} else if (length >= 2) {
size = 2;
vtmmio_write_config_2(sc, off, *(uint16_t *)s);
} else {
} else
#endif
{
size = 1;
vtmmio_write_config_1(sc, off, *s);
}
@ -711,7 +738,7 @@ vtmmio_reinit_virtqueue(struct vtmmio_softc *sc, int idx)
KASSERT(vq != NULL, ("%s: vq %d not allocated", __func__, idx));
vtmmio_select_virtqueue(sc, idx);
size = vtmmio_read_config_2(sc, VIRTIO_MMIO_QUEUE_NUM);
size = vtmmio_read_config_4(sc, VIRTIO_MMIO_QUEUE_NUM_MAX);
error = virtqueue_reinit(vq, size);
if (error)
@ -778,7 +805,7 @@ static void
vtmmio_select_virtqueue(struct vtmmio_softc *sc, int idx)
{
vtmmio_write_config_2(sc, VIRTIO_MMIO_QUEUE_SEL, idx);
vtmmio_write_config_4(sc, VIRTIO_MMIO_QUEUE_SEL, idx);
}
static void
@ -787,14 +814,27 @@ vtmmio_vq_intr(void *arg)
struct vtmmio_virtqueue *vqx;
struct vtmmio_softc *sc;
struct virtqueue *vq;
uint32_t status;
int idx;
sc = arg;
status = vtmmio_read_config_4(sc, VIRTIO_MMIO_INTERRUPT_STATUS);
vtmmio_write_config_4(sc, VIRTIO_MMIO_INTERRUPT_ACK, status);
/* The config changed */
if (status & VIRTIO_MMIO_INT_CONFIG)
if (sc->vtmmio_child_dev != NULL)
VIRTIO_CONFIG_CHANGE(sc->vtmmio_child_dev);
/* Notify all virtqueues. */
for (idx = 0; idx < sc->vtmmio_nvqs; idx++) {
vqx = &sc->vtmmio_vqs[idx];
vq = vqx->vtv_vq;
virtqueue_intr(vq);
};
if (status & VIRTIO_MMIO_INT_VRING) {
for (idx = 0; idx < sc->vtmmio_nvqs; idx++) {
vqx = &sc->vtmmio_vqs[idx];
if (vqx->vtv_no_intr == 0) {
vq = vqx->vtv_vq;
virtqueue_intr(vq);
}
}
}
}

View File

@ -42,7 +42,7 @@ INTERFACE virtio_mmio;
CODE {
static int
virtio_mmio_write(device_t dev, size_t offset)
virtio_mmio_note(device_t dev, size_t offset, int val)
{
return (1);
@ -63,7 +63,8 @@ CODE {
METHOD int note {
device_t dev;
size_t offset;
} DEFAULT virtio_mmio_write;
int val;
} DEFAULT virtio_mmio_note;
#
# Setup backend-specific interrupts.

View File

@ -659,16 +659,59 @@ gnttab_expand(unsigned int req_entries)
return (error);
}
int
gnttab_init(device_t dev)
MTX_SYSINIT(gnttab, &gnttab_list_lock, "GNTTAB LOCK", MTX_DEF);
/*------------------ Private Device Attachment Functions --------------------*/
/**
* \brief Identify instances of this device type in the system.
*
* \param driver The driver performing this identify action.
* \param parent The NewBus parent device for any devices this method adds.
*/
static void
granttable_identify(driver_t *driver __unused, device_t parent)
{
KASSERT(xen_domain(),
("Trying to attach grant-table device on non Xen domain"));
/*
* A single device instance for our driver is always present
* in a system operating under Xen.
*/
if (BUS_ADD_CHILD(parent, 0, driver->name, 0) == NULL)
panic("unable to attach Xen Grant-table device");
}
/**
* \brief Probe for the existence of the Xen Grant-table device
*
* \param dev NewBus device_t for this instance.
*
* \return Always returns 0 indicating success.
*/
static int
granttable_probe(device_t dev)
{
device_set_desc(dev, "Xen Grant-table Device");
return (BUS_PROBE_NOWILDCARD);
}
/**
* \brief Attach the Xen Grant-table device.
*
* \param dev NewBus device_t for this instance.
*
* \return On success, 0. Otherwise an errno value indicating the
* type of failure.
*/
static int
granttable_attach(device_t dev)
{
int i;
unsigned int max_nr_glist_frames;
unsigned int nr_init_grefs;
if (!is_running_on_xen())
return (ENODEV);
nr_grant_frames = 1;
boot_max_nr_grant_frames = __max_nr_grant_frames();
@ -714,7 +757,20 @@ gnttab_init(device_t dev)
free(gnttab_list[i], M_DEVBUF);
free(gnttab_list, M_DEVBUF);
return (ENOMEM);
}
MTX_SYSINIT(gnttab, &gnttab_list_lock, "GNTTAB LOCK", MTX_DEF);
/*-------------------- Private Device Attachment Data -----------------------*/
static device_method_t granttable_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, granttable_identify),
DEVMETHOD(device_probe, granttable_probe),
DEVMETHOD(device_attach, granttable_attach),
DEVMETHOD_END
};
DEFINE_CLASS_0(granttable, granttable_driver, granttable_methods, 0);
devclass_t granttable_devclass;
DRIVER_MODULE_ORDERED(granttable, xenpv, granttable_driver, granttable_devclass,
NULL, NULL, SI_ORDER_FIRST);

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2014 Roger Pau Monné <roger.pau@citrix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <contrib/dev/acpica/include/acpi.h>
#include <contrib/dev/acpica/include/accommon.h>
#include <dev/acpica/acpivar.h>
#include <sys/pciio.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pci_private.h>
#include <xen/xen-os.h>
#include <xen/hypervisor.h>
#include <xen/xen_pci.h>
#include "pcib_if.h"
#include "pci_if.h"
static int
xen_acpi_pci_probe(device_t dev)
{
if (!xen_pv_domain())
return (ENXIO);
if (acpi_get_handle(dev) == NULL)
return (ENXIO);
device_set_desc(dev, "Xen ACPI PCI bus");
return (BUS_PROBE_SPECIFIC);
}
static device_method_t xen_acpi_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, xen_acpi_pci_probe),
/* PCI interface overwrites */
DEVMETHOD(pci_enable_msi, xen_pci_enable_msi_method),
DEVMETHOD(pci_disable_msi, xen_pci_disable_msi_method),
DEVMETHOD(pci_child_added, xen_pci_child_added_method),
DEVMETHOD_END
};
static devclass_t pci_devclass;
DECLARE_CLASS(acpi_pci_driver);
DEFINE_CLASS_1(pci, xen_acpi_pci_driver, xen_acpi_pci_methods,
sizeof(struct pci_softc), acpi_pci_driver);
DRIVER_MODULE(xen_acpi_pci, pcib, xen_acpi_pci_driver, pci_devclass, 0, 0);
MODULE_DEPEND(xen_acpi_pci, pci, 1, 1, 1);
MODULE_DEPEND(xen_acpi_pci, acpi, 1, 1, 1);
MODULE_VERSION(xen_acpi_pci, 1);

80
sys/dev/xen/pci/xen_pci.c Normal file
View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2014 Roger Pau Monné <roger.pau@citrix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/pciio.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pci_private.h>
#include <xen/xen-os.h>
#include <xen/hypervisor.h>
#include <xen/xen_pci.h>
#include "pcib_if.h"
#include "pci_if.h"
static int
xen_pci_probe(device_t dev)
{
if (!xen_pv_domain())
return (ENXIO);
device_set_desc(dev, "Xen PCI bus");
return (BUS_PROBE_DEFAULT);
}
static device_method_t xen_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, xen_pci_probe),
/* PCI interface overwrites */
DEVMETHOD(pci_enable_msi, xen_pci_enable_msi_method),
DEVMETHOD(pci_disable_msi, xen_pci_disable_msi_method),
DEVMETHOD(pci_child_added, xen_pci_child_added_method),
DEVMETHOD_END
};
static devclass_t pci_devclass;
DECLARE_CLASS(pci_driver);
DEFINE_CLASS_1(pci, xen_pci_driver, xen_pci_methods, sizeof(struct pci_softc),
pci_driver);
DRIVER_MODULE(xen_pci, pcib, xen_pci_driver, pci_devclass, 0, 0);
MODULE_DEPEND(xen_pci, pci, 1, 1, 1);
MODULE_VERSION(xen_pci, 1);

View File

@ -224,14 +224,18 @@ ext2_truncate(struct vnode *vp, off_t length, int flags, struct ucred *cred,
* will be returned to the free list. lastiblock values are also
* normalized to -1 for calls to ext2_indirtrunc below.
*/
bcopy((caddr_t)&oip->i_db[0], (caddr_t)oldblks, sizeof(oldblks));
for (level = TRIPLE; level >= SINGLE; level--)
for (level = TRIPLE; level >= SINGLE; level--) {
oldblks[NDADDR + level] = oip->i_ib[level];
if (lastiblock[level] < 0) {
oip->i_ib[level] = 0;
lastiblock[level] = -1;
}
for (i = NDADDR - 1; i > lastblock; i--)
oip->i_db[i] = 0;
}
for (i = 0; i < NDADDR; i++) {
oldblks[i] = oip->i_db[i];
if (i > lastblock)
oip->i_db[i] = 0;
}
oip->i_flag |= IN_CHANGE | IN_UPDATE;
allerror = ext2_update(ovp, !DOINGASYNC(ovp));
@ -241,8 +245,14 @@ ext2_truncate(struct vnode *vp, off_t length, int flags, struct ucred *cred,
* Note that we save the new block configuration so we can check it
* when we are done.
*/
bcopy((caddr_t)&oip->i_db[0], (caddr_t)newblks, sizeof(newblks));
bcopy((caddr_t)oldblks, (caddr_t)&oip->i_db[0], sizeof(oldblks));
for (i = 0; i < NDADDR; i++) {
newblks[i] = oip->i_db[i];
oip->i_db[i] = oldblks[i];
}
for (i = 0; i < NIADDR; i++) {
newblks[NDADDR + i] = oip->i_ib[i];
oip->i_ib[i] = oldblks[NDADDR + i];
}
oip->i_size = osize;
error = vtruncbuf(ovp, cred, length, (int)fs->e2fs_bsize);
if (error && (allerror == 0))

View File

@ -797,11 +797,15 @@ msdosfs_unmount(struct mount *mp, int mntflags)
int error, flags;
flags = 0;
if (mntflags & MNT_FORCE)
error = msdosfs_sync(mp, MNT_WAIT);
if ((mntflags & MNT_FORCE) != 0) {
flags |= FORCECLOSE;
} else if (error != 0) {
return (error);
}
error = vflush(mp, 0, flags, curthread);
if (error && error != ENXIO)
return error;
if (error != 0 && error != ENXIO)
return (error);
pmp = VFSTOMSDOSFS(mp);
if ((pmp->pm_flags & MSDOSFSMNT_RONLY) == 0) {
error = markvoldirty(pmp, 0);

View File

@ -1305,8 +1305,8 @@ dounmount(mp, flags, td)
}
vput(fsrootvp);
}
if (((mp->mnt_flag & MNT_RDONLY) ||
(error = VFS_SYNC(mp, MNT_WAIT)) == 0) || (flags & MNT_FORCE) != 0)
if ((mp->mnt_flag & MNT_RDONLY) != 0 || (flags & MNT_FORCE) != 0 ||
(error = VFS_SYNC(mp, MNT_WAIT)) == 0)
error = VFS_UNMOUNT(mp, flags);
vn_finished_write(mp);
/*

View File

@ -1788,7 +1788,6 @@ sched_sync(void)
int last_work_seen;
int net_worklist_len;
int syncer_final_iter;
int first_printf;
int error;
last_work_seen = 0;

View File

@ -49,9 +49,9 @@
#define EXPORT_SYMBOL_GPL(name)
/* OFED pre-module initialization */
#define SI_SUB_OFED_PREINIT (SI_SUB_KTHREAD_INIT - 2)
#define SI_SUB_OFED_PREINIT (SI_SUB_ROOT_CONF - 2)
/* OFED default module initialization */
#define SI_SUB_OFED_MODINIT (SI_SUB_KTHREAD_INIT - 1)
#define SI_SUB_OFED_MODINIT (SI_SUB_ROOT_CONF - 1)
#include <sys/linker.h>

View File

@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/syscall.h>
#include <sys/sysent.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/uio.h>
#include <sys/signalvar.h>
#include <sys/vmmeter.h>

View File

@ -91,6 +91,15 @@ madt_parse_interrupt_override(ACPI_MADT_INTERRUPT_OVERRIDE *intr)
madt_parse_interrupt_values(intr, &trig, &pol);
/* Remap the IRQ if it is mapped to a different interrupt vector. */
if (intr->SourceIrq != intr->GlobalIrq && intr->GlobalIrq > 15 &&
intr->SourceIrq == AcpiGbl_FADT.SciInterrupt)
/*
* If the SCI is remapped to a non-ISA global interrupt,
* then override the vector we use to setup.
*/
acpi_OverrideInterruptLevel(intr->GlobalIrq);
/* Register the IRQ with the polarity and trigger mode found. */
xen_register_pirq(intr->GlobalIrq, trig, pol);
}

View File

@ -425,6 +425,17 @@ xen_intr_bind_isrc(struct xenisrc **isrcp, evtchn_port_t local_port,
/* Assign the opaque handler (the event channel port) */
*port_handlep = &isrc->xi_port;
#ifdef SMP
if (type == EVTCHN_TYPE_PORT) {
/*
* By default all interrupts are assigned to vCPU#0
* unless specified otherwise, so shuffle them to balance
* the interrupt load.
*/
xen_intr_assign_cpu(&isrc->xi_intsrc, intr_next_cpu());
}
#endif
if (filter == NULL && handler == NULL) {
/*
* No filter/handler provided, leave the event channel
@ -851,7 +862,7 @@ xen_intr_assign_cpu(struct intsrc *base_isrc, u_int apic_id)
struct evtchn_bind_vcpu bind_vcpu;
struct xenisrc *isrc;
u_int to_cpu, vcpu_id;
int error;
int error, masked;
#ifdef XENHVM
if (xen_vector_callback_enabled == 0)
@ -869,6 +880,11 @@ xen_intr_assign_cpu(struct intsrc *base_isrc, u_int apic_id)
return (EINVAL);
}
/*
* Mask the event channel while binding it to prevent interrupt
* delivery with an inconsistent state in isrc->xi_cpu.
*/
masked = evtchn_test_and_set_mask(isrc->xi_port);
if ((isrc->xi_type == EVTCHN_TYPE_VIRQ) ||
(isrc->xi_type == EVTCHN_TYPE_IPI)) {
/*
@ -879,29 +895,25 @@ xen_intr_assign_cpu(struct intsrc *base_isrc, u_int apic_id)
evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port);
isrc->xi_cpu = to_cpu;
evtchn_cpu_unmask_port(isrc->xi_cpu, isrc->xi_port);
mtx_unlock(&xen_intr_isrc_lock);
return (0);
goto out;
}
bind_vcpu.port = isrc->xi_port;
bind_vcpu.vcpu = vcpu_id;
/*
* Allow interrupts to be fielded on the new VCPU before
* we ask the hypervisor to deliver them there.
*/
evtchn_cpu_unmask_port(to_cpu, isrc->xi_port);
error = HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu);
if (isrc->xi_cpu != to_cpu) {
if (error == 0) {
/* Commit to new binding by removing the old one. */
evtchn_cpu_mask_port(isrc->xi_cpu, isrc->xi_port);
isrc->xi_cpu = to_cpu;
} else {
/* Roll-back to previous binding. */
evtchn_cpu_mask_port(to_cpu, isrc->xi_port);
evtchn_cpu_unmask_port(isrc->xi_cpu, isrc->xi_port);
}
}
out:
if (masked == 0)
evtchn_unmask_port(isrc->xi_port);
mtx_unlock(&xen_intr_isrc_lock);
return (0);
#else

View File

@ -31,8 +31,6 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/pciio.h>
#include <dev/pci/pcireg.h>
@ -41,52 +39,12 @@ __FBSDID("$FreeBSD$");
#include <xen/xen-os.h>
#include <xen/hypervisor.h>
#include <xen/xen_pci.h>
#include "pcib_if.h"
#include "pci_if.h"
static int xen_pci_probe(device_t dev);
static void xen_pci_enable_msi_method(device_t dev, device_t child,
uint64_t address, uint16_t data);
static void xen_pci_disable_msi_method(device_t dev, device_t child);
static void xen_pci_child_added_method(device_t dev, device_t child);
static device_method_t xen_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, xen_pci_probe),
/* PCI interface overwrites */
DEVMETHOD(pci_enable_msi, xen_pci_enable_msi_method),
DEVMETHOD(pci_disable_msi, xen_pci_disable_msi_method),
DEVMETHOD(pci_child_added, xen_pci_child_added_method),
DEVMETHOD_END
};
static devclass_t pci_devclass;
DECLARE_CLASS(acpi_pci_driver);
DEFINE_CLASS_1(pci, xen_pci_driver, xen_pci_methods, sizeof(struct pci_softc),
acpi_pci_driver);
DRIVER_MODULE(xen_pci, pcib, xen_pci_driver, pci_devclass, 0, 0);
MODULE_DEPEND(xen_pci, pci, 1, 1, 1);
MODULE_DEPEND(xen_pci, acpi, 1, 1, 1);
MODULE_VERSION(xen_pci, 1);
static int
xen_pci_probe(device_t dev)
{
device_set_desc(dev, "Xen PCI bus");
if (!xen_pv_domain())
return (ENXIO);
return (BUS_PROBE_SPECIFIC);
}
static void
void
xen_pci_enable_msi_method(device_t dev, device_t child, uint64_t address,
uint16_t data)
{
@ -99,7 +57,7 @@ xen_pci_enable_msi_method(device_t dev, device_t child, uint64_t address,
msi->msi_ctrl, 2);
}
static void
void
xen_pci_disable_msi_method(device_t dev, device_t child)
{
struct pci_devinfo *dinfo = device_get_ivars(child);
@ -110,7 +68,7 @@ xen_pci_disable_msi_method(device_t dev, device_t child)
msi->msi_ctrl, 2);
}
static void
void
xen_pci_child_added_method(device_t dev, device_t child)
{
struct pci_devinfo *dinfo;

View File

@ -66,15 +66,6 @@ static int
xenpv_attach(device_t dev)
{
device_t child;
int error;
/* Initialize grant table before any Xen specific device is attached */
error = gnttab_init(dev);
if (error != 0) {
device_printf(dev, "error initializing grant table: %d\n",
error);
return (error);
}
/*
* Let our child drivers identify any child devices that they

View File

@ -51,8 +51,6 @@ struct gnttab_free_callback {
uint16_t count;
};
int gnttab_init(device_t);
/*
* Allocate a grant table reference and return it in *result. Returns
* zero on success or errno on error.

37
sys/xen/xen_pci.h Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2014 Roger Pau Monné <roger.pau@citrix.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __XEN_PCI_H__
#define __XEN_PCI_H__
void xen_pci_enable_msi_method(device_t dev, device_t child, uint64_t address,
uint16_t data);
void xen_pci_disable_msi_method(device_t dev, device_t child);
void xen_pci_child_added_method(device_t dev, device_t child);
#endif /* !__XEN_PCI_H__ */

View File

@ -29,6 +29,7 @@ SUBDIR= adduser \
extattr \
extattrctl \
fifolog \
fstyp \
fwcontrol \
getfmac \
getpmac \

View File

@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd November 21, 2014
.Dd November 22, 2014
.Dt AUTO_MASTER 5
.Os
.Sh NAME
@ -213,14 +213,17 @@ Supported special maps are:
.Pp
.Bl -tag -width "-hosts" -compact
.It Li -hosts
This map queries the remote NFS server and maps exported volumes.
It is traditionally mounted on
Query the remote NFS server and map exported shares.
This map is traditionally mounted on
.Pa /net .
It enables access to files on a remote NFS server by accessing
Access to files on a remote NFS server is provided through the
.Pa /net/nfs-server-ip/share-name/
directory, without the need for any further configuration.
directory without any additional configuration.
.It Li -media
Query devices that are not yet mounted, but contain valid filesystems.
Generally used to access files on removable media.
.It Li -null
This map prevents the
Prevent
.Xr automountd 8
from mounting anything on the mountpoint.
.El

9
usr.sbin/fstyp/Makefile Normal file
View File

@ -0,0 +1,9 @@
# $FreeBSD$
PROG= fstyp
SRCS= fstyp.c ext2fs.c cd9660.c msdosfs.c ntfs.c ufs.c
MAN= fstyp.8
WARNS= 6
.include <bsd.prog.mk>

72
usr.sbin/fstyp/cd9660.c Normal file
View File

@ -0,0 +1,72 @@
/*-
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Edward Tomasz Napierala under sponsorship
* from the FreeBSD Foundation.
*
* 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 AUTHORS 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 AUTHORS 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fstyp.h"
#define G_LABEL_ISO9660_DIR "iso9660"
#define ISO9660_MAGIC "\x01" "CD001" "\x01\x00"
#define ISO9660_OFFSET 0x8000
#define VOLUME_LEN 32
int
fstyp_cd9660(FILE *fp, char *label, size_t size)
{
char *sector, *volume;
int i;
sector = read_buf(fp, ISO9660_OFFSET, 512);
if (sector == NULL)
return (1);
if (bcmp(sector, ISO9660_MAGIC, sizeof(ISO9660_MAGIC) - 1) != 0) {
free(sector);
return (1);
}
volume = sector + 0x28;
bzero(label, size);
strlcpy(label, volume, MIN(size, VOLUME_LEN));
free(sector);
for (i = size - 1; i > 0; i--) {
if (label[i] == '\0')
continue;
else if (label[i] == ' ')
label[i] = '\0';
else
break;
}
return (0);
}

90
usr.sbin/fstyp/ext2fs.c Normal file
View File

@ -0,0 +1,90 @@
/*-
* Copyright (c) 2005 Stanislav Sedov
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Edward Tomasz Napierala under sponsorship
* from the FreeBSD Foundation.
*
* 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 <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "fstyp.h"
#define EXT2FS_SB_OFFSET 1024
#define EXT2_SUPER_MAGIC 0xef53
#define EXT2_DYNAMIC_REV 1
typedef struct e2sb {
uint8_t fake1[56];
uint16_t s_magic;
uint8_t fake2[18];
uint32_t s_rev_level;
uint8_t fake3[40];
char s_volume_name[16];
} e2sb_t;
int
fstyp_ext2fs(FILE *fp, char *label, size_t size)
{
e2sb_t *fs;
char *s_volume_name;
fs = (e2sb_t *)read_buf(fp, EXT2FS_SB_OFFSET, 512);
if (fs == NULL)
return (1);
/* Check for magic and versio n*/
if (fs->s_magic == EXT2_SUPER_MAGIC &&
fs->s_rev_level == EXT2_DYNAMIC_REV) {
//G_LABEL_DEBUG(1, "ext2fs file system detected on %s.",
// pp->name);
} else {
free(fs);
return (1);
}
s_volume_name = fs->s_volume_name;
/* Terminate label */
s_volume_name[sizeof(fs->s_volume_name) - 1] = '\0';
if (s_volume_name[0] == '/')
s_volume_name += 1;
/* Check for volume label */
if (s_volume_name[0] == '\0') {
free(fs);
return (1);
}
strlcpy(label, s_volume_name, size);
return (0);
}

97
usr.sbin/fstyp/fstyp.8 Normal file
View File

@ -0,0 +1,97 @@
.\" Copyright (c) 2014 The FreeBSD Foundation
.\" All rights reserved.
.\"
.\" This software was developed by Edward Tomasz Napierala under sponsorship
.\" from the FreeBSD Foundation.
.\"
.\" 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 AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd December 6, 2014
.Dt FSTYP 8
.Os
.Sh NAME
.Nm fstyp
.Nd determine filesystem type
.Sh SYNOPSIS
.Nm
.Op Fl l
.Op Fl s
.Ar special
.Sh DESCRIPTION
The
.Nm
utility is used to determine the filesystem type on a given device.
It can recognize ISO-9660, Ext2, FAT, NTFS, and UFS filesystems.
The filesystem name is printed to the standard output
as, respectively,
.Li cd9660 ,
.Li ext2fs ,
.Li msdosfs ,
.Li ntfs ,
or
.Li ufs .
.Pp
Because
.Nm
is built specifically to detect filesystem types, it differs from
.Xr file 1
in several ways.
The output is machine-parsable, filesystem labels are supported,
and only filesystems are identified.
Security is improved with
.Xr capsicum 4 .
.Pp
These options are available:
.Bl -tag -width ".Fl l"
.It Fl l
In addition to filesystem type, print filesystem label if available.
.It Fl s
Ignore file type.
By default,
.Nm
only works on regular files and disk-like device nodes.
Trying to read other file types might have unexpected consequences or hang
indefinitely.
.El
.Sh EXIT STATUS
The
.Nm
utility exits 0 on success, and >0 if an error occurs or the filesystem
type is not recognized.
.Sh SEE ALSO
.Xr file 1 ,
.Xr capsicum 4 ,
.Xr glabel 8 ,
.Xr mount 8
.Sh HISTORY
The
.Nm
command appeared in
.Fx 11.0 .
.Sh AUTHORS
The
.Nm
utility was developed by
.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org
under sponsorship from the FreeBSD Foundation.

210
usr.sbin/fstyp/fstyp.c Normal file
View File

@ -0,0 +1,210 @@
/*-
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Edward Tomasz Napierala under sponsorship
* from the FreeBSD Foundation.
*
* 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/capsicum.h>
#include <sys/disk.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <vis.h>
#include "fstyp.h"
#define LABEL_LEN 256
typedef int (*fstyp_function)(FILE *, char *, size_t);
static struct {
const char *name;
fstyp_function function;
} fstypes[] = {
{ "cd9660", &fstyp_cd9660 },
{ "ext2fs", &fstyp_ext2fs },
{ "msdosfs", &fstyp_msdosfs },
{ "ntfs", &fstyp_ntfs },
{ "ufs", &fstyp_ufs },
{ NULL, NULL }
};
void *
read_buf(FILE *fp, off_t off, size_t len)
{
int error;
size_t nread;
void *buf;
error = fseek(fp, off, SEEK_SET);
if (error != 0) {
warn("cannot seek to %jd", (uintmax_t)off);
return (NULL);
}
buf = malloc(len);
if (buf == 0) {
warn("cannot malloc %zd bytes of memory", len);
return (NULL);
}
nread = fread(buf, len, 1, fp);
if (nread != 1) {
free(buf);
if (feof(fp) == 0)
warn("fread");
return (NULL);
}
return (buf);
}
char *
checked_strdup(const char *s)
{
char *c;
c = strdup(s);
if (c == NULL)
err(1, "strdup");
return (c);
}
static void
usage(void)
{
fprintf(stderr, "usage: fstyp [-l][-s] special\n");
exit(1);
}
static void
type_check(const char *path, FILE *fp)
{
int error, fd;
off_t mediasize;
struct stat sb;
fd = fileno(fp);
error = fstat(fd, &sb);
if (error != 0)
err(1, "%s: fstat", path);
if (S_ISREG(sb.st_mode))
return;
error = ioctl(fd, DIOCGMEDIASIZE, &mediasize);
if (error != 0)
errx(1, "%s: not a disk", path);
}
int
main(int argc, char **argv)
{
int ch, error, i, nbytes;
bool ignore_type = false, show_label = false;
char label[LABEL_LEN + 1], strvised[LABEL_LEN * 4 + 1];
char *path;
FILE *fp;
fstyp_function fstyp_f;
while ((ch = getopt(argc, argv, "ls")) != -1) {
switch (ch) {
case 'l':
show_label = true;
break;
case 's':
ignore_type = true;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc != 1)
usage();
path = argv[0];
fp = fopen(path, "r");
if (fp == NULL)
err(1, "%s", path);
error = cap_enter();
if (error != 0 && errno != ENOSYS)
err(1, "cap_enter");
if (ignore_type == false)
type_check(path, fp);
memset(label, '\0', sizeof(label));
for (i = 0;; i++) {
fstyp_f = fstypes[i].function;
if (fstyp_f == NULL)
break;
error = fstyp_f(fp, label, sizeof(label));
if (error == 0)
break;
}
if (fstypes[i].name == NULL) {
warnx("%s: filesystem not recognized", path);
return (1);
}
if (show_label && label[0] != '\0') {
/*
* XXX: I'd prefer VIS_HTTPSTYLE, but it unconditionally
* encodes spaces.
*/
nbytes = strsnvis(strvised, sizeof(strvised), label,
VIS_GLOB | VIS_NL, "\"'$");
if (nbytes == -1)
err(1, "strsnvis");
printf("%s %s\n", fstypes[i].name, strvised);
} else {
printf("%s\n", fstypes[i].name);
}
return (0);
}

46
usr.sbin/fstyp/fstyp.h Normal file
View File

@ -0,0 +1,46 @@
/*-
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Edward Tomasz Napierala under sponsorship
* from the FreeBSD Foundation.
*
* 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 FSTYP_H
#define FSTYP_H
#define MIN(a,b) (((a)<(b))?(a):(b))
void *read_buf(FILE *fp, off_t off, size_t len);
char *checked_strdup(const char *s);
int fstyp_cd9660(FILE *fp, char *label, size_t size);
int fstyp_ext2fs(FILE *fp, char *label, size_t size);
int fstyp_msdosfs(FILE *fp, char *label, size_t size);
int fstyp_ntfs(FILE *fp, char *label, size_t size);
int fstyp_ufs(FILE *fp, char *label, size_t size);
#endif /* !FSTYP_H */

183
usr.sbin/fstyp/msdosfs.c Normal file
View File

@ -0,0 +1,183 @@
/*-
* Copyright (c) 2004 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* Copyright (c) 2006 Tobias Reifenberger
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Edward Tomasz Napierala under sponsorship
* from the FreeBSD Foundation.
*
* 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 AUTHORS 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 AUTHORS 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fstyp.h"
#include "msdosfs.h"
#define LABEL_NO_NAME "NO NAME "
int
fstyp_msdosfs(FILE *fp, char *label, size_t size)
{
FAT_BSBPB *pfat_bsbpb;
FAT32_BSBPB *pfat32_bsbpb;
FAT_DES *pfat_entry;
uint8_t *sector0, *sector;
uint32_t i;
sector0 = NULL;
sector = NULL;
/* Load 1st sector with boot sector and boot parameter block. */
sector0 = (uint8_t *)read_buf(fp, 0, 512);
if (sector0 == NULL)
return (1);
/* Check for the FAT boot sector signature. */
if (sector0[510] != 0x55 || sector0[511] != 0xaa) {
goto error;
}
/*
* Test if this is really a FAT volume and determine the FAT type.
*/
pfat_bsbpb = (FAT_BSBPB *)sector0;
pfat32_bsbpb = (FAT32_BSBPB *)sector0;
if (UINT16BYTES(pfat_bsbpb->BPB_FATSz16) != 0) {
/*
* If the BPB_FATSz16 field is not zero and the string "FAT" is
* at the right place, this should be a FAT12 or FAT16 volume.
*/
if (strncmp(pfat_bsbpb->BS_FilSysType, "FAT", 3) != 0) {
goto error;
}
/* A volume with no name should have "NO NAME " as label. */
if (strncmp(pfat_bsbpb->BS_VolLab, LABEL_NO_NAME,
sizeof(pfat_bsbpb->BS_VolLab)) == 0) {
goto endofchecks;
}
strlcpy(label, pfat_bsbpb->BS_VolLab,
MIN(size, sizeof(pfat_bsbpb->BS_VolLab) + 1));
} else if (UINT32BYTES(pfat32_bsbpb->BPB_FATSz32) != 0) {
uint32_t fat_FirstDataSector, fat_BytesPerSector, offset;
/*
* If the BPB_FATSz32 field is not zero and the string "FAT" is
* at the right place, this should be a FAT32 volume.
*/
if (strncmp(pfat32_bsbpb->BS_FilSysType, "FAT", 3) != 0) {
goto error;
}
/*
* If the volume label is not "NO NAME " we're done.
*/
if (strncmp(pfat32_bsbpb->BS_VolLab, LABEL_NO_NAME,
sizeof(pfat32_bsbpb->BS_VolLab)) != 0) {
strlcpy(label, pfat32_bsbpb->BS_VolLab,
MIN(size, sizeof(pfat32_bsbpb->BS_VolLab) + 1));
goto endofchecks;
}
/*
* If the volume label "NO NAME " is in the boot sector, the
* label of FAT32 volumes may be stored as a special entry in
* the root directory.
*/
fat_FirstDataSector =
UINT16BYTES(pfat32_bsbpb->BPB_RsvdSecCnt) +
(pfat32_bsbpb->BPB_NumFATs *
UINT32BYTES(pfat32_bsbpb->BPB_FATSz32));
fat_BytesPerSector = UINT16BYTES(pfat32_bsbpb->BPB_BytsPerSec);
// fat_FirstDataSector, fat_BytesPerSector);
for (offset = fat_BytesPerSector * fat_FirstDataSector;;
offset += fat_BytesPerSector) {
sector = (uint8_t *)read_buf(fp, offset, fat_BytesPerSector);
if (sector == NULL)
goto error;
pfat_entry = (FAT_DES *)sector;
do {
/* No more entries available. */
if (pfat_entry->DIR_Name[0] == 0) {
goto endofchecks;
}
/* Skip empty or long name entries. */
if (pfat_entry->DIR_Name[0] == 0xe5 ||
(pfat_entry->DIR_Attr &
FAT_DES_ATTR_LONG_NAME) ==
FAT_DES_ATTR_LONG_NAME) {
continue;
}
/*
* The name of the entry is the volume label if
* ATTR_VOLUME_ID is set.
*/
if (pfat_entry->DIR_Attr &
FAT_DES_ATTR_VOLUME_ID) {
strlcpy(label, pfat_entry->DIR_Name,
MIN(size,
sizeof(pfat_entry->DIR_Name) + 1));
goto endofchecks;
}
} while((uint8_t *)(++pfat_entry) <
(uint8_t *)(sector + fat_BytesPerSector));
free(sector);
}
} else {
goto error;
}
endofchecks:
for (i = size - 1; i > 0; i--) {
if (label[i] == '\0')
continue;
else if (label[i] == ' ')
label[i] = '\0';
else
break;
}
free(sector0);
free(sector);
return (0);
error:
free(sector0);
free(sector);
return (1);
}

140
usr.sbin/fstyp/msdosfs.h Normal file
View File

@ -0,0 +1,140 @@
/*-
* Copyright (c) 2006 Tobias Reifenberger
* 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 AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/types.h>
/*
* Conversion macros for little endian encoded unsigned integers
* in byte streams to the local unsigned integer format.
*/
#define UINT16BYTES(p) ((uint32_t)((p)[0] + (256*(p)[1])))
#define UINT32BYTES(p) ((uint32_t)((p)[0] + (256*(p)[1]) + \
(65536*(p)[2]) + (16777216*(p)[3])))
/*
* All following structures are according to:
*
* Microsoft Extensible Firmware Initiative FAT32 File System Specification
* FAT: General Overview of On-Disk Format
* Version 1.03, December 6, 2000
* Microsoft Corporation
*/
/*
* FAT boot sector and boot parameter block for
* FAT12 and FAT16 volumes
*/
typedef struct fat_bsbpb {
/* common fields */
uint8_t BS_jmpBoot[3];
uint8_t BS_OEMName[8];
uint8_t BPB_BytsPerSec[2];
uint8_t BPB_SecPerClus;
uint8_t BPB_RsvdSecCnt[2];
uint8_t BPB_NumFATs;
uint8_t BPB_RootEntCnt[2];
uint8_t BPB_TotSec16[2];
uint8_t BPB_Media;
uint8_t BPB_FATSz16[2];
uint8_t BPB_SecPerTrack[2];
uint8_t BPB_NumHeads[2];
uint8_t BPB_HiddSec[4];
uint8_t BPB_TotSec32[4];
/* FAT12/FAT16 only fields */
uint8_t BS_DrvNum;
uint8_t BS_Reserved1;
uint8_t BS_BootSig;
uint8_t BS_VolID[4];
uint8_t BS_VolLab[11];
uint8_t BS_FilSysType[8];
} FAT_BSBPB; /* 62 bytes */
/*
* FAT boot sector and boot parameter block for
* FAT32 volumes
*/
typedef struct fat32_bsbpb {
/* common fields */
uint8_t BS_jmpBoot[3];
uint8_t BS_OEMName[8];
uint8_t BPB_BytsPerSec[2];
uint8_t BPB_SecPerClus;
uint8_t BPB_RsvdSecCnt[2];
uint8_t BPB_NumFATs;
uint8_t BPB_RootEntCnt[2];
uint8_t BPB_TotSec16[2];
uint8_t BPB_Media;
uint8_t BPB_FATSz16[2];
uint8_t BPB_SecPerTrack[2];
uint8_t BPB_NumHeads[2];
uint8_t BPB_HiddSec[4];
uint8_t BPB_TotSec32[4];
/* FAT32 only fields */
uint8_t BPB_FATSz32[4];
uint8_t BPB_ExtFlags[2];
uint8_t BPB_FSVer[2];
uint8_t BPB_RootClus[4];
uint8_t BPB_FSInfo[2];
uint8_t BPB_BkBootSec[2];
uint8_t BPB_Reserved[12];
uint8_t BS_DrvNum;
uint8_t BS_Reserved1;
uint8_t BS_BootSig;
uint8_t BS_VolID[4];
uint8_t BS_VolLab[11];
uint8_t BS_FilSysType[8];
} FAT32_BSBPB; /* 90 bytes */
/*
* FAT directory entry structure
*/
#define FAT_DES_ATTR_READ_ONLY 0x01
#define FAT_DES_ATTR_HIDDEN 0x02
#define FAT_DES_ATTR_SYSTEM 0x04
#define FAT_DES_ATTR_VOLUME_ID 0x08
#define FAT_DES_ATTR_DIRECTORY 0x10
#define FAT_DES_ATTR_ARCHIVE 0x20
#define FAT_DES_ATTR_LONG_NAME (FAT_DES_ATTR_READ_ONLY | \
FAT_DES_ATTR_HIDDEN | \
FAT_DES_ATTR_SYSTEM | \
FAT_DES_ATTR_VOLUME_ID)
typedef struct fat_des {
uint8_t DIR_Name[11];
uint8_t DIR_Attr;
uint8_t DIR_NTRes;
uint8_t DIR_CrtTimeTenth;
uint8_t DIR_CrtTime[2];
uint8_t DIR_CrtDate[2];
uint8_t DIR_LstAccDate[2];
uint8_t DIR_FstClusHI[2];
uint8_t DIR_WrtTime[2];
uint8_t DIR_WrtDate[2];
uint8_t DIR_FstClusLO[2];
uint8_t DIR_FileSize[4];
} FAT_DES;

165
usr.sbin/fstyp/ntfs.c Normal file
View File

@ -0,0 +1,165 @@
/*-
* Copyright (c) 2005 Takanori Watanabe
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Edward Tomasz Napierala under sponsorship
* from the FreeBSD Foundation.
*
* 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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fstyp.h"
#define NTFS_A_VOLUMENAME 0x60
#define NTFS_FILEMAGIC ((uint32_t)(0x454C4946))
#define NTFS_VOLUMEINO 3
#define G_LABEL_NTFS_DIR "ntfs"
struct ntfs_attr {
uint32_t a_type;
uint32_t reclen;
uint8_t a_flag;
uint8_t a_namelen;
uint8_t a_nameoff;
uint8_t reserved1;
uint8_t a_compression;
uint8_t reserved2;
uint16_t a_index;
uint16_t a_datalen;
uint16_t reserved3;
uint16_t a_dataoff;
uint16_t a_indexed;
} __packed;
struct ntfs_filerec {
uint32_t fr_hdrmagic;
uint16_t fr_hdrfoff;
uint16_t fr_hdrfnum;
uint8_t reserved[8];
uint16_t fr_seqnum;
uint16_t fr_nlink;
uint16_t fr_attroff;
uint16_t fr_flags;
uint32_t fr_size;
uint32_t fr_allocated;
uint64_t fr_mainrec;
uint16_t fr_attrnum;
} __packed;
struct ntfs_bootfile {
uint8_t reserved1[3];
uint8_t bf_sysid[8];
uint16_t bf_bps;
uint8_t bf_spc;
uint8_t reserved2[7];
uint8_t bf_media;
uint8_t reserved3[2];
uint16_t bf_spt;
uint16_t bf_heads;
uint8_t reserver4[12];
uint64_t bf_spv;
uint64_t bf_mftcn;
uint64_t bf_mftmirrcn;
int8_t bf_mftrecsz;
uint32_t bf_ibsz;
uint32_t bf_volsn;
} __packed;
int
fstyp_ntfs(FILE *fp, char *label, size_t size)
{
struct ntfs_bootfile *bf;
struct ntfs_filerec *fr;
struct ntfs_attr *atr;
off_t voloff;
char *filerecp, *ap;
int8_t mftrecsz;
char vnchar;
int recsize, j;
filerecp = NULL;
bf = (struct ntfs_bootfile *)read_buf(fp, 0, 512);
if (bf == NULL || strncmp(bf->bf_sysid, "NTFS ", 8) != 0)
return (1);
mftrecsz = bf->bf_mftrecsz;
recsize = (mftrecsz > 0) ? (mftrecsz * bf->bf_bps * bf->bf_spc) : (1 << -mftrecsz);
voloff = bf->bf_mftcn * bf->bf_spc * bf->bf_bps +
recsize * NTFS_VOLUMEINO;
filerecp = read_buf(fp, voloff, recsize);
if (filerecp == NULL)
goto fail;
fr = (struct ntfs_filerec *)filerecp;
if (fr->fr_hdrmagic != NTFS_FILEMAGIC)
goto fail;
for (ap = filerecp + fr->fr_attroff;
atr = (struct ntfs_attr *)ap, (int)atr->a_type != -1;
ap += atr->reclen) {
if (atr->a_type == NTFS_A_VOLUMENAME) {
if(atr->a_datalen >= size *2){
goto fail;
}
/*
*UNICODE to ASCII.
* Should we need to use iconv(9)?
*/
for (j = 0; j < atr->a_datalen; j++) {
vnchar = *(ap + atr->a_dataoff + j);
if (j & 1) {
if (vnchar) {
goto fail;
}
} else {
label[j / 2] = vnchar;
}
}
label[j / 2] = 0;
break;
}
}
free(bf);
free(filerecp);
return (0);
fail:
free(bf);
free(filerecp);
return (1);
}

109
usr.sbin/fstyp/ufs.c Normal file
View File

@ -0,0 +1,109 @@
/*-
* Copyright (c) 2002, 2003 Gordon Tetlow
* Copyright (c) 2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* Copyright (c) 2014 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Edward Tomasz Napierala under sponsorship
* from the FreeBSD Foundation.
*
* 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 AUTHORS 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 AUTHORS 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/types.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ufs/ufs/dinode.h>
#include <ufs/ffs/fs.h>
#include "fstyp.h"
static const int superblocks[] = SBLOCKSEARCH;
int
fstyp_ufs(FILE *fp, char *label, size_t labelsize)
{
int sb, superblock;
struct fs *fs;
/*
* Walk through the standard places that superblocks hide and look
* for UFS magic. If we find magic, then check that the size in the
* superblock corresponds to the size of the underlying provider.
* Finally, look for a volume label and create an appropriate
* provider based on that.
*/
for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) {
fs = (struct fs *)read_buf(fp, superblock, SBLOCKSIZE);
if (fs == NULL)
continue;
/*
* Check for magic. We also need to check if file system size is equal
* to providers size, because sysinstall(8) used to bogusly put first
* partition at offset 0 instead of 16, and glabel/ufs would find file
* system on slice instead of partition.
*/
#ifdef notyet
if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0 &&
((pp->mediasize / fs->fs_fsize == fs->fs_old_size) ||
(pp->mediasize / fs->fs_fsize == fs->fs_providersize))) {
/* Valid UFS1. */
} else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0 &&
((pp->mediasize / fs->fs_fsize == fs->fs_size) ||
(pp->mediasize / fs->fs_fsize == fs->fs_providersize))) {
/* Valid UFS2. */
} else {
g_free(fs);
continue;
}
#else
if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0) {
/* Valid UFS1. */
} else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0) {
/* Valid UFS2. */
} else {
free(fs);
continue;
}
#endif
if (fs->fs_sblockloc != superblock || fs->fs_ncg < 1 ||
fs->fs_bsize < MINBSIZE ||
(size_t)fs->fs_bsize < sizeof(struct fs)) {
free(fs);
continue;
}
strlcpy(label, fs->fs_volname, labelsize);
free(fs);
return (0);
}
return (1);
}

View File

@ -233,7 +233,7 @@ miss(NODE *p, char *tail)
miss(p->child, tp + 1);
*tp = '\0';
if (!create)
if (!create && !uflag)
continue;
if (chown(path, p->st_uid, p->st_gid) == -1) {
serr = errno;

View File

@ -5,10 +5,17 @@ TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.sbin/useradd
TESTSDIR= ${TESTSBASE}/usr.sbin/pw
ATF_TESTS_SH= pw_delete pw_lock pw_modify pw_etcdir
ATF_TESTS_SH= pw_etcdir \
pw_lock \
pw_groupdel \
pw_groupmod \
pw_useradd \
pw_userdel \
pw_usermod
TEST_METADATA.pw_delete+= required_user="root"
TEST_METADATA.pw_modify+= required_user="root"
.for tp in ${ATF_TESTS_SH}
TEST_METADATA.${tp}+= required_user="root"
.endfor
FILES= group helper_functions.shin master.passwd
FILESDIR= ${TESTSDIR}

View File

@ -0,0 +1,24 @@
# $FreeBSD$
# Import helper functions
. $(atf_get_srcdir)/helper_functions.shin
# Test to make sure we do not accidentially delete wheel when trying to delete
# an unknown group
atf_test_case group_do_not_delete_wheel_if_group_unknown
group_do_not_delete_wheel_if_group_unknown_head() {
atf_set "descr" "Make sure we do not consider gid 0 an unknown group"
}
group_do_not_delete_wheel_if_group_unknown_body() {
populate_etc_skel
atf_check -s exit:0 -o inline:"wheel:*:0:root\n" -x ${PW} groupshow wheel
atf_check -e inline:"pw: -g expects a number\n" -s exit:64 -x \
${PW} groupdel -g I_do_not_exist
atf_check -s exit:0 -o inline:"wheel:*:0:root\n" -x ${PW} groupshow wheel
}
atf_init_test_cases() {
atf_add_test_case group_do_not_delete_wheel_if_group_unknown
}

40
usr.sbin/pw/tests/pw_useradd.sh Executable file
View File

@ -0,0 +1,40 @@
# $FreeBSD$
# Import helper functions
. $(atf_get_srcdir)/helper_functions.shin
# Test add user
atf_test_case user_add
user_add_body() {
populate_etc_skel
atf_check -s exit:0 ${PW} useradd test
atf_check -s exit:0 -o match:"^test:.*" \
grep "^test:.*" $HOME/master.passwd
}
atf_test_case user_add_comments
user_add_comments_body() {
populate_etc_skel
atf_check -s exit:0 ${PW} useradd test -c "Test User,work,123,456"
atf_check -s exit:0 -o match:"^test:.*:Test User,work,123,456:" \
grep "^test:.*:Test User,work,123,456:" $HOME/master.passwd
}
atf_test_case user_add_comments_invalid
user_add_comments_invalid_body() {
populate_etc_skel
atf_check -s exit:65 -e match:"invalid character" \
${PW} useradd test -c "Test User,work,123:456,456"
atf_check -s exit:1 -o empty \
grep "^test:.*:Test User,work,123:456,456:" $HOME/master.passwd
}
atf_init_test_cases() {
atf_add_test_case user_add
atf_add_test_case user_add_comments
atf_add_test_case user_add_comments_invalid
}

View File

@ -3,6 +3,7 @@
# Import helper functions
. $(atf_get_srcdir)/helper_functions.shin
# Test that a user can be deleted when another user is part of this
# user's default group and does not go into an infinate loop.
# PR: 191427
@ -18,30 +19,19 @@ rmuser_seperate_group_body() {
${PW} userdel test || atf_fail "Delete the test user"
}
atf_test_case group_do_not_delete_wheel_if_group_unknown
group_do_not_delete_wheel_if_group_unknown_head() {
atf_set "descr" "Make sure we do not consider gid 0 an unknown group"
}
group_do_not_delete_wheel_if_group_unknown_body() {
populate_etc_skel
atf_check -s exit:0 -o inline:"wheel:*:0:root\n" -x ${PW} groupshow wheel
atf_check -e inline:"pw: -g expects a number\n" -s exit:64 -x ${PW} groupdel -g I_do_not_exist
atf_check -s exit:0 -o inline:"wheel:*:0:root\n" -x ${PW} groupshow wheel
}
atf_test_case user_do_not_try_to_delete_root_if_user_unknown
user_do_not_try_to_delete_root_if_user_unknown_head() {
atf_set "descr" "Make sure not to try to remove root if deleting an unknown user"
atf_set "descr" \
"Make sure not to try to remove root if deleting an unknown user"
}
user_do_not_try_to_delete_root_if_user_unknown_body() {
populate_etc_skel
atf_check -e inline:"pw: -u expects a number\n" -s exit:64 -x ${PW} userdel -u plop
atf_check -e inline:"pw: -u expects a number\n" -s exit:64 -x \
${PW} userdel -u plop
}
atf_init_test_cases() {
atf_add_test_case rmuser_seperate_group
atf_add_test_case group_do_not_delete_wheel_if_group_unknown
atf_add_test_case user_do_not_try_to_delete_root_if_user_unknown
}

56
usr.sbin/pw/tests/pw_usermod.sh Executable file
View File

@ -0,0 +1,56 @@
# $FreeBSD$
# Import helper functions
. $(atf_get_srcdir)/helper_functions.shin
# Test modifying a user
atf_test_case user_mod
user_mod_body() {
populate_etc_skel
atf_check -s exit:67 -e match:"no such user" ${PW} usermod test
atf_check -s exit:0 ${PW} useradd test
atf_check -s exit:0 ${PW} usermod test
atf_check -s exit:0 -o match:"^test:.*" \
grep "^test:.*" $HOME/master.passwd
}
# Test modifying a user with comments
atf_test_case user_mod_comments
user_mod_comments_body() {
populate_etc_skel
atf_check -s exit:0 ${PW} useradd test -c "Test User,home,123,456"
atf_check -s exit:0 ${PW} usermod test -c "Test User,work,123,456"
atf_check -s exit:0 -o match:"^test:.*:Test User,work,123,456:" \
grep "^test:.*:Test User,work,123,456:" $HOME/master.passwd
}
# Test modifying a user with invalid comments
atf_test_case user_mod_comments_invalid
user_mod_comments_invalid_body() {
populate_etc_skel
atf_check -s exit:0 ${PW} useradd test
atf_check -s exit:65 -e match:"invalid character" \
${PW} usermod test -c "Test User,work,123:456,456"
atf_check -s exit:1 -o empty \
grep "^test:.*:Test User,work,123:456,456:" $HOME/master.passwd
}
# Test modifying a user name with -l
atf_test_case user_mod_name
user_mod_name_body() {
populate_etc_skel
atf_check -s exit:0 ${PW} useradd foo
atf_check -s exit:0 ${PW} usermod foo -l "bar"
atf_check -s exit:0 -o match:"^bar:.*" \
grep "^bar:.*" $HOME/master.passwd
}
atf_init_test_cases() {
atf_add_test_case user_mod
atf_add_test_case user_mod_comments
atf_add_test_case user_mod_comments_invalid
atf_add_test_case user_mod_name
}