282 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#! /bin/bash
 | 
						|
#
 | 
						|
# Copyright 2020, Stormux, <storm_dragon@linux-a11y.org>
 | 
						|
#
 | 
						|
# This is free software; you can redistribute it and/or modify it under the
 | 
						|
# terms of the GNU General Public License as published by the Free
 | 
						|
# Software Foundation; either version 3, or (at your option) any later
 | 
						|
# version.
 | 
						|
#
 | 
						|
# This software is distributed in the hope that it will be useful,
 | 
						|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
# General Public License for more details.
 | 
						|
#
 | 
						|
# You should have received a copy of the GNU General Public License
 | 
						|
# along with this package; see the file COPYING.  If not, write to the Free
 | 
						|
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
# 02110-1301, USA.
 | 
						|
#
 | 
						|
 | 
						|
# keep track of mounted status for exit function
 | 
						|
mounted=1
 | 
						|
 | 
						|
set -e # Don't want to destroy stuff if this goes majorly wrong.
 | 
						|
trap cleanup EXIT # make sure the script cleans up after itself before closing.
 | 
						|
 | 
						|
 | 
						|
cleanup() {
 | 
						|
    if [[ $mounted -eq 0 ]]; then
 | 
						|
        umount -R /mnt
 | 
						|
        partx -d "${loopdev}"
 | 
						|
        losetup --detach "${loopdev}"
 | 
						|
    fi
 | 
						|
    if [[ -n "${imageFileName}" ]]; then
 | 
						|
        rm "${imageFileName}"
 | 
						|
    fi
 | 
						|
    exit 0
 | 
						|
}
 | 
						|
 | 
						|
help() {
 | 
						|
    echo -e "Usage:\n"
 | 
						|
    echo "With no arguments, build with default parameters."
 | 
						|
    for i in "${!command[@]}" ; do
 | 
						|
        echo "-${i/:/ <parameter>}: ${command[${i}]}"
 | 
						|
    done | sort
 | 
						|
    exit 0
 | 
						|
}
 | 
						|
 | 
						|
# Array of command line arguments
 | 
						|
declare -A command=(
 | 
						|
    [h]="This help screen."
 | 
						|
    [l:]="Language default is en_US."
 | 
						|
    [n:]="Image name, default is stormux-pi<32|64>-<yyyy-mm-dd>.img"
 | 
						|
    [s:]="image size in GB, default is 4."
 | 
						|
    [v:]="Version of the Raspberry Pi for which you are building. (32|64) default is 64."
 | 
						|
)
 | 
						|
 | 
						|
# Convert the keys of the associative array to a format usable by getopts
 | 
						|
args="${!command[*]}"
 | 
						|
args="${args//[[:space:]]/}"
 | 
						|
while getopts "${args}" i ; do
 | 
						|
    case "$i" in
 | 
						|
        h) help ;;
 | 
						|
        l)
 | 
						|
            imageLanguage="${OPTARG}.UTF-8"
 | 
						|
            ;;
 | 
						|
        n)
 | 
						|
            imageName="${OPTARG}"
 | 
						|
            ;;
 | 
						|
        s)
 | 
						|
            if [[ "${OPTARG}" =~ ^[[:digit:]]+$ ]]; then
 | 
						|
                imageSize="${OPTARG}G"
 | 
						|
            else
 | 
						|
                echo "Image size must be numeric."
 | 
						|
                exit 1
 | 
						|
            fi
 | 
						|
            ;;
 | 
						|
        v)
 | 
						|
            if [[ "${OPTARG}" =~ ^32|64$ ]]; then
 | 
						|
                imageVersion="${OPTARG}"
 | 
						|
            else
 | 
						|
                echo "Image version must be 32 for 32 bit (armv7h), or 64 for 64 bit (aarch64 default)."
 | 
						|
                exit 1
 | 
						|
            fi
 | 
						|
            ;;
 | 
						|
        *)
 | 
						|
            exit 1
 | 
						|
            ;;
 | 
						|
    esac
 | 
						|
done
 | 
						|
 | 
						|
# make sure variables are set, or use defaults.
 | 
						|
export imageVersion="${imageVersion:-64}"
 | 
						|
export imageSize="${imageSize:-4G}"
 | 
						|
imageName="${imageName:-stormux-pi4-${imageVersion}-$(date '+%Y-%m-%d').img}"
 | 
						|
imageName="${imageName/-64-/-aarch64-}"
 | 
						|
imageName="${imageName/-32-/-armv7h-}"
 | 
						|
export imageName
 | 
						|
export imageLanguage="${imageLanguage:-en_US.UTF-8}"
 | 
						|
 | 
						|
# Make sure the image file doesn't exist.
 | 
						|
