Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4bb4f53
Guard three x86-only assumptions so Omarchy can install on aarch64
oceanapplications Aug 24, 2026
dadd58c
Derive an aarch64 pacman.conf instead of skipping the restore
oceanapplications Aug 26, 2026
482ddef
Carry the Windows-on-ARM device trees in every UKI on Qualcomm SoCs
JimmayVV Aug 26, 2026
2704962
Kernel parameters Snapdragon laptops need under Windows-on-ARM firmware
JimmayVV Aug 26, 2026
7ed5c9b
Install the Adreno Vulkan driver on Qualcomm SoCs
JimmayVV Aug 26, 2026
9135311
Qualcomm firmware package, and blacklist the audio DSP until its blob…
JimmayVV Aug 26, 2026
f666cc9
Copy the vendor-signed Qualcomm firmware from Windows during install
JimmayVV Aug 26, 2026
0b803ef
Keep the Qualcomm DSPs off when the root disk is on USB
JimmayVV Aug 26, 2026
9ee74e8
Give an aarch64 install Arch Linux ARM's package sources
JimmayVV Aug 26, 2026
2e6ebc3
Address Snapdragon setup review feedback
birkskyum Aug 28, 2026
2ca93ee
Trim Snapdragon implementation comments
birkskyum Aug 28, 2026
db10580
Keep missing Qualcomm firmware from aborting setup
birkskyum Sep 4, 2026
88ce320
Preserve safe Snapdragon setup on failed firmware inspection
birkskyum Sep 5, 2026
c1379b8
Retain the published Omarchy repository on ARM edge installs
birkskyum Sep 5, 2026
c10a306
Syntax-check each Snapdragon setup script
birkskyum Sep 6, 2026
adbe25d
Add Yoga Slim 7x board support
birkskyum Aug 27, 2026
24a673b
Trim Yoga board setup comments
birkskyum Aug 28, 2026
139f086
Skip Yoga DSP startup when disabled
birkskyum Aug 28, 2026
13a2767
Initialize Yoga display before disk unlock
birkskyum Aug 28, 2026
e8adc16
Include compressed and extracted Yoga display firmware
birkskyum Sep 5, 2026
457dac3
Use the laptop console for Yoga disk unlock
birkskyum Sep 5, 2026
91a5a70
Reuse board-matched zap firmware and exercise Yoga failure paths
birkskyum Sep 6, 2026
acf19b8
Preserve ARM repositories during pacman refresh
birkskyum Sep 6, 2026
f681ff0
Merge current Snapdragon runtime into Yoga support
birkskyum Sep 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions bin/omarchy-hw-qualcomm-soc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash

# omarchy:summary=Detect a Qualcomm SoC from the boot device tree.

[[ -r /sys/firmware/devicetree/base/compatible ]] || exit 1
tr '\0' '\n' </sys/firmware/devicetree/base/compatible | grep '^qcom,' >/dev/null
23 changes: 17 additions & 6 deletions bin/omarchy-refresh-pacman
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
#!/bin/bash

# omarchy:summary=Overwrite the package configuration for /etc/pacman with the Omarchy default of using its dedicated mirrors and repositories, then update all packages.
# omarchy:args=[stable|rc|edge]
# omarchy:requires-sudo=true

sudo cp -f /etc/pacman.conf /etc/pacman.conf.bak
sudo cp -f /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak
set -e

channel="${1:-stable}"
pacman_config=${OMARCHY_PACMAN_CONFIG:-/etc/pacman.conf}
mirrorlist=${OMARCHY_MIRRORLIST:-/etc/pacman.d/mirrorlist}

if [[ $channel != "stable" && $channel != "rc" && $channel != "edge" ]]; then
echo "Error: Invalid channel '$channel'. Must be one of: stable, rc, edge"
# Do not replace a working ARM repository setup with an unpublished channel.
if [[ $(uname -m) == "aarch64" && ( $channel == "stable" || $channel == "rc" ) ]]; then
echo "Omarchy $channel packages are not published for aarch64 yet. No repository configuration changed." >&2
echo "Use 'omarchy refresh pacman edge' only if you intend to use edge packages and upgrade the system." >&2
exit 1
fi

staged=$(mktemp -d)
trap 'rm -rf -- "$staged"' EXIT
source "$OMARCHY_PATH/install/helpers/pacman.sh"
pacman_write_repository_config "$channel" "$staged/pacman.conf" "$staged/mirrorlist"

echo "Setting channel to $channel"
echo

