--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,11 @@ ifeq ($(WITHOUT_XATTR), 1)
   CPPFLAGS += -DWITHOUT_XATTR
 endif
 
+ifeq ($(shell uname -o),Cygwin)
+CPPFLAGS += -I./include/cygwin
+endif
+
+ifneq ($(shell uname -o),Cygwin)
 SUBDIRS = ubi-utils mkfs.ubifs
 
 TARGETS = ftl_format flash_erase flash_eraseall nanddump doc_loadbios \
@@ -17,6 +22,10 @@ TARGETS = ftl_format flash_erase flash_e
 	rfddump rfdformat \
 	serve_image recv_image \
 	sumtool #jffs2reader
+else
+SUBDIRS =
+TARGETS = mkfs.jffs2
+endif
 
 SYMLINKS =
 
--- /dev/null
+++ b/include/cygwin/bits-byteswap.h
@@ -0,0 +1,132 @@
+/* Macros to swap the order of bytes in integer values.
+   Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#if !defined _BYTESWAP_H && !defined _NETINET_IN_H
+# error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead."
+#endif
+
+#ifndef _BITS_BYTESWAP_H
+#define _BITS_BYTESWAP_H 1
+
+/* Swap bytes in 16 bit value.  */
+#define __bswap_constant_16(x) \
+     ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
+
+#ifdef __GNUC__
+# if __GNUC__ >= 2
+#  define __bswap_16(x) \
+     (__extension__							      \
+      ({ register unsigned short int __v, __x = (x);			      \
+	 if (__builtin_constant_p (__x))				      \
+	   __v = __bswap_constant_16 (__x);				      \
+	 else								      \
+	   __asm__ ("rorw $8, %w0"					      \
+		    : "=r" (__v)					      \
+ 		    : "0" (__x)						      \
+ 		    : "cc");						      \
+	 __v; }))
+# else
+/* This is better than nothing.  */
+#  define __bswap_16(x) \
+     (__extension__							      \
+      ({ register unsigned short int __x = (x); __bswap_constant_16 (__x); }))
+# endif
+#else
+static __inline unsigned short int
+__bswap_16 (unsigned short int __bsx)
+{
+  return __bswap_constant_16 (__bsx);
+}
+#endif
+
+/* Swap bytes in 32 bit value.  */
+#define __bswap_constant_32(x) \
+     ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) |		      \
+      (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
+
+#ifdef __GNUC__
+# if __GNUC__ >= 2
+/* To swap the bytes in a word the i486 processors and up provide the
+   `bswap' opcode.  On i386 we have to use three instructions.  */
+#  if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__
+#   define __bswap_32(x)						      \
+     (__extension__							      \
+      ({ register unsigned int __v, __x = (x);				      \
+	 if (__builtin_constant_p (__x))				      \
+	   __v = __bswap_constant_32 (__x);				      \
+	 else								      \
+	   __asm__ ("rorw $8, %w0;"					      \
+		    "rorl $16, %0;"					      \
+		    "rorw $8, %w0"					      \
+		    : "=r" (__v)					      \
+		    : "0" (__x)						      \
+		    : "cc");						      \
+	 __v; }))
+#  else
+#   define __bswap_32(x) \
+     (__extension__							      \
+      ({ register unsigned int __v, __x = (x);				      \
+	 if (__builtin_constant_p (__x))				      \
+	   __v = __bswap_constant_32 (__x);				      \
+	 else								      \
+	   __asm__ ("bswap %0" : "=r" (__v) : "0" (__x));		      \
+	 __v; }))
+#  endif
+# else
+#  define __bswap_32(x) \
+     (__extension__							      \
+      ({ register unsigned int __x = (x); __bswap_constant_32 (__x); }))
+# endif
+#else
+static __inline unsigned int
+__bswap_32 (unsigned int __bsx)
+{
+  return __bswap_constant_32 (__bsx);
+}
+#endif
+
+
+#if defined __GNUC__ && __GNUC__ >= 2
+/* Swap bytes in 64 bit value.  */
+#define __bswap_constant_64(x) \
+     ((((x) & 0xff00000000000000ull) >> 56)				      \
+      | (((x) & 0x00ff000000000000ull) >> 40)				      \
+      | (((x) & 0x0000ff0000000000ull) >> 24)				      \
+      | (((x) & 0x000000ff00000000ull) >> 8)				      \
+      | (((x) & 0x00000000ff000000ull) << 8)				      \
+      | (((x) & 0x0000000000ff0000ull) << 24)				      \
+      | (((x) & 0x000000000000ff00ull) << 40)				      \
+      | (((x) & 0x00000000000000ffull) << 56))
+
+# define __bswap_64(x) \
+     (__extension__							      \
+      ({ union { __extension__ unsigned long long int __ll;		      \
+		 unsigned long int __l[2]; } __w, __r;			      \
+         if (__builtin_constant_p (x))					      \
+	   __r.__ll = __bswap_constant_64 (x);				      \
+	 else								      \
+	   {								      \
+	     __w.__ll = (x);						      \
+	     __r.__l[0] = __bswap_32 (__w.__l[1]);			      \
+	     __r.__l[1] = __bswap_32 (__w.__l[0]);			      \
+	   }								      \
+	 __r.__ll; }))
+#endif
+
+#endif /* _BITS_BYTESWAP_H */
--- /dev/null
+++ b/include/cygwin/byteswap.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _BYTESWAP_H
+#define _BYTESWAP_H     1
+
+/* Get the machine specific, optimized definitions.  */
+#include "bits-byteswap.h"
+
+
+/* The following definitions must all be macros since otherwise some
+   of the possible optimizations are not possible.  */
+
+/* Return a value with all bytes in the 16 bit argument swapped.  */
+#define bswap_16(x) __bswap_16 (x)
+
+/* Return a value with all bytes in the 32 bit argument swapped.  */
+#define bswap_32(x) __bswap_32 (x)
+
+#if defined __GNUC__ && __GNUC__ >= 2
+/* Return a value with all bytes in the 64 bit argument swapped.  */
+# define bswap_64(x) __bswap_64 (x)
+#endif
+
+#endif /* byteswap.h */
--- /dev/null
+++ b/include/cygwin/endian.h
@@ -0,0 +1,26 @@
+#ifndef _CYGENDIAN_H_
+#define _CYGENDIAN_H_
+
+#ifdef __CYGWIN__
+
+#include <sys/param.h>
+
+#ifndef __BIG_ENDIAN
+#define __BIG_ENDIAN 4321
+#endif
+
+#ifndef __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN 1234
+#endif
+
+#ifndef __BYTE_ORDER
+#define __BYTE_ORDER	__LITTLE_ENDIAN
+#endif
+
+#ifndef BYTE_ORDER
+#define BYTE_ORDER	__LITTLE_ENDIAN
+#endif
+
+#endif /* __CYGWIN__ */
+
+#endif /* _CYGENDIAN_H_ */
--- /dev/null
+++ b/include/cygwin/ioctl.h
@@ -0,0 +1,38 @@
+#ifndef _CYGIOCTL_H_
+#define _CYGIOCTL_H_
+
+#ifdef __CYGWIN__
+
+#define _IOC_NRBITS     8
+#define _IOC_TYPEBITS   8
+#define _IOC_SIZEBITS   14
+#define _IOC_DIRBITS    2
+ 
+#define _IOC_NRMASK     ((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK   ((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK   ((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK    ((1 << _IOC_DIRBITS)-1)
+ 
+#define _IOC_NRSHIFT    0
+#define _IOC_TYPESHIFT  (_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT  (_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT   (_IOC_SIZESHIFT+_IOC_SIZEBITS)
+ 
+#define _IOC_NONE       0U
+#define _IOC_WRITE      1U
+#define _IOC_READ       2U
+ 
+#define _IOC(dir,type,nr,size) \
+	(((dir)  << _IOC_DIRSHIFT) | \
+	((type) << _IOC_TYPESHIFT) | \
+	((nr)   << _IOC_NRSHIFT) | \
+	((size) << _IOC_SIZESHIFT))
+
+#define _IO(type,nr)            _IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)      _IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size)      _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size)     _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+#endif /* __CYGWIN__ */
+
+#endif /* _CYGIOCTL_H_ */
--- /dev/null
+++ b/include/cygwin/pread.c
@@ -0,0 +1,41 @@
+#ifdef __CYGWIN__
+
+#include <errno.h>
+
+ssize_t
+pread(int fd, void *p, size_t n, off_t off)
+{
+        off_t ooff;
+        int oerrno;
+
+        if ((ooff  = lseek(fd, off, SEEK_SET)) == -1)
+                return -1;
+
+        n = read(fd, p, n);
+
+        oerrno = errno;
+        lseek(fd, ooff, SEEK_SET);
+        errno = oerrno;
+
+        return n;
+}
+
+ssize_t
+pwrite(int fd, const void *p, size_t n, off_t off)
+{
+        off_t ooff;
+        int oerrno;
+
+        if ((ooff  = lseek(fd, off, SEEK_SET)) == -1)
+                return -1;
+
+        n = write(fd, p, n);
+
+        oerrno = errno;
+        lseek(fd, ooff, SEEK_SET);
+        errno = oerrno;
+
+        return n;
+}
+
+#endif /* __CYGWIN__ */
--- /dev/null
+++ b/lnconf.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# Generic configure replacement.
+#
+# $Id: lnconf.sh,v 1.1 2004/04/05 21:55:59 igor Exp $ 
+#
+# Copies all files from the script directory to the current one.
+# Intended to replace 'configure' for packages that don't have one, to
+# allow building outside of the source tree.
+#
+# Note: this does not do any fancy things with detecting shells and
+# supporting other platforms.  But it should work on Cygwin.
+
+# find out where the script is located
+tdir=`echo "$0" | sed 's%[\\/][^\\/][^\\/]*$%%'`
+test "x$tdir" = "x$0" && tdir=.
+
+a_srcdir=`cd $tdir; pwd`
+a_destdir=`pwd`
+
+# sanity checks:
+# are we in the script directory?
+test "x$a_srcdir" = "x$a_destdir" && exit 0
+# is there any chance that this is the script directory?
+test "x`cd "$a_srcdir" && /bin/ls -id`" = "x`/bin/ls -id`" && exit 0
+
+# try to find lndir and use it if it's available
+LNDIR="`which lndir 2>/dev/null`"
+if [ "x$LNDIR" = "x" ]; then
+  lndir() {
+    test "x$1" = "x" && return 1
+    # be careful of the current directory
+    DINODE=`find . -maxdepth 0 -ls | sed 's/ .*$//'` 
+    case "`pwd`" in
+      "`cd "$1" && pwd`"/*) CUR="-type d -inum $DINODE -prune -o";;
+    esac
+    # duplicate the directory structure
+    (cd "$1" && find . $CUR -type d -mindepth 1 -print) | xargs -tr mkdir -p
+    # copy all symbolic links
+    (cd "$1" && find . $CUR -type l -mindepth 1 -print) | xargs -ri sh -c "ln -s \"\`readlink "$1/{}"\`\" \"{}\""
+    # or simply
+    #(cd "$1" && find . $CUR -type l -mindepth 1 -print) | xargs -ri ln -s "$1"/{} {}
+    # link all files
+    (cd "$1" && find . $CUR -type f -mindepth 1 -print) | xargs -ri ln -s "$1"/{} {}
+  }
+else
+  lndir() {
+    "$LNDIR" "$@"
+  }
+fi
+
+lndir "$tdir"
+
--- a/mkfs.jffs2.c
+++ b/mkfs.jffs2.c
@@ -75,6 +75,14 @@
 #include "crc32.h"
 #include "rbtree.h"
 
+#ifdef __CYGWIN__
+#include <cygwin/ioctl.h>
+#include <cygwin/endian.h>
+#include <cygwin/pread.c>
+# define IFTODT(mode)          (((mode) & 0170000) >> 12)
+# define DTTOIF(dirtype)       ((dirtype) << 12)
+#endif /* __CYGWIN__ */
+
 /* Do not use the weird XPG version of basename */
 #undef basename
 
@@ -474,7 +482,7 @@ static struct filesystem_entry *recursiv
    the following macros use it if available or use a hacky workaround...
  */
 
-#ifdef __GNUC__
+#if defined __GNUC__ && !defined __CYGWIN__
 #define SCANF_PREFIX "a"
 #define SCANF_STRING(s) (&s)
 #define GETCWD_SIZE 0
@@ -557,6 +565,14 @@ static int interpret_table_entry(struct 
 	}
 	entry = find_filesystem_entry(root, name, mode);
 	if (entry) {
+		/* Check the type */
+		if ((mode & S_IFMT) != (entry->sb.st_mode & S_IFMT)) {
+			error_msg ("skipping device_table entry '%s': type mismatch!", name);
+			free(name);
+			free(hostpath);
+			return 1;
+		}
+
 		/* Ok, we just need to fixup the existing entry
 		 * and we will be all done... */
 		entry->sb.st_uid = uid;
@@ -566,11 +582,21 @@ static int interpret_table_entry(struct 
 			entry->sb.st_rdev = makedev(major, minor);
 		}
 	} else {
+		if (type == 'f' || type == 'l') {
+			error_msg ("skipping device_table entry '%s': file does not exist!", name);
+			free(name);
+			free(hostpath);
+			return 1;
+		}
 		/* If parent is NULL (happens with device table entries),
 		 * try and find our parent now) */
 		tmp = strdup(name);
 		dir = dirname(tmp);
-		parent = find_filesystem_entry(root, dir, S_IFDIR);
+		if (!strcmp(dir, "/")) {
+			parent = root;
+		} else {
+			parent = find_filesystem_entry(root, dir, S_IFDIR);
+		}
 		free(tmp);
 		if (parent == NULL) {
 			error_msg ("skipping device_table entry '%s': no parent directory!", name);
@@ -584,6 +610,7 @@ static int interpret_table_entry(struct 
 				add_host_filesystem_entry(name, hostpath, uid, gid, mode, 0, parent);
 				break;
 			case 'f':
+			case 'l':
 				add_host_filesystem_entry(name, hostpath, uid, gid, mode, 0, parent);
 				break;
 			case 'p':
--- a/ubi-utils/src/libubi.c
+++ b/ubi-utils/src/libubi.c
@@ -30,6 +30,9 @@
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#ifdef __CYGWIN__
+#include <cygwin/ioctl.h>
+#endif
 #include <libubi.h>
 #include "libubi_int.h"
 #include "common.h"