I have not created an initrd from scratch. Basically you need the bare bones init files which will be required for execution (the list of which I do not know), plus the module directory with the particular modules. When initial load is complete it performs a pivot_root to the real file system.
As for the steps to create or examine an initrd, basically this should help:
There are several custom initrd web URLs, but most center on grub and x86 (typically live DVDs). The content after grub is done would probably be the same (we use U-Boot, x86 uses GRUB…initrd is only loaded in RAM by U-Boot and other than the mechanics of uncompressing it matter to U-Boot…the rest is a Linux requirement).
Here is the web search I used, though it isn’t specific to a Jetson:
Here is the kernel.org doc:
For a more specific example I suggest you download the R24.2.1 driver package. The “Linux_for_Tegra/bootloader/” directory contains file “initrd”, which during flash is copied directly to the “/boot” of the rootfs. The information of the first URL will give you a way to unpack and examine the content of this initrd. This particular initrd will not work in R28.1 or R28.2 since it is for a different kernel, but the structure should be close to what you want if you copy instead from the R28.1 or R28.2 (whichever you are using). If you run normally and mount an ext4 partition from the NVMe, and then run “lsmod”, then you will see which modules are required. Name this initrd with the “INITRD” entry of extlinux.conf and it should load this prior to starting the kernel. Try first without changing rootfs just to see it work. Once it works with no changes you should be able to rename the “rootfs=” to a new partition. The initrd itself and extlinux.conf will have to be on the mmcblk0p1 partition, but the rest of rootfs will end up on the NVMe.
In some of the more recent releases you will see an INITRD entry, and an initrd file, but the initrd file is zero bytes…it has no content. You should be able to drop your initrd in, but I strongly suggest giving it a new name and leaving the default zero byte version untouched in case of the need to use the original kernel for testing.
You do want to try to keep content minimal. In the 32-bit version space was extremely limited, and although you have much more room in 64-bit ARM the combined content of both initrd and modules must still be within the 128MB direct branch limit (I’m not sure how much is reserved for modules and how much is reserved for initrd…perhaps it is partitioned at 64MB but I’ve never checked.
If you create a log via serial console of a normal boot prior to working on the initrd, and then a log of any initrd boot, you can more or less “diff” the boot logs to use as a comparison while figuring out what the content needs to be.