if [[ -e "$imageName" ]]; then
 | 
						|
    echo "${imageName} exists, please remove or move it for this script to continue."
 | 
						|
    exit 1
 | 
						|
fi
 | 
						|
 | 
						|
# Make sure this script is ran as root.
 | 
						|
if [ "$(whoami)" != "root" ] ; then
 | 
						|
    echo "Error: This script must be run as root."
 | 
						|
    exit 1
 | 
						|
fi
 | 
						|
 | 
						|
# make sure the needed tools are installed
 | 
						|
if [[ "$(uname -m)" == "x86_64" ]]; then
 | 
						|
    if ! pacman -Q qemu-user-static &> /dev/null ; then
 | 
						|
        echo "Please install qemu-user-static and qemu-user-static-binfmt before continuing."
 | 
						|
        exit 1
 | 
						|
    fi
 | 
						|
    if ! pacman -Q qemu-user-static-binfmt &> /dev/null ; then
 | 
						|
        echo "Please install qemu-user-static and qemu-user-static-binfmt before continuing."
 | 
						|
        exit 1
 | 
						|
    fi
 | 
						|
fi
 | 
						|
for i in arch-install-scripts dosfstools parted wget ; do
 | 
						|
    if ! pacman -Q $i &> /dev/null ; then
 | 
						|
        echo "Please install $i before continuing."
 | 
						|
        exit 1
 | 
						|
    fi
 | 
						|
done
 | 
						|
 | 
						|
 | 
						|
# Url for the image to be downloaded.
 | 
						|
url[32]="http://os.archlinuxarm.org/os/ArchLinuxARM-rpi-armv7-latest.tar.gz"
 | 
						|
url[64]="http://os.archlinuxarm.org/os/ArchLinuxARM-rpi-aarch64-latest.tar.gz"
 | 
						|
 | 
						|
fallocate -l "$imageSize" "$imageName"
 | 
						|
loopdev="$(losetup --find --show "${imageName}")"
 | 
						|
parted --script "${loopdev}" mklabel msdos mkpart primary fat32 0% 200M mkpart primary ext4 200M 100%
 | 
						|
mkfs.vfat -F32 "${loopdev}p1"
 | 
						|
mkfs.ext4 -F "${loopdev}p2"
 | 
						|
mount "${loopdev}p2" /mnt
 | 
						|
mkdir /mnt/boot
 | 
						|
mount "${loopdev}p1" /mnt/boot
 | 
						|
# Things are mounted now, so set mounted to 0 (bash true)
 | 
						|
mounted=0
 | 
						|
imageFileName=$(mktemp)
 | 
						|
wget "${url[$imageVersion]}" -O "${imageFileName}"
 | 
						|
if [[ $imageVersion -eq 32 ]]; then
 | 
						|
    # Workaround for bsdtar errors when extracting 32 bit image.
 | 
						|
    set +e
 | 
						|
fi
 | 
						|
bsdtar -xpf "${imageFileName}" -C /mnt
 | 
						|
# Set -e in case it got unset for 32 bit image
 | 
						|
set -e
 | 
						|
arch-chroot /mnt << EOF
 | 
						|
# set up pacman
 | 
						|
pacman-key --init
 | 
						|
pacman-key --populate archlinuxarm
 | 
						|
pacman -Syy
 | 
						|
# Change kernels for aarch64
 | 
						|
if [[ "$imageVersion" == "64" ]]; then
 | 
						|
pacman -R --noconfirm linux-aarch64 uboot-raspberrypi
 | 
						|
pacman -S --noconfirm linux-rpi
 | 
						|
fi
 | 
						|
 | 
						|
# Install packages
 | 
						|
pacman -Su --needed --noconfirm \
 | 
						|
    alsa-firmware \
 | 
						|
    alsa-utils \
 | 
						|
    base \
 | 
						|
    base-devel \
 | 
						|
    bash-completion \
 | 
						|
    bluez \
 | 
						|
    bluez-utils \
 | 
						|
    brltty \
 | 
						|
    cloud-utils \
 | 
						|
    cronie \
 | 
						|
    dbus-broker \
 | 
						|
    espeak-ng \
 | 
						|
    fake-hwclock \
 | 
						|
    git \
 | 
						|
    go \
 | 
						|
    magic-wormhole \
 | 
						|
    man \
 | 
						|
    man-pages \
 | 
						|
    networkmanager \
 | 
						|
    ntp \
 | 
						|
    pipewire \
 | 
						|
    pipewire-alsa \
 | 
						|
    pipewire-jack \
 | 
						|
    pipewire-pulse \
 | 
						|
    poppler \
 | 
						|
    python-pyudev \
 | 
						|
    python-daemonize \
 | 
						|
    python-evdev \
 | 
						|
    python-dbus \
 | 
						|
    python-pyte \
 | 
						|
    raspberrypi-firmware \
 | 
						|
    realtime-privileges \
 | 
						|
    rhvoice-voice-bdl \
 | 
						|
    rng-tools \
 | 
						|
    rsync \
 | 
						|
    sox \
 | 
						|
    w3m \
 | 
						|
    wget \
 | 
						|
    wireless-regdb \
 | 
						|
    wireplumber \
 | 
						|
    xdg-user-dirs \
 | 
						|
    xdg-utils
 | 
						|
 | 
						|
