diff --git a/Makefile b/Makefile index 69957b8..f940a4f 100644 --- a/Makefile +++ b/Makefile @@ -1,29 +1,21 @@ .POSIX: -PREFIX = /usr +PREFIX = /usr/local BINDIR = ${PREFIX}/bin -DATADIR = ${PREFIX}/share -MANDIR = ${PREFIX}/share/man +LIBDIR = ${PREFIX}/lib install: - mkdir -p ${DESTDIR}${DATADIR}/tinyramfs \ - ${DESTDIR}${MANDIR}/man5 \ - ${DESTDIR}${MANDIR}/man8 \ - ${DESTDIR}${MANDIR}/man7 \ - ${DESTDIR}${BINDIR} - cp -R hooks ${DESTDIR}${DATADIR}/tinyramfs - cp device-helper ${DESTDIR}${DATADIR}/tinyramfs - cp init ${DESTDIR}${DATADIR}/tinyramfs - cp tinyramfs ${DESTDIR}${BINDIR}/tinyramfs - cp docs/tinyramfs.8 ${DESTDIR}${MANDIR}/man8 - cp docs/tinyramfs.hooks.7 ${DESTDIR}${MANDIR}/man7 - cp docs/tinyramfs.cmdline.7 ${DESTDIR}${MANDIR}/man7 - cp docs/tinyramfs.config.5 ${DESTDIR}${MANDIR}/man5 + mkdir -p ${DESTDIR}${BINDIR} + mkdir -p ${DESTDIR}${LIBDIR}/tinyramfs + cp -f tinyramfs ${DESTDIR}${BINDIR}/ + cp -f lib/init.sh ${DESTDIR}${LIBDIR}/tinyramfs/ + cp -f lib/helper.sh ${DESTDIR}${LIBDIR}/tinyramfs/ + cp -f lib/common.sh ${DESTDIR}${LIBDIR}/tinyramfs/ + cp -R hook ${DESTDIR}${LIBDIR}/tinyramfs/hook.d uninstall: rm -f ${DESTDIR}${BINDIR}/tinyramfs - rm -rf ${DESTDIR}${DATADIR}/tinyramfs - rm -f ${DESTDIR}${MANDIR}/man8/tinyramfs.8 - rm -f ${DESTDIR}${MANDIR}/man7/tinyramfs.hooks.7 - rm -f ${DESTDIR}${MANDIR}/man7/tinyramfs.cmdline.7 - rm -f ${DESTDIR}${MANDIR}/man5/tinyramfs.config.5 + rm -rf ${DESTDIR}${LIBDIR}/tinyramfs + +check: + (cd test && ./check.sh) diff --git a/docs/tinyramfs.8 b/docs/tinyramfs.8 deleted file mode 100644 index 8d0d229..0000000 --- a/docs/tinyramfs.8 +++ /dev/null @@ -1,91 +0,0 @@ -.\" Generated by scdoc 1.11.1 -.\" Complete documentation for this program is not available as a GNU info page -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.nh -.ad l -.\" Begin generated content: -.TH "tinyramfs" "8" "2021-05-10" -.P -.SH NAME -.P -Tinyramfs - tiny initramfs written in POSIX shell -.P -.SH SYNOPSIS -.P -\fBtinyramfs\fR [option].\&.\&.\& -.P -.SH DESCRIPTION -.P -Tinyramfs is a simple, extensible and modular initramfs generator tool written -with focus on portability.\& -.P -.SH OPTIONS -.P -\fB-o\fR, \fB--output\fR -.P -.RS 4 -Specify output location where initramfs image will be stored.\& -.P -.RE -\fB-c\fR, \fB--config\fR -.P -.RS 4 -Specify config location.\& Default is \fB/etc/tinyramfs/config\fR.\& -.P -.RE -\fB-k\fR, \fB--kernel\fR -.P -.RS 4 -Specify kernel version.\& Useful for bootstraping future system with modular -kernel.\& Default is current kernel version.\& -.P -.RE -\fB-m\fR, \fB--modules\fR -.P -.RS 4 -Specify directory where modules stored.\& Default is \fB/lib/modules\fR.\& -This option has no effect if \fBmonolith\fR or \fBhostonly\fR were enabled in config.\& -.P -.RE -\fB-H\fR, \fB--hooks\fR -.P -.RS 4 -Specify additional hooks location.\& Default is \fB/usr/share/tinyramfs/hooks\fR -and \fB/etc/tinyramfs/hooks\fR.\& -.P -.RE -\fB-D\fR, \fB--helper\fR -.P -.RS 4 -Specify location to device helper.\& Default is \fB/usr/share/tinyramfs/device-helper\fR.\& -.P -.RE -\fB-I\fR, \fB--init\fR -.P -.RS 4 -Specify location to init script.\& Default is \fB/usr/share/tinyramfs/init\fR.\& -.P -.RE -\fB-d\fR, \fB--debug\fR -.P -.RS 4 -Enable debug mode.\& Useful for reporting bugs in build stage.\& -.P -.RE -\fB-f\fR, \fB--force\fR -.P -.RS 4 -Forcefully overwrite initramfs image.\& -.P -.RE -.SH NOTES -.P -If you have modular kernel and you use \fBbusybox modrobe\fR to handle modules, you -must note that \fBbusybox modprobe\fR doesn't have ability to install soft -dependencies of modules (i.\&e modules.\&softdep).\& You must install them yourself -using hooks.\& See \fBtinyramfs.\&hooks\fR(7) how to do it.\& -.P -.SH SEE ALSO -.P -\fBtinyramfs.\&config\fR(5) \fBtinyramfs.\&cmdline\fR(7) \fBtinyramfs.\&hooks\fR(7) diff --git a/docs/tinyramfs.8.scd b/docs/tinyramfs.8.scd deleted file mode 100644 index f2f05f1..0000000 --- a/docs/tinyramfs.8.scd +++ /dev/null @@ -1,66 +0,0 @@ -tinyramfs(8) - -# NAME - -Tinyramfs - tiny initramfs written in POSIX shell - -# SYNOPSIS - -*tinyramfs* [option]... - -# DESCRIPTION - -Tinyramfs is a simple, extensible and modular initramfs generator tool written -with focus on portability. - -# OPTIONS - -*-o*, *--output* - - Specify output location where initramfs image will be stored. - -*-c*, *--config* - - Specify config location. Default is */etc/tinyramfs/config*. - -*-k*, *--kernel* - - Specify kernel version. Useful for bootstraping future system with modular - kernel. Default is current kernel version. - -*-m*, *--modules* - - Specify directory where modules stored. Default is */lib/modules*. - This option has no effect if *monolith* or *hostonly* were enabled in config. - -*-H*, *--hooks* - - Specify additional hooks location. Default is */usr/share/tinyramfs/hooks* - and */etc/tinyramfs/hooks*. - -*-D*, *--helper* - - Specify location to device helper. Default is */usr/share/tinyramfs/device-helper*. - -*-I*, *--init* - - Specify location to init script. Default is */usr/share/tinyramfs/init*. - -*-d*, *--debug* - - Enable debug mode. Useful for reporting bugs in build stage. - -*-f*, *--force* - - Forcefully overwrite initramfs image. - -# NOTES - -If you have modular kernel and you use *busybox modrobe* to handle modules, you -must note that *busybox modprobe* doesn't have ability to install soft -dependencies of modules (i.e modules.softdep). You must install them yourself -using hooks. See *tinyramfs.hooks*(7) how to do it. - -# SEE ALSO - -*tinyramfs.config*(5) *tinyramfs.cmdline*(7) *tinyramfs.hooks*(7) diff --git a/docs/tinyramfs.cmdline.7 b/docs/tinyramfs.cmdline.7 deleted file mode 100644 index d6ba91f..0000000 --- a/docs/tinyramfs.cmdline.7 +++ /dev/null @@ -1,213 +0,0 @@ -.\" Generated by scdoc 1.11.0 -.\" Complete documentation for this program is not available as a GNU info page -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.nh -.ad l -.\" Begin generated content: -.TH "tinyramfs.cmdline" "7" "2020-09-10" -.P -.SH NAME -.P -Tinyramfs - kernel command-line parameters -.P -.SH DESCRIPTION -.P -Tinyramfs provides a way to control configuration dynamically via -kernel parameters without needing to regenerate initramfs image.\& -.P -.SS MAN PAGE SYNTAX -.P -.nf -.RS 4 -| - OR -\&.\&.\&. - can be repeated -.fi -.RE -.P -.SH GENERAL PARAMETERS -.P -\fBdebug\fR=1 -.P -.RS 4 -Enable debug mode.\& -.P -.RE -\fBbreak\fR=breakpoint -.P -.RS 4 -Specify breakpoint where shell should be invoked.\& Useful for -debugging.\& List of builtin breakpoints: -.P -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -root -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -boot - -.RE -.P -Hooks can provide their own breakpoints.\& See source code of hooks -for more information.\& -.P -.RE -\fBroot\fR=UUID|LABEL|/dev/*|PARTUUID -.P -.RS 4 -Specify which way tinyramfs will use to look up root filesystem.\& -.P -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -UUID - lookup device by uuid -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -LABEL - lookup device by label -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -/dev/* - lookup device by full path -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -PARTUUID - lookup device by partition uuid - -.RE -.P -Initramfs must contain \fBblkid\fR(8) for ability to use UUID, LABEL, -PARTUUID.\& Note that PARTUUID only supported in util-linux \fBblkid\fR(8).\& -.P -.RE -\fBroot_type\fR|\fBrootfstype\fR=type -.P -.RS 4 -Explicitly set root filesystem type.\& Kernel must support specified type.\& -.P -.RE -\fBrootdelay\fR=delay -.P -.RS 4 -Specify maximum number of seconds to wait for root device.\& Default is 30.\& -.P -.RE -\fBroot_opts\fR|\fBrootflags\fR=opts -.RS 4 -.P -See \fBfstab\fR(5) fourth field.\& -.P -.RE -.SH HOOKS PARAMETERS -.P -Initramfs must contain appropriate hooks for ability to use below parameters.\& -.P -.SS LVM -.P -\fBlvm_tag\fR=tag -.P -.RS 4 -Specify LVM tag which will be used to trigger LVM.\& This option will be -ignored if \fBlvm_name\fR/\fBlvm_group\fR was specified.\& -.P -.RE -\fBlvm_name\fR=name -.P -.RS 4 -Specify LVM name which will be used to trigger LVM.\& \fBlvm_group\fR must be -specified.\& -.P -.RE -\fBlvm_group\fR=group -.P -.RS 4 -Specify LVM group which will be used to trigger LVM.\& -.P -.RE -\fBlvm_discard\fR=1 -.P -.RS 4 -Pass issue_discards to lvm.\& Leave empty to disable.\& Useful for SSD's.\& -.P -.RE -.SS LUKS -.P -\fBluks_name\fR=name -.P -.RS 4 -Specify which name will be registered to mapping table after cryptsetup -unlocks LUKS root.\& -.P -.RE -\fBluks_root\fR=UUID|LABEL|/dev/*|PARTUUID -.P -.RS 4 -See \fBroot\fR for details.\& -.P -.RE -\fBluks_discard\fR=1 -.P -.RS 4 -Pass --allow-discards to \fBcryptsetup\fR.\& Leave empty to disable.\& Useful for -SSD's, but you must know that security will be decreased.\& -.P -.RE -.SH EXAMPLES -.P -.SS ROOT -.P -.nf -.RS 4 -vmlinuz initrd=initramfs root=/dev/sda1 \&.\&.\&. -.fi -.RE -.P -.SS DISABLE DISCARD -.P -.nf -.RS 4 -vmlinuz initrd=\\initramfs luks_discard= lvm_discard= \&.\&.\&. -.fi -.RE -.P -.SS PASS ARGUMENTS TO REAL INIT -.P -.nf -.RS 4 -vmlinuz initrd=\\initramfs \&.\&.\&. -- args -.fi -.RE -.P -.SH SEE ALSO -.P -\fBtinyramfs\fR(8) \fBtinyramfs.\&config\fR(5) \fBtinyramfs.\&hooks\fR(7) diff --git a/docs/tinyramfs.cmdline.7.scd b/docs/tinyramfs.cmdline.7.scd deleted file mode 100644 index 31222a9..0000000 --- a/docs/tinyramfs.cmdline.7.scd +++ /dev/null @@ -1,122 +0,0 @@ -tinyramfs.cmdline(7) - -# NAME - -Tinyramfs - kernel command-line parameters - -# DESCRIPTION - -Tinyramfs provides a way to control configuration dynamically via -kernel parameters without needing to regenerate initramfs image. - -## MAN PAGE SYNTAX - -``` -| - OR -... - can be repeated -``` - -# GENERAL PARAMETERS - -*debug*=1 - - Enable debug mode. - -*break*=breakpoint - - Specify breakpoint where shell should be invoked. Useful for - debugging. List of builtin breakpoints: - - - root - - boot - - Hooks can provide their own breakpoints. See source code of hooks - for more information. - -*root*=UUID|LABEL|/dev/\*|PARTUUID - - Specify which way tinyramfs will use to look up root filesystem. - - - UUID - lookup device by uuid - - LABEL - lookup device by label - - /dev/\* - lookup device by full path - - PARTUUID - lookup device by partition uuid - - Initramfs must contain *blkid*(8) for ability to use UUID, LABEL, - PARTUUID. Note that PARTUUID only supported in util-linux *blkid*(8). - -*root_type*|*rootfstype*=type - - Explicitly set root filesystem type. Kernel must support specified type. - -*rootdelay*=delay - - Specify maximum number of seconds to wait for root device. Default is 30. - -*root_opts*|*rootflags*=opts - - See *fstab*(5) fourth field. - -# HOOKS PARAMETERS - -Initramfs must contain appropriate hooks for ability to use below parameters. - -## LVM - -*lvm_tag*=tag - - Specify LVM tag which will be used to trigger LVM. This option will be - ignored if *lvm_name*/*lvm_group* was specified. - -*lvm_name*=name - - Specify LVM name which will be used to trigger LVM. *lvm_group* must be - specified. - -*lvm_group*=group - - Specify LVM group which will be used to trigger LVM. - -*lvm_discard*=1 - - Pass issue_discards to lvm. Leave empty to disable. Useful for SSD's. - -## LUKS - -*luks_name*=name - - Specify which name will be registered to mapping table after cryptsetup - unlocks LUKS root. - -*luks_root*=UUID|LABEL|/dev/\*|PARTUUID - - See *root* for details. - -*luks_discard*=1 - - Pass --allow-discards to *cryptsetup*. Leave empty to disable. Useful for - SSD's, but you must know that security will be decreased. - -# EXAMPLES - -## ROOT - -``` -vmlinuz initrd=\initramfs root=/dev/sda1 ... -``` - -## DISABLE DISCARD - -``` -vmlinuz initrd=\\initramfs luks_discard= lvm_discard= ... -``` - -## PASS ARGUMENTS TO REAL INIT - -``` -vmlinuz initrd=\\initramfs ... -- args -``` - -# SEE ALSO - -*tinyramfs*(8) *tinyramfs.config*(5) *tinyramfs.hooks*(7) diff --git a/docs/tinyramfs.config.5 b/docs/tinyramfs.config.5 deleted file mode 100644 index b1e14c7..0000000 --- a/docs/tinyramfs.config.5 +++ /dev/null @@ -1,469 +0,0 @@ -.\" Generated by scdoc 1.11.0 -.\" Complete documentation for this program is not available as a GNU info page -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.nh -.ad l -.\" Begin generated content: -.TH "tinyramfs.config" "5" "2020-09-07" -.P -.SH NAME -.P -Tinyramfs - configuration file -.P -.SH SYNOPSIS -.P -\fB/etc/tinyramfs/config\fR -.P -.SH DESCRIPTION -.P -Tinyramfs configuration file is a list of environment variables.\& -Each variable must be written in POSIX way, bashism not allowed.\& -.P -Example: -.P -.nf -.RS 4 -key=value -.fi -.RE -.P -If value contains spaces it must must be quoted.\& -.P -.nf -.RS 4 -key="value value2" -.fi -.RE -.P -If value contains special symbols like $, it must be escaped -or quoted using single quotes.\& -.P -.nf -.RS 4 -key=\\$value -key='$value' -.fi -.RE -.P -If line exceeded maximum space on your display and you want to make it -more readable, you can concatenate them.\& -.P -.nf -.RS 4 -key=value -key="${key}value" -.fi -.RE -.P -If you want to temporary undefine variable without actually deleting it, -you can simply prepend #.\& -.P -.nf -.RS 4 -#key=value -.fi -.RE -.P -.SS MAN PAGE SYNTAX -.P -.nf -.RS 4 -| - OR -* - any value -[a] - optional value -\&.\&.\&. - can be repeated -.fi -.RE -.P -.SH GENERAL OPTIONS -.P -\fBmonolith\fR=1 -.P -.RS 4 -Monolithic kernel means kernel with builtin modules.\& -If you didn't build kernel yourself, then in most cases you have -modular kernel and you don't need to enable this option.\& To check -if you have monolithic you need to check if \fB/lib/modules//modules\fR exist.\& If this directory doesn't exist you probably -have monolithic kernel which means you need to set \fBmonolith\fR to \fB1\fR.\& -.P -.RE -\fBhostonly\fR=1 -.P -.RS 4 -Hostonly mode enumerates \fBsysfs\fR(5) and copies only neccessary modules -instead of copying all modules.\& Which means that this mode can dramatically -reduce initramfs size.\& This option will be ignored if \fBmonolith\fR was set -to \fB1\fR.\& -.P -.RE -\fBcompress\fR=command [args .\&.\&.\&] -.P -.RS 4 -Specify which command will be used to compress initramfs image.\& -There is a lot of commands you can use, such as: -.P -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -xz -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -zst (if supported by kernel) -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -gzip -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -bzip2 -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -and many more .\&.\&.\& - -.RE -.P -You can set compression level by specifing -[0-9] in args.\& -For example - gzip -9.\& -.P -.RE -\fBroot\fR=UUID|LABEL|/dev/*|PARTUUID -.P -.RS 4 -Specify which way tinyramfs will use to look up root filesystem.\& -.P -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -UUID - lookup device by uuid -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -LABEL - lookup device by label -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -/dev/* - lookup device by full path -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -PARTUUID - lookup device by partition uuid - -.RE -.P -You must install \fBblkid\fR(8) (avalable in toybox, busybox, util-linux) -for ability to use UUID, LABEL, PARTUUID.\& Note that PARTUUID only -supported in util-linux \fBblkid\fR(8).\& -.P -.RE -\fBroot_type\fR=type -.P -.RS 4 -Explicitly set root filesystem type instead of automatically discovering via -/proc/mounts.\& This option must be specified if you booted from Live CD.\& -.P -.RE -\fBroot_opts\fR=opts -.RS 4 -.P -See \fBfstab\fR(5) fourth field.\& -.P -.RE -\fBhooks\fR=hook [hook .\&.\&.\&] -.P -.RS 4 -Hooks provide a flexible way to extend tinyramfs with custom scripts.\& -You must know that \fBhooks are launched in the order in which they are -specified\fR.\& List of shipped by default hooks: -.P -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -lvm - LVM support -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -luks - LUKS support -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -mdev - mdev support -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -proc - CONFIG_UEVENT_HELPER support -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -mdevd - mdevd support -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -eudev - eudev support -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -keymap - keymap support -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -systemd-udevd - systemd udevd support - -.RE -.P -See below how to use them.\& -If hook doesn't have options, then it's not yet documented or can be used -"as is".\& -.P -More detailed information and how to write your own hooks described in -\fBtinyramfs.\&hooks\fR(7).\& -.P -.RE -.SH HOOKS OPTIONS -.P -.SS LVM -.P -\fBlvm_tag\fR=tag -.P -.RS 4 -Specify LVM tag which will be used to trigger LVM.\& This option will be -ignored if \fBlvm_name\fR/\fBlvm_group\fR was specified.\& -.P -.RE -\fBlvm_name\fR=name -.P -.RS 4 -Specify LVM name which will be used to trigger LVM.\& \fBlvm_group\fR must be -specified.\& -.P -.RE -\fBlvm_group\fR=group -.P -.RS 4 -Specify LVM group which will be used to trigger LVM.\& -.P -.RE -\fBlvm_config\fR=1 -.P -.RS 4 -Include \fB/etc/lvm/lvm.\&conf\fR in initramfs.\& -.P -.RE -\fBlvm_discard\fR=1 -.P -.RS 4 -Pass issue_discards to lvm.\& Useful for SSD's.\& -.P -.RE -.SS LUKS -.P -\fBluks_key\fR=/path/to/key -.RS 4 -.P -Specify location to key.\& -GPG-encrypted key currently not supported.\& -.P -.RE -\fBluks_name\fR=name -.P -.RS 4 -Specify which name will be registered to mapping table after cryptsetup -unlocks LUKS root.\& -.P -.RE -\fBluks_root\fR=UUID|LABEL|/dev/*|PARTUUID -.P -.RS 4 -See \fBroot\fR for details.\& -.P -.RE -\fBluks_header\fR=/path/to/header -.P -.RS 4 -Specify location to detached header.\& -.P -.RE -\fBluks_discard\fR=1 -.P -.RS 4 -Pass --allow-discards to \fBcryptsetup\fR.\& Useful for SSD's, but you must know -that security will be decreased.\& -.P -.RE -.SS KEYMAP -.P -\fBkeymap_path\fR=/path/to/keymap -.P -.RS 4 -Specify location to binary keymap.\& -Currently, this hook supports loading keymap only via busybox loadkmap.\& -kbd loadkeys not supported.\& -.P -.RE -.SH EXAMPLES -.P -Remember, these just examples !\& \fIDon't copy blindly\fR !\& Your configuration may -(and should) differ.\& -.P -.SS ROOT -.P -.nf -.RS 4 -hooks=eudev -root=/dev/sda1 -.fi -.RE -.P -.SS ROOT + MONOLITH + PROC (CONFIG_UEVENT_HELPER) -.P -.nf -.RS 4 -hooks=proc -monolith=1 -root=/dev/nvme0n1p1 -.fi -.RE -.P -.SS ROOT + COMPRESS -.P -.nf -.RS 4 -hostonly=1 -hooks=mdevd -compress="gzip -9" -root=PARTUUID=8e05009d-a1d5-4fdb-b407-b0e79360555c -.fi -.RE -.P -.SS ROOT + KEYMAP -.P -.nf -.RS 4 -root_type=f2fs -hooks="eudev keymap" -root=UUID=13bcb7cc-8fe5-4f8e-a1fe-e4b5b336f3ef -keymap_path=/usr/share/bkeymaps/colemak/en-latin9\&.bmap -.fi -.RE -.P -.SS ROOT + LUKS -.P -.nf -.RS 4 -hooks="mdev luks" -root=LABEL=my_root - -luks_discard=1 -luks_key=/root/key -luks_header=/root/header -luks_root=PARTUUID=35f923c5-083a-4950-a4da-e611d0778121 -.fi -.RE -.P -.SS ROOT + LVM + LUKS -.P -.nf -.RS 4 -compress="lz4 -9" -hooks="eudev lvm luks" -root=/dev/disk/by-uuid/aa82d7bb-ab2b-4739-935f-fd8a5c9a6cb0 - -luks_discard=1 -luks_root=/dev/sdb2 - -lvm_config=1 -lvm_discard=1 -lvm_name=lvm1 -lvm_group=lvm_grp2 -.fi -.RE -.P -.SH SEE ALSO -.P -\fBtinyramfs\fR(8) \fBtinyramfs.\&cmdline\fR(7) \fBtinyramfs.\&hooks\fR(7) diff --git a/docs/tinyramfs.config.5.scd b/docs/tinyramfs.config.5.scd deleted file mode 100644 index 3691bfa..0000000 --- a/docs/tinyramfs.config.5.scd +++ /dev/null @@ -1,263 +0,0 @@ -tinyramfs.config(5) - -# NAME - -Tinyramfs - configuration file - -# SYNOPSIS - -*/etc/tinyramfs/config* - -# DESCRIPTION - -Tinyramfs configuration file is a list of environment variables. -Each variable must be written in POSIX way, bashism not allowed. - -Example: - -``` -key=value -``` - -If value contains spaces it must must be quoted. - -``` -key="value value2" -``` - -If value contains special symbols like $, it must be escaped -or quoted using single quotes. - -``` -key=\\$value -key='$value' -``` - -If line exceeded maximum space on your display and you want to make it -more readable, you can concatenate them. - -``` -key=value -key="${key}value" -``` - -If you want to temporary undefine variable without actually deleting it, -you can simply prepend \#. - -``` -#key=value -``` - -## MAN PAGE SYNTAX - -``` -| - OR -* - any value -[a] - optional value -... - can be repeated -``` - -# GENERAL OPTIONS - -*monolith*=1 - - Monolithic kernel means kernel with builtin modules. - If you didn't build kernel yourself, then in most cases you have - modular kernel and you don't need to enable this option. To check - if you have monolithic you need to check if */lib/modules//modules* exist. If this directory doesn't exist you probably - have monolithic kernel which means you need to set *monolith* to *1*. - -*hostonly*=1 - - Hostonly mode enumerates *sysfs*(5) and copies only neccessary modules - instead of copying all modules. Which means that this mode can dramatically - reduce initramfs size. This option will be ignored if *monolith* was set - to *1*. - -*compress*=command [args ...] - - Specify which command will be used to compress initramfs image. - There is a lot of commands you can use, such as: - - - xz - - zst (if supported by kernel) - - gzip - - bzip2 - - and many more ... - - You can set compression level by specifing -[0-9] in args. - For example - gzip -9. - -*root*=UUID|LABEL|/dev/\*|PARTUUID - - Specify which way tinyramfs will use to look up root filesystem. - - - UUID - lookup device by uuid - - LABEL - lookup device by label - - /dev/\* - lookup device by full path - - PARTUUID - lookup device by partition uuid - - You must install *blkid*(8) (avalable in toybox, busybox, util-linux) - for ability to use UUID, LABEL, PARTUUID. Note that PARTUUID only - supported in util-linux *blkid*(8). - -*root_type*=type - - Explicitly set root filesystem type instead of automatically discovering via - /proc/mounts. This option must be specified if you booted from Live CD. - -*root_opts*=opts - - See *fstab*(5) fourth field. - -*hooks*=hook [hook ...] - - Hooks provide a flexible way to extend tinyramfs with custom scripts. - You must know that *hooks are launched in the order in which they are - specified*. List of shipped by default hooks: - - - lvm - LVM support - - luks - LUKS support - - mdev - mdev support - - proc - CONFIG_UEVENT_HELPER support - - mdevd - mdevd support - - eudev - eudev support - - keymap - keymap support - - systemd-udevd - systemd udevd support - - See below how to use them. - If hook doesn't have options, then it's not yet documented or can be used - "as is". - - More detailed information and how to write your own hooks described in - *tinyramfs.hooks*(7). - -# HOOKS OPTIONS - -## LVM - -*lvm_tag*=tag - - Specify LVM tag which will be used to trigger LVM. This option will be - ignored if *lvm_name*/*lvm_group* was specified. - -*lvm_name*=name - - Specify LVM name which will be used to trigger LVM. *lvm_group* must be - specified. - -*lvm_group*=group - - Specify LVM group which will be used to trigger LVM. - -*lvm_config*=1 - - Include */etc/lvm/lvm.conf* in initramfs. - -*lvm_discard*=1 - - Pass issue_discards to lvm. Useful for SSD's. - -## LUKS - -*luks_key*=/path/to/key - - Specify location to key. - GPG-encrypted key currently not supported. - -*luks_name*=name - - Specify which name will be registered to mapping table after cryptsetup - unlocks LUKS root. - -*luks_root*=UUID|LABEL|/dev/\*|PARTUUID - - See *root* for details. - -*luks_header*=/path/to/header - - Specify location to detached header. - -*luks_discard*=1 - - Pass --allow-discards to *cryptsetup*. Useful for SSD's, but you must know - that security will be decreased. - -## KEYMAP - -*keymap_path*=/path/to/keymap - - Specify location to binary keymap. - Currently, this hook supports loading keymap only via busybox loadkmap. - kbd loadkeys not supported. - -# EXAMPLES - -Remember, these just examples ! _Don't copy blindly_ ! Your configuration may -(and should) differ. - -## ROOT - -``` -hooks=eudev -root=/dev/sda1 -``` - -## ROOT + MONOLITH + PROC (CONFIG_UEVENT_HELPER) - -``` -hooks=proc -monolith=1 -root=/dev/nvme0n1p1 -``` - -## ROOT + COMPRESS - -``` -hostonly=1 -hooks=mdevd -compress="gzip -9" -root=PARTUUID=8e05009d-a1d5-4fdb-b407-b0e79360555c -``` - -## ROOT + KEYMAP - -``` -root_type=f2fs -hooks="eudev keymap" -root=UUID=13bcb7cc-8fe5-4f8e-a1fe-e4b5b336f3ef -keymap_path=/usr/share/bkeymaps/colemak/en-latin9.bmap -``` - -## ROOT + LUKS - -``` -hooks="mdev luks" -root=LABEL=my_root - -luks_discard=1 -luks_key=/root/key -luks_header=/root/header -luks_root=PARTUUID=35f923c5-083a-4950-a4da-e611d0778121 -``` - -## ROOT + LVM + LUKS - -``` -compress="lz4 -9" -hooks="eudev lvm luks" -root=/dev/disk/by-uuid/aa82d7bb-ab2b-4739-935f-fd8a5c9a6cb0 - -luks_discard=1 -luks_root=/dev/sdb2 - -lvm_config=1 -lvm_discard=1 -lvm_name=lvm1 -lvm_group=lvm_grp2 -``` - -# SEE ALSO - -*tinyramfs*(8) *tinyramfs.cmdline*(7) *tinyramfs.hooks*(7) diff --git a/docs/tinyramfs.hooks.7 b/docs/tinyramfs.hooks.7 deleted file mode 100644 index 194b878..0000000 --- a/docs/tinyramfs.hooks.7 +++ /dev/null @@ -1,177 +0,0 @@ -.\" Generated by scdoc 1.11.1 -.\" Complete documentation for this program is not available as a GNU info page -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.nh -.ad l -.\" Begin generated content: -.TH "tinyramfs.hooks" "7" "2021-05-10" -.P -.SH NAME -.P -Tinyramfs - hooks and related stuff -.P -.SH DESCRIPTION -.P -Hooks can be located in \fB/usr/share/tinyramfs/hooks\fR (system path) and -\fB/etc/tinyramfs/hooks\fR (user path).\& Tinyramfs also allows you to specify custom -location via \fB-H\fR option.\& See \fBtinyramfs\fR(8) for more information.\& -.P -Hooks provides a way to extend build and init process.\& Hooks must be written in -POSIX shell.\& Bashisms and other non-portable extensions are forbidden.\& In order -to write hooks you must know about hook structure.\& -.P -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} - - directory of hook scripts -.RS 4 -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} - - invoked in build process.\& -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -.\&init - invoked in init process.\& -.RE -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.IP \(bu 4 -.\} -.\&init.\&late - invoked after root filesystem was mounted.\& - -.RE -.P -.RE -.SS MAN PAGE SYNTAX -.P -.nf -.RS 4 -- B: extension can be used in build process -- I: extension can be used in init process -- BI: extension can be used in both processes -.fi -.RE -.P -.SH EXTENSIONS -.P -Tinyramfs also provides some extensions and environment variables to easily -interact with build and init system.\& -.P -.SS BI: print -.P -.RS 4 -Print message to stdout.\& -.P -.RE -.SS BI: panic [message] -.P -.RS 4 -If message was not specified, then tinyramfs will print default error -message.\& otherwise message will be printed.\& -.P -.RE -.SS B: copy_module -.P -.RS 4 -Copy kernel module by path to tinyramfs working directory.\& -.P -.RE -.SS B: copy_binary -.P -.RS 4 -If full path was specified and it's has executable bit, then it's will -be copied to /bin location of tinyramfs working directory.\& -.P -If name was specified, then tinyramfs will try to find command by name -in PATH.\& If it's success, command will be copied to /bin location of -tinyramfs working directory.\& Otherwise error message will appear.\& -.P -.RE -.SS B: copy_file -.P -.RS 4 - must be full path to file.\& -.P - must be full path where should be stored.\& Tinyramfs -will automatically create all leading directories if they aren't exist -already.\& Also no need to prepend path of tinyramfs working directory.\& -.P - permissions in octal format.\& -.P - if was set to 1, then tinyramfs will attempt to run strip -on file.\& Tinyramfs will silently ignore errors if strip doesn't -exists or failed to strip binary.\& -.P -.RE -.SS I: resolve_device -.P -.RS 4 -Sets \fBdevice\fR variable to full path of resolved UUID|LABEL|/dev/*|PARTUUID -.P -.RE -.SH VARIABLES -.P -.nf -.RS 4 -- BI: debug - 1 if debug mode enabled -- I: break - breakpoint for debugging -- B: tmpdir - full path of tinyramfs working directory (initramfs rootfs in future) -- B: kernel - kernel version -- B: moddir - modules directory -- B: init - path to init script -- B: helper - path to device-helper script -- B: config - config location -- B: output - output path -- BI: see tinyramfs\&.config(5) -.fi -.RE -.P -.SH EXAMPLES -.P -This example will show how to handle soft dependencies of ext4 module.\& -Create \fB/etc/tinyramfs/hooks/ext4\fR directory and copy below scripts with -appropriate names to that directory.\& After that, prepend \fBext4\fR to \fBhooks\fR -option in tinyrams config.\& -.P -.SS ext4 -.P -.nf -.RS 4 -print "Copying ext4 dependencies" - -for _mod in crc32c libcrc32c; do - copy_module "$_mod" -done -.fi -.RE -.P -.SS ext4.init -.P -.nf -.RS 4 -modprobe -a crc32c libcrc32c -.fi -.RE -.P -.SH SEE ALSO -.P -\fBtinyramfs\fR(8) \fBtinyramfs.\&config\fR(5) \fBtinyramfs.\&cmdline\fR(7) \fBtinyramfs.\&hooks\fR(7) diff --git a/docs/tinyramfs.hooks.7.scd b/docs/tinyramfs.hooks.7.scd deleted file mode 100644 index 1640fc9..0000000 --- a/docs/tinyramfs.hooks.7.scd +++ /dev/null @@ -1,115 +0,0 @@ -tinyramfs.hooks(7) - -# NAME - -Tinyramfs - hooks and related stuff - -# DESCRIPTION - -Hooks can be located in */usr/share/tinyramfs/hooks* (system path) and -*/etc/tinyramfs/hooks* (user path). Tinyramfs also allows you to specify custom -location via *-H* option. See *tinyramfs*(8) for more information. - -Hooks provides a way to extend build and init process. Hooks must be written in -POSIX shell. Bashisms and other non-portable extensions are forbidden. In order -to write hooks you must know about hook structure. - -- - directory of hook scripts - - - invoked in build process. - - .init - invoked in init process. - - .init.late - invoked after root filesystem was mounted. - -## MAN PAGE SYNTAX - -``` -- B: extension can be used in build process -- I: extension can be used in init process -- BI: extension can be used in both processes -``` - -# EXTENSIONS - -Tinyramfs also provides some extensions and environment variables to easily -interact with build and init system. - -## BI: print - - Print message to stdout. - -## BI: panic [message] - - If message was not specified, then tinyramfs will print default error - message. otherwise message will be printed. - -## B: copy_module - - Copy kernel module by path to tinyramfs working directory. - -## B: copy_binary - - If full path was specified and it's has executable bit, then it's will - be copied to /bin location of tinyramfs working directory. - - If name was specified, then tinyramfs will try to find command by name - in PATH. If it's success, command will be copied to /bin location of - tinyramfs working directory. Otherwise error message will appear. - -## B: copy_file - - must be full path to file. - - must be full path where should be stored. Tinyramfs - will automatically create all leading directories if they aren't exist - already. Also no need to prepend path of tinyramfs working directory. - - permissions in octal format. - - if was set to 1, then tinyramfs will attempt to run strip - on file. Tinyramfs will silently ignore errors if strip doesn't - exists or failed to strip binary. - -## I: resolve_device - - Sets *device* variable to full path of resolved UUID|LABEL|/dev/\*|PARTUUID - -# VARIABLES - -``` -- BI: debug - 1 if debug mode enabled -- I: break - breakpoint for debugging -- B: tmpdir - full path of tinyramfs working directory (initramfs rootfs in future) -- B: kernel - kernel version -- B: moddir - modules directory -- B: init - path to init script -- B: helper - path to device-helper script -- B: config - config location -- B: output - output path -- BI: see tinyramfs.config(5) -``` - -# EXAMPLES - -This example will show how to handle soft dependencies of ext4 module. -Create */etc/tinyramfs/hooks/ext4* directory and copy below scripts with -appropriate names to that directory. After that, prepend *ext4* to *hooks* -option in tinyrams config. - -## ext4 - -``` -print "Copying ext4 dependencies" - -for _mod in crc32c libcrc32c; do - copy_module "$_mod" -done -``` - -## ext4.init - -``` -modprobe -a crc32c libcrc32c -``` - -# SEE ALSO - -*tinyramfs*(8) *tinyramfs.config*(5) *tinyramfs.cmdline*(7) *tinyramfs.hooks*(7) diff --git a/hook/eudev/eudev b/hook/eudev/eudev new file mode 100644 index 0000000..9833d41 --- /dev/null +++ b/hook/eudev/eudev @@ -0,0 +1,15 @@ +# vim: set ft=sh: +# shellcheck shell=sh +# +# https://shellcheck.net/wiki/SC2154 +# shellcheck disable=2154 + +for _bin in udevd udevadm; do + copy_exec "$_bin" +done + +mkdir -p "${tmpdir}/lib/udev/rules.d" +cat > "${tmpdir}/lib/udev/rules.d/device.rules" << EOF +SUBSYSTEMS=="block", ACTION=="add", RUN+="/sbin/helper" +ENV{MODALIAS}=="?*", ACTION=="add", RUN+="/sbin/helper" +EOF diff --git a/hooks/eudev/eudev.init b/hook/eudev/eudev.init similarity index 61% rename from hooks/eudev/eudev.init rename to hook/eudev/eudev.init index de76644..5799100 100644 --- a/hooks/eudev/eudev.init +++ b/hook/eudev/eudev.init @@ -1,11 +1,9 @@ # vim: set ft=sh: # shellcheck shell=sh # -# https://www.shellcheck.net/wiki/SC2154 +# https://shellcheck.net/wiki/SC2154 # shellcheck disable=2154 -[ "$break" = eudev ] && { print "break before eudev.init"; sh; } - udevd -dN never udevadm trigger -c add -t subsystems udevadm trigger -c add -t devices diff --git a/hooks/eudev/eudev.init.late b/hook/eudev/eudev.init.late similarity index 100% rename from hooks/eudev/eudev.init.late rename to hook/eudev/eudev.init.late diff --git a/hook/keymap/keymap b/hook/keymap/keymap new file mode 100644 index 0000000..063054d --- /dev/null +++ b/hook/keymap/keymap @@ -0,0 +1,8 @@ +# vim: set ft=sh: +# shellcheck shell=sh +# +# https://shellcheck.net/wiki/SC2154 +# shellcheck disable=2154 + +copy_file "$keymap_path" "$keymap_path" 0644 +copy_exec loadkmap diff --git a/hooks/keymap/keymap.init b/hook/keymap/keymap.init similarity index 52% rename from hooks/keymap/keymap.init rename to hook/keymap/keymap.init index 79d07c5..0ae5bc3 100644 --- a/hooks/keymap/keymap.init +++ b/hook/keymap/keymap.init @@ -1,10 +1,8 @@ # vim: set ft=sh: # shellcheck shell=sh # -# https://www.shellcheck.net/wiki/SC2154 +# https://shellcheck.net/wiki/SC2154 # shellcheck disable=2154 -[ "$break" = keymap ] && { print "break before keymap.init"; sh; } - # TODO support loadkeys loadkmap < "$keymap_path" diff --git a/hooks/luks/luks b/hook/luks/luks similarity index 61% rename from hooks/luks/luks rename to hook/luks/luks index 2faae55..97d3e3e 100644 --- a/hooks/luks/luks +++ b/hook/luks/luks @@ -1,36 +1,36 @@ # vim: set ft=sh: # shellcheck shell=sh # -# https://www.shellcheck.net/wiki/SC2154 +# https://shellcheck.net/wiki/SC2154 # shellcheck disable=2154 [ "$luks_key" ] && { - copy_file "${luks_key#*=}" /root/key 400 0 + copy_file "${luks_key#*=}" /root/luks_key 0400 - sed "s|${luks_key#*=}|/root/key|" \ + sed "s|${luks_key#*=}|/root/luks_key|" \ "${tmpdir}/etc/tinyramfs/config" > "${tmpdir}/_" mv "${tmpdir}/_" "${tmpdir}/etc/tinyramfs/config" } [ "$luks_header" ] && { - copy_file "${luks_header#*=}" /root/header 400 0 + copy_file "${luks_header#*=}" /root/luks_header 0400 - sed "s|${luks_header#*=}|/root/header|" \ + sed "s|${luks_header#*=}|/root/luks_header|" \ "${tmpdir}/etc/tinyramfs/config" > "${tmpdir}/_" mv "${tmpdir}/_" "${tmpdir}/etc/tinyramfs/config" } -[ "$hostonly" = 1 ] && - for _module in \ +[ "$hostonly" ] && + for _mod in \ aes ecb xts lrw wp512 sha256 \ sha512 twofish serpent dm-crypt do - copy_module "$_module" + copy_kmod "$_mod" done # https://bugs.archlinux.org/task/56771 -[ -e /lib/libgcc_s.so.1 ] && copy_file /lib/libgcc_s.so.1 /lib/libgcc_s.so.1 755 1 +[ -e /lib/libgcc_s.so.1 ] && copy_file /lib/libgcc_s.so.1 /lib/libgcc_s.so.1 0755 1 -copy_binary cryptsetup +copy_exec cryptsetup diff --git a/hooks/luks/luks.init b/hook/luks/luks.init similarity index 78% rename from hooks/luks/luks.init rename to hook/luks/luks.init index a3b56b1..d192ea3 100644 --- a/hooks/luks/luks.init +++ b/hook/luks/luks.init @@ -1,11 +1,9 @@ # vim: set ft=sh: # shellcheck shell=sh # -# https://www.shellcheck.net/wiki/SC2154 +# https://shellcheck.net/wiki/SC2154 # shellcheck disable=2154 -[ "$break" = luks ] && { print "break before luks.init"; sh; } - mkdir -p /run/cryptsetup resolve_device "$luks_root" diff --git a/hooks/lvm/lvm b/hook/lvm/lvm similarity index 70% rename from hooks/lvm/lvm rename to hook/lvm/lvm index 6c757ae..d516744 100644 --- a/hooks/lvm/lvm +++ b/hook/lvm/lvm @@ -1,20 +1,20 @@ # vim: set ft=sh: # shellcheck shell=sh # -# https://www.shellcheck.net/wiki/SC2154 +# https://shellcheck.net/wiki/SC2154 # shellcheck disable=2154 -[ "$hostonly" = 1 ] && - for _module in \ +[ "$hostonly" ] && + for _mod in \ dm-log dm-cache dm-mirror \ dm-snapshot dm-multipath dm-thin-pool do - copy_module "$_module" + copy_kmod "$_mod" done -copy_binary lvm +copy_exec lvm -lvm_config=" +_config=' devices { write_cache_state = 0 } @@ -24,11 +24,11 @@ lvm_config=" } global { use_lvmetad = 0 - }" + }' mkdir -p "${tmpdir}/etc/lvm" lvm config \ - --config "$lvm_config" \ + --config "$_config" \ ${lvm_config:+--mergedconfig} \ > "${tmpdir}/etc/lvm/lvm.conf" diff --git a/hook/lvm/lvm.init b/hook/lvm/lvm.init new file mode 100644 index 0000000..71b378b --- /dev/null +++ b/hook/lvm/lvm.init @@ -0,0 +1,30 @@ +# vim: set ft=sh: +# shellcheck shell=sh +# +# https://shellcheck.net/wiki/SC2154 +# shellcheck disable=2154 + +mkdir -p /run/lvm /run/lock/lvm + +set -- --sysinit -qq -aay ${lvm_discard:+--config=devices\{issue_discards=1\}} + +if [ "$lvm_group" ] && [ "$lvm_name" ]; then + set -- lvchange "$@" "${lvm_group}/${lvm_name}" +elif [ "$lvm_group" ]; then + set -- vgchange "$@" "$lvm_group" +elif [ "$lvm_tag" ]; then + set -- lvchange "$@" "@${lvm_tag}" +else + set -- vgchange "$@" +fi + +_count=0 + +# Handle race condition. +while ! DM_DISABLE_UDEV=1 lvm "$@"; do + if [ "$((_count += 1))" = 10 ]; then + panic "failed to trigger LVM" + else + sleep 1 + fi +done diff --git a/hook/mdev/mdev b/hook/mdev/mdev new file mode 100644 index 0000000..8f688a0 --- /dev/null +++ b/hook/mdev/mdev @@ -0,0 +1,14 @@ +# vim: set ft=sh: +# shellcheck shell=sh +# +# https://shellcheck.net/wiki/SC2154 +# shellcheck disable=2154 + +for _bin in mdev find kill; do + copy_exec "$_bin" +done + +cat > "${tmpdir}/etc/mdev.conf" << EOF +SUBSYSTEM=block;.* 0:0 660 @/sbin/helper +\$MODALIAS=.* 0:0 660 @/sbin/helper +EOF diff --git a/hook/mdev/mdev.init b/hook/mdev/mdev.init new file mode 100644 index 0000000..d807aca --- /dev/null +++ b/hook/mdev/mdev.init @@ -0,0 +1,24 @@ +# vim: set ft=sh: +# shellcheck shell=sh +# +# https://shellcheck.net/wiki/SC2154 +# shellcheck disable=2154 + +mdev -s +mdev -df 2> /dev/null & + +# https://shellcheck.net/wiki/SC2034 +# shellcheck disable=2034 +mdev_pid=$! + +find /sys/devices -name uevent | + +while read -r uevent; do + printf add > "$uevent" +done 2> /dev/null + +find /sys/devices -name uevent | + +while read -r uevent; do + printf add > "$uevent" +done 2> /dev/null diff --git a/hooks/mdev/mdev.init.late b/hook/mdev/mdev.init.late similarity index 67% rename from hooks/mdev/mdev.init.late rename to hook/mdev/mdev.init.late index 86d18da..6479e36 100644 --- a/hooks/mdev/mdev.init.late +++ b/hook/mdev/mdev.init.late @@ -1,7 +1,7 @@ # vim: set ft=sh: # shellcheck shell=sh # -# https://www.shellcheck.net/wiki/SC2154 +# https://shellcheck.net/wiki/SC2154 # shellcheck disable=2154 kill "$mdev_pid" diff --git a/hook/mdevd/mdevd b/hook/mdevd/mdevd new file mode 100644 index 0000000..4af3991 --- /dev/null +++ b/hook/mdevd/mdevd @@ -0,0 +1,14 @@ +# vim: set ft=sh: +# shellcheck shell=sh +# +# https://shellcheck.net/wiki/SC2154 +# shellcheck disable=2154 + +for _bin in mdevd mdevd-coldplug kill; do + copy_exec "$_bin" +done + +cat > "${tmpdir}/etc/mdev.conf" << EOF +SUBSYSTEM=block;.* 0:0 660 @/sbin/helper +\$MODALIAS=.* 0:0 660 @/sbin/helper +EOF diff --git a/hook/mdevd/mdevd.init b/hook/mdevd/mdevd.init new file mode 100644 index 0000000..f28b97b --- /dev/null +++ b/hook/mdevd/mdevd.init @@ -0,0 +1,13 @@ +# vim: set ft=sh: +# shellcheck shell=sh +# +# https://shellcheck.net/wiki/SC2154 +# shellcheck disable=2154 + +mdevd 2> /dev/null & + +# https://shellcheck.net/wiki/SC2034 +# shellcheck disable=2034 +mdevd_pid=$! + +mdevd-coldplug diff --git a/hooks/mdevd/mdevd.init.late b/hook/mdevd/mdevd.init.late similarity index 67% rename from hooks/mdevd/mdevd.init.late rename to hook/mdevd/mdevd.init.late index 25b5d40..dc5ec26 100644 --- a/hooks/mdevd/mdevd.init.late +++ b/hook/mdevd/mdevd.init.late @@ -1,7 +1,7 @@ # vim: set ft=sh: # shellcheck shell=sh # -# https://www.shellcheck.net/wiki/SC2154 +# https://shellcheck.net/wiki/SC2154 # shellcheck disable=2154 kill "$mdevd_pid" diff --git a/hooks/proc/proc b/hook/proc/proc similarity index 70% rename from hooks/proc/proc rename to hook/proc/proc index 5295d6f..4c105de 100644 --- a/hooks/proc/proc +++ b/hook/proc/proc @@ -1,4 +1,4 @@ # vim: set ft=sh: # shellcheck shell=sh -copy_binary find +copy_exec find diff --git a/hook/proc/proc.init b/hook/proc/proc.init new file mode 100644 index 0000000..03a8ccf --- /dev/null +++ b/hook/proc/proc.init @@ -0,0 +1,19 @@ +# vim: set ft=sh: +# shellcheck shell=sh +# +# https://shellcheck.net/wiki/SC2154 +# shellcheck disable=2154 + +printf '/sbin/helper\n' > /proc/sys/kernel/hotplug + +find /sys/devices -name uevent | + +while read -r uevent; do + printf add > "$uevent" +done 2> /dev/null + +find /sys/devices -name uevent | + +while read -r uevent; do + printf add > "$uevent" +done 2> /dev/null diff --git a/hooks/proc/proc.init.late b/hook/proc/proc.init.late similarity index 51% rename from hooks/proc/proc.init.late rename to hook/proc/proc.init.late index be02e0c..f6b2ef5 100644 --- a/hooks/proc/proc.init.late +++ b/hook/proc/proc.init.late @@ -1,4 +1,4 @@ # vim: set ft=sh: # shellcheck shell=sh -printf '\n' > /proc/sys/kernel/hotplug +printf '\0' > /proc/sys/kernel/hotplug diff --git a/hook/systemd-udev/systemd-udev b/hook/systemd-udev/systemd-udev new file mode 100644 index 0000000..3ce38ae --- /dev/null +++ b/hook/systemd-udev/systemd-udev @@ -0,0 +1,15 @@ +# vim: set ft=sh: +# shellcheck shell=sh +# +# https://shellcheck.net/wiki/SC2154 +# shellcheck disable=2154 + +for _bin in /lib/systemd/systemd-udevd udevadm; do + copy_exec "$_bin" +done + +mkdir -p "${tmpdir}/lib/udev/rules.d" +cat > "${tmpdir}/lib/udev/rules.d/device.rules" << EOF +SUBSYSTEMS=="block", ACTION=="add", RUN+="/sbin/helper" +ENV{MODALIAS}=="?*", ACTION=="add", RUN+="/sbin/helper" +EOF diff --git a/hook/systemd-udev/systemd-udev.init b/hook/systemd-udev/systemd-udev.init new file mode 100644 index 0000000..fbaef50 --- /dev/null +++ b/hook/systemd-udev/systemd-udev.init @@ -0,0 +1,10 @@ +# vim: set ft=sh: +# shellcheck shell=sh +# +# https://shellcheck.net/wiki/SC2154 +# shellcheck disable=2154 + +systemd-udevd -dN never +udevadm trigger -c add -t subsystems +udevadm trigger -c add -t devices +udevadm settle diff --git a/hooks/systemd-udevd/systemd-udevd.init.late b/hook/systemd-udev/systemd-udev.init.late similarity index 100% rename from hooks/systemd-udevd/systemd-udevd.init.late rename to hook/systemd-udev/systemd-udev.init.late diff --git a/hooks/eudev/eudev b/hooks/eudev/eudev deleted file mode 100644 index 563d5f6..0000000 --- a/hooks/eudev/eudev +++ /dev/null @@ -1,19 +0,0 @@ -# vim: set ft=sh: -# shellcheck shell=sh -# -# https://www.shellcheck.net/wiki/SC2154 -# shellcheck disable=2154 - -for _binary in udevd udevadm; do - copy_binary "$_binary" -done - -mkdir -p "${tmpdir}/lib/udev/rules.d" - -printf "%s\n" \ - 'SUBSYSTEMS=="block", ACTION=="add", RUN+="/bin/device-helper"' \ -> "${tmpdir}/lib/udev/rules.d/device-helper.rules" - -[ "$monolith" = 1 ] || printf "%s\n" \ - 'ENV{MODALIAS}=="?*", ACTION=="add", RUN+="/bin/modprobe %E{MODALIAS}"' \ ->> "${tmpdir}/lib/udev/rules.d/device-helper.rules" diff --git a/hooks/keymap/keymap b/hooks/keymap/keymap deleted file mode 100644 index 99c2b5f..0000000 --- a/hooks/keymap/keymap +++ /dev/null @@ -1,8 +0,0 @@ -# vim: set ft=sh: -# shellcheck shell=sh -# -# https://www.shellcheck.net/wiki/SC2154 -# shellcheck disable=2154 - -copy_file "$keymap_path" "$keymap_path" 644 0 -copy_binary loadkmap diff --git a/hooks/lvm/lvm.init b/hooks/lvm/lvm.init deleted file mode 100644 index 73d8ec3..0000000 --- a/hooks/lvm/lvm.init +++ /dev/null @@ -1,24 +0,0 @@ -# vim: set ft=sh: -# shellcheck shell=sh -# -# https://www.shellcheck.net/wiki/SC2154 -# https://www.shellcheck.net/wiki/SC2068 -# shellcheck disable=2154,2068 - -[ "$break" = lvm ] && { print "break before lvm.init"; sh; } - -export DM_DISABLE_UDEV=1 -mkdir -p /run/lvm /run/lock/lvm - -set -- \ - --sysinit -qq -aay "${lvm_discard:+--config=devices\{issue_discards=1\}}" - -if [ "$lvm_group" ] && [ "$lvm_name" ]; then - lvm lvchange $@ "${lvm_group}/${lvm_name}" -elif [ "$lvm_group" ]; then - lvm vgchange $@ "$lvm_group" -elif [ "$lvm_tag" ]; then - lvm lvchange $@ "@${lvm_tag}" -else - lvm vgchange $@ -fi || panic "failed to trigger LVM" diff --git a/hooks/mdev/mdev b/hooks/mdev/mdev deleted file mode 100644 index d429684..0000000 --- a/hooks/mdev/mdev +++ /dev/null @@ -1,18 +0,0 @@ -# vim: set ft=sh: -# shellcheck shell=sh -# -# https://www.shellcheck.net/wiki/SC2154 -# https://www.shellcheck.net/wiki/SC2016 -# shellcheck disable=2154,2016 - -for _binary in mdev find kill; do - copy_binary "$_binary" -done - -printf "%s\n" \ - 'SUBSYSTEM=block;.* 0:0 660 @device-helper' \ -> "${tmpdir}/etc/mdev.conf" - -[ "$monolith" = 1 ] || printf "%s\n" \ - '$MODALIAS=.* 0:0 660 @modprobe "$MODALIAS"' \ ->> "${tmpdir}/etc/mdev.conf" diff --git a/hooks/mdev/mdev.init b/hooks/mdev/mdev.init deleted file mode 100644 index b314922..0000000 --- a/hooks/mdev/mdev.init +++ /dev/null @@ -1,17 +0,0 @@ -# vim: set ft=sh: -# shellcheck shell=sh -# -# https://www.shellcheck.net/wiki/SC2154 -# https://www.shellcheck.net/wiki/SC2034 -# shellcheck disable=2154,2034 - -[ "$break" = mdev ] && { print "break before mdev.init"; sh; } - -mdev -s -mdev -df 2> /dev/null & mdev_pid="$!" - -find /sys/devices -name uevent | - -while read -r uevent; do - printf add > "$uevent" -done 2> /dev/null diff --git a/hooks/mdevd/mdevd b/hooks/mdevd/mdevd deleted file mode 100644 index 2e9a33c..0000000 --- a/hooks/mdevd/mdevd +++ /dev/null @@ -1,18 +0,0 @@ -# vim: set ft=sh: -# shellcheck shell=sh -# -# https://www.shellcheck.net/wiki/SC2154 -# https://www.shellcheck.net/wiki/SC2016 -# shellcheck disable=2154,2016 - -for _binary in mdevd mdevd-coldplug kill; do - copy_binary "$_binary" -done - -printf "%s\n" \ - 'SUBSYSTEM=block;.* 0:0 660 @device-helper' \ -> "${tmpdir}/etc/mdev.conf" - -[ "$monolith" = 1 ] || printf "%s\n" \ - '$MODALIAS=.* 0:0 660 @modprobe "$MODALIAS"' \ ->> "${tmpdir}/etc/mdev.conf" diff --git a/hooks/mdevd/mdevd.init b/hooks/mdevd/mdevd.init deleted file mode 100644 index 397ce45..0000000 --- a/hooks/mdevd/mdevd.init +++ /dev/null @@ -1,11 +0,0 @@ -# vim: set ft=sh: -# shellcheck shell=sh -# -# https://www.shellcheck.net/wiki/SC2154 -# https://www.shellcheck.net/wiki/SC2034 -# shellcheck disable=2154,2034 - -[ "$break" = mdevd ] && { print "break before mdevd.init"; sh; } - -mdevd 2> /dev/null & mdevd_pid="$!" -mdevd-coldplug diff --git a/hooks/proc/proc.init b/hooks/proc/proc.init deleted file mode 100644 index 1b39c1b..0000000 --- a/hooks/proc/proc.init +++ /dev/null @@ -1,16 +0,0 @@ -# vim: set ft=sh: -# shellcheck shell=sh -# -# https://www.shellcheck.net/wiki/SC2154 -# shellcheck disable=2154 - -[ "$break" = proc ] && { print "break before proc.init"; sh; } - -command -v device-helper > /proc/sys/kernel/hotplug - -# Prepare for fork bomb! -find /sys/devices -name uevent | - -while read -r uevent; do - printf add > "$uevent" -done 2> /dev/null diff --git a/hooks/systemd-udevd/systemd-udevd b/hooks/systemd-udevd/systemd-udevd deleted file mode 100644 index 49a4369..0000000 --- a/hooks/systemd-udevd/systemd-udevd +++ /dev/null @@ -1,19 +0,0 @@ -# vim: set ft=sh: -# shellcheck shell=sh -# -# https://www.shellcheck.net/wiki/SC2154 -# shellcheck disable=2154 - -for _binary in /lib/systemd/systemd-udevd udevadm; do - copy_binary "$_binary" -done - -mkdir -p "${tmpdir}/lib/udev/rules.d" - -printf "%s\n" \ - 'SUBSYSTEMS=="block", ACTION=="add", RUN+="/bin/device-helper"' \ -> "${tmpdir}/lib/udev/rules.d/device-helper.rules" - -[ "$monolith" = 1 ] || printf "%s\n" \ - 'ENV{MODALIAS}=="?*", ACTION=="add", RUN+="/bin/modprobe %E{MODALIAS}"' \ ->> "${tmpdir}/lib/udev/rules.d/device-helper.rules" diff --git a/hooks/systemd-udevd/systemd-udevd.init b/hooks/systemd-udevd/systemd-udevd.init deleted file mode 100644 index e5ba419..0000000 --- a/hooks/systemd-udevd/systemd-udevd.init +++ /dev/null @@ -1,12 +0,0 @@ -# vim: set ft=sh: -# shellcheck shell=sh -# -# https://www.shellcheck.net/wiki/SC2154 -# shellcheck disable=2154 - -[ "$break" = systemd-udevd ] && { print "break before systemd-udevd.init"; sh; } - -/lib/systemd/systemd-udevd -dN never -udevadm trigger -c add -t subsystems -udevadm trigger -c add -t devices -udevadm settle diff --git a/init b/init deleted file mode 100755 index 56529f8..0000000 --- a/init +++ /dev/null @@ -1,146 +0,0 @@ -#!/bin/sh -# -# Tiny init -# -# https://www.shellcheck.net/wiki/SC2154 -# shellcheck disable=2154 - -print() -{ - printf "%b %s\n" "${2:-"\033[1;37m>>\033[m"}" "$1" -} - -panic() -{ - print "${1:-unexpected error occurred}" \ - "\033[1;31m!!\033[m" >&2 - - sh -} - -resolve_device() -{ - count=0; device="$1" - - case "${device%%=*}" in - UUID) device="/dev/disk/by-uuid/${device#*=}" ;; - LABEL) device="/dev/disk/by-label/${device#*=}" ;; - PARTUUID) device="/dev/disk/by-partuuid/${device#*=}" ;; - /dev/*) ;; - *) return 0 ;; - esac - - # Race condition may occur if device manager is not yet initialized device. - # To fix this, we simply waiting until device is available. If device - # didn't appear in specified time, we panic. - while :; do - if [ -b "$device" ]; then - return 0 - elif [ "$((count += 1))" = "${rootdelay:=30}" ]; then - break - else - sleep 1 - fi - done - - panic "failed to lookup partition" -} - -run_hook() -{ - type="$1" - - # Run hooks if any exist. - # - # https://www.shellcheck.net/wiki/SC1090 - # shellcheck disable=1090 - for hook in $hooks; do - [ -f "/usr/share/tinyramfs/hooks/${hook}/${hook}.${type}" ] || continue - . "/usr/share/tinyramfs/hooks/${hook}/${hook}.${type}" - done -} - -prepare_environment() -{ - # https://www.shellcheck.net/wiki/SC1091 - # shellcheck disable=1091 - . /etc/tinyramfs/config - - export \ - PATH=/bin TERM=linux SHELL=/bin/sh \ - LANG=C LC_ALL=C PS1="# " HOME=/root - - mount -t proc -o nosuid,noexec,nodev proc /proc - mount -t sysfs -o nosuid,noexec,nodev sys /sys - mount -t tmpfs -o nosuid,nodev,mode=0755 run /run - mount -t devtmpfs -o nosuid,noexec,mode=0755 dev /dev - - ln -s /proc/self/fd /dev/fd - ln -s fd/0 /dev/stdin - ln -s fd/1 /dev/stdout - ln -s fd/2 /dev/stderr -} - -parse_cmdline() -{ - read -r cmdline < /proc/cmdline - - for line in $cmdline; do case "$line" in - rootfstype=*) root_type="${line#*=}" ;; - rootflags=*) root_opts="${line#*=}" ;; - debug=1) set -x ;; - ro | rw) rorw="$line" ;; - --*) init_args="${cmdline#*-- }"; break ;; - *=*) command export "$line" ;; - *) command export "${line}=1" ;; - esac 2> /dev/null || :; done -} - -mount_root() -{ - [ "$break" = root ] && { print "break before mount_root()"; sh; } - - resolve_device "$root" - - # https://www.shellcheck.net/wiki/SC2086 - # shellcheck disable=2086 - mount \ - -o "${rorw:-ro}${root_opts:+,$root_opts}" ${root_type:+-t $root_type} \ - -- "$device" /mnt/root || panic "failed to mount root" -} - -boot_system() -{ - [ "$break" = boot ] && { print "break before boot_system()"; sh; } - - for dir in run dev sys proc; do - mount -o move "$dir" "/mnt/root/${dir}" - done - - # POSIX 'exec' has no '-c' flag to execute command with empty environment. - # Using 'env -i' instead to prevent leaking exported variables. - # - # Some implementations of 'switch_root' doesn't conform to POSIX utility - # guidelines and doesn't support '--'. This means that we can't guarantee - # safety of init_args. - # shellcheck disable=2086 - exec \ - env -i TERM=linux PATH=/bin:/sbin:/usr/bin:/usr/sbin \ - switch_root /mnt/root "${init-/sbin/init}" $init_args || - panic "failed to boot system" -} - -# Exit if command fails and disable globbing. -set -ef - -# Run emergency shell if init unexpectedly exiting due to error. -trap panic EXIT - -# TODO display fancy colored status info - -prepare_environment -parse_cmdline -run_hook init -mount_root -run_hook init.late -boot_system diff --git a/lib/common.sh b/lib/common.sh new file mode 100755 index 0000000..e9d57e3 --- /dev/null +++ b/lib/common.sh @@ -0,0 +1,160 @@ +# vim: set ft=sh: +# shellcheck shell=sh +# +# https://shellcheck.net/wiki/SC2154 +# shellcheck disable=2154 + +print() +{ + printf "%s %s\n" "${2:-">>"}" "$1" +} + +panic() +{ + print "${1:-unexpected error occurred}" '!>' >&2 + + if [ "$$" = 1 ]; then + sh + else + exit 1 + fi +} + +# random() +# { +# _sum=$(cksum < /proc/uptime) +# printf '%s' "${sum% *}" +# } + +# TODO ensure correctness +copy_file() +( + file=$1; dest=$2 + + [ -e "${tmpdir}/${dest}" ] && return + + while [ -h "$file" ]; do + mkdir -p "${tmpdir}/${file%/*}" + cp -P "$file" "${tmpdir}/${file}" + cd -P "${file%/*}" || exit + + symlink=$(ls -ld "$file") + symlink=${symlink##* -> } + + case $symlink in + /*) file=$symlink ;; + *) file="${PWD}/${symlink##*/}" ;; + esac + done + + [ -h "${tmpdir}/${dest}" ] && dest=$file + + mkdir -p "${tmpdir}/${dest%/*}" + cp "$file" "${tmpdir}/${dest}" + + [ "$3" ] && chmod "$3" "${tmpdir}/${dest}" + + # https://shellcheck.net/wiki/SC2015 + # shellcheck disable=2015 + [ "$4" ] && strip "${tmpdir}/${dest}" > /dev/null 2>&1 || : +) + +copy_exec() +{ + _bin=$(command -v "$1") + + case $_bin in /*) ;; + '') + panic "unable to find command: $1" + ;; + *) + # https://shellcheck.net/wiki/SC2086 + # shellcheck disable=2086 + { IFS=:; set -- $PATH; unset IFS; } + + for _dir; do + __bin="${_dir}/${_bin}" + + [ -x "$__bin" ] && break + done + + # https://shellcheck.net/wiki/SC2015 + # shellcheck disable=2015 + [ -x "$__bin" ] && _bin=$__bin || panic "unable to find command: $_bin" + ;; + esac + + copy_file "$_bin" "/bin/${_bin##*/}" 0755 1 + + # TODO copy libs to the directory of interpreter. + ldd "$_bin" 2> /dev/null | + + while read -r _lib || [ "$_lib" ]; do + _lib=${_lib#* => } + _lib=${_lib% *} + + [ -e "$_lib" ] && copy_file "$_lib" "$_lib" 0755 1 + done +} + +copy_kmod() +{ + modprobe -S "$kernel" -D "$1" 2> /dev/null | + + while read -r _ _mod || [ "$_mod" ]; do + case $_mod in /*) copy_file "$_mod" "$_mod" 0644; esac + done +} + +# TODO allow full path to hook +copy_hook() +{ + for _dir in "${local+./hook}" /etc/tinyramfs/hook.d /lib/tinyramfs/hook.d; do + _hook="${_dir}/${1}/${1}" + [ -f "$_hook" ] && break + done + + [ -f "$_hook" ] || panic "unable to find hook: $1" + + for _ext in init init.late; do + [ -f "${_hook}.${_ext}" ] || continue + + print "copying hook: ${1}.${_ext}" + + copy_file "${_hook}.${_ext}" "/lib/tinyramfs/hook.d/${1}/${1}.${_ext}" 0644 + done + + print "evaluating hook: $1" + + # https://shellcheck.net/wiki/SC1090 + # shellcheck disable=1090 + . "$_hook" +} + +resolve_device() +{ + device=$1; _count=${2:-30} + + case ${device%%=*} in + UUID) device="/dev/disk/by-uuid/${device#*=}" ;; + LABEL) device="/dev/disk/by-label/${device#*=}" ;; + PARTUUID) device="/dev/disk/by-partuuid/${device#*=}" ;; + /dev/*) ;; + *) return ;; + esac + + # Race condition may occur if device manager is not yet initialized device. + # To fix this, we simply waiting until device is available. If device + # didn't appear in specified time, we panic. + while :; do + if [ -b "$device" ]; then + return + elif [ "$((_count -= 1))" = 0 ]; then + break + else + sleep 1 + fi + done + + panic "failed to lookup partition: $device" +} diff --git a/device-helper b/lib/helper.sh similarity index 60% rename from device-helper rename to lib/helper.sh index 94b16ca..916417f 100755 --- a/device-helper +++ b/lib/helper.sh @@ -1,24 +1,25 @@ #!/bin/sh -f # -# create /dev/disk/by-* and /dev/mapper/* symlinks +# Load modules via $MODALIAS. +# Create /dev/disk/by-* and /dev/mapper/* symlinks. create_symlink() { - typ="$1"; sym="$2" + typ=$1; sym=$2 - sym="${sym%\"}" - sym="${sym#\"}" + sym=${sym%\"} + sym=${sym#\"} sym="/dev/disk/by-${typ}/${sym}" mkdir -p "${sym%/*}" ln -s "../../${dev_name}" "$sym" } -# DEVPATH is part of uevent which is exported to environment by device manager. -[ -b "/dev/${dev_name=${DEVPATH##*/}}" ] || exit 1 - exec > /dev/null 2>&1 +[ "$MODALIAS" ] && modprobe "$MODALIAS" +[ "$SUBSYSTEM" = block ] && [ -b "/dev/${dev_name=${DEVPATH##*/}}" ] || exit 1 + read -r dm_name < "/sys/block/${dev_name}/dm/name" && { mkdir -p /dev/mapper ln -sf "../${dev_name}" "/dev/mapper/${dm_name:?}" @@ -37,8 +38,8 @@ while ! _blkid=$(blkid "/dev/${dev_name}"); do fi done -for line in $_blkid; do case "${line%%=*}" in - UUID) create_symlink uuid "${line##*=}" ;; - LABEL) create_symlink label "${line##*=}" ;; - PARTUUID) create_symlink partuuid "${line##*=}" ;; +for line in $_blkid; do case ${line%%=*} in + UUID) create_symlink uuid "${line#*=}" ;; + LABEL) create_symlink label "${line#*=}" ;; + PARTUUID) create_symlink partuuid "${line#*=}" ;; esac; done diff --git a/lib/init.sh b/lib/init.sh new file mode 100755 index 0000000..7023c4a --- /dev/null +++ b/lib/init.sh @@ -0,0 +1,118 @@ +#!/bin/sh +# +# https://shellcheck.net/wiki/SC2154 +# https://shellcheck.net/wiki/SC2034 +# shellcheck disable=2154,2034 + +init_base() +{ + mount -t proc -o nosuid,noexec,nodev proc /proc + mount -t sysfs -o nosuid,noexec,nodev sys /sys + mount -t tmpfs -o nosuid,nodev,mode=0755 run /run + mount -t devtmpfs -o nosuid,noexec,mode=0755 dev /dev + + ln -s /proc/self/fd /dev/fd + ln -s fd/0 /dev/stdin + ln -s fd/1 /dev/stdout + ln -s fd/2 /dev/stderr +} + +eval_hooks() +{ + _type=$1 + + # https://shellcheck.net/wiki/SC2086 + # shellcheck disable=2086 + { IFS=,; set -- $hooks; unset IFS; } + + for _hook; do + [ -f "/lib/tinyramfs/hook.d/${_hook}/${_hook}.${_type}" ] || continue + [ "$rdbreak" = "$_hook" ] && panic "break before: ${_hook}.${_type}" + + # https://shellcheck.net/wiki/SC1090 + # shellcheck disable=1090 + . "/lib/tinyramfs/hook.d/${_hook}/${_hook}.${_type}" + done +} + +parse_cmdline() +{ + # XXX /proc/cmdline can contain multiline data? + read -r cmdline < /proc/cmdline + + # https://kernel.org/doc/html/latest/admin-guide/kernel-parameters.html + # ... parameters with '=' go into init's environment ... + for _param in $cmdline; do case $_param in + rdpanic) trap - EXIT ;; + rddebug) set -x ;; + + # Maintain backward compatibility with kernel parameters. + ro | rw) rorw=$_param ;; + rootwait) root_wait=-1 ;; + --) init_args=${_param##*--}; break ;; + rootfstype=*) root_type=${_param#*=} ;; + rootflags=*) root_opts=${_param#*=} ;; + rootdelay=*) root_wait=${_param#*=} ;; + esac; done +} + +mount_root() +{ + [ "$rdbreak" = root ] && panic 'break before: mount_root()' + + resolve_device "$root" "$root_wait" + + # https://shellcheck.net/wiki/SC2086 + # shellcheck disable=2086 + mount \ + -o "${rorw:-ro}${root_opts:+,$root_opts}" ${root_type:+-t "$root_type"} \ + -- "$device" /mnt/root || panic "failed to mount rootfs: $device" +} + +boot_system() +{ + [ "$rdbreak" = boot ] && panic 'break before: boot_system()' + + for _dir in run dev sys proc; do + mount -o move "/${_dir}" "/mnt/root/${_dir}" || : + done + + # POSIX 'exec' has no '-c' flag to execute command with empty environment. + # Use 'env -i' instead to prevent leaking exported variables. + # + # Some implementations of 'switch_root' doesn't conform to POSIX utility + # guidelines and doesn't support '--'. This means that safety of init_args + # isn't guaranteed. + # + # https://shellcheck.net/wiki/SC2086 + # shellcheck disable=2086 + exec \ + env -i TERM=linux PATH=/bin:/sbin:/usr/bin:/usr/sbin \ + switch_root /mnt/root "${init:-/sbin/init}" $init_args || + panic "failed to boot system" +} + +# TODO add `quiet` support + +# -e: Exit if command return status greater than 0 +# -f: Disable globbing *?[] +set -ef + +# Run emergency shell if init unexpectedly exiting due to error. +# TODO prompt to continue +trap panic EXIT + +# https://shellcheck.net/wiki/SC1091 +# shellcheck disable=1091 +. /lib/tinyramfs/common.sh + +# https://shellcheck.net/wiki/SC1091 +# shellcheck disable=1091 +. /etc/tinyramfs/config + +init_base +parse_cmdline +eval_hooks init +mount_root +eval_hooks init.late +boot_system diff --git a/tinyramfs b/tinyramfs index dd98bf9..2109e7e 100755 --- a/tinyramfs +++ b/tinyramfs @@ -1,256 +1,85 @@ #!/bin/sh # -# Tiny initramfs -# -# https://www.shellcheck.net/wiki/SC2154 +# https://shellcheck.net/wiki/SC2154 # shellcheck disable=2154 -print() -{ - printf "%b %s\n" "${2:-"\033[1;37m>>\033[m"}" "$1" -} - -panic() -{ - print "${1:-unexpected error occurred}" \ - "\033[1;31m!!\033[m" - - exit 1 -} >&2 - # TODO add version usage() { - cat << EOF -usage: ${0##*/} [option]... - -o, --output set path to initramfs image - -c, --config set path to config - -k, --kernel set kernel version - -m, --modules set path to modules - -H, --hooks set directory to hooks - -D, --helper set path to device helper - -I, --init set path to init script - -d, --debug enable debug mode - -f, --force overwrite initramfs image + cat >&2 << EOF +usage: ${0##*/} [option]... + -c set path to config + -k set kernel version + -m set path to modules + -l enable local mode + -d enable debug mode + -f overwrite initramfs image + -h display this message EOF + + exit "$1" } -parse_arguments() +init_base() { - while [ "$1" ]; do case "$1" in - -o | --output) - output="${2:?}"; shift 2 - ;; - -c | --config) - config="${2:?}"; shift 2 - ;; - -k | --kernel) - kernel="${2:?}"; shift 2 - ;; - -m | --modules) - moddir="${2:?}"; shift 2 - ;; - -H | --hooks) - hksdir="${2:?}"; shift 2 - ;; - -D | --helper) - helper="${2:?}"; shift 2 - ;; - -I | --init) - init="${2:?}"; shift 2 - ;; - -d | --debug) - debug=1; shift 1 - ;; - -f | --force) - force=1; shift 1 - ;; - -h | --help) - usage; exit 0 - ;; - *) - printf "invalid option: %s\n" "$1" - - usage; exit 1 - ;; - esac; done - - # https://www.shellcheck.net/wiki/SC1090 - # shellcheck disable=1090 - . "${config:=/etc/tinyramfs/config}" - - : "${kernel:=$(uname -r)}" - : "${moddir:=/lib/modules}" - : "${init:=/usr/share/tinyramfs/init}" - : "${helper:=/usr/share/tinyramfs/device-helper}" - : "${output:=${TMPDIR:-/tmp}/tinyramfs-${kernel}}" + print 'creating ramfs structure' mkdir -p "${tmpdir:=${TMPDIR:-/tmp}/tinyramfs.$$}" - # https://www.shellcheck.net/wiki/SC2015 + # https://shellcheck.net/wiki/SC2015 # shellcheck disable=2015 - [ "$debug" = 1 ] && set -x || trap 'rm -rf $tmpdir' EXIT INT -} + [ "$debug" ] && set -x || trap 'rm -rf $tmpdir' EXIT INT -prepare_initramfs() -{ - print "preparing initramfs" + ( + cd "$tmpdir" - # https://wikipedia.org/wiki/Filesystem_Hierarchy_Standard - mkdir -p \ - "${tmpdir}/dev" \ - "${tmpdir}/sys" \ - "${tmpdir}/tmp" \ - "${tmpdir}/run" \ - "${tmpdir}/var" \ - "${tmpdir}/proc" \ - "${tmpdir}/root" \ - "${tmpdir}/usr/lib" \ - "${tmpdir}/usr/bin" \ - "${tmpdir}/mnt/root" \ - "${tmpdir}/etc/tinyramfs" + # https://wikipedia.org/wiki/Filesystem_Hierarchy_Standard + mkdir -p \ + dev sys tmp run var proc root \ + usr/lib usr/bin mnt/root etc/tinyramfs - ln -s usr/lib "${tmpdir}/usr/lib64" - ln -s usr/lib "${tmpdir}/lib64" - ln -s usr/lib "${tmpdir}/lib" - ln -s usr/bin "${tmpdir}/bin" - ln -s usr/bin "${tmpdir}/sbin" - ln -s ../run "${tmpdir}/var/run" - ln -s ../run/lock "${tmpdir}/var/lock" - ln -s bin "${tmpdir}/usr/sbin" + ln -s usr/lib lib + ln -s usr/bin bin + ln -s usr/bin sbin + ln -s ../run var/run + ln -s ../run/lock var/lock + ln -s bin usr/sbin - for _binary in \ - \[ sh ln env mkdir sleep mount \ - printf switch_root "$helper" + ln -s lib/tinyramfs/init.sh init + ln -s ../lib/tinyramfs/helper.sh bin/helper + ) + + for _bin in \ + \[ sh ln env mkdir sleep \ + printf switch_root mount do - copy_binary "$_binary" + copy_exec "$_bin" done - command -v blkid > /dev/null && copy_binary blkid + if ! command -v ldd > /dev/null; then + print 'unable to find ldd' '~>' + fi - copy_file "$init" /init 755 0 - copy_file "$config" /etc/tinyramfs/config 644 0 + if ! command -v blkid > /dev/null; then + print 'unable to find blkid' '~>' + else + copy_exec blkid + fi + + copy_file "$config" /etc/tinyramfs/config 0644 + copy_file "$init" /lib/tinyramfs/init.sh 0755 + copy_file "$devh" /lib/tinyramfs/helper.sh 0755 + copy_file "$shrd" /lib/tinyramfs/common.sh 0755 } -copy_file() -( - file="$1"; dest="$2"; mode="$3"; strip="$4" - - [ -e "${tmpdir}/${dest}" ] && return 0 - - mkdir -p "${tmpdir}/${dest%/*}" || panic - - # Iterate throught symlinks and copy them - while [ -h "$file" ]; do - cp -P "$file" "${tmpdir}/${dest%/*}/${file##*/}" - cd -P "${file%/*}" - - symlink=$(ls -ld "$file") - symlink="${symlink##* -> }" - - # TODO handle ../../.. - case "$symlink" in - /*) file="$symlink" ;; - *) file="${PWD}/${symlink##*/}" ;; - esac - done - - [ -h "${tmpdir}/${dest}" ] && dest="$file" - - { - cp "$file" "${tmpdir}/${dest}" - chmod "$mode" "${tmpdir}/${dest}" - } || panic - - # https://www.shellcheck.net/wiki/SC2015 - # shellcheck disable=2015 - [ "$strip" = 1 ] && strip "${tmpdir}/${dest}" > /dev/null 2>&1 || : -) - -copy_binary() +copy_hooks() { - binary=$(command -v "$1") - - # If output is - # - # empty, do panic - # external command, do nothing - # builtin command, try to find external alternative. - # - # https://www.shellcheck.net/wiki/SC2086 + # https://shellcheck.net/wiki/SC2086 # shellcheck disable=2086 - case "$binary" in */*) ;; - "") - panic "$1 does not exist" - ;; - *) - IFS=:; set -- $PATH; unset IFS + { IFS=,; set -- $hooks; unset IFS; } - _binary="$binary" - - for _dir; do - binary="${_dir}/${_binary}" - - [ -x "$binary" ] && break - done || panic "$_binary does not exist" - ;; - esac - - copy_file "$binary" "/bin/${binary##*/}" 755 1 - - # Skip copying binary dependencies if ldd not available. - command -v ldd > /dev/null || return 0 - - # Copy binary dependencies if any exist. - ldd "$binary" 2> /dev/null | - - while read -r _library || [ "$_library" ]; do - - _library="${_library#* => }" - _library="${_library% *}" - - [ -e "$_library" ] || continue - - copy_file "$_library" "/lib/${_library##*/}" 755 1 - done -} - -copy_module() -{ - module="$1" - - modprobe -S "$kernel" -D "$module" 2> /dev/null | - - while read -r _ module || [ "$module" ]; do - - # Skip builtin modules. - case "$module" in */*) ;; *) continue; esac - - copy_file "$module" "$module" 644 0 - done -} - -copy_hook() -{ - hook="$1" - - for hook_dir in "$hksdir" /etc/tinyramfs/hooks /usr/share/tinyramfs/hooks; do - [ -f "${hook_dir}/${hook}/${hook}" ] && break - done || panic "could not find $hook hook" - - print "running $hook hook" - - # https://www.shellcheck.net/wiki/SC1090 - # shellcheck disable=1090 - . "${hook_dir}/${hook}/${hook}" - - for _type in init init.late; do - [ -f "${hook_dir}/${hook}/${hook}.${_type}" ] || continue - - print "copying ${hook}.${_type}" - - copy_file "${hook_dir}/${hook}/${hook}.${_type}" \ - "/usr/share/tinyramfs/hooks/${hook}/${hook}.${_type}" 644 0 + for _hook; do + copy_hook "$_hook" done } @@ -258,93 +87,118 @@ copy_modules() { # Skip this function if kernel # compiled with builtin modules. - if [ "$monolith" = 1 ]; then - return 0 + if [ "$monolith" ]; then + return - elif [ "$hostonly" = 1 ]; then - print "copying hostonly modules" + elif [ "$hostonly" ]; then + print 'copying hostonly modules' # Perform autodetection of modules via /sys # https://wiki.archlinux.org/index.php/Modalias find /sys/devices -name modalias -exec sort -u {} + | - while read -r _module || [ "$_module" ]; do - + while read -r _mod; do # Skip unneeded modules and skip modules which # depends on them as well. - case $(modprobe -S "$kernel" -D "$_module") in + case $(modprobe -S "$kernel" -D "$_mod") in *wmi* | *gpu* | *net*) continue ;; esac 2> /dev/null - copy_module "$_module" + copy_kmod "$_mod" done if [ "$root_type" ]; then - copy_module "$root_type" + copy_kmod "$root_type" else while read -r _ _dir _type _; do [ "$_dir" = / ] && break - done < /proc/mounts || panic "failed to autodetect root fs module" + done < /proc/mounts || panic 'unable to detect rootfs module' - copy_module "$_type" + copy_kmod "$_type" fi else - print "copying all modules" + print 'copying all modules' - find \ - "${moddir}/${kernel}/kernel/fs" \ - "${moddir}/${kernel}/kernel/lib" \ - "${moddir}/${kernel}/kernel/arch" \ - "${moddir}/${kernel}/kernel/crypto" \ - "${moddir}/${kernel}/kernel/drivers/md" \ - "${moddir}/${kernel}/kernel/drivers/ata" \ - "${moddir}/${kernel}/kernel/drivers/scsi" \ - "${moddir}/${kernel}/kernel/drivers/block" \ - "${moddir}/${kernel}/kernel/drivers/virtio" \ - "${moddir}/${kernel}/kernel/drivers/usb/host" \ - "${moddir}/${kernel}/kernel/drivers/usb/storage" \ - -type f 2> /dev/null | + ( + cd "${moddir}/${kernel}/kernel" - while read -r _module || [ "$_module" ]; do - copy_file "$_module" "/lib/modules/${_module#$moddir}" 644 0 - done + find \ + fs lib arch crypto drivers/md drivers/ata drivers/scsi \ + drivers/block drivers/virtio drivers/usb/host \ + drivers/usb/storage -type f 2> /dev/null | + + while read -r _mod; do + copy_file "$_mod" "/lib/modules/${kernel}/${_mod}" 0644 + done + ) fi - copy_binary modprobe + copy_exec modprobe copy_file "${moddir}/${kernel}/modules.order" \ - "/lib/modules/${kernel}/modules.order" 644 0 + "/lib/modules/${kernel}/modules.order" 0644 copy_file "${moddir}/${kernel}/modules.builtin" \ - "/lib/modules/${kernel}/modules.builtin" 644 0 + "/lib/modules/${kernel}/modules.builtin" 0644 depmod -b "$tmpdir" "$kernel" } -make_initramfs() -( - print "generating initramfs image" +create_image() +{ + print 'generating initramfs image' - [ "$force" != 1 ] && [ -e "$output" ] && - panic "initramfs image already exist" + [ -z "$force" ] && [ -e "$output" ] && + panic 'initramfs image already exist' - cd "$tmpdir"; find . | - cpio -oH newc 2> /dev/null | - ${compress:-cat} > "$output" || - panic "failed to generate initramfs image" + (cd "$tmpdir" && find . | cpio -oH newc 2> /dev/null) | ${compress:-cat} > "$output" || + panic 'failed to generate initramfs image' - print "done! check out $output" -) + print "done: $output" '+>' +} -# Exit if command fails and disable globbing. +while getopts c:k:m:ldfh opt; do case $opt in + c) config=$OPTARG ;; + k) kernel=$OPTARG ;; + m) moddir=$OPTARG ;; + l) local=1 ;; + d) debug=1 ;; + f) force=1 ;; + h) usage 0 ;; + ?) usage 2 ;; +esac; done + +shift "$((OPTIND - 1))" + +# https://shellcheck.net/wiki/SC2015 +# shellcheck disable=2015 +[ "$1" ] && output=$1 || usage 2 + +[ "$local" ] && { + init="${PWD}/lib/init.sh" + shrd="${PWD}/lib/common.sh" + devh="${PWD}/lib/helper.sh" +} + +: "${kernel:=$(uname -r)}" +: "${moddir:=/lib/modules}" +: "${init:=/lib/tinyramfs/init.sh}" +: "${devh:=/lib/tinyramfs/helper.sh}" +: "${shrd:=/lib/tinyramfs/common.sh}" + +# -e: Exit if command return status greater than 0 +# -f: Disable globbing *?[] set -ef -parse_arguments "$@" -prepare_initramfs +# https://shellcheck.net/wiki/SC1090 +# shellcheck disable=1090 +. "$shrd" -for _hook in $hooks; do - copy_hook "$_hook" -done +# https://shellcheck.net/wiki/SC1090 +# shellcheck disable=1090 +. "${config:=/etc/tinyramfs/config}" +init_base +copy_hooks copy_modules -make_initramfs +create_image