Q#1: Or, to be more general, what pieces of software are common amongst all Linux distributions, i.e. define a Linux distribution?
If we are talking about a GNU/Linux distribution, I can surely guess that the userland is pretty much the same among distributions.
I can't think of one that get's away without using GNU Coreutils, GNU Binutils, GNU Bash, GNU Compiler Collection, etc.
Now if all you want is a definition of what a Linux distribution is made of, then in one sentence, that's the Linux kernel, and a userland, that is a set of software you run on top of that kernel to make it useful to you.
Most Linux distributions also use some kind of software management system, to ease software installation and configuration for example, (be it by binary package management like Debian, or source package management like Gentoo), and occasionaly, some distro specific software, like for instance administration tools (I can think of
debconf for Debian, or
yast for OpenSuse for instance). If you would like a more definitive answer, you should definitely take a look at Linux From Scratch
Q#2: Is the part of Linux that runs before chrooting into rootfs common to
all Linux distros (and that's why the initial boot worked for both
Arch and Ubuntu)?
Yes and no. Most distros use a slightly modified version of the steps below, but the choices of the technology for the different pieces can be different. Different boot loaders (GRUB, Lilo, etc.) for example.
excerpt from Wikipedia article titled: Linux Startup Process
- The BIOS performs hardware-platform specific startup tasks
- Once the hardware is recognized and started correctly, the BIOS loads and executes the partition boot code from the designated boot
device, which contains phase 1 of a Linux boot loader. Phase 1 loads
phase 2 (the bulk of the boot loader code). Some loaders may use an
intermediate phase (known as phase 1.5) to achieve this since modern
large disks may not be fully readable without further code.
- The boot loader often presents the user with a menu of possible boot options. It then loads the operating system, which decompresses
into memory, and sets up system functions such as essential hardware
and memory paging, before calling start_kernel().
- start_kernel() then performs the majority of system setup (interrupts, the rest of memory management, device initialization,
drivers, etc.) before spawning separately, the idle process and
scheduler, and the Init process (which is executed in user space).
- The Init process executes scripts as needed that set up all non-operating system services and structures in order to allow a user
environment to be created, and then presents the user with a login
Much of the seeming complexity (phase 1 boot loader calling phase 2) has to do with the history in which the PC grew up, where things were bolted on as IBM and others standardizes the design of various sub-systems and how they worked together.
The other complexity comes from the nature of Linux, where various components are modular and interchangeable. This modular design comes with a price, that you're seeing here with the over designing of the architecture. Remember that Linux can boot on a multitude of hardware platforms and supports a variety of filesystems, and so this partly a consequence of all these choices.