20

I have an image of an existing partition generated with dd if=/dev/sdXN of=image.bin. Now I want to use this image as the basis for a virtual machine. I know how to convert the image into a format that VirtualBox can use.

The problem is that the "disk" image is really just the image of one partition and thus does not contain an MBR or a partition table. This makes it very hard to boot the VM.

Is there a simple way, given an image of a partition, to create a proper disk image, including a partition table?

5 Answers 5

13

You can do this on the host machine. Most tools like fdisk will operate on files, and kpartx gives you access to partitions in a file.

  1. Create a new empty 100GiB sparse image (make this slightly bigger than the size of the partition image)

    dd if=/dev/zero of=myvm.img bs=1G count=0 seek=100
    
  2. Partition the image file with fdisk

    fdisk myvm.img
    
  3. Make the partitions in the image file available is individual devices

    sudo kpartx -a myvm.img
    
  4. Copy the partition image into the partition

    sudo cp image.bin /dev/mapper/loop0p1
    
  5. Extend the filesystem to fill the entire partition

    sudo resize2fs /dev/mapper/loop0p1
    
  6. Close the partitions

    sudo kpartx -d myvm.img
    
  7. Dismantle the loopback device

    sudo losetup -D
    
7
  • Would this not make the created partition in the image "not match" the length of the imaged partition? And is there a way to solve that? And, would a "smart enough" filesystem manager be able to tell that it isn't using the whole partition size and expand itself to fit?
    – killermist
    Jun 19, 2012 at 23:44
  • @killermist Updated answer.
    – mgorven
    Jun 20, 2012 at 1:11
  • This is a good answer. Do you know any way to avoid copying the whole thing in the process? Jun 20, 2012 at 11:09
  • @MikaFischer Unfortunately not, because the partition table needs to exist before the partition, and I don't know of any mechanism to prepend data to a file.
    – mgorven
    Jun 20, 2012 at 16:36
  • I think Harun's answer is better because it is easy to do and can be scripted. Jan 12, 2014 at 8:09
10

I'm sure the original problem was solved long ago, but for anybody with a similar problem:

One way to avoid copying the whole image would be to create a .vmdk format image that refers to separate extent files for the partition table and for the partition contents.

I have this snippet lying around in a .vmdk file from a test I did a while ago:

RW 63 FLAT "parttable.bin" 0
RW 585937489 FLAT "partition-image.bin" 63

This means that the 63 sectors starting from offset 0 are read from the raw file "parttable.bin", but sector 63 and upwards come from the raw partition dump "partition-image.bin". (Of course, replace 63 with the actual offset to the first partition, usually 2048 these days).

The end result is that, from inside VBox, it looks like you have prepended the partition table on to the front of the partition image, without having to do the lengthy copy operation.

Partition the drive from within the VM and, if you get your offsets right, you should see your partition image contents inside the newly-created partition.

5
  • 2
    I think the '63' on second line needs to be 0 if partition-image.bin is a partition image. I have just done something like this and I needed to set this offset in partition image file to zero. philatwarrimoo.blogspot.com.au/2014/01/… Jan 12, 2014 at 8:06
  • Genius. I just had to do this to use a Windows partition for a VM on a Linux host, and this is the only thing that worked, using the steps from @philcolbourn: superuser.com/a/804396/93066
    – bmaupin
    Aug 28, 2014 at 19:19
  • What should be in the rest of the vmdk file?
    – gozzilli
    Nov 30, 2017 at 23:38
  • 1
    @gozzilli The rest of the file is a bunch of details like file version numbers, disk adaptor type, uuids and disk geometry. I don't know how to write those bits. I would recommend just using a tool to create a vmdk pointing at the disk image and then modify only the lines describing where to get the extra partition header from.
    – Harun
    Dec 1, 2017 at 7:13
4

Interesting problem. Here's what I would do:

  1. Create the VM with a disk appropriately large then boot it from a recovery CD.
  2. Gain access to your existing disk image somehow (nfs, cifs, etc.).
  3. Create the partitions you'll need on the VM's local disk.
  4. Use dd to write the partition image into the partition on the vm disk.

After this is done you'll need to update your boot loader. Assuming you're using GRUB, mount the newly written partition then chroot into it and run update-grub (be careful though, you may need to adjust its config files before it will work right).

Good luck!

2

You can resize the filesystem in place, with GParted.

Create the test image:

dd if=/dev/zero of=extfs bs=1M count=20
mkfs.ext4 extfs

I'm not using resize2fs, because it resizes the file, rather than leaving free space.

sudo losetup /dev/loop0 extfs
sudo ln -s /dev/loop0 /dev/loop0p1 # needed for GParted to be able to resize it
gksudo gparted /dev/loop0

Free 1 MB at the start.

sudo rm /dev/loop0p1
sudo losetup -d /dev/loop0

Finally, create the partition table.

fdisk extfs

Set the first sector to 2048 (2048 sectors * 512 B/sector = 1MB), last sector the default (i.e. end of image).

1

I personally prefer to append using dd.

I'm assuming 512-byte sectors here. There may be a case for 2048-byte sectors, so just swap the numbers in and do the maths.

In each case I'm using a 512MB test file for example:

dd if=/dev/zero of=testfs.img bs=512 count=1M mkfs.ext4 testfs.img

MBR

Composing the image

I personally prefer to append the first MB (2048 sectors) to its beginning:

dd if=testfs.img skip=2048 bs=512 of=full.img

Finally run fdisk to create the partition table (or copy in your own), I created 1 partition using default values.

Verifying

To verify, create loop partitions and autodetect:

sudo losetup -fP full.img

And run file on the resultant partitioned loopback device:

sudo file -s /dev/loop2p1 /dev/loop2p1: Linux rev 1.0 ext4 filesystem data, UUID=ae2945fd-54b5-486f-8dd0-9b18d6ae01b4 (extents) (large files) (huge files)

GPT

Composing the image

I personally prefer to append the first MB (2048 sectors, as gdisk will default to this number as it is 1 MB aligned) to its beginning for the beginning MBR and 34 sectors to its end (or 2048 for a full MB) for the end GPT (end sector may be different). Omitting the end GPT may lose you data:

dd if=testfs.img skip=2048 bs=512 of=full.img dd if=/dev/zero seek=1050624 bs=512 of=full.img count=34

Finally run gdisk to create the partition table (or copy in your own), I created 1 partition using default values.

Verifying

To verify, create loop partitions and autodetect:

sudo losetup -fP full.img

And run file on the resultant partitioned loopback device:

sudo file -s /dev/loop2p1 /dev/loop2p1: Linux rev 1.0 ext4 filesystem data, UUID=ae2945fd-54b5-486f-8dd0-9b18d6ae01b4 (extents) (large files) (huge files) This method ensures no guessing, resizing or manually aligning.

3
  • How do you find the end sector of the image in gpt
    – Anwar
    Oct 29, 2019 at 17:04
  • When i run this sudo file -s /dev/loop11p1 I got /dev/loop11p1: data . Which previously was an ext4 filesystem. And the resulting full.img is smaller. I think you've got the solution reversed.
    – Anwar
    Oct 29, 2019 at 17:22
  • I think you mean seek=2048 in this command dd if=testfs.img skip=2048 bs=512 of=full.img
    – Anwar
    Oct 30, 2019 at 6:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .