Modify raw image file in Linux

Raw img VS ISO img

Similarity

  1. They are both byte by byte copy of block device.

Difference

  1. ISO images have no partition table. They are read only.

  2. Raw images have partition tables and they are read/write.

Modify Raw Images

In this section we talk about how to modify raw images.

Mount the image

First we have to mount the image to poke around its content. In a GUI you might just double-click the image file. This would normally mount the image in read-only mode which means you can check its content, but there’s not much more you can do about the content.

Instead you should mount it as read/write mode, which is the default mode of mount. But before any mount command, you should figure out which partition you want to mount since there are several partitions in that image. To do that you can use the fdisk command

fdisk -l raw_img_file.img

A sample output could look like

raw_img_file.img: 128 MiB, 134217728 bytes, 262144 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xf110ee87

Device            Boot  Start    End Sectors Size Id Type
raw_img_file.img1        2048 100351   98304  48M 83 Linux
raw_img_file.img2      100352 253951  153600  75M 83 Linux
raw_img_file.img3      253952 262143    8192   4M 83 Linux

As we can see, firstly, it says that each sector is 512 bytes long (Sector size (logical/physical): 512 bytes / 512 bytes ), then that there’s a mountable partition that starts on sector 2048. If you want to mount that partition, you’ll have to pass that information along

mount -o loop,offset=1048576 raw_img_file.img /path/to/img/mount/point

Please check the mannual page of mount for details about these parameters.

Dismount the image

After done modifying the content, dismount the image with

umount /path/to/img/mount/point

And then you can copy it to a USB flash drive with dd

dd bs=1M if=raw_img_file.img of=/dev/sdX

where sdX is wherever your system maps your USB driver.

Modify ISO Images

For an ISO image, you have to copy its content out, edit as you wish, then re-burn the whole image.

Reference

https://www.linux.com/news/how-modify-raw-disk-image-your-custom-linux-distro/

Additional information

Add space to the image

This section is just copied from a web post. I haven’t tried it yet since the tool it uses works for ext2/3/4 file systems, not the one my image file is using.

You might find there’s not many space left on the img file for your modification

df -h /path/to/img/mount/point
Filesystem      Size  Used Avail Use% Mounted on 
/dev/loop0      3.1G  2.7G  265M  92%

You have to make the mounted partition bigger and this is where things get sticky.

Use parted to check some basic info about this image

# parted ArduinoOS_Redux.x86_64-0.0.XX.raw
GNU Parted 3.2 
Using /home/[your user]/ArduinoOS_Redux.x86_64-0.0.XX.raw 
Welcome to GNU Parted! Type 'help' to view a list of commands. 
(parted) print free
Model:  (file) 
Disk /home/[your user]/ArduinoOS_Redux.x86_64-0.0.XX.raw: 3427MB 
Sector size (logical/physical): 512B/512B 
Partition Table: msdos 
Disk Flags:  

Number  Start   End     Size    Type     File system  Flags 
      32.3kB  1049kB  1016kB           Free Space 
1      1049kB  3427MB  3426MB  primary  ext3         boot, type=83

The ~1MB free space at the beginning is actually the partition info. We have to add space at the end.

dd if=/dev/zero bs=1M count=512 >> ArduinoOS_Redux.x86_64-0.0.XX.raw

Then again in parted

# parted ArduinoOS_Redux.x86_64-0.0.XX.raw
GNU Parted 3.2 
Using /home/[your user]/ArduinoOS_Redux.x86_64-0.0.XX.raw 
Welcome to GNU Parted! Type 'help' to view a list of commands. 
(parted) print free                                                        
Model:  (file) 
Disk /home/[your user]/ArduinoOS_Redux.x86_64-0.0.XX.raw: 3964MB 
Sector size (logical/physical): 512B/512B 
Partition Table: msdos 
Disk Flags:  

Number  Start   End     Size    Type     File system  Flags 
      32.3kB  1049kB  1016kB           Free Space 
1      1049kB  3427MB  3426MB  primary  ext3         boot, type=83 
      3427MB  3964MB  537MB            Free Space

(parted) resizepart 1 3964MB
(parted) print free
Model: (file) 
Disk /home/[your user]/ArduinoOS_Redux.x86_64-0.0.XX.raw: 3964MB 
Sector size (logical/physical): 512B/512B 
Partition Table: msdos 
Disk Flags:  

Number  Start   End     Size    Type     File system  Flags 
      32.3kB  1049kB  1016kB           Free Space 
1      1049kB  3964MB  3963MB  primary  ext3         boot, type=83

parted‘s resizepart instruction takes two parameters: the partition to resize — in this case 1 — and the new end of the partition. As you saw two listings up, the empty space you created ends at the 3964MB mark, so you use that with resizepart.

But, resizepart works fine with real disks, for raw image, this is not enough. Therefore comes the kpartx tool. It take a raw image of a disc and create a “virtual device” in /dev/mapper that can then be manipulated as a real device with real partitions:

# kpartx -a ArduinoOS_Redux.x86_64-0.0.XX.raw

The -a option adds an entry, so if you now look under /dev/mapper:

$ ls /dev/mapper/ 
control  loop0p1

We first check the virtual partition:

# e2fsck -f -y -v -C 0 /dev/mapper/loop0p1
e2fsck 1.42.13 (17-May-2015) 
Pass 1: Checking inodes, blocks, and sizes 
Pass 2: Checking directory structure                                            
Pass 3: Checking directory connectivity 
Pass 4: Checking reference counts 
Pass 5: Checking group summary information 
                                                                              
     86010 inodes used (41.10%, out of 209248) 
      5413 non-contiguous files (6.3%) 
        83 non-contiguous directories (0.1%) 
           # of inodes with ind/dind/tind blocks: 5404/51/0 
    726741 blocks used (86.89%, out of 836352) 
         0 bad blocks 
         1 large file 

     69360 regular files 
      8272 directories 
         7 character device files 
         4 block device files 
         0 fifos 
      7797 links 
      8358 symbolic links (8166 fast symbolic links) 
         0 sockets 
------------ 
     93798 files

Then we try to resizing the file system

# resize2fs -p /dev/mapper/loop0p1
resize2fs 1.42.13 (17-May-2015) 
Resizing the filesystem on /dev/mapper/loop0p1 to 967424 (4k) blocks. 
Begin pass 1 (max = 4) 
Extending the inode table     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 
The filesystem on /dev/mapper/loop0p1 is now 967424 (4k) blocks long.

We can now delete the virtual device

# kpartx -d ArduinoOS_Redux.x86_64-0.0.XX.raw
Chao Cheng
Chao Cheng
Statistician

My research interests include applied statistics and machine learning.