sudo cp -f "$OMARCHY_PATH/default/pacman/pacman-$channel.conf" /etc/pacman.conf
sudo cp -f "$OMARCHY_PATH/default/pacman/mirrorlist-$channel" /etc/pacman.d/mirrorlist
sudo cp -f "$pacman_config" "$pacman_config.bak"
sudo cp -f "$mirrorlist" "$mirrorlist.bak"
sudo cp -f "$staged/pacman.conf" "$pacman_config"
sudo cp -f "$staged/mirrorlist" "$mirrorlist"

# Allow user customization of /etc/pacman.conf before the upgrade runs
omarchy-hook pre-refresh-pacman
Expand Down
2 changes: 2 additions & 0 deletions default/pacman/mirrorlist-aarch64
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Arch Linux ARM publishes this endpoint with a $arch/$repo layout.
Server = http://mirror.archlinuxarm.org/$arch/$repo
30 changes: 30 additions & 0 deletions default/pacman/pacman-aarch64.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# See the pacman.conf(5) manpage for option and repository directives
# Arch Linux ARM provides the aarch64 repositories used below.

[options]
Color
ILoveCandy
VerbosePkgLists
HoldPkg = pacman glibc
Architecture = auto
CheckSpace
ParallelDownloads = 5
DownloadUser = alpm

# By default, pacman accepts packages signed by keys that its local keyring
# trusts (see pacman-key and its man page), as well as unsigned packages.
SigLevel = Required DatabaseOptional
LocalFileSigLevel = Optional

# pacman searches repositories in the order defined here.
[core]
Include = /etc/pacman.d/mirrorlist

[extra]
Include = /etc/pacman.d/mirrorlist

[alarm]
Include = /etc/pacman.d/mirrorlist

[aur]
Include = /etc/pacman.d/mirrorlist
5 changes: 4 additions & 1 deletion etc/mkinitcpio.conf.d/thunderbolt_module.conf
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
MODULES+=(thunderbolt)
# linux-aarch64 does not provide the thunderbolt module.
if [[ $(uname -m) == x86_64 ]]; then
MODULES+=(thunderbolt)
fi
5 changes: 5 additions & 0 deletions install/hardware/all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ run_logged "$OMARCHY_INSTALL/hardware/apple/fix-suspend-nvme.sh"
run_logged "$OMARCHY_INSTALL/hardware/apple/fix-t2.sh"
run_logged "$OMARCHY_INSTALL/hardware/apple/fix-brcmfmac-supplicant.sh"

run_logged "$OMARCHY_INSTALL/hardware/qualcomm/dtb-uki.sh"
run_logged "$OMARCHY_INSTALL/hardware/qualcomm/kernel-params.sh"
run_logged "$OMARCHY_INSTALL/hardware/qualcomm/firmware.sh"

run_logged "$OMARCHY_INSTALL/hardware/lenovo/fix-yoga-pro7-bass-speakers.sh"
run_logged "$OMARCHY_INSTALL/hardware/lenovo/yoga-slim7x.sh"

run_logged "$OMARCHY_INSTALL/hardware/fix-bcm43xx.sh"
run_logged "$OMARCHY_INSTALL/hardware/fix-surface-keyboard.sh"
Expand Down
40 changes: 40 additions & 0 deletions install/hardware/lenovo/start-yoga-slim7x-remoteprocs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash

set -euo pipefail

remoteproc_root=${OMARCHY_YOGA_REMOTEPROC_ROOT:-/sys/class/remoteproc}
attempts=${OMARCHY_YOGA_REMOTEPROC_ATTEMPTS:-30}
sleep_seconds=${OMARCHY_YOGA_REMOTEPROC_SLEEP:-1}

for ((attempt = 1; attempt <= attempts; attempt++)); do
adsp_started=0
shopt -s nullglob

for state_file in "$remoteproc_root"/remoteproc*/state; do
remoteproc=${state_file%/state}
[[ -r $remoteproc/firmware && -r $state_file ]] || continue

firmware=$(tr -d '\0\n' <"$remoteproc/firmware")
case "$firmware" in
*qcadsp*) kind=ADSP ;;
*qccdsp*) kind=CDSP ;;
*) continue ;;
esac

if [[ $(<$state_file) == running ]]; then
echo "Yoga Slim 7x: $kind is already running"
[[ $kind == ADSP ]] && adsp_started=1
elif [[ -w $state_file ]] && printf 'start\n' >"$state_file"; then
echo "Yoga Slim 7x: started $kind"
[[ $kind == ADSP ]] && adsp_started=1
else
echo "Yoga Slim 7x: could not start $kind ($firmware)" >&2
fi
done

