5

In short:

How to extract the VERSION, SUBVERSION and PATCHLEVEl numbers from a system backup .img? ideally without root permissions.

Extended:

From the following page:

https://www.raspberrypi.org/downloads/raspbian/

It is provided a Debian zip extracted as .img, which represents a full system backup of a Debian/Raspian system for arm architecture.

For the generation of a custom kernel, it is required to know the VERSION, SUBVERSION and PATCHLEVEL of the system, equivalent to what is provided by the typical

$ uname -r
4.9.0-3-amd64

The easiest way is to load the system directly and run the command, but that is not applicable in this case.

Goal:

The kernel of the image need to be patched and cross-compiled. My intention is to create a script for this process, so it may be "easily" applied further when kernel updates come.

Adrian Maire
  • 1,916
  • 4
  • 20
  • 30

3 Answers3

5

If this is what I think it is, a disk image, then it would be exceedingly difficult to "patch the image" with a new kernel as it would have to not only take the actual kernel file into account, but the rest of the filesystem encoded on the image; the kernel may not be stored in a continuous fashion on the disk due to fragmentation and if the updated kernel is bigger (or smaller for that matter), the filesystem on the image needs to be updated accordingly.

Even if you somehow searched through the whole image for the variables that you are hoping to extract, you wouldn't know if any hits came from files that were actually present on the image's filesystem or from old files that were no longer referenced.

The best advice would be to mount the image and update it, alternatively write it to an SD card, update it and recreate it.

Doing it without mounting the image in one way or another would have to, by necessity, include simulating the filesystem.

Kusalananda
  • 333,661
  • My idea was to download from github the raspian kernel, apply the patch, build and only at the end, push the image to a SD, mount it and override the kernel with my build. Is that in your opinion do-able? – Adrian Maire Sep 15 '17 at 17:37
  • 1
    @AdrianMaire Not being a Linux person, I'd be hesitant to say "yes". On the BSD systems I'm using, updating the kernel without also updating the base system is not generally a good idea as some of the supporting utilities (daemons) may be relying on having been compiled with a particular version of the kernel avaliable. It may work, but it may not. But, as I said, I'm no Linux user and Linux may or may not be more resilient in that way. – Kusalananda Sep 15 '17 at 17:53
  • 1
    @AdrianMaire Someone tells me that as long as the kernel and the rest of the system are not getting too far out of sync, most things ought to work. That means, if you replace a kernel in a system distributed as one complete and tested package, then all bets are off, but you may possibly (likely even?) have something that is still working. – Kusalananda Sep 15 '17 at 18:08
  • 1
    @AdrianMaire I got curious about your last comment, so I asked a question about it: https://unix.stackexchange.com/questions/392512/updating-the-linux-kernel-while-leaving-rest-of-system-as-is – Kusalananda Sep 15 '17 at 19:29
  • Just for information: I managed to patch the kernel with Real-time full preemptive and apply it to the raspberry. It seem to work and return RT in the uname -a result. – Adrian Maire Sep 16 '17 at 14:37
4

This seems to work on the 2017-09-07-raspbian-stretch-lite.img image at that site:

$ sudo kpartx -rva 2017-09-07-raspbian-stretch-lite.img
add map loop0p1 (252:19): 0 85622 linear 7:0 8192
add map loop0p2 (252:20): 0 3528040 linear 7:0 94208
$ sudo mount -r /dev/mapper/loop0p1 mnt
$ LC_ALL=C gawk -v RS='\37\213\10\0' 'NR==2{printf "%s", RS $0; exit}
  ' < mnt/kernel.img | gunzip | grep -aPom1 'Linux version \S+'
Linux version 4.9.41+

(where \37\213\10\0 identifies the start of gzipped data).

As non-root, and assuming the first partition is always 4MiB within the image, using the GNU mtools to extract the kernel.img from that vfat partition:

$ MTOOLS_SKIP_CHECK=1 mtype -i 2017-09-07-raspbian-stretch-lite.img@@4M ::kernel.img|
  LC_ALL=C gawk -v RS='\37\213\10\0' 'NR==2{printf "%s", RS $0; exit}' |
  gunzip | grep -aPom1 'Linux version \K\S+'
4.9.41+

If not, on systems with /dev/fd support (and GNU grep):

MTOOLS_SKIP_CHECK=1 MTOOLSRC=/dev/fd/3 mtype z:kernel.img \
  3<< EOF 4< 2017-09-07-raspbian-stretch-lite.img |
drive z:
  file="/dev/fd/4"
  partition=1

EOF
  LC_ALL=C gawk -v RS='\37\213\10\0' 'NR==2{printf "%s", RS $0; exit}' |
  gunzip | grep -aPom1 'Linux version \K\S+'

(on other systems, use file="2017-09-07-raspbian-stretch-lite.img", the /dev/fd/4 is just for making it easier to adapt to arbitrary file names)

From, the zip file, you should be able to get away without extracting the whole image, just the first partition with:

#! /bin/zsh -
zip=${1?zip file missing}

MTOOLS_SKIP_CHECK=1 mtype -i =(
    unzip -p -- "$zip" | perl -ne '
      BEGIN{$/=\512}
      if ($. == 1) {
        ($offset, $size) = unpack("x454L<2",$_)
      } elsif ($. > $offset) {
        print;
        if ($. == $offset + $size - 1) {exit}
      }') ::kernel.img |
  LC_ALL=C gawk -v RS='\37\213\10\0' 'NR==2{printf "%s", RS $0; exit}' |
  gunzip | grep -aPom1 'Linux version \K\S+'
3

You could try to mount it.

fdisk -l /path/to/your.img

mount -o loop,offset=sector size * start of the partition  your.img /yourfolder

sector size * start of the partition : see fdisk output and multiply

Then you could look at the files in the boot folder.

rudib
  • 1,602
  • The loopback filesystem and losetup have supported partitioned disk images for a while now. Set up the loopback device with losetup -P, then mount the appropriate loopback partition. – Mark Sep 15 '17 at 21:57