move the rpitools repo to boxtools/rpi

as we will need anyway boxtools also for rpis
This commit is contained in:
2025-04-04 16:23:00 +02:00
parent 6908908d13
commit d7162993ad
8 changed files with 849 additions and 0 deletions

View File

@ -201,3 +201,41 @@ Use (b) above to boot from the BOOT_TINY USB stick
$ sh clone
```
You are asked to confirm or change the image name.
## Installation of a Fresh Raspberry Pi
### install from cloned image (work currently from a Mac only)
Put compute module into PoE adapter, connect microUSB 'POWER' to
a USB power supply, and connect micorUSB 'SLAVE' to your computer.
Go to the rpi subdir and then start
```
cd rpi
`./write_to emmc
```
You may test starting up the compute module in the PoE adapter, with a
LAN cable attached, or directly in the iono pi max.
* on startup, the name will be boxaaaaaa with aaaaaa the last digits of the ethernet address
* a new file should be created in the cfg sub directory
### installing RPI tools from an fresh raspberry image (downloaded with Raspberry Pi Imager)
use the script install-ionopimax.sh or install-ionopi.sh
(together with configsrtc.sh config-rtc-MCP79410.service)
to add the needed items for iono pi and the run time clock
### create a clone image
In the rpi subdirectory, execute
```
./clone
```
An dated image will be created within about 10 min. and copied to the given directory.

40
rpi/clone Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env python3
import os
import time
HOST = "l_samenv@samenv"
SUBDIR = "boxes/rpi_images"
DEFDEST = f"{HOST}:{SUBDIR}"
file = f"{time.strftime('%Y-%m-%d')}.lz4"
def prt(text):
print(time.strftime('%H:%M:%S'), text)
dest = input(f"destination directory for image [{DEFDEST}]: ") or DEFDEST
host, _, subdir = dest.partition(':')
if not subdir:
if '@' in host:
subdir = SUBDIR
else:
subdir, host = host, HOST
if os.system(f'ssh {host} cd {subdir}'):
raise ValueError(f'{host}:{subdir} does not exist')
if not os.system(f"bash -c 'ssh {host} ls {subdir}/{file} &> /dev/null'"):
print(f'{host}:{subdir}/{file} already exists')
file = input(f"destination file name [{file}]: ") or file
prt('needs about 10 minutes')
pid = os.getpid()
tmpfile = f"/media/rpi{pid}.img"
os.system(f"sudo bash image-backup -i {tmpfile}")
prt('pack and copy ... (3 minutes)')
os.system(f"bash -c 'dd if={tmpfile} bs=512k | lz4 | ssh {host} dd of={subdir}/{file} bs=512k'")
prt('cleanup ...')
os.system(f"sudo rm -f {tmpfile}")

View File

@ -0,0 +1,8 @@
[Unit]
Description=RTC configuration for MCP79410
[Service]
ExecStart=/usr/local/bin/configrtc.sh
[Install]
WantedBy=multi-user.target

7
rpi/configrtc.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
modprobe i2c-dev
# Calibrate the clock (default: 0x47). See datasheet for MCP7940N
i2cset -y 1 0x6f 0x08 0x47
modprobe i2c:mcp7941x
echo mcp7941x 0x6f > /sys/class/i2c-dev/i2c-1/device/new_device
hwclock -s

521
rpi/image-backup Normal file
View File

