Flashable custom initramfs for purpose of dual-firmware install

I'm inching closer to having this new device ready to go. It's a dual-firmware Ramips (MT7621) device with Uboot.
What I'm trying to finalize is an easy installation process that does not involve opening the unit or soldering UART pins. This is challenging on dual-firmware devices, since I can't predict which partition will get flashed on the end user's unit if I just provide a factory image. My tentative solution is to provide an interim image that the user can flash via a TFTP recovery process, and from there do a sysupgrade. To accomplish this, what I want to do is simply take the standard ramdisk uImage file, and wrap it with the special MIPS CSYS header this device requires for flashing.
So with all that background, it's really a simple question. In the Makefile, I want to prepend something to the standard ramdisk image. Do I need to define this as if I'm building from the new image entirely scratch, or is there a simple way to reference the existing ramdisk uImage and work with that? I hope there's a macro to reference the ramdisk image, but I couldn't figure out what it is.


If your OEM bootloader defines rootfs= as needed (before overriding it from DTS), you can parse that - see ZyXEL nbg6817, Linksys EA8300 and other Linksys devices as example (append-rootblock, introduced by the *-generic-Mangle-bootloader-s-kernel-arguments.patch patches in several targets). Nothing in OpenWrt really needs to know the location of the rootfs (and the kernel is loaded by the bootloader anyways), so you just need to mangle the bootargs correctly - and then parse /proc/cmdline for determining the flashing locations for your sysupgrade support code.

1 Like

Thanks, this is great stuff.
I went back to check, the OEM firmware doesn't pass anything useful I can parse... wish it did. The only thing to work from is a Uboot env variable, bootImage. I was already using that in my intended sysupgrade code; is there a way to get access to that prior to mounting root... maybe preinit? I think that would solve my problem.

My device's OEM firmware is clever, it always points root to a ramdisk. I could see where this gives some flexibility: come up on the ramdisk, have just enough there to determine which real root image to use, attach & mount it, and do a switchroot. Has this ever been used in OpenWRT? Seems potentially useful on more complex devices.

That being said, if I want to add a custom image based on the initramfs image, how would I do that? I want to do something like:
IMAGE/tftp-recovery.bin := $$(KERNEL_INITRAMFS) | some-custom-header
...but $(KERNEL_INITRAMFS) gives me just the kernel. Is there a label that represents the full initramfs image?

  • paste the full uboot-env...
  • can you modify it? ( either from stock or serial )

it always points to a file... just happens that file is a ramdisk...

AFAIK... there is one (popular/detailed) device that makes use of ramdisks heavily... you could also checkout the device @Grommish has been working with... as it also has some funky ramdisk stuff going on. ( but I think he has seen the light and is now not using the ramdisk approach... at least as the primary mode )

It all boils down to two-ish key questions...

  • Does some vendor functionality RELY on having ramdisk abilities

Actually maybe one.

In most cases tho' a non-ramdisk kernel with hardcoded cmdline does the job.

My device uses uBoot to load from a FAT MMC partition a ELF BIN image. I was originally using the initramfs BIN file as the whole image, which kept everything in RAM. At one point, the ODM used switch_root after the MMC device came online to swap to the storage device in a custom init

Here is the define/Default I was use, although as was mentioned (https://forum.openwrt.org/t/designing-openwrt-device-from-the-nearly-ground-up/66642), I have moved to a more traditional approach of passing root=/dev/mmcblk1pX rootfs=ext4 rootwait to the boot.

define Device/Default
  KERNEL_NAME := vmlinux.elf
  KERNEL_INITRAMFS_NAME := vmlinux-initramfs.elf
  KERNEL := kernel-bin | strip-kernel | patch-cmdline
  IMAGES := sysupgrade.tar
  IMAGE/sysupgrade.tar/squashfs := append-rootfs | pad-extra 128k | sysupgrade-tar rootfs=$$$$@
  IMAGE/sysupgrade.tar := sysupgrade-tar | append-metadata

I still create the initramfs, but I also create the ext4 root and sysupgrade for both squashfs and ext..

-rw-r--r-- 1 grommish grommish  6254279 Jul  4 18:45 openwrt-octeon-itus-itusrouter-ext4-sysupgrade.tar.gz
-rwxr-xr-x 1 grommish grommish 14894792 Jul  4 18:45 openwrt-octeon-itus-itusrouter-initramfs-kernel.bin
-rw-r--r-- 1 grommish grommish     2027 Jul  4 18:45 openwrt-octeon-itus-itusrouter.manifest
-rw-r--r-- 1 grommish grommish  2475942 Jul  4 18:45 openwrt-octeon-itus-itusrouter-rootfs.tar.gz
-rw-r--r-- 1 grommish grommish 10465280 Jul  4 18:45 openwrt-octeon-itus-itusrouter-squashfs-sysupgrade.tar

I use the openwrt-octeon-itus-itusrouter-initramfs-kernel.bin as a recovery-I-just-bricked-everything image (the device has 3 separate boot firmware images).

1 Like

Following up to this, I figured out how to build a flashable initramfs image for my Ramips device. With this, a full OpenWRT installation will take 2 steps but won't require opening the unit and/or soldering.

In my case, both the OEM firmware and Uboot check for a MIPS CSYS header on the uImage. By wrapping the initramfs uImage with a CSYS header, it becomes flashable.
To do this, put this in the makefile:

  KERNEL_INITRAMFS := $(KERNEL_DTB) | custom-initramfs-uimage flashable-initramfs |\
     edimax-header -s CSYS -m RN68 -f 0x001c0000 -S 0x01100000

This redefines the build for the initramfs image to add the edimax-header stage.

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