Version 4 (modified by 7 years ago) ( diff ) | ,
---|
Linux Block Storage Devices
Imaging a Block device
To place a root filesystem on a removable block storage device (mSATA disk, microSD card, USB Mass Storage device) you need to to the following:
- Partition the device
- Format the partition(s)
- Install the rootfs to the partition
The popular Linux filesystem used today is ext4 which has the following features:
- Built-in to most kernels (allowing it to be your root filesystem)
- Journalling support
- Can be re-sized even if mounted (via
resize2fs
)
The following commands will perform the above steps on a Linux development host. For convenience we set an env variable to represent the block device - take care to set this properly so as not to format a partition vital to your host (such as its rootfs)
- Determine device:
DEVICE=/dev/sdc
- Partition device:
printf "2048,,L,,\n" | sudo sfdisk -uS ${DEVICE}
- here we create a single Linux (type 83) partition offset at 1MiB - you can adjust the parameters to create multiple partitions depending on your needs
- Format the partition as ext4
sudo mkfs.ext4 ${DEVICE}1
- Note that if you put this into a script I've found you need to have a second or so of a sleep following the
sfdisk
to allow the OS to re-scan the partition table before it will realize that the partition exists
- Note that if you put this into a script I've found you need to have a second or so of a sleep following the
- Mount the partition:
sudo mount ${DEVICE}1 /mnt/disk
- make sure /mnt/disk exists - this is simply a mount-point
- Un-archive the rootfs tarball:
sudo tar -C /mnt/disk -xvf rootfs.tar.bz2
- If instead you have a rootfs directory created with
fakeroot
ordeboostrap
you can copy it with asudo cp -rupv rootfs/* /mnt/disk
- If instead you have a rootfs directory created with
- Unmount the partition:
sudo umount /mnt/disk
mmcblk0 Imaging
If the Desktop/Laptop being used to flash the microSD device shows up as /dev/mmcblk0 then it will act slightly different than the standard storage device (/dev/sda).
Follow the below example and adjust as necessary:
DEVICE=/dev/mmcblk0 printf "2048,,L,,\n" | sudo sfdisk --force --unit S ${DEVICE} sudo mkfs.ext4 ${DEVICE}p1 sudo mount ${DEVICE}p1 /mnt/disk sudo tar -C /mnt/disk -xvf rootfs.tar.bz2 sudo umount /mnt/disk
Imaging from U-Boot
For block device based boards, Gateworks has created an installable U-Boot script that will apply block device image files containing either an entire disk image or a single partition image (see the below section for creating disk images). This can be particularly useful for updating the firmware of a running target.
To update a block device:
1. Compress your image
In most situations the DRAM of your device will be smaller than the image file required to update your system, therefore it is necessary to split the image file and apply the resulting compressed parts in a piece wise update.
FILE=openwrt_1602_8gb.img # Split file every 500M with suffix ".part" and decimal increment split -d -b 500M ${FILE} ${FILE}.part gzip ${FILE}.* for i in $(ls ${FILE}.*); do mv $i ${FILE}.gz.$(echo $i | cut -d'.' -f3) done # Result will be 16 files such as openwrt_1602_8gb.img.gz.partXX # which adhere to the naming convention expected by the scriptIf you have a small image file that when compressed will fit into your device's DRAM, a simple
gzip -k ${FILE}
will suffice.2. Install the U-Boot script
On the target machine, source the block_image_update.scr U-Boot script attached to this page (or copy its contents with an editor). For example via tftp:
setenv serverip 192.168.1.100 tftp block_image_update.scr source $loadaddr3. Configure your U-Boot environment
From the script's usage:
The following environment variables need to be set in order for this script to run: imagefile - full path file name of gzipped (.gz) file devtype - interface type of target block device devnum - device number of target partoffset - start of target partition in bytes (0 for full disk image) Optional environment variable arguments: splitsuffix - the suffix of the split gzipped file (eg .part for file.img.gz.part00) imageload - the command, up to the file name, that will load your imagefile to loadaddr (defaults to [tftp 0x12000000])An example configuration:
setenv imagefile openwrt_1602_8gb.img.gz # image file from example above setenv devtype mmc # mmc interface for eMMC or uSD setenv devnum 0 # first device setenv partoffset 100000 # target the 1st partition at 1M offset setenv splitsuffix ".part" # suffix from example above setenv imageload "tftp ${loadaddr}" # command to load the image file (can be ext4load)
4. Run the added script with
run block_image_update
Disk Images
Compressed Disk Images (technically 'block device images') can be easily created on a Linux system with dd
and gzip
. This works for any block device (ie rotational disk, SSD, uSD, USB Mass Storage disk) and doesn't care at all what is on the disk. This is a very common technique for distributing pre-built OS images because it preserves the partitioning scheme of the disk you are imaging.
Compared to distributing filesystem images or archives of filesystem contents this has method has some pro's and con's:
- Pro's:
- Other OS's can install this type of image onto another block storage device (such as Windows via USB Image Tool)
- Con's:
- Images are created from a fixed-size block device and require the same or larger size block device to be installed onto
- After installation any additional storage space (ie installing an image meant for a 2GB microSD onto a 16GB microSD) can not be used until the disk is re-partitioned and re-sized
- Device sizes vary greatly - various manufacturers 4GB stick will likely not have the same number of cylinders (thus bytes) as another. If you try to expand an image onto a smaller device it will fail. Therefore you should probably tell dd to only grab perhaps 95% of the disk. For example, if you are imaging a 4GB stick (1024*0.95=972). I have 3x 4GB block devices here and the smallest is shown by
sfdisk
as 3.677GiB.sudo dd if=/dev/sdc bs=4M count=941 conv=notrunc,noerror | gzip -c > disk-img.gz
Creating a disk image
Procedure to create disk image from /dev/sdc
:
- (Optional) Zero out the storage device first (if not already done) to allow for the best compression as even if previous contents have been 'deleted' the data still exists (the filesystem directory table has just unlinked from it):
sudo dd if=/dev/zero of=/dev/sdc bs=4M
- Copy and gzip to a file:
sudo dd if=/dev/sdc bs=4M conv=sync,noerror | gzip -c > disk-img.gz
- You can use another compressor other than gzip if you wish but make sure those needing to use these images can support that compression
- The
conv=sync,noerror
tellsdd
to not fail on error and pad any partial or failed blocks with zeros
Note that these steps can take some time depending on the speed of your storage device. For example each step can take 10mins on an 8GB micro-SD over USB or 3mins on a 2GB micro-SD over USB
Using a disk image
Procedure to write a disk image back to /dev/sdc
:
- Linux:
zcat disk-img.gz | sudo dd of=/dev/sdc bs=4M
- Windows:
- See USB Image Tool
Note that this can take a some time depending on the write speed of your storage device. For example you will likely see times such as 4mins for 2GB and 30mins for 8GB micro-SD
Once booted you can use OS specific commands to resize partitions to take advantage any unused space on the device (for example, if the image was created using a 2GB microSD and you placed it onto a 16GB you can expand partitions to use the extra 14GB)
You can do this in Linux for an ext2/3/4 filesystem with resize2fs
. Because resize2fs
will not alter the partition table you need to do that first.
The following example assumes you have a single ext filesystem and will resize it using resize2fs
, partprobe
, and sfdisk
:
- Install necessary tools (assuming Ubuntu/debian):
apt-get install parted sfdisk e2fsprogs
- Use
sfdisk
to repartition:DEVICE=/dev/mmcblk0 # IMX6 microSD host (use /dev/sda for a USB or SATA disk) df -h . # show current size/used/avail sfdisk --list ${DEVICE} # show current printf "2048,,L,,\n" | sfdisk --force --no-reread -uS ${DEVICE} # re-create partition sfdisk --list ${DEVICE} # show new
- Use
partprobe
(or reboot system) to force kernel to re-read the partition table of device with mounted filesystems:partprobe # re-read partition table
- Use
resize2fs
to resize a partition to take up newly allocated space:resize2fs ${DEVICE}*1 # resize first partition
Attachments (1)
-
block_image_update.scr
(3.5 KB
) - added by 7 years ago.
blockdev_image_update.scr
Download all attachments as: .zip