Search code examples
linuxshelllinux-kernelembedded-linux

Getting kernel version from the compressed kernel image


I am working on a shell script. I have a pre-built zImage. is it possible to know the kernel version from which this zImage was created?

I have tried with the commands updated @ Getting uname information from a compressed kernel image, but both commands are failing.

$ dd if=zImage bs=1 skip=$(LC_ALL=C grep -a -b -o $'\x1f\x8b\x08\x00\x00\x00\x00\x00' zImage | \
  cut -d ':' -f 1) | zcat | grep -a 'Linux version'

dd: unrecognized operand `3165585'
Try `dd --help' for more information.

gzip: stdin: unexpected end of file

$ dd if=zImage bs=1 skip=$(LC_ALL=C grep -a -b -o $'\xFD\x37\x7A\x58\x5A\x00' zImage | \
  head -n 1 | cut -d ':' -f 1) | xzcat | grep -a 'Linux version'

xzcat: (stdin): File format not recognized

Can you guide me to identify the kernel version from zImage.


Solution

  • Check kernel compression algorithm

    Most likely your zImage was compressed using LZMA compressor. You can check it in next files:

    • in .config file (if you built kernel by yourself)
    • in /boot/config-`uname -r` file (if you are using your distribution)
    • in /proc/config.gz file (if CONFIG_IKCONFIG_PROC is enabled)

    Look for CONFIG_KERNEL_* param:

    $ cat .config | grep '^CONFIG_KERNEL_[^_]\+='
    

    If you have CONFIG_KERNEL_LZMA=y set, it means LZMA compressor is used.

    Unpack zImage

    LZMA format has 5d 00 00 header signature. So one can find position of compressed Image file in zImage file this way:

    $ grep -P -a -b -m 1 --only-matching '\x5D\x00\x00' zImage | cut -f 1 -d :
    

    To extract compressed Image:

    $ pos=$(grep -P -a -b -m 1 --only-matching '\x5D\x00\x00' zImage | cut -f 1 -d :)
    $ dd if=arch/arm/boot/zImage of=piggy.lzma bs=1 skip=$pos
    

    Now make sure that piggy.lzma is actually LZMA archive:

    $ file piggy.lzma 
    

    piggy.lzma: LZMA compressed data, streamed

    Decompress piggy.lzma:

    $ unlzma -c piggy.lzma > Image
    

    Find the Linux version

    Now that you have unpacked Image, you can find the Linux version using strings tool:

    $ strings Image | grep 'Linux version'
    

    which should give you something like this:

    Linux version 4.4.11-188843-g94c4bf5-dirty (joe@joe-laptop) (gcc version 4.8 (GCC) ) #1 SMP PREEMPT Thu May 26 20:55:27 EEST 2016