Last active
May 31, 2025 15:32
-
-
Save jroakes/452696b67ba3d0f5bdc800a1b644cdeb to your computer and use it in GitHub Desktop.
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 | |
# -*- mode: sh; indent-tabs-mode: nil; sh-basic-offset: 2; -*- | |
# vim: et sts=2 sw=2 | |
# | |
# Steam OS recovery / installer – **SATA & USB drives only** | |
# | |
set -eu | |
die() { echo >&2 "!! $*"; exit 1; } | |
readvar(){ IFS= read -r -d '' "$1" || true; } | |
# ---------- DRIVE ---------- | |
DISK=/dev/sda | |
DISK_SUFFIX= | |
DOPARTVERIFY=1 | |
# --------------------------- | |
# Optional firmware bundles | |
VENDORED_BIOS_UPDATE=/home/deck/jupiter-bios | |
VENDORED_CONTROLLER_UPDATE=/home/deck/jupiter-controller-fw | |
# ---------- PARTITIONS ----- | |
PART_SIZE_ESP=256 # MiB | |
PART_SIZE_EFI=64 | |
PART_SIZE_ROOT=5120 | |
PART_SIZE_VAR=256 | |
PART_SIZE_HOME=100 | |
DISK_SIZE=$(( 2 + PART_SIZE_HOME + PART_SIZE_ESP \ | |
+ 2*(PART_SIZE_EFI + PART_SIZE_ROOT + PART_SIZE_VAR) )) | |
TARGET_SECTOR_SIZE=512 | |
readvar PARTITION_TABLE <<EOF | |
label: gpt | |
%%DISKPART%%1: name="esp", size=${PART_SIZE_ESP}MiB, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B | |
%%DISKPART%%2: name="efi-A", size=${PART_SIZE_EFI}MiB, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 | |
%%DISKPART%%3: name="efi-B", size=${PART_SIZE_EFI}MiB, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 | |
%%DISKPART%%4: name="rootfs-A", size=${PART_SIZE_ROOT}MiB,type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709 | |
%%DISKPART%%5: name="rootfs-B", size=${PART_SIZE_ROOT}MiB,type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709 | |
%%DISKPART%%6: name="var-A", size=${PART_SIZE_VAR}MiB, type=4D21B016-B534-45C2-A9FB-5C16E091FD2D | |
%%DISKPART%%7: name="var-B", size=${PART_SIZE_VAR}MiB, type=4D21B016-B534-45C2-A9FB-5C16E091FD2D | |
%%DISKPART%%8: name="home", size=${PART_SIZE_HOME}MiB,type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915 | |
EOF | |
FS_ESP=1; FS_EFI_A=2; FS_EFI_B=3; FS_ROOT_A=4; FS_ROOT_B=5; FS_VAR_A=6; FS_VAR_B=7; FS_HOME=8 | |
diskpart(){ echo "$DISK$DISK_SUFFIX$1"; } | |
# ---------- COLOUR LOG HELPERS (restored in full) ---------- | |
_sh_c_colors=0 | |
[[ -t 1 && ${TERM:-dumb} != dumb ]] && _sh_c_colors="$(tput colors 2>/dev/null || echo 0)" | |
sh_c(){ [[ $_sh_c_colors -le 0 ]] || { IFS=\; && echo -n $'\e['"$*m"; }; } | |
estat(){ echo >&2 "$(sh_c 32 1)::$(sh_c) $*"; } | |
emsg() { echo >&2 "$(sh_c 34 1)::$(sh_c) $*"; } | |
ewarn(){ echo >&2 "$(sh_c 33 1);;$(sh_c) $*"; } | |
eerr() { echo >&2 "$(sh_c 31 1)!!$(sh_c) $*"; } | |
showcmd_unquoted(){ echo >&2 "$(sh_c 30 1)+$(sh_c) $*"; } | |
showcmd(){ showcmd_unquoted "${@Q}"; } | |
cmd(){ showcmd "$@"; "$@"; } | |
# ----------------------------------------------------------- | |
fmt_ext4(){ cmd mkfs.ext4 -F -L "$1" "$2"; } | |
fmt_fat32(){ cmd mkfs.vfat -n"$1" "$2"; } | |
# ---------- PROMPT ---------- | |
prompt_step(){ zenity --title "$1" --question --ok-label "Proceed" --cancel-label "Cancel" --no-wrap --text "$2"; } | |
prompt_reboot(){ prompt_step "Finished" "$1\n\nProceed to reboot?" && systemctl reboot; } | |
# ---------------------------- | |
# ---------- GRUB ---------- | |
install_grub(){ | |
local ps="$1" | |
estat "Running grub-install on set $ps" | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$ps" -- \ | |
grub-install --target=x86_64-efi --efi-directory=/efi \ | |
--bootloader-id=SteamOS --removable --recheck "$DISK" | |
} | |
finalize_part(){ | |
estat "Finalising part set $1" | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- \ | |
mkdir -p /efi/SteamOS /esp/SteamOS/conf | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- \ | |
steamos-partsets /efi/SteamOS/partsets | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- \ | |
steamos-bootconf create --image "$1" --conf-dir /esp/SteamOS/conf \ | |
--efi-dir /efi --set title "$1" | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- grub-mkimage | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- update-grub | |
install_grub "$1" | |
} | |
# ---------------------------- | |
# (Remaining functions – imageroot, verifypart, repair_steps, etc. – are **unchanged from Valve’s | |
# original** except that all NVMe-sanitise code paths and the `sanitize` menu entry have been removed.) | |
# … <snip – identical to Valve’s upstream code> … | |
# ---------- MENU ---------- | |
case "${1:-help}" in | |
all) | |
prompt_step "Wipe & Install" "This will format /dev/sda and install Steam OS." | |
writePartitionTable=1; writeOS=1; writeHome=1 | |
repair_steps; prompt_reboot "Re-imaging complete." ;; | |
system) | |
prompt_step "Repair System" "Reinstall core OS files, keep /home and games." | |
writeOS=1; repair_steps; prompt_reboot "System repair complete." ;; | |
home) | |
prompt_step "Reset User Data" "Format /home and /var – all personal data will be lost." | |
writeHome=1; repair_steps; prompt_reboot "User partitions reformatted." ;; | |
chroot) chroot_primary ;; | |
*) help ;; | |
esac |
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 | |
# -*- mode: sh; indent-tabs-mode: nil; sh-basic-offset: 2; -*- | |
# vim: et sts=2 sw=2 | |
# | |
# A collection of functions to create, repair, or modify a SteamOS installation for non-NVMe drives. | |
# This makes a number of assumptions about the target device and will be | |
# destructive if you have modified the expected partition layout. | |
# | |
set -eu | |
die() { echo >&2 "!! $*"; exit 1; } | |
readvar() { IFS= read -r -d '' "$1" || true; } | |
DISK=/dev/sda | |
DISK_SUFFIX= | |
DOPARTVERIFY=1 | |
# If this exists, use the jupiter-biosupdate binary from this directory, and set JUPITER_BIOS_DIR to this directory when | |
# invoking it. Used for including a newer bios payload than the base image. | |
VENDORED_BIOS_UPDATE=/home/deck/jupiter-bios | |
# If this exists, use the jupiter-controller-update binary from this directory, and set | |
# JUPITER_CONTROLLER_UPDATE_FIRMWARE_DIR to this directory when invoking it. Used for including a newer controller | |
# payload than the base image. | |
VENDORED_CONTROLLER_UPDATE=/home/deck/jupiter-controller-fw | |
# Partition table, sfdisk format, %%DISKPART%% filled in | |
# | |
PART_SIZE_ESP="256" | |
PART_SIZE_EFI="64" | |
PART_SIZE_ROOT="5120" # This should match the size from the input disk build | |
PART_SIZE_VAR="256" | |
PART_SIZE_HOME="100" # For the stub .img file we're making this can be tiny, OS expands to fill physical disk on first | |
# boot. We make sure to specify the inode ratio explicitly when formatting. | |
# Total size + 1MiB padding at beginning/end for GPT structures. | |
DISK_SIZE=$(( 2 + PART_SIZE_HOME + PART_SIZE_ESP + 2 * ( PART_SIZE_EFI + PART_SIZE_ROOT + PART_SIZE_VAR ) )) | |
# Alignment: Using general sizes like MiB and no explicit start offset points causes sfdisk to align to MiB boundaries | |
# by default (e.g. first partition will start at 1MiB). See `man sfdisk`. | |
# Sector size: Most physical SSD/SATA/etc use logical 512 sectors*. GPT partition tables aren't portable between varying | |
# sector sizes, so this .img cannot be used directly on a 4k-logical-sector device (a quick search suggests | |
# this is most likely with certain VM/cloud/network disks) | |
# | |
# Since we use 1MiB alignment, it should be possible to fixup this partition table for other sector sizes | |
# without physically moving any partitions at imaging time: | |
# | |
# dd if=output.img of=/target/disk | |
# | |
# # sfdisk will default to 512 for a local file, dumping the table correctly, then translate it to the | |
# # target device's sector size upon re-writing: | |
# | |
# sfdisk -d < output.img | sfdisk /target/disk | |
# | |
# Alternatively, use `losetup --sector-size` to remount the image at a different size, and use the above | |
# steps to regenerate the table. If this comes up often in practice we could output a "partitions4096.gpt" | |
# style file alongside the disk image that could be `dd`'d on top for weird VM setups. | |
# | |
# *Note: logical sectors != physical sectors != optimal I/O alignment. Logical sectors being the unit the | |
# OS addresses the disk by, and what GPT tables use as their basic written-to-disk unit. Most everything | |
# is 512 or (rarely) 4096. | |
TARGET_SECTOR_SIZE=512 # Passed to `losetup` to emulate, affects the sector-offsets sfdisk ends up writing. | |
readvar PARTITION_TABLE <<END_PARTITION_TABLE | |
label: gpt | |
%%DISKPART%%1: name="esp", size= ${PART_SIZE_ESP}MiB, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B | |
%%DISKPART%%2: name="efi-A", size= ${PART_SIZE_EFI}MiB, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 | |
%%DISKPART%%3: name="efi-B", size= ${PART_SIZE_EFI}MiB, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 | |
%%DISKPART%%4: name="rootfs-A", size= ${PART_SIZE_ROOT}MiB, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709 | |
%%DISKPART%%5: name="rootfs-B", size= ${PART_SIZE_ROOT}MiB, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709 | |
%%DISKPART%%6: name="var-A", size= ${PART_SIZE_VAR}MiB, type=4D21B016-B534-45C2-A9FB-5C16E091FD2D | |
%%DISKPART%%7: name="var-B", size= ${PART_SIZE_VAR}MiB, type=4D21B016-B534-45C2-A9FB-5C16E091FD2D | |
%%DISKPART%%8: name="home", size= ${PART_SIZE_HOME}MiB, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915 | |
END_PARTITION_TABLE | |
# Partition numbers on ideal target device, by index | |
FS_ESP=1 | |
FS_EFI_A=2 | |
FS_EFI_B=3 | |
FS_ROOT_A=4 | |
FS_ROOT_B=5 | |
FS_VAR_A=6 | |
FS_VAR_B=7 | |
FS_HOME=8 | |
diskpart() { echo "$DISK$DISK_SUFFIX$1"; } | |
## | |
## Util colors and such | |
## | |
err() { | |
echo >&2 | |
eerr "Imaging error occured, see above and restart process." | |
sleep infinity | |
} | |
trap err ERR | |
_sh_c_colors=0 | |
[[ -n $TERM && -t 1 && ${TERM,,} != dumb ]] && _sh_c_colors="$(tput colors 2>/dev/null || echo 0)" | |
sh_c() { [[ $_sh_c_colors -le 0 ]] || ( IFS=\; && echo -n $'\e['"${*:-0}m"; ); } | |
sh_quote() { echo "${@@Q}"; } | |
estat() { echo >&2 "$(sh_c 32 1)::$(sh_c) $*"; } | |
emsg() { echo >&2 "$(sh_c 34 1)::$(sh_c) $*"; } | |
ewarn() { echo >&2 "$(sh_c 33 1);;$(sh_c) $*"; } | |
einfo() { echo >&2 "$(sh_c 30 1)::$(sh_c) $*"; } | |
eerr() { echo >&2 "$(sh_c 31 1)!!$(sh_c) $*"; } | |
die() { local msg="$*"; [[ -n $msg ]] || msg="script terminated"; eerr "$msg"; exit 1; } | |
showcmd() { showcmd_unquoted "${@@Q}"; } | |
showcmd_unquoted() { echo >&2 "$(sh_c 30 1)+$(sh_c) $*"; } | |
cmd() { showcmd "$@"; "$@"; } | |
# Helper to format | |
fmt_ext4() { [[ $# -eq 2 && -n $1 && -n $2 ]] || die; cmd sudo mkfs.ext4 -F -L "$1" "$2"; } | |
fmt_fat32() { [[ $# -eq 2 && -n $1 && -n $2 ]] || die; cmd sudo mkfs.vfat -n"$1" "$2"; } | |
## | |
## Prompt mechanics - currently using Zenity | |
## | |
# Give the user a choice between Proceed, or Cancel (which exits this script) | |
# $1 Title | |
# $2 Text | |
# | |
prompt_step() | |
{ | |
title="$1" | |
msg="$2" | |
unconditional="${3-}" | |
if [[ ! ${unconditional-} && ${NOPROMPT:-} ]]; then | |
echo -e "$msg" | |
return 0 | |
fi | |
zenity --title "$title" --question --ok-label "Proceed" --cancel-label "Cancel" --no-wrap --text "$msg" | |
[[ $? = 0 ]] || exit 1 | |
} | |
prompt_reboot() | |
{ | |
local msg=$1 | |
local mode="reboot" | |
[[ ${POWEROFF:-} ]] && mode="shutdown" | |
prompt_step "Action Successful" "${msg}\n\nChoose Proceed to $mode now, or Cancel to stay in the repair image." "${REBOOTPROMPT:-}" | |
[[ $? = 0 ]] || exit 1 | |
if [[ ${POWEROFF:-} ]]; then | |
cmd systemctl poweroff | |
else | |
cmd systemctl reboot | |
fi | |
} | |
## | |
## Repair functions | |
## | |
# verify partition on target disk - at least make sure the type and partlabel match what we expect. | |
# $1 device | |
# $2 expected type | |
# $3 expected partlabel | |
# | |
verifypart() | |
{ | |
[[ $DOPARTVERIFY = 1 ]] || return 0 | |
TYPE="$(blkid -o value -s TYPE "$1" )" | |
PARTLABEL="$(blkid -o value -s PARTLABEL "$1" )" | |
if [[ ! $TYPE = "$2" ]]; then | |
eerr "Device $1 is type $TYPE but expected $2 - cannot proceed. You may try full recovery." | |
sleep infinity ; exit 1 | |
fi | |
if [[ ! $PARTLABEL = $3 ]] ; then | |
eerr "Device $1 has label $PARTLABEL but expected $3 - cannot proceed. You may try full recovery." | |
sleep infinity ; exit 2 | |
fi | |
} | |
# Replace the device rootfs (btrfs version). Source must be frozen before calling. | |
# $1 source device | |
# $2 target device | |
# | |
imageroot() | |
{ | |
local srcroot="$1" | |
local newroot="$2" | |
# copy then randomize target UUID - careful here! Duplicating btrfs ids is a problem | |
cmd dd if="$srcroot" of="$newroot" bs=128M status=progress oflag=sync | |
cmd btrfstune -f -u "$newroot" | |
cmd btrfs check "$newroot" | |
} | |
# Set up boot configuration in the target partition set | |
# $1 partset name | |
finalize_part() | |
{ | |
estat "Finalizing install part $1" | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- mkdir -p /efi/SteamOS | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- mkdir -p /esp/SteamOS/conf | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- steamos-partsets /efi/SteamOS/partsets | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- steamos-bootconf create --image "$1" --conf-dir /esp/SteamOS/conf --efi-dir /efi --set title "$1" | |
# Ensure proper GRUB installation for SATA drives | |
estat "Installing GRUB for partition set $1" | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=SteamOS --removable | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- grub-mkimage | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- update-grub | |
# Additional GRUB configuration for SATA compatibility | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$1" -- grub-install --target=i386-pc "$DISK" | |
} | |
## | |
## Main | |
## | |
onexit=() | |
exithandler() { | |
for func in "${onexit[@]}"; do | |
"$func" | |
done | |
} | |
trap exithandler EXIT | |
# Check existence of target disk | |
if [[ ! -e "$DISK" ]]; then | |
eerr "$DISK does not exist -- no SATA drive detected?" | |
sleep infinity | |
exit 1 | |
fi | |
# Simple disk wipe for new drives (no secure wipe needed) | |
simple_wipe() | |
{ | |
estat "Performing simple disk wipe for new drive" | |
echo "Wiping partition table and first sectors of $DISK" | |
cmd wipefs -a "$DISK" | |
cmd dd if=/dev/zero of="$DISK" bs=1M count=100 status=progress | |
cmd sync | |
echo "Simple wipe complete." | |
} | |
# Reinstall a fresh SteamOS copy. | |
# | |
repair_steps() | |
{ | |
if [[ $writePartitionTable = 1 ]]; then | |
estat "Write known partition table" | |
echo "$PARTITION_TABLE" | sed "s|%%DISKPART%%|$DISK|g" | sfdisk "$DISK" | |
elif [[ $writeOS = 1 || $writeHome = 1 ]]; then | |
# verify some partition settings to make sure we are ok to proceed with partial repairs | |
# in the case we just wrote the partition table, we know we are good and the partitions | |
# are unlabelled anyway | |
verifypart "$(diskpart $FS_ESP)" vfat esp | |
verifypart "$(diskpart $FS_EFI_A)" vfat efi-A | |
verifypart "$(diskpart $FS_EFI_B)" vfat efi-B | |
verifypart "$(diskpart $FS_VAR_A)" ext4 var-A | |
verifypart "$(diskpart $FS_VAR_B)" ext4 var-B | |
verifypart "$(diskpart $FS_HOME)" ext4 home | |
fi | |
# clear the var partition (user data), but also if we are reinstalling the OS | |
# a fresh system partition has problems with overlay otherwise | |
if [[ $writeOS = 1 || $writeHome = 1 ]]; then | |
estat "Creating var partitions" | |
fmt_ext4 var "$(diskpart $FS_VAR_A)" | |
fmt_ext4 var "$(diskpart $FS_VAR_B)" | |
fi | |
# Create boot partitions | |
if [[ $writeOS = 1 ]]; then | |
# Set up ESP/EFI boot partitions | |
estat "Creating boot partitions" | |
fmt_fat32 esp "$(diskpart $FS_ESP)" | |
fmt_fat32 efi "$(diskpart $FS_EFI_A)" | |
fmt_fat32 efi "$(diskpart $FS_EFI_B)" | |
fi | |
if [[ $writeHome = 1 ]]; then | |
estat "Creating home partition..." | |
cmd sudo mkfs.ext4 -F -O casefold -T huge -L home "$(diskpart $FS_HOME)" | |
estat "Remove the reserved blocks on the home partition..." | |
cmd tune2fs -m 0 "$(diskpart $FS_HOME)" | |
fi | |
# Stage a BIOS update for next reboot if updating OS. OOBE images like this one don't auto-update the bios on boot. | |
if [[ $writeOS = 1 ]]; then | |
estat "Staging a BIOS update for next boot if necessary" | |
# If we included a VENDORED_BIOS_UPDATE directory above, use the newer payload there and point JUPITER_BIOS_DIR to | |
# it. Directory should contain both a newer tool and newer firmware. | |
biostool=/usr/bin/jupiter-biosupdate | |
if [[ -n $VENDORED_BIOS_UPDATE && -d $VENDORED_BIOS_UPDATE ]]; then | |
biostool="$VENDORED_BIOS_UPDATE"/jupiter-biosupdate | |
export JUPITER_BIOS_DIR="$VENDORED_BIOS_UPDATE" | |
fi | |
# This is cursed, but, we want to stage the capsule in the onboard drive, which we are booting next | |
fix_esp() { | |
if [[ -n ${mounted_esp:-} ]]; then | |
cmd umount -l /esp || true | |
cmd umount -l /boot/efi || true | |
mounted_esp= | |
fi | |
} | |
onexit+=(fix_esp) | |
einfo "Mounting new ESP/EFI on /esp /boot/efi for BIOS staging" | |
cmd mount "$(diskpart $FS_ESP)" /esp | |
cmd mount "$(diskpart $FS_EFI_A)" /boot/efi | |
mounted_esp=1 | |
if [[ ${FORCEBIOS:-} ]]; then | |
"$biostool" --force || "$biostool" | |
else | |
"$biostool" | |
fi | |
fix_esp | |
fi | |
# Perform a controller update if updating OS. OOBE images like this one don't auto-update controllers on boot. | |
if [[ $writeOS = 1 ]]; then | |
estat "Updating controller firmware if necessary" | |
controller_tool="/usr/bin/jupiter-controller-update" | |
# If we included a VENDORED_CONTROLLER_UPDATE directory above, use the newer payload and point | |
# JUPITER_CONTROLLER_UPDATE_FIRMWARE_DIR to it. Directory should contain both a newer tool and newer firmware. | |
if [[ -n $VENDORED_CONTROLLER_UPDATE && -d $VENDORED_CONTROLLER_UPDATE ]]; then | |
controller_tool="$VENDORED_CONTROLLER_UPDATE"/jupiter-controller-update | |
export JUPITER_CONTROLLER_UPDATE_FIRMWARE_DIR="$VENDORED_CONTROLLER_UPDATE" | |
fi | |
JUPITER_CONTROLLER_UPDATE_IN_OOBE=1 "$controller_tool" | |
fi | |
if [[ $writeOS = 1 ]]; then | |
# Find rootfs | |
rootdevice="$(findmnt -n -o source / )" | |
if [[ -z $rootdevice || ! -e $rootdevice ]]; then | |
eerr "Could not find USB installer root -- usb hub issue?" | |
sleep infinity | |
exit 1 | |
fi | |
# Freeze our rootfs | |
estat "Freezing rootfs" | |
unfreeze() { fsfreeze -u / || true; } | |
onexit+=(unfreeze) | |
cmd fsfreeze -f / | |
estat "Imaging OS partition A" | |
imageroot "$rootdevice" "$(diskpart $FS_ROOT_A)" | |
estat "Imaging OS partition B" | |
imageroot "$rootdevice" "$(diskpart $FS_ROOT_B)" | |
estat "Finalizing boot configurations" | |
finalize_part A | |
finalize_part B | |
estat "Finalizing EFI system partition" | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset A -- steamcl-install --flags restricted --force-extra-removable | |
# Ensure bootloader is properly installed for SATA drives | |
estat "Final GRUB installation verification" | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset A -- grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=SteamOS --removable --force | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset A -- update-grub | |
fi | |
} | |
# drop into the primary OS partset on the device | |
# | |
chroot_primary() | |
{ | |
partset=$( steamos-chroot --no-overlay --disk "$DISK" --partset "A" -- steamos-bootconf selected-image ) | |
estat "Dropping into a chroot on the $partset partition set." | |
estat "You can make any needed changes here, and exit when done." | |
# FIXME etc overlay dir might not exist on a fresh install and this will fail | |
cmd steamos-chroot --disk "$DISK" --partset "$partset" | |
} | |
# print quick list of targets | |
# | |
help() | |
{ | |
readvar HELPMSG << EOD | |
This tool can be used to reinstall or repair your SteamOS installation on SATA/non-NVMe drives | |
Possible targets: | |
all : permanently destroy all data on the device, and (re)install SteamOS. | |
system : repair/reinstall SteamOS on the device's system partitions, preserving user data partitions. | |
home : reformat the devices /home and /var partitions, removing games and user data from the device. | |
chroot : chroot into to the primary SteamOS partition set. | |
wipe : perform a simple disk wipe operation for new drives. | |
EOD | |
emsg "$HELPMSG" | |
if [[ "$EUID" -ne 0 ]]; then | |
eerr "Please run as root." | |
exit 1 | |
fi | |
} | |
[[ "$EUID" -ne 0 ]] && help | |
writePartitionTable=0 | |
writeOS=0 | |
writeHome=0 | |
case "${1-help}" in | |
all) | |
prompt_step "Wipe Device & Install SteamOS" "This action will wipe and (re)install SteamOS on this device.\nThis will permanently destroy all data on your device.\n\nThis cannot be undone.\n\nChoose Proceed only if you wish to wipe and reinstall this device." | |
writePartitionTable=1 | |
writeOS=1 | |
writeHome=1 | |
simple_wipe | |
repair_steps | |
prompt_reboot "Reimaging complete." | |
;; | |
system) | |
prompt_step "Repair SteamOS" "This action will repair the SteamOS installation on the device, while attempting to preserve your games and personal content.\nSystem customizations may be lost.\n\nChoose Proceed to reinstall SteamOS on your device." | |
writeOS=1 | |
repair_steps | |
prompt_reboot "SteamOS reinstall complete." | |
;; | |
home) | |
prompt_step "Delete local user data" "This action will reformat the home partitions on your device.\nThis will destroy downloaded games and all personal content, including system configuration.\n\nThis action cannot be undone.\n\nChoose Proceed to reformat all user home partitions." | |
writeHome=1 | |
repair_steps | |
prompt_reboot "User partitions have been reformatted." | |
;; | |
chroot) | |
chroot_primary | |
;; | |
wipe) | |
prompt_step "Simple disk wipe" "This action will perform a simple wipe of the partition table and first sectors of the drive.\n\nThis is suitable for new drives and much faster than secure wiping.\n\nThis action cannot be undone.\n\nChoose Proceed only if you want to wipe the current device." | |
simple_wipe | |
;; | |
*) | |
help | |
;; | |
esac |
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 | |
# -*- mode: sh; indent-tabs-mode: nil; sh-basic-offset: 2; -*- | |
# vim: et sts=2 sw=2 | |
# | |
# A collection of functions to create, repair, or modify a SteamOS installation. | |
# This makes a number of assumptions about the target device and will be | |
# destructive if you have modified the expected partition layout. | |
# | |
set -eu | |
die() { echo >&2 "!! $*"; exit 1; } | |
readvar() { IFS= read -r -d '' "$1" || true; } | |
DISK=/dev/sda | |
DISK_SUFFIX= # Kept empty for non-NVMe drives like /dev/sda | |
DOPARTVERIFY=1 | |
# If this exists, use the jupiter-biosupdate binary from this directory, and set JUPITER_BIOS_DIR to this directory when | |
# invoking it. Used for including a newer bios payload than the base image. | |
VENDORED_BIOS_UPDATE=/home/deck/jupiter-bios | |
# If this exists, use the jupiter-controller-update binary from this directory, and set | |
# JUPITER_CONTROLLER_UPDATE_FIRMWARE_DIR to this directory when invoking it. Used for including a newer controller | |
# payload than the base image. | |
VENDORED_CONTROLLER_UPDATE=/home/deck/jupiter-controller-fw | |
# Partition table, sfdisk format | |
# | |
PART_SIZE_ESP="256" | |
PART_SIZE_EFI="64" | |
PART_SIZE_ROOT="5120" # This should match the size from the input disk build | |
PART_SIZE_VAR="256" | |
PART_SIZE_HOME="100" # For the stub .img file we're making this can be tiny, OS expands to fill physical disk on first | |
# boot. We make sure to specify the inode ratio explicitly when formatting. | |
# Total size + 1MiB padding at beginning/end for GPT structures (informational for image creation). | |
DISK_SIZE=$(( 2 + PART_SIZE_HOME + PART_SIZE_ESP + 2 * ( PART_SIZE_EFI + PART_SIZE_ROOT + PART_SIZE_VAR ) )) | |
# Alignment: Using general sizes like MiB and no explicit start offset points causes sfdisk to align to MiB boundaries | |
# by default (e.g. first partition will start at 1MiB). See `man sfdisk`. | |
# Sector size comments from original script retained for context, TARGET_SECTOR_SIZE is not actively used by this script for partitioning physical disk. | |
TARGET_SECTOR_SIZE=512 | |
readvar PARTITION_TABLE <<END_PARTITION_TABLE | |
label: gpt | |
1: name="esp", size= ${PART_SIZE_ESP}MiB, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B | |
2: name="efi-A", size= ${PART_SIZE_EFI}MiB, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 | |
3: name="efi-B", size= ${PART_SIZE_EFI}MiB, type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 | |
4: name="rootfs-A", size= ${PART_SIZE_ROOT}MiB, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709 | |
5: name="rootfs-B", size= ${PART_SIZE_ROOT}MiB, type=4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709 | |
6: name="var-A", size= ${PART_SIZE_VAR}MiB, type=4D21B016-B534-45C2-A9FB-5C16E091FD2D | |
7: name="var-B", size= ${PART_SIZE_VAR}MiB, type=4D21B016-B534-45C2-A9FB-5C16E091FD2D | |
8: name="home", size= ${PART_SIZE_HOME}MiB, type=933AC7E1-2EB4-4F13-B844-0E14E2AEF915 | |
END_PARTITION_TABLE | |
# Partition numbers on ideal target device, by index | |
FS_ESP=1 | |
FS_EFI_A=2 | |
FS_EFI_B=3 | |
FS_ROOT_A=4 | |
FS_ROOT_B=5 | |
FS_VAR_A=6 | |
FS_VAR_B=7 | |
FS_HOME=8 | |
diskpart() { echo "$DISK$DISK_SUFFIX$1"; } # For DISK=/dev/sda, DISK_SUFFIX="", this becomes /dev/sda1, /dev/sda2 etc. | |
## | |
## Util colors and such | |
## | |
err() { | |
echo >&2 | |
eerr "Imaging error occured, see above and restart process." | |
sleep infinity | |
} | |
trap err ERR | |
_sh_c_colors=0 | |
[[ -n $TERM && -t 1 && ${TERM,,} != dumb ]] && _sh_c_colors="$(tput colors 2>/dev/null || echo 0)" | |
sh_c() { [[ $_sh_c_colors -le 0 ]] || ( IFS=\; && echo -n $'\e['"${*:-0}m"; ); } | |
sh_quote() { echo "${@@Q}"; } | |
estat() { echo >&2 "$(sh_c 32 1)::$(sh_c) $*"; } | |
emsg() { echo >&2 "$(sh_c 34 1)::$(sh_c) $*"; } | |
ewarn() { echo >&2 "$(sh_c 33 1);;$(sh_c) $*"; } | |
einfo() { echo >&2 "$(sh_c 30 1)::$(sh_c) $*"; } | |
eerr() { echo >&2 "$(sh_c 31 1)!!$(sh_c) $*"; } | |
# die() is defined at the top | |
showcmd() { showcmd_unquoted "${@@Q}"; } | |
showcmd_unquoted() { echo >&2 "$(sh_c 30 1)+$(sh_c) $*"; } | |
cmd() { showcmd "$@"; "$@"; } | |
# Helper to format | |
fmt_ext4() { [[ $# -eq 2 && -n $1 && -n $2 ]] || die "fmt_ext4: invalid arguments"; cmd sudo mkfs.ext4 -F -L "$1" "$2"; } | |
fmt_fat32() { [[ $# -eq 2 && -n $1 && -n $2 ]] || die "fmt_fat32: invalid arguments"; cmd sudo mkfs.vfat -n"$1" "$2"; } | |
## | |
## Prompt mechanics - currently using Zenity | |
## | |
# Give the user a choice between Proceed, or Cancel (which exits this script) | |
# $1 Title | |
# $2 Text | |
# | |
prompt_step() | |
{ | |
title="$1" | |
msg="$2" | |
unconditional="${3-}" | |
if [[ ! ${unconditional-} && ${NOPROMPT:-} ]]; then | |
echo -e "$msg" | |
return 0 | |
fi | |
zenity --title "$title" --question --ok-label "Proceed" --cancel-label "Cancel" --no-wrap --text "$msg" | |
# $? is 0 for OK, 1 for Cancel. | |
# Explicitly check and exit. | |
if [[ $? -ne 0 ]]; then | |
ewarn "User cancelled operation." | |
exit 1 | |
fi | |
} | |
prompt_reboot() | |
{ | |
local msg=$1 | |
local mode="reboot" | |
[[ ${POWEROFF:-} ]] && mode="shutdown" | |
prompt_step "Action Successful" "${msg}\n\nChoose Proceed to $mode now, or Cancel to stay in the repair image." "${REBOOTPROMPT:-}" | |
# If prompt_step is cancelled, script will exit due to the check within prompt_step. | |
if [[ ${POWEROFF:-} ]]; then | |
cmd systemctl poweroff | |
else | |
cmd systemctl reboot | |
fi | |
} | |
## | |
## Repair functions | |
## | |
# verify partition on target disk - at least make sure the type and partlabel match what we expect. | |
# $1 device | |
# $2 expected type | |
# $3 expected partlabel | |
# | |
verifypart() | |
{ | |
[[ $DOPARTVERIFY = 1 ]] || return 0 | |
local device="$1" | |
local expected_type="$2" | |
local expected_partlabel="$3" | |
local TYPE PARTLABEL | |
TYPE="$(blkid -o value -s TYPE "$device" || true)" # ensure it doesn't die if blkid fails temporarily | |
PARTLABEL="$(blkid -o value -s PARTLABEL "$device" || true)" | |
if [[ "$TYPE" != "$expected_type" ]]; then | |
eerr "Device $device is type '$TYPE' but expected '$expected_type' - cannot proceed. You may try full recovery." | |
sleep infinity ; exit 1 | |
fi | |
if [[ "$PARTLABEL" != "$expected_partlabel" ]] ; then | |
eerr "Device $device has label '$PARTLABEL' but expected '$expected_partlabel' - cannot proceed. You may try full recovery." | |
sleep infinity ; exit 2 | |
fi | |
} | |
# Replace the device rootfs (btrfs version). Source must be frozen before calling. | |
# $1 source device | |
# $2 target device | |
# | |
imageroot() | |
{ | |
local srcroot="$1" | |
local newroot="$2" | |
# copy then randomize target UUID - careful here! Duplicating btrfs ids is a problem | |
cmd dd if="$srcroot" of="$newroot" bs=128M status=progress oflag=sync | |
cmd btrfstune -f -u "$newroot" | |
cmd btrfs check "$newroot" | |
} | |
# Set up boot configuration in the target partition set | |
# $1 partset name | |
finalize_part() | |
{ | |
local partset_name="$1" | |
estat "Finalizing install part $partset_name" | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$partset_name" -- mkdir -p /efi/SteamOS # Ensure parent dir exists | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$partset_name" -- mkdir -p /esp/SteamOS/conf | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$partset_name" -- steamos-partsets /efi/SteamOS/partsets | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$partset_name" -- steamos-bootconf create --image "$partset_name" --conf-dir /esp/SteamOS/conf --efi-dir /efi --set title "SteamOS $partset_name" | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$partset_name" -- grub-mkimage | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset "$partset_name" -- update-grub | |
} | |
## | |
## Main | |
## | |
onexit=() | |
exithandler() { | |
for func in "${onexit[@]}"; do | |
# Try to execute the function, suppress its errors, but log our own if it failed. | |
if ! "$func" 2>/dev/null; then | |
einfo "Exit handler function '$func' encountered an error or was already handled." | |
fi | |
done | |
} | |
trap exithandler EXIT | |
# Check existence of target disk | |
if [[ ! -b "$DISK" ]]; then # Check if it's a block device | |
eerr "$DISK does not exist or is not a block device -- no drive detected at $DISK?" | |
sleep infinity | |
exit 1 | |
fi | |
# Reinstall a fresh SteamOS copy. | |
# | |
repair_steps() | |
{ | |
if [[ $writePartitionTable = 1 ]]; then | |
estat "Writing known partition table to $DISK" | |
# sfdisk expects the "label: gpt" within the input stream | |
echo "$PARTITION_TABLE" | cmd sfdisk "$DISK" | |
elif [[ $writeOS = 1 || $writeHome = 1 ]]; then | |
# Verify some partition settings to make sure we are ok to proceed with partial repairs. | |
# PARTLABEL is set by sfdisk from `name=...` in the partition table. | |
# TYPE is set by mkfs. These will only be correct if partitions were previously formatted. | |
# If this is a repair, these checks are useful. If it's a fresh format after `writePartitionTable=1`, | |
# then these will likely fail for TYPE until formatted below, this is a slight logic flaw in original verify timing. | |
# For now, keeping as is, as full 'all' flow reformats anyway. | |
einfo "Verifying existing partition layout (labels expected from sfdisk, types from previous format if any)..." | |
verifypart "$(diskpart $FS_ESP)" vfat esp | |
verifypart "$(diskpart $FS_EFI_A)" vfat efi-A | |
verifypart "$(diskpart $FS_EFI_B)" vfat efi-B | |
# For rootfs, type is btrfs, LABEL is set by mkfs/btrfstune, not from sfdisk 'name'. 'name' becomes PARTLABEL. | |
# verifypart "$(diskpart $FS_ROOT_A)" btrfs rootfs-A # This would fail if not yet formatted as btrfs | |
verifypart "$(diskpart $FS_VAR_A)" ext4 var-A | |
verifypart "$(diskpart $FS_VAR_B)" ext4 var-B | |
verifypart "$(diskpart $FS_HOME)" ext4 home | |
fi | |
# clear the var partition (user data), but also if we are reinstalling the OS | |
# a fresh system partition has problems with overlay otherwise | |
if [[ $writeOS = 1 || $writeHome = 1 ]]; then | |
estat "Formatting var partitions" | |
fmt_ext4 var-A "$(diskpart $FS_VAR_A)" # Label 'var-A' | |
fmt_ext4 var-B "$(diskpart $FS_VAR_B)" # Label 'var-B' | |
fi | |
# Create boot partitions | |
if [[ $writeOS = 1 ]]; then | |
estat "Formatting boot partitions" | |
fmt_fat32 ESP "$(diskpart $FS_ESP)" # Label 'ESP' for the main System Partition | |
fmt_fat32 EFI-A "$(diskpart $FS_EFI_A)" # Label 'EFI-A' for slot A's EFI files | |
fmt_fat32 EFI-B "$(diskpart $FS_EFI_B)" # Label 'EFI-B' for slot B's EFI files | |
fi | |
if [[ $writeHome = 1 ]]; then | |
estat "Formatting home partition..." | |
cmd sudo mkfs.ext4 -F -O casefold,extent -T huge -L home "$(diskpart $FS_HOME)" | |
estat "Removing reserved blocks on the home partition..." | |
cmd tune2fs -m 0 "$(diskpart $FS_HOME)" | |
fi | |
# Stage a BIOS update for next reboot if updating OS. | |
if [[ $writeOS = 1 ]]; then | |
estat "Staging a BIOS update for next boot if necessary" | |
biostool="/usr/bin/jupiter-biosupdate" | |
if [[ -n "${VENDORED_BIOS_UPDATE-}" && -d "$VENDORED_BIOS_UPDATE" && -x "$VENDORED_BIOS_UPDATE/jupiter-biosupdate" ]]; then | |
biostool="$VENDORED_BIOS_UPDATE"/jupiter-biosupdate | |
export JUPITER_BIOS_DIR="$VENDORED_BIOS_UPDATE" | |
einfo "Using vendored BIOS update tool: $biostool" | |
fi | |
# Staging the capsule on the ESP for the system we are booting next. | |
mounted_esp_for_bios_update="" | |
_fix_esp_bios_stage() { # Renamed to avoid conflict if onexit had identical name | |
if [[ -n "$mounted_esp_for_bios_update" ]]; then | |
ewarn "Cleaning up BIOS staging mounts: /esp, /boot/efi" | |
cmd umount -l /esp || einfo "Failed to unmount /esp during BIOS stage cleanup." | |
cmd umount -l /boot/efi || einfo "Failed to unmount /boot/efi during BIOS stage cleanup." | |
mounted_esp_for_bios_update="" | |
fi | |
} | |
onexit+=(_fix_esp_bios_stage) | |
cmd mkdir -p /esp /boot/efi | |
einfo "Mounting ESP on /esp and EFI-A on /boot/efi for BIOS staging" | |
cmd mount "$(diskpart $FS_ESP)" /esp | |
cmd mount "$(diskpart $FS_EFI_A)" /boot/efi # Uses EFI-A for staging BIOS update | |
mounted_esp_for_bios_update=1 | |
if [[ -x "$biostool" ]]; then | |
if [[ -n "${FORCEBIOS-}" ]]; then # Check if FORCEBIOS is set and non-empty | |
einfo "Attempting forced BIOS update..." | |
"$biostool" --force || "$biostool" # Try with force, then without if that fails | |
else | |
einfo "Attempting standard BIOS update..." | |
"$biostool" | |
fi | |
else | |
ewarn "BIOS update tool $biostool not found or not executable. Skipping BIOS update." | |
fi | |
_fix_esp_bios_stage # Call cleanup immediately | |
fi | |
# Perform a controller update if updating OS. | |
if [[ $writeOS = 1 ]]; then | |
estat "Updating controller firmware if necessary" | |
controller_tool="/usr/bin/jupiter-controller-update" | |
if [[ -n "${VENDORED_CONTROLLER_UPDATE-}" && -d "$VENDORED_CONTROLLER_UPDATE" && -x "$VENDORED_CONTROLLER_UPDATE/jupiter-controller-update" ]]; then | |
controller_tool="$VENDORED_CONTROLLER_UPDATE"/jupiter-controller-update | |
export JUPITER_CONTROLLER_UPDATE_FIRMWARE_DIR="$VENDORED_CONTROLLER_UPDATE" | |
einfo "Using vendored controller update tool: $controller_tool" | |
fi | |
if [[ -x "$controller_tool" ]]; then | |
JUPITER_CONTROLLER_UPDATE_IN_OOBE=1 "$controller_tool" | |
else | |
ewarn "Controller update tool $controller_tool not found or not executable. Skipping controller update." | |
fi | |
fi | |
if [[ $writeOS = 1 ]]; then | |
# Find rootfs of the installer | |
rootdevice="$(findmnt -n -o SOURCE / )" | |
if [[ -z "$rootdevice" || ! -b "$rootdevice" ]]; then | |
eerr "Could not find USB installer root block device -- usb hub issue? (Found: '$rootdevice')" | |
sleep infinity | |
exit 1 | |
fi | |
# Freeze our rootfs (the installer's root) | |
estat "Freezing installer rootfs $rootdevice (if supported)" | |
root_fstype=$(findmnt -n -o FSTYPE "$rootdevice" || echo "unknown") | |
needs_unfreeze=0 | |
_unfreeze_installer_root() { # Renamed to avoid conflict | |
if [[ $needs_unfreeze -eq 1 ]]; then | |
einfo "Unfreezing installer rootfs /" | |
fsfreeze -u / | |
needs_unfreeze=0 | |
fi | |
} | |
onexit+=(_unfreeze_installer_root) | |
if command -v fsfreeze >/dev/null && [[ "$root_fstype" == "btrfs" || "$root_fstype" == "ext4" || "$root_fstype" == "xfs" || "$root_fstype" == "f2fs" ]]; then | |
cmd fsfreeze -f / | |
needs_unfreeze=1 | |
else | |
ewarn "fsfreeze command not found or installer filesystem '$root_fstype' not typically frozen. Skipping freeze of installer root." | |
fi | |
estat "Imaging OS partition A from $rootdevice to $(diskpart $FS_ROOT_A)" | |
imageroot "$rootdevice" "$(diskpart $FS_ROOT_A)" | |
estat "Imaging OS partition B from $rootdevice to $(diskpart $FS_ROOT_B)" | |
imageroot "$rootdevice" "$(diskpart $FS_ROOT_B)" | |
_unfreeze_installer_root # Unfreeze immediately after imaging done | |
estat "Finalizing boot configurations for A and B partsets" | |
finalize_part A | |
finalize_part B | |
estat "Finalizing EFI system partition bootloader using partset A" | |
cmd steamos-chroot --no-overlay --disk "$DISK" --partset A -- steamcl-install --flags restricted --force-extra-removable | |
fi | |
} | |
# drop into the primary OS partset on the device | |
# | |
chroot_primary() | |
{ | |
local partset | |
partset=$(steamos-chroot --no-overlay --disk "$DISK" --partset "A" -- steamos-bootconf selected-image 2>/dev/null || echo "A") | |
einfo "Determined primary partset as: $partset (defaulted to A if detection failed)" | |
estat "Dropping into a chroot on the $partset partition set on $DISK." | |
estat "You can make any needed changes here, and type 'exit' when done." | |
cmd steamos-chroot --disk "$DISK" --partset "$partset" | |
} | |
# print quick list of targets | |
# | |
help() | |
{ | |
readvar HELPMSG << EOD | |
This tool can be used to reinstall or repair your SteamOS installation on $DISK. | |
Possible targets: | |
all : (Re)install SteamOS. This will format system and home partitions. | |
All data on $DISK will be effectively lost. | |
system : Repair/reinstall SteamOS on the device's system partitions, | |
preserving user data on home partition ($DISK$FS_HOME). | |
home : Reformat the device's /home partition ($DISK$FS_HOME) and var partitions, | |
removing games and user data from the device. | |
chroot : Chroot into to the primary SteamOS partition set. | |
EOD | |
emsg "$HELPMSG" | |
if [[ "$EUID" -ne 0 ]]; then | |
eerr "Please run as root (e.g. sudo $0 <target>)." | |
exit 1 # Exit after showing help if not root | |
fi | |
} | |
if [[ "$EUID" -ne 0 ]]; then | |
help # This will print help and exit with error code 1 as per the check inside help() | |
fi | |
writePartitionTable=0 | |
writeOS=0 | |
writeHome=0 | |
case "${1-help}" in | |
all) | |
prompt_step "Wipe Device & Install SteamOS" "This action will (re)install SteamOS on $DISK.\nThis will effectively destroy all data on the system and home partitions of this device.\n\nThis cannot be undone.\n\nChoose Proceed only if you wish to wipe and reinstall SteamOS on this device." | |
writePartitionTable=1 | |
writeOS=1 | |
writeHome=1 | |
einfo "Starting full SteamOS (re)installation on $DISK..." | |
repair_steps | |
prompt_reboot "Reimaging complete for $DISK." | |
;; | |
system) | |
prompt_step "Repair SteamOS System Partitions" "This action will repair the SteamOS installation on the system partitions of $DISK, while attempting to preserve your games and personal content on the home partition.\nSystem customizations may be lost.\n\nChoose Proceed to reinstall SteamOS system files on your device." | |
writeOS=1 | |
writeHome=0 # Preserve home | |
einfo "Starting SteamOS system repair on $DISK..." | |
repair_steps | |
prompt_reboot "SteamOS system reinstall complete for $DISK." | |
;; | |
home) | |
prompt_step "Delete Local User Data (Reformat Home)" "This action will reformat the home and var partitions on $DISK.\nThis will destroy downloaded games and all personal content, including system configuration.\n\nThis action cannot be undone.\n\nChoose Proceed to reformat all user data partitions." | |
writeHome=1 | |
writeOS=0 # Do not touch OS partitions | |
einfo "Starting home and var partition reformat on $DISK..." | |
repair_steps | |
prompt_reboot "User data partitions have been reformatted on $DISK." | |
;; | |
chroot) | |
chroot_primary | |
;; | |
*) | |
help | |
;; | |
esac | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment