diff --git a/CREDITS.md b/CREDITS.md
new file mode 100644
index 0000000..e69de29
diff --git a/README.md b/README.md
index 78a2d30..968646b 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,216 @@
-# osx-serial-generator
-Generate complete sets of Serial Numbers for OSX-KVM, Docker-OSX and of course, OpenCore.
+# OSX Serial Generator
+
+![Running mac osx in a docker container](/running-mac-inside-docker-qemu.png?raw=true "OSX KVM DOCKER")
+
+Generate macOS valid serials, uuids, and board serials. Pertinent for working in iMessage security research.
+
+This project provides two tools for generating serial numbers for Hackintosh, OpenCore, Docker-OSx and OSX-KVM.
+
+Author: Sick.Codes https://sick.codes/ & https://twitter.com/sickcodes
+
+### PR & Contributor Credits
+
+https://github.com/sickcodes/osx-serial-generator/blob/master/CREDITS.md
+
+## Related
+
+- [Docker-OSX](https://github.com/sickcodes/Docker-OSX)
+- [OSX-KVM](https://github.com/kholia/OSX-KVM)
+- [OpenCore](https://github.com/acidanthera/OpenCorePkg)
+- [Hackintosh](https://www.reddit.com/r/hackintosh/)
+
+# Purpose
+
+These script were written by @sickcodes [https://twitter.com/sickcodes](https://twitter.com/sickcodes) for automating generating unique values at runtime in [Docker-OSX](https://github.com/sickcodes/Docker-OSX).
+
+This is for generating sets of serial numbers that simply work.
+
+If this is your first time, just run the first command below, without any options, and you will be given 1 complete set.
+
+Used at runtime in [Docker-OSX](https://github.com/sickcodes/Docker-OSX).
+
+- [https://github.com/kholia/OSX-KVM](https://github.com/kholia/OSX-KVM): "Run macOS on QEMU/KVM. With OpenCore + Big Sur support now! Only commercial (paid) support is available."
+
+- [https://github.com/sickcodes/Docker-OSX](https://github.com/sickcodes/Docker-OSX): "Run Mac in a Docker! Run near native OSX-KVM in Docker! X11 Forwarding! CI/CD for OS X!"
+
+- [https://github.com/kholia/OSX-KVM](https://github.com/kholia/OSX-KVM)
+
+# Requirements
+
+```bash
+# Ubuntu/Debian/Pop
+sudo apt update -y && sudo apt install libguestfs-tools build-essential wget git -y
+
+# Fedora, RHEL, CentOS
+sudo yum install libguestfs wget git -y
+sudo yum groupinstall 'Development Tools' -y
+
+# Arch, Manjaro
+sudo pacman -Sy libguestfs wget git base-devel
+
+```
+
+# Generating New Unique Serial Numbers
+
+Example
+```bash
+# make 1 serial set, using
+./generate-unique-machine-values.sh -c 1
+
+# make 100 serial sets
+./generate-unique-machine-values.sh -c 100 --model="iMacPro1,1"
+
+# make 5 serial sets, but also make config.plist for each set, and OpenCore-nopicker.qcow2 for each serial set.
+./generate-unique-machine-values.sh -c 5 --plists --bootdisks
+```
+
+## Already have your own `config.plist`?
+
+If you want to automate creating the qcow bootdisk each time, you can use placeholders and let this script build the image each time you change anything.
+
+If you want to use placeholders, you can supply that to either of the scripts in this repo and use `--custom-plist=./my_config.plist`
+
+```bash
+# make 5 serial sets, but also use my config.plist for each set AND make qcow2 image for each!
+./generate-unique-machine-values.sh -c 5 --custom-plist=./my_config.plist --bootdisks
+```
+
+Or you can manually enter the values generated above:
+
+```xml
+ MLB
+ {{BOARD_SERIAL}}
+ ROM
+ {{ROM}}
+ SpoofVendor
+
+ SystemProductName
+ {{DEVICE_MODEL}}
+ SystemSerialNumber
+ {{SERIAL}}
+ SystemUUID
+ {{UUID}}
+ ...
+ ...
+ ...
+ Resolution
+ {{WIDTH}}x{{HEIGHT}}@32
+ SanitiseClearScreen
+```
+```
+ {{DEVICE_MODEL}}, {{SERIAL}}, {{BOARD_SERIAL}},
+ {{UUID}}, {{ROM}}, {{WIDTH}}, {{HEIGHT}}
+```
+
+```bash
+General options:
+ --count, -n, -c Number of serials to generate
+ --model, -m Device model, e.g. 'iMacPro1,1'
+ --csv Optionally change the CSV output filename
+ --tsv Optionally change the TSV output filename
+ --output-dir Optionally change the script output location
+ --width Resolution x axis length in px, default 1920
+ --height Resolution y axis length in px, default 1080
+ --master-plist-url Specify an alternative master plist, via URL
+ --master-plist Optionally change the input plist
+ --custom-plist Same as --master-plist
+ --output-bootdisk Optionally change the bootdisk filename
+ --envs Create all corresponding sourcable envs
+ --plists Create all corresponding config.plists
+ --bootdisks Create all corresponding bootdisks [SLOW]
+ --help, -h, help Display this help and exit
+
+Additional options only if you are creating ONE serial set:
+ --output-bootdisk Optionally change the bootdisk filename
+ --output-env Optionally change the serials env filename
+
+Custom plist placeholders:
+ {{DEVICE_MODEL}}, {{SERIAL}}, {{BOARD_SERIAL}},
+ {{UUID}}, {{ROM}}, {{WIDTH}}, {{HEIGHT}}
+
+Example:
+ ./generate-unique-machine-values.sh --count 1 --plists --bootdisks --envs
+
+Defaults:
+ - One serial, for 'iMacPro1,1', in the current working directory
+ - CSV and TSV output
+ - plists in ./plists/ & bootdisks in ./bootdisks/ & envs in ./envs
+ - if you set --bootdisk name, --bootdisks is assumed
+ - if you set --custom-plist, --plists is assumed
+ - if you set --output-env, --envs is assumed
+
+```
+
+# Generating A Bootdisk Using Specific Serial Numbers
+
+If you already know the serial numbers, or you've generated them above in the past, then you can use this script:
+
+```bash
+
+Required options:
+ --model Device model, e.g. 'iMacPro1,1'
+ --serial Device Serial number
+ --board-serial Main Logic Board Serial number (MLB)
+ --uuid SMBIOS UUID (SmUUID)
+ --mac-address Used for both the MAC address and to set ROM
+ ROM is lowercased sans any colons
+Optional options:
+ --width Resolution x axis length in px, default 1920
+ --height Resolution y axis length in px, default 1080
+ --master-plist-url Specify an alternative master plist, via URL
+ --custom-plist
+ || --master-plist Optionally change the input plist.
+ --output-bootdisk Optionally change the bootdisk filename
+ --output-plist Optionally change the output plist filename
+ --help, -h, help Display this help and exit
+
+Placeholders: {{DEVICE_MODEL}}, {{SERIAL}}, {{BOARD_SERIAL}}, {{UUID}},
+ {{ROM}}, {{WIDTH}}, {{HEIGHT}}
+
+Example:
+ ./generate-specific-bootdisk.sh \
+ --model iMacPro1,1 \
+ --serial C02TW0WAHX87 \
+ --board-serial C027251024NJG36UE \
+ --uuid 5CCB366D-9118-4C61-A00A-E5BAF3BED451 \
+ --mac-address A8:5C:2C:9A:46:2F \
+ --output-bootdisk ./OpenCore-nopicker.qcow2 \
+ --width 1920 \
+ --height 1080
+
+```
+
+
+# Examples from Docker-OSX
+
+In the case example of why these scripts were written is:
+
+`GENERATE_UNIQUE` is used as a Docker argument to randomly generate 1 set at runtime, for every new container.
+
+`GENERATE_SPECIFIC` is used to specify an already known model, serial, board-serial, uuid and MAC address.
+
+```bash
+[[ "${GENERATE_UNIQUE}" == true ]] && { \
+ ./Docker-OSX/custom/generate-unique-machine-values.sh \
+ --master-plist-url="${MASTER_PLIST_URL}" \
+ --count 1 \
+ --tsv ./serial.tsv \
+ --bootdisks \
+ --width "${WIDTH:-1920}" \
+ --height "${HEIGHT:-1080}" \
+ --output-bootdisk "${BOOTDISK:=/home/arch/OSX-KVM/OpenCore-Catalina/OpenCore.qcow2}" \
+ --output-env "${ENV:=/env}" \
+; } \
+; [[ "${GENERATE_SPECIFIC}" == true ]] && { \
+ source "${ENV:=/env}" 2>/dev/null \
+ ; ./Docker-OSX/custom/generate-specific-bootdisk.sh \
+ --master-plist-url="${MASTER_PLIST_URL}" \
+ --model "${DEVICE_MODEL}" \
+ --serial "${SERIAL}" \
+ --board-serial "${BOARD_SERIAL}" \
+ --uuid "${UUID}" \
+ --mac-address "${MAC_ADDRESS}" \
+ --width "${WIDTH:-1920}" \
+ --height "${HEIGHT:-1080}" \
+ --output-bootdisk "${BOOTDISK:=/home/arch/OSX-KVM/OpenCore-Catalina/OpenCore.qcow2}"
+```
diff --git a/config-nopicker-custom.plist b/config-nopicker-custom.plist
new file mode 100644
index 0000000..6602df5
--- /dev/null
+++ b/config-nopicker-custom.plist
@@ -0,0 +1,884 @@
+
+
+
+
+
+
+
+ ACPI
+
+ Add
+
+
+ Comment
+ add DTGP method
+ Enabled
+
+ Path
+ SSDT-DTGP.aml
+
+
+ Comment
+ Fake EC and USBX Power
+ Enabled
+
+ Path
+ SSDT-EC.aml
+
+
+ Comment
+ USB 2.0 Injection
+ Enabled
+
+ Path
+ SSDT-EHCI.aml
+
+
+ Comment
+ CPU AGPM Plugin=1
+ Enabled
+
+ Path
+ SSDT-PLUG.aml
+
+
+ Delete
+
+
+ All
+
+ Comment
+ Delete CpuPm
+ Enabled
+
+ OemTableId
+ Q3B1UG0AAAA=
+ TableLength
+ 0
+ TableSignature
+ U1NEVA==
+
+
+ All
+
+ Comment
+ Delete Cpu0Ist
+ Enabled
+
+ OemTableId
+ Q3B1MElzdAA=
+ TableLength
+ 0
+ TableSignature
+ U1NEVA==
+
+
+ Patch
+
+
+ Comment
+ _Q11 to XQ11
+ Count
+ 1
+ Enabled
+
+ Find
+ X1ExMQ==
+ Limit
+ 0
+ Mask
+
+ OemTableId
+
+ Replace
+ WFExMQ==
+ ReplaceMask
+
+ Skip
+ 0
+ TableLength
+ 0
+ TableSignature
+
+
+
+ Comment
+ _Q12 to XQ12
+ Count
+ 1
+ Enabled
+
+ Find
+ X1ExMg==
+ Limit
+ 0
+ Mask
+
+ OemTableId
+
+ Replace
+ WFExMg==
+ ReplaceMask
+
+ Skip
+ 0
+ TableLength
+ 0
+ TableSignature
+
+
+
+ Quirks
+
+ FadtEnableReset
+
+ NormalizeHeaders
+
+ RebaseRegions
+
+ ResetHwSig
+
+ ResetLogoStatus
+
+
+
+ Booter
+
+ MmioWhitelist
+
+ Quirks
+
+ AvoidRuntimeDefrag
+
+ DevirtualiseMmio
+
+ DisableSingleUser
+
+ DisableVariableWrite
+
+ DiscardHibernateMap
+
+ EnableSafeModeSlide
+
+ EnableWriteUnprotector
+
+ ForceExitBootServices
+
+ ProtectMemoryRegions
+
+ ProtectSecureBoot
+
+ ProtectUefiServices
+
+ ProvideCustomSlide
+
+ ProvideMaxSlide
+ 0
+ RebuildAppleMemoryMap
+
+ SetupVirtualMap
+
+ SignalAppleOS
+
+ SyncRuntimePermissions
+
+
+
+ DeviceProperties
+
+ Add
+
+ PciRoot(0x1)/Pci(0x1F,0x0)
+
+ compatible
+ pci8086,2916
+ device-id
+
+ FikA
+
+ name
+ pci8086,2916
+
+
+ Delete
+
+ PciRoot(0x0)/Pci(0x1b,0x0)
+
+ MaximumBootBeepVolume
+
+
+
+ Kernel
+
+ Add
+
+
+ Arch
+ Any
+ BundlePath
+ VoodooHDA.kext
+ Comment
+
+ Enabled
+
+ ExecutablePath
+ Contents/MacOS/VoodooHDA
+ MaxKernel
+
+ MinKernel
+
+ PlistPath
+ Contents/Info.plist
+
+
+ Arch
+ x86_64
+ BundlePath
+ Lilu.kext
+ Comment
+ Patch engine
+ Enabled
+
+ ExecutablePath
+ Contents/MacOS/Lilu
+ MaxKernel
+
+ MinKernel
+ 12.0.0
+ PlistPath
+ Contents/Info.plist
+
+
+ Arch
+ x86_64
+ BundlePath
+ VirtualSMC.kext
+ Comment
+ SMC emulator
+ Enabled
+
+ ExecutablePath
+ Contents/MacOS/VirtualSMC
+ MaxKernel
+
+ MinKernel
+ 12.0.0
+ PlistPath
+ Contents/Info.plist
+
+
+ Arch
+ x86_64
+ BundlePath
+ WhateverGreen.kext
+ Comment
+ Video patches
+ Enabled
+
+ ExecutablePath
+ Contents/MacOS/WhateverGreen
+ MaxKernel
+
+ MinKernel
+ 12.0.0
+ PlistPath
+ Contents/Info.plist
+
+
+ BundlePath
+ AGPMInjector.kext
+ Comment
+
+ Enabled
+
+ ExecutablePath
+
+ MaxKernel
+
+ MinKernel
+
+ PlistPath
+ Contents/Info.plist
+
+
+ BundlePath
+ USBPorts.kext
+ Comment
+
+ Enabled
+
+ ExecutablePath
+
+ MaxKernel
+
+ MinKernel
+
+ PlistPath
+ Contents/Info.plist
+
+
+ Arch
+ x86_64
+ BundlePath
+ MCEReporterDisabler.kext
+ Comment
+ AppleMCEReporter disabler
+ Enabled
+
+ ExecutablePath
+
+ MaxKernel
+
+ MinKernel
+ 19.0.0
+ PlistPath
+ Contents/Info.plist
+
+
+ Block
+
+
+ Arch
+ Any
+ Comment
+
+ Enabled
+
+ Identifier
+ com.apple.driver.AppleTyMCEDriver
+ MaxKernel
+
+ MinKernel
+
+
+
+ Emulate
+
+ Cpuid1Data
+
+ VAYFAAAAAAAAAAAAAAAAAA==
+
+ Cpuid1Mask
+
+ ////AAAAAAAAAAAAAAAAAA==
+
+
+ Force
+
+
+ Arch
+ Any
+ BundlePath
+ System/Library/Extensions/IONetworkingFamily.kext
+ Comment
+ Patch engine
+ Enabled
+
+ Identifier
+ com.apple.iokit.IONetworkingFamily
+ ExecutablePath
+ Contents/MacOS/IONetworkingFamily
+ MaxKernel
+ 13.99.99
+ MinKernel
+
+ PlistPath
+ Contents/Info.plist
+
+
+ Patch
+
+
+ Base
+ _cpu_topology_sort
+ Comment
+ algrey - cpu_topology_sort -disable _x86_validate_topology
+ Count
+ 1
+ Enabled
+
+ Find
+
+ 6AAA//8=
+
+ Identifier
+ kernel
+ Limit
+ 0
+ Mask
+
+ /wAA//8=
+
+ MaxKernel
+ 20.99.99
+ MinKernel
+ 17.0.0
+ Replace
+
+ Dx9EAAA=
+
+ ReplaceMask
+
+
+ Skip
+ 0
+
+
+ Base
+
+ Comment
+ algrey - cpuid_set_cpufamily - force CPUFAMILY_INTEL_PENRYN
+ Count
+ 1
+ Enabled
+
+ Find
+
+ MduAPQAAAAAGdQA=
+
+ Identifier
+ kernel
+ Limit
+ 0
+ Mask
+
+ /////wAAAP///wA=
+
+ MaxKernel
+ 20.99.99
+ MinKernel
+ 17.0.0
+ Replace
+
+ u7xP6njpXQAAAJA=
+
+ ReplaceMask
+
+
+ Skip
+ 0
+
+
+ Quirks
+
+ AppleCpuPmCfgLock
+
+ AppleXcpmCfgLock
+
+ AppleXcpmExtraMsrs
+
+ AppleXcpmForceBoost
+
+ CustomSMBIOSGuid
+
+ DisableIoMapper
+
+ DisableLinkeditJettison
+
+ DisableRtcChecksum
+
+ DummyPowerManagement
+
+ ExternalDiskIcons
+
+ IncreasePciBarSize
+
+ LapicKernelPanic
+
+ PanicNoKextDump
+
+ PowerTimeoutKernelPanic
+
+ ThirdPartyDrives
+
+ XhciPortLimit
+
+
+ Scheme
+
+ FuzzyMatch
+
+ KernelArch
+ x86_64
+ KernelCache
+ Auto
+
+
+ Misc
+
+ BlessOverride
+
+ Boot
+
+ ConsoleAttributes
+ 0
+ HibernateMode
+ Auto
+ HideAuxiliary
+
+ PickerAttributes
+ 1
+ PickerAudioAssist
+
+ PickerMode
+ External
+ PollAppleHotKeys
+
+ ShowPicker
+
+ TakeoffDelay
+ 0
+ Timeout
+ 0
+
+ Debug
+
+ AppleDebug
+
+ ApplePanic
+
+ DisableWatchDog
+
+ DisplayDelay
+ 0
+ DisplayLevel
+ 2147483650
+ SerialInit
+
+ SysReport
+
+ Target
+ 3
+
+ Entries
+
+ Security
+
+ AllowNvramReset
+
+ AllowSetDefault
+
+ ApECID
+ 0
+ AuthRestart
+
+ BootProtect
+ None
+ DmgLoading
+ Signed
+ EnablePassword
+
+ ExposeSensitiveData
+ 6
+ HaltLevel
+ 2147483648
+ PasswordHash
+
+ PasswordSalt
+
+ ScanPolicy
+ 0
+ SecureBootModel
+ Disabled
+ Vault
+ Optional
+
+ Tools
+
+
+ Arguments
+
+ Auxiliary
+
+ Comment
+ Not signed for security reasons
+ Enabled
+
+ Name
+ UEFI Shell
+ Path
+ OpenShell.efi
+
+
+ Arguments
+ Shutdown
+ Auxiliary
+
+ Comment
+ Perform shutdown
+ Enabled
+
+ Name
+ Shutdown
+ Path
+ ResetSystem.efi
+
+
+
+ NVRAM
+
+ Add
+
+ 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14
+
+ DefaultBackgroundColor
+ AAAAAA==
+ UIScale
+ AQ==
+
+ 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102
+
+ rtc-blacklist
+
+
+ 7C436110-AB2A-4BBB-A880-FE41995C9F82
+
+ SystemAudioVolume
+ Rg==
+ boot-args
+ -v keepsyms=1 tlbto_us=0 vti=9
+ run-efi-updater
+ No
+ csr-active-config
+ ZwAAAA==
+ prev-lang:kbd
+ ZW4tVVM6MA==
+
+
+ Delete
+
+ 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14
+
+ UIScale
+ DefaultBackgroundColor
+
+ 4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102
+
+ rtc-blacklist
+
+ 7C436110-AB2A-4BBB-A880-FE41995C9F82
+
+ boot-args
+
+
+ LegacyEnable
+
+ LegacyOverwrite
+
+ LegacySchema
+
+ 7C436110-AB2A-4BBB-A880-FE41995C9F82
+
+ EFILoginHiDPI
+ EFIBluetoothDelay
+ LocationServicesEnabled
+ SystemAudioVolume
+ SystemAudioVolumeDB
+ SystemAudioVolumeSaved
+ bluetoothActiveControllerInfo
+ bluetoothInternalControllerInfo
+ flagstate
+ fmm-computer-name
+ nvda_drv
+ prev-lang:kbd
+
+ 8BE4DF61-93CA-11D2-AA0D-00E098032B8C
+
+ Boot0080
+ Boot0081
+ Boot0082
+ BootNext
+ BootOrder
+
+
+ WriteFlash
+
+
+ PlatformInfo
+
+ Automatic
+
+ Generic
+
+ AdviseWindows
+
+ MLB
+ {{BOARD_SERIAL}}
+ ROM
+ {{ROM}}
+ SpoofVendor
+
+ SystemProductName
+ {{DEVICE_MODEL}}
+ SystemSerialNumber
+ {{SERIAL}}
+ SystemUUID
+ {{UUID}}
+
+ UpdateDataHub
+
+ UpdateNVRAM
+
+ UpdateSMBIOS
+
+ UpdateSMBIOSMode
+ Create
+
+ UEFI
+
+ APFS
+
+ EnableJumpstart
+
+ GlobalConnect
+
+ HideVerbose
+
+ JumpstartHotPlug
+
+ MinDate
+ 0
+ MinVersion
+ 0
+
+ Audio
+
+ AudioCodec
+ 0
+ AudioDevice
+ PciRoot(0x1)/Pci(0x1,0x0)/Pci(0x0,0x1)
+ AudioOut
+ 0
+ AudioSupport
+
+ MinimumVolume
+ 20
+ PlayChime
+
+ VolumeAmplifier
+ 0
+
+ ConnectDrivers
+
+ Drivers
+
+ VBoxHfs.efi
+ OpenRuntime.efi
+ OpenCanopy.efi
+ #AudioDxe.efi
+ #OpenUsbKbDxe.efi
+ #UsbMouseDxe.efi
+ #Ps2KeyboardDxe.efi
+ #Ps2MouseDxe.efi
+ #HiiDatabase.efi
+ #NvmExpressDxe.efi
+ #XhciDxe.efi
+ #ExFatDxe.efi
+ #PartitionDxe.efi
+ #CrScreenshotDxe.efi
+
+ Input
+
+ KeyFiltering
+
+ KeyForgetThreshold
+ 5
+ KeyMergeThreshold
+ 2
+ KeySupport
+
+ KeySupportMode
+ Auto
+ KeySwap
+
+ PointerSupport
+
+ PointerSupportMode
+ ASUS
+ TimerResolution
+ 50000
+
+ Output
+
+ ClearScreenOnModeSwitch
+
+ ConsoleMode
+
+ DirectGopRendering
+
+ IgnoreTextInGraphics
+
+ ProvideConsoleGop
+
+ ReconnectOnResChange
+
+ ReplaceTabWithSpace
+
+ Resolution
+ {{WIDTH}}x{{HEIGHT}}@32
+ SanitiseClearScreen
+
+ TextRenderer
+ BuiltinGraphics
+ UgaPassThrough
+
+
+ ProtocolOverrides
+
+ AppleAudio
+
+ AppleBootPolicy
+
+ AppleDebugLog
+
+ AppleEvent
+
+ AppleFramebufferInfo
+
+ AppleImageConversion
+
+ AppleImg4Verification
+
+ AppleKeyMap
+
+ AppleRtcRam
+
+ AppleSecureBoot
+
+ AppleSmcIo
+
+ AppleUserInterfaceTheme
+
+ DataHub
+
+ DeviceProperties
+
+ FirmwareVolume
+
+ HashServices
+
+ OSInfo
+
+ UnicodeCollation
+
+
+ Quirks
+
+ ExitBootServicesDelay
+ 0
+ IgnoreInvalidFlexRatio
+
+ ReleaseUsbOwnership
+
+ RequestBootVarRouting
+
+ TscSyncTimeout
+ 0
+ UnblockFsConnect
+
+ ConnectDrivers
+
+
+
+
+
diff --git a/generate-specific-bootdisk.sh b/generate-specific-bootdisk.sh
new file mode 100755
index 0000000..f5e9800
--- /dev/null
+++ b/generate-specific-bootdisk.sh
@@ -0,0 +1,270 @@
+#!/bin/bash
+# ___ _____ __ ___ _ _ ___ _
+# / _ \/ __\ \/ / / __| ___ _ _(_)__ _| | / __|___ _ _ ___ _ _ __ _| |_ ___ _ _
+# | (_) \__ \> < \__ \/ -_) '_| / _` | | | (_ / -_) ' \/ -_) '_/ _` | _/ _ \ '_|
+# \___/|___/_/\_\ |___/\___|_| |_\__,_|_| \___\___|_||_\___|_| \__,_|\__\___/_|
+#
+# Repo: https://github.com/sickcodes/osx-serial-generator/
+# Title: OSX Serial Generator
+# Author: Sick.Codes https://sick.codes/
+# Version: 3.1
+# License: GPLv3+
+
+set -e
+
+help_text="Usage: ./generate-specific-bootdisk.sh
+
+Required options:
+ --model Device model, e.g. 'iMacPro1,1'
+ --serial Device Serial number
+ --board-serial Main Logic Board Serial number (MLB)
+ --uuid SMBIOS UUID (SmUUID)
+ --mac-address Used for both the MAC address and to set ROM
+ ROM is lowercased sans any colons
+Optional options:
+ --width Resolution x axis length in px, default 1920
+ --height Resolution y axis length in px, default 1080
+ --master-plist-url Specify an alternative master plist, via URL
+ --custom-plist
+ || --master-plist Optionally change the input plist.
+ --output-bootdisk Optionally change the bootdisk filename
+ --output-plist Optionally change the output plist filename
+ --help, -h, help Display this help and exit
+
+Placeholders: {{DEVICE_MODEL}}, {{SERIAL}}, {{BOARD_SERIAL}}, {{UUID}},
+ {{ROM}}, {{WIDTH}}, {{HEIGHT}}
+
+Example:
+ ./generate-specific-bootdisk.sh \\
+ --model iMacPro1,1 \\
+ --serial C02TW0WAHX87 \\
+ --board-serial C027251024NJG36UE \\
+ --uuid 5CCB366D-9118-4C61-A00A-E5BAF3BED451 \\
+ --mac-address A8:5C:2C:9A:46:2F \\
+ --output-bootdisk ./OpenCore-nopicker.qcow2 \\
+ --width 1920 \\
+ --height 1080
+
+Author: Sick.Codes https://sick.codes/
+Project: https://github.com/sickcodes/osx-serial-generator/
+License: GPLv3+
+"
+
+OPENCORE_IMAGE_MAKER_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/opencore-image-ng.sh'
+MASTER_PLIST_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-nopicker-custom.plist'
+
+# gather arguments
+while (( "$#" )); do
+ case "${1}" in
+
+ --help | -h | h | help )
+ echo "${help_text}" && exit 0
+ ;;
+
+ --model=* | -m=* )
+ export DEVICE_MODEL="${1#*=}"
+ shift
+ ;;
+ --model* | -m* )
+ export DEVICE_MODEL="${2}"
+ shift
+ shift
+ ;;
+
+ --serial=* )
+ export SERIAL="${1#*=}"
+ shift
+ ;;
+ --serial* )
+ export SERIAL="${2}"
+ shift
+ shift
+ ;;
+
+ --board-serial=* )
+ export BOARD_SERIAL="${1#*=}"
+ shift
+ ;;
+ --board-serial* )
+ export BOARD_SERIAL="${2}"
+ shift
+ shift
+ ;;
+
+ --uuid=* )
+ export UUID="${1#*=}"
+ shift
+ ;;
+ --uuid* )
+ export UUID="${2}"
+ shift
+ shift
+ ;;
+
+ --mac-address=* )
+ export MAC_ADDRESS="${1#*=}"
+ shift
+ ;;
+ --mac-address* )
+ export MAC_ADDRESS="${2}"
+ shift
+ shift
+ ;;
+
+ --width=* )
+ export WIDTH="${1#*=}"
+ shift
+ ;;
+ --width* )
+ export WIDTH="${2}"
+ shift
+ shift
+ ;;
+
+ --height=* )
+ export HEIGHT="${1#*=}"
+ shift
+ ;;
+ --height* )
+ export HEIGHT="${2}"
+ shift
+ shift
+ ;;
+
+ --output-bootdisk=* )
+ export OUTPUT_QCOW="${1#*=}"
+ shift
+ ;;
+ --output-bootdisk* )
+ export OUTPUT_QCOW="${2}"
+ shift
+ shift
+ ;;
+
+ --output-plist=* )
+ export OUTPUT_PLIST="${1#*=}"
+ shift
+ ;;
+ --output-plist* )
+ export OUTPUT_PLIST="${2}"
+ shift
+ shift
+ ;;
+
+ --master-plist-url=* )
+ export MASTER_PLIST_URL="${1#*=}"
+ shift
+ ;;
+
+ --master-plist-url* )
+ export MASTER_PLIST_URL="${2}"
+ shift
+ shift
+ ;;
+
+ --master-plist=* )
+ export MASTER_PLIST="${1#*=}"
+ shift
+ ;;
+ --master-plist* )
+ export MASTER_PLIST="${2}"
+ shift
+ shift
+ ;;
+
+ --custom-plist=* )
+ export MASTER_PLIST="${1#*=}"
+ shift
+ ;;
+ --custom-plist* )
+ export MASTER_PLIST="${2}"
+ shift
+ shift
+ ;;
+
+ *)
+ echo "Invalid option ${1}. Running with default values..."
+ shift
+ ;;
+ esac
+done
+
+
+download_qcow_efi_folder () {
+ [ -d ./OSX-KVM ] || git clone --depth 1 https://github.com/kholia/OSX-KVM.git
+ cp -ra ./OSX-KVM/OpenCore-Catalina/EFI .
+ mkdir -p ./EFI/OC/Resources
+ # clone some Apple drivers
+ [ -d ./OcBinaryData ] || git clone --depth 1 https://github.com/acidanthera/OcBinaryData.git
+ # copy said drivers into EFI/OC/Resources
+ cp -a ./OcBinaryData/Resources/* ./EFI/OC/Resources
+ # EFI Shell commands
+ touch startup.nsh \
+ && echo 'fs0:\EFI\BOOT\BOOTx64.efi' > startup.nsh
+}
+
+generate_bootdisk () {
+
+ # need a config.plist
+ if [ "${MASTER_PLIST}" ]; then
+ [ -e "${MASTER_PLIST}" ] || echo "Could not find: ${MASTER_PLIST}"
+ elif [ "${MASTER_PLIST}" ] && [ "${MASTER_PLIST_URL}" ]; then
+ echo 'You specified both a custom plist FILE & custom plist URL.'
+ echo 'Use only one of those options.'
+ elif [ "${MASTER_PLIST_URL}" ]; then
+ wget -O "${MASTER_PLIST:=./config-custom.plist}" "${MASTER_PLIST_URL}"
+ else
+ # default is config-nopicker-custom.plist from OSX-KVM with placeholders used in Docker-OSX
+ wget -O "${MASTER_PLIST:=./config-nopicker-custom.plist}" "${MASTER_PLIST_URL}"
+ fi
+
+ [ -e ./opencore-image-ng.sh ] \
+ || { wget "${OPENCORE_IMAGE_MAKER_URL}" \
+ && chmod +x opencore-image-ng.sh ; }
+
+ # plist required for bootdisks, so create anyway.
+ if [ "${DEVICE_MODEL}" ] \
+ && [ "${SERIAL}" ] \
+ && [ "${BOARD_SERIAL}" ] \
+ && [ "${UUID}" ] \
+ && [ "${MAC_ADDRESS}" ]; then
+ ROM="${MAC_ADDRESS//\:/}"
+ ROM="${ROM,,}"
+ sed -e s/\{\{DEVICE_MODEL\}\}/"${DEVICE_MODEL}"/g \
+ -e s/\{\{SERIAL\}\}/"${SERIAL}"/g \
+ -e s/\{\{BOARD_SERIAL\}\}/"${BOARD_SERIAL}"/g \
+ -e s/\{\{UUID\}\}/"${UUID}"/g \
+ -e s/\{\{ROM\}\}/"${ROM}"/g \
+ -e s/\{\{WIDTH\}\}/"${WIDTH:-1920}"/g \
+ -e s/\{\{HEIGHT\}\}/"${HEIGHT:-1080}"/g \
+ "${MASTER_PLIST}" > ./tmp.config.plist || exit 1
+ else
+ cat < < \__ \/ -_) '_| / _` | | | (_ / -_) ' \/ -_) '_/ _` | _/ _ \ '_|
+# \___/|___/_/\_\ |___/\___|_| |_\__,_|_| \___\___|_||_\___|_| \__,_|\__\___/_|
+#
+# Repo: https://github.com/sickcodes/osx-serial-generator/
+# Title: OSX Serial Generator
+# Author: Sick.Codes https://sick.codes/
+# Version: 3.1
+# License: GPLv3+
+
+set -e
+
+help_text="Usage: ./generate-unique-machine-values.sh
+
+General options:
+ --count, -n, -c Number of serials to generate
+ --model, -m Device model, e.g. 'iMacPro1,1'
+ --csv Optionally change the CSV output filename
+ --tsv Optionally change the TSV output filename
+ --output-dir Optionally change the script output location
+ --width Resolution x axis length in px, default 1920
+ --height Resolution y axis length in px, default 1080
+ --master-plist-url Specify an alternative master plist, via URL
+ --master-plist Optionally change the input plist
+ --custom-plist Same as --master-plist
+ --output-bootdisk Optionally change the bootdisk filename
+ --envs Create all corresponding sourcable envs
+ --plists Create all corresponding config.plists
+ --bootdisks Create all corresponding bootdisks [SLOW]
+ --help, -h, help Display this help and exit
+
+Additional options only if you are creating ONE serial set:
+ --output-bootdisk Optionally change the bootdisk filename
+ --output-env Optionally change the serials env filename
+
+Custom plist placeholders:
+ {{DEVICE_MODEL}}, {{SERIAL}}, {{BOARD_SERIAL}},
+ {{UUID}}, {{ROM}}, {{WIDTH}}, {{HEIGHT}}
+
+Example:
+ ./generate-unique-machine-values.sh --count 1 --plists --bootdisks --envs
+
+Defaults:
+ - One serial, for 'iMacPro1,1', in the current working directory
+ - CSV and TSV output
+ - plists in ./plists/ & bootdisks in ./bootdisks/ & envs in ./envs
+ - if you set --bootdisk name, --bootdisks is assumed
+ - if you set --custom-plist, --plists is assumed
+ - if you set --output-env, --envs is assumed
+
+Author: Sick.Codes https://sick.codes/
+Project: https://github.com/sickcodes/osx-serial-generator/
+License: GPLv3+
+"
+
+OPENCORE_IMAGE_MAKER_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/opencore-image-ng.sh'
+MASTER_PLIST_URL='https://raw.githubusercontent.com/sickcodes/osx-serial-generator/master/config-nopicker-custom.plist'
+
+# gather arguments
+while (( "$#" )); do
+ case "${1}" in
+
+ --help | -h | h | help )
+ echo "${help_text}" && exit 0
+ ;;
+
+ --count=* | -c=* | -n=* )
+ export SERIAL_SET_COUNT="${1#*=}"
+ shift
+ ;;
+ --count* | -c* | -n* )
+ export SERIAL_SET_COUNT="${2}"
+ shift
+ shift
+ ;;
+
+ --csv=* )
+ export CSV_OUTPUT_FILENAME="${1#*=}"
+ shift
+ ;;
+ --csv* )
+ export CSV_OUTPUT_FILENAME="${2}"
+ shift
+ shift
+ ;;
+
+ --tsv=* )
+ export TSV_OUTPUT_FILENAME="${1#*=}"
+ shift
+ ;;
+ --tsv* )
+ export TSV_OUTPUT_FILENAME="${2}"
+ shift
+ shift
+ ;;
+
+ --output-dir=* )
+ export OUTPUT_DIRECTORY="${1#*=}"
+ shift
+ ;;
+ --output-dir* )
+ export OUTPUT_DIRECTORY="${2}"
+ shift
+ shift
+ ;;
+
+ --output-bootdisk=* )
+ export OUTPUT_BOOTDISK="${1#*=}"
+ shift
+ ;;
+ --output-bootdisk* )
+ export OUTPUT_BOOTDISK="${2}"
+ shift
+ shift
+ ;;
+
+ --output-env=* )
+ export OUTPUT_ENV="${1#*=}"
+ shift
+ ;;
+ --output-env* )
+ export OUTPUT_ENV="${2}"
+ shift
+ shift
+ ;;
+
+ --model=* | -m=* )
+ export DEVICE_MODEL="${1#*=}"
+ shift
+ ;;
+ --model* | -m* )
+ export DEVICE_MODEL="${2}"
+ shift
+ shift
+ ;;
+
+ --width=* )
+ export WIDTH="${1#*=}"
+ shift
+ ;;
+
+ --width* )
+ export WIDTH="${2}"
+ shift
+ shift
+ ;;
+
+ --height=* )
+ export HEIGHT="${1#*=}"
+ shift
+ ;;
+ --height* )
+ export HEIGHT="${2}"
+ shift
+ shift
+ ;;
+
+ --master-plist-url=* )
+ export MASTER_PLIST_URL="${1#*=}"
+ shift
+ ;;
+
+ --master-plist-url* )
+ export MASTER_PLIST_URL="${2}"
+ shift
+ shift
+ ;;
+
+ --master-plist=* )
+ export MASTER_PLIST="${1#*=}"
+ shift
+ ;;
+
+ --master-plist* )
+ export MASTER_PLIST="${2}"
+ shift
+ shift
+ ;;
+
+ --custom-plist=* )
+ export MASTER_PLIST="${1#*=}"
+ shift
+ ;;
+
+ --custom-plist* )
+ export MASTER_PLIST="${2}"
+ shift
+ shift
+ ;;
+
+ --plists )
+ export CREATE_PLISTS=1
+ shift
+ ;;
+ --bootdisks )
+ export CREATE_BOOTDISKS=1
+ shift
+ ;;
+ --envs )
+ export CREATE_ENVS=1
+ shift
+ ;;
+
+ *)
+ echo "Invalid option. Running with default values..."
+ shift
+ ;;
+ esac
+done
+
+
+build_mac_serial () {
+ [ -d ./OpenCorePkg ] || git clone --depth 1 https://github.com/acidanthera/OpenCorePkg.git
+ make -C ./OpenCorePkg/Utilities/macserial/
+ mv ./OpenCorePkg/Utilities/macserial/macserial .
+ chmod +x ./macserial
+ stat ./macserial
+}
+
+download_vendor_mac_addresses () {
+ # download the MAC Address vendor list
+ [ -e "${MAC_ADDRESSES_FILE:=vendor_macs.tsv}" ] || wget -O "${MAC_ADDRESSES_FILE}" https://gitlab.com/wireshark/wireshark/-/raw/master/manuf
+}
+
+download_qcow_efi_folder () {
+ [ -d ./OSX-KVM ] || git clone --depth 1 https://github.com/kholia/OSX-KVM.git
+ cp -ra ./OSX-KVM/OpenCore-Catalina/EFI .
+ mkdir -p ./EFI/OC/Resources
+ # clone some Apple drivers
+ [ -d ./OcBinaryData ] || git clone --depth 1 https://github.com/acidanthera/OcBinaryData.git
+ # copy said drivers into EFI/OC/Resources
+ cp -a ./OcBinaryData/Resources/* ./EFI/OC/Resources
+ # EFI Shell commands
+ touch startup.nsh && echo 'fs0:\EFI\BOOT\BOOTx64.efi' > startup.nsh
+}
+
+
+generate_serial_sets () {
+
+
+
+ if [ "${CSV_OUTPUT_FILENAME}" ]; then
+ [ "${CSV_OUTPUT_FILENAME}" ] && export CSV_SERIAL_SETS_FILE="${CSV_OUTPUT_FILENAME}"
+ elif [ "${TSV_OUTPUT_FILENAME}" ]; then
+ [ "${TSV_OUTPUT_FILENAME}" ] && export TSV_SERIAL_SETS_FILE="${TSV_OUTPUT_FILENAME}"
+ else
+ export CSV_SERIAL_SETS_FILE="${OUTPUT_DIRECTORY}/serial_sets-${DATE_NOW}.csv"
+ export TSV_SERIAL_SETS_FILE="${OUTPUT_DIRECTORY}/serial_sets-${DATE_NOW}.tsv"
+ fi
+
+ ./macserial \
+ --num "${SERIAL_SET_COUNT}" \
+ --model "${DEVICE_MODEL}" \
+ | while IFS='\ \|\ ' read -r SERIAL BOARD_SERIAL; do
+ # make a uuid...
+ UUID="$(uuidgen)"
+ UUID="${UUID^^}"
+
+ # get a random vendor specific MAC address.
+ RANDOM_MAC_PREFIX="$(grep -e "${VENDOR_REGEX}" < "${MAC_ADDRESSES_FILE:=vendor_macs.tsv}" | sort --random-sort | head -n1)"
+ RANDOM_MAC_PREFIX="$(cut -d$'\t' -f1 <<< "${RANDOM_MAC_PREFIX}")"
+ MAC_ADDRESS="$(printf "${RANDOM_MAC_PREFIX}:%02X:%02X:%02X" $[RANDOM%256] $[RANDOM%256] $[RANDOM%256])"
+
+ [ -z "${WIDTH}" ] && WIDTH=1920
+ [ -z "${HEIGHT}" ] && HEIGHT=1080
+
+ # append to csv file
+ cat <> "${CSV_SERIAL_SETS_FILE}"
+"${DEVICE_MODEL}","${SERIAL}","${BOARD_SERIAL}","${UUID}","${MAC_ADDRESS}","${WIDTH}","${HEIGHT}"
+EOF
+ echo "Wrote CSV to: ${CSV_SERIAL_SETS_FILE}"
+
+ # append to tsv file
+ T=$'\t'
+ cat <> "${TSV_SERIAL_SETS_FILE}"
+${DEVICE_MODEL}${T}${SERIAL}${T}${BOARD_SERIAL}${T}${UUID}${T}${MAC_ADDRESS}${T}${WIDTH}${T}${HEIGHT}
+EOF
+ echo "Wrote CSV to: ${TSV_SERIAL_SETS_FILE}"
+
+ # make envs if --envs, but also if you set the env filename it will switch on by itself
+ if [ "${CREATE_ENVS}" ] || [ "${OUTPUT_ENV}" ]; then
+ mkdir -p "${OUTPUT_DIRECTORY}/envs"
+ OUTPUT_ENV_FILE="${OUTPUT_ENV:-"${OUTPUT_DIRECTORY}/envs/${SERIAL}.env.sh"}"
+ touch "${OUTPUT_ENV_FILE}"
+ cat < "${OUTPUT_ENV_FILE}"
+export DEVICE_MODEL="${DEVICE_MODEL}"
+export SERIAL="${SERIAL}"
+export BOARD_SERIAL="${BOARD_SERIAL}"
+export UUID="${UUID}"
+export MAC_ADDRESS="${MAC_ADDRESS}"
+export WIDTH="${WIDTH}"
+export HEIGHT="${HEIGHT}"
+EOF
+
+ fi
+
+ # plist required for bootdisks, so create anyway.
+ if [ "${CREATE_PLISTS}" ] || [ "${CREATE_BOOTDISKS}" ]; then
+
+ # need a config.plist
+ if [ "${MASTER_PLIST}" ]; then
+ [ -e "${MASTER_PLIST}" ] || echo "Could not find: ${MASTER_PLIST}"
+ elif [ "${MASTER_PLIST}" ] && [ "${MASTER_PLIST_URL}" ]; then
+ echo 'You specified both a custom plist FILE & custom plist URL.'
+ echo 'Use only one of those options.'
+ elif [ "${MASTER_PLIST_URL}" ]; then
+ wget -O "${MASTER_PLIST:=./config-custom.plist}" "${MASTER_PLIST_URL}"
+ else
+ # default is config-nopicker-custom.plist from OSX-KVM with placeholders used in Docker-OSX
+ wget -O "${MASTER_PLIST:=./config-nopicker-custom.plist}" "${MASTER_PLIST_URL}"
+ fi
+
+ mkdir -p "${OUTPUT_DIRECTORY}/plists"
+ source "${OUTPUT_ENV_FILE}"
+ ROM_VALUE="${MAC_ADDRESS//\:/}"
+ ROM_VALUE="${ROM_VALUE,,}"
+ sed -e s/\{\{DEVICE_MODEL\}\}/"${DEVICE_MODEL}"/g \
+ -e s/\{\{SERIAL\}\}/"${SERIAL}"/g \
+ -e s/\{\{BOARD_SERIAL\}\}/"${BOARD_SERIAL}"/g \
+ -e s/\{\{UUID\}\}/"${UUID}"/g \
+ -e s/\{\{ROM\}\}/"${ROM}"/g \
+ -e s/\{\{WIDTH\}\}/"${WIDTH}"/g \
+ -e s/\{\{HEIGHT\}\}/"${HEIGHT}"/g \
+ "${MASTER_PLIST}" > "${OUTPUT_DIRECTORY}/plists/${SERIAL}.config.plist" || exit 1
+ fi
+
+ # make bootdisk qcow2 format if --bootdisks, but also if you set the bootdisk filename
+ if [ "${CREATE_BOOTDISKS}" ] || [ "${OUTPUT_BOOTDISK}" ]; then
+ [ -e ./opencore-image-ng.sh ] \
+ || { wget "${OPENCORE_IMAGE_MAKER_URL}" \
+ && chmod +x opencore-image-ng.sh ; }
+ mkdir -p "${OUTPUT_DIRECTORY}/bootdisks"
+ ./opencore-image-ng.sh \
+ --cfg "${OUTPUT_DIRECTORY}/plists/${SERIAL}.config.plist" \
+ --img "${OUTPUT_BOOTDISK:-${OUTPUT_DIRECTORY}/bootdisks/${SERIAL}.OpenCore-nopicker.qcow2}" || exit 1
+ fi
+
+ done
+
+ [ -e "${CSV_SERIAL_SETS_FILE}" ] && \
+ cat <(echo "DEVICE_MODEL,SERIAL,BOARD_SERIAL,UUID,MAC_ADDRESS,WIDTH,HEIGHT") "${CSV_SERIAL_SETS_FILE}"
+
+
+ [ -e "${TSV_SERIAL_SETS_FILE}" ] && \
+ cat <(printf "DEVICE_MODEL\tSERIAL\tBOARD_SERIAL\tUUID\tMAC_ADDRESS\tWIDTH\tHEIGHT\n") "${TSV_SERIAL_SETS_FILE}"
+
+}
+
+main () {
+ # setting default variables if there are no options
+ export DATE_NOW="$(date +%F-%T)"
+ export DEVICE_MODEL="${DEVICE_MODEL:=iMacPro1,1}"
+ export VENDOR_REGEX="${VENDOR_REGEX:=Apple, Inc.}"
+ export SERIAL_SET_COUNT="${SERIAL_SET_COUNT:=1}"
+ export OUTPUT_DIRECTORY="${OUTPUT_DIRECTORY:=.}"
+ cat </dev/null 2>&1 || true
+ fi
+ sudo rm -rf "$WORK"
+}
+
+WORK="${TMPDIR-/var/tmp}/${0##*/}-$$"
+mkdir "$WORK" || exit 1
+trap 'do_cleanup' EXIT
+
+BASE="$(dirname $0)"
+
+######################################################################
+# parse args
+
+function print_help() {
+cat <
+ --img
+ --cfg
+EOF
+}
+
+while test "$1" != ""; do
+ case "$1" in
+ --iso)
+ iso="$2"
+ shift; shift
+ ;;
+ --img)
+ img="$2"
+ shift; shift
+ ;;
+ --cfg)
+ cfg="$2"
+ shift; shift
+ ;;
+ esac
+done
+
+######################################################################
+# guestfish script helpers
+
+function fish() {
+ echo "#" "$@"
+ guestfish --remote -- "$@" || exit 1
+}
+
+function fish_init() {
+ local format
+
+ case "$img" in
+ *.raw) format="raw" ;;
+ *) format="qcow2";;
+ esac
+
+ msg "creating and adding disk image"
+ fish disk-create $img $format 384M
+ fish add $img
+ fish run
+}
+
+function fish_fini() {
+ fish umount-all
+}
+
+# disabled by @sickcodes to allow unattended image overwrites
+######################################################################
+# sanity checks
+
+# if test ! -f "$cfg"; then
+# echo "ERROR: cfg not found: $cfg"
+# exit 1
+# fi
+# if test -f "$img"; then
+# if test "$allow_override" = "yes"; then
+# rm -f "$img"
+# else
+# echo "ERROR: image exists: $img"
+# exit 1
+# fi
+# fi
+
+######################################################################
+# go!
+
+msg "copy files from local folder"
+BASE="$(dirname $0)"
+cp -a $BASE/EFI $WORK
+find "$WORK"
+
+#msg "[debug] list drivers in EFI/OC"
+#(cd $WORK/EFI/OC; find driver* -print)
+
+export LIBGUESTFS_BACKEND=direct
+eval $(guestfish --listen)
+if test "$GUESTFISH_PID" = ""; then
+ echo "ERROR: starting guestfish failed"
+ exit 1
+fi
+
+fish_init
+
+msg "partition disk image"
+fish part-init /dev/sda gpt
+fish part-add /dev/sda p 2048 300000
+fish part-add /dev/sda p 302048 -2048
+fish part-set-gpt-type /dev/sda 1 C12A7328-F81F-11D2-BA4B-00A0C93EC93B
+fish part-set-bootable /dev/sda 1 true
+fish mkfs vfat /dev/sda1 label:EFI
+fish mkfs vfat /dev/sda2 label:OpenCoreBoo
+fish mount /dev/sda2 /
+fish mkdir /ESP
+fish mount /dev/sda1 /ESP
+
+msg "copy files to disk image"
+cp -v "$cfg" $WORK/config.plist
+fish mkdir /ESP/EFI
+fish mkdir /ESP/EFI/OC
+fish mkdir /ESP/EFI/OC/Kexts
+fish mkdir /ESP/EFI/OC/ACPI
+fish mkdir /ESP/EFI/OC/Resources
+fish mkdir /ESP/EFI/OC/Tools
+fish copy-in $WORK/EFI/BOOT /ESP/EFI
+fish copy-in $WORK/EFI/OC/OpenCore.efi /ESP/EFI/OC
+fish copy-in $WORK/EFI/OC/Drivers /ESP/EFI/OC/
+fish copy-in $WORK/EFI/OC/Kexts /ESP/EFI/OC/
+fish copy-in $WORK/EFI/OC/ACPI /ESP/EFI/OC/
+fish copy-in $WORK/EFI/OC/Resources /ESP/EFI/OC/
+fish copy-in $WORK/EFI/OC/Tools /ESP/EFI/OC/
+
+# Note
+fish copy-in startup.nsh /
+
+BASE="$(dirname $0)"
+fish copy-in "$WORK/config.plist" /ESP/EFI/OC/
+
+fish find /ESP/
+fish_fini