Merge pull request #55 from jaminmc/AutoSerial

Auto generate new Serial numbers!
This commit is contained in:
Gabriel Luchina 2025-07-23 11:02:03 -03:00 committed by GitHub
commit a60e53cb92
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 465 additions and 78 deletions

4
.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "tools/GenSMBIOS"]
path = tools/GenSMBIOS
url = https://github.com/jaminmc/GenSMBIOS.git
branch = AddCli

View File

@ -67,7 +67,7 @@ check_status "Failed to install git"
# Clone repository
log_message "Cloning OSX-PROXMOX repository..."
git clone https://github.com/luchina-gabriel/OSX-PROXMOX.git /root/OSX-PROXMOX >> "$LOG_FILE" 2>&1
git clone --recurse-submodules https://github.com/luchina-gabriel/OSX-PROXMOX.git /root/OSX-PROXMOX >> "$LOG_FILE" 2>&1
check_status "Failed to clone repository"
# Ensure directory exists and setup is executable

536
setup
View File

@ -6,21 +6,21 @@
# https://luchina.com.br
#
# COPYRIGHT - 2021, 2022
#
# All rights reserved - You may not copy, reproduce, distribute, publish, display, perform, modify,
# create derivative works, transmit, or in any way exploit any such content, nor may you distribute
# any part of this content over any network, including a local area network, sell or offer it for
# sale, or use such content to construct any kind of database.
#
# You may not alter or remove any copyright or other notice from copies of the content on any scripts
# in the solution of 'OSX-PROXMOX Solution - GABRIEL LUCHINA'.
#
# Copying or storing any content except as provided above is expressly prohibited without prior
# written permission of copyright holder identified in the individual contents copyright notice.
#
# For permission to use the content 'OSX-PROXMOX Solution - GABRIEL LUCHINA',
# All rights reserved - You may not copy, reproduce, distribute, publish, display, perform, modify,
# create derivative works, transmit, or in any way exploit any such content, nor may you distribute
# any part of this content over any network, including a local area network, sell or offer it for
# sale, or use such content to construct any kind of database.
#
# You may not alter or remove any copyright or other notice from copies of the content on any scripts
# in the solution of 'OSX-PROXMOX Solution - GABRIEL LUCHINA'.
#
# Copying or storing any content except as provided above is expressly prohibited without prior
# written permission of copyright holder identified in the individual contents copyright notice.
#
# For permission to use the content 'OSX-PROXMOX Solution - GABRIEL LUCHINA',
# please contact legal@luchina.com.br
#
#
# FOR DEV/STUDENT ONLY PURPOSES - NOT COMERCIAL
#
# Credits:
@ -37,7 +37,7 @@ SCRIPT_DIR="/root/OSX-PROXMOX"
LOGDIR="${SCRIPT_DIR}/logs"
MAIN_LOG="${LOGDIR}/main.log"
TMPDIR="${SCRIPT_DIR}/tmp"
HACKPXVERSION="2025.06.27"
HACKPXVERSION="2025.07.23"
OCVERSION="1.0.4"
DEFAULT_VM_PREFIX="HACK-"
BASE_RAM_SIZE=4096
@ -48,6 +48,7 @@ MAX_CORES=16
DHCP_CONF_DIR="/etc/dhcp/dhcpd.d"
NETWORK_INTERFACES_FILE="/etc/network/interfaces"
DHCP_USER="dhcpd"
OPENCORE_ISO="opencore-osx-proxmox-vm.iso"
# macOS version configuration
declare -A MACOS_CONFIG=(
@ -199,6 +200,26 @@ ensure_jq_dependency() {
fi
}
# Function to ensure xmlstarlet is installed
ensure_xmlstarlet_dependency() {
local logfile="${LOGDIR}/xmlstarlet-dependency.log"
if ! command -v xmlstarlet >/dev/null 2>&1; then
display_and_log "Installing xmlstarlet..." "$logfile"
apt-get update >>"$logfile" 2>&1 || log_and_exit "Failed to update apt" "$logfile"
apt-get install -y xmlstarlet >>"$logfile" 2>&1 || log_and_exit "Failed to install xmlstarlet" "$logfile"
fi
}
# Function to ensure base64 and xxd are available
ensure_base64_xxd_dependency() {
local logfile="${LOGDIR}/base64-xxd-dependency.log"
if ! command -v base64 >/dev/null || ! command -v xxd >/dev/null; then
display_and_log "Installing base64 and xxd..." "$logfile"
apt-get update >>"$logfile" 2>&1 || log_and_exit "Failed to update apt" "$logfile"
apt-get install -y coreutils xxd vim-common >>"$logfile" 2>&1 || display_and_log "Failed to install base64 and xxd. Editing ROM in base64 format." "$logfile"
fi
}
# Function to set ISODIR based on selected ISO storage
set_isodir() {
local logfile="${LOGDIR}/iso-storage-detection.log"
@ -317,7 +338,7 @@ setup_prerequisites() {
sed -i "s/ftp.$country.debian.org/ftp.debian.org/g" /etc/apt/sources.list
apt-get update >>"$logfile" 2>&1 || log_and_exit "Failed to update apt" "$logfile"
}
apt-get install -y vim unzip zip sysstat parted wget iptraf git htop ipcalc >>"$logfile" 2>&1 || log_and_exit "Failed to install packages" "$logfile"
apt-get install -y vim unzip zip sysstat parted wget iptraf git htop ipcalc coreutils vim-common xmlstarlet >>"$logfile" 2>&1 || log_and_exit "Failed to install packages" "$logfile"
sed -i 's/GRUB_TIMEOUT=5/GRUB_TIMEOUT=0/g' /etc/default/grub
local grub_cmd="quiet"
if [[ $OSX_PLATFORM == "AMD" ]]; then
@ -366,8 +387,12 @@ download_recovery_image() {
# Function to create VM
create_vm() {
local version_name=$1 vm_id=$2 vm_name=$3 disk_size=$4 storage=$5 core_count=$6 ram_size=$7 iso_size=$8 disk_type=$9 bridge=${10}
local iso_file version_name=$1 vm_id=$2 vm_name=$3 disk_size=$4 storage=$5 core_count=$6 ram_size=$7 iso_size=$8 disk_type=$9 bridge=${10}
local logfile="${LOGDIR}/crt-vm-${OSX_PLATFORM,,}-${version_name,,}.log"
iso_file="${OPENCORE_ISO}"
if [ ! -f "${ISODIR}/$iso_file" ]; then
update_opencore_iso
fi
[[ ! -d "/sys/class/net/$bridge" ]] && log_and_exit "Bridge $bridge does not exist" "$logfile"
local cpu_args device_args='-device isa-applesmc,osk="ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc" -smbios type=2'
@ -399,7 +424,7 @@ create_vm() {
--onboot 0 --ostype other --sockets 1 --start 0 --tablet 1 \
--vga vmware --vmgenid 1 --scsihw virtio-scsi-pci \
--"$disk_type" "${storage}:${disk_size},cache=none,discard=on" \
--ide0 "${storage_iso}:iso/opencore-osx-proxmox-vm.iso,media=cdrom,cache=unsafe,size=96M" \
--ide0 "${storage_iso}:iso/${iso_file},media=cdrom,cache=unsafe,size=96M" \
--ide2 "${storage_iso}:iso/recovery-${version_name,,}.iso,media=cdrom,cache=unsafe,size=${iso_size}" >>"$logfile" 2>&1 || log_and_exit "Failed to create VM" "$logfile"
sed -i 's/media=cdrom/media=disk/' "/etc/pve/qemu-server/$vm_id.conf" >>"$logfile" 2>&1 || log_and_exit "Failed to update VM config" "$logfile"
@ -419,8 +444,7 @@ add_no_subscription_repo() {
elif pveversion | grep -q "pve-manager/[8]"; then
printf "deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription\n" > /etc/apt/sources.list.d/pve-no-sub.list
elif pveversion | grep -q "pve-manager/[9]"; then
printf "Types: deb\nURIs: http://download.proxmox.com/debian/pve\nSuites: trixie\nComponents: pve-no-subscription\nSigned-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
\n" > /etc/apt/sources.list.d/pve-no-sub.sources
printf "Types: deb\nURIs: http://download.proxmox.com/debian/pve\nSuites: trixie\nComponents: pve-no-subscription\nSigned-By: /usr/share/keyrings/proxmox-archive-keyring.gpg\n" > /etc/apt/sources.list.d/pve-no-sub.sources
else
log_and_exit "Unsupported Proxmox version" "$logfile"
fi
@ -429,16 +453,407 @@ add_no_subscription_repo() {
read -n 1 -sp "Press any key to return to menu..."
}
# Cleaned function to update the SMBIOS in the OpenCore ISO
update_opencore_smbios() {
local iso_path=$1 oc_json_path=$2
local logfile="${LOGDIR}/update-opencore-smbios.log"
ensure_xmlstarlet_dependency
ensure_base64_xxd_dependency "$logfile"
ensure_jq_dependency
if [[ ! -f "$oc_json_path" ]]; then
read -rp "No Serial number generated. Do you want to generate a unique serial number? [Y/n]: " GENSMBIOS
if [[ "${GENSMBIOS:-Y}" =~ ^[Yy]$ ]]; then
SystemProductName="iMacPro1,1"
read -e -p "Enter System Product Name (press Enter to keep current): " -i "$SystemProductName" new_value
if [ -n "$new_value" ] && [ "$new_value" != "$SystemProductName" ]; then
SystemProductName="$new_value"
fi
python3 "$SCRIPT_DIR"/tools/GenSMBIOS/GenSMBIOS.py --install
python3 "$SCRIPT_DIR"/tools/GenSMBIOS/GenSMBIOS.py --generate "$SystemProductName" -j "$oc_json_path" >>"$logfile" 2>&1 || log_and_exit "Failed to generate SMBIOS" "$logfile"
else
display_and_log "Skipping SMBIOS generation" "$logfile"
return
fi
fi
local loopdev=$(losetup -f --show -P "$iso_path") || log_and_exit "Failed to set up loop device" "$logfile"
mkdir -p /mnt/opencore >>"$logfile" 2>&1 || log_and_exit "Failed to create mount point" "$logfile"
mount "${loopdev}p1" /mnt/opencore >>"$logfile" 2>&1 || log_and_exit "Failed to mount ISO" "$logfile"
local config="/mnt/opencore/EFI/OC/config.plist"
[[ ! -e "$config.backup" ]] && cp "$config" "$config.backup" >>"$logfile" 2>&1
# Temporary file
local TEMP_FILE="${config}.tmp"
cp "$config" "$TEMP_FILE"
# Define base XPaths
local nvram_xpath="//key[text()='NVRAM']/following-sibling::dict/key[text()='Add']/following-sibling::dict/key[text()='7C436110-AB2A-4BBB-A880-FE41995C9F82']/following-sibling::dict"
local platform_generic_xpath="//key[text()='PlatformInfo']/following-sibling::dict/key[text()='Generic']/following-sibling::dict"
# Function to read a value from plist
read_plist_value() {
xmlstarlet sel -t -v "${2}/key[text()='${3}']/following-sibling::*[1]" "$1" 2>/dev/null
}
# Function to update a value in plist
update_plist_value() {
xmlstarlet ed -L -u "${2}/key[text()='${3}']/following-sibling::*[1]" -v "$4" "$1"
}
# Load and apply JSON values
declare -A json_values
json_values["SystemProductName"]=$(jq -r '.Type // empty' "$oc_json_path")
json_values["SystemSerialNumber"]=$(jq -r '.Serial // empty' "$oc_json_path")
json_values["MLB"]=$(jq -r '."Board Serial" // empty' "$oc_json_path")
json_values["SystemUUID"]=$(jq -r '.SmUUID // empty' "$oc_json_path")
json_values["ROM"]=$(jq -r '.ROM // empty' "$oc_json_path") # HEX
updated=false
for key in SystemProductName SystemSerialNumber MLB SystemUUID ROM; do
if [ -n "${json_values[$key]}" ]; then
if [ "$key" == "ROM" ]; then
if command -v base64 >/dev/null 2>&1 && command -v xxd >/dev/null 2>&1; then
modified_value=$(echo -n "${json_values[$key]}" | xxd -r -p | base64)
else
display_and_log "Warning: base64 or xxd not available. Skipping ROM update." "$logfile"
continue
fi
else
modified_value="${json_values[$key]}"
fi
update_plist_value "$TEMP_FILE" "$platform_generic_xpath" "$key" "$modified_value"
display_and_log "Updated $key from JSON." "$logfile"
updated=true
fi
done
# Automatic boot-args adjustment
system_product_name=$(read_plist_value "$TEMP_FILE" "$platform_generic_xpath" "SystemProductName")
boot_args=$(read_plist_value "$TEMP_FILE" "$nvram_xpath" "boot-args")
flag=" -nehalem_error_disable"
if [ "$system_product_name" = "MacPro5,1" ]; then
if [[ ! "$boot_args" =~ $flag ]]; then
new_boot_args="$boot_args$flag"
update_plist_value "$TEMP_FILE" "$nvram_xpath" "boot-args" "$new_boot_args"
display_and_log "Automatically added '$flag' to boot-args." "$logfile"
updated=true
fi
else
if [[ "$boot_args" =~ $flag ]]; then
new_boot_args="${boot_args//$flag/}"
update_plist_value "$TEMP_FILE" "$nvram_xpath" "boot-args" "$new_boot_args"
display_and_log "Automatically removed '$flag' from boot-args." "$logfile"
updated=true
fi
fi
if $updated; then
display_and_log "Differences between original and modified file (unified format):" "$logfile"
xmlstarlet fo "$config" > "$config.fmt" || log_and_exit "Failed to format original file" "$logfile"
diff -u "$config.fmt" "$TEMP_FILE" || true
rm "$config.fmt"
read -p "Do you want to apply these changes to the original file? (y/n): " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
mv "$TEMP_FILE" "$config"
display_and_log "Changes applied to $config" "$logfile"
else
display_and_log "Changes discarded." "$logfile"
rm "$TEMP_FILE"
fi
else
display_and_log "No updates needed from JSON." "$logfile"
rm "$TEMP_FILE"
fi
# Cleanup
umount /mnt/opencore >>"$logfile" 2>&1 || log_and_exit "Failed to unmount ISO" "$logfile"
losetup -d "$loopdev" >>"$logfile" 2>&1 || log_and_exit "Failed to detach loop device" "$logfile"
}
# Cleaned function to customize OpenCore config.plist
customize_opencore_config() {
local oc_json_path iso logfile="${LOGDIR}/custom-oc-config.plist.log"
iso="${ISODIR}/${OPENCORE_ISO}"
oc_json_path="${ISODIR}/.smbios.json"
ensure_xmlstarlet_dependency
ensure_base64_xxd_dependency "$logfile"
ensure_jq_dependency
local loopdev=$(losetup -f --show -P "$iso") || log_and_exit "Failed to set up loop device" "$logfile"
mkdir -p /mnt/opencore >>"$logfile" 2>&1 || log_and_exit "Failed to create mount point" "$logfile"
mount "${loopdev}p1" /mnt/opencore >>"$logfile" 2>&1 || log_and_exit "Failed to mount ISO" "$logfile"
local config="/mnt/opencore/EFI/OC/config.plist"
[[ ! -e "$config.backup" ]] && cp "$config" "$config.backup" >>"$logfile" 2>&1
# Temporary file
local TEMP_FILE="${config}.tmp"
cp "$config" "$TEMP_FILE"
# Define base XPaths
local nvram_xpath="//key[text()='NVRAM']/following-sibling::dict/key[text()='Add']/following-sibling::dict/key[text()='7C436110-AB2A-4BBB-A880-FE41995C9F82']/following-sibling::dict"
local misc_boot_xpath="//key[text()='Misc']/following-sibling::dict/key[text()='Boot']/following-sibling::dict"
local platform_generic_xpath="//key[text()='PlatformInfo']/following-sibling::dict/key[text()='Generic']/following-sibling::dict"
# Define keys and sections
declare -A key_sections=( ["boot-args"]="nvram" ["csr-active-config"]="nvram" ["prev-lang:kbd"]="nvram" ["Timeout"]="misc_boot" ["MLB"]="platform_generic" ["SystemProductName"]="platform_generic" ["SystemSerialNumber"]="platform_generic" ["SystemUUID"]="platform_generic" ["ROM"]="platform_generic" )
keys=("boot-args" "csr-active-config" "prev-lang:kbd" "Timeout" "MLB" "SystemProductName" "SystemSerialNumber" "SystemUUID" "ROM")
# Function to read a value from plist
read_plist_value() {
xmlstarlet sel -t -v "${2}/key[text()='${3}']/following-sibling::*[1]" "$1" 2>/dev/null
}
# Function to update a value in plist
update_plist_value() {
xmlstarlet ed -L -u "${2}/key[text()='${3}']/following-sibling::*[1]" -v "$4" "$1"
}
# Function to remove a key from plist
remove_plist_key() {
local key_xpath="${2}/key[text()='${3}']"
local value_xpath="${2}/key[text()='${3}']/following-sibling::*[1]"
xmlstarlet ed -L -d "$key_xpath" -d "$value_xpath" "$1" || log_and_exit "Failed to remove $3" "$logfile"
}
# Integrate JSON logic
generate_new=false
if [ -f "$oc_json_path" ]; then
read -rp "Existing SMBIOS JSON found. Do you want to generate a new serial number? [y/N]: " GENSMBIOS
if [[ "${GENSMBIOS}" =~ ^[Yy]$ ]]; then
generate_new=true
else
# Apply existing JSON
declare -A json_values
json_values["SystemProductName"]=$(jq -r '.Type // empty' "$oc_json_path")
json_values["SystemSerialNumber"]=$(jq -r '.Serial // empty' "$oc_json_path")
json_values["MLB"]=$(jq -r '."Board Serial" // empty' "$oc_json_path")
json_values["SystemUUID"]=$(jq -r '.SmUUID // empty' "$oc_json_path")
json_values["ROM"]=$(jq -r '.ROM // empty' "$oc_json_path")
for key in SystemProductName SystemSerialNumber MLB SystemUUID ROM; do
if [ -n "${json_values[$key]}" ]; then
if [ "$key" == "ROM" ]; then
if command -v base64 >/dev/null 2>&1 && command -v xxd >/dev/null 2>&1; then
modified_value=$(echo -n "${json_values[$key]}" | xxd -r -p | base64)
else
display_and_log "Warning: base64 or xxd not available. Skipping ROM update." "$logfile"
continue
fi
else
modified_value="${json_values[$key]}"
fi
update_plist_value "$TEMP_FILE" "$platform_generic_xpath" "$key" "$modified_value"
display_and_log "Applied $key from existing JSON to temp file." "$logfile"
fi
done
fi
else
read -rp "No Serial number generated. Do you want to generate a unique serial number? [Y/n]: " GENSMBIOS
if [[ "${GENSMBIOS:-Y}" =~ ^[Yy]$ ]]; then
generate_new=true
fi
fi
# Generate new SMBIOS if requested
if $generate_new; then
SystemProductName="$(read_plist_value "$TEMP_FILE" "$platform_generic_xpath" "SystemProductName")"
read -e -p "Enter System Product Name (press Enter to keep current): " -i "$SystemProductName" new_value
if [ -n "$new_value" ] && [ "$new_value" != "$SystemProductName" ]; then
SystemProductName="$new_value"
fi
python3 "$SCRIPT_DIR"/tools/GenSMBIOS/GenSMBIOS.py --install
python3 "$SCRIPT_DIR"/tools/GenSMBIOS/GenSMBIOS.py --generate "$SystemProductName" -j "$oc_json_path" >>"$logfile" 2>&1 || log_and_exit "Failed to generate SMBIOS" "$logfile"
# Apply new JSON
declare -A json_values
json_values["SystemProductName"]=$(jq -r '.Type // empty' "$oc_json_path")
json_values["SystemSerialNumber"]=$(jq -r '.Serial // empty' "$oc_json_path")
json_values["MLB"]=$(jq -r '."Board Serial" // empty' "$oc_json_path")
json_values["SystemUUID"]=$(jq -r '.SmUUID // empty' "$oc_json_path")
json_values["ROM"]=$(jq -r '.ROM // empty' "$oc_json_path")
for key in SystemProductName SystemSerialNumber MLB SystemUUID ROM; do
if [ -n "${json_values[$key]}" ]; then
if [ "$key" == "ROM" ]; then
if command -v base64 >/dev/null 2>&1 && command -v xxd >/dev/null 2>&1; then
modified_value=$(echo -n "${json_values[$key]}" | xxd -r -p | base64)
else
display_and_log "Warning: base64 or xxd not available. Skipping ROM update." "$logfile"
continue
fi
else
modified_value="${json_values[$key]}"
fi
update_plist_value "$TEMP_FILE" "$platform_generic_xpath" "$key" "$modified_value"
display_and_log "Applied new $key from generated JSON to temp file." "$logfile"
fi
done
fi
# Prompt for edits
declare -A modified
for key in "${keys[@]}"; do
local section=${key_sections[$key]}
local base_xpath
case $section in
nvram) base_xpath="$nvram_xpath" ;;
misc_boot) base_xpath="$misc_boot_xpath" ;;
platform_generic) base_xpath="$platform_generic_xpath" ;;
esac
value=$(read_plist_value "$TEMP_FILE" "$base_xpath" "$key")
if [ -z "$value" ]; then
display_and_log "Warning: Could not read value for $key" "$logfile"
continue
fi
if [ "$key" == "csr-active-config" ]; then
current_value="$value"
echo "Current value for $key: $current_value"
read -rp "Remove csr-active-config (unlock SIP)? [Y/N] [N]: " RM_CSR_LOCK
if [[ "${RM_CSR_LOCK:-N}" =~ ^[Yy]$ ]]; then
modified[$key]="remove"
display_and_log "SIP unlocked. Use 'csrutil disable' in Recovery OS" "$logfile"
continue
fi
read -e -p "Edit value (press Enter to keep current): " -i "$current_value" new_value
if [ -n "$new_value" ] && [ "$new_value" != "$current_value" ]; then
modified[$key]="$new_value"
fi
elif [ "$key" == "ROM" ]; then
rom_convert=false
if command -v base64 >/dev/null && command -v xxd >/dev/null; then
rom_convert=true
current_value=$(echo -n "$value" | base64 -d | xxd -p -c 999 | tr -d '\n' | tr 'a-f' 'A-F')
else
current_value="$value"
fi
echo "Current value for $key (${rom_convert:+HEX}base64 if not): $current_value"
read -e -p "Edit value (press Enter to keep current): " -i "$current_value" new_value
if [ -n "$new_value" ] && [ "$new_value" != "$current_value" ]; then
if $rom_convert; then
modified[$key]=$(echo -n "$new_value" | xxd -r -p | base64)
else
modified[$key]="$new_value"
fi
fi
else
current_value="$value"
echo "Current value for $key: $current_value"
read -e -p "Edit value (press Enter to keep current): " -i "$current_value" new_value
if [ -n "$new_value" ] && [ "$new_value" != "$current_value" ]; then
modified[$key]="$new_value"
fi
fi
done
# Apply user modifications
if [ ${#modified[@]} -gt 0 ]; then
display_and_log "Applying user changes to temporary file..." "$logfile"
for key in "${!modified[@]}"; do
local section=${key_sections[$key]}
local base_xpath
case $section in
nvram) base_xpath="$nvram_xpath" ;;
misc_boot) base_xpath="$misc_boot_xpath" ;;
platform_generic) base_xpath="$platform_generic_xpath" ;;
esac
if [ "${modified[$key]}" == "remove" ]; then
remove_plist_key "$TEMP_FILE" "$base_xpath" "$key"
else
update_plist_value "$TEMP_FILE" "$base_xpath" "$key" "${modified[$key]}"
fi
done
fi
# Automatic boot-args adjustment
system_product_name=$(read_plist_value "$TEMP_FILE" "$platform_generic_xpath" "SystemProductName")
boot_args=$(read_plist_value "$TEMP_FILE" "$nvram_xpath" "boot-args")
flag=" -nehalem_error_disable"
if [ "$system_product_name" = "MacPro5,1" ]; then
if [[ ! "$boot_args" =~ $flag ]]; then
new_boot_args="$boot_args$flag"
update_plist_value "$TEMP_FILE" "$nvram_xpath" "boot-args" "$new_boot_args"
display_and_log "Automatically added '$flag' to boot-args." "$logfile"
fi
else
if [[ "$boot_args" =~ $flag ]]; then
new_boot_args="${boot_args//$flag/}"
update_plist_value "$TEMP_FILE" "$nvram_xpath" "boot-args" "$new_boot_args"
display_and_log "Automatically removed '$flag' from boot-args." "$logfile"
fi
fi
# Show diff if changes
xmlstarlet fo "$config" > "$config.fmt"
local diff_output=$(diff -u "$config.fmt" "$TEMP_FILE")
rm "$config.fmt"
if [ -n "$diff_output" ]; then
display_and_log "Differences between original and modified file (unified format):" "$logfile"
echo "$diff_output"
read -rp "Do you want to apply these changes to the original file? (y/n): " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
mv "$TEMP_FILE" "$config"
display_and_log "Changes applied to $config" "$logfile"
# Extract and save to JSON
declare -A extracted
for key in SystemProductName SystemSerialNumber MLB SystemUUID ROM; do
val=$(read_plist_value "$config" "$platform_generic_xpath" "$key")
if [ -z "$val" ]; then
display_and_log "Warning: Could not read $key from plist." "$logfile"
continue
fi
if [ "$key" == "ROM" ]; then
if command -v base64 >/dev/null 2>&1 && command -v xxd >/dev/null 2>&1; then
val=$(echo -n "$val" | base64 -d | xxd -p -c 999 | tr -d '\n' | tr 'a-f' 'A-F')
else
display_and_log "Warning: base64 or xxd not available. Skipping ROM extraction." "$logfile"
continue
fi
fi
extracted[$key]="$val"
done
jq -n \
--arg Type "${extracted[SystemProductName]}" \
--arg Serial "${extracted[SystemSerialNumber]}" \
--arg board_serial "${extracted[MLB]}" \
--arg SmUUID "${extracted[SystemUUID]}" \
--arg ROM "${extracted[ROM]}" \
'{Type: $Type, Serial: $Serial, "Board Serial": $board_serial, SmUUID: $SmUUID, ROM: $ROM}' > "$oc_json_path"
display_and_log "Updated/Created SMBIOS JSON at $oc_json_path" "$logfile"
else
display_and_log "Changes discarded." "$logfile"
rm "$TEMP_FILE"
fi
else
display_and_log "No changes were made." "$logfile"
rm "$TEMP_FILE"
fi
# Cleanup
umount /mnt/opencore >>"$logfile" 2>&1 || log_and_exit "Failed to unmount ISO" "$logfile"
losetup -d "$loopdev" >>"$logfile" 2>&1 || log_and_exit "Failed to detach loop device" "$logfile"
display_and_log "OpenCore config customized" "$logfile"
read -n 1 -sp "Press any key to return to menu..."
}
# Function to update OpenCore ISO
update_opencore_iso() {
local iso_path
local logfile="${LOGDIR}/update-opencore-iso.log"
local iso_url="https://github.com/luchina-gabriel/OSX-PROXMOX/raw/main/EFI/opencore-osx-proxmox-vm.iso"
local iso_path="${ISODIR}/opencore-osx-proxmox-vm.iso"
iso_path="${ISODIR}/${OPENCORE_ISO}"
oc_json_path="${ISODIR}/.smbios.json"
rm -f "$iso_path" >>"$logfile" 2>&1
if ! wget -q -O "$iso_path" "$iso_url" >>"$logfile" 2>&1; then
log_and_exit "Failed to download OpenCore ISO" "$logfile"
fi
ensure_base64_xxd_dependency
update_opencore_smbios "$iso_path" "$oc_json_path"
display_and_log "OpenCore ISO updated" "$logfile"
sleep 5
@ -463,7 +878,7 @@ remove_subscription_notice() {
# Function to configure network bridge
configure_network_bridge() {
local logfile="${LOGDIR}/configure-network-bridge.log"
# Logging functions
die() {
display_and_log "ERROR: $*" "$logfile"
@ -505,7 +920,7 @@ configure_network_bridge() {
ensure_dependencies() {
local deps=("ipcalc")
local missing=()
# Check for isc-dhcp-server
if ! dpkg -l isc-dhcp-server &>/dev/null; then
deps+=("isc-dhcp-server")
@ -521,7 +936,7 @@ configure_network_bridge() {
info "Installing missing dependencies: ${missing[*]}"
apt-get update && apt-get install -y "${missing[@]}" >>"$logfile" 2>&1 || die "Failed to install dependencies"
fi
# Ensure DHCP config directory exists
mkdir -p "$DHCP_CONF_DIR"
chown root:root "$DHCP_CONF_DIR"
@ -532,26 +947,26 @@ configure_network_bridge() {
calculate_network() {
local subnet=$1
declare -gA network_info
# Validate subnet format
if [[ ! "$subnet" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}$ ]]; then
warn "Invalid subnet format: $subnet"
return 1
fi
# Get ipcalc output
if ! ipcalc_output=$(ipcalc -nb "$subnet"); then
warn "ipcalc failed to process subnet: $subnet"
return 1
fi
# Parse network information
network_info["network"]=$(echo "$ipcalc_output" | awk '/^Network:/ {print $2}' | cut -d'/' -f1)
network_info["netmask"]=$(echo "$ipcalc_output" | awk '/^Netmask:/ {print $2}')
network_info["broadcast"]=$(echo "$ipcalc_output" | awk '/^Broadcast:/ {print $2}')
network_info["hostmin"]=$(echo "$ipcalc_output" | awk '/^HostMin:/ {print $2}')
network_info["hostmax"]=$(echo "$ipcalc_output" | awk '/^HostMax:/ {print $2}')
# Calculate DHCP range (skip first 50 IPs)
IFS='.' read -r i1 i2 i3 i4 <<< "${network_info[hostmin]}"
network_info["range_start"]="$i1.$i2.$i3.$((i4 + 50))"
@ -572,7 +987,7 @@ configure_network_bridge() {
validate_bridge() {
local bridge_num=$1
[[ "$bridge_num" =~ ^[0-9]+$ ]] || { warn "Bridge number must be a positive integer"; return 1; }
if [[ -d "/sys/class/net/vmbr$bridge_num" || \
-n $(grep -h "^iface vmbr$bridge_num" "$NETWORK_INTERFACES_FILE" 2>/dev/null) ]]; then
return 1 # Bridge exists
@ -583,7 +998,7 @@ configure_network_bridge() {
# Find next available bridge
find_next_bridge() {
local bridge_num=0
while ! validate_bridge "$bridge_num"; do
while ! validate_bridge "$bridge_num"; do
((bridge_num++))
done
echo "$bridge_num"
@ -593,10 +1008,10 @@ configure_network_bridge() {
validate_subnet() {
local subnet=$1
[[ "$subnet" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/[0-9]{1,2}$ ]] || { warn "Invalid CIDR format"; return 1; }
IFS='./' read -r ip1 ip2 ip3 ip4 mask <<< "$subnet"
(( ip1 <= 255 && ip2 <= 255 && ip3 <= 255 && ip4 <= 255 && mask <= 32 )) || { warn "Invalid IP/Netmask"; return 1; }
# Check for conflicts
while read -r existing; do
if [[ -n "$existing" ]]; then
@ -606,7 +1021,7 @@ configure_network_bridge() {
fi
fi
done < <(get_existing_subnets)
return 0
}
@ -643,7 +1058,7 @@ configure_network_bridge() {
for conf in "$DHCP_CONF_DIR"/*.conf; do
[[ -f "$conf" ]] && interfaces+=("$(basename "${conf%.conf}")")
done
# Update interfaces list
printf "INTERFACESv4=\"%s\"\n" "${interfaces[*]}" > /etc/default/isc-dhcp-server
}
@ -652,12 +1067,12 @@ configure_network_bridge() {
configure_dhcp() {
local bridge_name=$1
local subnet=$2
if ! calculate_network "$subnet"; then
warn "Failed to calculate network parameters for $subnet"
return 1
fi
# Create bridge-specific config
printf "subnet %s netmask %s {\n" "${network_info[network]}" "${network_info[netmask]}" > "$DHCP_CONF_DIR/$bridge_name.conf"
printf " range %s %s;\n" "${network_info[range_start]}" "${network_info[range_end]}" >> "$DHCP_CONF_DIR/$bridge_name.conf"
@ -693,7 +1108,7 @@ configure_network_bridge() {
configure_network() {
local bridge_num=$1
local subnet=$2
info "Calculating network parameters for $subnet..."
if ! calculate_network "$subnet"; then
die "Failed to calculate network parameters for $subnet"
@ -746,7 +1161,7 @@ configure_network_bridge() {
local default=$2
local validation_func=$3
local value
while true; do
read -rp "$prompt [$default]: " value
value=${value:-$default}
@ -762,7 +1177,7 @@ configure_network_bridge() {
# Main execution
info "Configuring network bridge for macOS in Cloud..."
# Check root
(( EUID == 0 )) || die "This function must be run as root"
@ -804,45 +1219,12 @@ configure_network_bridge() {
read -n 1 -s
}
# Function to customize OpenCore config.plist
customize_opencore_config() {
local logfile="${LOGDIR}/custom-oc-config.plist.log"
local iso="${ISODIR}/opencore-osx-proxmox-vm.iso"
local loopdev=$(losetup -f --show -P "$iso") || log_and_exit "Failed to set up loop device" "$logfile"
mkdir -p /mnt/opencore >>"$logfile" 2>&1 || log_and_exit "Failed to create mount point" "$logfile"
mount "${loopdev}p1" /mnt/opencore >>"$logfile" 2>&1 || log_and_exit "Failed to mount ISO" "$logfile"
local config="/mnt/opencore/EFI/OC/config.plist"
[[ ! -e "$config.backup" ]] && cp "$config" "$config.backup" >>"$logfile" 2>&1
local prev_lang=$(grep -E '..-..:0' "$config" | sed 's/.*\(..-..\).*/\1/')
local boot_args=$(grep '<key>boot-args' "$config" -A1 | tail -n1 | sed 's/.*>\(.*\)<.*/\1/')
local timeout=$(grep -A1 '>Timeout<' "$config" | tail -n1 | sed 's/.*>\(.*\)<.*/\1/')
read -rp "Enter language-country code [${prev_lang}]: " NEW_PREV_LANG
sed -i "s/..-..:0/${NEW_PREV_LANG:-$prev_lang}:0/" "$config" >>"$logfile" 2>&1 || log_and_exit "Failed to update language" "$logfile"
read -rp "Enter boot-args [${boot_args}]: " NEW_BOOT_ARGS
sed -i "s|${boot_args}|${NEW_BOOT_ARGS:-$boot_args}|" "$config" >>"$logfile" 2>&1 || log_and_exit "Failed to update boot-args" "$logfile"
read -rp "Remove csr-active-config (unlock SIP)? [Y/N] [N]: " RM_CSR_LOCK
if [[ "${RM_CSR_LOCK:-N}" =~ ^[Yy]$ ]]; then
sed -i '/<key>csr-active-config>/,+1d' "$config" >>"$logfile" 2>&1 || log_and_exit "Failed to remove csr-active-config" "$logfile"
display_and_log "SIP unlocked. Use 'csrutil disable' in Recovery OS" "$logfile"
fi
read -rp "Enter timeout [${timeout}]: " NEW_TIMEOUT
NEW_TIMEOUT=${NEW_TIMEOUT:-$timeout}
if [[ "$NEW_TIMEOUT" != "$timeout" ]]; then
sed -i "/<key>Timeout<\/key>/{n;s/<integer>$timeout<\/integer>/<integer>$NEW_TIMEOUT<\/integer>/}" "$config" >>"$logfile" 2>&1 || log_and_exit "Failed to update timeout" "$logfile"
fi
diff -u "$config.backup" "$config" || true
umount /mnt/opencore >>"$logfile" 2>&1 || log_and_exit "Failed to unmount ISO" "$logfile"
losetup -d "$loopdev" >>"$logfile" 2>&1 || log_and_exit "Failed to detach loop device" "$logfile"
display_and_log "OpenCore config customized" "$logfile"
read -n 1 -sp "Press any key to return to menu..."
}
# Function to configure macOS VM
configure_macos_vm() {
local opt=$1
local macopt=$1
local nextid=$2
local version_name version board_id model_id iso_size disk_type
IFS='|' read -r version_name version board_id model_id iso_size disk_type <<< "${MACOS_CONFIG[$opt]}"
local version_name version board_id model_id iso_size disk_type opt=$3
IFS='|' read -r version_name version board_id model_id iso_size disk_type <<< "$macopt"
local default_vm_name="${DEFAULT_VM_PREFIX}$(echo "$version_name" | tr -s ' ' | sed 's/^[ ]*//;s/[ ]*$//;s/[ ]/-/g' | tr '[:lower:]' '[:upper:]' | sed 's/-*$//')"
validate_vm_name "$default_vm_name" || log_and_exit "Invalid default VM name: $default_vm_name" "${LOGDIR}/main-menu.log"
clear
@ -1049,7 +1431,7 @@ main_menu() {
[[ -z "$OPT" || "$OPT" -eq 0 ]] && exit
if [[ ${MACOS_CONFIG[$OPT]} ]]; then
configure_macos_vm "$OPT" "$NEXTID"
configure_macos_vm "${MACOS_CONFIG[$OPT]}" "$NEXTID" "$OPT"
else
case $OPT in
200) add_no_subscription_repo ;;
@ -1070,8 +1452,8 @@ init_dirs
check_proxmox_version
set_isodir
# Check if OpenCore ISO exists, and install if not in the ISODIR.
if [ ! -f "${ISODIR}/opencore-osx-proxmox-vm.iso" ]; then
update_opencore_iso
if [ ! -f "${ISODIR}/${OPENCORE_ISO}" ]; then
update_opencore_iso "0"
fi
sleep 4
OSX_PLATFORM=$(detect_cpu_platform)

1
tools/GenSMBIOS Submodule

@ -0,0 +1 @@
Subproject commit 573f5fc375cb52688ccac4312de8422ae263dcf2