@ -0,0 +1,521 @@
#!/bin/bash
trap '{ stty sane; echo ""; errexit "Aborted"; }' SIGINT SIGTERM
MNTPATH="/tmp/img-backup-mnt"
ONEMB=$((1024 * 1024))
errexit()
{
echo ""
echo -e "$1"
echo ""
if [ "${MNTED}" = "TRUE" ]; then
umount "${BOOTMNT}/" &> /dev/null
umount "${MNTPATH}/" &> /dev/null
fi
rm -rf "${MNTPATH}/" &> /dev/null
rmloop
exit 1
}
mkloop()
{
LOOP="$(losetup -f --show -P "${IMGFILE}")"
if [ $? -ne 0 ]; then
errexit "Unable to create loop device"
fi
}
rmloop()
{
if [ "${LOOP}" != "" ]; then
losetup -d "${LOOP}"
LOOP=""
fi
}
mntimg()
{
mkloop
if [ ! -d "${MNTPATH}/" ]; then
mkdir "${MNTPATH}/"
if [ $? -ne 0 ]; then
errexit "Unable to make ROOT partition mount point"
fi
fi
mount "${LOOP}p2" "${MNTPATH}/"
if [ $? -ne 0 ]; then
errexit "Unable to mount image ROOT partition"
fi
MNTED=TRUE
if [ ! -d "${BOOTMNT}/" ]; then
mkdir -p "${BOOTMNT}/"
if [ $? -ne 0 ]; then
errexit "Unable to make BOOT partition mount point"
fi
fi
mount "${LOOP}p1" "${BOOTMNT}/"
if [ $? -ne 0 ]; then
errexit "Unable to mount image BOOT partition"
fi
}
umntimg()
{
umount "${BOOTMNT}/"
if [ $? -ne 0 ]; then
errexit "Unable to unmount image BOOT partition"
fi
umount "${MNTPATH}/"
if [ $? -ne 0 ]; then
errexit "Unable to unmount image ROOT partition"
fi
MNTED=FALSE
rmloop
rm -r "${MNTPATH}/"
}
fsckerr()
{
errexit "Filesystem appears corrupted "$1" resize2fs"
}
usage()
{
errexit "Usage: $0 [options] [pathto/imagefile for incremental backup]\n\
-h,--help This usage description\n\
-i,--initial pathto/filename of image file [,inital size MB [,added space for incremental MB]]\n\
-n,--noexpand Do not expand filesystem on first run after restore\n\
-o,--options Additional rsync options (comma separated)\n\
-u,--ubuntu Ubuntu (Deprecated)\n\
-x,--extract Extract image from NOOBS (force BOOT partition to -01 / ROOT partition to -02)"
}
backup()
{
mntimg
sync
rsync -aDH --partial --numeric-ids --delete --force --exclude "${MNTPATH}" --exclude '/dev' --exclude '/lost+found' --exclude '/media' --exclude '/mnt' \
--exclude '/proc' --exclude '/run' --exclude '/sys' --exclude '/tmp' --exclude '/var/swap' --exclude '/etc/udev/rules.d/70-persistent-net.rules' \
--exclude '/var/lib/asterisk/astdb.sqlite3-journal' "${OPTIONS[@]}" / "${MNTPATH}/"
if [[ $? -ne 0 && $? -ne 24 ]]; then
errexit "Unable to create backup"
fi
mkdir -p "${MNTPATH}/dev/" "${MNTPATH}/lost+found/" "${MNTPATH}/media/" "${MNTPATH}/mnt/" "${MNTPATH}/proc/" "${MNTPATH}/run/" "${MNTPATH}/sys/" "${MNTPATH}/tmp/"
if [ $? -ne 0 ]; then
errexit "Unable to create image directories"
fi
chmod a+rwxt "${MNTPATH}/tmp/"
if [ "${EXTRACT}" = "TRUE" ]; then
sed -i "/^[[:space:]]*#/!s|^\(.*root=\)\S\+\(\s\+.*\)$|\1PARTUUID=${PTUUID}-02\2|" "${BOOTMNT}/cmdline.txt"
sed -i "/^[[:space:]]*#/!s|^\S\+\(\s\+/boot\S*\s\+vfat\s\+.*\)$|PARTUUID=${PTUUID}-01\1|" "${MNTPATH}/etc/fstab"
sed -i "/^[[:space:]]*#/!s|^\S\+\(\s\+/\s\+.*\)$|PARTUUID=${PTUUID}-02\1|" "${MNTPATH}/etc/fstab"
fi
if [[ "${OSID}" != "ubuntu" && "${NOEXPAND}" = "FALSE" && "${ROOT_TYPE}" != "f2fs" && $(grep -v '^[[:space:]]*#' "${MNTPATH}/etc/rc.local" | grep -c 'resize-root-fs') -eq 0 ]]; then
cat <<\EOF1 > "${MNTPATH}/etc/resize-root-fs"
#!/bin/bash
ROOT_PART="$(mount | sed -n 's|^\(/dev/.*\) on / .*|\1|p')"
ROOT_DEV="$(sed 's/[0-9]\+$//' <<< "${ROOT_PART}")"
if [ "${ROOT_DEV}" = "/dev/mmcblk0p" ]; then
ROOT_DEV="${ROOT_DEV:0:(${#ROOT_DEV} - 1)}"
fi
START=$(sfdisk -d "${ROOT_DEV}" | sed -n "s|^${ROOT_PART}\s\+:.*start=\s*\([0-9]\+\).*$|\1|p")
PTTYPE="$(blkid "${ROOT_DEV}" | sed -n 's|^.*PTTYPE="\(\S\+\)".*|\1|p')"
if [ "${PTTYPE}" = "dos" ]; then
sfdisk --delete "${ROOT_DEV}" 2 > /dev/null
echo "${START},+" | sfdisk --no-reread --no-tell-kernel -N2 "${ROOT_DEV}" &> /dev/null
else
PARTUUID="$(blkid "${ROOT_PART}" | sed -n 's|^.*PARTUUID="\(\S\+\)".*|\1|p')"
sgdisk -d 2 "${ROOT_DEV}" > /dev/null
sgdisk -n 2:${START}:0 "${ROOT_DEV}" > /dev/null
sgdisk -u 2:${PARTUUID} "${ROOT_DEV}" > /dev/null
fi
cat <<\EOF2 > /etc/init.d/resize_root_fs
#!/bin/sh
### BEGIN INIT INFO
# Provides: resize_root_fs
# Required-Start:
# Required-Stop:
# Default-Start: 3
# Default-Stop:
# Short-Description: Resize root filesystem
# Description:
### END INIT INFO
case "$1" in
start)
resize2fs "$(mount | sed -n 's|^\(/dev/.*\) on / .*|\1|p')"
update-rc.d resize_root_fs remove
rm /etc/init.d/resize_root_fs
;;
*)
exit 3
;;
esac
EOF2
chmod +x /etc/init.d/resize_root_fs
update-rc.d resize_root_fs defaults
sed -i '/resize-root-fs/d' /etc/rc.local
rm /etc/resize-root-fs
shutdown --no-wall -r now
EOF1
chmod +x "${MNTPATH}/etc/resize-root-fs"
sed -i 's|^exit 0$|/etc/resize-root-fs\nexit 0|' "${MNTPATH}/etc/rc.local"
fi
sync
umntimg
mkloop
fatlabel "${LOOP}p1" "$(fatlabel ${ROOT_DEV_P}1 | sed -n '$p')" &> /dev/null
e2label "${LOOP}p2" "$(e2label ${ROOT_DEV_P}2)" &> /dev/null
rmloop
}
LOOP=""
MNTED=FALSE
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
if [ $(id -u) -ne 0 ]; then
errexit "$0 must be run as root user"
fi
PGMNAME="$(basename $0)"
for PID in $(pidof -x -o %PPID "${PGMNAME}"); do
if [ ${PID} -ne $$ ]; then
errexit "${PGMNAME} is already running"
fi
done
gdisk -l "${DEVICE}" &> /dev/null
if [ $? -eq 127 ]; then
echo ""
echo "gdisk not installed"
echo ""
echo -n "Ok to install gdisk (y/n)? "
while read -r -n 1 -s answer; do
if [[ "${answer}" = [yYnN] ]]; then
echo "${answer}"
if [[ "${answer}" = [yY] ]]; then
break
else
errexit "Aborted"
fi
fi
done
echo ""
echo "Installing gdisk"
echo ""
apt-get update
apt-get install gdisk
fi
rsync --version &> /dev/null
if [ $? -ne 0 ]; then
errexit "rsync not installed (run: apt-get install rsync)"
fi
OSID="$(sed -n 's|^ID=\(.*\)|\1|p' /etc/os-release)"
BOOTMNT="${MNTPATH}$(sed -n 's|^\S\+\s\+\(/boot\S*\)\s\+vfat\s\+.*$|\1|p' /etc/fstab)"
if [ "${BOOTMNT}" = "${MNTPATH}/boot/firmware" ]; then
BOOTSIZE=512
else
BOOTSIZE=256
fi
ROOT_PART="$(mount | sed -n 's|^\(/dev/.*\) on / .*|\1|p')"
ROOT_DEV_P="$(sed 's/[0-9]\+$//' <<< "${ROOT_PART}")"
ROOT_DEV="${ROOT_DEV_P}"
if [ "${ROOT_DEV}" = "/dev/mmcblk0p" ]; then
ROOT_DEV="${ROOT_DEV:0:(${#ROOT_DEV} - 1)}"
fi
ROOT_TYPE=$(blkid "${ROOT_PART}" | sed -n 's|^.*TYPE="\(\S\+\)".*|\1|p')
PTTYPE="$(blkid "${ROOT_DEV}" | sed -n 's|^.*PTTYPE="\(\S\+\)".*|\1|p')"
if [[ "${PTTYPE}" != "dos" && "${PTTYPE}" != "gpt" ]]; then
errexit "Unsupported partition table type: ${PTTYPE}"
fi
PARTUUID_B="$(blkid "${ROOT_DEV_P}1" | sed -n 's|^.*PARTUUID="\(\S\+\)".*|\1|p')"
PARTUUID_R="$(blkid "${ROOT_PART}" | sed -n 's|^.*PARTUUID="\(\S\+\)".*|\1|p')"
PTUUID="$(blkid "${ROOT_DEV}" | sed -n 's|^.*PTUUID="\(\S\+\)".*|\1|p')"
DFKFREE=$(df | grep "% /$" | awk '{print $3}')
INISIZE=$(((${DFKFREE} + (${DFKFREE} / 5)) / 1024))
IMGNAME=""
IMGSIZE=""
IMGINCR=""
IMGFILE=""
OPTIONS=()
EXTRACT=FALSE
NOEXPAND=FALSE
while [ $# -gt 0 ]; do
case "$1" in
-h|--help)
usage
;;
-i|--initial)
OIFS=${IFS}
IFS=','
INITIAL=($2)
IFS=${OIFS}
IMGNAME=${INITIAL[0]}
IMGSIZE=${INITIAL[1]}
IMGINCR=${INITIAL[2]}
shift 2
;;
-n|--noexpand)
NOEXPAND=TRUE
shift
;;
-o|--options)
OIFS=${IFS}
IFS=','
OPTIONS=($2)
IFS=${OIFS}
shift 2
;;
-u|--ubuntu)
shift
;;
-x|--extract)
EXTRACT=TRUE
shift
;;
-*|--*)
usage
;;
*)
IMGFILE="$1"
shift
;;
esac
done
if [ "${IMGFILE}" = "" ]; then
if [ "${IMGNAME}" != "" ]; then
IMGFILE="${IMGNAME}"
if [[ ! "${IMGFILE}" =~ ^/mnt/.*$ && ! "${IMGFILE}" =~ ^/media/.*$ ]]; then
errexit "${IMGFILE} does not begin with /mnt/ or /media/"
fi
if [ -d "${IMGFILE}" ]; then
errexit "${IMGFILE} is a directory"
fi
if [ "${IMGSIZE}" = "" ]; then
IMGSIZE=${INISIZE}
fi
IRFSSIZE=${IMGSIZE}
if [ "${IMGINCR}" = "" ]; then
IMGINCR=0
fi
ADDMB=${IMGINCR}
else
while :
do
echo ""
read -r -e -i "${IMGFILE}" -p "Image file to create? " IMGFILE
if [ "${IMGFILE}" = "" ]; then
continue
elif [[ ! "${IMGFILE}" =~ ^/mnt/.*$ && ! "${IMGFILE}" =~ ^/media/.*$ ]]; then
echo ""
echo "${IMGFILE} does not begin with /mnt/ or /media/"
continue
fi
if [ -d "${IMGFILE}" ]; then
echo ""
echo "${IMGFILE} is a directory"
elif [ -f "${IMGFILE}" ]; then
echo ""
echo -n "${IMGFILE} already exists, Ok to delete (y/n)? "
while read -r -n 1 -s answer; do
if [[ "${answer}" = [yYnN] ]]; then
echo "${answer}"
if [[ "${answer}" = [yY] ]]; then
break 2
else
break 1
fi
fi
done
else
break
fi
done
echo ""
read -r -e -p "Initial image file ROOT filesystem size (MB) [${INISIZE}]? " IRFSSIZE
if [ "${IRFSSIZE}" = "" ]; then
IRFSSIZE=${INISIZE}
fi
if [ "${ROOT_TYPE}" != "f2fs" ]; then
echo ""
read -r -e -p "Added space for incremental updates after shrinking (MB) [0]? " ADDMB
if [ "${ADDMB}" = "" ]; then
ADDMB=0
fi
fi
echo ""
echo -n "Create ${IMGFILE} (y/n)? "
while read -r -n 1 -s answer; do
if [[ "${answer}" = [yYnN] ]]; then
echo "${answer}"
if [[ "${answer}" = [yY] ]]; then
break
else
errexit "Aborted"
fi
fi
done
fi
if [ -f "${IMGFILE}" ]; then
rm "${IMGFILE}"
if [ $? -ne 0 ]; then
errexit "Unable to delete existing image file"
fi
fi
truncate -s $(((${IRFSSIZE} + ${BOOTSIZE}) * ${ONEMB})) "${IMGFILE}"
if [ $? -ne 0 ]; then
errexit "Unable to create image file"
fi
if [ "${PTTYPE}" = "dos" ]; then
echo "label: dos" | sfdisk "${IMGFILE}" > /dev/null
sfdisk "${IMGFILE}" <<EOF > /dev/null
,${BOOTSIZE}MiB,c
,+,83
EOF
else
sgdisk -Z "${IMGFILE}" &> /dev/null
sgdisk -n 1:0:+${BOOTSIZE}M "${IMGFILE}" &> /dev/null
sgdisk -t 1:0700 "${IMGFILE}" > /dev/null
sgdisk -n 2:0:0 "${IMGFILE}" &> /dev/null
sgdisk -t 2:8300 "${IMGFILE}" > /dev/null
gdisk "${IMGFILE}" <<EOF > /dev/null
r
h
1
n
0c
n
n
w
y
EOF
fi
mkloop
mkfs.vfat -F 32 -n boot -s 4 "${LOOP}p1" &> /dev/null
if [ $? -ne 0 ]; then
errexit "Unable to create image BOOT filesystem"
fi
dosfsck "${LOOP}p1" > /dev/null
if [ $? -ne 0 ]; then
errexit "Image BOOT filesystem appears corrupted"
fi
if [ "${ROOT_TYPE}" = "f2fs" ]; then
mkfs.f2fs "${LOOP}p2" > /dev/null
else
mkfs.ext4 -b 4096 -L rootfs -q "${LOOP}p2" > /dev/null
fi
if [ $? -ne 0 ]; then
errexit "Unable to create image ROOT filesystem"
fi
rmloop
echo ""
echo "Starting full backup (for incremental backups, run: $0 ${IMGFILE})"
backup
if [ "${ROOT_TYPE}" != "f2fs" ]; then
echo ""
mkloop
e2fsck -f -n "${LOOP}p2"
if [ $? -ne 0 ]; then
fsckerr "before"
fi
echo ""
resize2fs -f -M "${LOOP}p2"
resize2fs -f -M "${LOOP}p2"
resize2fs -f -M "${LOOP}p2"
e2fsck -f -n "${LOOP}p2"
if [ $? -ne 0 ]; then
fsckerr "after"
fi
INFO="$(tune2fs -l "${LOOP}p2" 2>/dev/null)"
rmloop
NEWSIZE=$(sed -n 's|^Block count:\s*\(.*\)|\1|p' <<< "${INFO}")
BLKSIZE=$(sed -n 's|^Block size:\s*\(.*\)|\1|p' <<< "${INFO}")
IMGFILE_P="${IMGFILE}"
if [[ "${IMGFILE_P: -1}" =~ ^[[:digit:]]$ ]]; then
IMGFILE_P+='p'
fi
START=$(sfdisk -d ${IMGFILE} | sed -n "s|^${IMGFILE_P}2\s\+:.*start=\s*\([0-9]\+\).*$|\1|p")
NEWEND=$((${START} + (${NEWSIZE} * (${BLKSIZE} / 512)) + ((${ADDMB} * ${ONEMB}) / 512) - 1))
if [ "${PTTYPE}" = "gpt" ]; then
((NEWEND += 33))
fi
truncate -s $(((${NEWEND} + 1) * 512)) "${IMGFILE}"
if [ "${PTTYPE}" = "dos" ]; then
sfdisk --delete "${IMGFILE}" 2 > /dev/null
echo "${START},+" | sfdisk -N2 "${IMGFILE}" &> /dev/null
fdisk "${IMGFILE}" <<EOF > /dev/null
x
i
0x${PTUUID}
r
w
EOF
else
sgdisk -Z "${IMGFILE}" &> /dev/null
sgdisk -n 1:0:+${BOOTSIZE}M "${IMGFILE}" &> /dev/null
sgdisk -t 1:0700 "${IMGFILE}" > /dev/null
sgdisk -n 2:0:0 "${IMGFILE}" &> /dev/null
sgdisk -t 2:8300 "${IMGFILE}" > /dev/null
sgdisk -u 1:"${PARTUUID_B}" "${IMGFILE}" > /dev/null
sgdisk -u 2:"${PARTUUID_R}" "${IMGFILE}" > /dev/null
sgdisk -U "${PTUUID}" "${IMGFILE}" > /dev/null
gdisk "${IMGFILE}" <<EOF > /dev/null
r
h
1
n
0c
n
n
w
y
EOF
fi
if [ ${ADDMB} -ne 0 ]; then
echo ""
mkloop
e2fsck -f -n "${LOOP}p2"
if [ $? -ne 0 ]; then
fsckerr "before"
fi
echo ""
resize2fs -f "${LOOP}p2"
e2fsck -f -n "${LOOP}p2"
if [ $? -ne 0 ]; then
fsckerr "after"
fi
rmloop
fi
fi
mntimg
while read DIR
do
touch -r "${DIR}" "${MNTPATH}${DIR}"
done <<< "$(echo "$(rsync -aDH --dry-run --itemize-changes --partial --numeric-ids --delete --force --exclude "${MNTPATH}" --exclude '/dev' \
--exclude '/lost+found' --exclude '/media' --exclude '/mnt' --exclude '/proc' --exclude '/run' --exclude '/sys' --exclude '/tmp' --exclude '/var/swap' \
--exclude '/etc/udev/rules.d/70-persistent-net.rules' --exclude '/var/lib/asterisk/astdb.sqlite3-journal' "${OPTIONS[@]}" / "${MNTPATH}/")" | \
sed -n "s|^\.d\.\.t\.\.\.\.\.\.\s\+\(.*$\)|/\1|p")"
umntimg
echo ""
else
if [[ ! "${IMGFILE}" =~ ^/mnt/.*$ && ! "${IMGFILE}" =~ ^/media/.*$ ]]; then
errexit "${IMGFILE} does not begin with /mnt/ or /media/"
fi
if [ -d "${IMGFILE}" ]; then
errexit "${IMGFILE} is a directory"
elif [ ! -f "${IMGFILE}" ]; then
errexit "${IMGFILE} not found"
fi
backup
fi
sync

