Skip to content

Commit

Permalink
Automate firmware (#558)
Browse files Browse the repository at this point in the history
  • Loading branch information
sharpenedblade committed Jul 12, 2024
1 parent 90ed05d commit fe8c338
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 50 deletions.
204 changes: 154 additions & 50 deletions docs/tools/firmware.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
#!/usr/bin/env bash
#
# Copyright (C) 2022 Aditya Garg <[email protected]>
# Copyright (C) 2022 Orlando Chamberlain <[email protected]>

# Copyright (C) 2024 Aditya Garg <[email protected]>
# Copyright (C) 2024 Orlando Chamberlain <[email protected]>
# Copyright (C) 2024 Sharpened Blade <[email protected]>
#
# The python script is based upon the original work by The Asahi Linux Contributors.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

rename_firmware () {
python3 - "$@" <<'EOF'
Expand Down Expand Up @@ -336,16 +355,114 @@ EOF
set -euo pipefail

verbose=""
while getopts "vhxp" option; do
subcmd=""
target_pkg_manager=""
args=()
interactive="true"
while getopts "ivhxp" option; do
case $option in
i) interactive="false" ;;
v) verbose="-v" ;;
h) echo "usage: $0 [-vhxp] [fw_dir_path output_archive_path]"; exit 0 ;;
h)
cat <<- EOF
usage: $0 [-vhx] subcommand [subcmd args]
Subcommands:
rename_only /path/to/firmware archive.tar
copy_to_efi
create_archive
create_package apt|rpm|pacman
get_from_efi
get_from_macos
get_from_online
EOF
exit 0 ;;
x) set -x;;
p) rename_firmware "${@:2:2}" ${verbose} && exit 0 ;;
?) exit 1 ;;
esac
done

if [[ "${1-}" == -* ]]; then
subcmd="${2-}"
args=( "${@:3}" )
else
subcmd="${1-}"
args=( "${@:2}" )
fi

if [[ "$subcmd" = "" ]] && [[ "$interactive" = "true" ]]; then
case "$(uname -s)" in
(Darwin)
echo "Detected macOS"
cat <<- EOF
How do you want to copy the firmware to Linux?
1. Copy the firmware to the EFI partition and run the same script on Linux to retrieve it.
2. Create a tarball of the firmware and extract it to Linux.
3. Create a Linux specific package which can be installed using a package manager.
Note: Option 2 and 3 require additional software like python3 and tools specific for your package manager. Requirements will be told as you proceed further.
EOF
read -r choice
case ${choice} in
(1) subcmd="copy_to_efi" ;;
(2) subcmd="create_archive" ;;
(3) subcmd="create_package"
echo -e "\nWhat package manager does your Linux distribution use?\n"
echo "1. apt"
echo "2. dnf"
echo "3. pacman"
read -r target_pkg_manager
case ${target_pkg_manager} in
(1) target_pkg_manager="apt" ;;
(2) target_pkg_manager="rpm" ;;
(3) target_pkg_manager="pacman" ;;
(*) echo -e "\nError: Invalid option!" && exit 1 ;;
esac
;;
(*) echo -e "\nError: Invalid option!" && exit 1 ;;
esac
;;
(Linux)
echo "Detected Linux"
cat <<- EOF
How do you want to copy the firmware to Linux?
1. Retrieve the firmware from the EFI partition.
2. Retrieve the firmware directly from macOS.
3. Download a macOS Recovery Image from Apple and extract the firmware from there.
Note: If you are choosing Option 1, then make sure you have run the same script on macOS before and chose Option 1 (Copy the firmware to the EFI partition and run the same script on Linux to retrieve it) there.
EOF
read -r choice
case ${choice} in
(1)
subcmd="get_from_efi" ;;
(2)
subcmd="get_from_macos" ;;
(3)
subcmd="get_from_online" ;;
(*)
echo -e "\nError: Invalid option!"
exit 1
;;
esac
;;
(*)
echo "Error: unsupported platform"
;;
esac
fi

if [[ "$subcmd" = "" ]]; then
echo "No subcommand specified"
exit 1
elif [[ "$subcmd" = "create_package" ]] && [[ "$target_pkg_manager" = "" ]]; then
target_pkg_manager="${args[0]}"
fi

