<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Sep 4, 2023 at 3:58 AM Paul Ruizendaal via TUHS <<a href="mailto:tuhs@tuhs.org">tuhs@tuhs.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Recently, I was looking into the “Das U-Boot” boot loader package. Summarised with great simplification, u-boot bundles device drivers, file systems, commands and a Bourne-like shell into a standalone package. Normally it auto-runs a script that brings up a system, but when used in interactive mode it allows a great deal of poking around.<br>
<br>
It made me think of the “standalone” set of programs for installing early Unix. On 16-bit understandably each basic command has to be a separate standalone program, but after the shift to 32-bit bundling more functionality in a single binary would have become possible.<br>
<br>
How did the Unix “standalone” package evolve in the 80’s, both in the research and BSD lineages? Is there any retrospective paper about that? Or is it a case of “Use the source, Luke”?<br></blockquote><div><br></div><div>The stand package continued in research and BSD to be those programs needed to install and/or recover</div><div>badly damaged systems.  You could create a new file system, copy a file from the tape to a partition, etc.</div><div>You couldn't do general scripting with this, by and large.</div><div><br></div><div>Originally, they were tape programs. This made sense because of its original focus. In time, some systems</div><div>could load the stand alone programs instead of the kernel, but they continued the original focus.</div><div><br></div><div>This is, imho, due in large part due to the miniroot. The miniroot evolved into both a full-enough system</div><div>to do the installation scripts in shell instead of C (Venix, at least, had their install program written in C).</div><div>You'd copy the minroot to swap and then install the system. But a number of additional programs were</div><div>placed into the miniroot so you could do some limited filesystem repair, file editing, etc.</div><div><br></div><div>In addition, many vendor's ROMs grew in complexity. Solbourne's ROMs, for example, could do basic</div><div>repair of UFS (clri level, not fsck level), and copy files from one place to another. I often recovered a</div><div>Solbourne system I screwed up by attaching an external SCSI drive that had a known good kernel,</div><div>init, etc.</div><div><br></div><div>The 'stand' environment was a whole set of tools that could be used to build stand-alone programs that</div><div>shared much code of their full unix brethren, despite not having a full kernel under them. Kernel services</div><div>were provided by different libraries that did filesystem things, block driver things, network things, etc</div><div>in a similar way to Unix, but with a much reduced footprint.<br></div><div><br></div><div>initramfs, as has been mentioned elsewhere, is pretty much a Linux invention. It was designed to</div><div>'punt' on the choose where to load things from and have a very minimal interface between the boot</div><div>loader and the system. In time, it grew to support more interfaces, more ways of loading, and better</div><div>ways to mount something that you could then 'pivot' onto. Few other unix systems went this route, though</div><div>many adopted some variation on the pivot_root functionality. Linux has moved beyond the pivot root after</div><div>having booted the correct kernel into being able to take over the machine early in, say, UEFI startup with</div><div>a minimal kernel and initramfs that just knows how to load the next kernel. They skipped the complex boot</div><div>loader stage, and went straight to the 'run linux earlier' stage which is how things like LinuxBoot, coreboot</div><div>and others have put the boot logic into bash scripts. The ability to 'kexec' a kernel and replace the current</div><div>running kernel originated in the 'non-stop' world that wanted to reduce downtime. Now, it's used to reduce</div><div>firmware complexity by eliminating large swaths of UEFI from the boot process, but also generalizes in</div><div>the embedded space.<br></div><div><br></div><div>FreeBSD, from around FreeBSD 2 (1995 or so), had /rescue which largely took over form the stand alone environment</div><div>for the repair duties of things. FreeBSD also adopted a more complex boot loader that would load the</div><div>kernel, modules, set tunables, etc prior to kicking off the kernel. Between /rescue having all the tools needed</div><div>to repair bad updates, repair failing disks, get that one last backup before the drive is dead while you wait</div><div>for the new drive to be delivered, etc, and /boot/loader being able to script loading the kernel while the BIOS</div><div>was still around so the need for drivers in the loader was lessened. However, as the BIOS evolved into UEFI</div><div>and FreeBSD pushed into the embedded space whose firmware provided a less rich environment to the boot</div><div>loader, so it was able to load things off fewer and fewer devices, it became clear that it would need a pivot</div><div>root feature to allow it to boot all the way into FreeBSD, load some drivers from an included ram disk, and then</div><div>use that mount a new root and then 'reroot' to that by killing everything and running init from that new root.</div><div>FreeBSD also moved from Forth to Lua in its scripting language for the boot loader, giving 'pre boot'</div><div>environment support better features. I also added the ability to use FreeBSD boot loader as a Linux binary</div><div>to load FreeBSD and its metadata from a LinuxBoot environment. Finally, FreeBSD has 'spun out' and</div><div>generalized the /rescue feature to allow creation of any 'BeastyBox' environment, similar to what you get</div><div>in a busy box, or clone, environment. This environment, though, is meant in large part on both Linux and</div><div>FreeBSD to be in constrained environments where a full install is prohibitive (even those that never pivot</div><div>to something more, like ap, routers and nas boxes).<br></div><div><br></div><div>NetBSD retains many of the old BSD stand-alone programs that started on the vax. I've not studied things</div><div>beyond noticing this. OpenBSD is similar. Their boot chain is a bit simpler than FreeBSD's, though there's</div><div>noises about porting FreeBSD's boot there. There's a port of /boot/loader to illumos too, but I don't know</div><div>if it is the default, or just available. So I'll not chat about it more.<br></div><div><br></div><div>So the original 'standalone' environment where you had one program running on a system has evolved</div><div>into either a rich boot loader environment that lets one do a lot to decide what kernel to load, or towards</div><div>having a minimal selection of unix programs faster and using /bin/sh or similar to do scripting. These</div><div>reduced environments are often called standalone, though all they share just the name with the earlier</div><div>'stand' programs: they are full unix programs, but with reduced feature sets and 'linker magic' to package</div><div>them in a way that's faster, smaller, etc (eg all in one binary). FreeBSD's boot loader is an outgrowth</div><div>of the original standalone env, by way of a port of NetBSD's libsa. <br></div><div><br></div><div>I suspect in the future, we'll see more and more of a trend for low-level init and then handing off to some</div><div>built-in kernel (be it Linux, BSD-based (there's now kexec), or whatever) to reuse more of the vetted code</div><div>rather than re-inventing Unix inside the boot loader (which is a valid criticism of FreeBSD's boot loader,</div><div>though it's rich feature set is what you get for the complexity).</div><div><br></div><div>Does that answer the prompt? Should I try to make this into more of a retrospective paper and actually</div><div>do the research on the areas I was hand-wavy about?</div><div><br></div><div>Warner<br></div></div></div>