Skip to content

Instantly share code, notes, and snippets.

@ryandesign
Last active May 11, 2024 08:20
Show Gist options
  • Save ryandesign/f631ae21d4d1a40f899a1efc0002b5f9 to your computer and use it in GitHub Desktop.
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.
#!/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