Compare commits

...

9 Commits

Author SHA1 Message Date
Dustin f14577cade Begin persistent storage implementation
Aimee OS/aimee-os/pipeline/head This commit looks good Details
Most of the logic in the `init-storage` script is the same as it was in
Aimee OS v1 (Gentoo).  The major difference is now we are initializing
the data volume in the initramfs instead of in the real OS.  This allows
us to make all of `/etc` writable via OverlayFS, instead of having only
certain sub-directories writable via bind-mounts.

Buildroot doesn't really have any tools for building an initramfs,
unfortunately.  It does have a bit of infrastructure for running
`dracut`, but I'd really rather avoid having that much complexity in the
initramfs; all we need is to run the `init-storage` script and then
switch root.  Instead, the `mkinitramfs.sh` script, called in the
post-build stage, creates the CPIO archive from files in the target
directory.  The only particularly interesting bit is how it resolves
shared library dependencies, to make sure the appropriate resources are
available for the requisite commands.

I briefly considered building a statically-linked BusyBox just for the
initramfs.  Since it doesn't provide several important tools like
`btrfs`/`mkfs.btrfs`, I had to implement the dynamic link resolution
function anyway.  It made sense, then, to copy Dash and the necessary
Coreutils binaries themselves.
2025-08-29 20:13:18 -05:00
Dustin 505b1745f6 configs/qemu: Enable debug shell on ttyAMA0
We set the default kernel command-line arguments to tell systemd to
spawn a debug shell on the serial console, instead of the default getty.
This will allow tests to run commands directly on the console, without
any authentication, etc.
2025-08-29 20:13:18 -05:00
Dustin 2bdf06f8cc grub2: Support setting rootflags in config
The `AIMEEOS_DEFAULT_ROOTFLAGS` kconfig option can be used to set the
default value for the `rootflags` GRUB2 environment variable.  The value
of this variable will be passed along as command-line arguments to
whatever kernel is chosen at boot.

