Disk image of OS + Recovery partition?
Starting from a working setup
A working setup is disk, or full-disk image with multiple partitions (FDI hereafter), where the OS and its recovery partition is known to be correct, most likely because it was created by the OS Installer. As mentioned in the comment, asr
is enough to handle copying both partitions in this case.
Assuming the source OS and recovery partitions are disk3s11
and disk3s12
, respectively, I recommend the following procedure:
-
Shrink the OS partition to its minimum size. This isn't necessary, but I suggest doing it when you can never be sure if the user's target partition will be as big as the one you're using.
$ diskutil resizeVolume disk3s11 limits ... (minimum size will be mentioned here) ... $ diskutil resizeVolume disk3s11 24GB
-
Create appropriately-sized temporary FDI as a sparsebundle. Remember, the Recovery takes extra 650 MB over the system partition, and EFI takes another 210 MB. So I'll add an extra GB to the size used in step 1 just to be safe. The catch here is,
hdiudil
support only binary prefixes (1024 fork
, etc.). In this example, 25 GB = 23.29 GiB.$ hdiutil create -layout GPTSPUD -type SPARSEBUNDLE -size 23.29g /tmp/temp_FDI created: /tmp/temp_FDI.sparsebundle
-
Attach the image without mounting it (it would fail, since the partition was not formatted). Take note of the
/dev/
entry for the Apple_HFS partition.$ hdiutil attach /tmp/temp_FDI.sparsebundle -nomount /dev/disk5 GUID_partition_scheme /dev/disk5s1 EFI /dev/disk5s2 Apple_HFS
-
Run
asr
with the image's empty partition as the target. You'll have to enter full path to/dev/...
entries. Also, since the source is a physical disk, elevated privileges are necessary. You should see the tool finish with 2 rows of Restoring... progress.$ sudo asr restore --source /dev/disk3s11 --target /dev/disk5s2 --erase --noverify Validating target...done Validating source...done Erase contents of /dev/disk5s2 ()? [ny]: y Validating sizes...done Restoring ....10....20....30....40....50....60....70....80....90....100 Restoring ....10....20....30....40....50....60....70....80....90....100
-
Finally, create a compressed read-only image from the sparsebundle. Use the sparsebundle's "whole disk"
/dev/
entry (/dev/disk5
).$ hdiutil create -format ULFO -srcdevice /dev/disk5 -o /tmp/OS_X_10.11-combined_FDI2.dmg ... Elapsed Time: 2m 33.743s File size: 8000565446 bytes, Checksum: CRC32 $5D496986 Sectors processed: 48842670, 38032196 compressed Speed: 120.8Mbytes/sec Savings: 68.0% created: /tmp/OS_X_10.11-combined_FDI2.dmg
You may wish to use
UDZO
format if you need your image to be compatible with older versions of OS X and their respective Recovery environments (ULFO was only introduced in 10.11).
Working from the ground up
It is possible to assemble a "working setup" from single-partition images (images which don't have partition table, and therefore no hint for asr
that a particular partition is a Recovery; SPI hereafter). The procedure is not for the faint of heart.
I'm going to assume that I have a compressed, read-only SPIs of both the system partition, and the recovery partition. Shrinking the partitions to minimum size is a whole another can of worms, where using a full-blown UDRW
image seems unavoidable. Feel free to suggest a simpler solution.
-
With that in mind, do a pre-shrink of the system partition image. Readonly image can only be shrunk with a shadow.
$ hdiutil resize -sectors min OS_X_10.11-system.dmg -shadow /tmp/pre-shrink.shadow
-
Check the image size, then attach it
$ hdiutil imageinfo OS_X_10.11-system.dmg -shadow /tmp/pre-shrink.shadow ... Total Bytes: 27648868352 $ hdiutil attach OS_X_10.11-system.dmg -shadow /tmp/pre-shrink.shadow -nomount ... /dev/disk7
The size is about 27.65 GB.
-
Create a sparse image big enough to hold the system and recovery partitions in full size - AFAICT, SPIs cannot be resized and that must be done inside an FDI. With extra space needed for EFI and recovery, we'll need 28.6 GB = 26.64 GiB.
$ hdiutil create -layout GPTSPUD -type SPARSEBUNDLE -size 26.64g /tmp/temp_FDI $ hdiutil attach /tmp/temp_FDI.sparsebundle -nomount /dev/disk5 GUID_partition_scheme /dev/disk5s1 EFI /dev/disk5s2 Apple_HFS
-
Do an
asr
restore from the system SPI's/dev/
node into the sparsebundle's data partition.$ asr restore --source /dev/disk7 --target /dev/disk5s2 --erase --noverify
-
Now, check the minimum size of the partition using
diskutil
. Then useresizeVolume
to shrink the partition and create the recovery partition in a single step.$ diskutil mount disk5s2 $ diskutil resizeVolume disk5s2 limits ... (minimum size will be mentioned here) ... $ diskutil resizeVolume disk5s2 24GB JHFS+ Recovery %recovery% Free\ Space dummy 1m
-
Restore the recovery SPI into the new partition on the FDI. It will probably get mounted, so unmount it. You can work with the image directly.
$ asr restoreexact --source /path/to/OS_X_10.11-recovery.dmg --target /dev/disk5s3 --erase --noverify ... $ diskutil umount disk5s3
-
Here's the tricky bit - dump the partition table using the
gpt
utility, taking note of the recovery partition's start and size values. Delete the record for the recovery partition, and re-add it with modified type GUID. You will know which record is for the recovery partition by the index ("disk5s3"), and by its size (shown here in 512 B sectors).$ gpt show disk5 ... 47546784 1269536 3 GPT part - "Recovery" ... $ gpt remove -i 3 disk5 $ gpt add -b 47546784 -s 1269536 -t 426F6F74-0000-11AA-AA11-00306543ECAC disk5
-
Optional: I also recommend changing the partition name (set to "disk image" by default) to match the system partition's volume name.
$ gpt label -i 2 -l "OS X 10.11" disk5
-
Now, since
hdiutil resize
doesn't work with sparsebundles the way we'd need, you can either:- Leave it at that. It's not like the free space consumes anything. Continue with step 5 in the Working setup scenario.
- Convert the temp_FDI.sparsebundle image to UDRW, and try to properly shrink that. I haven't tested that and the need to write out the entire size image for this step makes the whole exercise pointless.
- Treat the sparsebundle existing at this point as a disk with optimally-shrunk system, and perform the first scenario on it, skipping step 1. Ie. create another sparsebundle image, and run
asr
, which will this time copy both partitions into the new image, and convert that to ULFO image.
Restoring
Steps for restoring from the created image:
-
Mount the image using
# hdiutil attach /tmp/backup_image.dmg -nomount
-
Start the restore, either by:
- Use the "Disk Utility" app, restoring from the partition in the backup_image to the partition on your drive (the one in Sierra just works, restoring the Recovery partition too: you will see two Restoring/Verifying steps)
-
Use
asr
, similarly as described above:$ asr restore --source /dev/disk1s2 --target /dev/disk0s4 --erase --noverify