Raspberry Pi

From Segfault
Jump to navigation Jump to search

SD card

After getting an SD card adapter[1], I still could not[2] erase/format it on a MacBook:

$ diskutil eraseDisk HFS+ 32GB disk3
Started erase on disk3
Unmounting disk
Error: -69877: Couldn't open device

Not even directly writing to the block device would work, apparently due to hardware issues[3]

$ pv < /dev/zero > /dev/disk3
-bash: /dev/disk3: Permission denied

Same for the character device:[4][5]

$ pv < /dev/zero > /dev/rdisk3s1 
-bash: /dev/rdisk3s1: Permission denied

Headless Setup

Debian

While Debian does not seem to offer official images, we can use unofficial ones made by the Raspberry Pi image specs and the Debian image builder

https://people.debian.org/~gwolf/raspberrypi3/

The root password is set to raspberry.

Raspbian

The Raspberry Pi 3 Starter Kit came with a MicroSD card, pre-imaged with NOOBS, which appeared to boot and the RPI received a DHCP lease, but could not be logged into. But let's install a Debian based Raspbian Jessie Lite in the SD card instead:

sha1sum *raspbian-jessie-lite.zip                      # Verify the checksum!
unzip *raspbian-jessie-lite.zip
pv < *raspbian-jessie-lite.img | sudo dd of=/dev/sdb bs=1M

After the image has been written, the MicroSD card should look like this:

$ sudo fdisk -l /dev/sdb 
Disk /dev/sdb: 29.7 GiB, 31914983424 bytes, 62333952 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xc20f799b

Device     Boot  Start      End  Sectors  Size Id Type
/dev/sdb1         8192   137215   129024   63M  c W95 FAT32 (LBA)
/dev/sdb2       137216 62333951 62196736 29.7G 83 Linux
  • The vfat partition contains the boot loader and some firmware blobs
  • The ext4 partition contains the actual operating system.

We still have to solve the headless setup part. Mounting the ext4 partition reveals a Systemd based Debian system:

$ find etc/ -name "*ssh*" | xargs ls -dog
[...]
-rwxr-xr-x 1 4077 Apr 14  2016 etc/init.d/ssh
lrwxrwxrwx 1   13 Feb 25 23:57 etc/rc2.d/K01ssh -> ../init.d/ssh
lrwxrwxrwx 1   13 Feb 25 23:57 etc/rc3.d/K01ssh -> ../init.d/ssh
lrwxrwxrwx 1   13 Feb 25 23:57 etc/rc4.d/K01ssh -> ../init.d/ssh
lrwxrwxrwx 1   13 Feb 25 23:57 etc/rc5.d/K01ssh -> ../init.d/ssh
lrwxrwxrwx 1   37 Nov 25 09:29 etc/systemd/system/multi-user.target.wants/sshswitch.service -> /lib/systemd/system/sshswitch.service
  • In an SysV based system, we could just rename the K01ssh symlinks to e.g. S01ssh and then sshd should be started on the next boot.
  • But since we have a systemd based system, we have to enable sshd with service files:
cd ../etc/systemd/system/
ln -s /lib/systemd/system/ssh.service

cd ../multi-user.target.wants/
ln -s /lib/systemd/system/ssh.service

This should work, because /lib/systemd/system/ssh.service does really exists on that Raspbian image. But the easiest method would be to use its own sshswitch service, which is already active:

$ pwd 
../etc/systemd/system/multi-user.target.wants

$ cat ../../../../lib/systemd/system/sshswitch.service 
[Unit]
Description=Turn on SSH if /boot/ssh is present
ConditionPathExistsGlob=/boot/ssh{,.txt}
After=regenerate_ssh_host_keys.service

[Service]
Type=oneshot
ExecStart=/bin/sh -c "update-rc.d ssh enable && invoke-rc.d ssh start && rm -f /boot/ssh ; rm -f /boot/ssh.txt"
[...]

This will enable and start sshd if /boot/ssh or /boot/ssh.txt is present. Once enabled, one can login via SSH.

