<div dir="auto"><div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Apr 8, 2022, 12:44 Andreas Hartmann <<a href="mailto:hartan@7x.de" rel="noreferrer noreferrer" target="_blank">hartan@7x.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Fri, 2022-04-08 at 12:07 +0300, Mantas Mikulėnas wrote:<br>
> On Fri, Apr 8, 2022 at 10:08 AM Andreas Hartmann <<a href="mailto:hartan@7x.de" rel="noreferrer noreferrer noreferrer" target="_blank">hartan@7x.de</a>> wrote:<br>
> <br>
> > <br>
> > To this end I was wondering whether it would be feasible to "hook" into<br>
> > the boot<br>
> > process, somewhere before the disks are decrypted, to only have it charge<br>
> > (or<br>
> > continue to boot when I press some magic button maybe). Looking at the<br>
> > order of<br>
> > service startup I was thinking about maybe intercepting the boot between<br>
> > "local-<br>
> > fs-pre.target" and "machines.target" because nothing happens there on my<br>
> > setup.<br>
> > <br>
> <br>
> That "between" doesn't make sense, because the boot process waits for<br>
> machines.target *in parallel* with waiting for all other services that are<br>
> started via multi-user. The systemd boot process is non-linear and doesn't<br>
> have a fixed order, it's a dependency graph.<br>
> <br>
> According to bootup(7), there are two main synchronization points,<br>
> sysinit.target and basic.target, which all non-"early" services will wait<br>
> for. So if you have a service with Before=basic.target, it'll delay startup<br>
> of all normal services. (It would then need to explicitly specify After=<br>
> for things it needs, like specific devices or sockets.)<br>
<br>
Good hint, thank you!<br>
<br>
> <br>
> If the device was using an initramfs (which has a fully separate boot<br>
> process, its own udevd, etc.) then you could make the initramfs decide<br>
> between starting a normal boot vs minimal boot depending on charger status.<br>
> If it doesn't have an initramfs, then systemd *generators* could also be<br>
> used to dynamically swap default.target (or alter units in general)<br>
> depending on some condition, as they also run after /sys is mounted but<br>
> before any units at all are started... though this would only work if your<br>
> wanted sysfs entries appear without needing udev.<br>
<br>
Interesting, I wasn't aware such things could be performed. About udev: The way I<br>
understand it, udev is mostly involved in dynamic device probing or<br>
managing/reacting to device events. Is that correct?<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">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.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
In my particular scenario, I have a complete devicetree that contains the nodes<br>
for all the hardware I need. So from my understanding that's enough for the<br>
kernel to load the drivers et al, or am I mistaken?<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">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).</div><div dir="auto"><br></div><div dir="auto">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.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
> > - After which stage in the boot process is the sysfs available?<br>
> > <br>
> <br>
> It is mounted by init before any units are started. (sysfs *is* how you<br>
> interact with the kernel though...)<br>
<br>
That will make my life a lot easier. I really meant I don't want to program the<br>
syscalls to the kernel myself etc.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">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.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
> <br>
> But that doesn't mean all *devices* are available in it – many things could<br>
> take some time to appear, and devices requiring drivers to be loaded as<br>
> modules would only become available some unspecified time after<br>
> systemd-udevd.service is started.<br>
<br>
But isn't really any device driver a module?</blockquote></div></div><div dir="auto"><br></div><div dir="auto">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.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> If udev is responsible for loading<br>
the kernel modules (drivers) then that would mean I can't access any device at<br>
this stage, right?<br>
I thought that statically defining the devices and their drivers in the<br>
devicetree makes them available without ''extra effort''.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">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.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
> <br>
> If you need a specific /sys or /dev device that's not guaranteed to be<br>
> available statically, the correct way would be to use an After= dependency<br>
> on that specific device (like After=dev-sda.device). Systemd relies on udev<br>
> events for this.<br>
> <br>
> <br>
> > - Can I delay the boot for an indefinite amount of time, or will this<br>
> > cause some<br>
> > services later on in the process to timeout and fail?<br>
> > <br>
> <br>
> In theory you could, similar to how systemd-fsck works, but I'm not sure if<br>
> that's the right way to do what you want.<br>
<br>
Likely not, but I think it's the most simple to wrap my head around for starters.<br>
I'll do some more research about generators and when my devices become available<br>
in the sysfs.<br>
<br>
Thank you very much!<br>
<br>
<br>
hartan<br>
<br>
<br>
</blockquote></div></div></div>