Raspberry Pi

From Segfault
Jump to: navigation, 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


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 

$ cat ../../../../lib/systemd/system/sshswitch.service 
Description=Turn on SSH if /boot/ssh is present

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.



Install missing packages:

apt-get install acl apt-file apt-listchanges atop attr autossh bc bzip2 ca-certificates chrony cryptsetup curl deborphan devscripts debsums ecryptfs-utils git-core haveged s-nail htop iftop iotop irqbalance ksh less libpam-tmpdir lsof mlocate moreutils netcat-openbsd openssh-server openvpn p7zip-full pbzip2 pigz pv pwgen pxz rsync screen sharutils smartmontools ssmtp strace subversion sudo sysstat thermald 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 can be used, but with Debian/jessie, zramctl binary is not included in util-linux yet:

$ dpkg-architecture -q DEB_HOST_ARCH

$ 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


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

$ cat /etc/wpa_supplicant/wpa_supplicant.conf 


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

$ /opt/vc/bin/vcgencmd measure_temp


Disable Bluetooth, if not needed:

$ grep ^B /etc/default/bluetooth 

$ systemctl disable bluetooth hciuart
$ systemctl stop bluetooth hciuart

Enable periodic debsums verification:

$ grep ^C /etc/default/debsums 

Enable sysstat collection:

$ grep ^ENA /etc/default/sysstat 

Mount /tmp as tmpfs:

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

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
 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[11]:              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


To build a new kernel[12][13][14], 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


Adjust the PATH variable accordingly:

export PATH=../arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:$PATH      # Linaro Cross Compiler[15]
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


Adjust the PATH variable accordingly:

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

Create a viable kernel configuration:[16]

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[17]
   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


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