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.