diff --git a/diskimage_builder/block_device/__init__.py b/diskimage_builder/block_device/__init__.py
index 4a0715091..a2bb2b7eb 100644
--- a/diskimage_builder/block_device/__init__.py
+++ b/diskimage_builder/block_device/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2016 Andreas Florath (andreas@florath.net)
+# Copyright 2016-2017 Andreas Florath (andreas@florath.net)
 #
 # Licensed under the Apache License, Version 2.0 (the "License"); you may
 # not use this file except in compliance with the License. You may obtain
@@ -45,25 +45,18 @@ def main():
         epilog="Available phases:\n" + phase_doc)
     parser.add_argument('--phase', required=True,
                         help="phase to execute")
-    parser.add_argument('--config', required=False,
-                        help="configuration for block device "
-                             "layer as JSON object")
-    parser.add_argument('--build-dir', required=True,
-                        help="path to temporary build dir")
-    parser.add_argument('--image-size', required=False,
-                        help="default image size")
-    parser.add_argument('--image-dir', required=False,
-                        help="default image directory")
+    parser.add_argument('--params', required=True,
+                        help="parameters for block device handling")
+    parser.add_argument('--symbol', required=False,
+                        help="symbol to query for getval")
     args = parser.parse_args()
 
     logger.info("phase [%s]" % args.phase)
-    logger.info("config [%s]" % args.config)
-    logger.info("build_dir [%s]" % args.build_dir)
+    logger.info("params [%s]" % args.params)
+    if args.symbol:
+        logger.info("symbol [%s]" % args.symbol)
 
-    bd = BlockDevice(val_else_none(args.config),
-                     val_else_none(args.build_dir),
-                     val_else_none(args.image_size),
-                     val_else_none(args.image_dir))
+    bd = BlockDevice(args)
 
     # Check if the method is available
     method = getattr(bd, "cmd_" + args.phase, None)
@@ -76,6 +69,5 @@ def main():
 
     return 0
 
-
 if __name__ == "__main__":
     main()
diff --git a/diskimage_builder/block_device/blockdevice.py b/diskimage_builder/block_device/blockdevice.py
index 18b5e55e8..45a2ed4f0 100644
--- a/diskimage_builder/block_device/blockdevice.py
+++ b/diskimage_builder/block_device/blockdevice.py
@@ -1,4 +1,4 @@
-# Copyright 2016 Andreas Florath (andreas@florath.net)
+# Copyright 2016-2017 Andreas Florath (andreas@florath.net)
 #
 # Licensed under the Apache License, Version 2.0 (the "License"); you may
 # not use this file except in compliance with the License. You may obtain
@@ -36,6 +36,10 @@ class BlockDevice(object):
 
     A typical call sequence:
 
+    cmd_init: initialized the block device level config.  After this
+       call it is possible to e.g. query information from the (partially
+       automatic generated) internal state like root-label.
+
     cmd_create: creates all the different aspects of the block
        device. When this call is successful, the complete block level
        device is set up, filesystems are created and are mounted at
@@ -62,6 +66,13 @@ class BlockDevice(object):
 
     In a script this should be called in the following way:
 
+    dib-block-device --phase=init ...
+    # From that point the database can be queried, like
+    ROOT_LABEL=$(dib-block-device --phase=getval --symbol=root-label ...)
+
+    Please note that currently the dib-block-device executable can
+    only be used outside the chroot.
+
     dib-block-device --phase=create ...
     trap "dib-block-device --phase=delete ..." EXIT
     # copy / install files
@@ -71,50 +82,74 @@ class BlockDevice(object):
     trap - EXIT
     """
 
-    # Default configuration:
-    # one image, one partition, mounted under '/'
-    DefaultConfig = """
-- local_loop:
-    name: image0
-"""
+    def _merge_into_config(self):
+        """Merge old (default) config into new
 