Since post-image scripts do not have access to kconfig option values, we
need to build the GRUB2 environment file in the
`GRUB2_INSTALL_IMAGES_CMDS` script fragment instead.
2025-08-29 20:13:18 -05:00
Dustin 568397239b ci: Add CUSTOM_TARGET parameter
If a value is provided for the `CUSTOM_TARGET` parameter, the specified
target will be built first, before building the filesystem images.  This
provides a way to e.g. rebuild a specific package.
2025-08-29 20:13:18 -05:00
Dustin 4fa971e36e boot/grub2: Set terminfo dumb
GRUB seems to have trouble with line drawing on both the Raspberry Pi
and QEMU.
2025-08-29 20:13:18 -05:00
Dustin 1a33e711bb configs/*: Install GRUB terminfo module
So we can set `terminfo dumb` and hopefully get better output over the
serial console.
2025-08-29 20:13:18 -05:00
Dustin 3a0d599ff6 gen-grub-cfg: Support different kernel file names
Different architectures and/or configurations can use a different name
for the Linux kernel image file.  The `gen-grub-cfg.sh` shell script
needs to be able to identify the correct file name in the GRUB
configuration fragment it embeds in the root filesystem image.
2025-08-29 20:13:18 -05:00
Dustin 66af20213b board/qemu: Generate sdcard.img with post-image
In order to test AimeeOS A/B filesystem updates, we need a full disk
image just like the Raspberry Pi variant has.
2025-08-29 20:13:18 -05:00
Dustin d41ad4c55c ci: Add Jenkins pipeline 2025-08-29 20:13:14 -05:00
17 changed files with 517 additions and 7 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/_build

View File

@ -10,8 +10,12 @@ config AIMEEOS
select BR2_PACKAGE_COREUTILS
select BR2_PACKAGE_TAR
select BR2_PACKAGE_ZSTD
select BR2_PACKAGE_HOST_DOSFSTOOLS
select BR2_PACKAGE_HOST_GENIMAGE
select BR2_PACKAGE_HOST_MTOOLS
select BR2_TARGET_GRUB2
select BR2_PACKAGE_HOST_ZSTD
select BR2_PACKAGE_AIMEE_OS_UTILS
help
Enable all Aimee OS features.
@ -25,8 +29,12 @@ config AIMEEOS_RPI
select BR2_TARGET_UBOOT_NEEDS_OPENSSL
select BR2_TARGET_UBOOT_NEEDS_GNUTLS
select BR2_TARGET_GRUB2_ARM_EFI
select BR2_PACKAGE_HOST_DOSFSTOOLS
select BR2_PACKAGE_HOST_GENIMAGE
select BR2_PACKAGE_HOST_MTOOLS
help
Support running Aimee OS on Rasperry Pi devices
config AIMEEOS_DEFAULT_ROOTFLAGS
string "Default kernel command line argumens"
help
Additional command line arguments to pass to the kernel by default.
source "$BR2_EXTERNAL_AIMEEOS_PATH/package/aimee-os-utils/Config.in"

1
board/qemu/genimage.cfg Symbolic link
View File

@ -0,0 +1 @@
../raspberrypi3/genimage.cfg

18
board/qemu/post-image.sh Executable file
View File

@ -0,0 +1,18 @@
#!/bin/sh
set -e
BOARD_DIR=$(dirname "$0")
genimage_tmp=$(mktemp -d)
trap 'rm -rf "${genimage_tmp}"' EXIT
mkdir -p "${genimage_tmp}"/rootfs "${genimage_tmp}"/tmp
cd "${BINARIES_DIR}"
genimage \
--rootpath "${genimage_tmp}/rootfs" \
--tmppath "${genimage_tmp}/tmp" \
--inputpath "${BINARIES_DIR}" \
--outputpath "${BINARIES_DIR}" \
--config "${BOARD_DIR}"/genimage.cfg

View File

@ -3,10 +3,12 @@
vers=${BR2_EXTERNAL_AIMEEOS_VERSION}
br2_vers=${BR2_VERSION_FULL}
kernel_filename=$1
cat > "${TARGET_DIR}"/boot/grub.cfg <<EOF
menuentry "Aimee OS ${vers} (Buildroot ${br2_vers}) on \$dev" --class gnu-linux --id "id-\$partuuid" "\$dev" "\$partuuid" {
set root="\$2"
linux "/boot/zImage" root=PARTUUID=\$3 ro
linux "/boot/${kernel_filename}" root=PARTUUID=\$3 ro \$rootflags
initrd "/boot/initramfs.img.zst"
}
EOF

View File

@ -1,6 +1,8 @@
# vim: set ft=sh :
# vim: set sw=4 ts=4 sts=4 et:
terminfo dumb
load_env
regexp --set 1:disk '(.*),.*' $root
for dev in ($disk,gpt*); do

165
boot/initramfs/init-storage.sh Executable file
View File

@ -0,0 +1,165 @@
#!/bin/sh
# vim: set sw=4 ts=4 sts=4 et :
SUBVOLUMES='
/var
/var/log
/var/tmp
/etc
'
cleanup() {
if [ -n "${tmpdir}" ] && [ "${tmpdir}" != / ]; then
if mountpoint -q "${tmpdir}"; then
umount "${tmpdir}"
fi
rm -rf "${tmpdir}"
unset tmpdir
fi
}
copy_vol() {
dev="$1"
vol=$2
printf 'Copying %s contents to data volume\n' "${vol}" >&2
mount -o subvol="${vol#/}" "${dev}" "${tmpdir}" || exit
cp -au${VERBOSE+v} /sysroot/${vol#/}/. "${tmpdir}" || exit
umount "${tmpdir}"
}
format_dev() {
dev="$1"
partno=$(partition_number "${dev}")
if [ -n "${partno}" ]; then
disk="$(get_disk "${dev}")"
if [ -n "${disk}" ]; then
printf 'Resizing partition %d on disk %s\n' \
"${partno}" \
"${disk}" \
>&2
resize_partition "${disk}" "${partno}"
else
printf 'Could not find disk for device %s\n' \
"${dev}" \
>&2
fi
fi
printf 'Creating BTRFS filesystem on %s\n' "${dev}" >&2
mkfs.btrfs --quiet "${dev}" || exit
mount "${dev}" "${tmpdir}" || exit
for vol in ${SUBVOLUMES}; do
mkdir -p "${tmpdir}${vol%/*}" || exit
btrfs subvolume create "${tmpdir}${vol}" || exit
done
relabel_all
umount "${dev}" || exit
}
get_disk() {
_syspath=/sys/class/block/${1##*/}
[ -d "${_syspath}" ] || return 1
if [ ! -f "${_syspath}"/partition ]; then
readlink -f "${1}"
return $?
fi
_disk=$(readlink -f "${_syspath}"/..)
if [ -n "${_disk}" ]; then
printf '/dev/%s\n' "${_disk##*/}"
return 0
fi
return 1
}
has_fs() {
dev="$1"
fstype=$(blkid -o value -s TYPE "${dev}")
[ -n "${fstype}" ]
}
last_partition() {
cat /sys/class/block/"${1##*/}"/*/partition \
| sort -n \
| tail -n1
}
partition_number() {
cat /sys/class/block/${1##*/}/partition
}
relabel_all() {
if [ ! -d /sys/fs/selinux ] || [ ! -f /etc/selinux/config ]; then
return
fi
selinuxtype=$(. /etc/selinux/config && echo ${SELINUXTYPE})
find "${tmpdir}" | \
setfiles \
-v \
-F \
-m \
-r "${tmpdir}" \
-s \
/etc/selinux/${selinuxtype}/contexts/files/file_contexts
}
resize_partition() {
_disk="${1}"
_part="${2}"
_lastpart=$(last_partition "${_disk}")
if [ "${_part}" -ne "${_lastpart}" ]; then
printf 'Cannot resize %s, it is not the last partition on the disk\n' \
"${_dev}" \
>&2
return 1
fi
_uuid=$(sfdisk --part-uuid "${_disk}" "${_part}") || return $?
_type=$(sfdisk --part-type "${_disk}" "${_part}") || return $?
_label=$(sfdisk --part-label "${_disk}" "${_part}") || return $?
sfdisk --delete "${_disk}" "${_part}" || return $?
printf 'type=%s, uuid=%s, name="%s"\n' \
"${_type}" \
"${_uuid}" \
"${_label}" \
| sfdisk -N "${_part}" "${_disk}" --quiet --force \
|| return $?
partx -u "${_disk}"
}
setup_etc() {
dev="$1"
echo 'Initializing /etc overlay' >&2
mkdir -p /run/aimeeos/etc || return
mount -o subvol=etc "${dev}" /run/aimeeos/etc || return
mkdir -p /run/aimeeos/etc/rw /run/aimeeos/etc/work || return
mount -t overlay \
-o lowerdir=/sysroot/etc,upperdir=/run/aimeeos/etc/rw,workdir=/run/aimeeos/etc/work \
overlay \
/sysroot/etc
}
rootdev=$(findfs "$1")
datapart=$(findfs "${2:-PARTLABEL=aimeeos-data}")
if [ -b "${datapart}" ]; then
printf 'Found data partition: %s\n' "${datapart}" >&2
else
echo 'Could not identify data partition' >&2
exit 1
fi
trap cleanup INT TERM QUIT EXIT
tmpdir=/run/storinit
mkdir -p "${tmpdir}"
if ! has_fs "${datapart}"; then
format_dev "${datapart}"
fi
mkdir -p /sysroot
mount -o ro "${rootdev}" /sysroot || exit
setup_etc "${datapart}"
copy_vol "${datapart}" /var
exit 0

