Skip to content

Instantly share code, notes, and snippets.

@zqidev
Last active December 7, 2024 11:10
Show Gist options
  • Save zqidev/862d29c07a1dca677b743dfe8f9fe6c6 to your computer and use it in GitHub Desktop.
Save zqidev/862d29c07a1dca677b743dfe8f9fe6c6 to your computer and use it in GitHub Desktop.
P2V on Apple Silicon - Converting a Physical Apple Silicon MacBook to a Virtual Machine on another Apple Silicon device (M1, M2, M3) on Apple's Virtualization Framework

P2V on Apple Silicon - Converting a Physical Apple Silicon MacBook to a Virtual Machine on another Apple Silicon device (M1, M2, M3) on Apple's Virtualization Framework

Outline: Having recently bought a MacBook Pro (M3 Max) to replace my MacBook Air (M2), I decided it would be a good idea to start fresh and reinstall everything on my new Mac. However, I always like to keep a backup of my old data, so I thought it would be a good idea to virtualize my old machine on my new machine. Having much previous experience working with Windows P2V's (Physical to Virtual), I figured it would be as simple as Clone, Copy, Restore, and Boot. However, with the advent of Apple's new Signed System Volume, as well as the differences in file systems, APFS containers, and all, this ended up being a project that took about 2 days of nonstop researching, debugging, when I expected it to be a project which would last as long as it would take to clone my drive. I was very wrong. However, with all of my newfound knowledge in this subject, I finally found a way to make it work.

Starting off, virtualization was already rough. I had recently purchased Parallels, and running Windows was pretty difficult - I used many different Windows 11 images, from the one Parallels downloads itself, to tiny11 for arm, and many others. However, they would all end up extremely unstable and unusable, most of them having no UWP support - it would start off fine, but there would be a popup saying "App is not working. App needs an update" (App being Microsoft Store, by the way), and then failing afterwards. I ended up solving that by joining Windows Insider, downloading a vmdk, converting it in Parallels, and then running my own updates and etc. Also, I transferred over a Windows 11 license to an installation I thought was working, but ended up not, so I lost a windows license too. But, tangents over. At first, I thought the steps would be as followed: Make a macOS VM on my new computer, connect my old computer to my new computer, and use USB passthrough to use Migration Assistant to replicate my old computer. However, I realized a really big issue early on: Because I am virtualizing macOS, you have to use Apple's Virtualization Framework. Apple's Virtualization Framework is currently in its early days: it does not support USB passthrough, snapshots, changing hardware, etc. So, I would have to figure out an alternate solution. If you've read this far, I applaud you. This had basically nothing to do with what you probably came here for. I'm just writing this for myself aswell, for future reference, so I don't forget if I ever attempt something like this again.

Cloning the drive from the original device

I used Carbon Copy Cloner because SuperDuper!'s free trial was not enough for my purposes. This should theoretically be possible with hdiutil, but I appreciated the simplicity.

  1. Clone the entire Macintosh HD drive onto an external SSD. The output should be a sparsebundle file, as configured in the CCC output section. I used a sparsebundle file, as the read-only DMG file seemed very limiting and inefficient, but a dmg should work too.
  2. MAKE SURE TO SELECT THE "Legacy Bootable Clone" OPTION WHEN CLONING! image

After that, eject your external SSD. You're done!

Setting up your virtual machine.

I used both Parallels and UTM to do this, using UTM first just to get a feel of how it would work. UTM has a better wrapper for Apple's Virtualization Framework, having the ability to easily add sharable directories and multiple hard drives. Anyway, the general gist remains the same. However, because of UTM's easily configurable options, you should be able to figure it out just from the Parallels commands below.

  1. Create your macOS virtual machine:
prlctl create "macOS VM" -o macos --restore-image /path/to/restore/ipsw

(/path/to/restore/ipsw) is the installer IPSW you get from Apple. As of writing this, I got my installer IPSW from this url.

  1. Configure your virtual machine:
