Disks, partitions and file systems
Seasoned computer users have no problem distinguishing between disks, partitions and filesystems, but let's analyze them to have a common starting point. A disk is generally a physical device that stores data into randomly-accessible blocks. In more complex setups multiple physical disks can be combined as RAID arrays (either hardware or software) and exposed to the operating system as virtual disks. Partitions are sections on disks that usually hold a filesystem. Filesystems manage how files and data are stored in order to be found later on. In order to make a backup of your Odroid system you will need to preserve the partition information and the contents of the partitions.

Figure 1. Partition layout of an Odroid C1 tripleboot image
All disks start off with a 512 byte block of data that typically holds the bootloader (for x86 systems, 446 bytes) and the Master Boot Record (MBR https://en.wikipedia.org/wiki/Master_boot_record, 64 bytes). The MBR is a table with the start offset, length and partition type of your 4 primary partitions. These are the partitions mapped as 1-4 in the linux kernel (e.g. sda1-sda4 for a disk called sda). The MBR is an old data structure, introduced in 1983, so it has some limitations. The need to use ever-larger disks (>2TB) lead to the introduction of the GPT (GUID Partition Table https://en.wikipedia.org/wiki/GUID_Partition_Table) which replaces the MBR in newer systems. The Odroids can use both MBR and GPT, but the boot media is designed as a MBR volume because of its relatively small size and simplicity.
But, as you can see in figure 1, a disk may have more than 4 partitions. This is achieved by using a trick - one primary partition is marked as "extended" and it can contain any number of logical partitions (linux represents them with numbers from 5 onwards - e.g. sda5, sda6). The partition information for the logical partitions is stored in structures similar to the MBR called Extended Boot Record (EBR https://en.wikipedia.org/wiki/Extended_boot_record) which looks like a linked list (figure 2), but preceeds the actual partition on disk.

Figure 2. EBR position on disk
The partitions you'll usually see on Odroids are FAT16/FAT32 (seen as vfat under the mount command) and ext2/3/4. There are other partition types supported by Linux (e.g. NTFS, XFS, ZFS), but they are usually not critical to the boot process so they will be out of our scope. There are backup tools such as BackupPC (https://www.howtoforge.com/linux_backuppc) or Clonezilla (http://clonezilla.org/) which support more partition types or do backup on file level. These same tools should be used to backup your personal data, such as files, pictures or music. It's also a good idea before starting a backup to do a little "spring cleaning" and delete things you no longer need such as temporary files or downloads, to reduce the time it takes to do the backup and the size of the backup file. For instance, you can delete the cache of downloaded packages via apt with:
Code: Select all
$ sudo apt-get clean
There are a few ways of making a backup of your EMMC/SD card. The simplest to implement is to make a 1:1 binary copy of your data to an image file. For this task you can use a tool such as dd or Win32diskImager. Note that all the commands that follow expect to have the variable $backupDir replaced by the path to your desired backup directory (which can't be on the same partition you're trying to backup for obvious reasons).
Code: Select all
$ sudo dd if=/dev/mmcblk0 of=$backupDir/backup.img bs=1M
Code: Select all
# apt-get install pv
# dd if=/dev/mmcblk0 bs=1M | pv | dd of=$backupDir/backup.img
Code: Select all
$ sudo dd if=$backupDir/backup.img of=/dev/mmcblk0 bs=1M
Code: Select all
# dd if=/dev/mmcblk0 bs=1M | gzip -c > $backupDir/backup.img.gz
# gunzip -c $backupDir/backup.img.gz | dd of=/dev/mmcblk0 bs=1M
"dd" has the advantage that it is easy to use, but to gain backup/restore speed and minimize necessary backup space you need to break up the backup operation into several steps and avoid backing up free space. For this you'll need to backup:
- MBR + EBR
- Bootloader
- Individual partitions
MBR backup and restore
The MBR and EBR are small data structures and can be easily backed up with dd. But because the EBR's position on disk can vary you should rely on a partitioning tool to extract and restore the MBR/EBR data. Such a tool is sfdisk
Code: Select all
$ sudo apt-get install sfdisk
$ sudo sfdisk -d /dev/mmcblk0 > $backupDir/partition_table.txt
Code: Select all
$ sudo sfdisk /dev/mmcblk0 < $backupDir/partition_table.txt
Bootloader backup and restore
Odroids use U-Boot as a bootloader (detailed in Odroid Magazine November 2015: http://magazine.odroid.com/wp-content/u ... pdf#page=6). U-Boot stores its code and data in the unallocated space after the MBR and the beginning of the first partition. There is also some bootstrap code in the first 446 bytes in the first sector (before the partition table). Since the size and structure of U-Boot may differ between Odroid boards, it's safest to do a binary backup of this unallocated space with dd. First you need to find out the start sector of the first partition with sfdisk:
Code: Select all
$ sudo sfdisk -l /dev/mmcblk0

Figure 3. Identify the start sector of the first partition with sfdisk and sector size.
As you can see in figure 3, the first partition (loop0p1) starts at offset 49152. So, we'll need to copy everything up to and including sector 49151. The bs (block size) parameter must match what sfdisk reported in the "Units" line:
Code: Select all
$ sudo dd if=/dev/mmcblk0 of=$backupDir/bootloader.bin bs=512 count=49151
Code: Select all
$ sudo dd if=$backupDir/bootloader.bin of=/dev/mmcblk0 bs=512 skip=1 seek=1
Code: Select all
$ sudo dd if=$backupDir/bootloader.bin of=/dev/mmcblk0 bs=446 count=1
FAT partitions backup and restore
By default HardKernel's images come with a FAT16/32 partition mounted under /media/boot that holds the kernel, initrd, device tree and boot.ini files. All of these are crucial during system startup. Android installs expose this partition as "sdcard" storage.
There are several tools for linux that backup FAT partitions. I used to use partimage, but it fails to verify the checksum of the partitions on C2, so I switched to partclone. Partclone can do a block backup of FAT partitions preserving data at the same offsets, but can skip empty space.
Code: Select all
$ sudo apt-get install partclone
$ sudo partclone.vfat -c -s /dev/mmcblk0p1 -O $backupDir/partition_1.img
To restore a FAT partition you can run this command:
Code: Select all
$ sudo partclone.restore -s $backupDir/partition_1.img -o /dev/mmcblk0p1

Figure 4. Partclone backup with prior unmounting of /media/boot
Unfortunately, partclone will not allow you to restore a partition to a smaller or larger target partition - so any size adjustment you will need to make after the restore is done. Actually you can restore on a larger partition, but you will need to manually grow it to use the extra space later on.
Ext2/3/4 partitions backup and restore
In order to backup and restore Ext2/3/4 filesystems we'll need to use a different tool called fsarchiver. Unlike partclone, fsarchiver creates backup at file level and reconstructs the filesystem upon restore. Unfortunately because of certain particularities of FAT systems where Windows boot files need to be at specific offsets the author of fsarchiver does not support backing up FAT filesystems as well - so we're stuck to using two tools for the job. But with the help of external packages fsarchiver can support other filesystems as well - such as XFS, ReiserFS, JFS, BTRFS and NTFS. It usually backs up unmounted filesystems, but can be used on live filesystems as well with the "-A" flag (may not always work). Fsarchiver has the advantage that it can restore a filesystem in a bigger or smaller target partition preserving UUIDs. In order to back up the second partition you can run the following commands:
Code: Select all
$ sudo apt-get install fsarchiver
$ sudo fsarchiver -o -v -A -j 4 savefs $backupDir/partition_2.fsa /dev/mmcblk0p2
In order to restore a fsa backup you can run this command:
Code: Select all
$ sudo fsarchiver restfs $backupDir/partition_2.fsa id=0,dest=/dev/mmcblk0p2
Note that since fsarchiver supports multiple partitions inside an archive, it needs you to specify which partition id to restore. In our example we store only one partition in an archive, so you'll always specify id=0 when restoring.
SPI Flash
Newer boards, like the development Odroid N1 may feature a low capacity SPI NAND Flash chip designed to store the bootloader and kernel, so that it can boot from network, or from a SATA disk, without the need of a eMMC or SD card. Even if the layout of this chip hasn't been decided fully at the time of this writing, we can still back it up and restore it as a block device with dd. You can get a list (and description) of MTD devices in your Odroid by running:
Code: Select all
$ sudo cat /proc/mtd
dev: size erasesize name
mtd0: 01000000 00001000 "spi32766.0"
Code: Select all
$ sudo dd if=/dev/mtd0 of=$backupDir/flash_mtd0.bin bs=4096
Code: Select all
$ sudo apt-get install mtd-utils
$ sudo flash_erase -q /dev/mtd0 0 0
$ sudo dd if=$backupDir/flash_mtd0.bin of=/dev/mtd0 bs=4096
Now that you know how to do things manually I can hear complaints that backup and restore should be simpler, even point and click operations. I agree - nobody has the time to remember all the command line arguments from various commands. So I hacked together a rudimentary GUI that can walk you through your backup and restore process. Hooray!

Code: Select all
$ sudo wget -O /usr/local/bin/odroid-backup.pl https://raw.githubusercontent.com/mad-ady/odroid-backup/master/odroid-backup.pl
$ sudo chmod a+x /usr/local/bin/odroid-backup.pl
Code: Select all
$ sudo apt-get install libui-dialog-perl zenity dialog libnumber-bytes-human-perl libjson-perl fsarchiver udev util-linux coreutils partclone parted

Figure 5. Zenity vs display rendering
To perform a backup, start the tool in a terminal (sudo odroid-backup.pl) and select "Backup partitions", select OK (1). You will be presented with a list of removable drives in your system (you can start the program with -a to display all drives - this is the case when running directly on the Odroid, since eMMC and SD are shown as non-removable). Select the desired one and click OK (2). You will then be presented with a list of partitions on that drive. Select the ones you wish to back up (3). Next you will have to select a directory where to save the backups. It's best to have a clean directory (4). Press OK and backup will start (you have a rudimentary progress bar to keep you company) (5). When backup is done you will be presented with a status window with the backup results (and possible errors) (6). The backup files have the same naming convention used in this article. To backup a Flash NAND as well you need to re-run the tool and select it from the available disks. You can save the resulting file in the same directory as the partition backups.

Figure 6. Backup steps
To perform a restore, start the tool in a terminal (sudo odroid-backup.pl) and select "Restore partitions" and select OK (1). You will have to select the directory holding your precious backups and select OK (2). In the resulting window select which partitions you wish to restore from the backup and select OK (3). Note that the partitions are restored in the same order as they were on the original disk - meaning partition 1 will be the first partition and so on. In the last window you will be asked on which drive to restore the data (4). Enjoy your time watching the progress bar progressing (5) and in the end you will have a status window with the restore results (6). The log file is also saved in /var/log/odroid-backup.log.

Figure 7. Restore steps
As you might suspect no piece of software is free of bugs, but hopefully this six step script will have its uses. This script has some shortcomings - such as the zenity windows will not always display the instruction text, so I had to add it to the title bar as well, and there is no validation of the backups or restores. You will have to review the log to see that backup or restore didn't have any problems. One other limitation is that FAT partitions need to be manually unmounted before backup. Ext2/3/4 can be backed-up live. Also, the sfdisk on Ubuntu 14.04 doesn't support JSON output, so it will not work there (I can add support if needed). The program was tested backing up and restoring official HardKernel Linux and Android images, as well as tripleboot images, and so far everything seems to work. Ideas for improvement and patches are welcome as always.
Non-interactive operation
Here's how to use it in non-interactive mode. You will need to set the following parameters:
-
--backup
-- to do a backup, or -
--restore
-- to do a restore. Both backup and restore are incompatible at the same time for obvious reasons -
--disk sdc
-- The disk name (without /dev) is validated and an error is printed if that name doesn't exist in your system. Valid options are shown in case you input something wrong -
--partitions bootloader,mbr,/dev/sdc1
-- A comma separated list (with no spaces) of the partitions you want to backup or restore. Valid options are shown in case you input something wrong. When restoring, the partition names have only the number - e.g.bootloader,mbr,1,2
-
--directory
-- The directory to backup to or to restore from. If it doesn't exist it will be created. Previous backups inside will be overwritten with no warning.
Backup
sudo odroid-backup.pl --backup --disk sdc --partitions bootloader,mbr,/dev/sdc1,/dev/sdc2 --directory backup-emmc
sudo odroid-backup.pl --backup --disk mmcblk0 --partitions bootloader,mbr,/dev/mmcblk0p1,/dev/mmcblk0p2 --directory backup-emmc
Restore
sudo odroid-backup.pl --restore --disk sdc --partitions bootloader,mbr,1,2 --directory backup-emmc
sudo odroid-backup.pl --restore --disk mmcblk0 --partitions bootloader,mbr,1,2 --directory backup-emmc
Known limitations
If you backup an emmc for XU3/4, the hidden sectors (/dev/mmcblk0boot0, /dev/mmcblk0boot1) are not backed-up/restored. These blocks contain parts of the UBoot loader. When restoring a backup on an SD card or on a new eMMC, the board might boot with an older UBoot version (stored before the first partition). As a result of this the UBoot environment might be incomplete (e.g. there is no ${board_name} set), and booting might be different than normal. Once you do boot it is recommended that you reinstall uboot with this command on the new card:
Code: Select all
$ sudo apt-get install --reinstall uboot
I've also made an ansible deploy template that installs the dependencies needed by the program: https://github.com/mad-ady/ansible-odro ... ackup.yaml