0

I'm trying to build a custom Alpine Linux image for the raspberry pi. I'm using below script with some customisations, however, when I try to boot the image on the pi, I cannot get anything. The light stays red and the green light never comes up. It feels to that the bootloader isn't installed properly, however, I'm unsure how to debug this or figure out what's wrong. In the below the overlays directory is missing, but I have indeed already tried getting those there too but to know avail.

Here is some information of the image:

$ \ls -la
total 22998
drwxr-xr-x  3 hosh hosh     1536 Jan  1  1970 .
drwxr-x---+ 4 root root     4096 Jul 28 01:15 ..
-rw-r--r--  1 hosh hosh    25410 Jul 28 01:00 bcm2710-rpi-2-b.dtb
-rw-r--r--  1 hosh hosh    26451 Jul 28 01:00 bcm2710-rpi-3-b.dtb
-rw-r--r--  1 hosh hosh    27070 Jul 28 01:00 bcm2710-rpi-3-b-plus.dtb
-rw-r--r--  1 hosh hosh    25265 Jul 28 01:00 bcm2710-rpi-cm3.dtb
-rw-r--r--  1 hosh hosh    40697 Jul 28 01:00 bcm2711-rpi-4-b.dtb
-rw-r--r--  1 hosh hosh    20214 Jul 28 01:00 bcm2837-rpi-3-b.dtb
-rw-r--r--  1 hosh hosh    21003 Jul 28 01:00 bcm2837-rpi-3-b-plus.dtb
-rw-r--r--  1 hosh hosh    52296 Oct 21  2019 bootcode.bin
-rw-r--r--  1 hosh hosh      142 Jul 28 01:00 cmdline.txt
-rw-r--r--  1 hosh hosh   154521 Jan 23  2020 config-rpi
-rw-r--r--  1 hosh hosh      693 Jul 28 01:00 config.txt
-rw-r--r--  1 hosh hosh     6736 Oct 21  2019 fixup.dat
-rw-r--r--  1 hosh hosh  4690117 Jul 28 01:00 initramfs-rpi
drwxr-xr-x  2 hosh hosh    15872 Jul 28 01:14 overlays
-rw-r--r--  1 hosh hosh  2877988 Oct 21  2019 start.elf
-rw-r--r--  1 hosh hosh  2773338 Jan 23  2020 System.map-rpi
-rw-r--r--  1 hosh hosh 12782080 Jan 23  2020 vmlinuz-rpi

Contents of config.txt

$ cat config.txt
arm_control=0x200
kernel=vmlinuz-rpi
initramfs=initramfs-rpi

# On the Pi, the GPU and the CPU share RAM.  This is a headless install, so
# give the GPU the least amount of RAM it can get by with (16MB).
# This also triggers the Pi to use a cutdown version of the firmware (start_cd.elf).
gpu_mem=16

# Turn off audio, wifi and bluetooth.  (Note "dt" stands for device tree.)
dtparam=audio=off
dtoverlay=pi3-disable-wifi
dtoverlay=pi3-disable-bt

# Enable mini UART as serial port (/dev/ttyS0).
# Also, fixes VideoCore IV (aka the GPU or the VPU) frequency to 250MHz.
enable_uart=1

boot_delay=1

# use usercfg.txt to change other settings as this file may get overwritten
include usercfg.txt

And cmdline.txt

$ cat cmdline.txt
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet

In addition, these two scripts are the main code behind building the above:

make-image

#!/usr/bin/env bash

# these scripts are based on https://github.com/knoopx/alpine-raspberry-pi.
# todo https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh

set -eux

script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)

enter_chroot=false
if [[ "${1:-}" == "shell" ]]; then
  shift
  enter_chroot=true
fi

ALPINE_VERSION="${1:-3.12}"
ALPINE_ARCH="${2:-aarch64}"

if [[ "$ALPINE_ARCH" == "" ]] || [[ "$ALPINE_VERSION" == "" ]]; then
  echo "Error: must specify arguments alpine arch and version"
  echo "Usage:"
  echo "  $0 <version> <arch>"
  echo ""
  echo "Example:"
  echo "  $0 v3.10.2 aarch64"
fi

alpine_branch="$(echo "$ALPINE_VERSION" | awk -F. '{gsub("^v", "", $1); print "v"$1"."$2}')"

tmpdir="$(mktemp -d -t "alpine-rpi-$ALPINE_VERSION-$ALPINE_ARCH.XXXXXXXXXX")"
artifact_file="$script_dir/alpine-rpi-$ALPINE_VERSION-$ALPINE_ARCH.img"
rootfs="$tmpdir"
boot_dir="$rootfs/boot"
build_dir="$rootfs/build"

