[systemd-devel] Intercepting/Delaying the boot process

Mantas Mikulėnas grawity at gmail.com
Fri Apr 8 11:13:04 UTC 2022


On Fri, Apr 8, 2022, 12:44 Andreas Hartmann <hartan at 7x.de> wrote:

> On Fri, 2022-04-08 at 12:07 +0300, Mantas Mikulėnas wrote:
> > On Fri, Apr 8, 2022 at 10:08 AM Andreas Hartmann <hartan at 7x.de> wrote:
> >
> > >
> > > To this end I was wondering whether it would be feasible to "hook" into
> > > the boot
> > > process, somewhere before the disks are decrypted, to only have it
> charge
> > > (or
> > > continue to boot when I press some magic button maybe). Looking at the
> > > order of
> > > service startup I was thinking about maybe intercepting the boot
> between
> > > "local-
> > > fs-pre.target" and "machines.target" because nothing happens there on
> my
> > > setup.
> > >
> >
> > That "between" doesn't make sense, because the boot process waits for
> > machines.target *in parallel* with waiting for all other services that
> are
> > started via multi-user. The systemd boot process is non-linear and
> doesn't
> > have a fixed order, it's a dependency graph.
> >
> > According to bootup(7), there are two main synchronization points,
> > sysinit.target and basic.target, which all non-"early" services will wait
> > for. So if you have a service with Before=basic.target, it'll delay
> startup
> > of all normal services. (It would then need to explicitly specify After=
> > for things it needs, like specific devices or sockets.)
>
> Good hint, thank you!
>
> >
> > If the device was using an initramfs (which has a fully separate boot
> > process, its own udevd, etc.) then you could make the initramfs decide
> > between starting a normal boot vs minimal boot depending on charger
> status.
> > If it doesn't have an initramfs, then systemd *generators* could also be
> > used to dynamically swap default.target (or alter units in general)
> > depending on some condition, as they also run after /sys is mounted but
> > before any units at all are started... though this would only work if
> your
> > wanted sysfs entries appear without needing udev.
>
> Interesting, I wasn't aware such things could be performed. About udev:
> The way I
> understand it, udev is mostly involved in dynamic device probing or
> managing/reacting to device events. Is that correct?
>

It doesn't probe devices (the kernel does that), but it does react to the
kernel's "device detected" events – loads additional kernel modules (e.g.
if a USB device with specific vid:pid was probed, udev loads the
corresponding .ko module), forwards events to userspace (e.g. to systemd),
etc.


> In my particular scenario, I have a complete devicetree that contains the
> nodes
> for all the hardware I need. So from my understanding that's enough for the
> kernel to load the drivers et al, or am I mistaken?
>

DT tells the kernel what devices exist without it needing to e.g. scan a
bus (which the kernel would do on its own anyway – that's not udev's job),
but it *doesn't* tell the kernel what .ko modules to load for them (that's
udev's job).

So if all necessary drivers are built-in, great. But if some of them are
modular, udev is usually still needed, whether the device was discovered
through DT or ACPI or something else.


> > > - After which stage in the boot process is the sysfs available?
> > >
> >
> > It is mounted by init before any units are started. (sysfs *is* how you
> > interact with the kernel though...)
>
> That will make my life a lot easier. I really meant I don't want to
> program the
> syscalls to the kernel myself etc.
>

There aren't any other syscalls that would do what /sys does, anyway. The
file-based interface (i.e. open/read/write syscalls on /sys) is often the
*only* interface.


> >
> > But that doesn't mean all *devices* are available in it – many things
> could
> > take some time to appear, and devices requiring drivers to be loaded as
> > modules would only become available some unspecified time after
> > systemd-udevd.service is started.
>
> But isn't really any device driver a module?


No, they can be compiled into the main kernel image as well (and on
embedded systems, most likely they all are, but...still). "Module"
specifically means a separate .ko file in /lib/modules, as opposed to the
driver being literally part of /vmlinuz. Usually the kernel has some mix of
built-in and modular drivers.

If udev is responsible for loading
> the kernel modules (drivers) then that would mean I can't access any
> device at
> this stage, right?
> I thought that statically defining the devices and their drivers in the
> devicetree makes them available without ''extra effort''.
>

The device tree doesn't specify Linux drivers directly, there's still a
layer of translating the abstract DT 'compatible' strings (or
vendor/product IDs, or ACPI IDs, or whatever) to Linux-specific paths. For
built-in drivers, that mapping is indeed also built in to the kernel, but
for modular ones it's in /lib/.../modules.alias and has to be read by
udev/libkmod, and then the corresponding .ko file has to be given to the
kernel.


> >
> > If you need a specific /sys or /dev device that's not guaranteed to be
> > available statically, the correct way would be to use an After=
> dependency
> > on that specific device (like After=dev-sda.device). Systemd relies on
> udev
> > events for this.
> >
> >
> > > - Can I delay the boot for an indefinite amount of time, or will this
> > > cause some
> > > services later on in the process to timeout and fail?
> > >
> >
> > In theory you could, similar to how systemd-fsck works, but I'm not sure
> if
> > that's the right way to do what you want.
>
> Likely not, but I think it's the most simple to wrap my head around for
> starters.
> I'll do some more research about generators and when my devices become
> available
> in the sysfs.
>
> Thank you very much!
>
>
> hartan
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/systemd-devel/attachments/20220408/b57d0dfd/attachment-0001.htm>


More information about the systemd-devel mailing list