37
rpi/install-ionopi.sh Normal file
View File

@ -0,0 +1,37 @@
#!/bin/bash
# script for iono-pi when starting from fresh rpi image
sudo apt install -y git raspberrypi-kernel-headers
git clone --depth 1 https://github.com/sfera-labs/iono-pi-kernel-module
cd iono-pi-kernel-module
make
sudo make install
dtc -@ -Hepapr -I dts -O dtb -o ionopi.dtbo ionopi.dts
sudo cp ionopi.dtbo /boot/overlays/
sudo_append_to () {
sudo bash -c "grep -qxF '$2' $1 || sudo echo '$2' >> $1"
}
sudo_append_to /boot/config.txt dtoverlay=ionopi
sudo_append_to /boot/config.txt dtoverlay=i2c-rtc,mcp7941x
sudo groupadd ionopi || true
sudo cp 99-ionopi.rules /etc/udev/rules.d/
sudo raspi-config nonint do_i2c 1
sudo apt install -y i2c-tools
sudo apt autoremove -y --purge fake-hwclock
# RTC clock
sudo cp ../config-rtc-MCP79410.service /etc/systemd/system/
sudo cp ../configrtc.sh /usr/local/bin/
sudo chmod 744 /usr/local/bin/configrtc.sh
sudo chown root:root /usr/local/bin/configrtc.sh
sudo systemctl enable config-rtc-MCP79410.service
sudo_append_to /etc/systemd/timesyncd.conf "NTP=pstime1.psi.ch pstime2.psi.ch pstime3.psi.ch"
echo "do the following:"
echo ""
echo "> sudo reboot now"
echo ""
echo "and, after reboot set RTC time and check it is working"
echo ""
echo "> sudo hwclock -w"
echo "> timedatectl status"