clean_up() {
  [[ -x "$rootfs/destroy" ]] && "$rootfs/destroy" -y || true
  findmnt -M "$rootfs" && umount "$rootfs"
  [[ -n "$tmpdir" ]] && rm -rf "$tmpdir"
  losetup --detach-all # todo this should be only the current loop
}
trap clean_up SIGTERM SIGINT SIGQUIT

truncate -s 2G "$artifact_file"

{
  echo "o"
  echo "n"
  echo "p"
  echo "1"
  echo ""
  echo "+128MB"
  echo "t"
  echo "c"
  echo "n"
  echo "p"
  echo "2"
  echo ""
  echo ""
  echo "w"
} | fdisk -H 255 -S 63 "$artifact_file"

LOOP_DEV=$(losetup --partscan --show --find "$artifact_file")
BOOT_DEV="$LOOP_DEV"p1
ROOT_DEV="$LOOP_DEV"p2

# format partitions
mkfs.fat -F32 -n ALPINE "$BOOT_DEV"
mkfs.ext4 -O '^has_journal' "$ROOT_DEV"
mkdir -p "$rootfs"
mount --make-private "$ROOT_DEV" "$rootfs"
mkdir -p "$boot_dir"
mount --make-private "$BOOT_DEV" "$boot_dir"
mkdir -p "$build_dir"
mount --bind "$script_dir/build" "$build_dir"

sudo ./alpine-chroot-install \
  -a "$ALPINE_ARCH" \
  -b "$alpine_branch" \
  -d "$rootfs" \
  -k "ARCH CI QEMU_EMULATOR RPI_CI_.* TRAVIS_.*" \
  -p "ca-certificates ssl_client"

"${script_dir}/build/run.sh" "$rootfs"

if [[ "$enter_chroot" == "true" ]]; then
  "$rootfs/enter-chroot"
fi

file_dirs=(
  var/cache/apk
  root
  enter-chroot
  destroy
  etc/resolv.conf
  env.sh
)
for file_dir in "${file_dirs[@]}"; do
  file_dir="$rootfs/$file_dir"
  ls -la "$file_dir"
  [[ -d "$file_dir" ]] && find "$file_dir" -mindepth 1 -delete
  [[ -f "$file_dir" ]] && rm "$file_dir"
done

umount -lf "$rootfs"

# shrink image
ROOT_PART_START=$(parted -ms "$artifact_file" unit B print | awk -F: 'END{gsub("B$", "", $2); print $2}')
ROOT_BLOCK_SIZE=$(tune2fs -l "$ROOT_DEV" | awk -F': *' '/^Block size:/{print $2}')
ROOT_MIN_SIZE=$(resize2fs -P "$ROOT_DEV" 2>/dev/null | awk -F': *' '/:/{print $2}')

# shrink fs
e2fsck -f -p "$ROOT_DEV"
resize2fs -p "$ROOT_DEV" "$ROOT_MIN_SIZE"

# shrink partition
PART_END=$((ROOT_PART_START + (ROOT_MIN_SIZE * ROOT_BLOCK_SIZE)))
parted ---pretend-input-tty "$artifact_file" unit B resizepart 2 "$PART_END" yes

losetup -d "$LOOP_DEV"

# truncate free space
FREE_START=$(parted -ms "$artifact_file" unit B print free | awk -F: 'END{gsub("B$", "", $2); print $2}')
truncate -s "$FREE_START" "$artifact_file"

#gzip -f "$artifact_file"

echo "DONE."

In above script, the run.sh script, among other things runs the below script, which sets up the firmware:

#!/bin/sh

set -eux

apk add linux-rpi
#apk add linux-rpi4 # todo for rpi4
apk add linux-firmware-brcm
apk add raspberrypi-bootloader

dtb_file_copied=false

while read -r dtb; do
  cp "$dtb" "/boot"
  dtb_file_copied=true
done <<EOT
  $(apk manifest linux-rpi | awk "/${RPI_CI_DTB_FILES:-\.dtb$}/{print \"/\"\$2}")
EOT

cp -r "$(dirname "/$(apk manifest linux-rpi | awk '/overlays/{print $2}' | head -n1)")" /boot

if [ "$dtb_file_copied" != "true" ]; then
  echo "\e[1;31mDidn't find any device tree blobs to copy... exiting... \e[0m"
  exit 1
fi

What am I doing wrong that the image won't boot? And if not, how can I figure out what the issue is?

The full code that builds the image is

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.