Getting kernel version from the compressed kernel image
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 (ifCONFIG_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
Getting uname information from a compressed kernel image
For Linux image compressed with gzip, use this:
dd if=arch/arm/boot/zImage bs=1 skip=$(LC_ALL=C grep -a -b -o $'\x1f\x8b\x08\x00\x00\x00\x00\x00' arch/arm/boot/zImage | head -n 1 | cut -d ':' -f 1) | zcat | grep -a 'Linux version'
For Linux image compressed with xz, use this:
dd if=arch/arm/boot/zImage bs=1 skip=$(LC_ALL=C grep -a -b -o $'\xFD\x37\x7A\x58\x5A\x00' arch/arm/boot/zImage | head -n 1 | cut -d ':' -f 1) | xzcat | grep -a 'Linux version'
Because the image file contains data after the end of the compressed stream, you'll get an error you can ignore.
The string constant appears to be part of the frozen userspace visible kernel API:
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=init/version.c;hb=HEAD#l40
Is it possible to get kernel version from ELF image file without disassemble or using grep or strings?
As previously mentioned, the version number is hardcoded into the compressed image file. First it depends on the compression algorithm used to compress the content, how to decompress it.
Decompressing files in linux could be challenging due to the combination of compression algorithms and the correlated tool options (not to forget a newer version of tar for newer algorithms).
For files with
file extension tar.gz, tgz use e.g. $ tar -xzv -f vmlinuz.tgz
file extension tar.xz, use e.g. $ tar -xJv -f vmlinuz.tar.xz
file extension tar.bz2, use e.g. $ tar -xjv -f vmlinuz.tar.bz2
So if you have access to the file utility (should also run on windows), run the following to receive the version string and additional information of your file named e.g. vmlinuz-4.x.y-z-a.
file vmlinuz-4.x.y-z-a
Another possibility to reverse-engineer would be to read all strings of the binary file vmlinuz-4.x.y-z-a and grep for a part of the possible solution.
strings vmlinuz-4.x.y-z-a | grep 'linked,'
How can I determine the build/version of Linux kernel 'uImage'?
I just realized, the kernels I have immediate access to do have the version string stored uncompressed amongst the headers. strings uImage | grep 2.6
ought to be good enough for any 2.6 kernel which covers pretty much everything in the last 5+ years).
(original answer follows)
It's theoretically possible, but not entirely trivial.
Modern Linux kernel versions use a format called bzImage (for x86/x86_64, YMMV on other platforms). It actually consists of an ELF header and some other minutia (like a bit of decompression code) followed by, yes, a compressed image of the actual kernel.
Traditionally, the compression algorithm was zlib (contrary to popular misconception, 'bzImage' did not stand for "bzipped image", but for "big zImage" -- the original zImage format not being able to handle large kernels), though versions after 2.6.30 also support bzip2 and LZMA.
What you'll probably have to do is determine exactly where the compressed data starts (sorry, can't help you there, but trial and error might work), and write a bit of code to run it through the library for whichever compression algorithm is in use.
Buildroot doesn't generate compressed Kernel image
On arm64, Linux does not support self-extracting compression. It relies on the boot loader to do that.
The Linux build system does have an Image.gz
(and Image.bz2
etc.) target, but it does nothing more than calling gzip
on Image
(compare this with zImage
, which adds a self-extractor).
Since it is easy to do the compression outside of the kernel build system, and since there are so many different compressors possible, Buildroot doesn't provide options for them. However, it is possible to select a custom image name (BR2_LINUX_KERNEL_IMAGE_TARGET_CUSTOM
) and then set BR2_LINUX_KERNEL_IMAGE_TARGET_NAME
to Image.gz
. Alternatively, you can do the compression in a post-build script.
Remember to make sure that the bootloader is able to decompress with that algorithm.
Find linux kernel version of a router firmware from the filesystem
Along side the squashfs-root
folder there was a A0
file.
binwalk A0
revealed:
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
0 0x0 ELF 64-bit MSB MIPS32 rel2 executable, MIPS, version 1 (SYSV)
2969600 0x2D5000 Linux kernel version "2.6.16.26-Cavium-Octeon (william@J10) (gcc version 4.1.1 (Cavium@J10) (gcc version 4.1.1 (Cavium Networks Development Build)) "
2991185 0x2DA451 LZMA compressed data, properties: 0x40, dictionary size: 2097152 bytes, uncompressed size: 2097216 bytes
3329399 0x32CD77 LZMA compressed data, properties: 0x40, dictionary size: 16777216 bytes, uncompressed size: 1073741824 bytes
3429479 0x345467 LZMA compressed data, properties: 0x40, dictionary size: 33554432 bytes, uncompressed size: 131072 bytes
3429503 0x34547F LZMA compressed data, properties: 0x40, dictionary size: 33554432 bytes, uncompressed size: 131072 bytes
3429527 0x345497 LZMA compressed data, properties: 0x40, dictionary size: 33554432 bytes, uncompressed size: 131072 bytes
3504750 0x357A6E LZMA compressed data, properties: 0x5B, dictionary size: 16777216 bytes, uncompressed size: 88 bytes
3915776 0x3BC000 gzip compressed data, from Unix, last modified: Thu Mar 11 16:11:03 2010, max compression
why compressed kernel image is used in linux?
Generally the processor can decompress faster than the I/O system can read. By having less for the I/O system to read, you reduce the time needed for boot.
This assumption doesn't hold for all hardware combinations, of course. But it frequently does.
An additional benefit for embedded systems is that the kernel image takes up less space on the non-volatile storage, which may allow using a smaller (and cheaper) flash chip. Many of these systems have ~ 32MB of system RAM and only ~ 4MB of flash.
u-boot hangs at Uncompressing/Loading Kernel Image
I have limited experience in using FIT, so my observation below could be wrong. Anyhow, it looks to me like the first image of your ftb is being used, which in turn has a configuration which does not include a device tree. You are basically loading a kernel without any information about the hardware (such as where and how to access the uart for the serial console), right? More specifically, I think the kernel needs the "chosen" node (e.g. stdout-path) as described here https://www.kernel.org/doc/Documentation/devicetree/bindings/chosen.txt
I'm in a similar situation (developing a board based on a similar "luton" SoC from Vitesse->Microsemi->Microchip, VSC7425). I'm not having any problems booting linux 5.9 with u-boot 2021.07. Then again, it's not exactly the same hardware nor software.
You could try to move your device tree sub-image into the first image, and replace the first configuration with what is found in the second one.
Extract vmlinux from vmlinuz or bzImage
To extract the uncompressed kernel from the kernel image, you can use the extract-vmlinux
script from the scripts
directory in the kernel tree (available at least in kernel version 3.5) (if you get an error like
mktemp: Cannot create temp file /tmp/vmlinux-XXX: Invalid argument
you need to replace $(mktemp /tmp/vmlinux-XXX)
by $(mktemp /tmp/vmlinux-XXXXXX)
in the script). The command is /path/to/kernel/tree/scripts/extract-vmlinux <kernel image> >vmlinux
.
If the extracted kernel binary contains symbol information, you should¹ be able to create the System.map
file using the mksysmap
script from the same subdirectory. The command here is NM=nm /path/to/kernel/tree/scripts/mksysmap vmlinux System.map
.
¹ The kernel images shipped with my distribution seem to be stripped, so the script was not able to get the symbols.
Related Topics
Lapack/Blas/Openblas Proper Installation from Source - Replace System Libraries with New Ones
Jenkins Cannot Run Firefox: No Protocol Specified Error: Cannot Open Display:: 0
Postgres Copy Command, Binary File
Downloading a Tarball from Github Without Curl
Trying to Install Docker Gpg Key Recieving Error: Curl: Option '-' Is Unknown
Code Behind Rstudio Server Export Function
Removing Parts of a String That Contain Digit with Sed/Perl
Accessing Apache2 Residing Inside Docker Container from Host Machine Web Browser
How to Connect to Docker Container from Localhost
Aws Ec2: How to Remount Previous Ebs Volume Using Pivot_Root
Hugo Version Not Updating to Latest
Bash - Process Backspace Control Character When Redirecting Output to File
Linux Device Driver File Operations: It Is Possible to Have Race Conditions