Custom initramfs on Jetpack 5.1.1 for AGXI

Hello,I’m trying to create a custom initramfs built into the kernel image on Jetpack 5.1.1 for the AGXI. I want to do some recovery tasks during boot in case the rootfs gets corrupted. I have check this topic Custom initramfs on Jetpack 3.2 for TX1 .
I also have configured the kernel with:
And I rebuild the kernel with command:

${INITRD_DIR} is initramfs.cpio, the size of initramfs.cpio is 9MB.

After rebuild the kernel,the size of Image is 9MB larger than before. So I thought initramfs has been built into the kernel image. Then I replace the /boot/Image with the new Image. After I reboot the device, I hope it will load initramfs and enter initramfs.But the result is it still enter ubuntu. this is not what I expected.

I also notice that some reference say I need to change the bootargs ,and set "root=/dev/ram0 " or “root=/dev/initrd”, I have tried that . It will cause kernel crush and can not boot normally.

After I try to reflash the device with command:
sudo ./tools/kernel_flash/ --initrd jetson-agx-xavier-industrial mmcblk0p1
The device boot successfully but enter bash-5.0 like this:

I don’t if it is right. but I think that the device has enter initramfs.

At this time I found that the bootargs is :

and found

After reboot the device. It will go back to normal and enter ubuntu.

I’m trying to create a custom initramfs built into the kernel image and I hope it will load initramfs and enter initramfs from the Image, not from /boot/initrd.

Is there any suggestions for that?

Kind regards

I can’t answer the question, but do consider that the JetPack 3.x release is very very old, and both the hardware and the boot chain are completely different between that and an Xavier on JetPack 5.x (which is L4T R35.x). The R28.x (JetPack 3.x) boot chain itself has almost nothing in common with the R35.x boot chain. R35.x uses UEFI and is more modular, whereas R28.x uses UBoot. R32.x migrated from actual UBoot to CBoot with UBoot features ported to that, so even R32.x boot is far different than R35.x. None of R28.x, nor R32.x hardware is used these days on Xavier, although the biggest difference is more in GPU and not so much in CPU.

This is where you’d look up AGX Xavier hardware documents (including industrial):$product,jetson_agx_xavier

For documentation specific to your L4T release (you can find L4T release with “head -n 1 /etc/nv_tegra_release”), go to that exact release’s documentation:

Also note that the flash commands are not always what they seem. Jetsons do not have a BIOS, and the equivalent of that and the boot software is normally in partitions or QSPI memory on the module. Even so, eMMC models can use a kernel, device tree, etc., inside of “/bootor in partitions. This depends mostly on the content of your “/boot/extlinux/extlinux.conf”. Thus some boot content is stored in two places: Partitions and/boot”. If that content is named in extlinux.conf, then normally that content takes precedence. If that content is missing, then the partition content is used.

Partitions are always signed, and unsigned partition content is always refused (“/boot” content does not need to be signed). It is true that the default signing is with a NULL key, but the partitions are signed, even when not flashing with a specific key. If the security fuses are burned, then only the signed partition content is used and the “/boot” content is always ignored. The main point here is that flashing won’t always result in that content being used.

I also want to add that some partition names are not always what they seem. I couldn’t tell you the details of every partition name. Just be certain that when you name a partition on a command line flash that you’ve verified that the partition name and flash is really flashing what you expect. Additionally, make sure that any partition flash content remains within the size specification for that partition (you could truncate a partition that you’ve increased in size). There are XML files to edit if you are increasing non-rootfs partition size beyond what is already reserved.

Incidentally, Linux (and *NIX) specifies that most everything is treated as a file, and can be accessed as a file. This includes standard operations for things like read or write. Device special files though are “pseudo” files, and don’t really exist on the disk (they are drivers in RAM pretending to be files). The drivers often need some sort of interaction other than simple file operations, and that is the ioctl() call. The ioctl call is custom to each driver. If you use an ioctl call for a driver that does not understand that custom call, then you get an invalid ioctl error. You might have two different hardware devices which do exactly the same thing, but use different drivers, and you cannot interchange between the two drivers. Or you might have a progression of driver releases for a piece of hardware, and an ioctl call might exist for one release that does not exist on the other. ioctl calls are not portable across drivers.

Yes,I know thatThe R28.x (JetPack 3.x) boot chain itself has almost nothing in common with the R35.x boot chain. But they are both use linux kernel. Since 2.6 Linux kernel. the Linux kernels contain a gzipped “cpio” format archive, which is extracted into rootfs when the kernel boots up.
So there should be a way that makes agxi to support initramfs (built into the kerne and extracted into rootfs when the kernel boots up. ).

Please let me know if you have any other suggestion. Thank you.

What is the purpose for running with such an old kernel? Maybe if we know the use-case it might help. You are possibly right about the built-in initrd, but since Jetsons don’t have a BIOS there is a lot of state setup in boot software that you won’t find on a system with a BIOS, and it is all more or less custom. The side effect to this is that all I can suggest is some experimentation.

