5

I am creating an empty file...

dd if=/dev/zero of=${SDCARD} bs=1 count=0 seek=$(expr 1024 \* ${SDCARD_SIZE})

...then turning it into an drive image...

parted -s ${SDCARD} mklabel msdos

...and creating partitions on it

parted -s ${SDCARD} unit KiB mkpart primary fat32 ${IMAGE_ROOTFS_ALIGNMENT} $(expr ${IMAGE_ROOTFS_ALIGNMENT} \+ ${BOOT_SPACE_ALIGNED})
parted -s ${SDCARD} unit KiB mkpart primary $(expr  ${IMAGE_ROOTFS_ALIGNMENT} \+ ${BOOT_SPACE_ALIGNED}) $(expr ${IMAGE_ROOTFS_ALIGNMENT} \+ ${BOOT_SPACE_ALIGNED} \+ $ROOTFS_SIZE)

How do I use mkfs.ext and mkfs.vfat without mounting this image?

3

You want to format a partition in a disk-image file, rather than the entire image file. In that case, you need to use losetup to tell linux to use the image file as a loopback device.

NOTE: losetup requires root privileges, so must be run as root or with sudo. The /dev/loop* devices it uses/creates also require root privs to access and use.

e.g (as root)

# losetup /dev/loop0 ./sdcard.img

# fdisk -l /dev/loop0
Disk /dev/loop0: 1 MiB, 1048576 bytes, 2048 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: 0x54c246ab

Device       Boot Start   End Sectors   Size Id Type
/dev/loop0p1          1  1023    1023 511.5K  c W95 FAT32 (LBA)
/dev/loop0p2       1024  2047    1024   512K 83 Linux

# file -s /dev/loop0p1
/dev/loop0p1: data

# mkfs.vfat /dev/loop0p1 
mkfs.fat 3.0.28 (2015-05-16)
Loop device does not match a floppy size, using default hd params

# file -s /dev/loop0p1
/dev/loop0p1: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "mkfs.fat", sectors/cluster 4, root entries 512, sectors 1023 (volumes <=32 MB) , Media descriptor 0xf8, sectors/FAT 1, sectors/track 32, heads 64, serial number 0xfa9e3726, unlabeled, FAT (12 bit)

and, finally, detach the image from the loopback device:

# losetup -d /dev/loop0

See man losetup for more details.

4

To create an image with multiple partitions, a solution that doesn't require any fancy tools or root access is to first create the filesystems, then concatenate them.

truncate -s $IMAGE_ROOTFS_ALIGNMENT disk
truncate -s $BOOT_SPACE_ALIGNED part1
mkfs.fat part1
cat part1 >>disk
truncate -s $ROOTFS_SIZE part2
mkfs.ext4 part2
cat part2 >>disk

Then run parted or fdisk to create the partitions.

This approach has the downside that the resulting image won't be sparse.

0

To expand on the answer provided by @gilles, here's one way to create a disk image containing a formatted filesystem by first creating a filesystem (of type ESP in this example) within a file and then assembling that to a valid disk image; no root, mounts or loop devices required:

diskimg=diskimg    # filename of resulting disk image
size=$((260*(1<<20))) # desired size in bytes, 260MB in this case
alignment=1048576  # align to next MB (https://www.thomas-krenn.com/en/wiki/Partition_Alignment)
size=$(( (size + alignment - 1)/alignment * alignment ))  # ceil(size, 1MB)

# mkfs.fat requires size as an (undefined) block-count; seem to be units of 1k
mkfs.fat -C -F32 -n "volname" "${diskimg}".fat $((size >> 10))

# insert the filesystem to a new file at offset 1MB
dd if="${diskimg}".fat of="${diskimg}" conv=sparse obs=512 seek=$((alignment/512))
# extend the file by 1MB
truncate -s "+${alignment}" "${diskimg}"

# apply partitioning
parted --align optimal "${diskimg}" mklabel gpt mkpart ESP "${offset}B" '100%' set 1 boot on

The above approach has the side-benefit of being sparse when used on a filesystem that supports sparse files; the resulting "262MB" file occupies less than 200kB on disk:

du -h --apparent diskimg; du -h diskimg
262M    diskimg
196K    diskimg

For FAT filesystems the Mtools utilities support operating on an offset into a file (ext2/4/etc probably do as well?). This makes it easier, you just create the partitioned image and work on that directly:

diskimg=diskimg
size=$((260*(1<<20))) # desired size in bytes, 260MB in this case
# align to next MB (https://www.thomas-krenn.com/en/wiki/Partition_Alignment)
alignment=1048576

size=$(( (size + alignment - 1)/alignment * alignment ))

# image size is gpt + filesystem size + gpt backup
truncate -s $((size + 2*alignment)) "${diskimg}"

parted --machine --script --align optimal "${diskimg}" mklabel gpt mkpart ESP "${alignment}B" '100%' set 1 boot on

mformat -i "${diskimg}"@@"${alignment}" -t $((size>>20)) -h 64 -s 32 -v "volname"

Here's a diagram of the resulting image file:

partitioned image file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.