*: refactor

Documentation will be rewritten and added later.
This commit is contained in:
illiliti 2021-07-31 20:20:16 +03:00
parent 7bfc7fe315
commit a468c11a30
45 changed files with 618 additions and 2161 deletions

View File

@ -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)

View File

@ -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 <file>
.P
.RS 4
Specify output location where initramfs image will be stored.\&
.P
.RE
\fB-c\fR, \fB--config\fR <file>
.P
.RS 4
Specify config location.\& Default is \fB/etc/tinyramfs/config\fR.\&
.P
.RE
\fB-k\fR, \fB--kernel\fR <version>
.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 <directory>
.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 <directory>
.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 <file>
.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 <file>
.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)

View File

@ -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* <file>
Specify output location where initramfs image will be stored.
*-c*, *--config* <file>
Specify config location. Default is */etc/tinyramfs/config*.
*-k*, *--kernel* <version>
Specify kernel version. Useful for bootstraping future system with modular
kernel. Default is current kernel version.
*-m*, *--modules* <directory>
Specify directory where modules stored. Default is */lib/modules*.
This option has no effect if *monolith* or *hostonly* were enabled in config.
*-H*, *--hooks* <directory>
Specify additional hooks location. Default is */usr/share/tinyramfs/hooks*
and */etc/tinyramfs/hooks*.
*-D*, *--helper* <file>
Specify location to device helper. Default is */usr/share/tinyramfs/device-helper*.
*-I*, *--init* <file>
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)

View File

@ -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)

View File

@ -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)

View File

@ -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/<kernel
version>/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)

View File

@ -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/<kernel
version>/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)

View File

@ -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
.\}
<hook> - directory of hook scripts
.RS 4
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
<hook> - invoked in build process.\&
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
<hook>.\&init - invoked in init process.\&
.RE
.RS 4
.ie n \{\
\h'-04'\(bu\h'+03'\c
.\}
.el \{\
.IP \(bu 4
.\}
<hook>.\&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 <message>
.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 <full path>
.P
.RS 4
Copy kernel module by path to tinyramfs working directory.\&
.P
.RE
.SS B: copy_binary <name or full path>
.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 <file> <destination> <mode> <strip>
.P
.RS 4
<file> must be full path to file.\&
.P
<destination> must be full path where <file> 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
<mode> permissions in octal format.\&
.P
<strip> 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 <UUID|LABEL|/dev/\*|PARTUUID>
.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)

View File

@ -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.
- <hook> - directory of hook scripts
- <hook> - invoked in build process.
- <hook>.init - invoked in init process.
- <hook>.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 <message>
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 <full path>
Copy kernel module by path to tinyramfs working directory.
## B: copy_binary <name or full path>
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 <file> <destination> <mode> <strip>
<file> must be full path to file.
<destination> must be full path where <file> 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.
<mode> permissions in octal format.
<strip> 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 <UUID|LABEL|/dev/\*|PARTUUID>
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)

15
hook/eudev/eudev Normal file
View File

@ -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

View File

@ -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

8
hook/keymap/keymap Normal file
View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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"

30
hook/lvm/lvm.init Normal file
View File

@ -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

14
hook/mdev/mdev Normal file
View File

@ -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

24
hook/mdev/mdev.init Normal file
View File

@ -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

View File

@ -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"

14
hook/mdevd/mdevd Normal file
View File

@ -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

13
hook/mdevd/mdevd.init Normal file
View File

@ -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

View File

@ -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"

View File

@ -1,4 +1,4 @@
# vim: set ft=sh:
# shellcheck shell=sh
copy_binary find
copy_exec find

19
hook/proc/proc.init Normal file
View File

@ -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

View File

@ -1,4 +1,4 @@
# vim: set ft=sh:
# shellcheck shell=sh
printf '\n' > /proc/sys/kernel/hotplug
printf '\0' > /proc/sys/kernel/hotplug

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

146
init
View File

@ -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

160
lib/common.sh Executable file
View File

@ -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"
}

View File

@ -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

118
lib/init.sh Executable file
View File

@ -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

402
tinyramfs
View File

@ -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 <file> set path to initramfs image
-c, --config <file> set path to config
-k, --kernel <ver> set kernel version
-m, --modules <dir> set path to modules
-H, --hooks <dir> set directory to hooks
-D, --helper <file> set path to device helper
-I, --init <file> set path to init script
-d, --debug enable debug mode
-f, --force overwrite initramfs image
cat >&2 << EOF
usage: ${0##*/} [option]... <output>
-c <file> set path to config
-k <kern> set kernel version
-m <path> 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