((adsp_started)) && exit 0
sleep "$sleep_seconds"
done

echo "Yoga Slim 7x: audio DSP did not appear or could not be started" >&2
exit 1
68 changes: 68 additions & 0 deletions install/hardware/lenovo/yoga-slim7x.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Lenovo Yoga Slim 7x (14Q8X9 / 83ED) board-specific setup.

yoga_slim7x_compatible=""
compatible_path=${OMARCHY_YOGA_COMPATIBLE_PATH:-/sys/firmware/devicetree/base/compatible}
modules_load_dir=${OMARCHY_YOGA_MODULES_LOAD_DIR:-/etc/modules-load.d}
mkinitcpio_dir=${OMARCHY_YOGA_MKINITCPIO_DIR:-/etc/mkinitcpio.conf.d}
limine_config_dir=${OMARCHY_YOGA_LIMINE_CONFIG_DIR:-/etc/limine-entry-tool.d}
systemd_dir=${OMARCHY_YOGA_SYSTEMD_DIR:-/etc/systemd/system}

if [[ -r $compatible_path ]]; then
yoga_slim7x_compatible=$(tr '\0' '\n' <"$compatible_path")
fi

if omarchy-hw-qualcomm-soc &&
{ grep -qi '^lenovo,yoga-slim7x$' <<<"$yoga_slim7x_compatible" ||
omarchy-hw-match 'Yoga Slim 7x' || omarchy-hw-match '83ED'; }; then
echo "Detected Lenovo Yoga Slim 7x, applying board-specific support..."

# The Yoga exposes its CPU performance domains through SCMI.
mkdir -p "$modules_load_dir"
echo "scmi-cpufreq" >"$modules_load_dir/yoga-slim7x.conf"

# Initialize the internal keyboard and display before disk unlock.
mkdir -p "$mkinitcpio_dir"
cat >"$mkinitcpio_dir/yoga-slim7x-initramfs.conf" <<'CONF'
MODULES+=(i2c-hid-of qrtr ps883x pmic_glink_altmode)

# The board-signed zap shader is included by qcom-firmware-extract.
for firmware in \
qcom/gen70500_sqe.fw \
qcom/gen70500_gmu.bin; do
for suffix in '' .zst .xz; do
for directory in "${OMARCHY_YOGA_FIRMWARE_ROOT:-/usr/lib/firmware}/updates" \
"${OMARCHY_YOGA_FIRMWARE_ROOT:-/usr/lib/firmware}"; do
if [[ -f $directory/$firmware$suffix ]]; then
FILES+=("$directory/$firmware$suffix")
break 2
fi
done
done
done
unset firmware directory suffix
CONF

mkdir -p "$limine_config_dir"
cat >"$limine_config_dir/yoga-slim7x.conf" <<'CONF'
KERNEL_CMDLINE[default]+=" initcall_blacklist=simpledrm_platform_driver_init"
# Keep Plymouth and the keyboard hooks on the laptop console, not the serial port.
KERNEL_CMDLINE[default]+=" console=tty0"
CONF

# Start the board's DSP remote processors.
mkdir -p "$systemd_dir"
cat >"$systemd_dir/yoga-slim7x-remoteprocs.service" <<'UNIT'
[Unit]
Description=Start the Lenovo Yoga Slim 7x DSPs
ConditionPathExists=!/etc/modprobe.d/qualcomm-adsp-nofw.conf

[Service]
Type=oneshot
ExecStart=/bin/bash /usr/share/omarchy/install/hardware/lenovo/start-yoga-slim7x-remoteprocs.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
UNIT
systemctl enable yoga-slim7x-remoteprocs.service
fi
50 changes: 50 additions & 0 deletions install/hardware/qualcomm/dtb-uki.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Embed Qualcomm device trees so systemd-stub can select one from SMBIOS data.
# DeviceTreeAuto requires literal paths, so hardware setup refreshes the list.

if omarchy-hw-qualcomm-soc; then
omarchy-pkg-add systemd-ukify

dtb_dir=${OMARCHY_QUALCOMM_DTB_DIR:-/boot/dtbs/qcom}
uki_config=${OMARCHY_QUALCOMM_UKI_CONFIG:-/etc/kernel/uki.conf}
dtbs=()
for dtb in "$dtb_dir"/x1*.dtb "$dtb_dir"/hamoa*.dtb \
"$dtb_dir"/glymur*.dtb "$dtb_dir"/sc8280xp*.dtb; do
if [[ -f $dtb && $dtb != *-el2.dtb ]]; then
dtbs+=("$dtb")
fi
done