One possible experiment: Start with the kernel version and configuration expected with a compatible R32.x or 35.x release. Set it up for initrd boot, e.g., instructions to boot to an NVMe drive use initrd flash. When this is working, alter that same kernel by putting the exact generated initrd into your built-in kernel. In theory it will then boot using your method. If you cannot get that method to work, and you learn to make that work using the intended kernel and initrd, then I think you might have a chance at migrating.

I do want to suggest though that the setup of state which the BIOS would have performed is quite different between R28.x and R35.x or R32.x. Those earlier kernels are more or less expecting a very different setup state of the hardware before taking over from boot versus what an R32.x or R35.x kernel would expect. It isn’t just about using the same cpio archive initrd concept, it is also about what the kernel needs at the moment control is handed over from bootloader to kernel.

i want to do some recovery tasks during boot in case the rootfs gets corrupted…At the same time,these is no usb port or internet port that can be use to update or recovery the rootfs…

but spi port ,uart and pcie can use to do the recovery work …so we need this three port (use uart,spi and pcie to load kernel ,dtb and initramfs to boot the device.

I am still waitting for more suggestions . If anyone knows anything about it . Please let me know.Thanks .

That’s an interesting approach. It might work, though it is a lot of work to get there. Still, why the old kernel and not the kernel meant to go with that release?

I want to emphasize that the kernel from each major release expected a different state setup from the boot chain before the boot chain transfers execution to the kernel. The state required for an L4T R28.x kernel is quite different than that expected for an R32.x kernel (and even earlier R32.x was different than later R32.x). What you’re essentially asking for by mixing two kernel of such wide releases is to create a new combined “BIOS equivalent”. Would it not be possible to do what you are trying to do with the same kernel version the system runs on?

Not only is the above part of the issue with boot chains and support for given kernels, but Xavier did not even exist during the R28.x days, nor in the earlier R32.x days. No boot chain has ever existed for Xavier hardware for software from that release era, nor even a kernel or rootfs.

I don’t understand why you are always mention L4T R28.x kernel . Maybe you have mislead by the

,That is just a post for reference. And that is similar topic that I can find on the forums . I don’t use R28.x for Agx Xavier. I want to this not because that topic.

Now I hope to accomplish all the function base on R32.5.3. I hope to create a custom initramfs built into the kernel image and I hope it will load initramfs and enter initramfs from the Image,

The reason why I think R32.5.3 has the property is that it also based on linux . its kernel version is lager than 2.6. And as I have mention above. Since 2.6 Linux kernel. the Linux kernels contain a gzipped “cpio” format archive, which is extracted into rootfs when the kernel boots up.
I don’t see any data say that linux kernel verison larger than 5.x is not support the property . if you have related data or reference. please let me know.

I know there is a lot of work to do. not only about the kernel . the uefi application is also need to be modified.

This is an urget work. I hope to find a solution as soon as possible.

If you knows anything about it . Please let me know.Thanks .

And if anyone knows anything about it . Please let me know.Thank all.

Given JetPack releases are tied to specific L4T releases. R28.x was flashed by JetPack 3.x. Even the documentation of that release is quite wrong when mixed with JetPack 4.x, and further incorrect for JetPack 5.x. Because of the boot chain differences from one release to another, there is almost nothing useful from a JetPack 3.x document. If you are using any R32.x code (tied to JetPack 4.x), and mixing it with anything from JetPack 5.x (L4T R35.x), then this too will be wrong, although it will be “less wrong”. Mostly this is about the boot chain setup before handing over to the kernel.

Are you working purely with R35.3.1? This is what corresponds to JetPack 5.1.1. This is the only documentation that has any guarantee of working. This includes documentation regarding the initrd since that is used for handing over from boot chain to kernel. It is true though that if you are just talking about the initrd as a cpio archive, then such information is probably correct on all releases (but the setup and prior to handing over to initrd, and the actual content within the initrd, will change with release).

This URL is about a debug branch of UEFI, which you might find useful since failures during boot will become more verbose:

This is more about a simple “Hello World” application in UEFI:

Although you might be interested in changing parts, this is about cloning the UEFI repo:

See also this about the edk2:

This is a UEFI adaptation guide, and is using L4T R34.x (which is the developer preview release before R35.x that you are using; this mostly applies to your case, although some changes were made);

Here is an excerpt from a thread you won’t have access to:

As for the question here, our current UEFI is based on edk2
EDK II · tianocore/ Wiki

Tianocore website. Contribute to tianocore/ development by creating an account on GitHub.

With tag = edk2-stable202111

and below one is our fork.
GitHub - NVIDIA/edk2: NVIDIA fork of tianocore/edk2

NVIDIA fork of tianocore/edk2. Contribute to NVIDIA/edk2 development by creating an account on GitHub.


This might be of interest:

This would be useful to you, although it is about the very first UEFI implementation (things have changed, but I think most of this applies):

1 Like

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