View File

@ -0,0 +1,27 @@
#!/bin/sh
mkdir -p \
/dev \
/proc \
/run \
/sys \
/sysroot \
&& :
mount -t devtmpfs devtmpfs /dev
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t tmpfs tmpfs /run
set -- $(cat /proc/cmdline)
for arg; do
case "${arg}" in
root=*)
root=${arg#root=}
;;
esac
done
init-storage "${root}"
exec switch_root /sysroot /sbin/init

113
boot/mkinitramfs.sh Executable file
View File

@ -0,0 +1,113 @@
#!/bin/sh
if [ $(id -u) != 0 ]; then
exec "${HOST_DIR}"/bin/fakeroot "$0" "$@"
fi
export PATH="${HOST_DIR}:${PATH}"
TARGET_DIR=$1
WORKDIR=$(mktemp -d)
OUTDIR="${WORKDIR}"/initramfs
LIB_CACHE="${WORKDIR}"/libs.cache
PKGDIR="${0%/*}"
trap 'rm -rf "${WORKDIR}"' INT QUIT TERM EXIT
cache_libs() {
find \
"${TARGET_DIR}"/usr/lib \
"${TARGET_DIR}"/usr/lib64 \
\( -type f -o -type l \) \
-name '*.so*' \
| sed "s@${TARGET_DIR}@@" \
> "${LIB_CACHE}"
}
bin_install() {
for arg; do
arg=${arg#/}
[ -e "${OUTDIR}/${arg}" ] && continue
mkdir -p "${OUTDIR}/${arg%/*}"
cp -a "${TARGET_DIR}/${arg}" "${OUTDIR}/${arg}"
if [ -h "${TARGET_DIR}/${arg}" ]; then
bin_install "$(realpath --relative-to "${TARGET_DIR}" "${TARGET_DIR}/${arg}")"
elif [ -f "${TARGET_DIR}/${arg}" ]; then
readelf --dynamic "${TARGET_DIR}/${arg}" \
| awk '$2=="(NEEDED)"{gsub(/\[|\]/,"",$5); print $5}' \
| while IFS= read -r lib; do
path="$(grep "${lib}"'$' "${LIB_CACHE}")"
if [ -z "${path}" ]; then
printf 'ERROR could not resolve shared library %s\n' "${lib}" >&2
return 1
fi
bin_install "${path}"
done
elif [ ! -e "${TARGET_DIR}/${arg}" ]; then
printf 'ERROR could not find /%s to copy\n' "${arg}" >&2
return 1
fi
done
}
mk_skel() {
mkdir -p "${OUTDIR}"/dev
mknod -m 0622 "${OUTDIR}"/dev/console c 5 1
mkdir -p \
"${OUTDIR}"/usr \
"${OUTDIR}"/usr/bin \
"${OUTDIR}"/usr/sbin \
"${OUTDIR}"/usr/lib
ln -s usr/bin "${OUTDIR}"/bin
ln -s usr/sbin "${OUTDIR}"/sbin
ln -s usr/lib "${OUTDIR}"/lib
if [ -h "${TARGET_DIR}"/usr/lib64 ]; then
cp -P "${TARGET_DIR}"/usr/lib64 "${OUTDIR}"/usr
fi
if [ -h "${TARGET_DIR}"/lib64 ]; then
cp -P "${TARGET_DIR}"/lib64 "${OUTDIR}"
fi
}
rm -rf "${OUTDIR}"
mk_skel || exit
cache_libs || exit
bin_install \
/bin/cat \
/bin/cp \
/bin/ls \
/bin/mkdir \
/bin/mount \
/bin/rm \
/bin/sh \
/bin/sort \
/bin/tail \
/bin/umount \
/usr/bin/btrfs \
/usr/bin/mkfs.btrfs \
/usr/bin/mountpoint \
/usr/bin/readlink \
/usr/sbin/blkid \
/usr/sbin/findfs \
/usr/sbin/partx \
/usr/sbin/sfdisk \
/usr/sbin/switch_root \
|| exit
if [ -e "${TARGET_DIR}"/usr/bin/setfiles ]; then
bin_install /usr/bin/setfiles || exit
fi
install "${PKGDIR}"/initramfs/initramfs-init.sh "${OUTDIR}"/init || exit
install "${PKGDIR}"/initramfs/init-storage.sh "${OUTDIR}"/usr/bin/init-storage || exit
mkdir -p "${TARGET_DIR}"/boot
(cd "${OUTDIR}" && find . -mindepth 1 \
| LC_ALL=C sort \
| cpio --reproducible --quiet -o -H newc \
| zstd \
) > "${TARGET_DIR}"/boot/initramfs.img.zst

74
ci/Jenkinsfile vendored Normal file
View File

@ -0,0 +1,74 @@
pipeline {
parameters {
booleanParam 'CLEAN_BUILD'
string 'CUSTOM_TARGET'
}
options {
disableConcurrentBuilds()
}
agent {
kubernetes {
yamlFile 'ci/podTemplate.yaml'
yamlMergeStrategy merge()
workspaceVolume persistentVolumeClaimWorkspaceVolume(
claimName: 'buildroot-aimeeos'
)
defaultContainer 'build'
}
}
environment {
BR2_CCACHE_DIR = "${env.JENKINS_AGENT_WORKDIR}/br2-ccache"
}
stages {
stage('Clean') {
when {
expression {
return params.CLEAN_BUILD
}
}
steps {
sh 'git clean -fdx'
}
}
stage('Prepare') {
steps {
container('jnlp') {
sh 'if [ ! -d buildroot ]; then git clone https://gitlab.com/buildroot.org/buildroot.git -b 2025.05.x --depth 1; else git -C buildroot pull; fi'
}
}
}
stage('Build') {
steps {
sh 'make -C buildroot O="${PWD}"/_build BR2_EXTERNAL="${PWD}" aimeeos_qemu_aarch64_defconfig'
script {
if (params.CUSTOM_TARGET) {
sh "make -C _build '${CUSTOM_TARGET}'"
}
}
sh 'make -C _build'
}
post {
success {
dir('_build') {
archiveArtifacts('.config')
}
dir('_build/images') {
sh 'zstd -f firmware.img'
sh 'zstd -f sdcard.img'
archiveArtifacts([
'firmware.img.zst',
'rootfs.squashfs',
'sdcard.img.zst',
].join(','))
}
}
}
}
}
}

19
ci/podTemplate.yaml Normal file
View File

@ -0,0 +1,19 @@
spec:
containers:
- name: build
image: git.pyrocufflink.net/containerimages/buildroot
resources:
limits: &resources
cpu: 6
memory: 12Gi
requests: *resources
volumeMounts:
- mountPath: /etc/ssh/ssh_known_hosts
name: ssh-known-hosts
subPath: ssh_known_hosts
securityContext:
fsGroupChangePolicy: OnRootMismatch
volumes:
- name: ssh-known-hosts
configMap:
name: ssh-known-hosts

View File

@ -3,6 +3,7 @@ BR2_TOOLCHAIN_BUILDROOT_VENDOR="aimeeos"
BR2_GLOBAL_PATCH_DIR="board/qemu/patches"
BR2_DOWNLOAD_FORCE_CHECK_HASHES=y
BR2_INIT_SYSTEMD=y
BR2_ROOTFS_POST_IMAGE_SCRIPT="$(BR2_EXTERNAL_AIMEEOS_PATH)/board/qemu/post-image.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
@ -11,4 +12,5 @@ BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
# BR2_PACKAGE_BUSYBOX is not set
# BR2_TARGET_ROOTFS_TAR is not set
AIMEEOS=y
BR2_TARGET_GRUB2_BUILTIN_MODULES_EFI="boot configfile echo efi_gop fat gzio linux loadenv minicmd normal part_gpt probe regexp squash4 test zstd"
AIMEEOS_DEFAULT_ROOTFLAGS="systemd.mask=serial-getty@ttyAMA0 systemd.debug_shell systemd.default_debug_tty=ttyAMA0"
BR2_TARGET_GRUB2_BUILTIN_MODULES_EFI="boot configfile echo efi_gop fat gzio linux loadenv minicmd normal part_gpt probe regexp squash4 terminfo test zstd"

View File

@ -23,7 +23,7 @@ BR2_PACKAGE_RPI_FIRMWARE_VARIANT_PI=y
BR2_PACKAGE_RPI_FIRMWARE_CMDLINE_FILE="$(BR2_EXTERNAL_AIMEEOS_PATH)/board/raspberrypi3/cmdline.txt"
BR2_PACKAGE_RPI_FIRMWARE_CONFIG_FILE="$(BR2_EXTERNAL_AIMEEOS_PATH)/board/raspberrypi3/config.txt"
# BR2_TARGET_ROOTFS_TAR is not set
BR2_TARGET_GRUB2_BUILTIN_MODULES_EFI="boot configfile echo efi_gop fat gzio linux loadenv minicmd normal part_gpt probe regexp squash4 test zstd"
BR2_TARGET_GRUB2_BUILTIN_MODULES_EFI="boot configfile echo efi_gop fat gzio linux loadenv minicmd normal part_gpt probe regexp squash4 terminfo test zstd"
BR2_TARGET_UBOOT_BOARD_DEFCONFIG="rpi_3_32b"
BR2_PACKAGE_HOST_KMOD_XZ=y
AIMEEOS=y

View File

@ -1,13 +1,50 @@
ifeq ($(AIMEEOS),y)
# Disable the default fstab
SKELETON_INIT_SYSTEMD_ROOT_RO_OR_RW =
# Disable the default var.mount
SKELETON_INIT_SYSTEMD_ROOTFS_PRE_CMD_HOOKS =
# Enable required kernel options for Aimee OS storage
define AIMEEOS_LINUX_CONFIG_FIXUPS
$(call KCONFIG_ENABLE_OPT,CONFIG_BTRFS_FS)
$(call KCONFIG_ENABLE_OPT,CONFIG_BLK_DEV_INITRD)
endef
LINUX_KCONFIG_FIXUP_CMDS += $(AIMEEOS_LINUX_CONFIG_FIXUPS)
# Generate the initramfs image after building the target
BR2_ROOTFS_POST_BUILD_SCRIPT += $(BR2_EXTERNAL_AIMEEOS_PATH)/boot/mkinitramfs.sh
# Overwrite the grub.cfg provided by Buildroot with our own.
define AIMEEOS_GRUB2_INSTALL_IMAGES_CMDS
$(foreach tuple, $(GRUB2_TUPLES-y), \
$(INSTALL) -D -m 0644 $(BR2_EXTERNAL_AIMEEOS_PATH)/boot/grub2/grub.cfg $(GRUB2_CFG_$(tuple))
)
$(HOST_DIR)/bin/grub-editenv $(BINARIES_DIR)/efi-part/EFI/BOOT/grubenv set \
default=0 \
timeout=3 \
rootflags=$(AIMEEOS_DEFAULT_ROOTFLAGS)
endef
GRUB2_INSTALL_IMAGES_CMDS += $(AIMEEOS_GRUB2_INSTALL_IMAGES_CMDS)
ifneq ($(BR2_LINUX_KERNEL_IMAGE_TARGET_CUSTOM),)
AIMEEOS_KERNEL_FILENAME = $(BR2_LINUX_KERNEL_IMAGE_TARGET_CUSTOM)
else ifeq ($(BR2_LINUX_KERNEL_IMAGE),y)
AIMEEOS_KERNEL_FILENAME = Image
else ifeq ($(BR2_LINUX_KERNEL_IMAGEZ),y)
AIMEEOS_KERNEL_FILENAME = zImage
else ifeq ($(BR2_LINUX_KERNEL_VMLINUX),y)
AIMEEOS_KERNEL_FILENAME = vmlinux
else
$(error "Must define a Linux kernel target")
endif
# Generate the grub.cfg stub for the kernel embedded in rootfs.squashfs
define AIMEEOS_GEN_GRUB_CFG
$(BR2_EXTERNAL_AIMEEOS_PATH)/boot/grub2/gen-grub-cfg.sh
$(BR2_EXTERNAL_AIMEEOS_PATH)/boot/grub2/gen-grub-cfg.sh $(AIMEEOS_KERNEL_FILENAME)
endef
LINUX_TARGET_FINALIZE_HOOKS += AIMEEOS_GEN_GRUB_CFG
endif
include $(sort $(wildcard $(BR2_EXTERNAL_AIMEEOS_PATH)/package/*/*.mk))

View File

@ -0,0 +1,8 @@
config BR2_PACKAGE_AIMEE_OS_UTILS
bool
select BR2_PACKAGE_BTRFS_PROGS
select BR2_PACKAGE_UTIL_LINUX
select BR2_PACKAGE_UTIL_LINUX_BINARIES
select BR2_PACKAGE_UTIL_LINUX_MOUNTPOINT
select BR2_PACKAGE_UTIL_LINUX_PARTX
select BR2_PACKAGE_UTIL_LINUX_SWITCH_ROOT

View File

@ -0,0 +1,21 @@
################################################################################
#
# Aimee OS Utils
#
################################################################################
AIMEE_OS_UTILS_VERSION = 2.0
AIMEE_OS_UTILS_LICENSE = GPL-3.0+
AIMEE_OS_UTILS_DEPENDENCIES = \
host-fakeroot \
btrfs-progs \
AIMEE_OS_UTILS_SOURCE =
define AIMEE_OS_UTILS_INSTALL_INIT_SYSTEMD
$(INSTALL) -D -m u=rw,go=r \
$(AIMEE_OS_UTILS_PKGDIR)/var.mount \
$(TARGET_DIR)/usr/lib/systemd/system/var.mount
endef
$(eval $(generic-package))

View File

@ -0,0 +1,12 @@
[Unit]
Description=/var
DefaultDependencies=no
Conflicts=umount.target
Before=local-fs.target umount.target
After=swap.target
[Mount]
What=PARTLABEL=aimeeos-data
Where=/var
Type=btrfs
Options=subvol=var,nosuid,nodev,noexec