Commit 1cded551 authored by Paolo \'Blaisorblade\' Giarrusso's avatar Paolo \'Blaisorblade\' Giarrusso Committed by Linus Torvalds

[PATCH] uml: Uml base patch

The main part of UML; it is the last distributed patch for 2.6.7 Removes skas
support from the main UML patch; apply or get conflicts.
Signed-off-by: default avatarPaolo 'Blaisorblade' Giarrusso <blaisorblade_spam@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 27ef71dc
......@@ -61,6 +61,20 @@ config MODE_SKAS
config NET
bool "Networking support"
help
Unless you really know what you are doing, you should say Y here.
The reason is that some programs need kernel networking support even
when running on a stand-alone machine that isn't connected to any
other computer. If you are upgrading from an older kernel, you
should consider updating your networking tools too because changes
in the kernel and the tools often go hand in hand. The tools are
contained in the package net-tools, the location and version number
of which are given in Documentation/Changes.
For a general introduction to Linux networking, it is highly
recommended to read the NET-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
source "fs/Kconfig.binfmt"
......@@ -85,6 +99,19 @@ config HOSTFS
If you'd like to be able to work with files stored on the host,
say Y or M here; otherwise say N.
config HPPFS
tristate "HoneyPot ProcFS"
help
hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
entries to be overridden, removed, or fabricated from the host.
Its purpose is to allow a UML to appear to be a physical machine
by removing or changing anything in /proc which gives away the
identity of a UML.
See http://user-mode-linux.sf.net/hppfs.html for more information.
You only need this if you are setting up a UML honeypot. Otherwise,
it is safe to say 'N' here.
config MCONSOLE
bool "Management console"
......@@ -164,6 +191,17 @@ config KERNEL_STACK_ORDER
be 1 << order pages. The default is OK unless you're running Valgrind
on UML, in which case, set this to 3.
config UML_REAL_TIME_CLOCK
bool "Real-time Clock"
default y
help
This option makes UML time deltas match wall clock deltas. This should
normally be enabled. The exception would be if you are debugging with
UML and spend long times with UML stopped at a breakpoint. In this
case, when UML is restarted, it will call the timer enough times to make
up for the time spent at the breakpoint. This could result in a
noticable lag. If this is a problem, then disable this option.
endmenu
source "init/Kconfig"
......
......@@ -9,6 +9,10 @@ config FRAME_POINTER
config PT_PROXY
bool "Enable ptrace proxy"
depends on XTERM_CHAN && DEBUG_INFO
help
This option enables a debugging interface which allows gdb to debug
the kernel without needing to actually attach to kernel threads.
If you want to do kernel debugging, say Y here; otherwise say N.
config GPROF
bool "Enable gprof support"
......
......@@ -29,6 +29,20 @@ config BLK_DEV_UBD_SYNC
wise choice too. In all other cases (for example, if you're just
playing around with User-Mode Linux) you can choose N.
# Turn this back on when the driver actually works
#
#config BLK_DEV_COW
# tristate "COW block device"
# help
# This is a layered driver which sits above two other block devices.
# One is read-only, and the other is a read-write layer which stores
# all changes. This provides the illusion that the read-only layer
# can be mounted read-write and changed.
config BLK_DEV_COW_COMMON
bool
default BLK_DEV_COW || BLK_DEV_UBD
config BLK_DEV_LOOP
tristate "Loopback device support"
......
menu "Network Devices"
menu "UML Network Devices"
depends on NET
# UML virtual driver
......@@ -176,73 +176,5 @@ config UML_NET_SLIRP
Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp"
# Below are hardware-independent drivers mirrored from
# drivers/net/Config.in. It would be nice if Linux
# had HW independent drivers separated from the other
# but it does not. Until then each non-ISA/PCI arch
# needs to provide it's own menu of network drivers
config DUMMY
tristate "Dummy net driver support"
config BONDING
tristate "Bonding driver support"
config EQUALIZER
tristate "EQL (serial line load balancing) support"
config TUN
tristate "Universal TUN/TAP device driver support"
config ETHERTAP
tristate "Ethertap network tap (OBSOLETE)"
depends on EXPERIMENTAL && NETLINK
config PPP
tristate "PPP (point-to-point protocol) support"
config PPP_MULTILINK
bool "PPP multilink support (EXPERIMENTAL)"
depends on PPP && EXPERIMENTAL
config PPP_FILTER
bool "PPP filtering"
depends on PPP && FILTER
config PPP_ASYNC
tristate "PPP support for async serial ports"
depends on PPP
config PPP_SYNC_TTY
tristate "PPP support for sync tty ports"
depends on PPP
config PPP_DEFLATE
tristate "PPP Deflate compression"
depends on PPP
config PPP_BSDCOMP
tristate "PPP BSD-Compress compression"
depends on PPP
config PPPOE
tristate "PPP over Ethernet (EXPERIMENTAL)"
depends on PPP && EXPERIMENTAL
config SLIP
tristate "SLIP (serial line) support"
config SLIP_COMPRESSED
bool "CSLIP compressed headers"
depends on SLIP=y
config SLIP_SMART
bool "Keepalive and linefill"
depends on SLIP=y
config SLIP_MODE_SLIP6
bool "Six bit SLIP encapsulation"
depends on SLIP=y
endmenu
......@@ -22,17 +22,21 @@ core-y += $(ARCH_DIR)/kernel/ \
$(ARCH_DIR)/sys-$(SUBARCH)/
# Have to precede the include because the included Makefiles reference them.
SYMLINK_HEADERS = include/asm-um/archparam.h include/asm-um/system.h \
include/asm-um/sigcontext.h include/asm-um/processor.h \
include/asm-um/ptrace.h include/asm-um/arch-signal.h
SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \
arch-signal.h module.h
SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
$(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h
include $(ARCH_DIR)/Makefile-$(SUBARCH)
include $(ARCH_DIR)/Makefile-os-$(OS)
# This target adds dependencies to "prepare". They are defined in the included
# Makefiles (see Makefile-i386).
.PHONY: sys_prepare
sys_prepare:
@:
MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt
MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas
......@@ -41,6 +45,9 @@ ifneq ($(MAKEFILE-y),)
include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y))
endif
include $(ARCH_DIR)/Makefile-$(SUBARCH)
include $(ARCH_DIR)/Makefile-os-$(OS)
EXTRAVERSION := $(EXTRAVERSION)-1um
ARCH_INCLUDE = -I$(ARCH_DIR)/include
......@@ -52,14 +59,20 @@ ARCH_INCLUDE = -I$(ARCH_DIR)/include
CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
-D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \
$(MODE_INCLUDE)
-Dsigprocmask=kernel_sigprocmask $(MODE_INCLUDE)
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
# These are needed for clean and mrproper, since in that case .config is not
# included; the values here are meaningless
CONFIG_NEST_LEVEL ?= 0
CONFIG_KERNEL_HALF_GIGS ?= 0
SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000)
ifeq ($(CONFIG_MODE_SKAS), y)
$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
$(SYS_HEADERS) : $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h
endif
include/linux/version.h: arch/$(ARCH)/Makefile
......@@ -98,17 +111,17 @@ CPP_MODE_TT := $(shell [ "$(CONFIG_MODE_TT)" = "y" ] && echo -DMODE_TT)
CONFIG_KERNEL_STACK_ORDER ?= 2
STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \
CPPFLAGS_vmlinux.lds = $(shell echo -U$(SUBARCH) \
-DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \
-DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \
-DKERNEL_STACK_SIZE=$(STACK_SIZE)
-DKERNEL_STACK_SIZE=$(STACK_SIZE))
CPPFLAGS_$(LD_SCRIPT-y) = $(CPPFLAGS_vmlinux.lds) -P -C -Uum
export CPPFLAGS_$(LD_SCRIPT-y) = $(CPPFLAGS_vmlinux.lds) -P -C -Uum
LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y)
$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
$(call if_changed_dep,as_s_S)
#$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
# $(call if_changed_dep,as_s_S)
linux: vmlinux $(LD_SCRIPT-y)
$(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \
......@@ -116,37 +129,47 @@ linux: vmlinux $(LD_SCRIPT-y)
USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS))
USER_CFLAGS := $(patsubst -Dsigprocmask=kernel_sigprocmask,,$(USER_CFLAGS))
USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
$(MODE_INCLUDE)
# To get a definition of F_SETSIG
USER_CFLAGS += -D_GNU_SOURCE
# From main Makefile, these options are set after including the ARCH makefile.
# So copy them here.
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
USER_CFLAGS += -Os
else
USER_CFLAGS += -O2
endif
ifndef CONFIG_FRAME_POINTER
USER_CFLAGS += -fomit-frame-pointer
endif
ifdef CONFIG_DEBUG_INFO
USER_CFLAGS += -g
endif
CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/uml.lds \
$(ARCH_DIR)/dyn_link.ld.s $(GEN_HEADERS)
$(ARCH_DIR)/dyn_link.ld.s $(ARCH_DIR)/include/uml-config.h \
$(GEN_HEADERS)
$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c
$(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \
$(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS))
$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c sys_prepare
@ echo ' MAIN $@'
@ $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
archmrproper:
for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \
do \
$(MAKE) -C $$d archmrproper; \
done
rm -f $(CLEAN_FILES) $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) include/asm \
$(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS))
archclean: sysclean
for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \
do \
$(MAKE) -C $$d clean; \
done
find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
-o -name '*.gcov' \) -type f -print | xargs rm -f
rm -f linux x.i gmon.out $(ARCH_DIR)/link.ld $(GEN_HEADERS)
@:
archdep:
for d in $(ARCH_SUBDIRS); do $(MAKE) -C $$d fastdep; done
archclean:
@find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
-o -name '*.gcov' \) -type f -print | xargs rm -f
$(SYMLINK_HEADERS):
cd $(TOPDIR)/$(dir $@) ; \
......@@ -161,19 +184,26 @@ $(ARCH_DIR)/include/sysdep:
$(ARCH_DIR)/os:
cd $(ARCH_DIR) && ln -sf os-$(OS) os
$(ARCH_DIR)/include/uml-config.h :
sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@
# Generated files
define filechk_umlconfig
sed 's/ CONFIG/ UML_CONFIG/'
endef
$(ARCH_DIR)/include/uml-config.h : $(TOPDIR)/include/linux/autoconf.h
$(call filechk,umlconfig)
filechk_gen_header = $<
$(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task
$< > $@
$(call filechk,gen_header)
$(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants
$< > $@
$(call filechk,gen_header)
$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h \
$(ARCH_DIR)/util FORCE ;
$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants : $(ARCH_DIR)/util \
sys_prepare FORCE ;
$(ARCH_DIR)/util: FORCE
@$(call descend,$@,)
$(Q)$(MAKE) $(build)=$@
export SUBARCH USER_CFLAGS OS
......@@ -16,22 +16,27 @@ SYS_UTIL_DIR := $(ARCH_DIR)/sys-i386/util
SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
sys_prepare: $(SYS_DIR)/sc.h
prepare: $(SYS_HEADERS)
filechk_$(SYS_DIR)/sc.h := $(SYS_UTIL_DIR)/mk_sc
$(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
$< > $@
$(call filechk,$@)
filechk_$(SYS_DIR)/thread.h := $(SYS_UTIL_DIR)/mk_thread
$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
$< > $@
$(call filechk,$@)
$(SYS_UTIL_DIR)/mk_sc: FORCE ;
@$(call descend,$(SYS_UTIL_DIR),$@)
$(SYS_UTIL_DIR)/mk_sc: scripts/basic/fixdep include/config/MARKER FORCE ;
$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE ;
@$(call descend,$(SYS_UTIL_DIR),$@)
$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) sys_prepare FORCE ;
$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
$(SYS_UTIL_DIR): include/asm FORCE
@$(call descend,$@,)
$(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR)
sysclean :
rm -f $(SYS_HEADERS)
CLEAN_FILES += $(SYS_HEADERS)
......@@ -14,7 +14,7 @@ MODE_INCLUDE += -I$(TOPDIR)/$(ARCH_DIR)/kernel/skas/include
LINK_SKAS = -Wl,-rpath,/lib
LD_SCRIPT_SKAS = dyn.lds
GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
GEN_HEADERS += $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h
$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h :
$(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h
$(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h :
$(Q)$(MAKE) $(build)=$(ARCH_DIR)/kernel/skas $@
......@@ -227,7 +227,6 @@ CONFIG_ROMFS_FS=m
CONFIG_EXT2_FS=y
CONFIG_SYSV_FS=m
CONFIG_UDF_FS=m
# CONFIG_UDF_RW is not set
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
......
......@@ -3,29 +3,19 @@
#
CONFIG_USERMODE=y
CONFIG_MMU=y
CONFIG_SWAP=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_CONFIG_LOG_BUF_SHIFT=14
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
#
# General Setup
# UML-specific options
#
CONFIG_MODE_TT=y
CONFIG_MODE_SKAS=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
CONFIG_HOSTFS=y
CONFIG_HPPFS=y
CONFIG_MCONSOLE=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_HOST_2G_2G is not set
......@@ -36,12 +26,43 @@ CONFIG_KERNEL_HALF_GIGS=1
# CONFIG_HIGHMEM is not set
CONFIG_PROC_MM=y
CONFIG_KERNEL_STACK_ORDER=2
CONFIG_UML_REAL_TIME_CLOCK=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_STANDALONE=y
CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_SYSCTL=y
CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
#
# Loadable module support
#
CONFIG_MODULES=y
# CONFIG_KMOD is not set
# CONFIG_MODULES is not set
#
# Generic Driver Options
#
#
# Character Devices
......@@ -69,6 +90,7 @@ CONFIG_HOSTAUDIO=y
#
CONFIG_BLK_DEV_UBD=y
# CONFIG_BLK_DEV_UBD_SYNC is not set
CONFIG_BLK_DEV_COW_COMMON=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=y
CONFIG_BLK_DEV_RAM=y
......@@ -78,7 +100,7 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_NETDEVICES=y
#
# Network Devices
# UML Network Devices
#
CONFIG_UML_NET=y
CONFIG_UML_NET_ETHERTAP=y
......@@ -88,22 +110,6 @@ CONFIG_UML_NET_DAEMON=y
CONFIG_UML_NET_MCAST=y
# CONFIG_UML_NET_PCAP is not set
CONFIG_UML_NET_SLIRP=y
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=y
# CONFIG_ETHERTAP is not set
CONFIG_PPP=y
# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPP_ASYNC is not set
# CONFIG_PPP_SYNC_TTY is not set
# CONFIG_PPP_DEFLATE is not set
# CONFIG_PPP_BSDCOMP is not set
# CONFIG_PPPOE is not set
CONFIG_SLIP=y
# CONFIG_SLIP_COMPRESSED is not set
# CONFIG_SLIP_SMART is not set
# CONFIG_SLIP_MODE_SLIP6 is not set
#
# Networking support
......@@ -115,8 +121,6 @@ CONFIG_SLIP=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
# CONFIG_NETLINK_DEV is not set
# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
......@@ -130,8 +134,11 @@ CONFIG_INET=y
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_XFRM_USER is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_IPV6 is not set
# CONFIG_DECNET is not set
# CONFIG_BRIDGE is not set
# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
......@@ -140,9 +147,9 @@ CONFIG_IPV6_SCTP__=y
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_LLC is not set
# CONFIG_DECNET is not set
# CONFIG_BRIDGE is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_NET_DIVERT is not set
......@@ -159,6 +166,10 @@ CONFIG_IPV6_SCTP__=y
# Network testing
#
# CONFIG_NET_PKTGEN is not set
CONFIG_DUMMY=y
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
CONFIG_TUN=y
#
# Ethernet (10 or 100Mbit)
......@@ -169,13 +180,29 @@ CONFIG_IPV6_SCTP__=y
# Ethernet (1000 Mbit)
#
#
# Ethernet (10000 Mbit)
#
CONFIG_PPP=y
# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPP_FILTER is not set
# CONFIG_PPP_ASYNC is not set
# CONFIG_PPP_SYNC_TTY is not set
# CONFIG_PPP_DEFLATE is not set
# CONFIG_PPP_BSDCOMP is not set
# CONFIG_PPPOE is not set
CONFIG_SLIP=y
# CONFIG_SLIP_COMPRESSED is not set
# CONFIG_SLIP_SMART is not set
# CONFIG_SLIP_MODE_SLIP6 is not set
#
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set
#
# Token Ring devices (depends on LLC=y)
# Token Ring devices
#
# CONFIG_SHAPER is not set
......@@ -184,69 +211,101 @@ CONFIG_IPV6_SCTP__=y
#
# CONFIG_WAN is not set
#
# Amateur Radio support
#
# CONFIG_HAMRADIO is not set
#
# IrDA (infrared) support
#
# CONFIG_IRDA is not set
#
# Bluetooth support
#
# CONFIG_BT is not set
#
# File systems
#
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT3_FS is not set
# CONFIG_JBD is not set
CONFIG_REISERFS_FS=y
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
# CONFIG_JFS_FS is not set
# CONFIG_XFS_FS is not set
CONFIG_MINIX_FS=y
# CONFIG_ROMFS_FS is not set
CONFIG_QUOTA=y
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
CONFIG_AUTOFS_FS=m
CONFIG_AUTOFS4_FS=m
CONFIG_REISERFS_FS=m
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
CONFIG_AUTOFS_FS=y
CONFIG_AUTOFS4_FS=y
#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
# CONFIG_JOLIET is not set
# CONFIG_ZISOFS is not set
# CONFIG_UDF_FS is not set
#
# DOS/FAT/NT Filesystems
#
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
# CONFIG_NTFS_FS is not set
#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_DEVFS_FS=y
CONFIG_DEVFS_MOUNT=y
# CONFIG_DEVFS_DEBUG is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_RAMFS=y
#
# Miscellaneous filesystems
#
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
# CONFIG_HFSPLUS_FS is not set
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EXT3_FS is not set
# CONFIG_JBD is not set
CONFIG_FAT_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
# CONFIG_EFS_FS is not set
CONFIG_JFFS_FS=y
CONFIG_JFFS_FS_VERBOSE=0
CONFIG_JFFS_PROC_FS=y
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
# CONFIG_TMPFS is not set
CONFIG_RAMFS=y
CONFIG_ISO9660_FS=m
# CONFIG_JOLIET is not set
# CONFIG_ZISOFS is not set
# CONFIG_JFS_FS is not set
CONFIG_MINIX_FS=m
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
CONFIG_DEVFS_FS=y
CONFIG_DEVFS_MOUNT=y
# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UDF_FS is not set
# CONFIG_UFS_FS is not set
# CONFIG_XFS_FS is not set
#
# Network File Systems
#
# CONFIG_CODA_FS is not set
# CONFIG_INTERMEZZO_FS is not set
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
# CONFIG_EXPORTFS is not set
# CONFIG_CIFS is not set
# CONFIG_SMB_FS is not set
# CONFIG_CIFS is not set
# CONFIG_NCP_FS is not set
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
#
......@@ -254,11 +313,11 @@ CONFIG_EXT2_FS=y
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
CONFIG_NLS=y
#
# Native Language Support
#
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
......@@ -316,28 +375,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# SCSI support
#
CONFIG_SCSI=y
CONFIG_GENERIC_ISA_DMA=y
#
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
CONFIG_SD_EXTRA_DEVS=40
CONFIG_CHR_DEV_ST=y
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
CONFIG_SR_EXTRA_DEVS=2
CONFIG_CHR_DEV_SG=y
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
CONFIG_SCSI_DEBUG_QUEUES=y
CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_DEBUG=y
# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
......@@ -359,6 +397,7 @@ CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
#
# RAM/ROM/Flash chip drivers
......@@ -373,20 +412,21 @@ CONFIG_MTD_BLOCK=y
#
# Mapping drivers for chip access
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
#
# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_MTDRAM is not set
CONFIG_MTD_BLKMTD=m
CONFIG_MTD_BLKMTD=y
#
# Disk-On-Chip Device Drivers
#
# CONFIG_MTD_DOC1000 is not set
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
......
#
# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
# Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com)
# Licensed under the GPL
#
......@@ -39,6 +39,8 @@ obj-$(CONFIG_PTY_CHAN) += pty.o
obj-$(CONFIG_TTY_CHAN) += tty.o
obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
obj-$(CONFIG_UML_WATCHDOG) += harddog.o
obj-$(CONFIG_BLK_DEV_COW) += cow_kern.o
obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
obj-y += stdio_console.o $(CHAN_OBJS)
......@@ -46,18 +48,7 @@ USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \
null.o pty.o tty.o xterm.o
USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/drivers/$(file))
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
clean:
modules:
fastdep:
dep:
archmrproper: clean
......@@ -8,6 +8,7 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/string.h>
#include <linux/tty_flip.h>
#include <asm/irq.h>
#include "chan_kern.h"
......@@ -265,6 +266,11 @@ static int one_chan_config_string(struct chan *chan, char *str, int size,
{
int n = 0;
if(chan == NULL){
CONFIG_CHUNK(str, size, n, "none", 1);
return(n);
}
CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
if(chan->dev == NULL){
......@@ -420,7 +426,8 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device,
INIT_LIST_HEAD(chans);
}
if((out = strchr(str, ',')) != NULL){
out = strchr(str, ',');
if(out != NULL){
in = str;
*out = '\0';
out++;
......@@ -475,12 +482,15 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
goto out;
}
err = chan->ops->read(chan->fd, &c, chan->data);
if(err > 0) tty_receive_char(tty, c);
if(err > 0)
tty_receive_char(tty, c);
} while(err > 0);
if(err == 0) reactivate_fd(chan->fd, irq);
if(err == -EIO){
if(chan->primary){
if(tty != NULL) tty_hangup(tty);
if(tty != NULL)
tty_hangup(tty);
line_disable(dev, irq);
close_chan(chans);
free_chan(chans);
......
/*
* Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
* Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
......@@ -7,7 +7,6 @@
#include <stdlib.h>
#include <errno.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <sys/stat.h>
......@@ -24,29 +23,27 @@
void generic_close(int fd, void *unused)
{
close(fd);
os_close_file(fd);
}
int generic_read(int fd, char *c_out, void *unused)
{
int n;
n = read(fd, c_out, sizeof(*c_out));
if(n < 0){
if(errno == EAGAIN) return(0);
return(-errno);
}
else if(n == 0) return(-EIO);
return(1);
n = os_read_file(fd, c_out, sizeof(*c_out));
if(n == -EAGAIN)
return(0);
else if(n == 0)
return(-EIO);
return(n);
}
/* XXX Trivial wrapper around os_write_file */
int generic_write(int fd, const char *buf, int n, void *unused)
{
int count;
count = write(fd, buf, n);
if(count < 0) return(-errno);
return(count);
return(os_write_file(fd, buf, n));
}
int generic_console_write(int fd, const char *buf, int n, void *unused)
......@@ -68,15 +65,18 @@ int generic_console_write(int fd, const char *buf, int n, void *unused)
int generic_window_size(int fd, void *unused, unsigned short *rows_out,
unsigned short *cols_out)
{
struct winsize size;
int ret = 0;
if(ioctl(fd, TIOCGWINSZ, &size) == 0){
ret = ((*rows_out != size.ws_row) ||
(*cols_out != size.ws_col));
*rows_out = size.ws_row;
*cols_out = size.ws_col;
}
int rows, cols;
int ret;
ret = os_window_size(fd, &rows, &cols);
if(ret < 0)
return(ret);
ret = ((*rows_out != rows) || (*cols_out != cols));
*rows_out = rows;
*cols_out = cols;
return(ret);
}
......@@ -100,14 +100,16 @@ static int winch_thread(void *arg)
struct winch_data *data = arg;
sigset_t sigs;
int pty_fd, pipe_fd;
int count, err;
char c = 1;
close(data->close_me);
os_close_file(data->close_me);
pty_fd = data->pty_fd;
pipe_fd = data->pipe_fd;
if(write(pipe_fd, &c, sizeof(c)) != sizeof(c))
count = os_write_file(pipe_fd, &c, sizeof(c));
if(count != sizeof(c))
printk("winch_thread : failed to write synchronization "
"byte, errno = %d\n", errno);
"byte, err = %d\n", -count);
signal(SIGWINCH, winch_handler);
sigfillset(&sigs);
......@@ -123,26 +125,24 @@ static int winch_thread(void *arg)
exit(1);
}
if(ioctl(pty_fd, TIOCSCTTY, 0) < 0){
printk("winch_thread : TIOCSCTTY failed, errno = %d\n", errno);
exit(1);
}
if(tcsetpgrp(pty_fd, os_getpid()) < 0){
printk("winch_thread : tcsetpgrp failed, errno = %d\n", errno);
err = os_new_tty_pgrp(pty_fd, os_getpid());
if(err < 0){
printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err);
exit(1);
}
if(read(pipe_fd, &c, sizeof(c)) != sizeof(c))
count = os_read_file(pipe_fd, &c, sizeof(c));
if(count != sizeof(c))
printk("winch_thread : failed to read synchronization byte, "
"errno = %d\n", errno);
"err = %d\n", -count);
while(1){
pause();
if(write(pipe_fd, &c, sizeof(c)) != sizeof(c)){
printk("winch_thread : write failed, errno = %d\n",
errno);
}
count = os_write_file(pipe_fd, &c, sizeof(c));
if(count != sizeof(c))
printk("winch_thread : write failed, err = %d\n",
-count);
}
}
......@@ -154,8 +154,8 @@ static int winch_tramp(int fd, void *device_data, int *fd_out)
char c;
err = os_pipe(fds, 1, 1);
if(err){
printk("winch_tramp : os_pipe failed, errno = %d\n", -err);
if(err < 0){
printk("winch_tramp : os_pipe failed, err = %d\n", -err);
return(err);
}
......@@ -168,12 +168,12 @@ static int winch_tramp(int fd, void *device_data, int *fd_out)
return(pid);
}
close(fds[1]);
os_close_file(fds[1]);
*fd_out = fds[0];
n = read(fds[0], &c, sizeof(c));
n = os_read_file(fds[0], &c, sizeof(c));
if(n != sizeof(c)){
printk("winch_tramp : failed to read synchronization byte\n");
printk("read returned %d, errno = %d\n", n, errno);
printk("read failed, err = %d\n", -n);
printk("fd %d will not support SIGWINCH\n", fd);
*fd_out = -1;
}
......@@ -183,20 +183,24 @@ static int winch_tramp(int fd, void *device_data, int *fd_out)
void register_winch(int fd, void *device_data)
{
int pid, thread, thread_fd;
int count;
char c = 1;
if(!isatty(fd)) return;
if(!isatty(fd))
return;
pid = tcgetpgrp(fd);
if(!CHOOSE_MODE(is_tracer_winch(pid, fd, device_data), 0) &&
(pid == -1)){
if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
device_data) && (pid == -1)){
thread = winch_tramp(fd, device_data, &thread_fd);
if(fd != -1){
register_winch_irq(thread_fd, fd, thread, device_data);
if(write(thread_fd, &c, sizeof(c)) != sizeof(c))
count = os_write_file(thread_fd, &c, sizeof(c));
if(count != sizeof(c))
printk("register_winch : failed to write "
"synchronization byte\n");
"synchronization byte, err = %d\n",
-count);
}
}
}
......
#ifndef __COW_H__
#define __COW_H__
#include <asm/types.h>
#if __BYTE_ORDER == __BIG_ENDIAN
# define ntohll(x) (x)
# define htonll(x) (x)
#elif __BYTE_ORDER == __LITTLE_ENDIAN
# define ntohll(x) bswap_64(x)
# define htonll(x) bswap_64(x)
#else
#error "__BYTE_ORDER not defined"
#endif
extern int init_cow_file(int fd, char *cow_file, char *backing_file,
int sectorsize, int alignment, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out);
extern int file_reader(__u64 offset, char *buf, int len, void *arg);
extern int read_cow_header(int (*reader)(__u64, char *, int, void *),
void *arg, __u32 *version_out,
char **backing_file_out, time_t *mtime_out,
__u64 *size_out, int *sectorsize_out,
__u32 *align_out, int *bitmap_offset_out);
extern int write_cow_header(char *cow_file, int fd, char *backing_file,
int sectorsize, int alignment, long long *size);
extern void cow_sizes(int version, __u64 size, int sectorsize, int align,
int bitmap_offset, unsigned long *bitmap_len_out,
int *data_offset_out);
#endif
/*
* ---------------------------------------------------------------------------
* Local variables:
* c-file-style: "linux"
* End:
*/
This diff is collapsed.
#ifndef __COW_SYS_H__
#define __COW_SYS_H__
#include "kern_util.h"
#include "user_util.h"
#include "os.h"
#include "user.h"
static inline void *cow_malloc(int size)
{
return(um_kmalloc(size));
}
static inline void cow_free(void *ptr)
{
kfree(ptr);
}
#define cow_printf printk
static inline char *cow_strdup(char *str)
{
return(uml_strdup(str));
}
static inline int cow_seek_file(int fd, __u64 offset)
{
return(os_seek_file(fd, offset));
}
static inline int cow_file_size(char *file, __u64 *size_out)
{
return(os_file_size(file, size_out));
}
static inline int cow_write_file(int fd, char *buf, int size)
{
return(os_write_file(fd, buf, size));
}
#endif
/*
* ---------------------------------------------------------------------------
* Local variables:
* c-file-style: "linux"
* End:
*/
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <byteswap.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/user.h>
#include <netinet/in.h>
#include "os.h"
#include "cow.h"
#include "cow_sys.h"
#define PATH_LEN_V1 256
struct cow_header_v1 {
int magic;
int version;
char backing_file[PATH_LEN_V1];
time_t mtime;
__u64 size;
int sectorsize;
};
#define PATH_LEN_V2 MAXPATHLEN
struct cow_header_v2 {
unsigned long magic;
unsigned long version;
char backing_file[PATH_LEN_V2];
time_t mtime;
__u64 size;
int sectorsize;
};
/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in
* case other systems have different values for MAXPATHLEN
*/
#define PATH_LEN_V3 4096
/* Changes from V2 -
* PATH_LEN_V3 as described above
* Explicitly specify field bit lengths for systems with different
* lengths for the usual C types. Not sure whether char or
* time_t should be changed, this can be changed later without
* breaking compatibility
* Add alignment field so that different alignments can be used for the
* bitmap and data
* Add cow_format field to allow for the possibility of different ways
* of specifying the COW blocks. For now, the only value is 0,
* for the traditional COW bitmap.
* Move the backing_file field to the end of the header. This allows
* for the possibility of expanding it into the padding required
* by the bitmap alignment.
* The bitmap and data portions of the file will be aligned as specified
* by the alignment field. This is to allow COW files to be
* put on devices with restrictions on access alignments, such as
* /dev/raw, with a 512 byte alignment restriction. This also
* allows the data to be more aligned more strictly than on
* sector boundaries. This is needed for ubd-mmap, which needs
* the data to be page aligned.
* Fixed (finally!) the rounding bug
*/
struct cow_header_v3 {
__u32 magic;
__u32 version;
time_t mtime;
__u64 size;
__u32 sectorsize;
__u32 alignment;
__u32 cow_format;
char backing_file[PATH_LEN_V3];
};
/* COW format definitions - for now, we have only the usual COW bitmap */
#define COW_BITMAP 0
union cow_header {
struct cow_header_v1 v1;
struct cow_header_v2 v2;
struct cow_header_v3 v3;
};
#define COW_MAGIC 0x4f4f4f4d /* MOOO */
#define COW_VERSION 3
#define DIV_ROUND(x, len) (((x) + (len) - 1) / (len))
#define ROUND_UP(x, align) DIV_ROUND(x, align) * (align)
void cow_sizes(int version, __u64 size, int sectorsize, int align,
int bitmap_offset, unsigned long *bitmap_len_out,
int *data_offset_out)
{
if(version < 3){
*bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
*data_offset_out = bitmap_offset + *bitmap_len_out;
*data_offset_out = (*data_offset_out + sectorsize - 1) /
sectorsize;
*data_offset_out *= sectorsize;
}
else {
*bitmap_len_out = DIV_ROUND(size, sectorsize);
*bitmap_len_out = DIV_ROUND(*bitmap_len_out, 8);
*data_offset_out = bitmap_offset + *bitmap_len_out;
*data_offset_out = ROUND_UP(*data_offset_out, align);
}
}
static int absolutize(char *to, int size, char *from)
{
char save_cwd[256], *slash;
int remaining;
if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
cow_printf("absolutize : unable to get cwd - errno = %d\n",
errno);
return(-1);
}
slash = strrchr(from, '/');
if(slash != NULL){
*slash = '\0';
if(chdir(from)){
*slash = '/';
cow_printf("absolutize : Can't cd to '%s' - "
"errno = %d\n", from, errno);
return(-1);
}
*slash = '/';
if(getcwd(to, size) == NULL){
cow_printf("absolutize : unable to get cwd of '%s' - "
"errno = %d\n", from, errno);
return(-1);
}
remaining = size - strlen(to);
if(strlen(slash) + 1 > remaining){
cow_printf("absolutize : unable to fit '%s' into %d "
"chars\n", from, size);
return(-1);
}
strcat(to, slash);
}
else {
if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
cow_printf("absolutize : unable to fit '%s' into %d "
"chars\n", from, size);
return(-1);
}
strcpy(to, save_cwd);
strcat(to, "/");
strcat(to, from);
}
chdir(save_cwd);
return(0);
}
int write_cow_header(char *cow_file, int fd, char *backing_file,
int sectorsize, int alignment, long long *size)
{
struct cow_header_v3 *header;
unsigned long modtime;
int err;
err = cow_seek_file(fd, 0);
if(err < 0){
cow_printf("write_cow_header - lseek failed, err = %d\n", -err);
goto out;
}
err = -ENOMEM;
header = cow_malloc(sizeof(*header));
if(header == NULL){
cow_printf("Failed to allocate COW V3 header\n");
goto out;
}
header->magic = htonl(COW_MAGIC);
header->version = htonl(COW_VERSION);
err = -EINVAL;
if(strlen(backing_file) > sizeof(header->backing_file) - 1){
cow_printf("Backing file name \"%s\" is too long - names are "
"limited to %d characters\n", backing_file,
sizeof(header->backing_file) - 1);
goto out_free;
}
if(absolutize(header->backing_file, sizeof(header->backing_file),
backing_file))
goto out_free;
err = os_file_modtime(header->backing_file, &modtime);
if(err < 0){
cow_printf("Backing file '%s' mtime request failed, "
"err = %d\n", header->backing_file, -err);
goto out_free;
}
err = cow_file_size(header->backing_file, size);
if(err < 0){
cow_printf("Couldn't get size of backing file '%s', "
"err = %d\n", header->backing_file, -err);
goto out_free;
}
header->mtime = htonl(modtime);
header->size = htonll(*size);
header->sectorsize = htonl(sectorsize);
header->alignment = htonl(alignment);
header->cow_format = COW_BITMAP;
err = os_write_file(fd, header, sizeof(*header));
if(err != sizeof(*header)){
cow_printf("Write of header to new COW file '%s' failed, "
"err = %d\n", cow_file, -err);
goto out_free;
}
err = 0;
out_free:
cow_free(header);
out:
return(err);
}
int file_reader(__u64 offset, char *buf, int len, void *arg)
{
int fd = *((int *) arg);
return(pread(fd, buf, len, offset));
}
/* XXX Need to sanity-check the values read from the header */
int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg,
__u32 *version_out, char **backing_file_out,
time_t *mtime_out, __u64 *size_out,
int *sectorsize_out, __u32 *align_out,
int *bitmap_offset_out)
{
union cow_header *header;
char *file;
int err, n;
unsigned long version, magic;
header = cow_malloc(sizeof(*header));
if(header == NULL){
cow_printf("read_cow_header - Failed to allocate header\n");
return(-ENOMEM);
}
err = -EINVAL;
n = (*reader)(0, (char *) header, sizeof(*header), arg);
if(n < offsetof(typeof(header->v1), backing_file)){
cow_printf("read_cow_header - short header\n");
goto out;
}
magic = header->v1.magic;
if(magic == COW_MAGIC) {
version = header->v1.version;
}
else if(magic == ntohl(COW_MAGIC)){
version = ntohl(header->v1.version);
}
/* No error printed because the non-COW case comes through here */
else goto out;
*version_out = version;
if(version == 1){
if(n < sizeof(header->v1)){
cow_printf("read_cow_header - failed to read V1 "
"header\n");
goto out;
}
*mtime_out = header->v1.mtime;
*size_out = header->v1.size;
*sectorsize_out = header->v1.sectorsize;
*bitmap_offset_out = sizeof(header->v1);
*align_out = *sectorsize_out;
file = header->v1.backing_file;
}
else if(version == 2){
if(n < sizeof(header->v2)){
cow_printf("read_cow_header - failed to read V2 "
"header\n");
goto out;
}
*mtime_out = ntohl(header->v2.mtime);
*size_out = ntohll(header->v2.size);
*sectorsize_out = ntohl(header->v2.sectorsize);
*bitmap_offset_out = sizeof(header->v2);
*align_out = *sectorsize_out;
file = header->v2.backing_file;
}
else if(version == 3){
if(n < sizeof(header->v3)){
cow_printf("read_cow_header - failed to read V2 "
"header\n");
goto out;
}
*mtime_out = ntohl(header->v3.mtime);
*size_out = ntohll(header->v3.size);
*sectorsize_out = ntohl(header->v3.sectorsize);
*align_out = ntohl(header->v3.alignment);
*bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out);
file = header->v3.backing_file;
}
else {
cow_printf("read_cow_header - invalid COW version\n");
goto out;
}
err = -ENOMEM;
*backing_file_out = cow_strdup(file);
if(*backing_file_out == NULL){
cow_printf("read_cow_header - failed to allocate backing "
"file\n");
goto out;
}
err = 0;
out:
cow_free(header);
return(err);
}
int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize,
int alignment, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out)
{
__u64 size, offset;
char zero = 0;
int err;
err = write_cow_header(cow_file, fd, backing_file, sectorsize,
alignment, &size);
if(err)
goto out;
*bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment);
cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out,
bitmap_len_out, data_offset_out);
offset = *data_offset_out + size - sizeof(zero);
err = cow_seek_file(fd, offset);
if(err < 0){
cow_printf("cow bitmap lseek failed : err = %d\n", -err);
goto out;
}
/* does not really matter how much we write it is just to set EOF
* this also sets the entire COW bitmap
* to zero without having to allocate it
*/
err = cow_write_file(fd, &zero, sizeof(zero));
if(err != sizeof(zero)){
cow_printf("Write of bitmap to new COW file '%s' failed, "
"err = %d\n", cow_file, -err);
err = -EINVAL;
goto out;
}
return(0);
out:
return(err);
}
/*
* ---------------------------------------------------------------------------
* Local variables:
* c-file-style: "linux"
* End:
*/
......@@ -53,7 +53,8 @@ static int connect_to_switch(struct daemon_data *pri)
struct request_v3 req;
int fd, n, err;
if((pri->control = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
pri->control = socket(AF_UNIX, SOCK_STREAM, 0);
if(pri->control < 0){
printk("daemon_open : control socket failed, errno = %d\n",
errno);
return(-errno);
......@@ -67,7 +68,8 @@ static int connect_to_switch(struct daemon_data *pri)
goto out;
}
if((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0){
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if(fd < 0){
printk("daemon_open : data socket failed, errno = %d\n",
errno);
err = -errno;
......@@ -91,18 +93,18 @@ static int connect_to_switch(struct daemon_data *pri)
req.version = SWITCH_VERSION;
req.type = REQ_NEW_CONTROL;
req.sock = *local_addr;
n = write(pri->control, &req, sizeof(req));
n = os_write_file(pri->control, &req, sizeof(req));
if(n != sizeof(req)){
printk("daemon_open : control setup request returned %d, "
"errno = %d\n", n, errno);
printk("daemon_open : control setup request failed, err = %d\n",
-n);
err = -ENOTCONN;
goto out;
}
n = read(pri->control, sun, sizeof(*sun));
n = os_read_file(pri->control, sun, sizeof(*sun));
if(n != sizeof(*sun)){
printk("daemon_open : read of data socket returned %d, "
"errno = %d\n", n, errno);
printk("daemon_open : read of data socket failed, err = %d\n",
-n);
err = -ENOTCONN;
goto out_close;
}
......@@ -111,9 +113,9 @@ static int connect_to_switch(struct daemon_data *pri)
return(fd);
out_close:
close(fd);
os_close_file(fd);
out:
close(pri->control);
os_close_file(pri->control);
return(err);
}
......@@ -153,8 +155,8 @@ static void daemon_remove(void *data)
{
struct daemon_data *pri = data;
close(pri->fd);
close(pri->control);
os_close_file(pri->fd);
os_close_file(pri->control);
if(pri->data_addr != NULL) kfree(pri->data_addr);
if(pri->ctl_addr != NULL) kfree(pri->ctl_addr);
if(pri->local_addr != NULL) kfree(pri->local_addr);
......
......@@ -35,7 +35,8 @@ void *fd_init(char *str, int device, struct chan_opts *opts)
printk("fd_init : couldn't parse file descriptor '%s'\n", str);
return(NULL);
}
if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
data = um_kmalloc(sizeof(*data));
if(data == NULL) return(NULL);
*data = ((struct fd_chan) { .fd = n,
.raw = opts->raw });
return(data);
......
......@@ -27,10 +27,10 @@ static void pre_exec(void *d)
dup2(data->stdin, 0);
dup2(data->stdout, 1);
dup2(data->stdout, 2);
close(data->stdin);
close(data->stdout);
close(data->close_me[0]);
close(data->close_me[1]);
os_close_file(data->stdin);
os_close_file(data->stdout);
os_close_file(data->close_me[0]);
os_close_file(data->close_me[1]);
}
int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
......@@ -44,15 +44,15 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
char **args = NULL;
err = os_pipe(in_fds, 1, 0);
if(err){
printk("harddog_open - os_pipe failed, errno = %d\n", -err);
return(err);
if(err < 0){
printk("harddog_open - os_pipe failed, err = %d\n", -err);
goto out;
}
err = os_pipe(out_fds, 1, 0);
if(err){
printk("harddog_open - os_pipe failed, errno = %d\n", -err);
return(err);
if(err < 0){
printk("harddog_open - os_pipe failed, err = %d\n", -err);
goto out_close_in;
}
data.stdin = out_fds[0];
......@@ -72,42 +72,47 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
pid = run_helper(pre_exec, &data, args, NULL);
close(out_fds[0]);
close(in_fds[1]);
os_close_file(out_fds[0]);
os_close_file(in_fds[1]);
if(pid < 0){
err = -pid;
printk("harddog_open - run_helper failed, errno = %d\n", err);
goto out;
printk("harddog_open - run_helper failed, errno = %d\n", -err);
goto out_close_out;
}
n = read(in_fds[0], &c, sizeof(c));
n = os_read_file(in_fds[0], &c, sizeof(c));
if(n == 0){
printk("harddog_open - EOF on watchdog pipe\n");
helper_wait(pid);
err = -EIO;
goto out;
goto out_close_out;
}
else if(n < 0){
printk("harddog_open - read of watchdog pipe failed, "
"errno = %d\n", errno);
"err = %d\n", -n);
helper_wait(pid);
err = -errno;
goto out;
err = n;
goto out_close_out;
}
*in_fd_ret = in_fds[0];
*out_fd_ret = out_fds[1];
return(0);
out_close_in:
os_close_file(in_fds[0]);
os_close_file(in_fds[1]);
out_close_out:
os_close_file(out_fds[0]);
os_close_file(out_fds[1]);
out:
close(out_fds[1]);
close(in_fds[0]);
return(err);
}
void stop_watchdog(int in_fd, int out_fd)
{
close(in_fd);
close(out_fd);
os_close_file(in_fd);
os_close_file(out_fd);
}
int ping_watchdog(int fd)
......@@ -115,11 +120,12 @@ int ping_watchdog(int fd)
int n;
char c = '\n';
n = write(fd, &c, sizeof(c));
if(n < sizeof(c)){
printk("ping_watchdog - write failed, errno = %d\n",
errno);
return(-errno);
n = os_write_file(fd, &c, sizeof(c));
if(n != sizeof(c)){
printk("ping_watchdog - write failed, err = %d\n", -n);
if(n < 0)
return(n);
return(-EIO);
}
return 1;
......
......@@ -5,12 +5,12 @@
#include "linux/config.h"
#include "linux/module.h"
#include "linux/version.h"
#include "linux/init.h"
#include "linux/slab.h"
#include "linux/fs.h"
#include "linux/sound.h"
#include "linux/soundcard.h"
#include "asm/uaccess.h"
#include "kern_util.h"
#include "init.h"
#include "hostaudio.h"
......@@ -19,30 +19,39 @@
char *dsp = HOSTAUDIO_DEV_DSP;
char *mixer = HOSTAUDIO_DEV_MIXER;
#define DSP_HELP \
" This is used to specify the host dsp device to the hostaudio driver.\n" \
" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
#define MIXER_HELP \
" This is used to specify the host mixer device to the hostaudio driver.\n" \
" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
#ifndef MODULE
static int set_dsp(char *name, int *add)
{
dsp = uml_strdup(name);
dsp = name;
return(0);
}
__uml_setup("dsp=", set_dsp,
"dsp=<dsp device>\n"
" This is used to specify the host dsp device to the hostaudio driver.\n"
" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
);
__uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
static int set_mixer(char *name, int *add)
{
mixer = uml_strdup(name);
mixer = name;
return(0);
}
__uml_setup("mixer=", set_mixer,
"mixer=<mixer device>\n"
" This is used to specify the host mixer device to the hostaudio driver.\n"
" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
);
__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
#else /*MODULE*/
MODULE_PARM(dsp, "s");
MODULE_PARM_DESC(dsp, DSP_HELP);
MODULE_PARM(mixer, "s");
MODULE_PARM_DESC(mixer, MIXER_HELP);
#endif
/* /dev/dsp file operations */
......@@ -51,23 +60,55 @@ static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count,
loff_t *ppos)
{
struct hostaudio_state *state = file->private_data;
void *kbuf;
int err;
#ifdef DEBUG
printk("hostaudio: read called, count = %d\n", count);
#endif
return(hostaudio_read_user(state, buffer, count, ppos));
kbuf = kmalloc(count, GFP_KERNEL);
if(kbuf == NULL)
return(-ENOMEM);
err = hostaudio_read_user(state, kbuf, count, ppos);
if(err < 0)
goto out;
if(copy_to_user(buffer, kbuf, err))
err = -EFAULT;
out:
kfree(kbuf);
return(err);
}
static ssize_t hostaudio_write(struct file *file, const char *buffer,
size_t count, loff_t *ppos)
{
struct hostaudio_state *state = file->private_data;
void *kbuf;
int err;
#ifdef DEBUG
printk("hostaudio: write called, count = %d\n", count);
#endif
return(hostaudio_write_user(state, buffer, count, ppos));
kbuf = kmalloc(count, GFP_KERNEL);
if(kbuf == NULL)
return(-ENOMEM);
err = -EFAULT;
if(copy_from_user(kbuf, buffer, count))
goto out;
err = hostaudio_write_user(state, kbuf, count, ppos);
if(err < 0)
goto out;
out:
kfree(kbuf);
return(err);
}
static unsigned int hostaudio_poll(struct file *file,
......@@ -86,12 +127,43 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct hostaudio_state *state = file->private_data;
unsigned long data = 0;
int err;
#ifdef DEBUG
printk("hostaudio: ioctl called, cmd = %u\n", cmd);
#endif
return(hostaudio_ioctl_user(state, cmd, arg));
switch(cmd){
case SNDCTL_DSP_SPEED:
case SNDCTL_DSP_STEREO:
case SNDCTL_DSP_GETBLKSIZE:
case SNDCTL_DSP_CHANNELS:
case SNDCTL_DSP_SUBDIVIDE:
case SNDCTL_DSP_SETFRAGMENT:
if(get_user(data, (int *) arg))
return(-EFAULT);
break;
default:
break;
}
err = hostaudio_ioctl_user(state, cmd, (unsigned long) &data);
switch(cmd){
case SNDCTL_DSP_SPEED:
case SNDCTL_DSP_STEREO:
case SNDCTL_DSP_GETBLKSIZE:
case SNDCTL_DSP_CHANNELS:
case SNDCTL_DSP_SUBDIVIDE:
case SNDCTL_DSP_SETFRAGMENT:
if(put_user(data, (int *) arg))
return(-EFAULT);
break;
default:
break;
}
return(err);
}
static int hostaudio_open(struct inode *inode, struct file *file)
......@@ -225,7 +297,8 @@ MODULE_LICENSE("GPL");
static int __init hostaudio_init_module(void)
{
printk(KERN_INFO "UML Audio Relay\n");
printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
dsp, mixer);
module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
if(module_data.dev_audio < 0){
......
......@@ -4,9 +4,6 @@
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "hostaudio.h"
......@@ -20,45 +17,31 @@
ssize_t hostaudio_read_user(struct hostaudio_state *state, char *buffer,
size_t count, loff_t *ppos)
{
ssize_t ret;
#ifdef DEBUG
printk("hostaudio: read_user called, count = %d\n", count);
#endif
ret = read(state->fd, buffer, count);
if(ret < 0) return(-errno);
return(ret);
return(os_read_file(state->fd, buffer, count));
}
ssize_t hostaudio_write_user(struct hostaudio_state *state, const char *buffer,
size_t count, loff_t *ppos)
{
ssize_t ret;
#ifdef DEBUG
printk("hostaudio: write_user called, count = %d\n", count);
#endif
ret = write(state->fd, buffer, count);
if(ret < 0) return(-errno);
return(ret);
return(os_write_file(state->fd, buffer, count));
}
int hostaudio_ioctl_user(struct hostaudio_state *state, unsigned int cmd,
unsigned long arg)
{
int ret;
#ifdef DEBUG
printk("hostaudio: ioctl_user called, cmd = %u\n", cmd);
#endif
ret = ioctl(state->fd, cmd, arg);
if(ret < 0) return(-errno);
return(ret);
return(os_ioctl_generic(state->fd, cmd, arg));
}
int hostaudio_open_user(struct hostaudio_state *state, int r, int w, char *dsp)
......@@ -67,14 +50,15 @@ int hostaudio_open_user(struct hostaudio_state *state, int r, int w, char *dsp)
printk("hostaudio: open_user called\n");
#endif
state->fd = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
if(state->fd >= 0) return(0);
state->fd = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
printk("hostaudio_open_user failed to open '%s', errno = %d\n",
dsp, errno);
if(state->fd < 0) {
printk("hostaudio_open_user failed to open '%s', err = %d\n",
dsp, -state->fd);
return(state->fd);
}
return(-errno);
return(0);
}
int hostaudio_release_user(struct hostaudio_state *state)
......@@ -82,10 +66,10 @@ int hostaudio_release_user(struct hostaudio_state *state)
#ifdef DEBUG
printk("hostaudio: release called\n");
#endif
if(state->fd >= 0){
close(state->fd);
state->fd=-1;
}
if(state->fd >= 0){
os_close_file(state->fd);
state->fd = -1;
}
return(0);
}
......@@ -95,15 +79,11 @@ int hostaudio_release_user(struct hostaudio_state *state)
int hostmixer_ioctl_mixdev_user(struct hostmixer_state *state,
unsigned int cmd, unsigned long arg)
{
int ret;
#ifdef DEBUG
printk("hostmixer: ioctl_user called cmd = %u\n",cmd);
#endif
ret = ioctl(state->fd, cmd, arg);
if(ret < 0)
return(-errno);
return(ret);
return(os_ioctl_generic(state->fd, cmd, arg));
}
int hostmixer_open_mixdev_user(struct hostmixer_state *state, int r, int w,
......@@ -115,12 +95,13 @@ int hostmixer_open_mixdev_user(struct hostmixer_state *state, int r, int w,
state->fd = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
if(state->fd >= 0) return(0);
printk("hostaudio_open_mixdev_user failed to open '%s', errno = %d\n",
mixer, errno);
if(state->fd < 0) {
printk("hostaudio_open_mixdev_user failed to open '%s', "
"err = %d\n", mixer, state->fd);
return(state->fd);
}
return(-errno);
return(0);
}
int hostmixer_release_mixdev_user(struct hostmixer_state *state)
......@@ -130,7 +111,7 @@ int hostmixer_release_mixdev_user(struct hostmixer_state *state)
#endif
if(state->fd >= 0){
close(state->fd);
os_close_file(state->fd);
state->fd = -1;
}
......
......@@ -6,8 +6,8 @@
#include "linux/sched.h"
#include "linux/slab.h"
#include "linux/list.h"
#include "linux/interrupt.h"
#include "linux/devfs_fs_kernel.h"
#include "asm/irq.h"
#include "asm/uaccess.h"
#include "chan_kern.h"
#include "irq_user.h"
......@@ -16,38 +16,55 @@
#include "user_util.h"
#include "kern_util.h"
#include "os.h"
#include "irq_kern.h"
#define LINE_BUFSIZE 4096
void line_interrupt(int irq, void *data, struct pt_regs *unused)
static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
{
struct line *dev = data;
if(dev->count > 0)
chan_interrupt(&dev->chan_list, &dev->task, dev->tty, irq,
dev);
return IRQ_HANDLED;
}
void line_timer_cb(void *arg)
static void line_timer_cb(void *arg)
{
struct line *dev = arg;
line_interrupt(dev->driver->read_irq, dev, NULL);
}
static void buffer_data(struct line *line, const char *buf, int len)
static int write_room(struct line *dev)
{
int end;
int n;
if(dev->buffer == NULL) return(LINE_BUFSIZE - 1);
n = dev->head - dev->tail;
if(n <= 0) n = LINE_BUFSIZE + n;
return(n - 1);
}
static int buffer_data(struct line *line, const char *buf, int len)
{
int end, room;
if(line->buffer == NULL){
line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC);
if(line->buffer == NULL){
printk("buffer_data - atomic allocation failed\n");
return;
return(0);
}
line->head = line->buffer;
line->tail = line->buffer;
}
room = write_room(line);
len = (len > room) ? room : len;
end = line->buffer + LINE_BUFSIZE - line->tail;
if(len < end){
memcpy(line->tail, buf, len);
......@@ -60,6 +77,8 @@ static void buffer_data(struct line *line, const char *buf, int len)
memcpy(line->buffer, buf, len);
line->tail = line->buffer + len;
}
return(len);
}
static int flush_buffer(struct line *line)
......@@ -95,7 +114,7 @@ int line_write(struct line *lines, struct tty_struct *tty, int from_user,
struct line *line;
char *new;
unsigned long flags;
int n, err, i;
int n, err, i, ret = 0;
if(tty->stopped) return 0;
......@@ -104,9 +123,13 @@ int line_write(struct line *lines, struct tty_struct *tty, int from_user,
if(new == NULL)
return(0);
n = copy_from_user(new, buf, len);
if(n == len)
return(-EFAULT);
buf = new;
if(n == len){
len = -EFAULT;
goto out_free;
}
len -= n;
}
i = tty->index;
......@@ -115,41 +138,50 @@ int line_write(struct line *lines, struct tty_struct *tty, int from_user,
down(&line->sem);
if(line->head != line->tail){
local_irq_save(flags);
buffer_data(line, buf, len);
ret += buffer_data(line, buf, len);
err = flush_buffer(line);
local_irq_restore(flags);
if(err <= 0)
goto out;
goto out_up;
}
else {
n = write_chan(&line->chan_list, buf, len,
line->driver->write_irq);
if(n < 0){
len = n;
goto out;
ret = n;
goto out_up;
}
if(n < len)
buffer_data(line, buf + n, len - n);
len -= n;
ret += n;
if(len > 0)
ret += buffer_data(line, buf + n, len);
}
out:
out_up:
up(&line->sem);
return(len);
out_free:
if(from_user)
kfree(buf);
return(ret);
}
void line_write_interrupt(int irq, void *data, struct pt_regs *unused)
static irqreturn_t line_write_interrupt(int irq, void *data,
struct pt_regs *unused)
{
struct line *dev = data;
struct tty_struct *tty = dev->tty;
int err;
err = flush_buffer(dev);
if(err == 0) return;
if(err == 0)
return(IRQ_NONE);
else if(err < 0){
dev->head = dev->buffer;
dev->tail = dev->buffer;
}
if(tty == NULL) return;
if(tty == NULL)
return(IRQ_NONE);
if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
(tty->ldisc.write_wakeup != NULL))
......@@ -161,21 +193,9 @@ void line_write_interrupt(int irq, void *data, struct pt_regs *unused)
* writes.
*/
if (waitqueue_active(&tty->write_wait))
if(waitqueue_active(&tty->write_wait))
wake_up_interruptible(&tty->write_wait);
}
int line_write_room(struct tty_struct *tty)
{
struct line *dev = tty->driver_data;
int n;
if(dev->buffer == NULL) return(LINE_BUFSIZE - 1);
n = dev->head - dev->tail;
if(n <= 0) n = LINE_BUFSIZE + n;
return(n - 1);
return(IRQ_HANDLED);
}
int line_setup_irq(int fd, int input, int output, void *data)
......@@ -305,7 +325,7 @@ int line_setup(struct line *lines, int num, char *init, int all_allowed)
if(*end != '='){
printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
init);
return(1);
return(0);
}
init = end;
}
......@@ -313,12 +333,12 @@ int line_setup(struct line *lines, int num, char *init, int all_allowed)
if((n >= 0) && (n >= num)){
printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
n, num);
return(1);
return(0);
}
else if(n >= 0){
if(lines[n].count > 0){
printk("line_setup - device %d is open\n", n);
return(1);
return(0);
}
if(lines[n].init_pri <= INIT_ONE){
lines[n].init_pri = INIT_ONE;
......@@ -332,7 +352,7 @@ int line_setup(struct line *lines, int num, char *init, int all_allowed)
else if(!all_allowed){
printk("line_setup - can't configure all devices from "
"mconsole\n");
return(1);
return(0);
}
else {
for(i = 0; i < num; i++){
......@@ -346,7 +366,7 @@ int line_setup(struct line *lines, int num, char *init, int all_allowed)
}
}
}
return(0);
return(1);
}
int line_config(struct line *lines, int num, char *str)
......@@ -357,7 +377,7 @@ int line_config(struct line *lines, int num, char *str)
printk("line_config - uml_strdup failed\n");
return(-ENOMEM);
}
return(line_setup(lines, num, new, 0));
return(!line_setup(lines, num, new, 0));
}
int line_get_config(char *name, struct line *lines, int num, char *str,
......@@ -369,7 +389,7 @@ int line_get_config(char *name, struct line *lines, int num, char *str,
dev = simple_strtoul(name, &end, 0);
if((*end != '\0') || (end == name)){
*error_out = "line_setup failed to parse device number";
*error_out = "line_get_config failed to parse device number";
return(0);
}
......@@ -379,15 +399,15 @@ int line_get_config(char *name, struct line *lines, int num, char *str,
}
line = &lines[dev];
down(&line->sem);
if(!line->valid)
CONFIG_CHUNK(str, size, n, "none", 1);
else if(line->count == 0)
CONFIG_CHUNK(str, size, n, line->init_str, 1);
else n = chan_config_string(&line->chan_list, str, size, error_out);
up(&line->sem);
return(n);
}
......@@ -396,7 +416,14 @@ int line_remove(struct line *lines, int num, char *str)
char config[sizeof("conxxxx=none\0")];
sprintf(config, "%s=none", str);
return(line_setup(lines, num, config, 0));
return(!line_setup(lines, num, config, 0));
}
int line_write_room(struct tty_struct *tty)
{
struct line *dev = tty->driver_data;
return(write_room(dev));
}
struct tty_driver *line_register_devfs(struct lines *set,
......@@ -412,7 +439,8 @@ struct tty_driver *line_register_devfs(struct lines *set,
return NULL;
driver->driver_name = line_driver->name;
driver->name = line_driver->devfs_name;
driver->name = line_driver->device_name;
driver->devfs_name = line_driver->devfs_name;
driver->major = line_driver->major;
driver->minor_start = line_driver->minor_start;
driver->type = line_driver->type;
......@@ -432,7 +460,7 @@ struct tty_driver *line_register_devfs(struct lines *set,
for(i = 0; i < nlines; i++){
if(!lines[i].valid)
tty_unregister_devfs(driver, i);
tty_unregister_device(driver, i);
}
mconsole_register_dev(&line_driver->mc);
......@@ -465,24 +493,25 @@ struct winch {
struct line *line;
};
void winch_interrupt(int irq, void *data, struct pt_regs *unused)
irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
{
struct winch *winch = data;
struct tty_struct *tty;
int err;
char c;
err = generic_read(winch->fd, &c, NULL);
if(err < 0){
if(err != -EAGAIN){
printk("winch_interrupt : read failed, errno = %d\n",
-err);
printk("fd %d is losing SIGWINCH support\n",
winch->tty_fd);
free_irq(irq, data);
return;
if(winch->fd != -1){
err = generic_read(winch->fd, &c, NULL);
if(err < 0){
if(err != -EAGAIN){
printk("winch_interrupt : read failed, "
"errno = %d\n", -err);
printk("fd %d is losing SIGWINCH support\n",
winch->tty_fd);
return(IRQ_HANDLED);
}
goto out;
}
goto out;
}
tty = winch->line->tty;
if(tty != NULL){
......@@ -492,7 +521,9 @@ void winch_interrupt(int irq, void *data, struct pt_regs *unused)
kill_pg(tty->pgrp, SIGWINCH, 1);
}
out:
reactivate_fd(winch->fd, WINCH_IRQ);
if(winch->fd != -1)
reactivate_fd(winch->fd, WINCH_IRQ);
return(IRQ_HANDLED);
}
DECLARE_MUTEX(winch_handler_sem);
......@@ -529,7 +560,10 @@ static void winch_cleanup(void)
list_for_each(ele, &winch_handlers){
winch = list_entry(ele, struct winch, list);
close(winch->fd);
if(winch->fd != -1){
deactivate_fd(winch->fd, WINCH_IRQ);
os_close_file(winch->fd);
}
if(winch->pid != -1)
os_kill_process(winch->pid, 1);
}
......
......@@ -23,6 +23,7 @@
#include "kern_util.h"
#include "user_util.h"
#include "user.h"
#include "os.h"
#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
......@@ -62,7 +63,8 @@ static int mcast_open(void *data)
goto out;
}
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0){
printk("mcast_open : data socket failed, errno = %d\n",
errno);
fd = -ENOMEM;
......@@ -72,7 +74,7 @@ static int mcast_open(void *data)
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
errno);
close(fd);
os_close_file(fd);
fd = -EINVAL;
goto out;
}
......@@ -82,7 +84,7 @@ static int mcast_open(void *data)
sizeof(pri->ttl)) < 0) {
printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
errno);
close(fd);
os_close_file(fd);
fd = -EINVAL;
goto out;
}
......@@ -91,7 +93,7 @@ static int mcast_open(void *data)
if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
errno);
close(fd);
os_close_file(fd);
fd = -EINVAL;
goto out;
}
......@@ -99,7 +101,7 @@ static int mcast_open(void *data)
/* bind socket to mcast address */
if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
printk("mcast_open : data bind failed, errno = %d\n", errno);
close(fd);
os_close_file(fd);
fd = -EINVAL;
goto out;
}
......@@ -115,7 +117,7 @@ static int mcast_open(void *data)
"interface on the host.\n");
printk("eth0 should be configured in order to use the "
"multicast transport.\n");
close(fd);
os_close_file(fd);
fd = -EINVAL;
}
......@@ -137,7 +139,7 @@ static void mcast_close(int fd, void *data)
errno);
}
close(fd);
os_close_file(fd);
}
int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
......
/*
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
* Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
......@@ -15,6 +15,9 @@
#include "linux/sysrq.h"
#include "linux/workqueue.h"
#include "linux/module.h"
#include "linux/file.h"
#include "linux/fs.h"
#include "linux/namei.h"
#include "linux/proc_fs.h"
#include "asm/irq.h"
#include "asm/uaccess.h"
......@@ -27,6 +30,7 @@
#include "init.h"
#include "os.h"
#include "umid.h"
#include "irq_kern.h"
static int do_unlink_socket(struct notifier_block *notifier,
unsigned long what, void *data)
......@@ -67,7 +71,7 @@ void mc_work_proc(void *unused)
DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
irqreturn_t mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int fd;
struct mconsole_entry *new;
......@@ -75,9 +79,10 @@ void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
fd = (int) dev_id;
while (mconsole_get_request(fd, &req)){
if(req.cmd->as_interrupt) (*req.cmd->handler)(&req);
if(req.cmd->context == MCONSOLE_INTR)
(*req.cmd->handler)(&req);
else {
new = kmalloc(sizeof(req), GFP_ATOMIC);
new = kmalloc(sizeof(*new), GFP_ATOMIC);
if(new == NULL)
mconsole_reply(&req, "Out of memory", 1, 0);
else {
......@@ -88,6 +93,7 @@ void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
if(!list_empty(&mc_requests)) schedule_work(&mconsole_work);
reactivate_fd(fd, MCONSOLE_IRQ);
return(IRQ_HANDLED);
}
void mconsole_version(struct mc_request *req)
......@@ -100,20 +106,109 @@ void mconsole_version(struct mc_request *req)
mconsole_reply(req, version, 0, 0);
}
void mconsole_log(struct mc_request *req)
{
int len;
char *ptr = req->request.data;
ptr += strlen("log ");
len = req->len - (ptr - req->request.data);
printk("%.*s", len, ptr);
mconsole_reply(req, "", 0, 0);
}
void mconsole_proc(struct mc_request *req)
{
struct nameidata nd;
struct file_system_type *proc;
struct super_block *super;
struct file *file;
int n, err;
char *ptr = req->request.data, *buf;
ptr += strlen("proc");
while(isspace(*ptr)) ptr++;
proc = get_fs_type("proc");
if(proc == NULL){
mconsole_reply(req, "procfs not registered", 1, 0);
goto out;
}
super = (*proc->get_sb)(proc, 0, NULL, NULL);
put_filesystem(proc);
if(super == NULL){
mconsole_reply(req, "Failed to get procfs superblock", 1, 0);
goto out;
}
up_write(&super->s_umount);
nd.dentry = super->s_root;
nd.mnt = NULL;
nd.flags = O_RDONLY + 1;
nd.last_type = LAST_ROOT;
err = link_path_walk(ptr, &nd);
if(err){
mconsole_reply(req, "Failed to look up file", 1, 0);
goto out_kill;
}
file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
if(IS_ERR(file)){
mconsole_reply(req, "Failed to open file", 1, 0);
goto out_kill;
}
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if(buf == NULL){
mconsole_reply(req, "Failed to allocate buffer", 1, 0);
goto out_fput;
}
if((file->f_op != NULL) && (file->f_op->read != NULL)){
do {
n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1,
&file->f_pos);
if(n >= 0){
buf[n] = '\0';
mconsole_reply(req, buf, 0, (n > 0));
}
else {
mconsole_reply(req, "Read of file failed",
1, 0);
goto out_free;
}
} while(n > 0);
}
else mconsole_reply(req, "", 0, 0);
out_free:
kfree(buf);
out_fput:
fput(file);
out_kill:
deactivate_super(super);
out: ;
}
#define UML_MCONSOLE_HELPTEXT \
"Commands:
version - Get kernel version
help - Print this message
halt - Halt UML
reboot - Reboot UML
config <dev>=<config> - Add a new device to UML;
same syntax as command line
config <dev> - Query the configuration of a device
remove <dev> - Remove a device from UML
sysrq <letter> - Performs the SysRq action controlled by the letter
cad - invoke the Ctl-Alt-Del handler
stop - pause the UML; it will do nothing until it receives a 'go'
go - continue the UML after a 'stop'
"Commands: \n\
version - Get kernel version \n\
help - Print this message \n\
halt - Halt UML \n\
reboot - Reboot UML \n\
config <dev>=<config> - Add a new device to UML; \n\
same syntax as command line \n\
config <dev> - Query the configuration of a device \n\
remove <dev> - Remove a device from UML \n\
sysrq <letter> - Performs the SysRq action controlled by the letter \n\
cad - invoke the Ctl-Alt-Del handler \n\
stop - pause the UML; it will do nothing until it receives a 'go' \n\
go - continue the UML after a 'stop' \n\
log <string> - make UML enter <string> into the kernel log\n\
proc <file> - returns the contents of the UML's /proc/<file>\n\
"
void mconsole_help(struct mc_request *req)
......@@ -302,7 +397,7 @@ int mconsole_init(void)
if(umid_file_name("mconsole", file, sizeof(file))) return(-1);
snprintf(mconsole_socket_name, sizeof(file), "%s", file);
sock = create_unix_socket(file, sizeof(file));
sock = os_create_unix_socket(file, sizeof(file), 1);
if (sock < 0){
printk("Failed to initialize management console\n");
return(1);
......@@ -344,11 +439,16 @@ static int write_proc_mconsole(struct file *file, const char *buffer,
if(buf == NULL)
return(-ENOMEM);
if(copy_from_user(buf, buffer, count))
return(-EFAULT);
if(copy_from_user(buf, buffer, count)){
count = -EFAULT;
goto out;
}
buf[count] = '\0';
mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count);
out:
kfree(buf);
return(count);
}
......
/*
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
* Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
* Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
......@@ -18,16 +18,18 @@
#include "umid.h"
static struct mconsole_command commands[] = {
{ "version", mconsole_version, 1 },
{ "halt", mconsole_halt, 0 },
{ "reboot", mconsole_reboot, 0 },
{ "config", mconsole_config, 0 },
{ "remove", mconsole_remove, 0 },
{ "sysrq", mconsole_sysrq, 1 },
{ "help", mconsole_help, 1 },
{ "cad", mconsole_cad, 1 },
{ "stop", mconsole_stop, 0 },
{ "go", mconsole_go, 1 },
{ "version", mconsole_version, MCONSOLE_INTR },
{ "halt", mconsole_halt, MCONSOLE_PROC },
{ "reboot", mconsole_reboot, MCONSOLE_PROC },
{ "config", mconsole_config, MCONSOLE_PROC },
{ "remove", mconsole_remove, MCONSOLE_PROC },
{ "sysrq", mconsole_sysrq, MCONSOLE_INTR },
{ "help", mconsole_help, MCONSOLE_INTR },
{ "cad", mconsole_cad, MCONSOLE_INTR },
{ "stop", mconsole_stop, MCONSOLE_PROC },
{ "go", mconsole_go, MCONSOLE_INTR },
{ "log", mconsole_log, MCONSOLE_INTR },
{ "proc", mconsole_proc, MCONSOLE_PROC },
};
/* Initialized in mconsole_init, which is an initcall */
......@@ -139,6 +141,7 @@ int mconsole_reply(struct mc_request *req, char *str, int err, int more)
memcpy(reply.data, str, len);
reply.data[len] = '\0';
total -= len;
str += len;
reply.len = len + 1;
len = sizeof(reply) + reply.len - sizeof(reply.data);
......
......@@ -120,7 +120,10 @@ static int __init mmapper_init(void)
printk(KERN_INFO "Mapper v0.1\n");
v_buf = (char *) find_iomem("mmapper", &mmapper_size);
if(mmapper_size == 0) return(0);
if(mmapper_size == 0){
printk(KERN_ERR "mmapper_init - find_iomem failed\n");
return(0);
}
p_buf = __pa(v_buf);
......
......@@ -26,6 +26,7 @@
#include "mconsole_kern.h"
#include "init.h"
#include "irq_user.h"
#include "irq_kern.h"
static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED;
LIST_HEAD(opened);
......@@ -37,7 +38,8 @@ static int uml_net_rx(struct net_device *dev)
struct sk_buff *skb;
/* If we can't allocate memory, try again next round. */
if ((skb = dev_alloc_skb(dev->mtu)) == NULL) {
skb = dev_alloc_skb(dev->mtu);
if (skb == NULL) {
lp->stats.rx_dropped++;
return 0;
}
......@@ -61,14 +63,14 @@ static int uml_net_rx(struct net_device *dev)
return pkt_len;
}
void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
struct uml_net_private *lp = dev->priv;
int err;
if(!netif_running(dev))
return;
return(IRQ_NONE);
spin_lock(&lp->lock);
while((err = uml_net_rx(dev)) > 0) ;
......@@ -83,6 +85,7 @@ void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
out:
spin_unlock(&lp->lock);
return(IRQ_HANDLED);
}
static int uml_net_open(struct net_device *dev)
......@@ -250,37 +253,6 @@ void uml_net_user_timer_expire(unsigned long _conn)
#endif
}
/*
* default do nothing hard header packet routines for struct net_device init.
* real ethernet transports will overwrite with real routines.
*/
static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, void *daddr, void *saddr, unsigned len)
{
return(0); /* no change */
}
static int uml_net_rebuild_header(struct sk_buff *skb)
{
return(0); /* ignore */
}
static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh)
{
return(-1); /* fail */
}
static void uml_net_header_cache_update(struct hh_cache *hh,
struct net_device *dev, unsigned char * haddr)
{
/* ignore */
}
static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr)
{
return(0); /* nothing */
}
static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED;
static struct list_head devices = LIST_HEAD_INIT(devices);
......@@ -290,7 +262,7 @@ static int eth_configure(int n, void *init, char *mac,
struct uml_net *device;
struct net_device *dev;
struct uml_net_private *lp;
int err, size;
int save, err, size;
size = transport->private_size + sizeof(struct uml_net_private) +
sizeof(((struct uml_net_private *) 0)->user);
......@@ -332,12 +304,6 @@ static int eth_configure(int n, void *init, char *mac,
snprintf(dev->name, sizeof(dev->name), "eth%d", n);
device->dev = dev;
dev->hard_header = uml_net_hard_header;
dev->rebuild_header = uml_net_rebuild_header;
dev->hard_header_cache = uml_net_header_cache;
dev->header_cache_update= uml_net_header_cache_update;
dev->hard_header_parse = uml_net_header_parse;
(*transport->kern->init)(dev, init);
dev->mtu = transport->user->max_packet;
......@@ -364,21 +330,29 @@ static int eth_configure(int n, void *init, char *mac,
}
lp = dev->priv;
INIT_LIST_HEAD(&lp->list);
spin_lock_init(&lp->lock);
lp->dev = dev;
lp->fd = -1;
lp->mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 };
lp->have_mac = device->have_mac;
lp->protocol = transport->kern->protocol;
lp->open = transport->user->open;
lp->close = transport->user->close;
lp->remove = transport->user->remove;
lp->read = transport->kern->read;
lp->write = transport->kern->write;
lp->add_address = transport->user->add_address;
lp->delete_address = transport->user->delete_address;
lp->set_mtu = transport->user->set_mtu;
/* lp.user is the first four bytes of the transport data, which
* has already been initialized. This structure assignment will
* overwrite that, so we make sure that .user gets overwritten with
* what it already has.
*/
save = lp->user[0];
*lp = ((struct uml_net_private)
{ .list = LIST_HEAD_INIT(lp->list),
.lock = SPIN_LOCK_UNLOCKED,
.dev = dev,
.fd = -1,
.mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
.have_mac = device->have_mac,
.protocol = transport->kern->protocol,
.open = transport->user->open,
.close = transport->user->close,
.remove = transport->user->remove,
.read = transport->kern->read,
.write = transport->kern->write,
.add_address = transport->user->add_address,
.delete_address = transport->user->delete_address,
.set_mtu = transport->user->set_mtu,
.user = { save } });
init_timer(&lp->tl);
lp->tl.function = uml_net_user_timer_expire;
......@@ -611,7 +585,8 @@ static int net_remove(char *str)
unregister_netdev(dev);
list_del(&device->list);
free_netdev(device);
kfree(device);
free_netdev(dev);
return(0);
}
......
......@@ -26,8 +26,7 @@ int tap_open_common(void *dev, char *gate_addr)
if(gate_addr == NULL) return(0);
if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
&tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){
printk("Invalid tap IP address - '%s'\n",
gate_addr);
printk("Invalid tap IP address - '%s'\n", gate_addr);
return(-EINVAL);
}
return(0);
......@@ -60,18 +59,18 @@ void read_output(int fd, char *output, int len)
}
*output = '\0';
if(read(fd, &remain, sizeof(remain)) != sizeof(remain)){
printk("read_output - read of length failed, errno = %d\n",
errno);
n = os_read_file(fd, &remain, sizeof(remain));
if(n != sizeof(remain)){
printk("read_output - read of length failed, err = %d\n", -n);
return;
}
while(remain != 0){
n = (remain < len) ? remain : len;
actual = read(fd, output, n);
actual = os_read_file(fd, output, n);
if(actual != n){
printk("read_output - read of data failed, "
"errno = %d\n", errno);
"err = %d\n", -actual);
return;
}
remain -= actual;
......@@ -83,13 +82,12 @@ int net_read(int fd, void *buf, int len)
{
int n;
while(((n = read(fd, buf, len)) < 0) && (errno == EINTR)) ;
n = os_read_file(fd, buf, len);
if(n < 0){
if(errno == EAGAIN) return(0);
return(-errno);
}
else if(n == 0) return(-ENOTCONN);
if(n == -EAGAIN)
return(0);
else if(n == 0)
return(-ENOTCONN);
return(n);
}
......@@ -112,13 +110,13 @@ int net_write(int fd, void *buf, int len)
{
int n;
while(((n = write(fd, buf, len)) < 0) && (errno == EINTR)) ;
if(n < 0){
if(errno == EAGAIN) return(0);
return(-errno);
}
else if(n == 0) return(-ENOTCONN);
return(n);
n = os_write_file(fd, buf, len);
if(n == -EAGAIN)
return(0);
else if(n == 0)
return(-ENOTCONN);
return(n);
}
int net_send(int fd, void *buf, int len)
......@@ -157,7 +155,7 @@ static void change_pre_exec(void *arg)
{
struct change_pre_exec_data *data = arg;
close(data->close_me);
os_close_file(data->close_me);
dup2(data->stdout, 1);
}
......@@ -167,15 +165,15 @@ static int change_tramp(char **argv, char *output, int output_len)
struct change_pre_exec_data pe_data;
err = os_pipe(fds, 1, 0);
if(err){
printk("change_tramp - pipe failed, errno = %d\n", -err);
if(err < 0){
printk("change_tramp - pipe failed, err = %d\n", -err);
return(err);
}
pe_data.close_me = fds[0];
pe_data.stdout = fds[1];
pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
close(fds[1]);
os_close_file(fds[1]);
read_output(fds[0], output, output_len);
waitpid(pid, NULL, 0);
return(pid);
......
......@@ -5,7 +5,6 @@
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include "chan_user.h"
#include "os.h"
......
......@@ -6,6 +6,7 @@
#include "linux/list.h"
#include "linux/sched.h"
#include "linux/slab.h"
#include "linux/interrupt.h"
#include "linux/irq.h"
#include "linux/spinlock.h"
#include "linux/errno.h"
......@@ -14,6 +15,7 @@
#include "kern_util.h"
#include "kern.h"
#include "irq_user.h"
#include "irq_kern.h"
#include "port.h"
#include "init.h"
#include "os.h"
......@@ -38,21 +40,21 @@ struct port_dev {
struct connection {
struct list_head list;
int fd;
int helper_pid;
int helper_pid;
int socket[2];
int telnetd_pid;
struct port_list *port;
};
static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs)
{
struct connection *conn = data;
int fd;
fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
if(fd < 0){
if(fd == -EAGAIN)
return;
return(IRQ_NONE);
printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n",
-fd);
......@@ -65,6 +67,7 @@ static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
list_add(&conn->list, &conn->port->connections);
up(&conn->port->sem);
return(IRQ_HANDLED);
}
static int port_accept(struct port_list *port)
......@@ -102,8 +105,7 @@ static int port_accept(struct port_list *port)
}
list_add(&conn->list, &port->pending);
ret = 1;
goto out;
return(1);
out_free:
kfree(conn);
......@@ -138,12 +140,13 @@ void port_work_proc(void *unused)
DECLARE_WORK(port_work, port_work_proc, NULL);
static void port_interrupt(int irq, void *data, struct pt_regs *regs)
static irqreturn_t port_interrupt(int irq, void *data, struct pt_regs *regs)
{
struct port_list *port = data;
port->has_connection = 1;
schedule_work(&port_work);
return(IRQ_HANDLED);
}
void *port_data(int port_num)
......
......@@ -47,10 +47,12 @@ void *port_init(char *str, int device, struct chan_opts *opts)
return(NULL);
}
if((kern_data = port_data(port)) == NULL)
kern_data = port_data(port);
if(kern_data == NULL)
return(NULL);
if((data = um_kmalloc(sizeof(*data))) == NULL)
data = um_kmalloc(sizeof(*data));
if(data == NULL)
goto err;
*data = ((struct port_chan) { .raw = opts->raw,
......@@ -90,7 +92,7 @@ void port_close(int fd, void *d)
struct port_chan *data = d;
port_remove_dev(data->kernel_data);
close(fd);
os_close_file(fd);
}
int port_console_write(int fd, const char *buf, int n, void *d)
......@@ -130,11 +132,15 @@ int port_listen_fd(int port)
goto out;
}
if((listen(fd, 1) < 0) || (os_set_fd_block(fd, 0))){
if(listen(fd, 1) < 0){
err = -errno;
goto out;
}
err = os_set_fd_block(fd, 0);
if(err < 0)
goto out;
return(fd);
out:
os_close_file(fd);
......@@ -153,10 +159,10 @@ void port_pre_exec(void *arg)
dup2(data->sock_fd, 0);
dup2(data->sock_fd, 1);
dup2(data->sock_fd, 2);
close(data->sock_fd);
os_close_file(data->sock_fd);
dup2(data->pipe_fd, 3);
os_shutdown_socket(3, 1, 0);
close(data->pipe_fd);
os_close_file(data->pipe_fd);
}
int port_connection(int fd, int *socket, int *pid_out)
......@@ -166,11 +172,12 @@ int port_connection(int fd, int *socket, int *pid_out)
"/usr/lib/uml/port-helper", NULL };
struct port_pre_exec_data data;
if((new = os_accept_connection(fd)) < 0)
return(-errno);
new = os_accept_connection(fd);
if(new < 0)
return(new);
err = os_pipe(socket, 0, 0);
if(err)
if(err < 0)
goto out_close;
data = ((struct port_pre_exec_data)
......@@ -186,11 +193,11 @@ int port_connection(int fd, int *socket, int *pid_out)
out_shutdown:
os_shutdown_socket(socket[0], 1, 1);
close(socket[0]);
os_close_file(socket[0]);
os_shutdown_socket(socket[1], 1, 1);
close(socket[1]);
os_close_file(socket[1]);
out_close:
close(new);
os_close_file(new);
return(err);
}
......
......@@ -7,12 +7,12 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#include "chan_user.h"
#include "user.h"
#include "user_util.h"
#include "kern_util.h"
#include "os.h"
struct pty_chan {
void (*announce)(char *dev_name, int dev);
......@@ -26,7 +26,8 @@ void *pty_chan_init(char *str, int device, struct chan_opts *opts)
{
struct pty_chan *data;
if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
data = um_kmalloc(sizeof(*data));
if(data == NULL) return(NULL);
*data = ((struct pty_chan) { .announce = opts->announce,
.dev = device,
.raw = opts->raw });
......@@ -39,7 +40,8 @@ int pts_open(int input, int output, int primary, void *d, char **dev_out)
char *dev;
int fd;
if((fd = get_pty()) < 0){
fd = get_pty();
if(fd < 0){
printk("open_pts : Failed to open pts\n");
return(-errno);
}
......@@ -57,29 +59,27 @@ int pts_open(int input, int output, int primary, void *d, char **dev_out)
int getmaster(char *line)
{
struct stat stb;
char *pty, *bank, *cp;
int master;
int master, err;
pty = &line[strlen("/dev/ptyp")];
for (bank = "pqrs"; *bank; bank++) {
line[strlen("/dev/pty")] = *bank;
*pty = '0';
if (stat(line, &stb) < 0)
if (os_stat_file(line, NULL) < 0)
break;
for (cp = "0123456789abcdef"; *cp; cp++) {
*pty = *cp;
master = open(line, O_RDWR);
master = os_open_file(line, of_rdwr(OPENFLAGS()), 0);
if (master >= 0) {
char *tp = &line[strlen("/dev/")];
int ok;
/* verify slave side is usable */
*tp = 't';
ok = access(line, R_OK|W_OK) == 0;
err = os_access(line, OS_ACC_RW_OK);
*tp = 'p';
if (ok) return(master);
(void) close(master);
if(err == 0) return(master);
(void) os_close_file(master);
}
}
}
......
......@@ -4,11 +4,9 @@
#include <stddef.h>
#include <sched.h>
#include <string.h>
#include <sys/fcntl.h>
#include <sys/errno.h>
#include <sys/termios.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include "user_util.h"
#include "kern_util.h"
......@@ -65,9 +63,9 @@ static void slip_pre_exec(void *arg)
{
struct slip_pre_exec_data *data = arg;
if(data->stdin != -1) dup2(data->stdin, 0);
if(data->stdin >= 0) dup2(data->stdin, 0);
dup2(data->stdout, 1);
if(data->close_me != -1) close(data->close_me);
if(data->close_me >= 0) os_close_file(data->close_me);
}
static int slip_tramp(char **argv, int fd)
......@@ -77,8 +75,8 @@ static int slip_tramp(char **argv, int fd)
int status, pid, fds[2], err, output_len;
err = os_pipe(fds, 1, 0);
if(err){
printk("slip_tramp : pipe failed, errno = %d\n", -err);
if(err < 0){
printk("slip_tramp : pipe failed, err = %d\n", -err);
return(err);
}
......@@ -96,7 +94,7 @@ static int slip_tramp(char **argv, int fd)
printk("slip_tramp : failed to allocate output "
"buffer\n");
close(fds[1]);
os_close_file(fds[1]);
read_output(fds[0], output, output_len);
if(output != NULL){
printk("%s", output);
......@@ -105,7 +103,7 @@ static int slip_tramp(char **argv, int fd)
if(waitpid(pid, &status, 0) < 0) err = errno;
else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
printk("'%s' didn't exit with status 0\n", argv[0]);
err = EINVAL;
err = -EINVAL;
}
}
return(err);
......@@ -118,15 +116,17 @@ static int slip_open(void *data)
char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf,
NULL };
int sfd, mfd, disc, sencap, err;
int sfd, mfd, err;
if((mfd = get_pty()) < 0){
printk("umn : Failed to open pty\n");
return(-1);
mfd = get_pty();
if(mfd < 0){
printk("umn : Failed to open pty, err = %d\n", -mfd);
return(mfd);
}
if((sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0)) < 0){
printk("Couldn't open tty for slip line\n");
return(-1);
sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
if(sfd < 0){
printk("Couldn't open tty for slip line, err = %d\n", -sfd);
return(sfd);
}
if(set_up_tty(sfd)) return(-1);
pri->slave = sfd;
......@@ -138,28 +138,23 @@ static int slip_open(void *data)
err = slip_tramp(argv, sfd);
if(err != 0){
printk("slip_tramp failed - errno = %d\n", err);
return(-err);
if(err < 0){
printk("slip_tramp failed - err = %d\n", -err);
return(err);
}
if(ioctl(pri->slave, SIOCGIFNAME, pri->name) < 0){
printk("SIOCGIFNAME failed, errno = %d\n", errno);
return(-errno);
err = os_get_ifname(pri->slave, pri->name);
if(err < 0){
printk("get_ifname failed, err = %d\n", -err);
return(err);
}
iter_addresses(pri->dev, open_addr, pri->name);
}
else {
disc = N_SLIP;
if(ioctl(sfd, TIOCSETD, &disc) < 0){
printk("Failed to set slip line discipline - "
"errno = %d\n", errno);
return(-errno);
}
sencap = 0;
if(ioctl(sfd, SIOCSIFENCAP, &sencap) < 0){
printk("Failed to set slip encapsulation - "
"errno = %d\n", errno);
return(-errno);
err = os_set_slip(sfd);
if(err < 0){
printk("Failed to set slip discipline encapsulation - "
"err = %d\n", -err);
return(err);
}
}
return(mfd);
......@@ -181,9 +176,9 @@ static void slip_close(int fd, void *data)
err = slip_tramp(argv, -1);
if(err != 0)
printk("slip_tramp failed - errno = %d\n", err);
close(fd);
close(pri->slave);
printk("slip_tramp failed - errno = %d\n", -err);
os_close_file(fd);
os_close_file(pri->slave);
pri->slave = -1;
}
......@@ -243,7 +238,7 @@ static void slip_add_addr(unsigned char *addr, unsigned char *netmask,
{
struct slip_data *pri = data;
if(pri->slave == -1) return;
if(pri->slave < 0) return;
open_addr(addr, netmask, pri->name);
}
......@@ -252,7 +247,7 @@ static void slip_del_addr(unsigned char *addr, unsigned char *netmask,
{
struct slip_data *pri = data;
if(pri->slave == -1) return;
if(pri->slave < 0) return;
close_addr(addr, netmask, pri->name);
}
......
......@@ -4,7 +4,6 @@
#include <stddef.h>
#include <sched.h>
#include <string.h>
#include <sys/fcntl.h>
#include <sys/errno.h>
#include <sys/wait.h>
#include <sys/signal.h>
......@@ -48,15 +47,15 @@ static int slirp_tramp(char **argv, int fd)
return(pid);
}
/* XXX This is just a trivial wrapper around os_pipe */
static int slirp_datachan(int *mfd, int *sfd)
{
int fds[2], err;
err = os_pipe(fds, 1, 1);
if(err){
printk("slirp_datachan: Failed to open pipe, errno = %d\n",
-err);
if(err < 0){
printk("slirp_datachan: Failed to open pipe, err = %d\n", -err);
return(err);
}
......@@ -77,7 +76,7 @@ static int slirp_open(void *data)
pid = slirp_tramp(pri->argw.argv, sfd);
if(pid < 0){
printk("slirp_tramp failed - errno = %d\n", pid);
printk("slirp_tramp failed - errno = %d\n", -pid);
os_close_file(sfd);
os_close_file(mfd);
return(pid);
......@@ -97,8 +96,8 @@ static void slirp_close(int fd, void *data)
struct slirp_data *pri = data;
int status,err;
close(fd);
close(pri->slave);
os_close_file(fd);
os_close_file(pri->slave);
pri->slave = -1;
......
......@@ -10,6 +10,7 @@
#include "linux/major.h"
#include "linux/mm.h"
#include "linux/init.h"
#include "linux/console.h"
#include "asm/termbits.h"
#include "asm/irq.h"
#include "line.h"
......@@ -53,8 +54,9 @@ static int ssl_remove(char *str);
static struct line_driver driver = {
.name = "UML serial line",
.devfs_name = "tts/%d",
.major = TTYAUX_MAJOR,
.device_name = "ttS",
.devfs_name = "tts/",
.major = TTY_MAJOR,
.minor_start = 64,
.type = TTY_DRIVER_TYPE_SERIAL,
.subtype = 0,
......@@ -149,6 +151,9 @@ static int ssl_ioctl(struct tty_struct *tty, struct file * file,
case TCSETSW:
case TCGETA:
case TIOCMGET:
case TCSBRK:
case TCSBRKP:
case TIOCMSET:
ret = -ENOIOCTLCMD;
break;
default:
......@@ -212,6 +217,37 @@ static struct tty_operations ssl_ops = {
*/
static int ssl_init_done = 0;
static void ssl_console_write(struct console *c, const char *string,
unsigned len)
{
struct line *line = &serial_lines[c->index];
if(ssl_init_done)
down(&line->sem);
console_write_chan(&line->chan_list, string, len);
if(ssl_init_done)
up(&line->sem);
}
static struct tty_driver *ssl_console_device(struct console *c, int *index)
{
*index = c->index;
return ssl_driver;
}
static int ssl_console_setup(struct console *co, char *options)
{
return(0);
}
static struct console ssl_cons = {
name: "ttyS",
write: ssl_console_write,
device: ssl_console_device,
setup: ssl_console_setup,
flags: CON_PRINTBUFFER,
index: -1,
};
int ssl_init(void)
{
char *new_title;
......@@ -227,17 +263,18 @@ int ssl_init(void)
new_title = add_xterm_umid(opts.xterm_title);
if(new_title != NULL) opts.xterm_title = new_title;
register_console(&ssl_cons);
ssl_init_done = 1;
return(0);
}
__initcall(ssl_init);
late_initcall(ssl_init);
static int ssl_chan_setup(char *str)
{
line_setup(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]),
str, 1);
return(1);
return(line_setup(serial_lines,
sizeof(serial_lines)/sizeof(serial_lines[0]),
str, 1));
}
__setup("ssl", ssl_chan_setup);
......
......@@ -83,7 +83,8 @@ static int con_remove(char *str);
static struct line_driver driver = {
.name = "UML console",
.devfs_name = "vc/%d",
.device_name = "tty",
.devfs_name = "vc/",
.major = TTY_MAJOR,
.minor_start = 0,
.type = TTY_DRIVER_TYPE_CONSOLE,
......@@ -159,6 +160,15 @@ static int chars_in_buffer(struct tty_struct *tty)
static int con_init_done = 0;
static struct tty_operations console_ops = {
.open = con_open,
.close = con_close,
.write = con_write,
.chars_in_buffer = chars_in_buffer,
.set_termios = set_termios,
.write_room = line_write_room,
};
int stdio_init(void)
{
char *new_title;
......@@ -166,7 +176,8 @@ int stdio_init(void)
printk(KERN_INFO "Initializing stdio console driver\n");
console_driver = line_register_devfs(&console_lines, &driver,
&console_ops, vts, sizeof(vts)/sizeof(vts[0]));
&console_ops, vts,
sizeof(vts)/sizeof(vts[0]));
lines_init(vts, sizeof(vts)/sizeof(vts[0]));
......@@ -178,24 +189,19 @@ int stdio_init(void)
return(0);
}
__initcall(stdio_init);
late_initcall(stdio_init);
static void console_write(struct console *console, const char *string,
unsigned len)
{
if(con_init_done) down(&vts[console->index].sem);
console_write_chan(&vts[console->index].chan_list, string, len);
if(con_init_done) up(&vts[console->index].sem);
}
struct line *line = &vts[console->index];
static struct tty_operations console_ops = {
.open = con_open,
.close = con_close,
.write = con_write,
.chars_in_buffer = chars_in_buffer,
.set_termios = set_termios,
.write_room = line_write_room,
};
if(con_init_done)
down(&line->sem);
console_write_chan(&line->chan_list, string, len);
if(con_init_done)
up(&line->sem);
}
static struct tty_driver *console_device(struct console *c, int *index)
{
......@@ -208,22 +214,28 @@ static int console_setup(struct console *co, char *options)
return(0);
}
static struct console stdiocons = INIT_CONSOLE("tty", console_write,
console_device, console_setup,
CON_PRINTBUFFER);
static struct console stdiocons = {
name: "tty",
write: console_write,
device: console_device,
setup: console_setup,
flags: CON_PRINTBUFFER,
index: -1,
};
static void __init stdio_console_init(void)
static int __init stdio_console_init(void)
{
INIT_LIST_HEAD(&vts[0].chan_list);
list_add(&init_console_chan.list, &vts[0].chan_list);
register_console(&stdiocons);
return(0);
}
console_initcall(stdio_console_init);
static int console_chan_setup(char *str)
{
line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1);
return(1);
return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1));
}
__setup("con", console_chan_setup);
......
......@@ -5,7 +5,6 @@
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include "chan_user.h"
......@@ -30,7 +29,8 @@ void *tty_chan_init(char *str, int device, struct chan_opts *opts)
}
str++;
if((data = um_kmalloc(sizeof(*data))) == NULL)
data = um_kmalloc(sizeof(*data));
if(data == NULL)
return(NULL);
*data = ((struct tty_chan) { .dev = str,
.raw = opts->raw });
......
This diff is collapsed.
This diff is collapsed.
......@@ -8,7 +8,6 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#include <signal.h>
#include <sched.h>
......@@ -36,7 +35,8 @@ void *xterm_init(char *str, int device, struct chan_opts *opts)
{
struct xterm_chan *data;
if((data = malloc(sizeof(*data))) == NULL) return(NULL);
data = malloc(sizeof(*data));
if(data == NULL) return(NULL);
*data = ((struct xterm_chan) { .pid = -1,
.helper_pid = -1,
.device = device,
......@@ -93,7 +93,7 @@ int xterm_open(int input, int output, int primary, void *d, char **dev_out)
"/usr/lib/uml/port-helper", "-uml-socket",
file, NULL };
if(access(argv[4], X_OK))
if(os_access(argv[4], OS_ACC_X_OK) < 0)
argv[4] = "port-helper";
fd = mkstemp(file);
......@@ -106,13 +106,13 @@ int xterm_open(int input, int output, int primary, void *d, char **dev_out)
printk("xterm_open : unlink failed, errno = %d\n", errno);
return(-errno);
}
close(fd);
os_close_file(fd);
fd = create_unix_socket(file, sizeof(file));
fd = os_create_unix_socket(file, sizeof(file), 1);
if(fd < 0){
printk("xterm_open : create_unix_socket failed, errno = %d\n",
-fd);
return(-fd);
return(fd);
}
sprintf(title, data->title, data->device);
......@@ -128,15 +128,16 @@ int xterm_open(int input, int output, int primary, void *d, char **dev_out)
if(data->direct_rcv)
new = os_rcv_fd(fd, &data->helper_pid);
else {
if((err = os_set_fd_block(fd, 0)) != 0){
err = os_set_fd_block(fd, 0);
if(err < 0){
printk("xterm_open : failed to set descriptor "
"non-blocking, errno = %d\n", err);
"non-blocking, err = %d\n", -err);
return(err);
}
new = xterm_fd(fd, &data->helper_pid);
}
if(new < 0){
printk("xterm_open : os_rcv_fd failed, errno = %d\n", -new);
printk("xterm_open : os_rcv_fd failed, err = %d\n", -new);
goto out;
}
......@@ -160,7 +161,7 @@ void xterm_close(int fd, void *d)
if(data->helper_pid != -1)
os_kill_process(data->helper_pid, 0);
data->helper_pid = -1;
close(fd);
os_close_file(fd);
}
void xterm_free(void *d)
......
......@@ -5,9 +5,12 @@
#include "linux/errno.h"
#include "linux/slab.h"
#include "linux/signal.h"
#include "linux/interrupt.h"
#include "asm/semaphore.h"
#include "asm/irq.h"
#include "irq_user.h"
#include "irq_kern.h"
#include "kern_util.h"
#include "os.h"
#include "xterm.h"
......@@ -19,17 +22,18 @@ struct xterm_wait {
int new_fd;
};
static void xterm_interrupt(int irq, void *data, struct pt_regs *regs)
static irqreturn_t xterm_interrupt(int irq, void *data, struct pt_regs *regs)
{
struct xterm_wait *xterm = data;
int fd;
fd = os_rcv_fd(xterm->fd, &xterm->pid);
if(fd == -EAGAIN)
return;
return(IRQ_NONE);
xterm->new_fd = fd;
up(&xterm->sem);
return(IRQ_HANDLED);
}
int xterm_fd(int socket, int *pid_out)
......@@ -54,7 +58,8 @@ int xterm_fd(int socket, int *pid_out)
if(err){
printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
"err = %d\n", err);
return(err);
ret = err;
goto out;
}
down(&data->sem);
......@@ -62,6 +67,7 @@ int xterm_fd(int socket, int *pid_out)
ret = data->new_fd;
*pid_out = data->pid;
out:
kfree(data);
return(ret);
......
#include <asm-generic/vmlinux.lds.h>
OUTPUT_FORMAT(ELF_FORMAT)
OUTPUT_ARCH(ELF_ARCH)
ENTRY(_start)
......@@ -10,12 +12,15 @@ SECTIONS
{
. = START + SIZEOF_HEADERS;
.interp : { *(.interp) }
. = ALIGN(4096);
__binary_start = .;
. = ALIGN(4096); /* Init code and data */
_stext = .;
__init_begin = .;
.text.init : { *(.text.init) }
.init.text : {
_sinittext = .;
*(.init.text)
_einittext = .;
}
. = ALIGN(4096);
......@@ -55,7 +60,9 @@ SECTIONS
} =0x90909090
.plt : { *(.plt) }
.text : {
*(.text .stub .text.* .gnu.linkonce.t.*)
*(.text)
SCHED_TEXT
*(.stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} =0x90909090
......@@ -67,7 +74,7 @@ SECTIONS
#include "asm/common.lds.S"
.data.init : { *(.data.init) }
init.data : { *(.init.data) }
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -11,6 +11,8 @@ extern int signal_stack_size;
extern int change_sig(int signal, int on);
extern void set_sigstack(void *stack, int size);
extern void set_handler(int sig, void (*handler)(int), int flags, ...);
extern int set_signals(int enable);
extern int get_signals(void);
#endif
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment