(Almost) Found a way to modify the kernel cmdline without recompile

Dear Fellow Users,

after much reading and experimentation, I (kinda) found a way to modify the cmdline of kernel without recompiling. Please kindly point out if this is doable, and all feed backs are welcome :slight_smile:

Here are my steps so far:

  1. Obtain/download the firmware in your working directory.
  2. Install your favorite extraction utility, either binwalk or better, I use the modkit below:
    https://github.com/rampageX/firmware-mod-kit
  3. Extract the firmware according to instructions. With binwalk you will have to also use dd and lzma the old version https://tukaani.org/lzma/
    With the modkit above, in the image parts folder, extract the header.img file with dd and lzma.
    4)here is what I got so far:
/tmp$ binwalk -v header.img
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes, header CRC: 0xBBEEBB2E, created: 2020-02-27 21:05:12, image size: 1603592 bytes, Data Address: 0x80060000, Entry Point: 0x80060000, data CRC: 0xD140C0A2, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "MIPS OpenWrt Linux-4.14.171"
64            0x40            LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 5163124 bytes

/tmp$ dd if=header.img bs=1 skip=64 of=kernel.lzma
/tmp$ lzma -d < kernel.lzma > kernel

If you get "corrupt" error, it's fine, the file is extracted. Or alternatively, download the original lzma and install it: https://tukaani.org/lzma/
The result is the same.

Now if you do:

hexdump -C kernel | head
or
strings | head

the kernel cmdline is here!!

The question is, can I safely edit it?

The next question is, how do I repackage the extracted kernel back into the firmware?

Much thanks to all!

:slight_smile: :slight_smile: :slight_smile:

why not modify the bootcmd string of uboot ?

Hello,

because of two reasons. One a lot of firmwares ignore cmdline passed from bootloader, and second, I don't use uboot. :slight_smile:

Although you're trying to avoid recompilation do you have a full build environment? If so then looking the tail end of the build with reasonable verbosity enabled would show you the tools used. A touch on the kernel file followed by make should capture what you need. You could then turn them into a standalone script if needed.

Thank you for the hints!

There is a build root installed, however my understanding of development is very close to null ;(

Does this mean I'll need to do an experimental compile and capture the last several lines for examination?

That's what I would do. Do a regular compile, then use the touch utility to update the timestamp on the kernel file (if that is the one you will hack). Next use make -j 1 V=s to get a linear, one-action at a time list of what is then done.

Make that into a script that should replicate the same thing and see if it builds an image that you can flash. It may be exactly the same as the original, or vary a bit if things like timestamps get embeded in it. Once it does flash OK then start making your changes to the kernel file.

Thank you, after reading and digging into the build system I found these under:
/target/linux/ar71xx/image/legacy.mk

VMLINUX:=$(BIN_DIR)/$(IMG_PREFIX)-vmlinux
UIMAGE:=$(BIN_DIR)/$(IMG_PREFIX)-uImage

# $(1): input file.
# $(2): output file.
# $(3): extra arguments for lzma.
define CompressLzma
  $(STAGING_DIR_HOST)/bin/lzma e $(1) -lc1 -lp2 -pb2 $(3) $(2)
endef

and

define Image/BuildKernel
        cp $(KDIR)/vmlinux.elf $(VMLINUX).elf
        cp $(KDIR)/vmlinux $(VMLINUX).bin
        dd if=$(KDIR)/vmlinux.bin.lzma of=$(VMLINUX).lzma bs=65536 conv=sync
        $(call MkuImage,lzma,,$(KDIR)/vmlinux.bin.lzma,$(UIMAGE)-lzma.bin)
        cp $(KDIR)/loader-generic.elf $(VMLINUX)-lzma.elf
        -mkdir -p $(KDIR_TMP)
endef

and I am succeful in unpacking and repacking the original kernel file using the lzma and dd conversions.

The router boots alright!

BUT, once I have edited the kernel cmdline with hexeditor and repacked, I always get these:

Trying to boot firmware from 0x00020000 in flash bank 0 ...
Reading data into memory ...
U-Boot firmware image header detected.
    Image Name:   MIPS OpenWrt Linux-4.14.171
    Data Size:    1603592 Bytes
    Load Address: 80060000
    Entry Point:  80060000
Uncompressing data (LZMA) ... ERROR, LzmaDecode.c, 323

Decoding error = 1

What gives??

:sob:

You perhaps need to up a level to ensure any checksums in files are also set correctly.

If you can find where the kernel cmdline is changed in a full build, change only that thing and do the same as above you may spot the extra bit that you need.

There may be a short cut by making sure that the cmdline stays the same length - maybe that is the need. Are you lengthening / shortening it?

See also if you can put your image file on the router and use the tools there to reproduce the error. That might give you a clue what is not working.

...at some point, just building from source becomes a lot easier and less error prone.

2 Likes