37
rpi/install-ionopimax.sh Normal file
View File

@ -0,0 +1,37 @@
#!/bin/bash
# script for iono-pi when starting from fresh rpi image
sudo apt install -y git raspberrypi-kernel-headers
git clone --depth 1 https://github.com/sfera-labs/iono-pi-max-kernel-module
cd iono-pi-max-kernel-module
make
sudo make install
dtc -@ -Hepapr -I dts -O dtb -o ionopimax.dtbo ionopimax.dts
sudo cp ionopimax.dtbo /boot/overlays/
sudo_append_to () {
sudo bash -c "grep -qxF '$2' $1 || sudo echo '$2' >> $1"
}
sudo_append_to /boot/config.txt dtoverlay=ionopimax
sudo_append_to /boot/config.txt dtoverlay=i2c-rtc,mcp7941x
sudo groupadd ionopimax || true
sudo cp 99-ionopimax.rules /etc/udev/rules.d/
sudo raspi-config nonint do_i2c 1
sudo apt install -y i2c-tools
sudo apt autoremove -y --purge fake-hwclock
# RTC clock
sudo cp ../config-rtc-MCP79410.service /etc/systemd/system/
sudo cp ../configrtc.sh /usr/local/bin/
sudo chmod 744 /usr/local/bin/configrtc.sh
sudo chown root:root /usr/local/bin/configrtc.sh
sudo systemctl enable config-rtc-MCP79410.service
sudo_append_to /etc/systemd/timesyncd.conf "NTP=pstime1.psi.ch pstime2.psi.ch pstime3.psi.ch"
echo "do the following:"
echo ""
echo "> sudo reboot now"
echo ""
echo "and, after reboot set RTC time and check it is working"
echo ""
echo "> sudo hwclock -w"
echo "> timedatectl status"