if ((${#dtbs[@]} == 0)); then
echo "No Windows-on-ARM device trees under $dtb_dir; the UKI gets no .dtbauto sections" >&2
else
managed_begin="# BEGIN OMARCHY QUALCOMM DEVICE TREES"
managed_end="# END OMARCHY QUALCOMM DEVICE TREES"

mkdir -p "$(dirname "$uki_config")"
uki_tmp=$(mktemp "${uki_config}.XXXXXX")

if [[ -f $uki_config ]]; then
cp -p "$uki_config" "$uki_tmp"
awk -v begin="$managed_begin" -v end="$managed_end" '
$0 == begin { managed = 1; next }
managed && $0 == end { managed = 0; next }
!managed { print }
' "$uki_config" >"$uki_tmp"
else
chmod 0644 "$uki_tmp"
fi

{
echo "$managed_begin"
echo "# Generated by Omarchy for Qualcomm Snapdragon devices."
echo "# systemd-stub selects a device tree from SMBIOS data."
echo "# Rerun 'omarchy apply hardware' after a kernel update adds new boards."
echo "[UKI]"
echo "DeviceTreeAuto=${dtbs[*]}"
echo "$managed_end"
} >>"$uki_tmp"

mv -f "$uki_tmp" "$uki_config"
echo "Listed ${#dtbs[@]} device trees in $uki_config"
fi
fi
29 changes: 29 additions & 0 deletions install/hardware/qualcomm/firmware.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Install packaged Qualcomm firmware and vendor-signed blobs extracted from Windows.
# Keep the DSP driver disabled when starting it could disconnect the root disk.

if omarchy-hw-qualcomm-soc; then
omarchy-pkg-add linux-firmware-qcom qcom-firmware-extract

qcom-firmware-extract --install --no-rebuild || true

modprobe_dir=${OMARCHY_QUALCOMM_MODPROBE_DIR:-/etc/modprobe.d}
root_source=$(findmnt -no SOURCE --nofsroot / 2>/dev/null || true)

mkdir -p "$modprobe_dir"
if [[ -n $root_source ]] && lsblk -sno TRAN "$root_source" 2>/dev/null | grep -q '^usb$'; then
# Starting the DSPs resets USB-C, so keep them off when root is on USB.
cat >"$modprobe_dir/qualcomm-adsp-nofw.conf" <<'CONF'
# Generated by Omarchy for Qualcomm Snapdragon devices.
# Keep the DSP driver off while the root disk is attached over USB.
blacklist qcom_q6v5_pas
CONF
elif ! missing_firmware=$(qcom-firmware-extract --list-missing) || grep -q 'adsp' <<<"$missing_firmware"; then
cat >"$modprobe_dir/qualcomm-adsp-nofw.conf" <<'CONF'
# Generated by Omarchy for Qualcomm Snapdragon devices.
# Keep the DSP driver off until its signed firmware can be verified.
blacklist qcom_q6v5_pas
CONF
else
rm -f "$modprobe_dir/qualcomm-adsp-nofw.conf"
fi
fi
13 changes: 13 additions & 0 deletions install/hardware/qualcomm/kernel-params.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Add firmware workarounds required by current Snapdragon laptops.

DROP_IN="/etc/limine-entry-tool.d/qualcomm-snapdragon.conf"

if omarchy-hw-qualcomm-soc; then
mkdir -p /etc/limine-entry-tool.d
cat >"$DROP_IN" <<'CONF'
# Generated by Omarchy for Qualcomm Snapdragon devices.
# Keep display and I/O resources enabled until their drivers load.
# Disable pointer authentication and waiting for an unavailable TPM.
KERNEL_CMDLINE[default]+=" clk_ignore_unused pd_ignore_unused arm64.nopauth systemd.tpm2_wait=0"
CONF
fi
5 changes: 5 additions & 0 deletions install/hardware/vulkan.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ for vendor in "${!VULKAN_DRIVERS[@]}"; do
fi
done

# Adreno GPUs are platform devices, so lspci never sees them.
if omarchy-hw-qualcomm-soc; then
PACKAGES+=(vulkan-freedreno)
fi

if (( ${#PACKAGES[@]} > 0 )); then
omarchy-pkg-add "${PACKAGES[@]}"
fi
25 changes: 25 additions & 0 deletions install/helpers/pacman.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Write repository files for both offline-install finalization and refreshes.
# Callers choose the destination so refreshes can stage files before using sudo.
pacman_write_repository_config() {
local channel=$1 config=$2 mirrorlist=$3
local defaults="$OMARCHY_PATH/default/pacman"

if [[ $channel != "stable" && $channel != "rc" && $channel != "edge" ]]; then
echo "Error: Invalid channel '$channel'. Must be one of: stable, rc, edge" >&2
return 1
fi

if [[ $(uname -m) == "aarch64" ]]; then
cp -f "$defaults/pacman-aarch64.conf" "$config" || return 1
cp -f "$defaults/mirrorlist-aarch64" "$mirrorlist" || return 1

# Only edge publishes an aarch64 Omarchy repository. Offline stable/RC
# installs retain ALARM without silently opting into an experimental channel.
if [[ $channel == "edge" ]]; then
printf "\n[omarchy]\nServer = https://pkgs.omarchy.org/edge/\$arch\n" >>"$config" || return 1
fi
else
cp -f "$defaults/pacman-$channel.conf" "$config" || return 1
cp -f "$defaults/mirrorlist-$channel" "$mirrorlist" || return 1
fi
}
3 changes: 3 additions & 0 deletions install/omarchy-other.packages
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,6 @@ t2fanrd

# Framework 16
qmk-hid

# Qualcomm Snapdragon support packages
qcom-firmware-extract
21 changes: 17 additions & 4 deletions install/post-install/pacman.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
# Configure pacman after package installation completes. Offline target package
# installs use the live ISO's offline pacman.conf until this final restore.
cp -f "$OMARCHY_PATH/default/pacman/pacman-${OMARCHY_MIRROR:-stable}.conf" /etc/pacman.conf
cp -f "$OMARCHY_PATH/default/pacman/mirrorlist-${OMARCHY_MIRROR:-stable}" /etc/pacman.d/mirrorlist
# Replace the installer's offline pacman configuration with online repositories.
pacman_config=${OMARCHY_PACMAN_CONFIG:-/etc/pacman.conf}
mirrorlist=${OMARCHY_MIRRORLIST:-/etc/pacman.d/mirrorlist}
source "$OMARCHY_PATH/install/helpers/pacman.sh"

if [[ $(uname -m) == "aarch64" ]]; then
# Install the keyring before replacing the offline package source.
omarchy-pkg-add archlinuxarm-keyring
fi

pacman_write_repository_config "${OMARCHY_MIRROR:-stable}" "$pacman_config" "$mirrorlist" || return 1

if [[ $(uname -m) == "aarch64" ]]; then
# Trust every installed keyring before the first signed sync.
pacman-key --init
pacman-key --populate
fi

# Wait for CUPS to own the file, the way omarchy-settings does, so pacman does
# not turn the override into a .pacnew during ISO package installation.
Expand Down
9 changes: 7 additions & 2 deletions install/user/mise-work.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@ case ${OMARCHY_SETUP_CONTEXT:-runtime} in
esac

if [[ -n $NODE_PACKAGE_DIR ]]; then
NODE_TARBALL=$(find "$NODE_PACKAGE_DIR" -name "node-v*-linux-x64.tar.gz" -type f 2>/dev/null | head -n1)
# Node names its builds x64/arm64, not by uname
case "$(uname -m)" in
aarch64) _NODE_ARCH=arm64 ;;
*) _NODE_ARCH=x64 ;;
esac
NODE_TARBALL=$(find "$NODE_PACKAGE_DIR" -name "node-v*-linux-${_NODE_ARCH}.tar.gz" -type f 2>/dev/null | head -n1)
if [[ -z $NODE_TARBALL ]]; then
if [[ ${OMARCHY_SETUP_CONTEXT:-} == "provision-owner" ]]; then
# A factory snapshot predating the bundled tarball may not have it staged.
Expand All @@ -31,7 +36,7 @@ if [[ -n $NODE_PACKAGE_DIR ]]; then
exit 1
fi
else
NODE_VERSION=$(basename "$NODE_TARBALL" | sed 's/node-v\(.*\)-linux-x64.tar.gz/\1/')
NODE_VERSION=$(basename "$NODE_TARBALL" | sed "s/node-v\\(.*\\)-linux-${_NODE_ARCH}.tar.gz/\\1/")
NODE_INSTALL_DIR="$HOME/.local/share/mise/installs/node/$NODE_VERSION"

mkdir -p "$NODE_INSTALL_DIR"
Expand Down
Loading