aur_install() {
local aur_package=$1
local dir
Expand Down Expand Up @@ -397,6 +514,11 @@ install_package() {
local package=$1
local package_manager
package_manager=$(detect_package_manager)
if [[ "$interactive" = "false" ]]; then
echo "$package is missing. Install it then try again"
echo "Exiting"
exit 1
fi
if [[ $package = "linux-apfs-rw" ]]
then
local apfs_driver_link=https://github.com/linux-apfs/linux-apfs-rw.git
Expand Down Expand Up @@ -480,6 +602,11 @@ create_firmware_archive() {
}

python_check () {
if [[ "$interactive" = "false" ]]; then
echo "Xcode command line tools are missing."
echo "Exiting"
exit 1
fi
echo -e "\nChecking for missing dependencies"
if [ ! -f "/Library/Developer/CommandLineTools/usr/bin/python3" ] && [ ! -f "/Applications/Xcode.app/Contents/Developer/usr/bin/python3" ]
then
Expand Down Expand Up @@ -708,7 +835,6 @@ nvram_txcap_quirk() {
os=$(uname -s)
case "$os" in
(Darwin)
echo "Detected macOS"
ver=$(sw_vers -productVersion)
ver_check=$(sw_vers -productVersion | cut -d "." -f 1)
identifier=$(system_profiler SPHardwareDataType | grep "Model Identifier" | cut -d ":" -f 2 | xargs)
Expand All @@ -726,19 +852,8 @@ case "$os" in
EOF
fi
cat <<- EOF
How do you want to copy the firmware to Linux?
1. Copy the firmware to the EFI partition and run the same script on Linux to retrieve it.
2. Create a tarball of the firmware and extract it to Linux.
3. Create a Linux specific package which can be installed using a package manager.
Note: Option 2 and 3 require additional software like python3 and tools specific for your package manager. Requirements will be told as you proceed further.
EOF
read -r choice
case ${choice} in
(1)
case ${subcmd} in
("copy_to_efi")
echo -e "\nMounting the EFI partition"
EFILABEL=$(diskutil info disk0s1 | grep "Volume Name" | cut -d ":" -f 2 | xargs)
sudo diskutil mount disk0s1
Expand All @@ -751,11 +866,10 @@ case "$os" in
echo "Copying this script to EFI"
cp "$0" "/Volumes/${EFILABEL}/firmware.sh" 2>/dev/null \
|| curl -s https://wiki.t2linux.org/tools/firmware.sh > "/Volumes/${EFILABEL}/firmware.sh" \
|| (echo && cat <<- EOF && read -r
|| ( echo && cat <<- EOF && [ "$interactive" = "true" ] && echo "Press enter after you have copied" && read -r
Failed to copy script.
Please copy the script manually to the EFI partition using Finder
Make sure the name of the script is firmware.sh in the EFI partition
Press enter after you have copied"
EOF
)
sudo diskutil unmount "/Volumes/${EFILABEL}/"
Expand All @@ -769,7 +883,7 @@ case "$os" in
sudo umount /tmp/apple-wifi-efi
EOF
;;
(2)
("create_archive")
python_check
echo -e "\nCreating a tarball of the firmware"
create_firmware_archive /usr/share/firmware "$HOME/Downloads/firmware.tar"
Expand All @@ -786,21 +900,16 @@ case "$os" in
sudo modprobe hci_bcm4377
EOF
;;
(3)
echo -e "\nWhat package manager does your Linux distribution use?\n"
echo "1. apt"
echo "2. dnf"
echo "3. pacman"
read -r package
("create_package")
python_check
case ${package} in
(1)
case ${target_pkg_manager} in
("apt")
create_deb
;;
(2)
("dnf")
create_rpm
;;
(3)
("pacman")
create_arch_pkg
;;
(*)
Expand All @@ -809,6 +918,9 @@ case "$os" in
;;
esac
;;
("rename_only")
rename_firmware "${args[@]}" ${verbose}
;;
(*)
echo -e "\nError: Invalid option!"
exit 1
Expand All @@ -817,7 +929,6 @@ case "$os" in
;;

(Linux)
echo "Detected Linux"
if [[ ! -e /lib/firmware/brcm ]]; then
cat <<- EOF
/lib/firmware/brcm does not seem to exist. This script requires that directory to function.
Expand All @@ -827,19 +938,8 @@ case "$os" in
EOF
exit 1
fi
cat <<- EOF
How do you want to copy the firmware to Linux?
1. Retrieve the firmware from the EFI partition.
2. Retrieve the firmware directly from macOS.
3. Download a macOS Recovery Image from Apple and extract the firmware from there.
Note: If you are choosing Option 1, then make sure you have run the same script on macOS before and chose Option 1 (Copy the firmware to the EFI partition and run the same script on Linux to retrieve it) there.
EOF
read -r choice
case ${choice} in
(1)
case ${subcmd} in
("get_from_efi")
echo -e "\nRe-mounting the EFI partition"
mountpoint=$(mktemp -d)
workdir=$(mktemp -d)
Expand All @@ -860,7 +960,11 @@ case "$os" in
done
reload_kernel_modules
echo -e "\nKeeping a copy of the firmware and the script in the EFI partition shall allow you to set up Wi-Fi again in the future by running this script or the commands told in the macOS step in Linux only, without the macOS step."
read -rp "Do you want to keep a copy? (y/N)" input
if [ "$interactive" = "true" ]; then
read -rp "Do you want to keep a copy? (y/N)" input
else
input="y"
fi
if [[ ($input != y) && ($input != Y) ]]
then
echo -e "\nRemoving the copy from the EFI partition"
Expand All @@ -878,7 +982,7 @@ case "$os" in
sudo rmdir ${verbose} "$mountpoint"
echo -e "\nDone!"
;;
(2)
("get_from_macos")
echo -e "\nChecking for missing dependencies"
# Load the apfs driver, and install if missing
sudo modprobe ${verbose} apfs 2>/dev/null || install_package linux-apfs-rw
Expand Down Expand Up @@ -925,7 +1029,7 @@ case "$os" in
unmount_macos_and_cleanup
echo "Done!"
;;
(3)
("get_from_online")
# Detect whether curl and dmg2img are installed
echo -e "\nChecking for missing dependencies"
curl --version >/dev/null 2>&1 || install_package curl
Expand Down
14 changes: 14 additions & 0 deletions docs/tools/get-apple-firmware.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[Unit]
Description=Get Apple WiFi and Bluetooth firmware
ConditionFirstBoot=yes
ConditionPathExists=/lib/firmware/brcm
Wants=first-boot-complete.target
Before=first-boot-complete.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/libexec/get-apple-firmware -i get_from_macos

[Install]
WantedBy=multi-user.target

0 comments on commit fe8c338

Please sign in to comment.