161
rpi/write_to Executable file
View File

@ -0,0 +1,161 @@
#!/usr/bin/env python3
import sys
import os
import time
import re
from select import select
from glob import glob
from subprocess import check_output, STDOUT, PIPE, Popen, TimeoutExpired
IMAGES_HOST = 'l_samenv@samenv'
IMAGES_DIR = 'boxes/rpi_images'
IMAGES_PAT = '*.lz4'
extdisks = {}
def prt(text):
print(time.strftime('%H:%M:%S'), text)
def cmd(command, verbose=False):
if verbose:
print(f'> {command}')
return check_output(command.split(), stderr=STDOUT).decode('latin-1')
def find_raspi(kind):
# collect info about disks
dlist = '\n' + cmd('/usr/sbin/diskutil list')
extdisks.clear()
proposed = []
noname = re.compile(r' +0: +\*\d+\.?\d* GB +disk')
for dinfo in dlist.split('\n/dev/'):
if not dinfo:
continue
disk, info = dinfo.split(maxsplit=1)
if 'external' in info.split('\n')[0]:
extdisks[disk] = info
if kind == 'emmc':
if 'Windows_FAT_32 bootfs' in info and 'Linux' in info:
proposed.append(disk)
elif noname.search(info):
proposed.append(disk)
elif kind == 'sd':
if 'Apple' not in info:
proposed.append(disk)
return proposed
def rpiboot():
if os.path.exists('/Volumes/bootfs'):
prt('unmount bootfs')
os.system('diskutil unmount bootfs')
lines = []
with Popen(['rpiboot'], stdout=PIPE) as p:
tmo = 1
t = 0
while select([p.stdout], [], [], tmo)[0]:
rawline = p.stdout.readline()
if not rawline:
return tmo != 1
line = rawline.decode('latin-1').strip()
if lines is None:
print(line)
elif 'Waiting' in line:
tmo = 2
lines.append(line)
t = time.time()
elif tmo == 1:
lines.append(line)
else:
print('\n'.join(lines))
print(line)
lines = None
else:
p.terminate()
return False
def list_external():
print('--- external disks:')
for disk, info in extdisks.items():
print(disk, info)
rescue = """
Remark: not all cables might work.
Example on Markus Mac:
- does not work: black USB C to USB C cable
- works: white USB A to USB C cable plugged into docking station.
Please unpower the box with compute module,
start this script again and put power immediately."""
def write_image(kind):
if kind == 'eemc':
print("\nmake sure microUSB 'SLAVE' is connected to this computer")
print("and microUSB 'POWER' is connected to a USB power supply\n")
prt('try to find CM (compute module on PoE device) ...')
else:
pass
proposed = find_raspi(kind)
if not proposed and kind == 'emmc':
# we may install rpiboot here if not available
# git clone --depth=1 https://github.com/raspberrypi/usbboot
# cd usbboot
# make
# ./rpiboot
print('not found - put rpi in bootloader mode')
if not rpiboot() and not rpiboot():
print(rescue)
return
for _ in range(10):
proposed = find_raspi(kind)
if proposed:
break
time.sleep(0.1)
else:
list_external()
print('can not find CM')
return
list_external()
if len(proposed) > 1:
if kind == 'emmc':
print('several potential devices for CM:', proposed)
return
dev = input('select device to write to {" ".join(proposed)}: ')
else:
dev = proposed[0]
images = check_output(['sudo', '-u', 'zolliker', 'ssh', IMAGES_HOST, f'cd {IMAGES_DIR} ; ls {IMAGES_PAT}']).decode('latin-1').split('\n')
for file in sorted(images):
print(file)
print('')
image = input(f'select image to write to {dev} [{file}]: ') or file
prt(f'unmount {dev} ...')
print('you may be prompted for your account password for sudo')
os.system(f'sudo diskutil unmountDisk /dev/{dev}')
print('')
prt('get, uncompress and write... (takes about 15 min)')
os.system(f'ssh {IMAGES_HOST} "dd if={IMAGES_DIR}/{image} bs=512k" | lz4 -d | sudo dd of=/dev/{dev} bs=512k')
prt('unmount bootfs')
for _ in range(3):
if os.path.exists('/Volumes/bootfs'):
prt('unmount bootfs')
os.system('diskutil unmount bootfs')
break
time.sleep(1.0)
prt('done')
os.system(f'diskutil unmountDisk /dev/{dev}')
if len(sys.argv) == 2:
write_image(sys.argv[1])
else:
print("""
Usage:
> write_to emmc # write to compute module using PoE board"
> write_to sd # write to sd card
""")