-# This is an example of the next level config
-# mkfs:
-#  base: root
-#  type: ext4
-#  mount_point: /
+        There is the need to be compatible using some old environment
+        variables.  This is done in the way, that if there is no
+        explicit value given, these values are inserted into the current
+        configuration.
+        """
+        for entry in self.config:
+            for k, v in entry.items():
+                if k == 'mkfs':
+                    if 'name' not in v:
+                        continue
+                    if v['name'] != 'mkfs_root':
+                        continue
+                    if 'type' not in v \
+                       and 'root-fs-type' in self.params:
+                        v['type'] = self.params['root-fs-type']
+                    if 'opts' not in v \
+                       and 'root-fs-opts' in self.params:
+                        v['opts'] = self.params['root-fs-opts']
+                    if 'label' not in v \
+                       and 'root-label' in self.params:
+                        if self.params['root-label'] is not None:
+                            v['label'] = self.params['root-label']
+                        else:
+                            v['label'] = "cloudimg-rootfs"
 
-    def __init__(self, block_device_config, build_dir,
-                 default_image_size, default_image_dir):
+    @staticmethod
+    def _load_json(file_name):
+        if os.path.exists(file_name):
+            with codecs.open(file_name, encoding="utf-8", mode="r") as fd:
+                return json.load(fd)
+        return None
+
+    def __init__(self, args):
         logger.debug("Creating BlockDevice object")
-        logger.debug("Config given [%s]" % block_device_config)
-        logger.debug("Build dir [%s]" % build_dir)
-        if block_device_config is None:
-            block_device_config = BlockDevice.DefaultConfig
-        self.config = yaml.safe_load(block_device_config)
-        logger.debug("Using config [%s]" % self.config)
+        logger.debug("Param file [%s]" % args.params)
+        self.args = args
 
-        self.default_config = {
-            'image_size': default_image_size,
-            'image_dir': default_image_dir}
-        self.state_dir = os.path.join(build_dir,
-                                      "states/block-device")
+        with open(self.args.params) as param_fd:
+            self.params = yaml.safe_load(param_fd)
+        logger.debug("Params [%s]" % self.params)
+
+        self.state_dir = os.path.join(
+            self.params['build-dir'], "states/block-device")
         self.state_json_file_name \
             = os.path.join(self.state_dir, "state.json")
         self.plugin_manager = extension.ExtensionManager(
             namespace='diskimage_builder.block_device.plugin',
             invoke_on_load=False)
+        self.config_json_file_name \
+            = os.path.join(self.state_dir, "config.json")
 
-    def write_state(self, result):
+        self.config = self._load_json(self.config_json_file_name)
+        self.state = self._load_json(self.state_json_file_name)
+        logger.debug("Using state [%s]", self.state)
+
+        # This needs to exists for the state and config files
+        try:
+            os.makedirs(self.state_dir)
+        except OSError:
+            pass
+
+    def write_state(self, state):
         logger.debug("Write state [%s]" % self.state_json_file_name)
-        os.makedirs(self.state_dir)
         with open(self.state_json_file_name, "w") as fd:
-            json.dump([self.config, self.default_config, result], fd)
-
-    def load_state(self):
-        with codecs.open(self.state_json_file_name,
-                         encoding="utf-8", mode="r") as fd:
-            return json.load(fd)
+            json.dump(state, fd)
 
     def create_graph(self, config, default_config):
         # This is the directed graph of nodes: each parse method must
@@ -152,10 +187,28 @@ class BlockDevice(object):
         return dg, call_order
 
     def create(self, result, rollback):
-        dg, call_order = self.create_graph(self.config, self.default_config)
+        dg, call_order = self.create_graph(self.config, self.params)
         for node in call_order:
             node.create(result, rollback)
 
+    def cmd_init(self):
+        """Initialize block device setup
+
+        This initializes the block device setup layer. One major task
+        is to parse and check the configuration, write it down for
+        later examiniation and execution.
+        """
+        with open(self.params['config'], "rt") as config_fd:
+            self.config = yaml.safe_load(config_fd)
+        logger.debug("Config before merge [%s]" % self.config)
+        self._merge_into_config()
+        logger.debug("Final config [%s]" % self.config)
+        # Write the final config
+        with open(self.config_json_file_name, "wt") as fd:
+            json.dump(self.config, fd)
+        logger.info("Wrote final block device config to [%s]"
+                    % self.config_json_file_name)
+
     def cmd_create(self):
         """Creates the block device"""
 
@@ -187,47 +240,33 @@ class BlockDevice(object):
         logger.info("create() finished")
         return 0
 
-    def _load_state(self):
-        logger.info("_load_state() called")
-        try:
-            os.stat(self.state_json_file_name)
-        except OSError:
-            logger.info("State already cleaned - no way to do anything here")
-            return None, None, None
-
-        config, default_config, state = self.load_state()
-        logger.debug("Using config [%s]" % config)
-        logger.debug("Using default config [%s]" % default_config)
-        logger.debug("Using state [%s]" % state)
-
-        # Deleting must be done in reverse order
-        dg, call_order = self.create_graph(config, default_config)
-        reverse_order = reversed(call_order)
-        return dg, reverse_order, state
-
     def cmd_umount(self):
         """Unmounts the blockdevice and cleanup resources"""
 
-        dg, reverse_order, state = self._load_state()
+        dg, call_order = self.create_graph(self.config, self.params)
+        reverse_order = reversed(call_order)
         if dg is None:
             return 0
         for node in reverse_order:
-            node.umount(state)
+            node.umount(self.state)
 
         # To be compatible with the current implementation, echo the
         # result to stdout.
-        print("%s" % state['image0']['image'])
+        print("%s" % self.state['image0']['image'])
 
         return 0
 
     def cmd_cleanup(self):
         """Cleanup all remaining relicts - in good case"""
 
-        dg, reverse_order, state = self._load_state()
+        # Deleting must be done in reverse order
+        dg, call_order = self.create_graph(self.config, self.params)
+        reverse_order = reversed(call_order)
+
         if dg is None:
             return 0
         for node in reverse_order:
-            node.cleanup(state)
+            node.cleanup(self.state)
 
         logger.info("Removing temporary dir [%s]" % self.state_dir)
         shutil.rmtree(self.state_dir)
@@ -237,11 +276,14 @@ class BlockDevice(object):
     def cmd_delete(self):
         """Cleanup all remaining relicts - in case of an error"""
 
-        dg, reverse_order, state = self._load_state()
+        # Deleting must be done in reverse order
+        dg, call_order = self.create_graph(self.config, self.params)
+        reverse_order = reversed(call_order)
+
         if dg is None:
             return 0
         for node in reverse_order:
-            node.delete(state)
+            node.delete(self.state)
 
         logger.info("Removing temporary dir [%s]" % self.state_dir)
         shutil.rmtree(self.state_dir)
diff --git a/diskimage_builder/block_device/level0/localloop.py b/diskimage_builder/block_device/level0/localloop.py
index dfa543d8d..11249a05e 100644
--- a/diskimage_builder/block_device/level0/localloop.py
+++ b/diskimage_builder/block_device/level0/localloop.py
@@ -39,12 +39,12 @@ class LocalLoop(NodePluginBase):
             self.size = parse_abs_size_spec(config['size'])
             logger.debug("Image size [%s]" % self.size)
         else:
-            self.size = parse_abs_size_spec(default_config['image_size'])
+            self.size = parse_abs_size_spec(default_config['image-size'])
             logger.debug("Using default image size [%s]" % self.size)
         if 'directory' in config:
             self.image_dir = config['directory']
         else:
-            self.image_dir = default_config['image_dir']
+            self.image_dir = default_config['image-dir']
         self.name = config['name']
         Digraph.Node.__init__(self, self.name)
         self.filename = os.path.join(self.image_dir, self.name + ".raw")
diff --git a/diskimage_builder/lib/common-functions b/diskimage_builder/lib/common-functions
index ac71350fb..e1153a4bd 100644
--- a/diskimage_builder/lib/common-functions
+++ b/diskimage_builder/lib/common-functions
@@ -359,3 +359,51 @@ function unmount_dir {
         sudo umount -fl $m || true
     done
 }
+
+# Create YAML config file for the block device layer
+# The order here is: use the one the user provides - if there is
+# none provided, fall back to the possible one element which
+# defines a fallback configuration.
+# Parameters:
+#   - name of the to be created config file
+function block_device_create_config_file {
+    local CONFIG_YAML="$1"
+
+    # User setting overwrites this
+    if [[ ${DIB_BLOCK_DEVICE_CONFIG:-} == file://* ]]; then
+        cp $(echo ${DIB_BLOCK_DEVICE_CONFIG} | cut -c 8-) ${CONFIG_YAML}
+        return
+    fi
+    if [ -n "${DIB_BLOCK_DEVICE_CONFIG:-}" ]; then
+        printf "%s" "${DIB_BLOCK_DEVICE_CONFIG}" >${CONFIG_YAML}
+        return
+    fi
+
+    eval declare -A image_elements=($(get_image_element_array))
+    for i in ${!image_elements[@]}; do
+        local BLOCK_DEVICE_CFG_PATH=${image_elements[$i]}/block-device-${ARCH}.yaml
+        if [ -e ${BLOCK_DEVICE_CFG_PATH} ]; then
+            cp ${BLOCK_DEVICE_CFG_PATH} ${CONFIG_YAML}
+        else
+            BLOCK_DEVICE_CFG_PATH=${image_elements[$i]}/block-device-default.yaml
+            if [ -e ${BLOCK_DEVICE_CFG_PATH} ]; then
+                cp ${BLOCK_DEVICE_CFG_PATH} ${CONFIG_YAML}
+            fi
+        fi
+    done
+
+    # If no config is there (until now) use the default config
+    if [ ! -e ${CONFIG_YAML} ]; then
+        cat >${CONFIG_YAML} <<EOF
+- local_loop:
+    name: image0
+    mkfs:
+      name: mkfs_root
+      mount:
+        mount_point: /
+        fstab:
+          options: "defaults"
+          fsck-passno: 1
+EOF
+    fi
+}
diff --git a/diskimage_builder/lib/disk-image-create b/diskimage_builder/lib/disk-image-create
index 67edd26bd..cadac5a35 100644
--- a/diskimage_builder/lib/disk-image-create
+++ b/diskimage_builder/lib/disk-image-create
@@ -276,6 +276,28 @@ if [[ -n "${GENTOO_PROFILE}" ]]; then
 fi
 
 mk_build_dir
+
+# Create the YAML file with the final and raw configuration for
+# the block device layer.
+mkdir -p ${TMP_BUILD_DIR}/block-device
+BLOCK_DEVICE_CONFIG_YAML=${TMP_BUILD_DIR}/block-device/config.yaml
+block_device_create_config_file "${BLOCK_DEVICE_CONFIG_YAML}"
+
+# Write out the parameter file
+DIB_BLOCK_DEVICE_PARAMS_YAML=${TMP_BUILD_DIR}/block-device/params.yaml
+export DIB_BLOCK_DEVICE_PARAMS_YAML
+cat >${DIB_BLOCK_DEVICE_PARAMS_YAML} <<EOF
+config: ${BLOCK_DEVICE_CONFIG_YAML}
+image-dir: ${TMP_IMAGE_DIR}
+root-fs-type: ${FS_TYPE}
+root-label: ${DIB_ROOT_LABEL}
+mount-base: ${TMP_BUILD_DIR}/mnt
+build-dir: ${TMP_BUILD_DIR}
+EOF
+
+dib-block-device --phase=init \
+                 --params="${DIB_BLOCK_DEVICE_PARAMS_YAML}"
+
 create_base
 # This variable needs to be propagated into the chroot
 mkdir -p $TMP_HOOKS_PATH/environment.d
@@ -397,12 +419,19 @@ fi
 DIB_BLOCK_DEVICE_SCRIPT=$(which dib-block-device)
 
 if [ -z ${IMAGE_BLOCK_DEVICE} ] ; then
-    IMAGE_BLOCK_DEVICE=$(${DIB_BLOCK_DEVICE_SCRIPT} \
-                             --phase=create \
-                             --config="${DIB_BLOCK_DEVICE_CONFIG:-}" \
-                             --image-size="${DIB_IMAGE_SIZE}"KiB \
-                             --image-dir="${TMP_IMAGE_DIR}" \
-                             --build-dir="${TMP_BUILD_DIR}" )
+    # For compatibily reasons in addition to the YAML configuration
+    # there is the need to handle the old environment variables.
+    echo "image-size: ${DIB_IMAGE_SIZE}KiB" >> ${DIB_BLOCK_DEVICE_PARAMS_YAML}
+
+    # After changeing the parameters, there is the need to
+    # re-run dib-block-device init because some value might
+    # change based on the new set parameters.
+    dib-block-device --phase=init \
+                     --params="${DIB_BLOCK_DEVICE_PARAMS_YAML}"
+
+    # values to dib-block-device: using the YAML config and
+    IMAGE_BLOCK_DEVICE=$(dib-block-device --phase=create \
+                                          --params="${DIB_BLOCK_DEVICE_PARAMS_YAML}")
 fi
 export IMAGE_BLOCK_DEVICE
 LOOPDEV=${IMAGE_BLOCK_DEVICE}
@@ -413,7 +442,7 @@ export IMAGE_BLOCK_DEVICE_WITHOUT_PART
 
 export EXTRA_DETACH="detach_loopback ${IMAGE_BLOCK_DEVICE_WITHOUT_PART}"
 export EXTRA_UNMOUNT="dib-block-device --phase=cleanup \
-                      --build-dir=\"${TMP_BUILD_DIR}\""
+                      --params=\"${DIB_BLOCK_DEVICE_PARAMS_YAML}\""
 
 sudo mkfs -t $FS_TYPE $MKFS_OPTS -L ${DIB_ROOT_LABEL} ${IMAGE_BLOCK_DEVICE}
 # Tuning the rootfs uuid works only for ext filesystems.
@@ -467,13 +496,12 @@ fi
 # space before converting the image to some other format.
 export EXTRA_UNMOUNT=""
 unmount_image
-export TMP_IMAGE_PATH=$(${DIB_BLOCK_DEVICE_SCRIPT} \
-                            --phase=umount \
-                            --build-dir="${TMP_BUILD_DIR}" )
+TMP_IMAGE_PATH=$(dib-block-device --phase=umount \
+                                  --params="${DIB_BLOCK_DEVICE_PARAMS_YAML}")
+export TMP_IMAGE_PATH
 
-${DIB_BLOCK_DEVICE_SCRIPT} \
-    --phase=cleanup \
-    --build-dir="${TMP_BUILD_DIR}"
+dib-block-device --phase=cleanup \
+                 --params="${DIB_BLOCK_DEVICE_PARAMS_YAML}"
 
 cleanup_build_dir