diff --git a/meta-ohos-core/classes/writables.bbclass b/meta-ohos-core/classes/writables.bbclass
new file mode 100644
index 0000000000000000000000000000000000000000..8dc76a9e3149fe4cf7c07bd4cf2882b248a591bf
--- /dev/null
+++ b/meta-ohos-core/classes/writables.bbclass
@@ -0,0 +1,181 @@
+# SPDX-FileCopyrightText: Huawei Inc.
+#
+# SPDX-License-Identifier: Apache-2.0
+
+# This class provides support for defining, at the level of the recipe, the
+# required writable paths. It provides support for maintaining persistent or
+# volatile state at runtime for read-only filesystems.
+#
+# To take advantage of the provided functionality, one would define a set of
+# writable as part of WRITABLES:
+# WRITABLES = "logs database misc"
+#
+# Each writable's associated path is defined using a VarFlag:
+#
+# WRITABLE_PATH[logs] = "/foo/bar/logs"
+# WRITABLE_PATH[database] = "/foo/bar/db"
+# WRITABLE_PATH[misc] = "/foo/bar/misc"
+#
+# Each WRITABLE_PATH is a directory.
+#
+# By default, each writable is of type persistent (it will use a bind mount
+# from the state partition to the writable's path). This can be switched to
+# volatile by defining:
+#
+# WRITABLE_TYPE[logs] = "volatile"
+#
+# The supported types are "volatile" and "persistent".
+#
+# This will use a tmpfs for the provided writable path.
+
+inherit systemd
+
+# The read-write area needs to be provided by the OS in the form of a rw
+# mountpoint handled with systemd mount unit. In this way the state/writable
+# systemd mount units this class generates, will have the correct dependency on
+# having the read-write partition mounted.
+SYSTEM_STATE_RUNTIME_MOUNTPOINT ??= "/var/run/mount/sysdata"
+SYSTEM_STATE_MOUNT_UNIT ??= "run-mount-sysdata.mount"
+
+# The mount units depend on having the system state partition mounted at a
+# known location as described above. The respective system partition mount
+# units are part of the x-mounts package. This provides the
+# SYSTEM_STATE_MOUNT_UNIT systemd mount unit.
+RDEPENDS_${PN} += "x-mounts"
+
+# This is the root filesystem hierarchy used as part of the bind mount units to
+# provide read-write locations.
+SYSDATA_OVERLAY ??= "rootfs-overlay"
+
+def escapeSystemdUnitName(path):
+    escapeMap = {
+        '/': '-',
+        '-': "\\x2d",
+        '\\': "\\x5d"
+    }
+    return "".join([escapeMap.get(c, c) for c in path.strip('/')])
+
+def mountUnitName(unit):
+    return escapeSystemdUnitName(unit) + '.mount'
+
+def write_mount_unit(writable, what, dst):
+    """Writes a mount unit to destination - argument `dst`. The mount unit is
+       described as a dictionary (argument `writable`) for most of the mount
+       unit parts with the exception of `What` which is provided by the
+       argument 'what'."""
+
+    MountUnit = "[Unit]\n" \
+                "DefaultDependencies=no\n" \
+                "Conflicts=umount.target\n" \
+                "Before=local-fs.target umount.target\n"
+    if writable["after"]:
+        MountUnit += "After=%s\n" % ' '.join(writable["after"])
+    if writable["requires"]:
+        MountUnit += "Requires=%s\n" % ' '.join(writable["after"])
+    MountUnit += "\n"\
+                 "[Mount]\n"
+    if what:
+        MountUnit += "What=%s\n" % what
+    if writable["where"]:
+        MountUnit += "Where=%s\n" % writable["where"]
+    if writable["type"]:
+        MountUnit += "Type=%s\n" % writable["type"]
+    if writable["options"]:
+        MountUnit += "Options=%s\n" % ','.join(writable["options"])
+    MountUnit += "\n"\
+                 "[Install]\n" \
+                 "WantedBy=local-fs.target\n"
+
+    with open((dst), 'w') as f:
+        f.write(MountUnit)
+
+def get_writable_data(d):
+    wdata = []
+    writables = d.getVar('WRITABLES')
+    if not writables:
+        bb.fatal("No writable paths defined")
+    for writable in writables.split():
+        where = d.getVarFlag('WRITABLE_PATH', writable)
+        if not where:
+            bb.fatal("No writable path defined for %s" % writable)
+        options = []
+        after = []
+        requires = []
+        type = d.getVarFlag('WRITABLE_TYPE', writable) or 'persistent'
+        if type == 'persistent':
+            state_mount_unit = d.getVar('SYSTEM_STATE_MOUNT_UNIT')
+            if not state_mount_unit:
+                bb.fatal("SYSTEM_STATE_MOUNT_UNIT not defined")
+            type = 'none'
+            options.append('bind')
+            after.append(state_mount_unit)
+            requires.append(state_mount_unit)
+        elif type == 'volatile':
+            type = 'tmpfs'
+        else:
+            bbfatal("%s mount type not implemented" % type)
+        writable_data = {
+            'after': after,
+            'requires': requires,
+            'id': writable,
+            'where': where,
+            'type': type,
+            'options': options,
+        }
+        wdata.append(writable_data)
+    return wdata
+
+python() {
+    import os
+
+    systemd_system_unitdir = d.getVar('systemd_system_unitdir')
+    for writable in get_writable_data(d):
+        d.appendVar('FILES_' + d.getVar('PN'), ' ' + writable['where'])
+        d.appendVar('FILES_' + d.getVar('PN'), ' ' + \
+            os.path.join(systemd_system_unitdir, mountUnitName(writable['where'])))
+        d.appendVar('SYSTEMD_SERVICE_' + d.getVar('PN'), ' ' + \
+            mountUnitName(writable['where']))
+}
+
+python install_mount_units() {
+    import os
+
+    # Validate and define the path where the persistent state is kept
+    state_mountpoint = d.getVar('SYSTEM_STATE_RUNTIME_MOUNTPOINT')
+    if not state_mountpoint:
+        bb.fatal("SYSTEM_STATE_RUNTIME_MOUNTPOINT not defined.")
+    sys_data_overlay = d.getVar('SYSDATA_OVERLAY')
+    if not sys_data_overlay:
+        bb.fatal("SYSDATA_OVERLAY not defined.")
+    persistent_path = os.path.join(state_mountpoint, sys_data_overlay)
+
+    dee = d.getVar('D')
+    systemd_system_unitdir = d.getVar('systemd_system_unitdir').strip('/')
+    d_systemd_system_unitdir = os.path.join(dee, systemd_system_unitdir)
+    os.makedirs(d_systemd_system_unitdir, exist_ok=True)
+
+    for writable in get_writable_data(d):
+        where = writable['where'].strip('/')
+        # Where usually is created by systemd when not in place but on a
+        # read-only filesystem that won't work so we make sure we have the
+        # right mountpoints on the filesystem.
+        where_installpath = os.path.join(dee, where)
+        if os.path.exists(where_installpath):
+            if os.path.isdir(where_installpath) and os.listdir(where_installpath):
+                bb.fatal("The path for %s writable (%s) already exists and contains entries that will be shadowed at runtime. Please fix." % (writable, where_installpath))
+            elif os.path.isdir(where_installpath) and not os.listdir(where_installpath):
+                pass
+            else:
+                bb.fatal("The path for %s writable (%s) already exists and it is not an empty directory. Please fix." % (writable, where_installpath))
+        else:
+            os.makedirs(os.path.join(dee, where))
+        if writable['type'] == 'tmpfs':
+            what = 'tmpfs'
+        else:
+            what = os.path.join(persistent_path, where)
+        dst = os.path.join(d_systemd_system_unitdir, mountUnitName(where))
+        write_mount_unit(writable, what, dst)
+}
+
+do_install[vardeps] += "WRITABLES WRITABLE_PATH WRITABLE_TYPE"
+do_install[postfuncs] += "install_mount_units"