mirror of
https://github.com/ublue-os/bazzite.git
synced 2025-02-21 09:39:49 +00:00
feat: Add jupiter-hw-support-bazzite spec that lacks drive handling scripts.
chore: Initial add of drive handling scripts from jupiter-hw-support package to our repo.
This commit is contained in:
parent
2c68978bd4
commit
6f6f1dbca5
108
spec_files/jupiter-hw-support/jupiter-hw-support-bazzite.spec
Normal file
108
spec_files/jupiter-hw-support/jupiter-hw-support-bazzite.spec
Normal file
@ -0,0 +1,108 @@
|
||||
%define packagename jupiter-hw-support
|
||||
Name: %{packagename}-bazzite
|
||||
Version: {{{ git_dir_version }}}
|
||||
Release: 1%{?dist}
|
||||
Summary: Steam Deck Hardware Support Package
|
||||
License: GPLv3
|
||||
URL: https://github.com/ublue-os/bazzite
|
||||
|
||||
Source: https://gitlab.com/evlaV/%{packagename}/-/archive/master/%{packagename}-master.tar.gz
|
||||
Patch0: fedora.patch
|
||||
|
||||
Requires: python3
|
||||
Requires: python3-libevdev
|
||||
Requires: python3-crcmod
|
||||
Requires: python3-click
|
||||
Requires: python3-progressbar2
|
||||
Requires: python3-hid
|
||||
Requires: hidapi
|
||||
Requires: dmidecode
|
||||
Requires: jq
|
||||
Requires: alsa-utils
|
||||
Requires: parted
|
||||
Requires: e2fsprogs
|
||||
|
||||
BuildRequires: systemd-rpm-macros
|
||||
|
||||
%description
|
||||
SteamOS 3.0 Steam Deck Hardware Support Package
|
||||
|
||||
# Disable debug packages
|
||||
%define debug_package %{nil}
|
||||
|
||||
%prep
|
||||
%setup -n %{packagename}-master
|
||||
%patch 0 -p1
|
||||
|
||||
%build
|
||||
|
||||
%install
|
||||
export QA_RPATHS=0x0003
|
||||
mkdir -p %{buildroot}%{_datadir}/
|
||||
mkdir -p %{buildroot}%{_unitdir}/
|
||||
mkdir -p %{buildroot}%{_bindir}/
|
||||
mkdir -p %{buildroot}%{_sysconfdir}/
|
||||
cp -rv usr/share/* %{buildroot}%{_datadir}
|
||||
cp -rv usr/lib/systemd/system/* %{buildroot}%{_unitdir}/
|
||||
cp -rv usr/lib/hwsupport %{buildroot}%{_prefix}/lib/hwsupport
|
||||
cp -rv usr/lib/udev %{buildroot}%{_prefix}/lib/udev
|
||||
cp -rv usr/bin/* %{buildroot}%{_bindir}
|
||||
cp -rv usr/lib/systemd/system/* %{buildroot}%{_unitdir}
|
||||
cp -rv etc/* %{buildroot}%{_sysconfdir}
|
||||
# Remove unneeded files
|
||||
rm %{buildroot}%{_sysconfdir}/default/grub-steamos
|
||||
rm %{buildroot}%{_datadir}/jupiter_bios_updater/h2offt-g
|
||||
rm %{buildroot}%{_datadir}/jupiter_bios_updater/H2OFFTx64-G.sh
|
||||
rm -rf %{buildroot}%{_datadir}/jupiter_bios_updater/driver
|
||||
rm -rf %{buildroot}%{_unitdir}/multi-user.target.wants
|
||||
rm %{buildroot}%{_prefix}/lib/udev/rules.d/99-steamos-automount.rules
|
||||
rm %{buildroot}%{_prefix}/lib/hwsupport/format-device.sh
|
||||
rm %{buildroot}%{_prefix}/lib/hwsupport/steamos-automount.sh
|
||||
|
||||
# Do post-installation
|
||||
%post
|
||||
%systemd_post jupiter-biosupdate.service
|
||||
%systemd_post jupiter-controller-update.service
|
||||
|
||||
# Do before uninstallation
|
||||
%preun
|
||||
%systemd_preun jupiter-biosupdate.service
|
||||
%systemd_preun jupiter-controller-update.service
|
||||
|
||||
# Do after uninstallation
|
||||
%postun
|
||||
%systemd_postun_with_restart jupiter-biosupdate.service
|
||||
%systemd_postun_with_restart jupiter-controller-update.service
|
||||
|
||||
# This lists all the files that are included in the rpm package and that
|
||||
# are going to be installed into target system where the rpm is installed.
|
||||
%files
|
||||
%{_sysconfdir}/systemd/system/*
|
||||
%{_bindir}/amd_system_info
|
||||
%{_bindir}/foxnet-biosupdate
|
||||
%{_bindir}/jupiter-biosupdate
|
||||
%{_bindir}/jupiter-check-support
|
||||
%{_bindir}/jupiter-controller-update
|
||||
%{_bindir}/steamos-polkit-helpers/*
|
||||
%{_bindir}/thumbstick_cal
|
||||
%{_bindir}/thumbstick_fine_cal
|
||||
%{_bindir}/trigger_cal
|
||||
%{_prefix}/lib/hwsupport/*
|
||||
%{_prefix}/lib/systemd/system/*
|
||||
%{_prefix}/lib/udev/rules.d/*
|
||||
%{_datadir}/alsa/ucm2/conf.d/acp5x/*
|
||||
%{_datadir}/icons/steam/*
|
||||
%{_datadir}/steamos/steamos.png
|
||||
%{_datadir}/jupiter_bios/*
|
||||
%{_datadir}/jupiter_bios_updater/*
|
||||
%{_datadir}/jupiter_controller_fw_updater/*
|
||||
%{_datadir}/plymouth/themes/steamos/*
|
||||
%{_datadir}/polkit-1/actions/org.valve.steamos.policy
|
||||
%{_datadir}/polkit-1/rules.d/org.valve.steamos.rules
|
||||
%{_datadir}/steamos/steamos-cursor-config
|
||||
%{_datadir}/steamos/steamos-cursor.png
|
||||
|
||||
# Finally, changes from the latest release of your application are generated from
|
||||
# your project's Git history. It will be empty until you make first annotated Git tag.
|
||||
%changelog
|
||||
{{{ git_dir_changelog }}}
|
148
system_files/deck/usr/lib/hwsupport/format-device.sh
Normal file
148
system_files/deck/usr/lib/hwsupport/format-device.sh
Normal file
@ -0,0 +1,148 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
exec &> >(tee | logger -t steamos-format-device)
|
||||
|
||||
RUN_VALIDATION=1
|
||||
EXTENDED_OPTIONS="nodiscard"
|
||||
# default owner for the new filesystem
|
||||
OWNER="1000:1000"
|
||||
|
||||
OPTS=$(getopt -l force,skip-validation,full,quick,owner:,device: -n format-device.sh -- "" "$@")
|
||||
|
||||
eval set -- "$OPTS"
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
--force) RUN_VALIDATION=0; shift ;;
|
||||
--skip-validation) RUN_VALIDATION=0; shift ;;
|
||||
--full) EXTENDED_OPTIONS="discard"; shift ;;
|
||||
--quick) EXTENDED_OPTIONS="nodiscard"; shift ;;
|
||||
--owner) OWNER="$2"; shift 2;;
|
||||
--device) STORAGE_DEVICE="$2"; shift 2 ;;
|
||||
--) shift; break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "$#" -gt 0 ]]; then
|
||||
echo "Unknown option $1"; exit 22
|
||||
fi
|
||||
|
||||
EXTENDED_OPTIONS="$EXTENDED_OPTIONS,root_owner=$OWNER"
|
||||
|
||||
# We only support SD/MMC and USB mass-storage devices
|
||||
case "$STORAGE_DEVICE" in
|
||||
"")
|
||||
echo "Usage: $(basename $0) [--force] [--skip-validation] [--full] [--quick] [--owner <uid>:<gid>] --device <device>"
|
||||
exit 19 #ENODEV
|
||||
;;
|
||||
/dev/mmcblk?)
|
||||
STORAGE_PARTITION="${STORAGE_DEVICE}p1"
|
||||
;;
|
||||
/dev/sd?)
|
||||
STORAGE_PARTITION="${STORAGE_DEVICE}1"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown or unsupported device: $STORAGE_DEVICE"
|
||||
exit 19 #ENODEV
|
||||
esac
|
||||
|
||||
if [[ ! -e "$STORAGE_DEVICE" ]]; then
|
||||
exit 19 #ENODEV
|
||||
fi
|
||||
|
||||
# Prevent accidental formatting of system drives
|
||||
if [[ $(lsblk -d -n -r -o hotplug "$STORAGE_DEVICE") != "1" ]]; then
|
||||
echo "$STORAGE_DEVICE is not a hotplug device"
|
||||
exit 19 #ENODEV
|
||||
fi
|
||||
|
||||
STORAGE_PARTBASE="${STORAGE_PARTITION#/dev/}"
|
||||
|
||||
systemctl stop steamos-automount@"$STORAGE_PARTBASE".service
|
||||
|
||||
# lock file prevents the mount service from re-mounting as it gets triggered by udev rules.
|
||||
#
|
||||
# NOTE: Uses a shared lock filename between this and the auto-mount script to ensure we're not double-triggering nor
|
||||
# automounting while formatting or vice-versa.
|
||||
MOUNT_LOCK="/var/run/jupiter-automount-${STORAGE_PARTBASE//\/_}.lock"
|
||||
MOUNT_LOCK_FD=9
|
||||
exec 9<>"$MOUNT_LOCK"
|
||||
|
||||
if ! flock -n "$MOUNT_LOCK_FD"; then
|
||||
echo "Failed to obtain lock $MOUNT_LOCK, failing"
|
||||
exit 5
|
||||
fi
|
||||
|
||||
# If any partitions on the device are mounted, unmount them before continuing
|
||||
# to prevent problems later
|
||||
for m in $(lsblk -n "$STORAGE_DEVICE" -o MOUNTPOINTS| awk NF | sort -u); do
|
||||
if ! umount "$m"; then
|
||||
echo "Failed to unmount filesystem: $m"
|
||||
exit 32 # EPIPE
|
||||
fi
|
||||
done
|
||||
|
||||
# Test the sdcard
|
||||
# Some fake cards advertise a larger size than their actual capacity,
|
||||
# which can result in data loss or other unexpected behaviour. It is
|
||||
# best to try to detect these issues as early as possible.
|
||||
if [[ "$RUN_VALIDATION" != "0" ]]; then
|
||||
echo "stage=testing"
|
||||
if ! f3probe --destructive "$STORAGE_DEVICE"; then
|
||||
# Fake sdcards tend to only behave correctly when formatted as exfat
|
||||
# The tricks they try to pull fall apart with any other filesystem and
|
||||
# it renders the card unusuable.
|
||||
#
|
||||
# Here we restore the card to exfat so that it can be used with other devices.
|
||||
# It won't be usable with the deck, and usage of the card will most likely
|
||||
# result in data loss. We return a special error code so we can surface
|
||||
# a specific error to the user.
|
||||
echo "stage=rescuing"
|
||||
echo "Bad sdcard - rescuing"
|
||||
for i in {1..3}; do # Give this a couple of tries since it fails sometimes
|
||||
echo "Create partition table: $i"
|
||||
dd if=/dev/zero of="$STORAGE_DEVICE" bs=512 count=1024 # see comment in similar statement below
|
||||
if ! parted --script "$STORAGE_DEVICE" mklabel msdos mkpart primary 0% 100% ; then
|
||||
echo "Failed to create partition table: $i"
|
||||
continue # try again
|
||||
fi
|
||||
|
||||
echo "Create exfat filesystem: $i"
|
||||
sync
|
||||
if ! mkfs.exfat "$STORAGE_PARTITION"; then
|
||||
echo "Failed to exfat filesystem: $i"
|
||||
continue # try again
|
||||
fi
|
||||
|
||||
echo "Successfully restored device"
|
||||
break
|
||||
done
|
||||
|
||||
# Return a specific error code so the UI can warn the user about this bad device
|
||||
exit 14 # EFAULT
|
||||
fi
|
||||
fi
|
||||
|
||||
# Clear out the garbage bits generated by f3probe from the partition table sectors
|
||||
# Otherwise parted may think we have existing partitions in a bogus state
|
||||
dd if=/dev/zero of="$STORAGE_DEVICE" bs=512 count=1024
|
||||
|
||||
# Format as EXT4 with casefolding for proton compatibility
|
||||
echo "stage=formatting"
|
||||
sync
|
||||
parted --script "$STORAGE_DEVICE" mklabel gpt mkpart primary 0% 100%
|
||||
sync
|
||||
mkfs.ext4 -m 0 -O casefold -E "$EXTENDED_OPTIONS" -F "$STORAGE_PARTITION"
|
||||
sync
|
||||
udevadm settle
|
||||
|
||||
# trigger the mount service
|
||||
flock -u "$MOUNT_LOCK_FD"
|
||||
if ! systemctl start steamos-automount@"$STORAGE_PARTBASE".service; then
|
||||
echo "Failed to start mount service"
|
||||
journalctl --no-pager --boot=0 -u steamos-automount@"$STORAGE_PARTBASE".service
|
||||
exit 5
|
||||
fi
|
||||
|
||||
exit 0
|
185
system_files/deck/usr/lib/hwsupport/steamos-automount.sh
Normal file
185
system_files/deck/usr/lib/hwsupport/steamos-automount.sh
Normal file
@ -0,0 +1,185 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Originally from https://serverfault.com/a/767079
|
||||
|
||||
# This script is called from our systemd unit file to mount or unmount
|
||||
# a USB drive.
|
||||
|
||||
usage()
|
||||
{
|
||||
echo "Usage: $0 {add|remove} device_name (e.g. sdb1)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ $# -ne 2 ]]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
ACTION=$1
|
||||
DEVBASE=$2
|
||||
DEVICE="/dev/${DEVBASE}"
|
||||
|
||||
# Shared between this and the auto-mount script to ensure we're not double-triggering nor automounting while formatting
|
||||
# or vice-versa.
|
||||
MOUNT_LOCK="/var/run/jupiter-automount-${DEVBASE//\/_}.lock"
|
||||
|
||||
# Obtain lock
|
||||
exec 9<>"$MOUNT_LOCK"
|
||||
if ! flock -n 9; then
|
||||
echo "$MOUNT_LOCK is active: ignoring action $ACTION"
|
||||
# Do not return a success exit code: it could end up putting the service in 'started' state without doing the mount
|
||||
# work (further start commands will be ignored after that)
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Wait N seconds for steam
|
||||
wait_steam()
|
||||
{
|
||||
local i=0
|
||||
local wait=$1
|
||||
echo "Waiting up to $wait seconds for steam to load"
|
||||
while ! pgrep -x steamwebhelper &>/dev/null && (( i++ < wait )); do
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
send_steam_url()
|
||||
{
|
||||
local command="$1"
|
||||
local arg="$2"
|
||||
local encoded=$(urlencode "$arg")
|
||||
if pgrep -x "steam" > /dev/null; then
|
||||
# TODO use -ifrunning and check return value - if there was a steam process and it returns -1, the message wasn't sent
|
||||
# need to retry until either steam process is gone or -ifrunning returns 0, or timeout i guess
|
||||
systemd-run -M 1000@ --user --collect --wait sh -c "./.steam/root/ubuntu12_32/steam steam://${command}/${encoded@Q}"
|
||||
echo "Sent URL to steam: steam://${command}/${arg} (steam://${command}/${encoded})"
|
||||
else
|
||||
echo "Could not send steam URL steam://${command}/${arg} (steam://${command}/${encoded}) -- steam not running"
|
||||
fi
|
||||
}
|
||||
|
||||
# From https://gist.github.com/HazCod/da9ec610c3d50ebff7dd5e7cac76de05
|
||||
urlencode()
|
||||
{
|
||||
[ -z "$1" ] || echo -n "$@" | hexdump -v -e '/1 "%02x"' | sed 's/\(..\)/%\1/g'
|
||||
}
|
||||
|
||||
do_mount()
|
||||
{
|
||||
# Get info for this drive: $ID_FS_LABEL, and $ID_FS_TYPE
|
||||
dev_json=$(lsblk -o PATH,LABEL,FSTYPE --json -- "$DEVICE" | jq '.blockdevices[0]')
|
||||
ID_FS_LABEL=$(jq -r '.label | select(type == "string")' <<< "$dev_json")
|
||||
ID_FS_TYPE=$(jq -r '.fstype | select(type == "string")' <<< "$dev_json")
|
||||
|
||||
# Global mount options
|
||||
OPTS="rw,noatime"
|
||||
|
||||
# File system type specific mount options
|
||||
#if [[ ${ID_FS_TYPE} == "vfat" ]]; then
|
||||
# OPTS+=",users,gid=100,umask=000,shortname=mixed,utf8=1,flush"
|
||||
#fi
|
||||
|
||||
# We need symlinks for Steam for now, so only automount ext4 as that'll Steam will format right now
|
||||
if [[ ${ID_FS_TYPE} != "ext4" ]]; then
|
||||
echo "Error mounting ${DEVICE}: wrong fstype: ${ID_FS_TYPE} - ${dev_json}"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Prior to talking to udisks, we need all udev hooks (we were started by one) to finish, so we know it has knowledge
|
||||
# of the drive. Our own rule starts us as a service with --no-block, so we can wait for rules to settle here
|
||||
# safely.
|
||||
if ! udevadm settle; then
|
||||
echo "Failed to wait for \`udevadm settle\`"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ask udisks to auto-mount. This needs a version of udisks that supports the 'as-user' option.
|
||||
ret=0
|
||||
reply=$(busctl call --allow-interactive-authorization=false --expect-reply=true --json=short \
|
||||
org.freedesktop.UDisks2 \
|
||||
/org/freedesktop/UDisks2/block_devices/"${DEVBASE}" \
|
||||
org.freedesktop.UDisks2.Filesystem \
|
||||
Mount 'a{sv}' 3 \
|
||||
as-user s deck \
|
||||
auth.no_user_interaction b true \
|
||||
options s "$OPTS") || ret=$?
|
||||
|
||||
if [[ $ret -ne 0 ]]; then
|
||||
echo "Error mounting ${DEVICE} (status = $ret)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Expected reply is of the format
|
||||
# {"type":"s","data":["/run/media/deck/home"]}
|
||||
mount_point=$(jq -r '.data[0] | select(type == "string")' <<< "$reply" || true)
|
||||
if [[ -z $mount_point ]]; then
|
||||
echo "Error when mounting ${DEVICE}: udisks returned success but could not parse reply:"
|
||||
echo "---"$'\n'"$reply"$'\n'"---"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create a symlink from /run/media to keep compatibility with apps
|
||||
# that use the older mount point (for SD cards only).
|
||||
case "${DEVBASE}" in
|
||||
mmcblk0p*)
|
||||
if [[ -z "${ID_FS_LABEL}" ]]; then
|
||||
old_mount_point="/run/media/${DEVBASE}"
|
||||
else
|
||||
old_mount_point="/run/media/${mount_point##*/}"
|
||||
fi
|
||||
if [[ ! -d "${old_mount_point}" ]]; then
|
||||
rm -f -- "${old_mount_point}"
|
||||
ln -s -- "${mount_point}" "${old_mount_point}"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "**** Mounted ${DEVICE} at ${mount_point} ****"
|
||||
|
||||
# If Steam is running, notify it
|
||||
send_steam_url "addlibraryfolder" "${mount_point}"
|
||||
}
|
||||
|
||||
do_unmount()
|
||||
{
|
||||
# If Steam is running, notify it
|
||||
local mount_point=$(findmnt -fno TARGET "${DEVICE}" || true)
|
||||
if [[ -n $mount_point ]]; then
|
||||
send_steam_url "removelibraryfolder" "${mount_point}"
|
||||
# Remove symlink to the mount point that we're unmounting
|
||||
find /run/media -maxdepth 1 -xdev -type l -lname "${mount_point}" -exec rm -- {} \;
|
||||
else
|
||||
# If we don't know the mount point then remove all broken symlinks
|
||||
find /run/media -maxdepth 1 -xdev -xtype l -exec rm -- {} \;
|
||||
fi
|
||||
}
|
||||
|
||||
do_retrigger()
|
||||
{
|
||||
local mount_point=$(findmnt -fno TARGET "${DEVICE}" || true)
|
||||
[[ -n $mount_point ]] || return 0
|
||||
|
||||
# In retrigger mode, we want to wait a bit for steam as the common pattern is starting in parallel with a retrigger
|
||||
wait_steam 10
|
||||
# This is a truly gnarly way to ensure steam is ready for commands.
|
||||
# TODO literally anything else
|
||||
sleep 6
|
||||
send_steam_url "addlibraryfolder" "${mount_point}"
|
||||
}
|
||||
|
||||
case "${ACTION}" in
|
||||
add)
|
||||
do_mount
|
||||
;;
|
||||
remove)
|
||||
do_unmount
|
||||
;;
|
||||
retrigger)
|
||||
do_retrigger
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
Loading…
x
Reference in New Issue
Block a user