Re: Intercepting/Delaying the boot process

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Apr 8, 2022, 12:44 Andreas Hartmann <hartan@xxxxx> 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@xxxxx> 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



[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux