Last active
May 10, 2025 01:45
-
-
Save ryandesign/f631ae21d4d1a40f899a1efc0002b5f9 to your computer and use it in GitHub Desktop.
Adds ext4 driver to OpenCore Legacy Patcher so that a Linux partition can be selected.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# SPDX-FileCopyrightText: © 2024 Ryan Carsten Schmidt <https://github.com/ryandesign> | |
# SPDX-License-Identifier: MIT | |
# | |
# Adds ext4 driver to OpenCore Legacy Patcher so that a Linux partition can be selected. | |
# Based on instructions by rikerjoe at: | |
# https://tinkerdifferent.com/threads/dual-boot-linux-mint-21-2-and-macos-with-opencore-legacy-patcher-and-opencore-bootpicker.3115/ | |
set -u | |
: "${OC_DRIVER_URL:=https://github.com/acidanthera/OcBinaryData/raw/dcf5032351154034e7c8ef6fd15674b1c71e3d92/Drivers/ext4_x64.efi}" | |
: "${PLISTBUDDY:=/usr/libexec/PlistBuddy}" | |
: "${TMPDIR:=/tmp}" | |
script_name="${0##*/}" | |
err() { | |
echo "$script_name: $1" | |
exit "${2:-1}" | |
} | |
get_efi_device() { | |
local device= | |
diskutil list -plist > "$tmpfile" || return $? | |
local disk=0 | |
while [[ -z $device ]]; do | |
"$PLISTBUDDY" -c "Print :AllDisksAndPartitions:$disk:DeviceIdentifier" "$tmpfile" >/dev/null 2>&1 || break | |
local partition=0 | |
while [[ -z $device ]]; do | |
local content | |
content=$("$PLISTBUDDY" -c "Print :AllDisksAndPartitions:$disk:Partitions:$partition:Content" "$tmpfile" 2>/dev/null) || break | |
[[ $content = "EFI" ]] && device=$("$PLISTBUDDY" -c "Print :AllDisksAndPartitions:$disk:Partitions:$partition:DeviceIdentifier" "$tmpfile") | |
partition=$((partition + 1)) | |
done | |
disk=$((disk + 1)) | |
done | |
[[ -n $device ]] || return 1 | |
echo "$device" | |
} | |
get_device_mountpoint() { | |
diskutil info -plist "$1" > "$tmpfile" || return $? | |
local mountpoint | |
mountpoint=$("$PLISTBUDDY" -c "Print :MountPoint" "$tmpfile") || return $? | |
[[ -n $mountpoint ]] || return 1 | |
echo "$mountpoint" | |
} | |
mount_device() { | |
sudo diskutil mount "$1" >/dev/null | |
} | |
unmount_device() { | |
sudo diskutil unmount "$1" >/dev/null | |
} | |
plist_has_array_item() { | |
local plist="$1" | |
local array_path="$2" | |
local dict_key="$3" | |
local dict_value="$4" | |
local found= | |
local index=0 | |
while [[ -z $found ]]; do | |
value=$("$PLISTBUDDY" -c "Print $array_path:$index:$dict_key" "$plist" 2>/dev/null) || break | |
if [[ $value = "$dict_value" ]]; then | |
found=1 | |
break | |
fi | |
index=$((index + 1)) | |
done | |
[[ -n $found ]] || return 1 | |
} | |
cleanup() { | |
if [[ -n "${oc_config_bak-}" ]] && cmp -s "$oc_config" "$oc_config_bak"; then | |
echo "Deleting $oc_config_bak because no changes were made" | |
rm -f "$oc_config_bak" | |
fi | |
if [[ -n "${unmount_efi_device-}" ]]; then | |
unmount_device "$efi_device" && echo "Unmounted EFI partition" | |
elif [[ -n "${efi_mountpoint-}" ]]; then | |
echo "Leaving EFI partition mounted" | |
fi | |
rm -f "$tmpfile" | |
} | |
tmpfile=$(mktemp "$TMPDIR/$script_name.XXXXXXXX") || exit $? | |
trap cleanup EXIT | |
efi_device=$(get_efi_device) || err "Cannot find EFI partition" | |
if efi_mountpoint=$(get_device_mountpoint "$efi_device"); then | |
echo "EFI partition is already mounted at $efi_mountpoint" | |
else | |
[[ $(id -u) = 0 ]] || err "Must be run as root to mount and unmount EFI partition" | |
mount_device "$efi_device" || exit $? | |
efi_mountpoint=$(get_device_mountpoint "$efi_device") | |
unmount_efi_device=1 | |
echo "Mounted EFI partition at $efi_mountpoint" | |
fi | |
oc_dir="$efi_mountpoint/EFI/OC" | |
oc_config="$oc_dir/config.plist" | |
oc_driver="${OC_DRIVER_URL##*/}" | |
oc_drivers_dir="$oc_dir/Drivers" | |
if [[ -e "$oc_drivers_dir/$oc_driver" ]]; then | |
echo "Driver $oc_driver is already on EFI partition" | |
else | |
[[ -d "$oc_drivers_dir" ]] || err "$oc_drivers_dir does not exist" | |
echo "Downloading driver $oc_driver" | |
curl -fLsSo "$tmpfile" "$OC_DRIVER_URL" || exit $? | |
mime=$(file --brief --mime-type "$tmpfile") || exit $? | |
[[ "$mime" = "application/x-dosexec" ]] || err "$oc_driver does not look like an EFI driver" | |
echo "Moving driver $oc_driver to EFI partition" | |
mv "$tmpfile" "$oc_drivers_dir/$oc_driver" || exit $? | |
fi | |
[[ -e "$oc_config" ]] || err "$oc_config does not exist" | |
oc_config_bak="$oc_config.bak" | |
[[ -e "$oc_config_bak" ]] && oc_config_bak="$oc_config_bak.$(date +%s)" | |
echo "Backing up $oc_config to $oc_config_bak" | |
cp -a "$oc_config" "$oc_config_bak" | |
if plist_has_array_item "$oc_config" :UEFI:Drivers Path "OpenLinuxBoot.efi"; then | |
echo "Driver OpenLinuxBoot.efi is already in $oc_config" | |
else | |
err "Driver OpenLinuxBoof.efi is not in $oc_config" | |
fi | |
if plist_has_array_item "$oc_config" :UEFI:Drivers Path "$oc_driver"; then | |
echo "Driver $oc_driver is already in $oc_config" | |
else | |
echo "Adding driver $oc_driver to $oc_config" | |
"$PLISTBUDDY" \ | |
-c "Add :UEFI:Drivers:0 dict" \ | |
-c "Add :UEFI:Drivers:0:Arguments string" \ | |
-c "Add :UEFI:Drivers:0:Comment string" \ | |
-c "Add :UEFI:Drivers:0:Enabled bool" \ | |
-c "Set :UEFI:Drivers:0:Enabled true" \ | |
-c "Add :UEFI:Drivers:0:LoadEarly bool" \ | |
-c "Set :UEFI:Drivers:0:LoadEarly false" \ | |
-c "Add :UEFI:Drivers:0:Path string" \ | |
-c "Set :UEFI:Drivers:0:Path $oc_driver" \ | |
"$oc_config" || exit $? | |
fi | |
for key in RequestBootVarRouting LauncherOption HideAuxiliary; do | |
path=":UEFI:Quirks:$key" | |
desired_value=true | |
if value=$("$PLISTBUDDY" -c "Print $path" "$oc_config" 2>/dev/null); then | |
if [[ $value = "$desired_value" ]]; then | |
echo "$path is already $desired_value" | |
else | |
echo "Setting $path to $desired_value" | |
"$PLISTBUDDY" -c "Set $path $desired_value" "$oc_config" || exit $? | |
fi | |
else | |
echo "Adding new key $path and setting to $desired_value" | |
"$PLISTBUDDY" -c "Add $path bool $desired_value" "$oc_config" || exit $? | |
fi | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment