#!/bin/zsh
set -euo pipefail
VM_DIR="${VM_DIR:-vm}"
DISK_SIZE_GB="${DISK_SIZE:-64}"
CPU_COUNT="${CPU:-8}"
MEMORY_MB="${MEMORY:-8192}"
SEP_STORAGE_SIZE=$((512 * 1024))
SCRIPT_DIR="${0:A:h}"
FW_ROM_DIR="/System/Library/Frameworks/Virtualization.framework/Versions/A/Resources"
ROM_SRC="${FW_ROM_DIR}/AVPBooter.vresearch1.bin"
SEPROM_SRC="${FW_ROM_DIR}/AVPSEPBooter.vresearch1.bin"
while [[ $# -gt 0 ]]; do
case "$1" in
--dir)
VM_DIR="$2"
shift 2
;;
--disk-size)
DISK_SIZE_GB="$2"
shift 2
;;
--rom)
ROM_SRC="$2"
shift 2
;;
--seprom)
SEPROM_SRC="$2"
shift 2
;;
-h | --help)
echo "Usage: $0 [--dir VM] [--disk-size 64] [--rom path] [--seprom path]"
echo ""
echo "Options:"
echo " --dir VM directory name (default: VM)"
echo " --disk-size Disk image size in GB (default: 64)"
echo " --rom Path to AVPBooter ROM (default: framework built-in)"
echo " --seprom Path to AVPSEPBooter ROM (default: framework built-in)"
exit 0
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
DISK_SIZE_BYTES=$((DISK_SIZE_GB * 1024 * 1024 * 1024))
echo "=== vphone create_vm ==="
echo "Directory : ${VM_DIR}"
echo "Disk size : ${DISK_SIZE_GB} GB"
echo "AVPBooter : ${ROM_SRC}"
echo "AVPSEPBooter: ${SEPROM_SRC}"
echo ""
if [[ ! -f "${ROM_SRC}" ]]; then
echo "ERROR: AVPBooter ROM not found: ${ROM_SRC}"
echo " On Apple Internal macOS, this should be at:"
echo " ${FW_ROM_DIR}/AVPBooter.vresearch1.bin"
exit 1
fi
if [[ ! -f "${SEPROM_SRC}" ]]; then
echo "ERROR: AVPSEPBooter ROM not found: ${SEPROM_SRC}"
echo " On Apple Internal macOS, this should be at:"
echo " ${FW_ROM_DIR}/AVPSEPBooter.vresearch1.bin"
exit 1
fi
if [[ -d "${VM_DIR}" ]]; then
echo "WARNING: ${VM_DIR}/ already exists"
if [[ -f "${VM_DIR}/Disk.img" ]]; then
echo " Disk.img already exists — skipping disk creation"
echo " Delete ${VM_DIR}/Disk.img manually to recreate"
fi
else
echo "[1/4] Creating ${VM_DIR}/"
mkdir -p "${VM_DIR}"
fi
if [[ ! -f "${VM_DIR}/Disk.img" ]]; then
echo "[2/4] Creating sparse disk image (${DISK_SIZE_GB} GB)"
dd if=/dev/zero of="${VM_DIR}/Disk.img" bs=1 count=0 seek="${DISK_SIZE_BYTES}" 2>/dev/null
echo " -> ${VM_DIR}/Disk.img ($(du -h "${VM_DIR}/Disk.img" | cut -f1) on disk)"
else
echo "[2/4] Disk.img exists — skipping"
fi
if [[ ! -f "${VM_DIR}/SEPStorage" ]]; then
echo "[3/4] Creating SEP storage (512 KB)"
dd if=/dev/zero of="${VM_DIR}/SEPStorage" bs=1 count="${SEP_STORAGE_SIZE}" 2>/dev/null
else
echo "[3/4] SEPStorage exists — skipping"
fi
echo "[4/4] Copying ROMs"
ROM_DST="${VM_DIR}/AVPBooter.vresearch1.bin"
SEPROM_DST="${VM_DIR}/AVPSEPBooter.vresearch1.bin"
if [[ -f "${ROM_DST}" ]] && cmp -s "${ROM_SRC}" "${ROM_DST}"; then
echo " AVPBooter.vresearch1.bin — up to date"
else
cp "${ROM_SRC}" "${ROM_DST}"
echo " AVPBooter.vresearch1.bin — copied ($(wc -c <"${ROM_DST}" | tr -d ' ') bytes)"
fi
if [[ -f "${SEPROM_DST}" ]] && cmp -s "${SEPROM_SRC}" "${SEPROM_DST}"; then
echo " AVPSEPBooter.vresearch1.bin — up to date"
else
cp "${SEPROM_SRC}" "${SEPROM_DST}"
echo " AVPSEPBooter.vresearch1.bin — copied ($(wc -c <"${SEPROM_DST}" | tr -d ' ') bytes)"
fi
touch "${VM_DIR}/.gitkeep"
echo "[5/4] Generating VM manifest (config.plist)"
"${SCRIPT_DIR}/vm_manifest.py" \
--vm-dir "${VM_DIR}" \
--cpu "${CPU_COUNT}" \
--memory "${MEMORY_MB}" \
--disk-size "${DISK_SIZE_GB}" || {
echo "ERROR: Failed to generate VM manifest"
exit 1
}
echo ""
echo "=== VM created at ${VM_DIR}/ ==="
echo ""
echo "Contents:"
ls -lh "${VM_DIR}/"
echo ""
echo "Manifest (config.plist) saved with VM configuration."
echo "Future boots will read configuration from this manifest."
echo ""
echo "Next steps:"
echo " 1. Prepare firmware: make fw_prepare"
echo " 2. Patch firmware: make fw_patch"
echo " 3. Boot DFU: make boot_dfu"
echo " 4. Boot normal: make boot"