# set the language
 | 
						|
sed -i "s/#$imageLanguage/$imageLanguage/" /etc/locale.gen
 | 
						|
echo "LANG=$imageLanguage" > /etc/locale.conf
 | 
						|
locale-gen
 | 
						|
# Configure and enable Hardware Random Number Generator
 | 
						|
echo 'RNGD_OPTS="-o /dev/random -r /dev/hwrng"' > /etc/conf.d/rngd
 | 
						|
systemctl enable rngd.service
 | 
						|
# Set the distribution name.
 | 
						|
echo 'Stormux \r (\l)' > /etc/issue
 | 
						|
echo >> /etc/issue
 | 
						|
# Change the alarm user to be stormux
 | 
						|
usermod -a -g users -G wheel,realtime,audio,video,network,brlapi -m -d /home/stormux -l stormux alarm
 | 
						|
# Grant sudo privileges to the stormux user for package installation.
 | 
						|
echo 'stormux ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/wheel
 | 
						|
# Set the password for the root user
 | 
						|
echo -e "root\nroot" | passwd "root"
 | 
						|
# Set the password for the stormux user
 | 
						|
echo -e "stormux\nstormux" | passwd "stormux"
 | 
						|
# Change to the stormux user and install some packages
 | 
						|
sudo -iu stormux
 | 
						|
# Create desktop, downloads, music, and other directories.
 | 
						|
xdg-user-dirs-update
 | 
						|
# Build AUR packages
 | 
						|
export aurPackages=(fenrir-git \
 | 
						|
    growpartfs \
 | 
						|
    log2ram \
 | 
						|
    yay)
 | 
						|
export PKGDEST=~/packages
 | 
						|
for p in "\${aurPackages[@]}" ; do
 | 
						|
    git clone https://aur.archlinux.org/\${p}.git
 | 
						|
    cd ~/\${p}
 | 
						|
    makepkg -A
 | 
						|
    cd ~
 | 
						|
    rm -rf \${p}
 | 
						|
done
 | 
						|
exit
 | 
						|
# Install built packages
 | 
						|
for p in /home/stormux/packages/* ; do
 | 
						|
    pacman -U --noconfirm \${p}
 | 
						|
done
 | 
						|
rm -rf /home/stormux/packages/
 | 
						|
# Enable linger so that hopefully sound will start at login.
 | 
						|
mkdir -p /var/lib/systemd/linger
 | 
						|
touch /var/lib/systemd/linger/stormux
 | 
						|
systemctl --global enable dbus-broker.service pipewire.service pipewire-pulse.service
 | 
						|
/usr/share/fenrirscreenreader/tools/configure_pipewire.sh
 | 
						|
sudo -u stormux /usr/share/fenrirscreenreader/tools/configure_pipewire.sh
 | 
						|
# Configure sudo for group wheel, remove nopasswd for the stormux user
 | 
						|
echo '%wheel ALL=(ALL) ALL' > /etc/sudoers.d/wheel
 | 
						|
# Set the hostname
 | 
						|
echo stormux > /etc/hostname
 | 
						|
# Configure services
 | 
						|
systemctl enable brltty.path cronie.service dbus-broker.service fake-hwclock.service fenrirscreenreader.service log2ram.service NetworkManager.service ntpd.service
 | 
						|
systemctl disable dbus.service
 | 
						|
# Cleanup packages
 | 
						|
pacman -Sc --noconfirm
 | 
						|
pacman -R --noconfirm go
 | 
						|
 | 
						|
# Update fstab for Raspberry Pi 4. Not needed until linux-aarch64 works.
 | 
						|
# [[ $imageVersion -eq 4 ]] && sed -i 's/mmcblk0/mmcblk1/g' /etc/fstab
 | 
						|
EOF
 | 
						|
 | 
						|
# Copy override files into place.
 | 
						|
cp -rv ../files/boot/* /mnt/boot
 | 
						|
cp -rv ../files/etc/* /mnt/etc
 | 
						|
cp -rv ../files/var/* /mnt/var
 | 
						|
cp -rv ../files/usr/* /mnt/usr
 | 
						|
cp -rv ../files/etc/skel/{.,}* /mnt/home/stormux/
 | 
						|
 | 
						|
# Exiting calls the cleanup function to unmount.
 | 
						|
exit 0
 |