xref: /OK3568_Linux_fs/yocto/poky/meta/classes/overlayfs-etc.bbclass (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun# Class for setting up /etc in overlayfs
2*4882a593Smuzhiyun#
3*4882a593Smuzhiyun# In order to have /etc directory in overlayfs a special handling at early boot stage is required
4*4882a593Smuzhiyun# The idea is to supply a custom init script that mounts /etc before launching actual init program,
5*4882a593Smuzhiyun# because the latter already requires /etc to be mounted
6*4882a593Smuzhiyun#
7*4882a593Smuzhiyun# The configuration must be machine specific. You should at least set these three variables:
8*4882a593Smuzhiyun#   OVERLAYFS_ETC_MOUNT_POINT ?= "/data"
9*4882a593Smuzhiyun#   OVERLAYFS_ETC_FSTYPE ?= "ext4"
10*4882a593Smuzhiyun#   OVERLAYFS_ETC_DEVICE ?= "/dev/mmcblk0p2"
11*4882a593Smuzhiyun#
12*4882a593Smuzhiyun# To control more mount options you should consider setting mount options:
13*4882a593Smuzhiyun#   OVERLAYFS_ETC_MOUNT_OPTIONS ?= "defaults"
14*4882a593Smuzhiyun#
15*4882a593Smuzhiyun# The class provides two options for /sbin/init generation
16*4882a593Smuzhiyun# 1. Default option is to rename original /sbin/init to /sbin/init.orig and place generated init under
17*4882a593Smuzhiyun#    original name, i.e. /sbin/init. It has an advantage that you won't need to change any kernel
18*4882a593Smuzhiyun#    parameters in order to make it work, but it poses a restriction that package-management can't
19*4882a593Smuzhiyun#    be used, becaause updating init manager would remove generated script
20*4882a593Smuzhiyun# 2. If you are would like to keep original init as is, you can set
21*4882a593Smuzhiyun#    OVERLAYFS_ETC_USE_ORIG_INIT_NAME = "0"
22*4882a593Smuzhiyun#    Then generated init will be named /sbin/preinit and you would need to extend you kernel parameters
23*4882a593Smuzhiyun#    manually in your bootloader configuration.
24*4882a593Smuzhiyun#
25*4882a593Smuzhiyun# Regardless which mode you choose, update and migration strategy of configuration files under /etc
26*4882a593Smuzhiyun# overlay is out of scope of this class
27*4882a593Smuzhiyun
28*4882a593SmuzhiyunROOTFS_POSTPROCESS_COMMAND += '${@bb.utils.contains("IMAGE_FEATURES", "overlayfs-etc", "create_overlayfs_etc_preinit;", "", d)}'
29*4882a593SmuzhiyunIMAGE_FEATURES_CONFLICTS_overlayfs-etc = "${@ 'package-management' if bb.utils.to_boolean(d.getVar('OVERLAYFS_ETC_USE_ORIG_INIT_NAME'), True) else ''}"
30*4882a593Smuzhiyun
31*4882a593SmuzhiyunOVERLAYFS_ETC_MOUNT_POINT ??= ""
32*4882a593SmuzhiyunOVERLAYFS_ETC_FSTYPE ??= ""
33*4882a593SmuzhiyunOVERLAYFS_ETC_DEVICE ??= ""
34*4882a593SmuzhiyunOVERLAYFS_ETC_USE_ORIG_INIT_NAME ??= "1"
35*4882a593SmuzhiyunOVERLAYFS_ETC_MOUNT_OPTIONS ??= "defaults"
36*4882a593SmuzhiyunOVERLAYFS_ETC_INIT_TEMPLATE ??= "${COREBASE}/meta/files/overlayfs-etc-preinit.sh.in"
37*4882a593SmuzhiyunOVERLAYFS_ETC_EXPOSE_LOWER ??= "0"
38*4882a593Smuzhiyun
39*4882a593Smuzhiyunpython create_overlayfs_etc_preinit() {
40*4882a593Smuzhiyun    overlayEtcMountPoint = d.getVar("OVERLAYFS_ETC_MOUNT_POINT")
41*4882a593Smuzhiyun    overlayEtcFsType = d.getVar("OVERLAYFS_ETC_FSTYPE")
42*4882a593Smuzhiyun    overlayEtcDevice = d.getVar("OVERLAYFS_ETC_DEVICE")
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun    if not overlayEtcMountPoint:
45*4882a593Smuzhiyun        bb.fatal("OVERLAYFS_ETC_MOUNT_POINT must be set in your MACHINE configuration")
46*4882a593Smuzhiyun    if not overlayEtcDevice:
47*4882a593Smuzhiyun        bb.fatal("OVERLAYFS_ETC_DEVICE must be set in your MACHINE configuration")
48*4882a593Smuzhiyun    if not overlayEtcFsType:
49*4882a593Smuzhiyun        bb.fatal("OVERLAYFS_ETC_FSTYPE should contain a valid file system type on {0}".format(overlayEtcDevice))
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun    with open(d.getVar("OVERLAYFS_ETC_INIT_TEMPLATE"), "r") as f:
52*4882a593Smuzhiyun        PreinitTemplate = f.read()
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun    useOrigInit = oe.types.boolean(d.getVar('OVERLAYFS_ETC_USE_ORIG_INIT_NAME'))
55*4882a593Smuzhiyun    preinitPath = oe.path.join(d.getVar("IMAGE_ROOTFS"), d.getVar("base_sbindir"), "preinit")
56*4882a593Smuzhiyun    initBaseName = oe.path.join(d.getVar("base_sbindir"), "init")
57*4882a593Smuzhiyun    origInitNameSuffix = ".orig"
58*4882a593Smuzhiyun    exposeLower = oe.types.boolean(d.getVar('OVERLAYFS_ETC_EXPOSE_LOWER'))
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun    args = {
61*4882a593Smuzhiyun        'OVERLAYFS_ETC_MOUNT_POINT': overlayEtcMountPoint,
62*4882a593Smuzhiyun        'OVERLAYFS_ETC_MOUNT_OPTIONS': d.getVar('OVERLAYFS_ETC_MOUNT_OPTIONS'),
63*4882a593Smuzhiyun        'OVERLAYFS_ETC_FSTYPE': overlayEtcFsType,
64*4882a593Smuzhiyun        'OVERLAYFS_ETC_DEVICE': overlayEtcDevice,
65*4882a593Smuzhiyun        'SBIN_INIT_NAME': initBaseName + origInitNameSuffix if useOrigInit else initBaseName,
66*4882a593Smuzhiyun        'OVERLAYFS_ETC_EXPOSE_LOWER': "true" if exposeLower else "false"
67*4882a593Smuzhiyun    }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun    if useOrigInit:
70*4882a593Smuzhiyun        # rename original /sbin/init
71*4882a593Smuzhiyun        origInit = oe.path.join(d.getVar("IMAGE_ROOTFS"), initBaseName)
72*4882a593Smuzhiyun        bb.debug(1, "rootfs path %s, init path %s, test %s" % (d.getVar('IMAGE_ROOTFS'), origInit, d.getVar("IMAGE_ROOTFS")))
73*4882a593Smuzhiyun        bb.utils.rename(origInit, origInit + origInitNameSuffix)
74*4882a593Smuzhiyun        preinitPath = origInit
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun    with open(preinitPath, 'w') as f:
77*4882a593Smuzhiyun        f.write(PreinitTemplate.format(**args))
78*4882a593Smuzhiyun    os.chmod(preinitPath, 0o755)
79*4882a593Smuzhiyun}
80