Last active
June 13, 2024 10:22
-
-
Save joevt/a4ef4cd2e1485d0dd595893007bdfd6a to your computer and use it in GitHub Desktop.
Commands for kexts
This file contains 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 | |
# joevt Jun 12, 2024 | |
#10.3 Panther to 10.13 High Sierra | |
kextload=kextload | |
# Later macOS versions | |
command -v kextutil > /dev/null 2>&1 && kextload=kextutil | |
getkextidentifier () { | |
local thekextpath="$1" | |
if [[ ! -f "$thekextpath/Contents/Info.plist" ]]; then | |
echo "# Missing Info.plist." 1>&2 | |
return 1 | |
fi | |
# Mac OS X 10.4 doesn't have PlistBuddy so just use perl | |
perl -0777 -n -e 'if (m|<key>CFBundleIdentifier</key>\s*<string>(.+)</string>|) { print $1 }' "$thekextpath/Contents/Info.plist" | |
} | |
checkkext () { | |
local thekextpath="$1" | |
if [[ -d "$thekextpath" ]]; then | |
if [[ -f "$thekextpath/Contents/Info.plist" ]]; then | |
local kextname | |
kextname="$(basename "$thekextpath")" | |
if grep -q -E "\.kext$" <<< "$kextname"; then | |
local kextidentifier="" | |
kextidentifier="$(getkextidentifier "$thekextpath")" | |
local theerr=$? | |
if (( theerr == 0 )); then | |
return 0 | |
else | |
echo "# Missing CFBundleIdentifier." 1>&2 | |
return 1 | |
fi | |
else | |
echo "# \"$kextname\" not a kext." 1>&2 | |
return 1 | |
fi | |
else | |
echo "# Missing Info.plist." 1>&2 | |
return 1 | |
fi | |
else | |
echo "# Expected a kext package directory." 1>&2 | |
return 1 | |
fi | |
} | |
unloadkext () { | |
local thekextpath="$1" | |
checkkext "$thekextpath" || return 1 | |
local kextname | |
kextname="$(basename "$thekextpath")" | |
local kextidentifier | |
kextidentifier="$(getkextidentifier "$thekextpath")" | |
echo "# kextname: $kextname" | |
echo "# kextidentifier: $kextidentifier" | |
if ( kextstat 2> /dev/null | grep -q "$kextidentifier" ); then | |
while : ; do | |
echo "# Unloading ${kextname}." | |
sudo kextunload -b "$kextidentifier" | |
( kextstat 2> /dev/null | grep -q "$kextidentifier" ) || break | |
sleep 1 | |
done | |
echo "# Unloaded ${kextname}." | |
else | |
echo "# ${kextname} is not loaded." | |
fi | |
} | |
checkkextpermissions () { | |
local thekextpath="$1" | |
checkkext "$thekextpath" || return 1 | |
badpermissions="$(find "$thekextpath" -exec ls -ld {} \; | sed -E '/drwxr-xr-x.* root *wheel /d ; /-rw.r-.r-..* root *wheel /d')" | |
if (( $(printf "%s" "$badpermissions" | wc -l) == 0 )); then | |
return 0 | |
fi | |
echo "# Permissions are not correct for the following:" 1>&2 | |
echo "$badpermissions" 1>&2 | |
return 1 | |
} | |
fixkextpermissions () { | |
local thekextpath="$1" | |
checkkext "$thekextpath" || return 1 | |
if checkkextpermissions "$thekextpath" 2> /dev/null ; then | |
echo "# Permissions are good. No changes were required." | |
return 0 | |
fi | |
sudo chown -R root:wheel "$thekextpath" | |
sudo find "$thekextpath" -type d -exec /bin/chmod 0755 {} \; | |
sudo find "$thekextpath" -type f -exec /bin/chmod 0644 {} \; | |
if checkkextpermissions "$thekextpath" 2> /dev/null ; then | |
echo "# Fixed permissions." | |
return 0 | |
fi | |
echo "# Could not fix permissions." 1>&2 | |
return 1 | |
} | |
loadkext () { | |
local thekextpath="$1" | |
checkkext "$thekextpath" || return 1 | |
local kextname | |
kextname="$(basename "$thekextpath")" | |
local kextloadpath | |
if fixkextpermissions "$thekextpath" > /dev/null 2>&1 ; then | |
kextloadpath="$thekextpath" | |
else | |
echo "# Cannot fix permissions. Will load kext from temporary directory." 1>&2 | |
local kexttmpdir | |
kexttmpdir="$(mktemp -d /tmp/KextUtil_XXXXXXX)" | |
kextloadpath="$kexttmpdir/$kextname" | |
sudo cp -R "$thekextpath" "$kextloadpath" | |
if ! fixkextpermissions "$kextloadpath" ; then | |
return 1 | |
fi | |
fi | |
unloadkext "$kextloadpath" | |
if ( sudo "$kextload" "$kextloadpath" ); then | |
echo "# Loaded ${kextname}." | |
return 0 | |
else | |
echo "# $kextname was not loaded." 1>&2 | |
return 1 | |
fi | |
} | |
mountsystemrw () { | |
mount | grep ' on / ' | grep -q 'read-only' && sudo mount -uw / | |
} | |
installkext () { | |
local doload=0 | |
local dosystem=0 | |
while (( $# )); do | |
if [[ "$1" == "-l" ]]; then | |
doload=1 | |
elif [[ "$1" == "-s" ]]; then | |
dosystem=1 | |
else | |
break | |
fi | |
shift 1 | |
done | |
local thekextpath="$1" | |
checkkext "$thekextpath" || return 1 | |
local kextname | |
kextname="$(basename "$thekextpath")" | |
local kextinstalldir="/Library/Extensions" | |
if ((dosystem)) || [[ ! -d /Library/Extensions ]] ; then | |
kextinstalldir="/System/Library/Extensions" | |
dosystem=1 | |
fi | |
local kextidentifier | |
kextidentifier="$(getkextidentifier "$thekextpath")" | |
if ((doload)); then | |
# unloadkext will do these echo lines for us: | |
# echo "# kextname: $kextname" | |
# echo "# kextidentifier: $kextidentifier" | |
unloadkext "$thekextpath" | |
else | |
echo "# kextname: $kextname" | |
echo "# kextidentifier: $kextidentifier" | |
fi | |
local kexttmpdir | |
kexttmpdir="$(mktemp -d /tmp/KextUtil_XXXXXXX)" | |
kextloadpath="$kexttmpdir/$kextname" | |
sudo cp -R "$thekextpath" "$kextloadpath" | |
if ! fixkextpermissions "$kextloadpath" ; then | |
return 1 | |
fi | |
if [[ -d "/System/Library/Extensions/$kextname" ]]; then | |
mountsystemrw | |
sudo rm -R "/System/Library/Extensions/$kextname" | |
fi | |
if [[ -d "/Library/Extensions/$kextname" ]]; then | |
sudo rm -R "/Library/Extensions/$kextname" | |
fi | |
if ((dosystem)); then | |
mountsystemrw | |
fi | |
sudo mv "$kextloadpath" "$kextinstalldir" | |
echo "# Installed ${kextname}." | |
if ((doload)); then | |
sudo "$kextload" "$kextinstalldir/$kextname" | |
kextstat 2> /dev/null | grep "$kextidentifier" | |
echo "# Loaded ${kextname}." | |
fi | |
} | |
removekext () { | |
local thekextpath="$1" | |
checkkext "$thekextpath" || return 1 | |
local kextname | |
kextname="$(basename "$thekextpath")" | |
if [[ "$thekextpath" == /System/Library/* ]] ; then | |
mountsystemrw | |
fi | |
sudo rm -R "$thekextpath" && echo "# Removed ${kextname}." || echo "# Error removing ${kextname}." | |
} | |
rebuildkextcache () { | |
sudo kextcache -i / | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage
Load the commands into the terminal like this:
source KextUtil.sh
Utility Functions
These utility functions are used by the main functions listed below.
getkextidentifier
kextpathkextstat
or to unload the kext.checkkext
kextpathstderr
.checkkext
before attempting to do anything.checkkextpermissions
kextpathstderr
.fixkextpermissions
to see if the permissions need to be fixed.fixkextpermissions
kextpathloadkext
,unloadkext
, andinstallkext
.Main Functions
loadkext
kextpathunloadkext
kextpathinstallkext
[-s] [-l] kextpath/Library/Extensions
. if-s
is specified then the install location is/System/Library/Extensions
. Do not use-s
for Big Sur and later.-l
is specified. It will first unload previously loaded kext if necessary./System/Library/Extensions
if it exists there. It will mount the root volume as read/write if necessary (works in the case of Catalina; for later macOS it is expected that the kext will not be in/System
)./Library/Extensions
if it exists there.removekext
kextpath/System
).Updates
Jun 12, 2024
kextutil
.Feb 10, 2024
/Library/Extensions
if it doesn't exist (as in Mac OS X 10.4 Tiger).May 9, 2023
loadkext
andinstallkext
.checkkext
,installkext
, andremovekext
.May 8, 2023
unloadkext
.checkkextpermissions
so thatchown
andchmod
are not used unnecessarily.fixkextpermissions
now returns a status if the permissions needed to be fixed but could not be fixed.loadkext
will now load a kext from its current location if possible. It may modify permissions if necessary. It will revert to using a temporary directory if necessary.mountsystemrw
for mounting the/
root volume as read write. This is useful for Catalina.removekext
now mounts the root volume as read write if necessary.Jan 31, 2023
-s
option forinstallkext
to install to/System/Library/Extensions
. This is required to load unsigned kexts in OS X 10.9 Mavericks.Jan 6, 2023
Dec 8, 2022