diff --git a/Kconfig b/Kconfig
index 75f9eaa..83d2857 100644
--- a/Kconfig
+++ b/Kconfig
@@ -498,3 +498,4 @@ config ZSTD
 
 source parser/Config.in
 source handlers/Config.in
+source fatfs/Config.in
diff --git a/Makefile b/Makefile
index a1d185e..9231c41 100644
--- a/Makefile
+++ b/Makefile
@@ -359,7 +359,7 @@ include $(srctree)/Makefile.flags
 # Defaults to vmlinux, but the arch makefile usually adds further targets
 
 objs-y		:= core handlers
-libs-y		:= corelib mongoose parser suricatta bootloader
+libs-y		:= corelib mongoose parser suricatta bootloader fatfs
 bindings-y	:= bindings
 tools-y		:= tools
 
diff --git a/fatfs/Config.in b/fatfs/Config.in
new file mode 100644
index 0000000..8d416f6
--- /dev/null
+++ b/fatfs/Config.in
@@ -0,0 +1,6 @@
+config FAT_FILESYSTEM
+	bool "FAT file system creation support"
+	depends on DISKFORMAT
+	default n
+	help
+	  Enable support for creating FAT file systems.
diff --git a/fatfs/Makefile b/fatfs/Makefile
new file mode 100644
index 0000000..551528d
--- /dev/null
+++ b/fatfs/Makefile
@@ -0,0 +1,3 @@
+lib-$(CONFIG_FAT_FILESYSTEM) += diskio.o \
+				fat_fs.o \
+				ff.o
diff --git a/fatfs/diskio.c b/fatfs/diskio.c
index 1976add..479aec9 100644
--- a/fatfs/diskio.c
+++ b/fatfs/diskio.c
@@ -21,37 +21,44 @@
 
 #define SECTOR_SIZE	512
 
-static int file_descriptor;
-static char device_name[MAX_VOLNAME];
-static bool init_status;
-
-int fatfs_init(char *device);
-void fatfs_release(void);
+static int file_descriptor = -1;
 
 
+/*
+ * Extension to FatFs library: fatfs_init associates the fatfs library with
+ * a disk device file. It has to be called before using any FatFs API function.
+ */
 int fatfs_init(char *device)
 {
-	if (strnlen(device_name, MAX_VOLNAME)) {
+	if (file_descriptor >= 0) {
 		ERROR("Called fatfs_init second time without fatfs_release");
 		return -1;
 	}
 
-	strncpy(device_name, device, sizeof(device_name));
-	file_descriptor = open(device_name, O_RDWR);
+	if (!device) {
+		ERROR("Device name is NULL pointer");
+		return -1;
+	}
+
+	file_descriptor = open(device, O_RDWR);
 
 	if (file_descriptor < 0) {
-		ERROR("Device %s cannot be opened: %s", device_name, strerror(errno));
-		return -ENODEV;
+		ERROR("Device %s cannot be opened: %s", device, strerror(errno));
+		return -1;
 	}
 
 	return 0;
 }
 
+/*
+ * Extension to FatFs libary: fatfs_release closes a disk device.
+ */
 void fatfs_release(void)
 {
-	(void)close(file_descriptor);
-	memset(device_name, 0, MAX_VOLNAME);
-	init_status = false;
+	if (file_descriptor >= 0) {
+		(void)close(file_descriptor);
+		file_descriptor = -1;
+	}
 }
 
 DSTATUS disk_status(BYTE pdrv)
@@ -59,10 +66,7 @@ DSTATUS disk_status(BYTE pdrv)
 	DSTATUS status = 0;
 	(void)pdrv;
 
-	if (!strnlen(device_name, MAX_VOLNAME))
-		status |= STA_NODISK;
-
-	if (!init_status)
+	if (file_descriptor < 0)
 		status |= STA_NOINIT;
 
 	return status;
@@ -70,8 +74,6 @@ DSTATUS disk_status(BYTE pdrv)
 
 DSTATUS disk_initialize(BYTE pdrv)
 {
-	init_status = true;
-
 	return disk_status(pdrv);
 }
 
@@ -128,14 +130,14 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
 		if (!buff)
 			return RES_PARERR;
 
-		*(LBA_t*)buff = size;
+		*(LBA_t *)buff = size;
 		break;
 	}
 	case GET_SECTOR_SIZE:
 		if (!buff)
 			return RES_PARERR;
 
-		*(WORD*)buff = SECTOR_SIZE;
+		*(WORD *)buff = SECTOR_SIZE;
 		break;
 	case GET_BLOCK_SIZE:
 		/* Get erase block size of flash memories, return 1 if not a
@@ -144,7 +146,7 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
 		if (!buff)
 			return RES_PARERR;
 
-		*(WORD*)buff = 1;
+		*(WORD *)buff = 1;
 		break;
 	default:
 		ERROR("cmd %d not implemented", cmd);
diff --git a/fatfs/fat_fs.c b/fatfs/fat_fs.c
new file mode 100644
index 0000000..942e96e
--- /dev/null
+++ b/fatfs/fat_fs.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 Weidmueller Interface GmbH & Co. KG
+ * Roland Gaudig <roland.gaudig@weidmueller.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0-or-later
+ */
+
+#include <errno.h>
+#include <stddef.h>
+
+#include <fatfs_interface.h>
+#include <swupdate.h>
+#include <util.h>
+
+#include "ff.h"
+
+
+int fat_mkfs(char *device_name)
+{
+	if (fatfs_init(device_name))
+		return -1;
+
+	void* working_buffer = malloc(FF_MAX_SS);
+
+	if (!working_buffer) {
+		fatfs_release();
+		return -ENOMEM;
+	}
+
+	MKFS_PARM mkfs_parm = {
+		.fmt = FM_ANY | FM_SFD,
+		.au_size = 0,
+		.align = 0,
+		.n_fat = 0,
+		.n_root = 0
+	};
+
+	FRESULT result = f_mkfs("", &mkfs_parm, working_buffer, FF_MAX_SS);
+	free(working_buffer);
+
+	if (result != FR_OK) {
+		fatfs_release();
+		return -1;
+	}
+
+	fatfs_release();
+	return 0;
+}
diff --git a/include/fatfs_interface.h b/include/fatfs_interface.h
new file mode 100644
index 0000000..a5d8ef7
--- /dev/null
+++ b/include/fatfs_interface.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2021 Weidmueller Interface GmbH & Co. KG
+ * Roland Gaudig <roland.gaudig@weidmueller.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0-or-later
+ */
+
+#ifndef _FATFS_INTERFACE_H
+#define _FATFS_INTERFACE_H
+
+extern int fat_mkfs(char *device_name);
+
+#endif
