Monthly Archives: February 2021

Reading images created with imageUSB on Windows via Linux

I’ve started to catch up on a set of technology refresh projects in my house related to Linux machines running on small systems, such as the Raspberry Pi family and the ODROID line of systems. As part of this effort, I wanted to make a quick backup of an SD card. I had a Windows 10 system close at hand with a card reader so I found a free utility called imageUSB from Passmark Software that could do the job of making an image backup. However, I found that I initially was not able to read this disk image on a Linux system. This article shows both why this was a problem and two ways to work around that problem.

The SD card was from a system called pi2, a Raspberry Pi 2 that had been running Raspbian based on Debian Stretch and NOOBS. I had already successfully used a fresh SD card to install the latest Raspberry Pi OS on that system and I had done some spot-backups of things like /etc and configuration files from /home/pi but I wanted to have the full boot media available from another Linux system.

When I tried to attach that backup file (pi-2021-02-12.bin) in Linux with the loop device using losetup, it did not see any partitions. I suspected that maybe the partition data was not actually present at the start of the file, so I inspected the file:

root@example:/media/bak/pi2# od -a pi2-2021-02-12.bin  | head
 0000000   i nul   m nul   a nul   g nul   e nul   U nul   S nul   B nul
 0000020 nul nul nul nul nul nul nul nul nul nul nul nul nul nul nul nul
 0000040 soh nul nul nul enq nul nul nul   k etx nul nul nul nul nul nul
 0000060 nul nul can   5 etx nul nul nul  si   @   %   4  gs soh nul nul
 0000100   3 nul   5 nul   1 nul   E nul   0 nul   4 nul   9 nul   9 nul
 0000120   9 nul   9 nul   E nul   3 nul   D nul   1 nul   9 nul   A nul
 0000140   1 nul   6 nul   D nul   9 nul   6 nul   D nul   C nul   E nul
 0000160   1 nul   D nul   0 nul   5 nul   8 nul   6 nul   B nul   6 nul
 0000200 nul nul   2 nul   F nul   6 nul   8 nul   4 nul   D nul   1 nul
 0000220   B nul   B nul   3 nul   8 nul   9 nul   7 nul   3 nul   2 nul

See the first line of output? It has “imageUSB” interspersed with nul characters. This was a clue that this software left some sort of mark on the file. A quick Google search lead to a discussion on a forum describing how imageUSB  adds a 512 byte header to every start of every image it creates. It looks easy enough to fix with dd though by skipping one 512 byte block when copying it:

root@example:/media/bak/pi2# dd bs=512 skip=1 if=pi2-2021-02-12.bin of=pi2-2021-02-12.img &
[1] 19058
root@example:/media/bak/pi2# ls -l
total 15613848
-rw-r--r-- 1 root     staff         451 Feb 13 15:20 README.md
-rw-rw-r-- 1 user     staff 15931539968 Feb 12 23:18 pi2-2021-02-12.bin
-rw-r--r-- 1 root     staff    41401856 Feb 13 15:21 pi2-2021-02-12.img
-rw-rw-r-- 1 user     staff        1126 Feb 12 22:09 pi2-2021-02-12.log
root@example:/media/bak/pi2# ls -l
total 15654436
-rw-r--r-- 1 root     staff         451 Feb 13 15:20 README.md
-rw-rw-r-- 1 user     staff 15931539968 Feb 12 23:18 pi2-2021-02-12.bin
-rw-r--r-- 1 root     staff    82951680 Feb 13 15:21 pi2-2021-02-12.img
-rw-rw-r-- 1 user     staff        1126 Feb 12 22:09 pi2-2021-02-12.log
root@example:/media/bak/pi2# file pi2-2021-02-12.img
pi2-2021-02-12.img: DOS/MBR boot sector; partition 1 : ID=0xe, start-CHS (0x80,0,1), end-CHS (0x3ff,3,16), startsector 8192, 129024 sectors; partition 2 : ID=0x5, start-CHS (0x3ff,3,16), end-CHS (0x3ff,3,16), startsector 137216, 30979072 sectors

Even better, it’s not really necessary to fix with dd in order to read this file as a Linux loop device as one can simply use the -o or --offset parameter of losetup to skip the imageUSB header:

root@example:/media/bak/pi2# losetup --find --show pi2-2021-02-12.bin -o 512 /dev/loop0 root@example:/media/bak/pi2# sfdisk -l /dev/loop0 Disk /dev/loop0: 14.9 GiB, 15931539456 bytes, 31116288 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: 0xf64b6124 Device        Boot    Start      End  Sectors  Size Id Type/dev/loop0p1           8192   137215   129024   63M  e W95 FAT16 (LBA)/dev/loop0p2         137216 31116287 30979072 14.8G  5 Extended/dev /loop0p5         139264   204797    65534   32M 83 Linux/dev/loop0p6        3604480  3700735    96256   47M  c W95 FAT32 (LBA)/dev/loop0p7        3702784  7614463  3911680  1.9G 83 Linux/dev/loop0p8        7618560  7759871   141312   69M  c W95 FAT32 (LBA)/dev/loop0p9        7766016 20439037 12673022    6G 83 Linux/dev/loop0p10      20439040 24414207  3975168  1.9G 83 Linux/dev/loop0p11      24416256 31115263  6699008  3.2G 83 Linux

This didn’t do it at first though… the loop devices for each partition that I expected to see did not get created. Running partprobe did not work either to find the partitions. I found some advice on forcing losetup to rescan the partition table by appending a -P parameter that worked though.

root@example:/media/bak/pi2# losetup -d /dev/loop0
root@example:/media/bak/pi2# losetup --find --show pi2-2021-02-12.bin -o 512 -P
/dev/loop0
root@example:/media/bak/pi2# lsblk | grep loop
loop0                                       7:0    0  14.9G  0 loop|-loop0p1                                 259:0    0    63M  0 loop|-loop0p2                                 259:1    0     1K  0 loop|-loop0p5                                 259:2    0    32M  0 loop|-loop0p6                                 259:3    0    47M  0 loop|-loop0p7                                 259:4    0   1.9G  0 loop|-loop0p8                                 259:5    0    69M  0 loop|-loop0p9                                 259:6    0     6G  0 loop|-loop0p10                                259:7    0   1.9G  0 loop`-loop0p11                                259:8    0   3.2G  0 loop
root@example:/media/bak/pi2# mount /dev/loop0p10 /mnt/tmp
root@example:/media/bak/pi2# ls -l /mnt/tmp
total 12
drwx------ 2 1000 1000 4096 Jan 11 20:46 ssh-B65YqdJu83g3
drwx------ 2 1000 1000 4096 Jan 11 20:46 ssh-LrQyz3U9EXMx
drwx------ 3 root root 4096 Nov  1 18:17 systemd-private-2379166a348446dab60162396dcdc36f-systemd-timesyncd.service-p0zvYV
root@example:/media/bak/pi2# # that was the tmp directory
root@example:/media/bak/pi2# umount /mnt/tmp
root@example:/media/bak/pi2# mount /dev/loop0p11 /mnt/tmp
root@example:/media/bak/pi2# ls -l /mnt/tmp
total 24
drwx------  8 root root  4096 Feb  7 19:09 docker
drwx------  2 root root 16384 Dec 21  2018 lost+found
drwxr-xr-x 32 1000 1000  4096 Feb  8 00:00 pi
root@example:/media/bak/pi2# # that was the home directory

Although not being able to read this backup file from Linux initially was a bit frustrating to deal with, in fixing it I learned some new tricks regarding Linux loop devices. I hope this is useful to other people who might be facing the same issue.