Arch Linux ARM

To install Arch Linux instead, we also have to prepare the SD card:

fdisk /dev/sdf
> 100 MB 0x0b (W95 FAT32)
>        0x83 (Linux)

mkfs.vfat -vn BOOT /dev/sdf1                                                          # -F 32 needed?[6]
mkfs.ext4 -vL root /dev/sdf2

mkdir /mnt/rpi-{boot,root}
mount -t vfat /dev/sdf1 /mnt/rpi-boot
mount -t ext4 /dev/sdf2 /mnt/rpi-root

Grab the correct image from the download site and install like:

wget http://os.archlinuxarm.org/os/ArchLinuxARM-rpi-3-latest.tar.gz{,.md5,.sig}
md5sum -c ArchLinuxARM*.md5
gpg --recv-keys 68B3537F39A313B3E574D06777193F152BDBE6A6
gpg --verify ArchLinuxARM*.sig

Extract into the root, and move the /boot contents to the first partition:

bsdtar -xpf ArchLinuxARM*tar.gz -C /mnt/rpi-root/
mv /mnt/rpi-root/boot/* /mnt/rpi-boot/
umount /mnt/rpi-{boot,root}

With that, Arch Linux should be able to boot.

NetBSD

Not exactly a headless setup, but close enough. The installation, in short:

wget https://cdn.netbsd.org/pub/NetBSD/NetBSD-8.0/evbarm-earmv7hf/binary/gzimg/armv7.img.gz               # There's no checksum here :-\
gzip -dc armv7.img.gz | pv > /dev/sdX

Again, NetBSD doesn't seem to publish checksums for these images, so let's at least verify if our image made it to the SDcard correctly:

$ gzip -dc armv7.img.gz | wc -c && gzip -dc armv7.img.gz | sha256sum
1669922816
82a1e487c4d4109f19040f5f89868086da9c59215cdbfb53cf5bffd20f3767dd
$ pv -Ss 1669922816 /dev/sdX | sha256sum | grep 82a1e487c4d4109f19040f5f89868086da9c59215cdbfb53cf5bffd20f3767dd
82a1e487c4d4109f19040f5f89868086da9c59215cdbfb53cf5bffd20f3767dd

NetBSD will boot and will grow its filesystem to fill the entire SDcard and reboot again. We can setup a user account and then use SSH to login, so that we can continue in a headless fashion:

useradd -m -G wheel dummy
passwd dummy

Postinst

Packages

Install missing packages:

apt-get install acl apt-listchanges atop attr autossh bc bzip2 ca-certificates curl deborphan debsums git haveged s-nail htop iftop iotop irqbalance ksh less libpam-tmpdir lsof mlocate netcat-openbsd openssh-server p7zip-full pbzip2 pigz pv pwgen rsync screen sharutils smartmontools strace sudo sysstat vim vnstat whois zsh

For x86 based systems:

firmware-iwlwifi i7z intel-microcode mcelog memtest86+ msr-tools

For desktop systems:

chromium flashplugin-nonfree gedit gnome-core gnome-themes gnome-tweak-tool icedove enigmail firefox libcanberra-gtk-module xul-ext-https-everywhere xul-ext-noscript xul-ext-refcontrol libreoffice-calc libreoffice-writer pidgin pidgin-otr rdesktop sox xtightvncviewer ekiga


Zram

Zram can be used, but with Debian/jessie, zramctl binary is not included in util-linux yet:

$ dpkg-architecture -q DEB_HOST_ARCH
armhf

$ wget http://ftp.us.debian.org/debian/pool/main/u/util-linux/util-linux_2.29.1-1_armhf.deb
$ dpkg -x util-linux_2.29.1-1_armhf.deb x
$ sudo mv x/sbin/zramctl /usr/local/sbin/

Then, as root:

modprobe zram && modprobe lz4_compress && sleep 1 && zramctl -a lz4 -f -s 512M && mkswap /dev/zram0 && swapon -p 2 /dev/zram0

WiFi

The RPI 3 supports 802.11n WiFi, but only the 2.4 GHz variant:[7][8]

$ cat /etc/wpa_supplicant/wpa_supplicant.conf 
[...]
network={
       disabled=0
           ssid="ESSID"
            psk="passphrase"
          proto=WPA2
       key_mgmt=WPA-PSK
       pairwise=CCMP
          group=CCMP
}

Sensors

Instead of using lm-sensors, the RPI can be queried via its (pre-installed) libraspberrypi-bin tools:[9]

$ /opt/vc/bin/vcgencmd measure_temp
temp=48.3'C

Miscellaneous

Disable Bluetooth, if not needed:

$ grep ^B /etc/default/bluetooth 
BLUETOOTH_ENABLED=0

$ systemctl disable bluetooth hciuart
$ systemctl stop bluetooth hciuart

Enable periodic debsums verification:

$ grep ^C /etc/default/debsums 
CRON_CHECK=weekly

Enable sysstat collection:

$ grep ^ENA /etc/default/sysstat 
ENABLED="true"

Mount /tmp as tmpfs:

$ grep ^[A-Z] /etc/default/tmpfs 
RAMTMP=yes

View the kernel configuration, if needed:

$ sudo modprobe configs
$ ls -go /proc/config.gz 
-r--r--r-- 1 31643 Mar  1 01:23 /proc/config.gz

Installing irqbalance may not help so much, because the board may not support it:[10]

$ cat /proc/interrupts 
           CPU0       CPU1       CPU2       CPU3       
 16:          0          0          0          0  bcm2836-timer   0 Edge arch_timer
 17:    1325340    2396930    2651875    1604640  bcm2836-timer   1 Edge arch_timer
 23:        402          0          0          0  ARMCTRL-level   1 Edge 3f00b880.mailbox
 24:          2          0          0          0  ARMCTRL-level   2 Edge VCHIQ doorbell
 39:          1          0          0          0  ARMCTRL-level  41 Edge    
 46:          0          0          0          0  ARMCTRL-level  48 Edge bcm2708_fb dma
 48:      54282          0          0          0  ARMCTRL-level  50 Edge DMA IRQ
 50:          0          0          0          0  ARMCTRL-level  52 Edge DMA IRQ
 62:  435446749          0          0          0  ARMCTRL-level  64 Edge dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1[11][12]
 79:          0          0          0          0  ARMCTRL-level  81 Edge 3f200000.gpio:bank0
 80:          0          0          0          0  ARMCTRL-level  82 Edge 3f200000.gpio:bank1
 86:      43862          0          0          0  ARMCTRL-level  88 Edge mmc0
 92:     580497          0          0          0  ARMCTRL-level  94 Edge mmc1
FIQ[13]:              usb_fiq
IPI0:          0          0          0          0  CPU wakeup interrupts
IPI1:          0          0          0          0  Timer broadcast interrupts
IPI2:   20480575   37755008   26262138   26052578  Rescheduling interrupts
IPI3:       1088       1058       1115       1068  Function call interrupts
IPI4:    2767657    3219384    2344363    2403153  Single function call interrupts
IPI5:          0          0          0          0  CPU stop interrupts
IPI6:          0          0          0          0  IRQ work interrupts
IPI7:          0          0          0          0  completion interrupts
Err:           0

Kernel

To build a new kernel[14][15][16], we'll better cross-compile, otherwise the process may just take too long:

git clone git://github.com/raspberrypi/linux raspberrypi_linux-git                    #  Add --depth=1 to omit some history.
git clone git://github.com/raspberrypi/tools raspberrypi_tools-git
git clone --depth 1 https://github.com/raspberrypi/firmware raspberrypi_firmware-git  # Omit --depth=1 to get the full history.

Checkout a stable kernel release:

cd ../raspberrypi_linux-git
git checkout rpi-4.12.y

aarch32

Adjust the PATH variable accordingly:

export PATH=../arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:$PATH      # Linaro Cross Compiler[17]
export PATH=/opt/ctng/tools/arm-unknown-linux-gnueabihf/bin:$PATH                     # Crosstool-NG

Create a viable kernel configuration:

export DIR=${TMPDIR:-/tmp}/aarch32 && [ -d $DIR ] && rm -rf $DIR && mkdir $DIR
make O=$DIR ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig

Compile with:

make -j4 O=$DIR ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs

Collect all the bits and install on our RPI:

export KERNEL=kernel7 INSTDIR=${TMPDIR:-/tmp}/aarch32_inst
rm -rf $INSTDIR && mkdir -p $INSTDIR/boot/overlays

make O=$DIR ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=$INSTDIR modules_install
scripts/mkknlimg $DIR/arch/arm/boot/zImage   $INSTDIR/boot/$KERNEL.img

aarch64

Adjust the PATH variable accordingly:

export PATH=../arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:$PATH      # Linaro Cross Compiler[17]
export PATH=/opt/ctng/tools/aarch64-unknown-linux-gnueabi/bin:$PATH                   # Crosstool-NG

Create a viable kernel configuration:[18]

export DIR=${TMPDIR:-/tmp}/aarch64 && [ -d $DIR ] && rm -rf $DIR && mkdir $DIR
make O=$DIR ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnueabi- bcmrpi3_defconfig

Compile with:

make -j4 O=$DIR ARCH=arm64 CROSS_COMPILE=aarch64-unknown-linux-gnueabi- Image.gz modules dtbs
scripts/mkknlimg $DIR/arch/arm64/boot/Image.gz $DIR/arch/arm64/boot/kernel8.img

Collect all the bits and install onto the SD card:

export RPIROOT=/mnt/rpi-root RPIBOOT=/mnt/rpi-boot                                    # Where the SD card is mounted

sudo tar -C $RPIBOOT -cvf ~/backup_boot.tar .                                         # Backup boot!
sudo tar -C $RPIROOT/lib/modules -cvf ~/backup_modules.tar .                          # Backup modules!

sudo cp -ivr ../raspberrypi_firmware-git/boot/* $RPIBOOT/                             # This will populate $RPIBOOT; only needed once.
sudo cp -iv $DIR/arch/arm64/boot/kernel8.img $RPIBOOT/kernel8.img
sudo cp -iv $DIR/arch/arm64/boot/Image       $RPIBOOT/kernel8.img
sudo cp -iv $DIR/arch/arm64/boot/dts/broadcom/bcm{2710,2837}-rpi-3-b.dtb $RPIBOOT/

sudo mkdir -p $RPIBOOT/overlays
sudo cp -iv $DIR/arch/arm64/boot/dts/overlays/* $RPIBOOT/overlays/

echo "kernel=kernel8.img" | sudo tee -a $RPIBOOT/config.txt                           # Should already be in place
sudo env PATH=$PATH make O=$DIR ARCH=arm64 \                                          # The env PATH trick may (not) be necessary[19]
   CROSS_COMPILE=aarch64-unknown-linux-gnueabi- INSTALL_MOD_PATH=$RPIROOT modules_install
sudo umount -v $RPIROOT $RPIBOOT

If things don't work out, we restore from backup:

sudo tar -C $RPIBOOT -xpf ~/backup_boot.tar
sudo tar -C $RPIROOT/lib/modules -xpf ~/backup_modules.tar

Architecture

Model CPU Port
Raspberry Pi Model A+ BCM2835 SoC 32-bit ARMv6 + VFPv2 armel
Raspberry Pi 1 Model B (same) (same)
Raspberry Pi Model B+ (same) (same)
Raspberry Pi 2 Model B BCM2836 SoC 32-bit quad-core ARM Cortex-A7 (ARMv7) armhf
Raspberry Pi 3 Model B BCM2837 SoC 64-bit quad-core ARM Cortex-A53 (ARMv8) armhf / arm64

Links


References