diff --git a/Makefile b/Makefile
index ba74696..e43fd9d 100644
--- a/Makefile
+++ b/Makefile
@@ -303,6 +303,7 @@ LIBS-y += test/libtest.o
 
 LIBS-$(CONFIG_DM) += common/dm/libdm.o
 LIBS-$(CONFIG_DM) += drivers/demo/libdemo.o
+LIBS-${CONFIG_DM_BLOCK} += drivers/blockdev/libblockdev.o
 
 ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP34XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),)
 LIBS-y += $(CPUDIR)/omap-common/libomap-common.o
diff --git a/drivers/blockdev/Makefile b/drivers/blockdev/Makefile
new file mode 100644
index 0000000..693e236
--- /dev/null
+++ b/drivers/blockdev/Makefile
@@ -0,0 +1,42 @@
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	:= $(obj)libblockdev.o
+
+COBJS-${CONFIG_DM_BLOCK} := core.o
+
+COBJS	:= $(COBJS-y)
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/include/dm/blockdev.h b/include/dm/blockdev.h
new file mode 100644
index 0000000..828eb2b
--- /dev/null
+++ b/include/dm/blockdev.h
@@ -0,0 +1,121 @@
+/*
+ * (C) Copyright 2012
+ * Pavel Herrmann <morpheus.ibis@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _DM_BLOCKDEV_H_
+#define _DM_BLOCKDEV_H_ 1
+
+#include <dm/options.h>
+#include <dm/structures.h>
+
+#define BLOCKDEV_IFTYPE_BITS 4
+#define BLOCKDEV_IFTYPE_COUNT (1<<BLOCKDEV_IFTYPE_BITS)
+#define BLOCKDEV_IFTYPE_MAX BLOCKDEV_IFTYPE_COUNT-1
+
+/* core interface structures */
+
+enum blockdev_iftype {
+	BLOCKDEV_IFTYPE_UNKNOWN = 0,
+	BLOCKDEV_IFTYPE_PARTITION,
+	BLOCKDEV_IFTYPE_ATA,
+	BLOCKDEV_IFTYPE_SD,
+	BLOCKDEV_IFTYPE_USB,
+};
+
+/* values from ATA specification */
+#define BLOCKDEV_TYPE_UNKNOWN	0xff
+#define BLOCKDEV_TYPE_HARDDISK	0x00
+#define BLOCKDEV_TYPE_TAPE	0x01
+#define BLOCKDEV_TYPE_CDROM	0x05
+#define BLOCKDEV_TYPE_OPDISK	0x07
+/* this one does not exist in ATA */
+#define BLOCKDEV_TYPE_PARTITION	0xfe
+
+enum blockdev_option_code {
+	BLKD_OPT_IFTYPE = 0,
+	BLKD_OPT_TYPE,
+	BLKD_OPT_BLOCKSIZE,
+	BLKD_OPT_BLOCKCOUNT,
+	BLKD_OPT_REMOVABLE,
+	BLKD_OPT_LBA48,
+	BLKD_OPT_VENDOR,
+	BLKD_OPT_PRODUCT,
+	BLKD_OPT_REVISION,
+	BLKD_OPT_SCSILUN,
+	BLKD_OPT_SCSITARGET,
+	BLKD_OPT_OFFSET
+};
+
+struct blockdev_ops {
+	lbaint_t	(*read)(struct instance *inst, lbaint_t start,
+				lbaint_t blkcnt, void *buffer);
+	lbaint_t	(*write)(struct instance *inst, lbaint_t start,
+				lbaint_t blkcnt, void *buffer);
+	lbaint_t	(*erase)(struct instance *inst, lbaint_t start,
+				lbaint_t blkcnt);
+	int		(*get_option)(struct instance *inst,
+				enum blockdev_option_code option,
+				struct option *result);
+	int		(*set_option)(struct instance *inst,
+				enum blockdev_option_code option,
+				struct option *value);
+};
+
+struct blockdev_core_hint {
+	enum blockdev_iftype iftype;
+	unsigned int part_number;
+};
+
+/* platform data for devices */
+
+struct blockdev_ata_platform_data {
+	int port_number;
+};
+
+struct blockdev_partition_platform_data {
+	lbaint_t offset;
+	lbaint_t block_count;
+	unsigned int part_number;
+};
+
+/* core command API */
+
+struct instance *get_blockdev_by_name(char *name);
+int scan_partitions(struct instance *i);
+int add_partition(struct instance *parent, lbaint_t start, lbaint_t length,
+	unsigned int number);
+int print_blockdev_info(struct instance *i);
+int print_blockdev_info_all(void);
+
+/* core driver API */
+
+lbaint_t blockdev_read(struct instance *i, lbaint_t start, lbaint_t blkcnt,
+		void *buffer);
+lbaint_t blockdev_write(struct instance *i, lbaint_t start, lbaint_t blkcnt,
+		void *buffer);
+lbaint_t blockdev_erase(struct instance *i, lbaint_t start, lbaint_t blkcnt);
+int blockdev_get_option(struct instance *i, enum blockdev_option_code op,
+		struct option *result);
+int blockdev_set_option(struct instance *i, enum blockdev_option_code op,
+		struct option *value);
+
+#endif
