Jetson Xavier NX: Load rootfs Image in initrd

Hello,
is there a way to mount the rootfs for a Jetson Xavier NX from a read-only image File. We are looking for a way to have a fixed firmware image that can easily be updated remotely in devices. I have a raw image created by cloning /dev/mmcblk0p1. Can this image File be mounted as the rootfs via initrd?

Per default the initrd mounts /dev/mmcblk0p1 as specified via the bootargs.

cat /proc/cmdline
...root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 ...

What kind of mounts does initrd support?

Thanks

I can’t really answer this explicitly as what you are interested in knowing, but I will give you some history and details you might find useful.

Historically, a bootloader and boot chain had to understand the filesystem type of the software to boot to, and the kernel itself also had to understand that filesystem. As an example, if the bootloader understands ext4, and the kernel understands ext4, then it is possible for the bootloader to load the kernel itself when the kernel exists in an ext4 filesystem. That is the simple case.

Now imagine the kernel is using some other fancy filesystem type for some special reason. Maybe the developer is creating something new that the bootloader doesn’t know about, or maybe the filesystem is encrypted and so the bootloader doesn’t understand encryption. A very common case is that a user has some massive files and they want the efficiency of the XFS filesystem. The kernel already has this driver if you enable it, but what about the bootloader? Will you port the Linux driver into the bootloader? What if the filesystem type is 64-bit and the bootloader is 32-bit? This can become difficult.

A solution, in the case that the bootloader already understands ext4, would be to store the kernel and boot content in ext4, but have the rest of the filesystem that other filesystem type, e.g., maybe “/boot” is ext4, and “/” is XFS.

Now let’s complicate it more and say that the driver to the first hard drive is known, but that a second hard drive is involved, and that this is a type not understood by the bootloader. These days a RAID appliance might need a different driver even though it consists (at the lower levels) as a simple ATA or SCSI device. Now you have yet another driver to worry about. The list goes on and on and on.

What developed as a result of this is a RAM disk, whereby a chunk of RAM is treated as if it is a disk. This has a very simple filesystem type in it, more or less just a tree structure without a lot of features, e.g., without SElinux labels and without journals. Every bootloader understands RAM. Every kernel will understand RAM. So the RAM disk is born. The kernel is not in the RAM disk, but it is read in any manner the kernel can be read; the kernel can be saved as pure data in a binary partition without a filesystem; the kernel can be in ext4. But now what if the kernel itself does not understand the filesystem? You have to add this to the kernel. One easy solution is to put this in the form of a loadable module. But how does the kernel itself read an XFS kernel module on XFS before the XFS module is loaded? That’s not solvable. So instead though, what if the RAM disk type is always understood by the kernel, and always understood by the bootloader? Just put the minimal init on the RAM disk, and put the kernel module on the RAM disk. The kernel can then load its own XFS module.

The magic comes when the kernel performs a pivot root command to take the “/” of the actual disk system on top of the “/” of the RAM disk. Then dissolve the RAM disk. You now have a system that has the XFS module loaded, and the filesystem is XFS. That pivot root command is the magic. The initial RAM disk is an adapter between two filesystems and two kernels (note that a bootloader is a kernel, but when it runs its one program, it overwrites itself with a new kernel; the Linux kernel persists).

Much of your question revolves around knowing about init. The Linux kernel itself, when it starts, is capable of running only one program. The kernel is process ID 0, the first process it runs, init, is PID 1. It is init which runs in the initrd. That initrd can have pretty much anything in it so long as a few conditions are met.

One condition is that since this runs in RAM you can’t get too much content there. A related, but different requirement for keeping the RAM disk (an “initial” RAM disk is the initrd) small is one of CPU architecture. There is a memory region below where the kernel loads which is reserved for initrd and kernel modules. For example use up too much for the initrd and you won’t have enough room for the modules (to some extent they share this space). That space limitation depends on the architecture because of how direct branch assembler instructions are used to go in and out of that memory space (the direct branch has different size limits on different architectures; on 32-bit ARM it was 32 MB, and on 64-bit ARM I think around 125 MB is available, though I don’t remember exactly). x86_64 is just huge in direct branch size limits, but it too has a limit.

It is init which loads modules, and init does not care if it is in an initrd or on a hard drive. If you can fit something into your initrd, then the kernel can work with it. You’d basically extract the initrd you have, see it as a filesystem, add or edit files in that filesystem, and then turn it back into an initrd, and suddenly what you have will run when this “adapter” runs. When the adapter is complete, it will pivot root and turn the actual filesystem into “/”. The initrd will then go away and no longer exist.

Incidentally, the kernel cmdline spec for “rootfs=” is what runs after the initrd. It is in fact probably the boot stage creating that spec, then inherited by the initrd, which causes that spec to continue to exist in the final running kernel. You don’t need to even look at this since the initrd has lived and died before you ever see this. There are flash options which tell the system to use or load an initrd.

The ways of modifying this are extensive, it is difficult to give you one way or place to change the initrd. The system you got that cmdline from probably booted from an initrd. Sometimes there is an INITRD spec in the extlinux.conf file, sometimes the initrd is specified entirely with flash command options.

If you do modify an initrd you might run into cases where the size must be limited; if the size changes, sometimes the flash software has to be told about it. One could probably write a book about that.


The really short answer: The initrd can pretty much run anything you have room for. Typically though you would not use the initrd to load another initrd.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.