# Create your disk images:
truncate -s 512G disk0.img
truncate -s 512G disk1.img

# Optional:
# Configure different settings:
prlctl set "macOS VM" --show-dev-tools on
prlctl set "macOS VM" --memsize 16384
prlctl set "macOS VM" --cpus 6
  1. Set up your virtual hard drives (Parallels only! Just clicking the UTM "Add Hard Drive" button should take care of everything for you)

By default, Parallels only uses disk0.img as the main hard drive. You will need to add the other hard disk by yourself.

# Make a file called config.ini in your virtual machine directory: It would probably be ~/Parallels/macOS VM.macvm/
Add the following contents into the file:

[Hardware]
Disk1.Path = disk1.img
  1. Set up your shared drives.

Plug in your external SSD with the .dmg / .sparsebundle backup of your original machine. Enable shared directories on UTM / Parallels, with the command in Parallels being

prlctl set "macOS VM" --shf-host-add "BackupDisk" --path /Volumes/{EXTERNAL SSD}/ --mode rw --enable
(BackupDisk can be anything, it'll just be the name of the disk in the VM)

Transferring Data

Now we're all done. Boot up your new VM, and install macOS like you normally would. When you reach the onboarding screen, power off the VM and boot into recovery (Right click the VM and click Start in Recovery Mode)

This is the hard part. Go to terminal.

# Check which disks are which.
diskutil list

# There should be two SSD's. One contains the VM's macOS installation, one blank hard drive, and one DMG image with a synthesized container (this is the recovery image, I'm pretty sure).

# Format the blank hard disk. 
diskutil partitionDisk /dev/diskX 1 gpt apfs "TempDisk" 100%

# Find the disk number of this new disk. 
diskutil list
# In the output, look for the entry which says GUID Partition Scheme in the same category as the volume "TempDisk".
# Note this number down. I will refer to it as TARGETDISK.

# Now, delete the temporary partition. We just needed it to create an APFS container to store all our original data. 
diskutil apfs deletevolume "TempDisk"

# Ok. Now we need to transfer the data from our original MacBook backup to the new disk. 
# Start by mounting the dmg file.
hdiutil mount /path/to/IMAGEFILE -shadow /tmp/img.shadow -noverify

# Now that it's mounted, we will need to find the snapshot ID of the backup DMG. I will refer to this as SNAPSHOTID. It should be something like "com.apple.os_update" or something...
diskutil apfs listSnapshots (path to the disk you just mounted)

# This is a really complex step that is hard to explain. You need to find the snapshot ID "Macintosh HD" partition of the backup image. Look for the entry in "diskutil list" that says "disk image", with a "APFS CONTAINER" under, and next to the "APFS CONTAINER" should show a "diskX". Go to diskX and there should be a "Macintosh HD" section, with a /dev/diskXsY. Note that down, and put it into the command above. I will refer to this as ORIGINALDISK.

# Now we finally start transferring the data. It takes a while. The "asr" (Apple Software Restore) command should show two progress bars.
asr --source ORIGINALDISK --target TARGETDISK -toSnapshot SNAPSHOTID

# Now you're done with the data! Now, for clarity, rename the newly restored TARGETDISK

To rename the targetdisk, just qiut terminal and go to disk utility. there will now be like a lot of entries which say "Macintosh HD". Unmount the disk image, and rename the targetdisk to "Original Macintosh HD" and "Original Data" or something so you can differentiate between the original VM-installed OS and the old MacBook OS.

We're basically done now. I found that directly selecting the original MacBook OS as the startup disk did not work, so I booted into the VM-installed OS, and used Migration Assistant to transfer everything. It was a long, tedious process, but in the end I (hopefully, as of writing this the Migration Assistant is still not done..) got a functional, bootable backup of my old MacBook. If anyone ends up reading this and has questions, please leave them below! Sorry if the steps were unclear, I mostly wrote this for my own reference and I am pretty bad at writing documentation. Also, this is my first time using GitHub Gists aswell!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment