TL;DR: Clone partition with dd, convert to vmdk with qemu-img (splitting is optional with VBoxManage), create a new VM in Fusion, create a second virtual drive to host EFI partition, install bootloader on new EFI and change fstab with new UUID accordingly. Boot into the VM, defragment drive, zero out leftover space and request Fusion to shrink space
I like virtualisation. It isn’t the silver bullet that can remedy every possible situation but with the fine tuned ability to integrate or isolate an instance and the community that has been built around it, virtualisation proves itself to be an incredibly useful tool.
I am a
filthy casual who likes to occasionally game but the bloat on Windows 10 is what drove me to macOS but alas, Catalina strikes and the few games I could play couldn’t run anymore. No Mojave downgrade for me because Xcode 11.
The solution? The tux. Marjaro XFCE (the sweet rolling releases of Arch Linux with the simplicity of Xubuntu), Steam (and therefore Proton), Lutris (and therefore Wine) seemed to be an option that was not “install Windows 10 and deal with it” or “install Windows 7” (my motherboard has no Windows 7 drivers that I can use) or “just get a copy of LTSC and reset the trial every 60 days”.
I dual-booted whenever I could to play but found not being able to switch between work and play instantaneously was a bit annoying.
The solution? VMWare Fusion with generous VRAM. But I don’t want to redo my setup or re-download my library (it took two weeks to download).
So, now I finally had a reason to image my physical
ext4 partition and run it on as a guest macOS, without ever reading the files on the partition via macOS.
A form of (preferrably external) storage twice the capacity of the partition that you intend to clone
macOS High Sierra or higher (because Homebrew does not officially support anything below that)
The latest Homebrew package manager
A live disk image of the operating system you are running on the physical drive
Presuming you have the Homebrew package manager, we will install QEMU and VirtualBox (even though I will be using VMWare Fusion later because of VirtualBox VRAM limits), so to fetch those packages
$ brew install qemu coreutils $ brew cask install virtuabox
Performing our physical-to-virtual partition conversion⌗
Alright, now we have the tools, now let’s first convert make an image of the partition on our external volume
We need sudo here because we are attempting to seek read permissions from /dev/driveXsY Replace X and Y with the respective drive numbers Replace EXTERN with the name of your external volume $ sudo gdd if=/dev/diskXsY of=/Volumes/EXTERN/disk0.img status=progress
Done? Now, you should verify the integrity of the disk by attempting to checksum match the original partition with our new image
Replace X and Y with the respective drive numbers Replace EXTERN with the name of your external volume $ sha256sum /dev/diskXsY b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 $ sha256sum /Volumes/EXTERN/disk0.img b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 They're the same, :)
Converting our clone into a virtual drive⌗
Confident we have exactly the same thing? Now let’s get rid of that partition on our internal volume so we can accommodate the new drive. I just used Disk Utility for that.
With that done, now let’s convert our image into a vmdk file that VMWare Fusion can use
NOTE: I am performing this step on the external volume, if you’re satisfied with a monolithic disk image, then you can just write it to the internal volume directly
$ qemu-img convert -O vmdk /Volumes/EXTERN/disk0.img /Volumes/EXTERN/disk0.vmdk
Splitting our monolithic virtual drive⌗
If you don’t plan on using VMWare Fusion (maybe something like VirtualBox, which requires VMDK files to not exceed 2GB) or you prefer split disk images, then you can convert them to a split image
Replace INTERNALDRV with the name of your internal volume $ VBoxManage clonemedium /Volumes/EXTERN/disk0.vmdk /Volumes/INTERNALDRV/disk0.vmdk --format VMDK --variant Split2G
Making the virtual machine boot⌗
NOTE: These step is not necessary if you have imaged the entire drive (and therefore all its partitions and volumes) or if you image the EFI partition using the steps above
With our files ready, now we a system drive that won’t boot.
Why? Because the EFI is housed elsewhere (and I can’t image the EFI partition because I changed my bootloader), so we will have to repair that.
Before we do that, we must create a new virtual disk of a gigabyte and boot the VM with both drives. I have made my boot virtual drive NVME and my system drive SATA so I can recognise it easily.
Now, within the live disk, partition our new virtual drive to be a giant FAT32 EFI partition (i.e. with
esp flags) using GParted. You may need to initialise a new partition table, if you need to, then select GPT.
We can safely presume that our new boot partition is now
/dev/nvme0n1p1 and our system volume is
/dev/sda1 because there is no partition table on our system drive at all because we only imaged a singular partition)
Let’s start by installing the GRUB bootloader
We need to gain access as root of our system drive, so let's set up the needed tools $ sudo pacman -Sy arch-install-scripts Go to "File Explorer", open our newfangled system volume and copy its UUID and paste it in place of our dummy UUID $ sudo arch-chroot /run/media/manjaro/DUMMYUUID-UUID-0000-0000-3e2f0b6fcfd9/ We are now in chroot (and therefore, acting as root within our system drive) # mount /dev/nvme0n1p1 /boot/efi We install the GRUB bootloader # grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=GRUB
We’re not done yet, the bootloader is installed but the UUID of our EFI partition is different from what the physical EFI partition originally had, grab the new UUID (not
UUID) and replace UUID value for
# blkid /dev/nvme0n1p1: UUID="UUID-0000" BLOCK_SIZE="512" TYPE="vfat" PARTUUID="DUMMYUUID-UUID-0000-0000-06045437bb06" # nano /etc/fstab
We’re done! 🎉
(I mean, I could barely game, but yay?) EDIT: Fixed by going to VMWare Fusion > Preferences > Gaming > Always optimise mouse for games and then increasing mouse sensitivity within Manjaro
Shrinking the virtual disk image⌗
Edit (18th June): The conversion of the raw DD image to a virtual disk image reduced the image size from 500GB to ~300GB but because I was running short of storage real estate, here is a way of reducing it even further
Unfortunately, one of the downsides of the method I used is that I cannot do any partitioning on my virtual disk because there is no partition table to speak of.
The solution? (at least if you are using a VMWare product and have already installed
open-vm-tools) is asking VMWare to figure it out for you.
Defragment the drive first $ sudo e4defrag / Zero out all the unused space (to mark it as unused) $ dd if=/dev/zero of=wipefile bs=1M; sync; rm wipefile Request VMWare to shrink all the disks associated with the VM $ sudo vmware-toolbox-cmd disk shrinkonly