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