diff --git a/Dockerfile b/Dockerfile
index d1e5e2b..2cc77c4 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,35 +1,22 @@
-FROM --platform=linux/amd64 debian:trixie-slim AS builder
+FROM --platform=$BUILDPLATFORM alpine AS builder
-ARG VERSION_KVM_OPENCORE="v21"
-ARG REPO_KVM_OPENCORE="https://github.com/thenickdude/KVM-Opencore"
+ARG VERSION_OPENCORE="1.0.2"
+ARG REPO_OPENCORE="https://github.com/acidanthera/OpenCorePkg"
+ADD $REPO_OPENCORE/releases/download/$VERSION_OPENCORE/OpenCore-$VERSION_OPENCORE-RELEASE.zip /tmp/opencore.zip
-ARG DEBCONF_NOWARNINGS="yes"
-ARG DEBIAN_FRONTEND="noninteractive"
-ARG DEBCONF_NONINTERACTIVE_SEEN="true"
-
-RUN set -eu && \
- apt-get update && \
- apt-get --no-install-recommends -y install \
- fdisk \
- mtools && \
- apt-get clean && \
- rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
-
-COPY --chmod=755 ./src/build.sh /run
-COPY --chmod=644 ./config.plist /run
-
-ADD $REPO_KVM_OPENCORE/releases/download/$VERSION_KVM_OPENCORE/OpenCore-$VERSION_KVM_OPENCORE.iso.gz /tmp/opencore.iso.gz
-
-RUN gzip -d /tmp/opencore.iso.gz && \
- run/build.sh /tmp/opencore.iso /run/config.plist && \
- rm -rf /tmp/*
+RUN apk --update add unzip && \
+ unzip /tmp/opencore.zip -d /tmp/oc && \
+ cp /tmp/oc/Utilities/macserial/macserial.linux /macserial && \
+ rm -rf /tmp/* /var/tmp/* /var/cache/apk/*
FROM scratch AS runner
-COPY --from=qemux/qemu-docker:6.07 / /
+COPY --from=qemux/qemu-docker:6.08 / /
ARG VERSION_ARG="0.0"
+ARG VERSION_KVM_OPENCORE="v21"
ARG VERSION_OSX_KVM="326053dd61f49375d5dfb28ee715d38b04b5cd8e"
ARG REPO_OSX_KVM="https://raw.githubusercontent.com/kholia/OSX-KVM"
+ARG REPO_KVM_OPENCORE="https://github.com/thenickdude/KVM-Opencore"
ARG DEBCONF_NOWARNINGS="yes"
ARG DEBIAN_FRONTEND="noninteractive"
@@ -38,13 +25,17 @@ ARG DEBCONF_NONINTERACTIVE_SEEN="true"
RUN set -eu && \
apt-get update && \
apt-get --no-install-recommends -y install \
+ xxd \
+ fdisk \
+ mtools \
python3 && \
apt-get clean && \
echo "$VERSION_ARG" > /run/version && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY --chmod=755 ./src /run/
-COPY --chmod=644 --from=builder /images /images
+COPY --chmod=644 ./config.plist /
+COPY --chmod=755 --from=builder /macserial /usr/local/bin/
ADD --chmod=644 \
$REPO_OSX_KVM/$VERSION_OSX_KVM/OVMF_CODE.fd \
@@ -52,8 +43,10 @@ ADD --chmod=644 \
$REPO_OSX_KVM/$VERSION_OSX_KVM/OVMF_VARS-1024x768.fd \
$REPO_OSX_KVM/$VERSION_OSX_KVM/OVMF_VARS-1920x1080.fd /usr/share/OVMF/
-EXPOSE 8006 5900
+ADD $REPO_KVM_OPENCORE/releases/download/$VERSION_KVM_OPENCORE/OpenCore-$VERSION_KVM_OPENCORE.iso.gz /opencore.iso.gz
+
VOLUME /storage
+EXPOSE 8006 5900
ENV VERSION="13"
ENV RAM_SIZE="4G"
diff --git a/readme.md b/readme.md
index 7ee1874..259dc43 100644
--- a/readme.md
+++ b/readme.md
@@ -74,7 +74,7 @@ kubectl apply -f https://raw.githubusercontent.com/dockur/macos/refs/heads/maste
- Choose `Disk Utility` and then select the largest `Apple Inc. VirtIO Block Media` disk.
- - Click the `Erase` button to format the disk, and give it any recognizable name you like.
+ - Click the `Erase` button to format the disk to APFS, and give it any recognizable name you like.
- Close the current window and proceed the installation by clicking `Reinstall macOS`.
diff --git a/src/boot.sh b/src/boot.sh
index 879253f..07955e4 100644
--- a/src/boot.sh
+++ b/src/boot.sh
@@ -2,34 +2,28 @@
set -Eeuo pipefail
# Docker environment variables
-: "${BOOT_MODE:="full"}" # Boot mode
+: "${BOOT_MODE:="macos"}" # Boot mode
BOOT_DESC=""
BOOT_OPTS=""
SECURE="off"
OVMF="/usr/share/OVMF"
-case "${BOOT_MODE,,}" in
- "full" )
+case "${HEIGHT,,}" in
+ "1080" )
DEST="$PROCESS"
- BOOT_DESC=" 1920x1080"
ROM="OVMF_CODE.fd"
VARS="OVMF_VARS-1920x1080.fd"
;;
- "hd" )
+ "768" )
DEST="${PROCESS}_hd"
- BOOT_DESC=" 1024x768"
ROM="OVMF_CODE.fd"
VARS="OVMF_VARS-1024x768.fd"
;;
- "default" )
- BOOT_DESC=""
+ *)
ROM="OVMF_CODE.fd"
VARS="OVMF_VARS.fd"
- DEST="${PROCESS}_default"
- ;;
- *)
- error "Unknown BOOT_MODE, value \"${BOOT_MODE}\" is not recognized!" && exit 33
+ DEST="${PROCESS}_${HEIGHT}"
;;
esac
@@ -58,31 +52,104 @@ fi
BOOT_OPTS+=" -drive if=pflash,format=raw,readonly=on,file=$DEST.rom"
BOOT_OPTS+=" -drive if=pflash,format=raw,file=$DEST.vars"
-# OpenCoreBoot
-BOOT_DRIVE_ID="OpenCore"
-BOOT_DRIVE="$STORAGE/boot.img"
-BOOT_VERSION="$STORAGE/boot.version"
-BOOT_FILE="/images/OpenCore.img.gz"
-BOOT_SIZE=$(stat -c%s "$BOOT_FILE")
-
-CURRENT_SIZE=""
-if [ -f "$BOOT_VERSION" ]; then
- CURRENT_SIZE=$(<"$BOOT_VERSION")
-fi
+IMG="$STORAGE/boot.img"
-if [ "$CURRENT_SIZE" != "$BOOT_SIZE" ]; then
- rm -f "$BOOT_DRIVE" 2>/dev/null || true
-fi
+if [ ! -f "$IMG" ]; then
+
+ FILE="OpenCore.img"
+ IMG="/tmp/$FILE"
+ rm -f "$IMG"
-if [ ! -f "$BOOT_DRIVE" ] || [ ! -s "$BOOT_DRIVE" ]; then
- msg="Extracting boot image"
+ # OpenCoreBoot
+ ISO="/opencore.iso"
+ OUT="/tmp/extract"
+
+ rm -rf "$OUT"
+ mkdir -p "$OUT"
+
+ msg="Building boot image"
info "$msg..." && html "$msg..."
- gzip -dkc "$BOOT_FILE" > "$BOOT_DRIVE"
- echo "$BOOT_SIZE" > "$BOOT_VERSION"
+
+ [ ! -f "$ISO" ] && gzip -dk "$ISO.gz"
+
+ if [ ! -f "$ISO" ] || [ ! -s "$ISO" ]; then
+ error "Could not find image file \"$ISO\"." && exit 10
+ fi
+
+ START=$(sfdisk -l "$ISO" | grep -i -m 1 "EFI System" | awk '{print $2}')
+ mcopy -bspmQ -i "$ISO@@${START}S" ::EFI "$OUT"
+
+ CFG="$OUT/EFI/OC/config.plist"
+ cp /config.plist "$CFG"
+
+ ROM="${MAC//[^[:alnum:]]/}"
+ ROM="${ROM,,}"
+ BROM=$(echo "$ROM" | xxd -r -p | base64)
+ RESOLUTION="${WIDTH}x${HEIGHT}@32"
+
+ sed -r -i -e 's|m7zhIYfl|'"${BROM}"'|g' "$CFG"
+ sed -r -i -e 's|iMacPro1,1|'"${MODEL}"'|g' "$CFG"
+ sed -r -i -e 's|C02TM2ZBHX87|'"${SN}"'|g' "$CFG"
+ sed -r -i -e 's|C02717306J9JG361M|'"${MLB}"'|g' "$CFG"
+ sed -r -i -e 's|1920x1080@32|'"${RESOLUTION}"'|g' "$CFG"
+ sed -r -i -e 's|007076A6-F2A2-4461-BBE5-BAD019F8025A|'"${UUID}"'|g' "$CFG"
+
+ # Build image
+
+ MB=256
+ CLUSTER=4
+ START=2048
+ SECTOR=512
+ FIRST_LBA=34
+
+ SIZE=$(( MB*1024*1024 ))
+ OFFSET=$(( START*SECTOR ))
+ TOTAL=$(( SIZE-(FIRST_LBA*SECTOR) ))
+ LAST_LBA=$(( TOTAL/SECTOR ))
+ COUNT=$(( LAST_LBA-(START-1) ))
+
+ if ! truncate -s "$SIZE" "$IMG"; then
+ rm -f "$IMG"
+ error "Could not allocate space to create image $IMG ." && exit 11
+ fi
+
+ PART="/tmp/partition.fdisk"
+
+ { echo "label: gpt"
+ echo "label-id: 1ACB1E00-3B8F-4B2A-86A4-D99ED21DCAEB"
+ echo "device: $FILE"
+ echo "unit: sectors"
+ echo "first-lba: $FIRST_LBA"
+ echo "last-lba: $LAST_LBA"
+ echo "sector-size: $SECTOR"
+ echo ""
+ echo "${FILE}1 : start=$START, size=$COUNT, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=05157F6E-0AE8-4D1A-BEA5-AC172453D02C, name=\"primary\""
+
+ } > "$PART"
+
+ sfdisk -q "$IMG" < "$PART"
+ echo "drive c: file=\"$IMG\" partition=0 offset=$OFFSET" > /etc/mtools.conf
+
+ mformat -F -M "$SECTOR" -c "$CLUSTER" -T "$COUNT" -v "EFI" "C:"
+ mcopy -bspmQ "$OUT/EFI" "C:"
+
+ rm -rf "$OUT"
+
+ if [[ "$DEBUG" == [Yy1]* ]]; then
+ info ""
+ info "Model: $MODEL"
+ info "Rom: $ROM"
+ info "Serial: $SN"
+ info "Board: $MLB"
+ info ""
+ fi
+
fi
+BOOT_DRIVE_ID="OpenCore"
+
DISK_OPTS+=" -device virtio-blk-pci,drive=${BOOT_DRIVE_ID},bus=pcie.0,addr=0x5,bootindex=$BOOT_INDEX"
-DISK_OPTS+=" -drive file=$BOOT_DRIVE,id=$BOOT_DRIVE_ID,format=raw,cache=unsafe,readonly=on,if=none"
+DISK_OPTS+=" -drive file=$IMG,id=$BOOT_DRIVE_ID,format=raw,cache=unsafe,readonly=on,if=none"
CPU_VENDOR=$(lscpu | awk '/Vendor ID/{print $3}')
DEFAULT_FLAGS="vendor=GenuineIntel,vmware-cpuid-freq=on,-pdpe1gb"
diff --git a/src/build.sh b/src/build.sh
deleted file mode 100644
index e68f1a7..0000000
--- a/src/build.sh
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/env bash
-set -Eeuo pipefail
-
-DST="/images"
-OUT="/tmp/extract"
-
-rm -rf "$OUT"
-rm -rf "$DST"
-
-mkdir -p "$OUT"
-mkdir -p "$DST"
-
-echo "Extracting template image..."
-
-if [ ! -f "$1" ] || [ ! -s "$1" ]; then
- echo "Could not find image file \"$1\"." && exit 10
-fi
-
-START=$(sfdisk -l "$1" | grep -i -m 1 "EFI System" | awk '{print $2}')
-mcopy -bspmQ -i "$1@@${START}S" ::EFI "$OUT"
-
-echo "Building OpenCore image..."
-
-cp "$2" "$OUT/EFI/OC/"
-
-MB=256
-CLUSTER=4
-START=2048
-SECTOR=512
-FIRST_LBA=34
-
-SIZE=$(( MB*1024*1024 ))
-OFFSET=$(( START*SECTOR ))
-TOTAL=$(( SIZE-(FIRST_LBA*SECTOR) ))
-LAST_LBA=$(( TOTAL/SECTOR ))
-COUNT=$(( LAST_LBA-(START-1) ))
-
-FILE="OpenCore.img"
-IMG="/tmp/$FILE"
-rm -f "$IMG"
-
-if ! truncate -s "$SIZE" "$IMG"; then
- rm -f "$IMG"
- echo "Could not allocate file $IMG for the OpenCore image." && exit 11
-fi
-
-PART="/tmp/partition.fdisk"
-
-{ echo "label: gpt"
- echo "label-id: 1ACB1E00-3B8F-4B2A-86A4-D99ED21DCAEB"
- echo "device: $FILE"
- echo "unit: sectors"
- echo "first-lba: $FIRST_LBA"
- echo "last-lba: $LAST_LBA"
- echo "sector-size: $SECTOR"
- echo ""
- echo "${FILE}1 : start=$START, size=$COUNT, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=05157F6E-0AE8-4D1A-BEA5-AC172453D02C, name=\"primary\""
-
-} > "$PART"
-
-sfdisk -q "$IMG" < "$PART"
-
-echo "drive c: file=\"$IMG\" partition=0 offset=$OFFSET" > /etc/mtools.conf
-
-mformat -F -M "$SECTOR" -c "$CLUSTER" -T "$COUNT" -v "EFI" "C:"
-
-echo "Copying files to image..."
-
-mcopy -bspmQ "$OUT/EFI" "C:"
-rm -rf "$OUT"
-
-echo "Compressing image..."
-
-gzip -c "$IMG" > "$DST/$FILE.gz"
-rm -f "$IMG"
-
-echo "Finished succesfully!"
diff --git a/src/install.sh b/src/install.sh
index 3322c21..7d2eed5 100644
--- a/src/install.sh
+++ b/src/install.sh
@@ -3,12 +3,14 @@ set -Eeuo pipefail
# Docker environment variables
-: "${SN:=""}"
-: "${MLB:=""}"
-: "${MAC:=""}"
-: "${UUID:=""}"
-: "${MODEL:="iMacPro1,1"}"
-: "${VERSION:="13"}" # OSX Version
+: "${SN:=""}" # Device serial
+: "${MLB:=""}" # Board serial
+: "${MAC:=""}" # MAC address
+: "${UUID:=""}" # Unique ID
+: "${WIDTH:="1920"}" # Horizontal
+: "${HEIGHT:="1080"}" # Vertical
+: "${VERSION:="13"}" # OSX Version
+: "${MODEL:="iMacPro1,1"}" # Device model
TMP="$STORAGE/tmp"
BASE_IMG_ID="InstallMedia"
@@ -76,8 +78,9 @@ generateID() {
[ -s "$file" ] && UUID=$(<"$file")
[ -n "$UUID" ] && return 0
- UUID=$(cat /proc/sys/kernel/random/uuid)
- echo "${UUID^^}" > "$file"
+ UUID=$(cat /proc/sys/kernel/random/uuid 2> /dev/null || uuidgen --random)
+ UUID="${UUID^^}"
+ echo "$UUID" > "$file"
return 0
}
@@ -92,7 +95,35 @@ generateAddress() {
# Generate Apple MAC address based on Docker container ID in hostname
MAC=$(echo "$HOST" | md5sum | sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/00:16:cb:\3:\4:\5/')
- echo "${MAC^^}" > "$file"
+ MAC="${MAC^^}"
+ echo "$MAC" > "$file"
+
+ return 0
+}
+
+generateSerial() {
+
+ local file="$STORAGE/$PROCESS.sn"
+ local file2="$STORAGE/$PROCESS.mlb"
+
+ [ -n "$SN" ] && [ -n "$MLB" ] && return 0
+ [ -s "$file" ] && SN=$(<"$file")
+ [ -s "$file2" ] && MLB=$(<"$file2")
+ [ -n "$SN" ] && [ -n "$MLB" ] && return 0
+
+ # Generate unique serial numbers for machine
+ SN=$(/usr/local/bin/macserial --num 1 --model "${MODEL}" 2>/dev/null)
+
+ SN="${SN##*$'\n'}"
+ [[ "$SN" != *" | "* ]] && error "$SN" && return 1
+
+ MLB=${SN#*|}
+ MLB="${MLB#"${MLB%%[![:space:]]*}"}"
+ SN="${SN%%|*}"
+ SN="${SN%"${SN##*[![:space:]]}"}"
+
+ echo "$SN" > "$file"
+ echo "$MLB" > "$file2"
return 0
}
@@ -121,8 +152,12 @@ if ! generateID; then
error "Failed to generate UUID!" && exit 35
fi
+if ! generateSerial; then
+ error "Failed to generate serialnumber!" && exit 36
+fi
+
if ! generateAddress; then
- error "Failed to generate MAC address!" && exit 36
+ error "Failed to generate MAC address!" && exit 37
fi
DISK_OPTS="-device virtio-blk-pci,drive=${BASE_IMG_ID},bus=pcie.0,addr=0x6"