Linux – How to load initrd into memory to be passed to kernel when using kexec

embeddedinitrdlinuxmips

As the MIPS port of kexec doesn't support the --initrd param, I'm looking for workarounds to imitate the feature. According to Linux/MIPS wiki, MIPS kernels support rd_start and rd_size kernel command line arguments for specifying the location of initrd. I'm wondering would it be possible to load initrd into memory and pass it along the kernel parameters?

If it's possible, where in memory I should load the file and how do I load it? I thought about concatenating the kernel and the initrd into one file, but how do I get the address where kexec has loaded the new kernel?

A bit of background: I have a WNDR3700 wifi router running OpenWrt with a kexec'd kernel. My goal is to boot into a vanilla OpenWrt kernel stored on usb to ease upgrades. The problem (currently) is that the usb modules are not build into the kernel, but instead they are provided as loadable kernel modules. I'm able to boot from usb to another kernel using an embedded initramfs, but using an initramfs requires me to compile the kernel, doesn't it? So, alternatively, could I embed initramfs/initrd into an existing kernel binary/elf (without any ramdisk) and avoid recompiling the kernel?

Also, obviously compiling the usb modules into the kernel requires recompiling the kernel, so that's not an option.

Best Answer

If it's possible, where in memory I should load the file and how do I load it?

On Linux small devices you have defined memory regions:

$ cat /proc/mtd 
dev:    size   erasesize  name
mtd0: 00020000 00010000 "u-boot"
mtd1: 00102b20 00010000 "kernel"
mtd2: 006cd4e0 00010000 "rootfs"
mtd3: 00510000 00010000 "rootfs_data"
mtd4: 00010000 00010000 "art"
mtd5: 007d0000 00010000 "firmware"

Be careful to not to brick your device.

Related Question