Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
Completely bespoke stage-1 init, shell-free #66
As much as possible shell-free.
This is a big chunk of code. Don't be alarmed.
The goal is to make an init that is entirely based on tasks and dependencies, rather than a chunk of shell script that is hopefully ordered right.
Another goal is to keep the cross-compilation requirement.
A final goal is to keep the closure size as small as possible. The budget is ~8MiB total for the compressed initrd.
In a future improvement, it should be possible to, at first, select a generation to boot into (though stage-2 only), and furthermore, kexec to a kernel+initrd loaded from the system, making this a stage-0, that loads the real stage-1. It may also be possible to go kexec-free, and simply switch_root to another stage-1, though this sounds unlikely to be useful in the Mobile space.
A thousand-foot view
This adds an mruby build harness. What is that? It allows selecting gems to be compiled in the mruby build, and also allows building an mruby-based project into a binary. This is something that could graduate into Nixpkgs at some point.
This, then, adds the new init script. As of the creation of the PR, it does not clean up old initrd stuff.
One of the goal was to get a real programming language. Shell doesn't work here, especially since it's not even full bash!
The current choice is not a final choice, but the current choice for getting things rolling. I initially explored Rust, but had issues getting Rust programs cross-compiling. I probably want to explore using Rust again. Hopefully the language choice will not seep through and re-writing the main ideas and concept will be possible without changing the nix-side implementation.
You don't like Ruby? Eh, everyone has their flaws.
This is naïve! I don't order the tasks before running them, thus at the very worst I could loop as many time as there are tasks (if all dependencies are met in execution). A first optimization would be to order the tasks on dependencies before running them. Though, the loop executes tightly enough for our needs that it is not causing grief.
Other things may be messy, I am making it all up along the way.
As of right now, the implementation is to parity and better than the previous init.
I also believe it is faster to boot. At the very least, there are no artificial delays added. This does have the drawback of having the "empty, white coloured" logo transition happen quickly enough that on some devices it looks like it goes from empty to coloured. Oh well!
Implementation of generation selection is a task for a future PR. Right now I'll be inspecting this PR as best as an author can, and I'll merge it by the end of this week.
The only current issue is that I don't have a
I've tested the
Just guessing at this point since I don't know much about this, but notice this line in the
Finally, I know there was some discussion about using systemd in stage-1 NixOS/nixpkgs#72401, and I would be interested in your comments about whether this is feasible / useful for mobile-nixos.
@samueldr Well there's some progress--but now it crashes in
I was able to get adb to work. Here are the changes I had made: (not intended to be applied as-is, but for discussion)
I followed the AOSP usb init script for marlin as closely as I could:
We're now starting `bootlogd` first thing, this in turn allows it to capture all logs. Though, this does mean that `sh` is back in the critical path of the system. Anyway, it was never exactly out.
This is used to ensure mount points are mounted with the right options, if for some reason they were already mounted. Reasons they could be mounted? They could have been required for things like logging the boot.